22 from contextlib
import contextmanager
32 background = ConfigurableField(target=SubtractBackgroundTask, doc=
"Background subtraction")
33 maskPlanes = ListField(
35 default=[
"DETECTED",
"DETECTED_NEGATIVE",
"BAD",
"SAT",
"NO_DATA",
"INTRP"],
36 doc=
"Mask planes for pixels to ignore when scaling variance",
38 limit = Field(dtype=float, default=10.0, doc=
"Maximum variance scaling value to permit")
43 self.
background.undersampleStyle =
"REDUCE_INTERP_ORDER" 44 self.
background.ignoredPixelMask = [
"DETECTED",
"DETECTED_NEGATIVE",
"BAD",
"SAT",
"NO_DATA",
"INTRP"]
48 """Scale the variance in a MaskedImage 50 The variance plane in a convolved or warped image (or a coadd derived 51 from warped images) does not accurately reflect the noise properties of 52 the image because variance has been lost to covariance. This Task 53 attempts to correct for this by scaling the variance plane to match 54 the observed variance in the image. This is not perfect (because we're 55 not tracking the covariance) but it's simple and is often good enough. 57 ConfigClass = ScaleVarianceConfig
58 _DefaultName =
"scaleVariance" 61 Task.__init__(self, *args, **kwargs)
62 self.makeSubtask(
"background")
66 """Context manager for subtracting the background 68 We need to subtract the background so that the entire image 69 (apart from objects, which should be clipped) will have the 70 image/sqrt(variance) distributed about zero. 72 This context manager subtracts the background, and ensures it 77 maskedImage : `lsst.afw.image.MaskedImage` 78 Image+mask+variance to have background subtracted and restored. 82 context : context manager 83 Context manager that ensure the background is restored. 85 bg = self.background.fitBackground(maskedImage)
86 bgImage = bg.getImageF()
87 maskedImage -= bgImage
91 maskedImage += bgImage
93 def run(self, maskedImage):
94 """Rescale the variance in a maskedImage 98 maskedImage : `lsst.afw.image.MaskedImage` 99 Image for which to determine the variance rescaling factor. 104 Variance rescaling factor. 109 If the estimated variance rescaling factor exceeds the 114 if np.isnan(factor)
or factor > self.config.limit:
115 self.log.warn(
"Pixel-based variance rescaling factor (%f) exceeds configured limit (%f); " 116 "trying image-based method", factor, self.config.limit)
118 if np.isnan(factor)
or factor > self.config.limit:
119 raise RuntimeError(
"Variance rescaling factor (%f) exceeds configured limit (%f)" %
120 (factor, self.config.limit))
121 self.log.info(
"Renormalizing variance by %f" % (factor,))
122 maskedImage.variance *= factor
126 """Determine the variance rescaling factor from pixel statistics 128 We calculate SNR = image/sqrt(variance), and the distribution 129 for most of the background-subtracted image should have a standard 130 deviation of unity. The variance rescaling factor is the factor that 131 brings that distribution to have unit standard deviation. 133 This may not work well if the image has a lot of structure in it, as 134 the assumptions are violated. In that case, use an alternate 139 maskedImage : `lsst.afw.image.MaskedImage` 140 Image for which to determine the variance rescaling factor. 145 Variance rescaling factor. 147 variance = maskedImage.variance
148 snr = maskedImage.image.array/np.sqrt(variance.array)
149 maskVal = maskedImage.mask.getPlaneBitMask(self.config.maskPlanes)
150 isGood = ((maskedImage.mask.array & maskVal) == 0) & (maskedImage.variance.array > 0)
152 q1, q3 = np.percentile(snr[isGood], (25, 75))
153 stdev = 0.74*(q3 - q1)
157 """Determine the variance rescaling factor from image statistics 159 We calculate average(SNR) = stdev(image)/median(variance), and 160 the value should be unity. The variance rescaling factor is the 161 factor that brings this value to unity. 163 This may not work well if the pixels from which we measure the 164 standard deviation of the image are not effectively the same pixels 165 from which we measure the median of the variance. In that case, use 170 maskedImage : `lsst.afw.image.MaskedImage` 171 Image for which to determine the variance rescaling factor. 176 Variance rescaling factor. 178 maskVal = maskedImage.mask.getPlaneBitMask(self.config.maskPlanes)
179 isGood = ((maskedImage.mask.array & maskVal) == 0) & (maskedImage.variance.array > 0)
181 q1, q3 = np.percentile(maskedImage.image.array[isGood], (25, 75))
182 ratio = 0.74*(q3 - q1)/np.sqrt(np.median(maskedImage.variance.array[isGood]))
def run(self, maskedImage)
def __init__(self, args, kwargs)
def subtractedBackground(self, maskedImage)
def pixelBased(self, maskedImage)
def imageBased(self, maskedImage)