23 from __future__
import absolute_import, division, print_function
25 from contextlib
import contextmanager
35 background = ConfigurableField(target=SubtractBackgroundTask, doc=
"Background subtraction")
36 maskPlanes = ListField(
38 default=[
"DETECTED",
"DETECTED_NEGATIVE",
"BAD",
"SAT",
"NO_DATA",
"INTRP"],
39 doc=
"Mask planes for pixels to ignore when scaling variance",
41 limit = Field(dtype=float, default=10.0, doc=
"Maximum variance scaling value to permit")
46 self.
background.undersampleStyle =
"REDUCE_INTERP_ORDER" 47 self.
background.ignoredPixelMask = [
"DETECTED",
"DETECTED_NEGATIVE",
"BAD",
"SAT",
"NO_DATA",
"INTRP"]
51 """Scale the variance in a MaskedImage 53 The variance plane in a convolved or warped image (or a coadd derived 54 from warped images) does not accurately reflect the noise properties of 55 the image because variance has been lost to covariance. This Task 56 attempts to correct for this by scaling the variance plane to match 57 the observed variance in the image. This is not perfect (because we're 58 not tracking the covariance) but it's simple and is often good enough. 60 ConfigClass = ScaleVarianceConfig
61 _DefaultName =
"scaleVariance" 64 Task.__init__(self, *args, **kwargs)
65 self.makeSubtask(
"background")
69 """Context manager for subtracting the background 71 We need to subtract the background so that the entire image 72 (apart from objects, which should be clipped) will have the 73 image/sqrt(variance) distributed about zero. 75 This context manager subtracts the background, and ensures it 80 maskedImage : `lsst.afw.image.MaskedImage` 81 Image+mask+variance to have background subtracted and restored. 85 context : context manager 86 Context manager that ensure the background is restored. 88 bg = self.background.fitBackground(maskedImage)
89 bgImage = bg.getImageF()
90 maskedImage -= bgImage
94 maskedImage += bgImage
96 def run(self, maskedImage):
97 """Rescale the variance in a maskedImage 101 maskedImage : `lsst.afw.image.MaskedImage` 102 Image for which to determine the variance rescaling factor. 107 Variance rescaling factor. 112 If the estimated variance rescaling factor exceeds the 117 if factor > self.config.limit:
118 self.log.warn(
"Pixel-based variance rescaling factor (%f) exceeds configured limit (%f); " 119 "trying image-based method", factor, self.config.limit)
121 if factor > self.config.limit:
122 raise RuntimeError(
"Variance rescaling factor (%f) exceeds configured limit (%f)" %
123 (factor, self.config.limit))
124 self.log.info(
"Renormalizing variance by %f" % (factor,))
125 maskedImage.variance *= factor
129 """Determine the variance rescaling factor from pixel statistics 131 We calculate SNR = image/sqrt(variance), and the distribution 132 for most of the background-subtracted image should have a standard 133 deviation of unity. The variance rescaling factor is the factor that 134 brings that distribution to have unit standard deviation. 136 This may not work well if the image has a lot of structure in it, as 137 the assumptions are violated. In that case, use an alternate 142 maskedImage : `lsst.afw.image.MaskedImage` 143 Image for which to determine the variance rescaling factor. 148 Variance rescaling factor. 150 variance = maskedImage.variance
151 snr = maskedImage.image.array/np.sqrt(variance.array)
152 maskVal = maskedImage.mask.getPlaneBitMask(self.config.maskPlanes)
153 isGood = (maskedImage.mask.array & maskVal) == 0
155 q1, q3 = np.percentile(snr[isGood], (25, 75))
156 stdev = 0.74*(q3 - q1)
160 """Determine the variance rescaling factor from image statistics 162 We calculate average(SNR) = stdev(image)/median(variance), and 163 the value should be unity. The variance rescaling factor is the 164 factor that brings this value to unity. 166 This may not work well if the pixels from which we measure the 167 standard deviation of the image are not effectively the same pixels 168 from which we measure the median of the variance. In that case, use 173 maskedImage : `lsst.afw.image.MaskedImage` 174 Image for which to determine the variance rescaling factor. 179 Variance rescaling factor. 181 isGood = (maskedImage.mask.array & maskVal) == 0
183 q1, q3 = np.percentile(maskedImage.image.array[isGood], (25, 75))
184 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)