22 from contextlib
import contextmanager
34 default=[
"DETECTED",
"DETECTED_NEGATIVE",
"BAD",
"SAT",
"NO_DATA",
"INTRP"],
35 doc=
"Mask planes for pixels to ignore when scaling variance",
37 limit =
Field(dtype=float, default=10.0, doc=
"Maximum variance scaling value to permit")
42 self.
background.undersampleStyle =
"REDUCE_INTERP_ORDER" 43 self.
background.ignoredPixelMask = [
"DETECTED",
"DETECTED_NEGATIVE",
"BAD",
"SAT",
"NO_DATA",
"INTRP"]
47 """Scale the variance in a MaskedImage 49 The variance plane in a convolved or warped image (or a coadd derived 50 from warped images) does not accurately reflect the noise properties of 51 the image because variance has been lost to covariance. This Task 52 attempts to correct for this by scaling the variance plane to match 53 the observed variance in the image. This is not perfect (because we're 54 not tracking the covariance) but it's simple and is often good enough. 56 ConfigClass = ScaleVarianceConfig
57 _DefaultName =
"scaleVariance" 60 Task.__init__(self, *args, **kwargs)
65 """Context manager for subtracting the background 67 We need to subtract the background so that the entire image 68 (apart from objects, which should be clipped) will have the 69 image/sqrt(variance) distributed about zero. 71 This context manager subtracts the background, and ensures it 76 maskedImage : `lsst.afw.image.MaskedImage` 77 Image+mask+variance to have background subtracted and restored. 81 context : context manager 82 Context manager that ensure the background is restored. 84 bg = self.background.fitBackground(maskedImage)
85 bgImage = bg.getImageF()
86 maskedImage -= bgImage
90 maskedImage += bgImage
92 def run(self, maskedImage):
93 """Rescale the variance in a maskedImage 97 maskedImage : `lsst.afw.image.MaskedImage` 98 Image for which to determine the variance rescaling factor. 103 Variance rescaling factor. 108 If the estimated variance rescaling factor exceeds the 113 if np.isnan(factor)
or factor > self.
config.limit:
114 self.
log.
warn(
"Pixel-based variance rescaling factor (%f) exceeds configured limit (%f); " 115 "trying image-based method", factor, self.
config.limit)
117 if np.isnan(factor)
or factor > self.
config.limit:
118 raise RuntimeError(
"Variance rescaling factor (%f) exceeds configured limit (%f)" %
119 (factor, self.
config.limit))
120 self.
log.
info(
"Renormalizing variance by %f" % (factor,))
121 maskedImage.variance *= factor
125 """Determine the variance rescaling factor from pixel statistics 127 We calculate SNR = image/sqrt(variance), and the distribution 128 for most of the background-subtracted image should have a standard 129 deviation of unity. The variance rescaling factor is the factor that 130 brings that distribution to have unit standard deviation. 132 This may not work well if the image has a lot of structure in it, as 133 the assumptions are violated. In that case, use an alternate 138 maskedImage : `lsst.afw.image.MaskedImage` 139 Image for which to determine the variance rescaling factor. 144 Variance rescaling factor. 146 variance = maskedImage.variance
147 snr = maskedImage.image.array/np.sqrt(variance.array)
148 maskVal = maskedImage.mask.getPlaneBitMask(self.
config.maskPlanes)
149 isGood = ((maskedImage.mask.array & maskVal) == 0) & (maskedImage.variance.array > 0)
152 q1, q3 = np.percentile(snr[isGood], (25, 75))
159 stdev = 0.74*(q3 - q1)
163 """Determine the variance rescaling factor from image statistics 165 We calculate average(SNR) = stdev(image)/median(variance), and 166 the value should be unity. The variance rescaling factor is the 167 factor that brings this value to unity. 169 This may not work well if the pixels from which we measure the 170 standard deviation of the image are not effectively the same pixels 171 from which we measure the median of the variance. In that case, use 176 maskedImage : `lsst.afw.image.MaskedImage` 177 Image for which to determine the variance rescaling factor. 182 Variance rescaling factor. 184 maskVal = maskedImage.mask.getPlaneBitMask(self.
config.maskPlanes)
185 isGood = ((maskedImage.mask.array & maskVal) == 0) & (maskedImage.variance.array > 0)
187 q1, q3 = np.percentile(maskedImage.image.array[isGood], (25, 75))
188 ratio = 0.74*(q3 - q1)/np.sqrt(np.median(maskedImage.variance.array[isGood]))
def makeSubtask(self, name, keyArgs)
def run(self, maskedImage)
def __init__(self, args, kwargs)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
def subtractedBackground(self, maskedImage)
def pixelBased(self, maskedImage)
def imageBased(self, maskedImage)