Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-21706: Add filter definitions to support BOT #251

Merged
merged 15 commits into from Sep 16, 2020

Conversation

RobertLuptonTheGood
Copy link
Member

Now with LATISS! #250 was just to discuss with Tim

Copy link
Contributor

@mfisherlevine mfisherlevine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some changes, and a rebase needed.

Comment on lines 33 to 34
LSST_IMSIM_FILTER_DEFINITIONS, TS3_FILTER_DEFINITIONS, TS8_FILTER_DEFINITIONS, \
COMCAM_FILTER_DEFINITIONS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now use parens for import continuation rather than \ for some reason.

logger = lsst.log.Log.getLogger("LsstCamMapper")
logger.warn('Unknown physical_filter "%s" for %s %s; replacing with "%s"',
obsInfo.physical_filter,
obsInfo.observation_id, obsInfo.detector_unique_name,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the obsInfo.detector_unique_name is necessary here it means we somehow have different filters for detectors within a visit, which would be pretty crazy. I don't much care if you want to keep it for some reason though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want the user to be able to find the offending file unambiguously. I agree that it won't matter modulo CCS bugs/data corruption

@@ -44,7 +44,7 @@ def setUp(self):
ccdExposureId_bits = 52
exposureIds = {'raw': 3019031900001029,
}
filters = {'raw': 'NONE',
filters = {'raw': 'UNKNOWN',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See OOB conversation about NONE to UNKNOWN for this whole file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary: there is no FILTER keyword, so UNKNOWN is more appropriate than NONE. I suppose I could rebase the file to add this fact to the commit comment, but is it worth it?

@@ -44,7 +44,7 @@ def setUp(self):
ccdExposureId_bits = 52
exposureIds = {'raw': 3019053000001000,
}
filters = {'raw': 'NONE',
filters = {'raw': 'UNKNOWN',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See OOB conversation about NONE to UNKNOWN for this whole file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give us a clue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OOB chat was about what these mean. NONE should be used for "there was no filter in place" i.e. equivalent to EMPTY (NB this is different from BLANK or CLEAR which means clear glass, but of a non-blocking kind) whereas UNKNOWN means we don't have sufficient information to say what this is, so either there was no header key present, or it was present but it was an empty card, or it contained a string that we were unable to map, so the filter remains a mystery and could be anything in reality.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The objection to these changes was therefore that, given the above, this was a semantic difference, as NONE and UNKNOWN are not equivalent. However, it turns out that this is actually correct, and was previously wrong, as there was no information present in the test file, I am told.

@@ -414,7 +414,7 @@ def test_parsetask_lsstCam_translator(self):
testType='BIAS',
seqNum=1,
dayObs="2019-03-19",
filter='NONE',
filter='UNKNOWN',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See OOB conversation about NONE to UNKNOWN here.

Comment on lines 131 to 132
addFilter(BOTFilters_dict,
abstract_filter=af, physical_filter=pf, lambdaEff=lambdaEff)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fits on one line.

Comment on lines +134 to +147
BOTFilters = [
FilterDefinition(abstract_filter="unknown", physical_filter="UNKNOWN", lambdaEff=0.0),
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also fits on one line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above

FilterDefinition(physical_filter="550CutOn", lambdaEff=0.0)]

TS3_FILTER_DEFINITIONS = FilterDefinitionCollection(
*LsstCamFilters0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we want to add the nominal LSST filters to TS3?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS3 used the LSSTCam filters before I worked on the code, and as I don't know what's out in the wild it seemed safer to leave them.

FilterDefinition(physical_filter="550CutOn", lambdaEff=0.0)]

TS8_FILTER_DEFINITIONS = FilterDefinitionCollection(
*LsstCamFilters0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we want to add the nominal LSST filters to TS8?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment on TS3

Comment on lines 120 to 129
if nd == "empty":
if abstract_filter == "empty":
af = "empty"
else:
af = f"{abstract_filter}"
elif abstract_filter == "empty":
pf = nd
af = f"{nd.replace('.', '_')}"
else:
af = f"{abstract_filter}~{nd.replace('.', '_')}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I get what this block is doing, but boy did I have to stare at it for a minute. I wonder if it could be clearer... At least I think it deserves a comment on what it's trying to achieve.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment added.

obsInfo = ObservationInfo(exp.getMetadata())
try:
filt = afwImage.Filter(obsInfo.physical_filter)
except pexExceptions.NotFoundError:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please catch a LookupError here rather than trying to specifically catch pexExceptions. We are generally trying to avoid pex.exceptions in python unless it's critical that we be able to catch that variant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the exception's type and didn't know that it was a subclass of LookupError. Fixed.

filter=False)

if filter:
obsInfo = ObservationInfo(exp.getMetadata())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can give this a hint by adding translator_class=self.translatorClass as a second argument.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wasted too much time... Specifying translator_class=self.translatorClass broke the unit tests. We weren't setting LatissMapper.translator = LatissTranslator.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very sorry about that. I don't know how I missed it from Latiss. I just checked imsim and ts8 and they do have it set.

mfisherlevine and others added 15 commits September 16, 2020 00:37
With all the ND filters in the second BOT filter wheel we have more than 128 filters, so would need an extra bit in nbit_filter. Instead, we only use the "base" of the filter name (discarding anything after the ~) when calculating coaddExposureId.  This is OK because we won't ever be coadding data of this type;  additionally we assert that the ID of any filter that appears in a coaddExposureId fits in the allocated bits, and arrange that the real LSST filters satisfy this condition.
@RobertLuptonTheGood RobertLuptonTheGood merged commit e85a124 into master Sep 16, 2020
@timj timj deleted the tickets/DM-21706 branch May 12, 2022 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants