def setUp(self): self.FWHM = 5 self.psf = algorithms.DoubleGaussianPsf( 15, 15, self.FWHM / (2 * math.sqrt(2 * math.log(2)))) maskedImageFile = os.path.join(afwdataDir, "CFHT", "D4", "cal-53535-i-797722_1.fits") self.mi = afwImage.MaskedImageF(maskedImageFile) if False: # use sub-image? self.mi = self.mi.Factory( self.mi, afwImage.BBox(afwImage.PointI(760, 20), 256, 256)) self.mi.getMask().addMaskPlane("INTERP") self.badPixels = testUtils.makeDefectList()
def testDetection(self): """Test CR detection.""" # # Subtract background # bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE) bctrl.setNxSample(int(self.mi.getWidth() / 256) + 1) bctrl.setNySample(int(self.mi.getHeight() / 256) + 1) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) im = self.mi.getImage() try: backobj = afwMath.makeBackground(im, bctrl) except Exception as e: print(e, file=sys.stderr) bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) backobj = afwMath.makeBackground(im, bctrl) im -= backobj.getImageF() if display: frame = 0 disp = afwDisplay.Display(frame=frame) disp.mtv(self.mi, title=self._testMethodName + ": Raw") # raw frame if self.mi.getWidth() > 256: disp.pan(944 - self.mi.getX0(), 260 - self.mi.getY0()) # # Mask known bad pixels # badPixels = testUtils.makeDefectList() algorithms.interpolateOverDefects(self.mi, self.psf, badPixels) stats = afwMath.makeStatistics(self.mi.getImage(), afwMath.MEANCLIP | afwMath.STDEVCLIP) background = stats.getValue(afwMath.MEANCLIP) crConfig = algorithms.FindCosmicRaysConfig() crs = algorithms.findCosmicRays(self.mi, self.psf, background, pexConfig.makePropertySet(crConfig)) if display: frame += 1 disp = afwDisplay.Display(frame=frame) disp.mtv(self.mi, title=self._testMethodName + ": CRs removed") if self.mi.getWidth() > 256: disp.pan(944 - self.mi.getX0(), 260 - self.mi.getY0()) print("Detected %d CRs" % len(crs)) if display and False: for cr in crs: bbox = cr.getBBox() bbox.shift( lsst.geom.ExtentI(-self.mi.getX0(), -self.mi.getY0())) disp.line([(bbox.getMinX() - 0.5, bbox.getMinY() - 0.5), (bbox.getMaxX() + 0.5, bbox.getMinY() - 0.5), (bbox.getMaxX() + 0.5, bbox.getMaxY() + 0.5), (bbox.getMinX() - 0.5, bbox.getMaxY() + 0.5), (bbox.getMinX() - 0.5, bbox.getMinY() - 0.5)]) if self.nCR is not None: self.assertEqual(len(crs), self.nCR)
def testDetection(self): """Test object detection""" # # Fix defects # # Mask known bad pixels # badPixels = testUtils.makeDefectList() algorithms.interpolateOverDefects(self.mi, self.psf, badPixels) # # Subtract background # bgGridSize = 64 # was 256 ... but that gives only one region and the spline breaks bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE) bctrl.setNxSample(int(self.mi.getWidth() / bgGridSize) + 1) bctrl.setNySample(int(self.mi.getHeight() / bgGridSize) + 1) backobj = afwMath.makeBackground(self.mi.getImage(), bctrl) self.mi.getImage()[:] -= backobj.getImageF() # # Remove CRs # crConfig = algorithms.FindCosmicRaysConfig() algorithms.findCosmicRays(self.mi, self.psf, 0, pexConfig.makePropertySet(crConfig)) # # We do a pretty good job of interpolating, so don't propagagate the convolved CR/INTRP bits # (we'll keep them for the original CR/INTRP pixels) # savedMask = self.mi.getMask().Factory(self.mi.getMask(), True) saveBits = savedMask.getPlaneBitMask("CR") | \ savedMask.getPlaneBitMask("BAD") | \ savedMask.getPlaneBitMask("INTRP") # Bits to not convolve savedMask &= saveBits msk = self.mi.getMask() msk &= ~saveBits # Clear the saved bits del msk # # Smooth image # psf = algorithms.DoubleGaussianPsf( 15, 15, self.FWHM / (2 * math.sqrt(2 * math.log(2)))) cnvImage = self.mi.Factory(self.mi.getBBox()) kernel = psf.getKernel() afwMath.convolve(cnvImage, self.mi, kernel, afwMath.ConvolutionControl()) msk = cnvImage.getMask() msk |= savedMask # restore the saved bits del msk threshold = afwDetection.Threshold(3, afwDetection.Threshold.STDEV) # # Only search the part of the frame that was PSF-smoothed # llc = lsst.geom.PointI(psf.getKernel().getWidth() // 2, psf.getKernel().getHeight() // 2) urc = lsst.geom.PointI(cnvImage.getWidth() - llc[0] - 1, cnvImage.getHeight() - llc[1] - 1) middle = cnvImage.Factory(cnvImage, lsst.geom.BoxI(llc, urc), afwImage.LOCAL) ds = afwDetection.FootprintSet(middle, threshold, "DETECTED") del middle # # Reinstate the saved (e.g. BAD) (and also the DETECTED | EDGE) bits in the unsmoothed image # savedMask[:] = cnvImage.getMask() msk = self.mi.getMask() msk |= savedMask del msk del savedMask if display: disp = afwDisplay.Display(frame=2) disp.mtv(self.mi, title=self._testMethodName + ": image") afwDisplay.Display(frame=3).mtv(cnvImage, title=self._testMethodName + ": cnvImage") # # Time to actually measure # schema = afwTable.SourceTable.makeMinimalSchema() sfm_config = measBase.SingleFrameMeasurementConfig() sfm_config.plugins = [ "base_SdssCentroid", "base_CircularApertureFlux", "base_PsfFlux", "base_SdssShape", "base_GaussianFlux", "base_PixelFlags" ] sfm_config.slots.centroid = "base_SdssCentroid" sfm_config.slots.shape = "base_SdssShape" sfm_config.slots.psfFlux = "base_PsfFlux" sfm_config.slots.gaussianFlux = None sfm_config.slots.apFlux = "base_CircularApertureFlux_3_0" sfm_config.slots.modelFlux = "base_GaussianFlux" sfm_config.slots.calibFlux = None sfm_config.plugins["base_SdssShape"].maxShift = 10.0 sfm_config.plugins["base_CircularApertureFlux"].radii = [3.0] task = measBase.SingleFrameMeasurementTask(schema, config=sfm_config) measCat = afwTable.SourceCatalog(schema) # detect the sources and run with the measurement task ds.makeSources(measCat) self.exposure.setPsf(self.psf) task.run(measCat, self.exposure) self.assertGreater(len(measCat), 0) for source in measCat: if source.get("base_PixelFlags_flag_edge"): continue if display: disp.dot("+", source.getX(), source.getY())