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-23396: Function "overscanCorrection" in "isrFunctions.py" needs refactoring #127

Merged
merged 2 commits into from Apr 27, 2020

Conversation

czwa
Copy link
Contributor

@czwa czwa commented Feb 24, 2020

Split isrFunctions.overscanCorrection to new class.

This split is necessary to reduce the confusion in overscanCorrection,
reduce the duplication, and limit the number of nested if/else
statements used. The functionality should be identical, just in
better named and more reusable components.

@czwa czwa requested a review from PaulPrice February 24, 2020 17:07
Copy link
Contributor

@PaulPrice PaulPrice left a comment

Choose a reason for hiding this comment

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

I think this needs a bit more work. The OverscanCorrector class should be a Task, and should contain all the overscan correction logic so the caller doesn't need to do any logic themselves.

import lsst.afw.image as afwImage


class OverscanCorrector():
Copy link
Contributor

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 a Task, as that's the standard unit of code reuse. It would also give you access to a logger and configuration parameters. And otherwise, just about all the methods below should be @staticmethod: self is unused.

Comment on lines 509 to 515
if fitType in ('MEAN', 'MEANCLIP', 'MEDIAN'):
overscanValue, maskArray, isTransposed = corrector.overscanConstant(overscanImage)
elif fitType in ('MEDIAN_PER_ROW', 'POLY', 'CHEB', 'LEG',
'NATURAL_SPLINE', 'CUBIC_SPLINE', 'AKIMA_SPLINE'):
overscanValue, maskArray, isTransposed = corrector.overscanVector(overscanImage, order)
else:
raise pexExcept.Exception('%s : %s an invalid overscan type' % ("overscanCorrection", fitType))
Copy link
Contributor

Choose a reason for hiding this comment

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

Move this logic into the OverscanCorrectionTask. That's the thing that knows what it can do, so it should decide how to do it.


if isinstance(overscanValue, float):
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to see this logic in the OverscanCorrectionTask too. It knows best what the return types are, so it knows best how to apply them.

statControl : `lsst.afw.math.StatisticsControl`, optional
Statistics control object.
sigma : `float`, optional
Number of sigma to use for sigma clipping.
Copy link
Contributor

Choose a reason for hiding this comment

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

fitType and sigma should go in OverscanCorrectionConfig.


Parameters
----------
image : `numpy.ndarray`, `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage`
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect this goes over 80 chars. Is that allowed? If not, how do we deal with it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could not find any details, and have abbreviated types to fit.

python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Show resolved Hide resolved
@czwa czwa force-pushed the tickets/DM-23396 branch 4 times, most recently from 5015951 to 477b450 Compare March 4, 2020 22:20
@czwa czwa requested a review from PaulPrice March 4, 2020 22:24
Copy link
Contributor

@PaulPrice PaulPrice left a comment

Choose a reason for hiding this comment

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

You need to go one step further: use the OverscanCorrectionTask directly in the `IsrTask.

config.overscanIsInt = True

overscanTask = OverscanCorrectionTask(config=config)
return overscanTask.run(ampImage, overscanImage)
Copy link
Contributor

Choose a reason for hiding this comment

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

You should deprecate this function, and modify IsrTask to call the OverscanCorrectionTask directly. Otherwise, there's not really any advantage to having the overscan correction in a Task.

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 newest commit does this, although it still calls it from an IsrTask.overscanCorrection call. The overscan chopping is still in IsrTask, allowing OverscanCorrectionTask to concentrate on the image-level math.

This has necessitated config changes on obs_ packages to point to the updated overscan config item.

python/lsst/ip/isr/overscan.py Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
"CUBIC_SPLINE": "Fit cubic spline to the longest axis of the overscan region",
"AKIMA_SPLINE": "Fit Akima spline to the longest axis of the overscan region",
"MEAN": "Correct using the mean of the overscan region",
"MEANCLIP": "Correct using a clipped mean of the overscan region",
Copy link
Contributor

Choose a reason for hiding this comment

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

Where are the clipping parameters set?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OverscanCorrectionTaskConfig.numSigmaClip controls the clipping.

python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
python/lsst/ip/isr/overscan.py Show resolved Hide resolved
@czwa czwa force-pushed the tickets/DM-23396 branch 2 times, most recently from 77bca0f to c5e6fc9 Compare March 10, 2020 20:59
@czwa czwa requested a review from PaulPrice April 15, 2020 21:46
Copy link
Contributor

@PaulPrice PaulPrice left a comment

Choose a reason for hiding this comment

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

Just a few minor details.

python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
Value or fit subtracted from the amplifier image data.
- ``overscanFit`` : scalar or `lsst.afw.image.Image`
Value or fit subtracted from the overscan image data.
- ``overscanImage`` : `lsst.afw.image.Image`
Copy link
Contributor

Choose a reason for hiding this comment

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

Why return this? The input overscanImage should be modified, so the user has this already.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is used (optionally) in the empirical variance calculation. That happens after the trim and assembly, and I suspect saving that image segment as part of the overscan results struct was chosen instead of deciding whether to save it during the trim step.

python/lsst/ip/isr/overscan.py Outdated Show resolved Hide resolved
@@ -131,6 +152,9 @@ def run(self, ampImage, overscanImage):
overscanArray[:, :] = overscanValue[:, np.newaxis]
if maskSuspect:
maskSuspect.getArray()[maskArray, :] |= ampImage.getMask().getPlaneBitMask("SUSPECT")
else:
raise pexExcept.Exception('%s : %s an invalid overscan type' %
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this particular exception type, rather than something more specific?

Copy link
Member

Choose a reason for hiding this comment

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

Also in python we really want to raise python exceptions not pex_exception exceptions. Those exist so that C++ code can raise python-style exceptions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to RuntimeError.

if 'fitType' in kwargs:
config.overscan.fitType = kwargs['fitType']
if 'order' in kwargs:
config.overscan.order = kwargs['order']
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you should be more defensive about kwargs contents only matching the things you're looking for.

Here and in other places below (factor this into a function).

This split is necessary to reduce the confusion in overscanCorrection,
reduce the duplication, and limit the number of nested if/else
statements used.  The functionality should be identical, just in
better named and more reusable components.
@czwa czwa merged commit a9bf60b into master Apr 27, 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
Development

Successfully merging this pull request may close these issues.

None yet

3 participants