34from contextlib
import contextmanager
36from .overscan
import OverscanCorrectionTask, OverscanCorrectionTaskConfig
37from .defects
import Defects
41 """Make a double Gaussian PSF.
46 FWHM of double Gaussian smoothing kernel.
51 The created smoothing kernel.
53 ksize = 4*int(fwhm) + 1
54 return measAlg.DoubleGaussianPsf(ksize, ksize, fwhm/(2*math.sqrt(2*math.log(2))))
58 """Make a transposed copy of a masked image.
68 The transposed copy of the input image.
70 transposed = maskedImage.Factory(lsst.geom.Extent2I(maskedImage.getHeight(), maskedImage.getWidth()))
71 transposed.getImage().getArray()[:] = maskedImage.getImage().getArray().T
72 transposed.getMask().getArray()[:] = maskedImage.getMask().getArray().T
73 transposed.getVariance().getArray()[:] = maskedImage.getVariance().getArray().T
78 """Interpolate over defects specified in a defect list.
84 defectList : `lsst.meas.algorithms.Defects`
85 List of defects to interpolate over.
87 FWHM of double Gaussian smoothing kernel.
88 fallbackValue : scalar, optional
89 Fallback value if an interpolated value cannot be determined.
90 If
None, then the clipped mean of the image
is used.
93 if fallbackValue
is None:
95 if 'INTRP' not in maskedImage.getMask().getMaskPlaneDict():
96 maskedImage.getMask().addMaskPlane(
'INTRP')
97 measAlg.interpolateOverDefects(maskedImage, psf, defectList, fallbackValue,
True)
102 """Mask pixels based on threshold detection.
107 Image to process. Only the mask plane is updated.
110 growFootprints : scalar, optional
111 Number of pixels to grow footprints of detected regions.
112 maskName : str, optional
113 Mask plane name,
or list of names to convert
117 defectList : `lsst.meas.algorithms.Defects`
118 Defect list constructed
from pixels above the threshold.
121 thresh = afwDetection.Threshold(threshold)
122 fs = afwDetection.FootprintSet(maskedImage, thresh)
124 if growFootprints > 0:
125 fs = afwDetection.FootprintSet(fs, rGrow=growFootprints, isotropic=
False)
126 fpList = fs.getFootprints()
129 mask = maskedImage.getMask()
130 bitmask = mask.getPlaneBitMask(maskName)
131 afwDetection.setMaskFromFootprintList(mask, fpList, bitmask)
133 return Defects.fromFootprintList(fpList)
136def growMasks(mask, radius=0, maskNameList=['BAD'], maskValue="BAD"):
137 """Grow a mask by an amount and add to the requested plane.
142 Mask image to process.
144 Amount to grow the mask.
145 maskNameList : `str` or `list` [`str`]
146 Mask names that should be grown.
148 Mask plane to assign the newly masked pixels to.
151 thresh = afwDetection.Threshold(mask.getPlaneBitMask(maskNameList), afwDetection.Threshold.BITMASK)
152 fpSet = afwDetection.FootprintSet(mask, thresh)
153 fpSet = afwDetection.FootprintSet(fpSet, rGrow=radius, isotropic=
False)
154 fpSet.setMask(mask, maskValue)
158 maskNameList=['SAT'], fallbackValue=None):
159 """Interpolate over defects identified by a particular set of mask planes.
166 FWHM of double Gaussian smoothing kernel.
167 growSaturatedFootprints : scalar, optional
168 Number of pixels to grow footprints for saturated pixels.
169 maskNameList : `List` of `str`, optional
171 fallbackValue : scalar, optional
172 Value of last resort
for interpolation.
174 mask = maskedImage.getMask()
176 if growSaturatedFootprints > 0
and "SAT" in maskNameList:
180 growMasks(mask, radius=growSaturatedFootprints, maskNameList=[
'SAT'], maskValue=
"SAT")
182 thresh = afwDetection.Threshold(mask.getPlaneBitMask(maskNameList), afwDetection.Threshold.BITMASK)
183 fpSet = afwDetection.FootprintSet(mask, thresh)
184 defectList = Defects.fromFootprintList(fpSet.getFootprints())
193 """Mark saturated pixels and optionally interpolate over them
200 Saturation level used as the detection threshold.
202 FWHM of double Gaussian smoothing kernel.
203 growFootprints : scalar, optional
204 Number of pixels to grow footprints of detected regions.
205 interpolate : Bool, optional
206 If
True, saturated pixels are interpolated over.
207 maskName : str, optional
209 fallbackValue : scalar, optional
210 Value of last resort
for interpolation.
213 maskedImage=maskedImage,
214 threshold=saturation,
215 growFootprints=growFootprints,
225 """Compute number of edge trim pixels to match the calibration data.
227 Use the dimension difference between the raw exposure and the
228 calibration exposure to compute the edge trim pixels. This trim
229 is applied symmetrically,
with the same number of pixels masked on
237 Calibration image to draw new bounding box
from.
242 ``rawMaskedImage`` trimmed to the appropriate size
246 Rasied
if ``rawMaskedImage`` cannot be symmetrically trimmed to
247 match ``calibMaskedImage``.
249 nx, ny = rawMaskedImage.getBBox().getDimensions() - calibMaskedImage.getBBox().getDimensions()
251 raise RuntimeError(
"Raw and calib maskedImages are trimmed differently in X and Y.")
253 raise RuntimeError(
"Calibration maskedImage is trimmed unevenly in X.")
255 raise RuntimeError(
"Calibration maskedImage is larger than raw data.")
259 replacementMaskedImage = rawMaskedImage[nEdge:-nEdge, nEdge:-nEdge, afwImage.LOCAL]
260 SourceDetectionTask.setEdgeBits(
262 replacementMaskedImage.getBBox(),
263 rawMaskedImage.getMask().getPlaneBitMask(
"EDGE")
266 replacementMaskedImage = rawMaskedImage
268 return replacementMaskedImage
272 """Apply bias correction in place.
277 Image to process. The image is modified by this method.
279 Bias image of the same size
as ``maskedImage``
280 trimToFit : `Bool`, optional
281 If
True, raw data
is symmetrically trimmed to match
287 Raised
if ``maskedImage``
and ``biasMaskedImage`` do
not have
294 if maskedImage.getBBox(afwImage.LOCAL) != biasMaskedImage.getBBox(afwImage.LOCAL):
295 raise RuntimeError(
"maskedImage bbox %s != biasMaskedImage bbox %s" %
296 (maskedImage.getBBox(afwImage.LOCAL), biasMaskedImage.getBBox(afwImage.LOCAL)))
297 maskedImage -= biasMaskedImage
300def darkCorrection(maskedImage, darkMaskedImage, expScale, darkScale, invert=False, trimToFit=False):
301 """Apply dark correction in place.
306 Image to process. The image is modified by this method.
308 Dark image of the same size
as ``maskedImage``.
310 Dark exposure time
for ``maskedImage``.
312 Dark exposure time
for ``darkMaskedImage``.
313 invert : `Bool`, optional
314 If
True, re-add the dark to an already corrected image.
315 trimToFit : `Bool`, optional
316 If
True, raw data
is symmetrically trimmed to match
322 Raised
if ``maskedImage``
and ``darkMaskedImage`` do
not have
327 The dark correction
is applied by calculating:
328 maskedImage -= dark * expScaling / darkScaling
333 if maskedImage.getBBox(afwImage.LOCAL) != darkMaskedImage.getBBox(afwImage.LOCAL):
334 raise RuntimeError(
"maskedImage bbox %s != darkMaskedImage bbox %s" %
335 (maskedImage.getBBox(afwImage.LOCAL), darkMaskedImage.getBBox(afwImage.LOCAL)))
337 scale = expScale / darkScale
339 maskedImage.scaledMinus(scale, darkMaskedImage)
341 maskedImage.scaledPlus(scale, darkMaskedImage)
345 """Set the variance plane based on the image plane.
350 Image to process. The variance plane is modified.
352 The amplifier gain
in electrons/ADU.
354 The amplifier read nmoise
in ADU/pixel.
356 var = maskedImage.getVariance()
357 var[:] = maskedImage.getImage()
362def flatCorrection(maskedImage, flatMaskedImage, scalingType, userScale=1.0, invert=False, trimToFit=False):
363 """Apply flat correction in place.
368 Image to process. The image is modified.
370 Flat image of the same size
as ``maskedImage``
372 Flat scale computation method. Allowed values are
'MEAN',
374 userScale : scalar, optional
375 Scale to use
if ``scalingType``=
'USER'.
376 invert : `Bool`, optional
377 If
True, unflatten an already flattened image.
378 trimToFit : `Bool`, optional
379 If
True, raw data
is symmetrically trimmed to match
385 Raised
if ``maskedImage``
and ``flatMaskedImage`` do
not have
386 the same size
or if ``scalingType``
is not an allowed value.
391 if maskedImage.getBBox(afwImage.LOCAL) != flatMaskedImage.getBBox(afwImage.LOCAL):
392 raise RuntimeError(
"maskedImage bbox %s != flatMaskedImage bbox %s" %
393 (maskedImage.getBBox(afwImage.LOCAL), flatMaskedImage.getBBox(afwImage.LOCAL)))
399 if scalingType
in (
'MEAN',
'MEDIAN'):
402 elif scalingType ==
'USER':
403 flatScale = userScale
405 raise RuntimeError(
'%s : %s not implemented' % (
"flatCorrection", scalingType))
408 maskedImage.scaledDivides(1.0/flatScale, flatMaskedImage)
410 maskedImage.scaledMultiplies(1.0/flatScale, flatMaskedImage)
414 """Apply illumination correction in place.
419 Image to process. The image is modified.
421 Illumination correction image of the same size
as ``maskedImage``.
423 Scale factor
for the illumination correction.
424 trimToFit : `Bool`, optional
425 If
True, raw data
is symmetrically trimmed to match
431 Raised
if ``maskedImage``
and ``illumMaskedImage`` do
not have
437 if maskedImage.getBBox(afwImage.LOCAL) != illumMaskedImage.getBBox(afwImage.LOCAL):
438 raise RuntimeError(
"maskedImage bbox %s != illumMaskedImage bbox %s" %
439 (maskedImage.getBBox(afwImage.LOCAL), illumMaskedImage.getBBox(afwImage.LOCAL)))
441 maskedImage.scaledDivides(1.0/illumScale, illumMaskedImage)
445 statControl=None, overscanIsInt=True):
446 """Apply overscan correction in place.
451 Image of amplifier to correct; modified.
453 Image of overscan; modified.
455 Type of fit
for overscan correction. May be one of:
457 - ``MEAN``: use mean of overscan.
458 - ``MEANCLIP``: use clipped mean of overscan.
459 - ``MEDIAN``: use median of overscan.
460 - ``MEDIAN_PER_ROW``: use median per row of overscan.
461 - ``POLY``: fit
with ordinary polynomial.
462 - ``CHEB``: fit
with Chebyshev polynomial.
463 - ``LEG``: fit
with Legendre polynomial.
464 - ``NATURAL_SPLINE``: fit
with natural spline.
465 - ``CUBIC_SPLINE``: fit
with cubic spline.
466 - ``AKIMA_SPLINE``: fit
with Akima spline.
469 Polynomial order
or number of spline knots; ignored unless
470 ``fitType`` indicates a polynomial
or spline.
472 Statistics control object. In particular, we pay attention to
474 overscanIsInt : `bool`
475 Treat the overscan region
as consisting of integers, even
if it
's been
476 converted to float. E.g. handle ties properly.
480 result : `lsst.pipe.base.Struct`
481 Result struct with components:
483 - ``imageFit``: Value(s) removed
from image (scalar
or
485 - ``overscanFit``: Value(s) removed
from overscan (scalar
or
487 - ``overscanImage``: Overscan corrected overscan region
492 Raised
if ``fitType``
is not an allowed value.
496 The ``ampMaskedImage``
and ``overscanImage`` are modified,
with the fit
497 subtracted. Note that the ``overscanImage`` should
not be a subimage of
498 the ``ampMaskedImage``, to avoid being subtracted twice.
500 Debug plots are available
for the SPLINE fitTypes by setting the
501 `debug.display`
for `name` ==
"lsst.ip.isr.isrFunctions". These
502 plots show the scatter plot of the overscan data (collapsed along
503 the perpendicular dimension)
as a function of position on the CCD
504 (normalized between +/-1).
506 ampImage = ampMaskedImage.getImage()
510 config.fitType = fitType
514 config.numSigmaClip = collapseRej
516 config.overscanIsInt =
True
519 return overscanTask.run(ampImage, overscanImage)
523 """Apply brighter fatter correction in place for the image.
528 Exposure to have brighter-fatter correction applied. Modified
530 kernel : `numpy.ndarray`
531 Brighter-fatter kernel to apply.
533 Number of correction iterations to run.
535 Convergence threshold in terms of the sum of absolute
536 deviations between an iteration
and the previous one.
538 If
True, then the exposure values are scaled by the gain prior
540 gains : `dict` [`str`, `float`]
541 A dictionary, keyed by amplifier name, of the gains to use.
542 If gains
is None, the nominal gains
in the amplifier object are used.
547 Final difference between iterations achieved
in correction.
549 Number of iterations used to calculate correction.
553 This correction takes a kernel that has been derived
from flat
554 field images to redistribute the charge. The gradient of the
555 kernel
is the deflection field due to the accumulated charge.
557 Given the original image I(x)
and the kernel K(x) we can compute
558 the corrected image Ic(x) using the following equation:
560 Ic(x) = I(x) + 0.5*d/dx(I(x)*d/dx(
int( dy*K(x-y)*I(y))))
562 To evaluate the derivative term we expand it
as follows:
564 0.5 * ( d/dx(I(x))*d/dx(
int(dy*K(x-y)*I(y)))
565 + I(x)*d^2/dx^2(
int(dy* K(x-y)*I(y))) )
567 Because we use the measured counts instead of the incident counts
568 we apply the correction iteratively to reconstruct the original
569 counts
and the correction. We stop iterating when the summed
570 difference between the current corrected image
and the one
from
571 the previous iteration
is below the threshold. We do
not require
572 convergence because the number of iterations
is too large a
573 computational cost. How we define the threshold still needs to be
574 evaluated, the current default was shown to work reasonably well
575 on a small set of images. For more information on the method see
576 DocuShare Document-19407.
578 The edges
as defined by the kernel are
not corrected because they
579 have spurious values due to the convolution.
581 image = exposure.getMaskedImage().getImage()
584 with gainContext(exposure, image, applyGain, gains):
586 kLx = numpy.shape(kernel)[0]
587 kLy = numpy.shape(kernel)[1]
588 kernelImage = afwImage.ImageD(kLx, kLy)
589 kernelImage.getArray()[:, :] = kernel
590 tempImage = image.clone()
592 nanIndex = numpy.isnan(tempImage.getArray())
593 tempImage.getArray()[nanIndex] = 0.
595 outImage = afwImage.ImageF(image.getDimensions())
596 corr = numpy.zeros_like(image.getArray())
597 prev_image = numpy.zeros_like(image.getArray())
611 for iteration
in range(maxIter):
614 tmpArray = tempImage.getArray()
615 outArray = outImage.getArray()
617 with numpy.errstate(invalid=
"ignore", over=
"ignore"):
619 gradTmp = numpy.gradient(tmpArray[startY:endY, startX:endX])
620 gradOut = numpy.gradient(outArray[startY:endY, startX:endX])
621 first = (gradTmp[0]*gradOut[0] + gradTmp[1]*gradOut[1])[1:-1, 1:-1]
624 diffOut20 = numpy.diff(outArray, 2, 0)[startY:endY, startX + 1:endX - 1]
625 diffOut21 = numpy.diff(outArray, 2, 1)[startY + 1:endY - 1, startX:endX]
626 second = tmpArray[startY + 1:endY - 1, startX + 1:endX - 1]*(diffOut20 + diffOut21)
628 corr[startY + 1:endY - 1, startX + 1:endX - 1] = 0.5*(first + second)
630 tmpArray[:, :] = image.getArray()[:, :]
631 tmpArray[nanIndex] = 0.
632 tmpArray[startY:endY, startX:endX] += corr[startY:endY, startX:endX]
635 diff = numpy.sum(numpy.abs(prev_image - tmpArray))
639 prev_image[:, :] = tmpArray[:, :]
641 image.getArray()[startY + 1:endY - 1, startX + 1:endX - 1] += \
642 corr[startY + 1:endY - 1, startX + 1:endX - 1]
644 return diff, iteration
649 """Context manager that applies and removes gain.
654 Exposure to apply/remove gain.
656 Image to apply/remove gain.
658 If True, apply
and remove the amplifier gain.
659 gains : `dict` [`str`, `float`]
660 A dictionary, keyed by amplifier name, of the gains to use.
661 If gains
is None, the nominal gains
in the amplifier object are used.
666 Exposure
with the gain applied.
670 if gains
and apply
is True:
671 ampNames = [amp.getName()
for amp
in exp.getDetector()]
672 for ampName
in ampNames:
673 if ampName
not in gains.keys():
674 raise RuntimeError(f
"Gains provided to gain context, but no entry found for amp {ampName}")
677 ccd = exp.getDetector()
679 sim = image.Factory(image, amp.getBBox())
681 gain = gains[amp.getName()]
690 ccd = exp.getDetector()
692 sim = image.Factory(image, amp.getBBox())
694 gain = gains[amp.getName()]
701 sensorTransmission=None, atmosphereTransmission=None):
702 """Attach a TransmissionCurve to an Exposure, given separate curves for
703 different components.
708 Exposure object to modify by attaching the product of all given
709 ``TransmissionCurves`` in post-assembly trimmed detector coordinates.
710 Must have a valid ``Detector`` attached that matches the detector
711 associated
with sensorTransmission.
713 A ``TransmissionCurve`` that represents the throughput of the optics,
714 to be evaluated
in focal-plane coordinates.
716 A ``TransmissionCurve`` that represents the throughput of the filter
717 itself, to be evaluated
in focal-plane coordinates.
719 A ``TransmissionCurve`` that represents the throughput of the sensor
720 itself, to be evaluated
in post-assembly trimmed detector coordinates.
722 A ``TransmissionCurve`` that represents the throughput of the
723 atmosphere, assumed to be spatially constant.
728 The TransmissionCurve attached to the exposure.
732 All ``TransmissionCurve`` arguments are optional;
if none are provided, the
733 attached ``TransmissionCurve`` will have unit transmission everywhere.
735 combined = afwImage.TransmissionCurve.makeIdentity()
736 if atmosphereTransmission
is not None:
737 combined *= atmosphereTransmission
738 if opticsTransmission
is not None:
739 combined *= opticsTransmission
740 if filterTransmission
is not None:
741 combined *= filterTransmission
742 detector = exposure.getDetector()
743 fpToPix = detector.getTransform(fromSys=camGeom.FOCAL_PLANE,
744 toSys=camGeom.PIXELS)
745 combined = combined.transformedBy(fpToPix)
746 if sensorTransmission
is not None:
747 combined *= sensorTransmission
748 exposure.getInfo().setTransmissionCurve(combined)
752def applyGains(exposure, normalizeGains=False, ptcGains=None):
753 """Scale an exposure by the amplifier gains.
758 Exposure to process. The image is modified.
759 normalizeGains : `Bool`, optional
760 If
True, then amplifiers are scaled to force the median of
761 each amplifier to equal the median of those medians.
762 ptcGains : `dict`[`str`], optional
763 Dictionary keyed by amp name containing the PTC gains.
765 ccd = exposure.getDetector()
766 ccdImage = exposure.getMaskedImage()
770 sim = ccdImage.Factory(ccdImage, amp.getBBox())
772 sim *= ptcGains[amp.getName()]
777 medians.append(numpy.median(sim.getImage().getArray()))
780 median = numpy.median(numpy.array(medians))
781 for index, amp
in enumerate(ccd):
782 sim = ccdImage.Factory(ccdImage, amp.getBBox())
783 if medians[index] != 0.0:
784 sim *= median/medians[index]
788 """Grow the saturation trails by an amount dependent on the width of the
794 Mask which will have the saturated areas grown.
798 for i
in range(1, 6):
800 for i
in range(6, 8):
802 for i
in range(8, 10):
806 if extraGrowMax <= 0:
809 saturatedBit = mask.getPlaneBitMask(
"SAT")
811 xmin, ymin = mask.getBBox().getMin()
812 width = mask.getWidth()
814 thresh = afwDetection.Threshold(saturatedBit, afwDetection.Threshold.BITMASK)
815 fpList = afwDetection.FootprintSet(mask, thresh).getFootprints()
818 for s
in fp.getSpans():
819 x0, x1 = s.getX0(), s.getX1()
821 extraGrow = extraGrowDict.get(x1 - x0 + 1, extraGrowMax)
824 x0 -= xmin + extraGrow
825 x1 -= xmin - extraGrow
832 mask.array[y, x0:x1+1] |= saturatedBit
836 """Set all BAD areas of the chip to the average of the rest of the exposure
841 Exposure to mask. The exposure mask is modified.
842 badStatistic : `str`, optional
843 Statistic to use to generate the replacement value
from the
844 image data. Allowed values are
'MEDIAN' or 'MEANCLIP'.
848 badPixelCount : scalar
849 Number of bad pixels masked.
850 badPixelValue : scalar
851 Value substituted
for bad pixels.
856 Raised
if `badStatistic`
is not an allowed value.
858 if badStatistic ==
"MEDIAN":
859 statistic = afwMath.MEDIAN
860 elif badStatistic ==
"MEANCLIP":
861 statistic = afwMath.MEANCLIP
863 raise RuntimeError(
"Impossible method %s of bad region correction" % badStatistic)
865 mi = exposure.getMaskedImage()
867 BAD = mask.getPlaneBitMask(
"BAD")
868 INTRP = mask.getPlaneBitMask(
"INTRP")
871 sctrl.setAndMask(BAD)
874 maskArray = mask.getArray()
875 imageArray = mi.getImage().getArray()
876 badPixels = numpy.logical_and((maskArray & BAD) > 0, (maskArray & INTRP) == 0)
877 imageArray[:] = numpy.where(badPixels, value, imageArray)
879 return badPixels.sum(), value
883 """Check to see if an exposure is in a filter specified by a list.
885 The goal of this is to provide a unified filter checking interface
886 for all filter dependent stages.
892 filterList : `list` [`str`]
893 List of physical_filter names to check.
894 log : `logging.Logger`
895 Logger to handle messages.
900 True if the exposure
's filter is contained in the list.
902 if len(filterList) == 0:
904 thisFilter = exposure.getFilter()
905 if thisFilter
is None:
906 log.warning(
"No FilterLabel attached to this exposure!")
910 if thisPhysicalFilter
in filterList:
912 elif thisFilter.bandLabel
in filterList:
914 log.warning(
"Physical filter (%s) should be used instead of band %s for filter configurations"
915 " (%s)", thisPhysicalFilter, thisFilter.bandLabel, filterList)
922 """Get the physical filter label associated with the given filterLabel.
924 If ``filterLabel`` is `
None`
or there
is no physicalLabel attribute
925 associated
with the given ``filterLabel``, the returned label will be
932 physical filter label.
933 log : `logging.Logger`
934 Logger to handle messages.
938 physicalFilter : `str`
939 The value returned by the physicalLabel attribute of ``filterLabel``
if
940 it exists, otherwise set to \
"Unknown\".
942 if filterLabel
is None:
943 physicalFilter =
"Unknown"
944 log.warning(
"filterLabel is None. Setting physicalFilter to \"Unknown\".")
947 physicalFilter = filterLabel.physicalLabel
949 log.warning(
"filterLabel has no physicalLabel attribute. Setting physicalFilter to \"Unknown\".")
950 physicalFilter =
"Unknown"
951 return physicalFilter
A class to contain the data, WCS, and other information needed to describe an image of the sky.
A group of labels for a filter in an exposure or coadd.
A class to represent a 2-dimensional array of pixels.
Represent a 2-dimensional array of bitmask pixels.
A class to manipulate images, masks, and variance as a single object.
A spatially-varying transmission curve as a function of wavelength.
Parameters to control convolution.
A kernel created from an Image.
Pass parameters to a Statistics object.
Represent a Psf as a circularly symmetrical double Gaussian.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
Convolve an Image or MaskedImage with a Kernel, setting pixels of an existing output image.
Property stringToStatisticsProperty(std::string const property)
Conversion function to switch a string to a Property (see Statistics.h)
def biasCorrection(maskedImage, biasMaskedImage, trimToFit=False)
def growMasks(mask, radius=0, maskNameList=['BAD'], maskValue="BAD")
def darkCorrection(maskedImage, darkMaskedImage, expScale, darkScale, invert=False, trimToFit=False)
def saturationCorrection(maskedImage, saturation, fwhm, growFootprints=1, interpolate=True, maskName='SAT', fallbackValue=None)
def interpolateDefectList(maskedImage, defectList, fwhm, fallbackValue=None)
def illuminationCorrection(maskedImage, illumMaskedImage, illumScale, trimToFit=True)
def checkFilter(exposure, filterList, log)
def gainContext(exp, image, apply, gains=None)
def brighterFatterCorrection(exposure, kernel, maxIter, threshold, applyGain, gains=None)
def makeThresholdMask(maskedImage, threshold, growFootprints=1, maskName='SAT')
def setBadRegions(exposure, badStatistic="MEDIAN")
def applyGains(exposure, normalizeGains=False, ptcGains=None)
def getPhysicalFilter(filterLabel, log)
def trimToMatchCalibBBox(rawMaskedImage, calibMaskedImage)
def updateVariance(maskedImage, gain, readNoise)
def overscanCorrection(ampMaskedImage, overscanImage, fitType='MEDIAN', order=1, collapseRej=3.0, statControl=None, overscanIsInt=True)
def interpolateFromMask(maskedImage, fwhm, growSaturatedFootprints=1, maskNameList=['SAT'], fallbackValue=None)
def transposeMaskedImage(maskedImage)
def flatCorrection(maskedImage, flatMaskedImage, scalingType, userScale=1.0, invert=False, trimToFit=False)
def attachTransmissionCurve(exposure, opticsTransmission=None, filterTransmission=None, sensorTransmission=None, atmosphereTransmission=None)
def widenSaturationTrails(mask)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations.