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-23983: Cannot apply crosstalk in Gen 3 DECam processing #150

Merged
merged 7 commits into from Jun 11, 2020

Conversation

czwa
Copy link
Contributor

@czwa czwa commented May 18, 2020

Handle crosstalk via a CrosstalkCalibs persisted as FITS/YAML. Use ip_isr's updated CrosstalkTask for application, even for inter-ccd crosstalk. obs_decam still needs to subclass CrosstalkTask to implement the prepCrosstalk() method with gen2 butlers.

@czwa czwa requested a review from mrawls May 18, 2020 20:10
decam/SConscript Outdated

makeCrosstalk = env.Command(crosstalkOutDir, crosstalkInFile, command)

# Ingest crosstalk
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest a second comment here explaining that this calls ingestCuratedCalibs.py to put crosstalk calib products in the built obs_decam package. Please update the very top comment line of this script to indicate that it does things pertaining to linearity, defects, and crosstalk.

dataDict['coeffs'] = dataDict['coeffs'].transpose()

decamCT = ipIsr.crosstalk.CrosstalkCalib.fromDict(dataDict)
# Lie to ingestCuratedCalibs, because it interprets calibDate as validStart.
Copy link
Contributor

Choose a reason for hiding this comment

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

lol... how do defects handle this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The conversion of existing defects wrote the yaml representation (what this script is attempting to duplicate) to files containing the explicit start points, and set CALIBDATE to that value. The new defects use the midpoint of the input observations (which I don't think it correct, either). I've updated the comment to be more informative, and this will likely be revisited in the future when all the calibrations are more unified.

Raised if the detector is not known.
"""
ampIndexMap = {'A': 0, 'B': 1}
detMap = {'ccd01': 'S29', 'ccd02': 'S30', 'ccd03': 'S31', 'ccd04': 'S25', 'ccd05': 'S26',
Copy link
Contributor

Choose a reason for hiding this comment

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

This nearly duplicates

detectorNames = {
1: 'S29', 2: 'S30', 3: 'S31', 4: 'S25', 5: 'S26', 6: 'S27', 7: 'S28', 8: 'S20', 9: 'S21',
10: 'S22', 11: 'S23', 12: 'S24', 13: 'S14', 14: 'S15', 15: 'S16', 16: 'S17', 17: 'S18',
18: 'S19', 19: 'S8', 20: 'S9', 21: 'S10', 22: 'S11', 23: 'S12', 24: 'S13', 25: 'S1', 26: 'S2',
27: 'S3', 28: 'S4', 29: 'S5', 30: 'S6', 31: 'S7', 32: 'N1', 33: 'N2', 34: 'N3', 35: 'N4',
36: 'N5', 37: 'N6', 38: 'N7', 39: 'N8', 40: 'N9', 41: 'N10', 42: 'N11', 43: 'N12', 44: 'N13',
45: 'N14', 46: 'N15', 47: 'N16', 48: 'N17', 49: 'N18', 50: 'N19', 51: 'N20', 52: 'N21',
53: 'N22', 54: 'N23', 55: 'N24', 56: 'N25', 57: 'N26', 58: 'N27', 59: 'N28', 60: 'N29',
62: 'N31'}
, is that because the mapper is going to go away? Is there a more generic place for this mapping to land?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to use DecamMapper.detectorNames here and for detSerialMap (which is just a flip of key:value to value:key). If the mapper does go away, this will suddenly fail, and will need to be handled at that time.
I think the "more generic" place is the obs_decam Instrument definition, but I'm not sure.

decamCT.writeText(f"{outDir}/1970-01-01T00:00:00.yaml")


def readFile(fromFile):
Copy link
Contributor

Choose a reason for hiding this comment

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

fromFile is an awkward variable name, perhaps crosstalkFile? I do appreciate that "from" indicates it's to be read from and not written to, though, so maybe crosstalkInfile?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fromFile -> crosstalkInfile

@@ -0,0 +1,32 @@
description: ip_isr handling of DECAM specific full FP CT solution
Copy link
Contributor

Choose a reason for hiding this comment

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

If permitted with character limits etc., DECAM -> DECam, FP -> focal plane, CT -> crosstalk

reference: raw_visit
storage: FitsStorage
tables: crosstalk
template: crosstalk/%(calibDate)s/crosstalk-%(calibDate)s-%(ccdnum)03d.fits
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems weird to me that the date that lands in the file path will be something in 1970 and have no bearing on how recent the crosstalk coefficients actually are. This probably doesn't matter 99% of the time... what do defects do?

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 the same thing as this: calibDate is used to index the files, using 1970 as the "for all data" value, with later dates used to indicate when the previous calibration should be superseded. If the crosstalk changes, we'll either need to replace the xtalk text file that is used to generate the tables (if the new values are better measurements), or will need to modify makeCrosstalkDecam.py to set calibDate differently (if the new values represent a physical change in the crosstalk of the camera).

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair enough, I guess we will live with it :) validity is so tricky!

try:
source_exposure = butler.get('raw', dataId={'visit': visit, 'ccd': sourceDet})
except RuntimeError:
self.log.warn('Cannot access source %s, SKIPPING IT' % sourceDet)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use f-strings instead of % thingies, unlike whoever wrote the original code 🙃

for amp in source_exposure.getDetector():
decamisr.overscanCorrection(source_exposure, amp)

# Do not assemble here, as DECam CT is corrected before assembly.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this always the case, now? I remember the old doCrosstalkBeforeAssemble but I don't remember when it was True or False or why.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

HSC and DECam have different conventions, and I think there's a linearity correction term that changes the pixel values differently depending on when it's applied.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair enough, but there is still a doCrosstalkBeforeAssemble in the ip_isr config. It defaults to False in ip_isr, but unless that config is going away, I would prefer to refer to it here (even if it hardwired one way or the other and there is virtually no reason to have it set differently).

(crosstalk._detectorName, sourceDet))

for amp in source_exposure.getDetector():
decamisr.overscanCorrection(source_exposure, amp)
Copy link
Contributor

Choose a reason for hiding this comment

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

There was previously a check to see if maybe it had already been overscan corrected, but I suppose that's virtually impossible?

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 should be impossible. This only triggers in gen2, and explicitly requests the 'raw'. In gen3, this isn't called because the crosstalkSources there are isrOscanCorr, which always should have the overscan removed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotcha. Incidentally, can the gen3 crosstalkSources be more verbosely isrOverscanCorrected?

return crosstalkSources

@pipeBase.timeMethod
def run(self, exposure, crosstalkSources=None):
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 going to assume this all moved to ip_isr and not panic.

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 now inheriting the new CrosstalkTask.run(), and that has all the inter-chip logic now.

czwa added 4 commits June 1, 2020 14:46
ip_isr now supports inter-chip crosstalk, so use that code.  Add
script to construct compatible crosstalk calibration files.
As part of the transition to the new crosstalk code, Decam now only
needs to implement the prepCrosstalk method.  This reads the interChip
portion of the crosstalk calibration, and uses that to pre-process the
other source detectors needed for the current ISR process.
@czwa czwa merged commit 350520e into master Jun 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants