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-10299: Apply crosstalk correction in decam #50
Conversation
python/lsst/ip/isr/isrTask.py
Outdated
@@ -465,6 +466,9 @@ def run(self, ccdExposure, bias=None, linearizer=None, dark=None, flat=None, def | |||
|
|||
@return a pipeBase.Struct with field: | |||
- exposure | |||
otherDataRef : `lsst.daf.persistence.butlerSubset.ButlerDataRef` | |||
optional dataRef, e.g., needed for DECam crosstalk correction |
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.
Isn't it possible to derive the exposure-based dataRef
from the CCD-based dataRef
?
And I believe the run
method is forbidden from receiving a dataRef
.
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.
You're correct that run
methods generally shouldn't receive a dataRef
, as per RFC-352. I've added this special case because I need to extract data from other CCDs within DecamCrosstalkTask
. I use the dataRef
to get a Butler and retrieve one or more different exposures with different ccdnums as needed. It's not clear to me how I could move this into a runDataRef
method as suggested by RFC-352, but I'm open to suggestions.
I also thought I'd preserved old-style docstrings here for consistency (this was before the AHM hack day doc-venture), so I'm impressed you found this briefly-existing numpydoc version :)
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 think this will work:
def getVisitSensorRefs(sensorRef):
"""Return a data reference for all sensors in the visit
Parameters
----------
sensorRef : `lsst.daf.persistence.ButlerDataRef`
Data reference for a single sensor.
Returns
-------
visitSensorRefs : `list` of `lsst.daf.persistence.ButlerDataRef`
Data references for all sensors in the visit.
"""
butler = sensorRef.getButler()
visitKeys = butler.getKeys("raw", "visit")
dataId = sensorRef.dataId.copy()
for kk in set(dataId.keys()).difference(set(visitKeys)):
dataId.pop(kk)
visitRef = butler.dataRef("raw", "visit", dataId)
return [rr for rr in visitRef.subItems("ccd")]
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 established pattern is that runDataRef
loads everything that's required and passes that to the run
method. I am concerned that it's naive (because loading the entire focal plane at once for every CCD is not good), but them's the rules. You'll need to get @RobertLuptonTheGood to sign off on your design.
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.
Note that the decision on RFC-352 was "We will permit exceptions to that, by means of RFC — anybody who is (re-)designing or implementing a task, and who doesn't feel that run is appropriate, can file an RFC to explain why and get an exemption." We haven't fixed up our existing cases either.
Your suggested getVisitSensorRefs()
seems to have its own problems of butler dataId manipulation.
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.
What's the conclusion here? I agree with John that there are cases when we might need to pass objects that look a bit like dataRefs around (reference catalogues are one), but I didn't see an RFC to permit it here.
Why is this in DecamCrosstalkTask
rather than generalising the cross-talk correction code?
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.
Hey folks — just to be clear, the aim behind this PR was for @mrawls to iterate with @SimonKrughoff on the approach she should take here. As of now, that discussion is still ongoing; let's see how it converges. Should any RFCs or other special measures be needed, rest assured that everything will be done by the book.
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 believe the conclusion is to add a (noop) method called prepCrosstalk
to the default CrosstalkTask. Then they will override that in the DECam version to assemble need information. That's a generic solution that other crosstalk implementations can use.
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 may be another argument to the run method, but I don't think it has to be a data ref.
python/lsst/ip/isr/isrTask.py
Outdated
@@ -439,7 +439,8 @@ def readIsrData(self, dataRef, rawExposure): | |||
def run(self, ccdExposure, bias=None, linearizer=None, dark=None, flat=None, defects=None, | |||
fringes=None, bfKernel=None, camera=None, | |||
opticsTransmission=None, filterTransmission=None, | |||
sensorTransmission=None, atmosphereTransmission=None): | |||
sensorTransmission=None, atmosphereTransmission=None, | |||
otherDataRef=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.
The way you've implemented the decam crosstalk correction, I don't think that modifications here are necessary. I think this should be reverted except to add a prepCrosstalk
method to the CrosstalkTask
base class.
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.
That method would be called in the RunDataRef
method on IsrTask. You would still have to pass through the source data object, but then it wouldn't be opaque.
python/lsst/ip/isr/isrTask.py
Outdated
# immediate=True required for functors and linearizers are functors; see ticket DM-6515 | ||
linearizer = dataRef.get("linearizer", immediate=True) if self.doLinearize(ccd) else None | ||
darkExposure = self.getIsrExposure(dataRef, "dark") if self.config.doDark else None | ||
flatExposure = self.getIsrExposure(dataRef, "flat") if self.config.doFlat else None | ||
flatExposure = self.getIsrExposure(dataRef, self.config.flatDataProductName) \ | ||
if self.config.doFlat else 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 confused why this is in a ticket for adding crosstalk. It seems to be complicating the issue.
Also, it seems odd to only generalize two of them. Why not also generalize dark
?
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 came up when I was writing a test which calls DecamCpIsrTask, which had its own copy-pasted readIsrData method for the specially-named cpBias and cpFlat issue alone. It was slowly diverging from ip_isr's readIsrData which is what I wanted to use anyway, so instead of perpetuating the copy-paste cycle I thought it best to just add this fix. (There aren't such a thing as cpDarks so I let it be.)
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 see. Please add the generalization for dark
. I think it would be pretty confusing to someone who uses this to have access to only two of the three.
python/lsst/ip/isr/isrTask.py
Outdated
self.crosstalk.run(ccdExposure, otherDataRef) | ||
if crosstalkSources is not None: | ||
# crosstalkSources is used by DECam | ||
self.crosstalk.run(ccdExposure, crosstalkSources) | ||
else: | ||
self.crosstalk.run(ccdExposure) |
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 think you should add the crosstalkSources to the default CrosstalkTask
. It can default to None
in the base class.
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.
Think I've got this now.
ba25570
to
daf9f15
Compare
daf9f15
to
c17ebf1
Compare
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 happy with this if the one simplification I mention is implemented.
python/lsst/ip/isr/isrTask.py
Outdated
# crosstalkSources is used by DECam | ||
self.crosstalk.run(ccdExposure, crosstalkSources) | ||
else: | ||
self.crosstalk.run(ccdExposure) |
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 can now be collapsed to:
if self.config.doCrosstalk:
self.crosstalk.run(ccdExposure, crosstalkSources)
c17ebf1
to
5990cfb
Compare
Note that only obs_decam presently has a prepCrosstalk method which returns crosstalkSources that are not None. Correspondingly, CrosstalkTask's run now accepts crosstalkSources but expects them to be None by default. Includes some flake8 cleanups and numpydoc docstrings.
This is useful for using community pipeline bias and flats with obs_decam, which are called cpBias and cpFlat. For completeness, we include darkDataProductName too.
5990cfb
to
e427493
Compare
No description provided.