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-41490: Recover WCS for input with astrometry failures #40

Merged
merged 1 commit into from Jan 19, 2024

Conversation

cmsaunders
Copy link
Collaborator

No description provided.

Copy link
Contributor

@parejkoj parejkoj left a comment

Choose a reason for hiding this comment

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

There's no test of this functionality: you should be able to make a trivial visitSummary that has a None (or missing) WCS for one detector and test with that.

Comment on lines 1016 to 1017
# This extension does not have information necessary for
# fit. Skip these detections.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not following this comment (I don't know what an extension is in this context). By "these detections", do you mean "this detector/visit"?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

"extension" is the gbdes term for one detector from one visit, and it's used throughout the gbdes task. I can change this line to "Skip the detections from this detector for this visit" to make it more clear.

Comment on lines 1188 to 1189
# This extension does not have information necessary for
# fit. Skip these detections.
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as above, with the aded question of why this is duplicated here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is duplicated because the sources get loaded two times--once when the source association is done, and again when they are added to the model fitting object.

Copy link
Contributor

@parejkoj parejkoj left a comment

Choose a reason for hiding this comment

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

Sorry, I clicked the button too soon earlier.

# This extension was not fit, but try to recover WCS
genericElements = mapTemplate["EXPOSURE/DEVICE/base"]["Elements"]
mapElements = []
instrument = visitSummary[0].getVisitInfo().getInstrumentLabel()
Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able to do summary.visitInfo.instrumentLabel, instead of using getters.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

summary.visitInfo doesn't work, but I can do visitSummary[0].getVisitInfo().instrumentLabel.

python/lsst/drp/tasks/gbdesAstrometricFit.py Outdated Show resolved Hide resolved
elements = mapTemplate[component]["Elements"]
for element in elements:
for generic, specific in {
"BAND": instrument,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is instrument really a thing to substitute for band?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It probably shouldn't be, but these lines are trying to replicate how gbdes names mappings, and the instrument name is what ends up here (probably due to this line: https://github.com/lsst/gbdes/blob/4efbc7097dc222cb35d22f8aed79572413aa1a97/include/Instrument.h#L21). A near-term item on my to-do list is to switch to fitting multiple bands at once, so this will probably be addressed there.

genericElements = mapTemplate["EXPOSURE/DEVICE/base"]["Elements"]
mapElements = []
instrument = visitSummary[0].getVisitInfo().getInstrumentLabel()
for component in genericElements:
Copy link
Contributor

Choose a reason for hiding this comment

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

I really don't understand what this nested set of loops is supposed to do. I assume it's a gbdes internals thing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sort of...this loop goes through the generic definitions for the mappings that take you from pixels to sky and uses those to get the names for the maps for a specific extension (i.e. visit/detector). I spent a lot of time trying to get gbdes to do this itself, but couldn't manage it, so this is my replication of how gbdes makes the names.

if mapName in wcsf.mapCollection.allMapNames():
mapElements = wcsf.mapCollection.orderAtoms(f"{mapName}/base")
else:
# This extension was not fit, but try to recover WCS
Copy link
Contributor

Choose a reason for hiding this comment

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

Assuming "extension" means "detector/visit": if a detector/visit wasn't fit, how could there be a WCS?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, "extension" means "detector/visit". The detector part of the model is fixed by the sources from this detector on other visits, and the visit part of the model is fixed using the other detectors for the visit. Actually, this makes me realize I need to add a check so that this doesn't fail when there is only one detector.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Scratch the part about what happens when there is only one detector. That will be caught at line 1354.

Comment on lines 745 to 751
self.log.warning(
"WCS is None for visit %d, detector %d: this extension will be dropped.",
visit,
detector,
)
continue
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be a warning, or an info-level message? Also, saying "extension" in the log is unhelpful for anyone who doesn't know the gbdes internals.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think a warning is right (from the dev-guide: "WARNING: for conditions that may indicate a problem but that allow continued execution"). I think there should be a note of caution for the resulting WCS.
I changed the message to say "...this extension (visit/detector) will be dropped."

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you have a way to flag the WCSs that are "reconstructed" in this case in the output, to warn users? A warning message may be appropriate here, but it's not sufficient to tell people that the output WCS is potentially unreliable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, neither the WCSs nor the visitSummary tables have a flag for WCS quality. The WCS fit will have higher uncertainty, as it would if there were very few stars to fit, and Eli and I have talked a bit about how to propagate this information.

@cmsaunders
Copy link
Collaborator Author

Thanks for the review @parejkoj. I'll add a unit test and update the PR.

@cmsaunders cmsaunders force-pushed the tickets/DM-41490 branch 2 times, most recently from 6941558 to 0509645 Compare January 9, 2024 19:23
Copy link
Contributor

@parejkoj parejkoj left a comment

Choose a reason for hiding this comment

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

You really should pull the contents of some of these for-loops into separate functions. That will make it easier to parse, and at least in one case here, you won't have duplicated code.

Comment on lines 1169 to 1217
)[0]
)
if len(findExtension) == 0:
# This extension does not have information necessary for
# fit. Skip the detections from this detector for this
# visit.
continue
extensionIndex = findExtension[0]

Copy link
Contributor

Choose a reason for hiding this comment

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

Most of the contents of this for-loop are the same as the loop at line 1000: looks like you should have a function for the internals here that gets called in both places.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I looked at this for a while and decided that the two loops are different enough that a function is not going to improve clarity much. I did implement a _find_extension_index() method for a part of the loop that is repeated.

for component in genericElements:
elements = mapTemplate[component]["Elements"]
for element in elements:
element = element.replace("BAND", str(instrument))
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 you need a comment here as to why band and instrument are being mixed.

)

# Check that the fit WCS for the extension with input WCS=None returns
# finite sky values.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should it return finite sky values, or correct sky values? Is the test dataset not large enough to get a reasonable fit in this case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The test data is simulated without the missing WCS, so we don't expect to be able to recover the same input in this test. It's possible to do a whole new simulation, but I don't think it's worthwhile in this case.

Copy link
Contributor

@parejkoj parejkoj left a comment

Choose a reason for hiding this comment

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

Thanks for the cleanups.

@cmsaunders cmsaunders merged commit 21efbaf into main Jan 19, 2024
3 checks passed
@cmsaunders cmsaunders deleted the tickets/DM-41490 branch January 19, 2024 20:10
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

2 participants