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
Conversation
decam/SConscript
Outdated
|
||
makeCrosstalk = env.Command(crosstalkOutDir, crosstalkInFile, command) | ||
|
||
# Ingest crosstalk |
There was a problem hiding this comment.
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.
decam/makeCrosstalkDecam.py
Outdated
dataDict['coeffs'] = dataDict['coeffs'].transpose() | ||
|
||
decamCT = ipIsr.crosstalk.CrosstalkCalib.fromDict(dataDict) | ||
# Lie to ingestCuratedCalibs, because it interprets calibDate as validStart. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
decam/makeCrosstalkDecam.py
Outdated
Raised if the detector is not known. | ||
""" | ||
ampIndexMap = {'A': 0, 'B': 1} | ||
detMap = {'ccd01': 'S29', 'ccd02': 'S30', 'ccd03': 'S31', 'ccd04': 'S25', 'ccd05': 'S26', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This nearly duplicates
obs_decam/python/lsst/obs/decam/decamMapper.py
Lines 49 to 57 in 0afad47
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'} |
There was a problem hiding this comment.
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.
decam/makeCrosstalkDecam.py
Outdated
decamCT.writeText(f"{outDir}/1970-01-01T00:00:00.yaml") | ||
|
||
|
||
def readFile(fromFile): |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fromFile
-> crosstalkInfile
pipelines/RunIsr.yaml
Outdated
@@ -0,0 +1,32 @@ | |||
description: ip_isr handling of DECAM specific full FP CT solution |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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!
python/lsst/obs/decam/crosstalk.py
Outdated
try: | ||
source_exposure = butler.get('raw', dataId={'visit': visit, 'ccd': sourceDet}) | ||
except RuntimeError: | ||
self.log.warn('Cannot access source %s, SKIPPING IT' % sourceDet) |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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.
Ignore crosstalk directory.
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.