def bypass_defects(self, datasetType, pythonType, butlerLocation, dataId): """Return a defect based on the butler location returned by map_defects. Parameters ---------- butlerLocation : `lsst.daf.persistence.ButlerLocation` A ButlerLocation with locationList = path to defects FITS file. dataId : `dict` The usual data ID; "ccd" must be set. Notes ----- The name "bypass_XXX" means the butler makes no attempt to convert the ButlerLocation into an object, which is what we want for now, since that conversion is a bit tricky. """ (ccdKey, ccdSerial) = self._getCcdKeyVal(dataId) defectsFitsPath = butlerLocation.locationList[0] with fits.open(defectsFitsPath) as hduList: for hdu in hduList[1:]: if str(hdu.header["SERIAL"]) != ccdSerial: continue defectList = measAlg.Defects() for data in hdu.data: bbox = afwGeom.Box2I( afwGeom.Point2I(int(data['x0']), int(data['y0'])), afwGeom.Extent2I(int(data['width']), int(data['height'])), ) defectList.append(bbox) return defectList raise RuntimeError("No defects for ccdSerial %s in %s" % (ccdSerial, defectsFitsPath))
def testDefectBase(self): """Test DefectBases""" defectList = measAlg.Defects() ccdImage = afwImage.MaskedImageF(250, 225) ccdImage.set(self.setVal, 0, self.setVal) # # Insert some defects into the Ccd # for x0, y0, x1, y1 in [ (34, 0, 35, 80), (34, 81, 34, 100), (180, 100, 182, 130), ]: bbox = lsst.geom.Box2I(lsst.geom.Point2I(x0, y0), lsst.geom.Point2I(x1, y1)) defectList.append(bbox) bad = ccdImage.Factory(ccdImage, bbox, afwImage.LOCAL) bad.set(100) defectList.maskPixels(ccdImage, maskName="BAD") mask = ccdImage.getMask() bitMask = mask.getPlaneBitMask('BAD') for d in defectList: bad = mask.Factory(mask, d.getBBox(), afwImage.LOCAL) self.assertTrue((bad.getArray() & bitMask == bitMask).all()) if display: disp = afwDisplay.Display() disp.mtv(ccdImage.getImage(), title=self._testMethodName + ": Defects") for d in defectList: afwDisplay.utils.drawBBox(d.getBBox(), ctype=afwDisplay.CYAN, borderWidth=.5) disp.incrDefaultFrame() ipIsr.interpolateDefectList(ccdImage, defectList, 2.) im = ccdImage.getImage() for d in defectList: intrp = im.Factory(im, d.getBBox()) expect = np.empty_like(intrp.getArray()) expect[:] = self.setVal self.assertImagesEqual(intrp, expect) if display: disp = afwDisplay.Display() disp.mtv(ccdImage.getImage(), title=self._testMethodName + ": Defects Interpolated") for d in defectList: afwDisplay.utils.drawBBox(d.getBBox(), ctype=afwDisplay.CYAN, borderWidth=.5) disp.incrDefaultFrame()
def transposeDefectList(self, defectList, checkBbox=None): retDefectList = measAlg.Defects() for defect in defectList: bbox = defect.getBBox() nbbox = geom.Box2I(geom.Point2I(bbox.getMinY(), bbox.getMinX()), geom.Extent2I(bbox.getDimensions()[1], bbox.getDimensions()[0])) if checkBbox: if checkBbox.overlaps(bbox): retDefectList.append(measAlg.Defect(nbbox)) else: pass else: retDefectList.append(measAlg.Defect(nbbox)) return retDefectList
def transposeDefectList(defectList): """Make a transposed copy of a defect list. Parameters ---------- defectList : `lsst.meas.algorithms.Defects` Input list of defects. Returns ------- retDefectList : `lsst.meas.algorithms.Defects` Transposed list of defects. """ if isinstance(defectList, measAlg.Defects): return defectList.transpose() return measAlg.Defects(defectList).transpose()
def writeDefectsFile(bboxList, path): """Write a mask image from a fits table of defects. Parameters ---------- bboxList : `list` of `lsst.geom.Box2I` List of bounding boxes defining defect locations. path : `str` Path of output defects file; should end with ".fits". """ maskBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1, 1)) for box in bboxList: maskBBox.include(box) defectsMaskedImage = afwImage.MaskedImageF(maskBBox) defectList = measAlg.Defects(bboxList) defectsMaskedImage = defectList.maskPixels(defectsMaskedImage, maskName='BAD') defectsMaskedImage.getMask().writeFits(MaskFileName) print("wrote %s with bbox %s" % (MaskFileName, maskBBox,))
def test1295(self): """A test case for #1295 (failure to interpolate over groups of defects.""" im = afwImage.ImageF(lsst.geom.ExtentI(100, 100)) mi = afwImage.makeMaskedImage(im) mi.set(100) flat = afwImage.ImageF(im.getDimensions()) flat.set(1) flat[50:51, :, afwImage.LOCAL] = 0.0 flat[55:56, :, afwImage.LOCAL] = 0.0 flat[58:59, :, afwImage.LOCAL] = 0.0 flat[51:60, 51:, afwImage.LOCAL] = 0.0 mi /= flat if display: afwDisplay.Display(frame=0).mtv(mi, title=self._testMethodName + ": Raw") defectList = algorithms.Defects() bbox = lsst.geom.BoxI(lsst.geom.PointI(50, 0), lsst.geom.ExtentI(1, 100)) defectList.append(algorithms.Defect(bbox)) bbox = lsst.geom.BoxI(lsst.geom.PointI(55, 0), lsst.geom.ExtentI(1, 100)) defectList.append(algorithms.Defect(bbox)) bbox = lsst.geom.BoxI(lsst.geom.PointI(58, 0), lsst.geom.ExtentI(1, 100)) defectList.append(algorithms.Defect(bbox)) bbox = lsst.geom.BoxI(lsst.geom.PointI(51, 51), lsst.geom.ExtentI(9, 49)) defectList.append(algorithms.Defect(bbox)) psf = algorithms.DoubleGaussianPsf( 15, 15, 1. / (2 * math.sqrt(2 * math.log(2)))) algorithms.interpolateOverDefects(mi, psf, defectList, 50.) if display: afwDisplay.Display(frame=1).mtv(mi, title=self._testMethodName + ": Interpolated") self.assertTrue(np.isfinite(mi.image[56, 51, afwImage.LOCAL]))
def addDefects(exp, nBadCols=10): img = exp.getMaskedImage().getImage() (xsize, ysize) = img.getDimensions() defectList = measAlg.Defects() # set some bad cols and add them to a defect list for xi in numpy.random.randint(0, xsize, nBadCols): yi = numpy.random.randint(0, ysize) xi, yi = int(xi), int(yi) bbox = afwGeom.Box2I(afwGeom.PointI(xi, 0), afwGeom.ExtentI(1, yi+1)) subIm = afwImage.ImageF(img, bbox) subIm.set(1e7) defectList.append(bbox) # set a 15 pixel box of defects at the upper left corner to demonstrate fallbackValue bbox = afwGeom.Box2I(afwGeom.PointI(0, ysize-15), afwGeom.ExtentI(15, 15)) subIm = afwImage.ImageF(img, bbox) subIm.set(1e7) defectList.append(bbox) return defectList
def run(self, image, planeName=None, fwhmPixels=None, defects=None): """!Interpolate in place over pixels in a maskedImage marked as bad Pixels to be interpolated are set by either a mask planeName provided by the caller OR a defects list of type `~lsst.meas.algorithms.Defects` If both are provided an exception is raised. Note that the interpolation code in meas_algorithms currently doesn't use the input PSF (though it's a required argument), so it's not important to set the input PSF parameters exactly. This PSF is set here as the psf attached to the "image" (i.e if the image passed in is an Exposure). Otherwise, a psf model is created using measAlg.GaussianPsfFactory with the value of fwhmPixels (the value passed in by the caller, or the default defaultFwhm set in measAlg.GaussianPsfFactory if None). @param[in,out] image MaskedImage OR Exposure to be interpolated @param[in] planeName name of mask plane over which to interpolate If None, must provide a defects list. @param[in] fwhmPixels FWHM of core star (pixels) If None the default is used, where the default is set to the exposure psf if available @param[in] defects List of defects of type measAlg.Defects over which to interpolate. """ try: maskedImage = image.getMaskedImage() except AttributeError: maskedImage = image # set defectList from defects OR mask planeName provided if planeName is None: if defects is None: raise ValueError("No defects or plane name provided") else: if not isinstance(defects, measAlg.Defects): defectList = measAlg.Defects(defects) else: defectList = defects planeName = "defects" else: if defects is not None: raise ValueError( "Provide EITHER a planeName OR a list of defects, not both" ) if planeName not in maskedImage.getMask().getMaskPlaneDict(): raise ValueError("maskedImage does not contain mask plane %s" % planeName) defectList = measAlg.Defects.fromMask(maskedImage, planeName) # set psf from exposure if provided OR using modelPsf with fwhmPixels provided try: psf = image.getPsf() self.log.info("Setting psf for interpolation from image") except AttributeError: self.log.info( "Creating psf model for interpolation from fwhm(pixels) = %s" % (str(fwhmPixels) if fwhmPixels is not None else (str(self.config.modelPsf.defaultFwhm)) + " [default]")) psf = self.config.modelPsf.apply(fwhm=fwhmPixels) fallbackValue = 0.0 # interpolateOverDefects needs this to be a float, regardless if it is used if self.config.useFallbackValueAtEdge: fallbackValue = self._setFallbackValue(maskedImage) self.interpolateImage(maskedImage, psf, defectList, fallbackValue) self.log.info("Interpolated over %d %s pixels." % (len(defectList), planeName))
def test_defects(self): defects = algorithms.Defects() defects.append( algorithms.Defect( lsst.geom.Box2I(lsst.geom.Point2I(5, 6), lsst.geom.Point2I(41, 50)))) defects.append( lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Point2I(4, 5))) defects.append(lsst.geom.Point2I(10, 12)) defects.append( afwImage.DefectBase( lsst.geom.Box2I(lsst.geom.Point2I(100, 200), lsst.geom.Extent2I(5, 5)))) self.assertEqual(len(defects), 4) for d in defects: self.assertIsInstance(d, algorithms.Defect) # Transposition transposed = defects.transpose() self.assertEqual(len(transposed), len(defects)) self.assertEqual( transposed[0].getBBox(), lsst.geom.Box2I(lsst.geom.Point2I(6, 5), lsst.geom.Extent2I(45, 37))) # Serialization round trip meta = PropertyList() meta["TESTHDR"] = "testing" defects.setMetadata(meta) table = defects.toFitsRegionTable() defects2 = algorithms.Defects.fromTable(table) self.assertEqual(defects2, defects) # via FITS with lsst.utils.tests.getTempFilePath(".fits") as tmpFile: defects.writeFits(tmpFile) defects2 = algorithms.Defects.readFits(tmpFile) # Equality tests the bounding boxes so metadata is tested separately. self.assertEqual(defects2, defects) self.assertMetadata(defects2, defects) # via text file with lsst.utils.tests.getTempFilePath(".ecsv") as tmpFile: defects.writeText(tmpFile) defects2 = algorithms.Defects.readText(tmpFile) # Equality tests the bounding boxes so metadata is tested separately. self.assertEqual(defects2, defects) self.assertMetadata(defects2, defects) # Check bad values with self.assertRaises(ValueError): defects.append( lsst.geom.Box2D(lsst.geom.Point2D(0., 0.), lsst.geom.Point2D(3.1, 3.1))) with self.assertRaises(ValueError): defects.append("defect")
def testEdge(self): """Test that we can interpolate to the edge""" mi = afwImage.MaskedImageF(80, 30) ima = mi.getImage().getArray() # # Loop over number of bad columns at left or right edge of image # for nBadCol in range(0, 20): mi.set((0, 0x0, 0)) np.random.seed(666) ima[:] = np.random.uniform(-1, 1, ima.shape) defects = [] if nBadCol > 0: # # Bad left edge # ima[:, 0:nBadCol] = 10 defects.append( lsst.geom.BoxI(lsst.geom.PointI(0, 0), lsst.geom.ExtentI(nBadCol, mi.getHeight()))) # # With another bad set of columns next to bad left edge # ima[:, -nBadCol:] = 10 defects.append( lsst.geom.BoxI( lsst.geom.PointI(mi.getWidth() - nBadCol, 0), lsst.geom.ExtentI(nBadCol, mi.getHeight()))) # # Bad right edge # ima[0:10, nBadCol + 1:nBadCol + 4] = 100 defects.append( lsst.geom.BoxI(lsst.geom.PointI(nBadCol + 1, 0), lsst.geom.ExtentI(3, 10))) # # With another bad set of columns next to bad right edge # ima[0:10, -nBadCol - 4:-nBadCol - 1] = 100 defects.append((lsst.geom.BoxI( lsst.geom.PointI(mi.getWidth() - nBadCol - 4, 0), lsst.geom.ExtentI(3, 10)))) # # Test cases that left and right bad patches nearly (or do) coalesce # ima[-3:, 0:mi.getWidth() // 2 - 1] = 100 defects.append( lsst.geom.BoxI(lsst.geom.PointI(0, mi.getHeight() - 3), lsst.geom.ExtentI(mi.getWidth() // 2 - 1, 1))) ima[-3:, mi.getWidth() // 2 + 1:] = 100 defects.append( lsst.geom.BoxI( lsst.geom.PointI(mi.getWidth() // 2 + 1, mi.getHeight() - 3), lsst.geom.ExtentI(mi.getWidth() // 2 - 1, 1))) ima[-2:, 0:mi.getWidth() // 2] = 100 defects.append( lsst.geom.BoxI(lsst.geom.PointI(0, mi.getHeight() - 2), lsst.geom.ExtentI(mi.getWidth() // 2, 1))) ima[-2:, mi.getWidth() // 2 + 1:] = 100 defects.append( lsst.geom.BoxI( lsst.geom.PointI(mi.getWidth() // 2 + 1, mi.getHeight() - 2), lsst.geom.ExtentI(mi.getWidth() // 2 - 1, 1))) ima[-1:, :] = 100 defects.append( lsst.geom.BoxI(lsst.geom.PointI(0, mi.getHeight() - 1), lsst.geom.ExtentI(mi.getWidth(), 1))) # Test fix for HSC-978: long defect stops one pixel shy of the edge (when nBadCol == 0) ima[13, :-1] = 100 defects.append( lsst.geom.BoxI(lsst.geom.PointI(0, 13), lsst.geom.ExtentI(mi.getWidth() - 1, 1))) ima[14, 1:] = 100 defects.append( lsst.geom.BoxI(lsst.geom.PointI(1, 14), lsst.geom.ExtentI(mi.getWidth() - 1, 1))) # # Build list of defects to interpolate over # defectList = algorithms.Defects() for bbox in defects: defectList.append(algorithms.Defect(bbox)) # # Guess a PSF and do the work # if display: afwDisplay.Display(frame=2).mtv(mi, title=self._testMethodName + ": image") psf = algorithms.DoubleGaussianPsf( 15, 15, 1. / (2 * math.sqrt(2 * math.log(2)))) algorithms.interpolateOverDefects(mi, psf, defectList, 0, True) if display: afwDisplay.Display(frame=3).mtv(mi, title=self._testMethodName + ": image") self.assertGreater(np.min(ima), -2) self.assertGreater(2, np.max(ima))