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-23238: Add per row overscan removal #125
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.
General comment beyond the individual ones though: I am kind of surprised this isn't just a few lines put in around L513 where it says
elif fitType in ('MEDIAN',): if overscanIsInt:
because at that point, you've got the int image already. Can you not just loop over the rows there? Am I misunderstanding the flow here?
@@ -106,7 +111,6 @@ def checkPolyOverscanCorrectionX(self, **kwargs): | |||
|
|||
dataBox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(10, 10)) | |||
dataImage = afwImage.MaskedImageF(maskedImage, dataBox) | |||
|
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.
Not sure why this empty line (and the one below, and above at L333) got deleted/added, but I'm not really one who cares about this. Others certainly are, so in general try not to do this unless there's a reason for it.
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 don't remember why that's there, probably I was testing some code, or put a "print" statement and then deleted it. I don't care either; why is it important?
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 it's just generally untidy and making diffing more confusing. @timj are there reasons to care deeply about such things?
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.
Usually removing or adding lines in parts of the code not being changed is not seen as worthwhile unless it's making the code compliant with some standard. I tend to avoid these sorts of changes because they distract people reading the diff into wondering why the line disappeared. If removing/adding the blank line is wanted it should be done as a distinct commit making clear this is a formatting cleanup.
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 also would prefer keeping the blank lines as I find they make the code easier to read. And below on L118 as well. And above on L85.
python/lsst/ip/isr/isrFunctions.py
Outdated
fitTypeStats = afwMath.stringToStatisticsProperty('MEDIAN') | ||
# Loop over rows because there is no afwMath.Median(array, axis=1) | ||
for row in biasMaskedArr: | ||
if row.mask is False: |
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 need to go in with a debugger, but is that ever True
? Isn't row.mask
the mask array for a whole row? If so, that never is
False.
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.
Actually, one of the unit tests found that it could be False
if this condition is not satisfied: https://github.com/lsst/ip_isr/blob/tickets/DM-23238/python/lsst/ip/isr/isrFunctions.py#L545 (a masked numpy array is not created).
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 might == False
but surely it can't be False
, right?
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.e. remember that 0 == False
is True, but 0 is False
is not.
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 have to be careful if a mask is in theory a numpy array here. There are many definitions of "truth" available depending on whether there is any numpy mask attached and whether it's filled with zeroes. If mask is meant to be a numpy array I would not expect it to ever be truly the boolean False
. Is this really testing that mask
is None
rather than False
?
python/lsst/ip/isr/isrFunctions.py
Outdated
# Loop over rows because there is no afwMath.Median(array, axis=1) | ||
for row in biasMaskedArr: | ||
if row.mask is False: | ||
row.mask = numpy.repeat(False, len(row)) |
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.
And even then, I'm not quite sure what this is doing really.
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 second argument of medianRow = afwMath.makeStatistics(row, row.mask, fitTypeStats, statControl).getValue()
---one line below---is expecting a list. It fails if it just False
, so I'm creating a list of False
to pass a valid argument.
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 don't think you have to pass in a mask at all. Can't you just remove the argument and call with a different signature?
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, as discussed OOB, I don't think we ever want to mask a row - it makes sense for things where a spline or poly is being fitted up the column, but for a row-wise median we have to have a number for every row.
python/lsst/ip/isr/isrFunctions.py
Outdated
for row in biasMaskedArr: | ||
if row.mask is False: | ||
row.mask = numpy.repeat(False, len(row)) | ||
medianRow = afwMath.makeStatistics(row, row.mask, fitTypeStats, statControl).getValue() |
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, I just realised, doing this here means you're actually doing a single-round-sigma-clipped row-wise median, right? Not saying that's bad per se but trying to understand what's happening here.
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 are a few lines before the loop that do some clipping, and then, in the loop, the median is taken, as you point out. This section of the code was originally intended for the polynomial cases of the overscan correction, so it might be redundant in the case of the median per row. But then if I move the loop to the other section, things might break as we pointed out in another comment.
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.
Can you check with @RobertLuptonTheGood (or he can confirm here, now that he's tagged) that he's OK with doing a single round of clipping before doing the per-row median please? I don't it's necessarily bad, but maybe there is some statistical subtlety that will cause him to dislike this.
For any onlookers, @czwa is taking over the review now. |
I moved the loop that calculates the median per row to the part of the code where it says |
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.
Looks good. I think there are just style issues here.
@@ -106,7 +111,6 @@ def checkPolyOverscanCorrectionX(self, **kwargs): | |||
|
|||
dataBox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(10, 10)) | |||
dataImage = afwImage.MaskedImageF(maskedImage, dataBox) | |||
|
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 also would prefer keeping the blank lines as I find they make the code easier to read. And below on L118 as well. And above on L85.
python/lsst/ip/isr/isrFunctions.py
Outdated
offArray = offImage.getArray() | ||
ovFitArray = overscanFit.getArray() | ||
offArray[:, :] = collapsedReshaped | ||
ovFitArray[:, :] = numpy.repeat(collapsed, biasArray.shape[1]).reshape(biasArray.shape) |
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 it possible to refactor this to use the simpler offArray[:, :] = vector[:, numpy.newaxis] or vector[numpy.newaxis, :]
as is done for the spline/polynomial fits below (L629 on master)? I think all these transposes and repeats are correct, but I find the newaxis notation easier to follow.
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 followed this suggestion (thanks), and have followed what is done in the spline/polynomial part.
python/lsst/ip/isr/isrFunctions.py
Outdated
|
||
if overscanIsInt: | ||
del overscanImageI | ||
elif fitType in ('POLY', 'CHEB', 'LEG', 'NATURAL_SPLINE', 'CUBIC_SPLINE', 'AKIMA_SPLINE'): | ||
elif fitType in ('POLY', 'CHEB', 'LEG', 'NATURAL_SPLINE', 'CUBIC_SPLINE', |
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 change needed? Same with whitespace below on L561.
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 fixed these.
cc75af8
to
3d1d6db
Compare
No description provided.