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-38486: Combined dark seems to not have exposure time #179

Merged
merged 2 commits into from Apr 13, 2023
Merged

Conversation

czwa
Copy link
Contributor

@czwa czwa commented Apr 4, 2023

Populate a visitInfo for combined calibration.

@timj
Copy link
Member

timj commented Apr 4, 2023

In theory, if we are propagating input headers to output and adjusting all the times properly, then ObservationInfo should still work (because it will have the "raw" headers understood by it) and then you could use the obsInfo to visitInfo routine from obs_base.

@czwa
Copy link
Contributor Author

czwa commented Apr 4, 2023

Checking this manually to see if the header in an existing calibration could be converted fails with a ValueError: None of the registered translation classes ['DECam', 'SuprimeCam', 'HSC', 'MegaPrime', 'SDSS'] understood this header. The TELESCOP parameter is possibly the problem, with LSST AuxTelescope found in the header not matching the Rubin Auxiliary Telescope that the LATISS translator in obs_lsst has.
Constructing the visitInfo manually seemed the right solution, as the exposure time is ill defined for some products: flats represent some product of throughputs that isn't really time dependent, so the use of 1.0s times there (and in the fringe which has a similar issue) is to supply a time that is safe against dividing by the exposure time. The dark should scale correctly, but that scale isn't propagated into the input metadata (although it is in the output metadata). 1.0s cannot be the correct times for the bias, which is why that is special cased to 0.0.

@timj
Copy link
Member

timj commented Apr 4, 2023

ValueError

Okay. The problem here is that the metadata translator for LATISS hasn't been registered yet because nothing knows it has to import lsst.obs.lsst.translators. The only way this would be imported is if the code asked butler for the instrument class and imported that (using Instrument.fromName()) and then it would work. The advantage of the ObservationInfo approach is you get a fully populated combo visitInfo but I understand that this might not be workable (especially if you are stripping headers like EXPTIME out the combined header rather than updating it) [I hope you aren't leaving the EXPTIME header in there with a confusing value]

Also, we need to fix the LATISS headers so they have the right telescope name...

Copy link
Member

@timj timj left a comment

Choose a reason for hiding this comment

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

I have many questions. I've also re-read combineHeaders and it confuses me a lot because it seems to be making life hard for itself in many places and then not being used anywhere. There are two places it's called and none of them use the return value.

expTime = 0.0
inputVisitInfo = inputExpHandles[0].get(component="visitInfo")
visitInfo = afwImage.VisitInfo(exposureTime=expTime, darkTime=expTime,
instrumentLabel=inputVisitInfo.getInstrumentLabel())
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
instrumentLabel=inputVisitInfo.getInstrumentLabel())
instrumentLabel=inputVisitInfo.instrumentLabel)

# Populate a visitInfo. Set the exposure time and dark time
# to 0.0 or 1.0 as appropriate, and copy the instrument name
# from one of the inputs.
expTime = 1.0
Copy link
Member

Choose a reason for hiding this comment

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

How come the exposure time isn't the sum of all the dark exposure times? We could easily calculate that in combineHeaders since we already loop over visitInfo to store the exposure times in the header.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's 1.0s as the scale factors used to combine the input darks are the dark_time values. This normalizes the combined dark to have unit exposure time, which is then scaled to match the dark_time of the exposures that will be corrected (in IsrTask).

@@ -341,6 +341,18 @@ def run(self, inputExpHandles, inputScales=None, inputDims=None):
self.combineHeaders(inputExpHandles, combinedExp,
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 a bit confused by this call because we don't do anything with the header this calculates.

I also just looked in combineHeaders and I wonder if we can make use of the first and last parameters to merge_headers -- those are designed to allow you to pick the first DATE-OBS you encounter and the last DATE-END you encounter such that the ObservationGroup code at the end might not be needed. Also we now use DATE-BEG in addition to DATE-OBS.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This does set the values in the combined calibration, possibly accidentally, as the header is pulled from the calibration exposure and updated. I've assumed this was a pointer-like operation, and the exposure is updated as the header object is updated.

I don't recall why this was originally returning the header, and that can likely be removed now. For the ObservationGroup code, I'm not sure that it's adding anything essential (in the cp_pipe/ISR sense) to the headers. I thought the merge_headers call was finding all the common headers and adding them, then there's the provenance information being added manually, and from the example headers I've been looking at, there's only a DATE-OBS field being added. The examples appear to be adding that field via the except block, using the calibDate. The comment on that field is wrong (and updated on this branch), but this is another keyword that isn't used downstream anywhere.

Copy link
Member

Choose a reason for hiding this comment

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

Okay. It's all very confusing and seems to be working differently to what it's documented to do. There is the added confusion that it generates a merged header but then copies everything that got dropped back into the original header but that's exactly what the first mode option does in merge_headers anyhow, and if the first and last parameters are used it will automatically makes sure it picks up the first DATE-OBS and the last DATE-END. The way it's now written you don't want merged to exist at all because you are wanting to use the other header you got from the exposure and then copy everything back out of merged into the alias.

I think ObservationGroup is used because that can sort the headers into date order before it reads back the start time and end time (which it gets from header translation).

expTime = 1.0
if self.config.connections.outputData.lower() == 'bias':
expTime = 0.0
inputVisitInfo = inputExpHandles[0].get(component="visitInfo")
Copy link
Member

Choose a reason for hiding this comment

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

Would be convenient if we didn't have to do this because combineHeaders returned some kind of combo VisitInfo as well as the modified header.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've moved this into the combineHeaders call, as that has the VisitInfo list already available, to avoid the unnecessary extra get.

Copy link
Member

@timj timj left a comment

Choose a reason for hiding this comment

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

This looks okay. Thanks.

Maybe change the documentation for combineHeaders to say that it will update the header in place for calib as well as returning it.

@czwa czwa merged commit f02adec into main Apr 13, 2023
1 check passed
@czwa czwa deleted the tickets/DM-38486 branch April 13, 2023 20:31
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