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-23044: PTC task should persist usable linearity models #29
Conversation
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 have quite a few questions and comments. Some of my questions are my lack of understanding of what Linearizer does.
python/lsst/cp/pipe/ptc.py
Outdated
now = datetime.datetime.utcnow() | ||
butler = dataRef.getButler() | ||
|
||
for linPair in [("LOOKUPTABLE", 'linearizeLut'), ("LINEARIZEPOLYNOMIAL", 'linearizePolynomial'), |
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.
change this to
for linType, dataType in [("LOOKUPTABLE", 'linearizeLut'), ("LINEARIZEPOLYNOMIAL", 'linearizePolynomial')]:
python/lsst/cp/pipe/ptc.py
Outdated
instruName=self.config.instrumentName, | ||
linearizerType=linType, tableArray=tableArray, | ||
log=self.log) | ||
butler.put(linearizer.toDict(), datasetType=dataType, dataId={'detector': detNum, |
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.
Why are we putting a dict here and not the actual linearizer object? I don't really understand gen2 so maybe I'm getting confused but shouldn't it be able to take a special object?
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 tried getting rid of "toDict" and it did not work properly. It seems that gen2 butler expects a dict.
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 would need to teach it to do the right thing like we taught butler to understand that Defects can be put.
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 that cp_pipe doesn't use the butler for defects but does try to use the butler for ptc. I think that explains why Butler.put has not been set up for Defects. It should be simple for Linearizer to have the dataset type added to gen2 butler since it emulates a normal Catalog by supporting writeFits.
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.
So the linearizer should be treated like a fits catalog and written as a fits catalog? Should not they be human-readable?
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 are putting them into a butler so the format does not have to be the same as the format you use in obs_lsst_data. If you have been copying the files out of the butler manually then that would make a difference (otherwise you'd need a quick readFits/writeText copy-like command). I don't know how easy it is to add a new formatter in gen2 that would call writeText directly so maybe it's not going to be possible to do this in gen2 properly.
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.
At this moment I don't know either how easy what you describe would be. Could this be left for a future ticket, if necessary?
python/lsst/cp/pipe/ptc.py
Outdated
Detector object | ||
instruName : `str`, optional | ||
Instrument name | ||
linearizerType : `str`, optional |
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.
Given that you default linearizerType argument to an empty string and then raise an exception if you give an empty string, doesn't that mean that the parameter is not optional at all?
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.
Yes. I set "LINEARIZEPOLYNOMIAL" as default.
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 that a safe default to use? Are you better off always being explicit?
python/lsst/cp/pipe/ptc.py
Outdated
Detector name | ||
detNum : `int` | ||
Detector number | ||
detector : `lsst.afw.cameraGeom.detector.detector.Detector` |
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 should be lsst.afw.cameraGeom.Detector
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.
Also, don't pass in detNum and detName if you are already passing in the entire detector object. Calculate what you need directly in this method.
python/lsst/cp/pipe/ptc.py
Outdated
---------- | ||
dataset : `lsst.cp.pipe.ptc.PhotonTransferCurveDataset` | ||
The dataset containing the means, variances and exposure times | ||
detName : `srt` |
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.
str not srt.
python/lsst/cp/pipe/ptc.py
Outdated
linearizer = Linearizer(table=tableArray, log=log) | ||
else: | ||
raise RuntimeError("tableArray must be provided when creating a LookupTable linearizer") | ||
elif linearizerType in ['LINEARIZESQUARED', 'LINEARIZEPOLYNOMIAL']: |
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.
In general using a list for a readonly sequence seems odd to me and a tuple might be better. Also be consistent with quote type. You mostly seem to use double quotes so use them everywhere.
ampName = amp.getName() | ||
if linearizerType == 'LOOKUPTABLE': | ||
linearizer.linearityCoeffs[ampName] = [i, 0] | ||
linearizer.linearityType[ampName] = "LookupTable" |
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.
A way to remove the linearity type from the if clauses would be to define the mapping in a dict:
linearityType = {"LOOKUPTABLE": "LookupTable", "LINEARIZESQUARED": "Squared"}
for ... in ...:
linearizer.linearityType[ampName] = linearityType[linearizerType]
Saying that, why do you need to tell the Linearizer object what each amp is when it seems to be a constant? Am I seeing a special case here or is it always true that every amp has the same type? Could you instead have Linearizer subclasses that have their type defined for them like @SimonKrughoff did for the Curve class? Maybe @czwa can tell me. Of course if each amp can have different types then that would explain this but the code here doesn't allow that.
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.
Having this be amplifier based instead of detector (or camera) based is a result of directly mapping the cameraGeom linearity parameters to the new Linearizer. I also didn't want to prevent different amplifiers from having different correction types (because electronics can always be difficult in unique ways).
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.
So this means that Linearizer can support per-amp but this cp_pipe task can't. Can this be mentioned somewhere in the task docstring?
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 left the "if" clauses because there are other things specific to each linearizer type that are being set. I added clarification regarding the linearizers in the doc-string of "MeasurePhotonTransferCurveTask".
python/lsst/cp/pipe/ptc.py
Outdated
meanSignalVector = k0 + k1*exposureTimeVector + k2*exposureTimeVector^2 +... | ||
+ kn*exposureTimeVector^n, with n = "polynomialFitDegreeNonLinearity". | ||
|
||
linearizerTableRow: list of `np.float` | ||
linearizerTableRow : list of `np.float` |
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.
Use back ticks. I think np.float
and float
are interchangeable so do they really need to be numpy floats?
python/lsst/cp/pipe/ptc.py
Outdated
@@ -623,55 +735,76 @@ def calculateLinearityResidualAndLinearizers(self, exposureTimeVector, meanSigna | |||
|
|||
Returns | |||
------- | |||
c0: `np.float` | |||
polynomialLinearizerCoefficients : `list` of `np.float` |
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.
Do not use np
abbreviation in docstrings. numpy.float
should be used. Why is this a list of individual numpy floats and not a single numpy array? (and also float
and numpy.float
should be identical from your point of view shouldn't they?)
python/lsst/cp/pipe/ptc.py
Outdated
if ptcFitType == 'ASTIERAPPROXIMATION': | ||
ptcFunc = self.funcAstier | ||
stringTitle = r"Var = $\frac{1}{2g^2a_{00}}(\exp (2a_{00} \mu g) - 1) + \frac{n_{00}}{g^2}$" | ||
|
||
stringTitle = (r"Var = $\frac{1}{2g^2a_{00}}(\exp (2a_{00} \mu g) - 1) + \frac{n_{00}}{g^2}$ " + |
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.
Do not use a plus to concatenate. It's not needed.
python/lsst/cp/pipe/ptc.py
Outdated
""" | ||
if linearizerType == 'LOOKUPTABLE': | ||
if tableArray is not None: | ||
linearizer = Linearizer(table=tableArray, log=log) |
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.
Would it help if the detector argument was passed in here?
No description provided.