def measureConstantOverscan(self, image): """Measure a constant overscan value. Parameters ---------- image : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage` Image data to measure the overscan from. Returns ------- results : `lsst.pipe.base.Struct` Overscan result with entries: - ``overscanValue``: Overscan value to subtract (`float`) - ``maskArray``: Placeholder for a mask array (`list`) - ``isTransposed``: Orientation of the overscan (`bool`) """ if self.config.fitType == 'MEDIAN': calcImage = self.integerConvert(image) else: calcImage = image fitType = afwMath.stringToStatisticsProperty(self.config.fitType) overscanValue = afwMath.makeStatistics(calcImage, fitType, self.statControl).getValue() return Struct(overscanValue=overscanValue, maskArray=None, isTransposed=False)
def collapseArrayMedian(self, maskedArray): """Collapse overscan array (and mask) to a 1-D vector of using the correct integer median of row-values. Parameters ---------- maskedArray : `numpy.ma.masked_array` Masked array of input overscan data. Returns ------- collapsed : `numpy.ma.masked_array` Single dimensional overscan data, combined with the afwMath median. """ integerMI = self.integerConvert(maskedArray) collapsed = [] fitType = afwMath.stringToStatisticsProperty('MEDIAN') for row in integerMI: newRow = row.compressed() if len(newRow) > 0: rowMedian = afwMath.makeStatistics( newRow, fitType, self.statControl).getValue() else: rowMedian = np.nan collapsed.append(rowMedian) return np.array(collapsed)
def makeThreshold(self, image, thresholdParity, factor=1.0): """Make an afw.detection.Threshold object corresponding to the task's configuration and the statistics of the given image. Parameters ---------- image : `afw.image.MaskedImage` Image to measure noise statistics from if needed. thresholdParity: `str` One of "positive" or "negative", to set the kind of fluctuations the Threshold will detect. factor : `float` Factor by which to multiply the configured detection threshold. This is useful for tweaking the detection threshold slightly. Returns ------- threshold : `lsst.afw.detection.Threshold` Detection threshold. """ parity = False if thresholdParity == "negative" else True thresholdValue = self.config.thresholdValue thresholdType = self.config.thresholdType if self.config.thresholdType == 'stdev': bad = image.getMask().getPlaneBitMask(self.config.statsMask) sctrl = afwMath.StatisticsControl() sctrl.setAndMask(bad) stats = afwMath.makeStatistics(image, afwMath.STDEVCLIP, sctrl) thresholdValue *= stats.getValue(afwMath.STDEVCLIP) thresholdType = 'value' threshold = afwDet.createThreshold(thresholdValue * factor, thresholdType, parity) threshold.setIncludeMultiplier(self.config.includeThresholdMultiplier) return threshold
def flatCorrection(maskedImage, flatMaskedImage, scalingType, userScale=1.0, invert=False, trimToFit=False): """Apply flat correction in place. Parameters ---------- maskedImage : `lsst.afw.image.MaskedImage` Image to process. The image is modified. flatMaskedImage : `lsst.afw.image.MaskedImage` Flat image of the same size as ``maskedImage`` scalingType : str Flat scale computation method. Allowed values are 'MEAN', 'MEDIAN', or 'USER'. userScale : scalar, optional Scale to use if ``scalingType``='USER'. invert : `Bool`, optional If True, unflatten an already flattened image. trimToFit : `Bool`, optional If True, raw data is symmetrically trimmed to match calibration size. Raises ------ RuntimeError Raised if ``maskedImage`` and ``flatMaskedImage`` do not have the same size or if ``scalingType`` is not an allowed value. """ if trimToFit: maskedImage = trimToMatchCalibBBox(maskedImage, flatMaskedImage) if maskedImage.getBBox(afwImage.LOCAL) != flatMaskedImage.getBBox( afwImage.LOCAL): raise RuntimeError("maskedImage bbox %s != flatMaskedImage bbox %s" % (maskedImage.getBBox(afwImage.LOCAL), flatMaskedImage.getBBox(afwImage.LOCAL))) # Figure out scale from the data # Ideally the flats are normalized by the calibration product pipeline, but this allows some flexibility # in the case that the flat is created by some other mechanism. if scalingType in ('MEAN', 'MEDIAN'): scalingType = afwMath.stringToStatisticsProperty(scalingType) flatScale = afwMath.makeStatistics(flatMaskedImage.image, scalingType).getValue() elif scalingType == 'USER': flatScale = userScale else: raise RuntimeError('%s : %s not implemented' % ("flatCorrection", scalingType)) if not invert: maskedImage.scaledDivides(1.0 / flatScale, flatMaskedImage) else: maskedImage.scaledMultiplies(1.0 / flatScale, flatMaskedImage)
def setBadRegions(exposure, badStatistic="MEDIAN"): """Set all BAD areas of the chip to the average of the rest of the exposure Parameters ---------- exposure : `lsst.afw.image.Exposure` Exposure to mask. The exposure mask is modified. badStatistic : `str`, optional Statistic to use to generate the replacement value from the image data. Allowed values are 'MEDIAN' or 'MEANCLIP'. Returns ------- badPixelCount : scalar Number of bad pixels masked. badPixelValue : scalar Value substituted for bad pixels. Raises ------ RuntimeError Raised if `badStatistic` is not an allowed value. """ if badStatistic == "MEDIAN": statistic = afwMath.MEDIAN elif badStatistic == "MEANCLIP": statistic = afwMath.MEANCLIP else: raise RuntimeError("Impossible method %s of bad region correction" % badStatistic) mi = exposure.getMaskedImage() mask = mi.getMask() BAD = mask.getPlaneBitMask("BAD") INTRP = mask.getPlaneBitMask("INTRP") sctrl = afwMath.StatisticsControl() sctrl.setAndMask(BAD) value = afwMath.makeStatistics(mi, statistic, sctrl).getValue() maskArray = mask.getArray() imageArray = mi.getImage().getArray() badPixels = numpy.logical_and((maskArray & BAD) > 0, (maskArray & INTRP) == 0) imageArray[:] = numpy.where(badPixels, value, imageArray) return badPixels.sum(), value
def _addStats(self, exposure, background, statsKeys=None): """Add statistics about the background to the exposure's metadata @param[in,out] exposure exposure whose background was subtracted @param[in,out] background background model (an lsst.afw.math.BackgroundList) @param[in] statsKeys key names used to store the mean and variance of the background in the exposure's metadata (a pair of strings); if None then use ("BGMEAN", "BGVAR"); ignored if stats is false """ netBgImg = background.getImage() if statsKeys is None: statsKeys = ("BGMEAN", "BGVAR") mnkey, varkey = statsKeys meta = exposure.getMetadata() s = afwMath.makeStatistics(netBgImg, afwMath.MEAN | afwMath.VARIANCE) bgmean = s.getValue(afwMath.MEAN) bgvar = s.getValue(afwMath.VARIANCE) meta.addDouble(mnkey, bgmean) meta.addDouble(varkey, bgvar)
def interpolateDefectList(maskedImage, defectList, fwhm, fallbackValue=None): """Interpolate over defects specified in a defect list. Parameters ---------- maskedImage : `lsst.afw.image.MaskedImage` Image to process. defectList : `lsst.meas.algorithms.Defects` List of defects to interpolate over. fwhm : scalar FWHM of double Gaussian smoothing kernel. fallbackValue : scalar, optional Fallback value if an interpolated value cannot be determined. If None, then the clipped mean of the image is used. """ psf = createPsf(fwhm) if fallbackValue is None: fallbackValue = afwMath.makeStatistics(maskedImage.getImage(), afwMath.MEANCLIP).getValue() if 'INTRP' not in maskedImage.getMask().getMaskPlaneDict(): maskedImage.getMask().addMaskPlane('INTRP') measAlg.interpolateOverDefects(maskedImage, psf, defectList, fallbackValue, True) return maskedImage