def testSaturation(self): saturation = 1000 bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Point2I(19, 19)) maskedImage = afwImage.MaskedImageF(bbox) maskedImage.set(100, 0x0, 1) exposure = afwImage.ExposureF(maskedImage, None) bbox = afwGeom.Box2I(afwGeom.Point2I(9, 5), afwGeom.Point2I(9, 15)) submi = afwImage.MaskedImageF(maskedImage, bbox, afwImage.PARENT, False) submi.set(saturation, 0x0, 1) ipIsr.makeThresholdMask( maskedImage=maskedImage, threshold=saturation, growFootprints=0, maskName='SAT', ) ipIsr.interpolateFromMask( maskedImage=maskedImage, fwhm=5.0, growFootprints=1, maskName='SAT', ) mask = maskedImage.getMask() bitmaskBad = mask.getPlaneBitMask('BAD') bitmaskSat = mask.getPlaneBitMask('SAT') bitmaskInterp = mask.getPlaneBitMask('INTRP') height = maskedImage.getHeight() width = maskedImage.getWidth() for j in range(height): for i in range(width): # Grown saturation mask; one around the mask at 9 if i >= 8 and i <= 10: if (i, j) in [(8, 4), (8, 16), (10, 4), (10, 16)]: #Should not be saturated or interpolated at all self.assertEqual(mask.get(i, j) & bitmaskInterp, 0) self.assertEqual(mask.get(i, j) & bitmaskSat, 0) elif (j > 4 and j < 16) and (i == 8 or i == 10): # Not saturated but interpolated over self.assertEqual( mask.get(i, j) & bitmaskInterp, bitmaskInterp) elif (j == 4 or j == 16): # Interpolated over; bottom/top self.assertEqual( mask.get(i, j) & bitmaskInterp, bitmaskInterp) elif (j > 4 and j < 16 and i == 9): # Both saturated and interpolated over; guts of it self.assertEqual( mask.get(i, j) & bitmaskInterp, bitmaskInterp) self.assertEqual( mask.get(i, j) & bitmaskSat, bitmaskSat) else: # Neither; above or below the mask self.assertEqual(mask.get(i, j), 0) else: self.assertEqual(mask.get(i, j), 0)
def run(self, exposure): for maskPlane in self.config.maskPlanesToInterpolate: interpolateFromMask(exposure.maskedImage, fwhm=self.config.fwhm, maskName=maskPlane) result = Struct(exposure=exposure) return result
def testSaturation(self): """Test saturation threshold masking and interpolation. The test image used here is a simulated 20x20 square with a 10-pixel long defect in the y-direction. """ saturation = 1000 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Point2I(19, 19)) maskedImage = afwImage.MaskedImageF(bbox) maskedImage.set(100, 0x0, 1) bbox = lsst.geom.Box2I(lsst.geom.Point2I(9, 5), lsst.geom.Point2I(9, 15)) submi = afwImage.MaskedImageF(maskedImage, bbox, afwImage.PARENT, False) submi.set(saturation, 0x0, 1) ipIsr.makeThresholdMask( maskedImage=maskedImage, threshold=saturation, growFootprints=0, maskName='SAT', ) ipIsr.interpolateFromMask( maskedImage=maskedImage, fwhm=5.0, growSaturatedFootprints=1, maskNameList=['SAT'], ) mask = maskedImage.getMask() bitmaskSat = mask.getPlaneBitMask('SAT') bitmaskInterp = mask.getPlaneBitMask('INTRP') height = maskedImage.getHeight() width = maskedImage.getWidth() for j in range(height): for i in range(width): # Grown saturation mask; one around the mask at 9 if i >= 8 and i <= 10: if (i, j) in [(8, 4), (8, 16), (10, 4), (10, 16)]: # Should not be saturated or interpolated at all self.assertEqual(mask[i, j, afwImage.LOCAL] & bitmaskInterp, 0) self.assertEqual(mask[i, j, afwImage.LOCAL] & bitmaskSat, 0) elif (j > 4 and j < 16) and (i == 8 or i == 10): # Not saturated but interpolated over self.assertEqual(mask[i, j, afwImage.LOCAL] & bitmaskInterp, bitmaskInterp) elif (j == 4 or j == 16): # Interpolated over; bottom/top self.assertEqual(mask[i, j, afwImage.LOCAL] & bitmaskInterp, bitmaskInterp) elif (j > 4 and j < 16 and i == 9): # Both saturated and interpolated over; guts of it self.assertEqual(mask[i, j, afwImage.LOCAL] & bitmaskInterp, bitmaskInterp) self.assertEqual(mask[i, j, afwImage.LOCAL] & bitmaskSat, bitmaskSat) else: # Neither; above or below the mask self.assertEqual(mask[i, j, afwImage.LOCAL], 0) else: self.assertEqual(mask[i, j, afwImage.LOCAL], 0)
def applyInterpolateFromMask(self, maskedImage, fwhm=0.001): for maskName in self._added_mask_types: try: ipIsr.interpolateFromMask(maskedImage, fwhm=fwhm, maskName=maskName) except pexExcept.InvalidParameterError: pass
def testSaturation(self): saturation = 1000 bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Point2I(19,19)) maskedImage = afwImage.MaskedImageF(bbox) maskedImage.set(100, 0x0, 1) exposure = afwImage.ExposureF(maskedImage, None) bbox = afwGeom.Box2I(afwGeom.Point2I(9,5), afwGeom.Point2I(9,15)) submi = afwImage.MaskedImageF(maskedImage, bbox, afwImage.PARENT, False) submi.set(saturation, 0x0, 1) ipIsr.makeThresholdMask( maskedImage = maskedImage, threshold = saturation, growFootprints = 0, maskName = 'SAT', ) ipIsr.interpolateFromMask( maskedImage = maskedImage, fwhm = 5.0, growFootprints = 1, maskName = 'SAT', ) mask = maskedImage.getMask() bitmaskBad = mask.getPlaneBitMask('BAD') bitmaskSat = mask.getPlaneBitMask('SAT') bitmaskInterp = mask.getPlaneBitMask('INTRP') height = maskedImage.getHeight() width = maskedImage.getWidth() for j in range(height): for i in range(width): # Grown saturation mask; one around the mask at 9 if i >= 8 and i <= 10: if (i,j) in [(8,4),(8,16),(10,4),(10,16)]: #Should not be saturated or interpolated at all self.assertEqual(mask.get(i,j) & bitmaskInterp, 0) self.assertEqual(mask.get(i,j) & bitmaskSat, 0) elif (j >4 and j < 16) and (i == 8 or i == 10): # Not saturated but interpolated over self.assertEqual(mask.get(i,j) & bitmaskInterp, bitmaskInterp) elif (j == 4 or j == 16): # Interpolated over; bottom/top self.assertEqual(mask.get(i,j) & bitmaskInterp, bitmaskInterp) elif (j > 4 and j < 16 and i == 9): # Both saturated and interpolated over; guts of it self.assertEqual(mask.get(i,j) & bitmaskInterp, bitmaskInterp) self.assertEqual(mask.get(i,j) & bitmaskSat, bitmaskSat) else: # Neither; above or below the mask self.assertEqual(mask.get(i,j), 0) else: self.assertEqual(mask.get(i,j), 0)
def applyInterpolateFromMask(self, maskedImage, fwhm=0.001): try: for maskName in self._added_mask_types: try: ipIsr.interpolateFromMask(maskedImage, fwhm=fwhm, maskName=maskName) except pexExcept.InvalidParameterError: pass except TypeError: # interface change in ip_isr/isrFunctions.py v18.1.0: ipIsr.interpolateFromMask(maskedImage, fwhm=fwhm, maskNameList=self._added_mask_types)
def runDataRef(self, sensorRef): r"""Load the post instrument signature removal image \param[in] sensorRef sensor-level butler data reference \return postIsrExposure exposure to be passed to processCcdExposure """ inputExposure = sensorRef.get("eimage", immediate=True) # eimages are int, but computation needs to be done on floating point values inputExposure = inputExposure.convertF() if self.config.doAddNoise: self.addNoise(inputExposure) if self.config.doSetVariance: self.setVariance(inputExposure) if self.config.maskEdgeBorder > 0: self.maskEdges(inputExposure) # eimages are transposed relative to the read direction. # Transpose the image to do interpolation in the serial direction mi = inputExposure.getMaskedImage() mi = isr.transposeMaskedImage(mi) # We may need to ingest the results of the processing and # ingestProcessed.py expects some specific header cards. # Set the header cards to values appropriate for an image # that has not been read out. md = inputExposure.getMetadata() md.add('RDNOISE', 0.) md.add('SATURATE', self.config.sat_val) md.add('GAINEFF', 1.) # Mask saturation isr.makeThresholdMask( maskedImage=mi, threshold=self.config.sat_val, growFootprints=0, maskName='SAT') # Interpolate isr.interpolateFromMask( maskedImage=mi, fwhm=self.config.interp_size, growFootprints=0, maskName='SAT', ) inputExposure.setMaskedImage(isr.transposeMaskedImage(mi)) return pipeBase.Struct(exposure=inputExposure)
def runDataRef(self, sensorRef): """Load the post instrument signature removal image \param[in] sensorRef sensor-level butler data reference \return postIsrExposure exposure to be passed to processCcdExposure """ inputExposure = sensorRef.get("eimage", immediate=True) # eimages are int, but computation needs to be done on floating point values inputExposure = inputExposure.convertF() if self.config.doAddNoise: self.addNoise(inputExposure) if self.config.doSetVariance: self.setVariance(inputExposure) if self.config.maskEdgeBorder > 0: self.maskEdges(inputExposure) # eimages are transposed relative to the read direction. # Transpose the image to do interpolation in the serial direction mi = inputExposure.getMaskedImage() mi = isr.transposeMaskedImage(mi) # We may need to ingest the results of the processing and # ingestProcessed.py expects some specific header cards. # Set the header cards to values appropriate for an image # that has not been read out. md = inputExposure.getMetadata() md.add('RDNOISE', 0.) md.add('SATURATE', self.config.sat_val) md.add('GAINEFF', 1.) # Mask saturation isr.makeThresholdMask( maskedImage=mi, threshold=self.config.sat_val, growFootprints=0, maskName='SAT') # Interpolate isr.interpolateFromMask( maskedImage=mi, fwhm=self.config.interp_size, growFootprints=self.config.growSaturationFootprintSize, maskName='SAT', ) inputExposure.setMaskedImage(isr.transposeMaskedImage(mi)) return pipeBase.Struct(exposure=inputExposure)
def test_interpolateFromMask(self): """Expect number of interpolated pixels to be non-zero. """ ipIsr.makeThresholdMask(self.mi, 200, growFootprints=2, maskName='SAT') for growFootprints in range(0, 3): interpMaskedImage = ipIsr.interpolateFromMask(self.mi, 2.0, growSaturatedFootprints=growFootprints, maskNameList=['SAT']) numBit = countMaskedPixels(interpMaskedImage, "INTRP") self.assertEqual(numBit, 40800, msg=f"interpolateFromMask with growFootprints={growFootprints}")
def test_interpolateFromMask(self): """Expect number of interpolated pixels to be non-zero. """ ipIsr.makeThresholdMask(self.mi, 200, growFootprints=2, maskName='SAT') for growFootprints in range(0, 3): interpMaskedImage = ipIsr.interpolateFromMask( self.mi, 2.0, growSaturatedFootprints=growFootprints, maskNameList=['SAT']) numBit = countMaskedPixels(interpMaskedImage, "INTRP") self.assertEqual( numBit, 40800, msg=f"interpolateFromMask with growFootprints={growFootprints}" )
def testSaturation(self): """Test saturation threshold masking and interpolation. The test image used here is a simulated 20x20 square with a 10-pixel long defect in the y-direction. """ saturation = 1000 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Point2I(19, 19)) maskedImage = afwImage.MaskedImageF(bbox) maskedImage.set(100, 0x0, 1) bbox = lsst.geom.Box2I(lsst.geom.Point2I(9, 5), lsst.geom.Point2I(9, 15)) submi = afwImage.MaskedImageF(maskedImage, bbox, afwImage.PARENT, False) submi.set(saturation, 0x0, 1) ipIsr.makeThresholdMask( maskedImage=maskedImage, threshold=saturation, growFootprints=0, maskName='SAT', ) ipIsr.interpolateFromMask( maskedImage=maskedImage, fwhm=5.0, growSaturatedFootprints=1, maskNameList=['SAT'], ) mask = maskedImage.getMask() bitmaskSat = mask.getPlaneBitMask('SAT') bitmaskInterp = mask.getPlaneBitMask('INTRP') height = maskedImage.getHeight() width = maskedImage.getWidth() for j in range(height): for i in range(width): # Grown saturation mask; one around the mask at 9 if i >= 8 and i <= 10: if (i, j) in [(8, 4), (8, 16), (10, 4), (10, 16)]: # Should not be saturated or interpolated at all self.assertEqual( mask[i, j, afwImage.LOCAL] & bitmaskInterp, 0) self.assertEqual( mask[i, j, afwImage.LOCAL] & bitmaskSat, 0) elif (j > 4 and j < 16) and (i == 8 or i == 10): # Not saturated but interpolated over self.assertEqual( mask[i, j, afwImage.LOCAL] & bitmaskInterp, bitmaskInterp) elif (j == 4 or j == 16): # Interpolated over; bottom/top self.assertEqual( mask[i, j, afwImage.LOCAL] & bitmaskInterp, bitmaskInterp) elif (j > 4 and j < 16 and i == 9): # Both saturated and interpolated over; guts of it self.assertEqual( mask[i, j, afwImage.LOCAL] & bitmaskInterp, bitmaskInterp) self.assertEqual( mask[i, j, afwImage.LOCAL] & bitmaskSat, bitmaskSat) else: # Neither; above or below the mask self.assertEqual(mask[i, j, afwImage.LOCAL], 0) else: self.assertEqual(mask[i, j, afwImage.LOCAL], 0)