def testRemoveMaskPlane(self): mMask = self.mMask1 # Add mask plane FOO and make sure it got added properly mMask.addMaskPlane("FOO") self.assertIn("FOO", mMask.getMaskPlaneDict()) self.assertIn("FOO", Mask().getMaskPlaneDict()) # Remove plane FOO, noting that removeMaskPlane removes it from the # default, but each instance remembers the version of the mask # dictionary that was current when it was created, so it will still # be in the mMask dict. mMask.removeMaskPlane("FOO") self.assertIn("FOO", mMask.getMaskPlaneDict()) self.assertNotIn("FOO", Mask().getMaskPlaneDict())
def __init__(self, *args, **kwargs): pipeBase.Task.__init__(self, *args, **kwargs) self._badPixelMask = Mask.getPlaneBitMask(self.config.badMaskPlanes) self._statsControl = afwMath.StatisticsControl() self._statsControl.setNumSigmaClip(self.config.numSigmaClip) self._statsControl.setNumIter(self.config.numIter) self._statsControl.setAndMask(self._badPixelMask)
def testMaskFitsReader(self): maskIn = Mask(self.bbox, dtype=MaskPixel) maskIn.array[:, :] = np.random.randint(low=1, high=5, size=maskIn.array.shape) with lsst.utils.tests.getTempFilePath(".fits") as fileName: maskIn.writeFits(fileName) reader = MaskFitsReader(fileName) self.assertEqual(reader.readBBox(), self.bbox) self.assertEqual(reader.readDType(), MaskPixel) self.assertEqual(reader.fileName, fileName) for args in self.args: with self.subTest(args=args): array = reader.readArray(*args) mask = reader.read(*args) subIn = maskIn.subset(*args) if args else maskIn self.assertEqual(MaskPixel, array.dtype) self.assertTrue(np.all(subIn.array == array)) self.assertEqual(subIn.getXY0(), reader.readXY0(*args)) self.assertImagesEqual(subIn, mask)
def getSpanSetFromImages(images, thresh=0, xy0=None): """Create a Footprint from a set of Images Parameters ---------- images: `MultibandImage` or list of `Image`, array Images to extract the footprint from thresh: `float` All pixels above `thresh` will be included in the footprint xy0: `Point2I` Location of the minimum value of the images bounding box (if images is an array, otherwise the image bounding box is used). Returns ------- spans: `SpanSet` Union of all spans in the images above the threshold imageBBox: `Box2I` Bounding box for the input images. """ # Set the threshold for each band if not hasattr(thresh, "__len__"): thresh = [thresh] * len(images) # If images is a list of `afw Image` objects then # merge the SpanSet in each band into a single Footprint if isinstance(images, MultibandBase) or isinstance(images[0], Image): spans = SpanSet() for n, image in enumerate(images): mask = image.array > thresh[n] mask = Mask(mask.astype(np.int32), xy0=image.getBBox().getMin()) spans = spans.union(SpanSet.fromMask(mask)) imageBBox = images[0].getBBox() else: # Use thresh to detect the pixels above the threshold in each band thresh = np.array(thresh) if xy0 is None: xy0 = Point2I(0, 0) mask = np.any(images > thresh[:, None, None], axis=0) mask = Mask(mask.astype(np.int32), xy0=xy0) spans = SpanSet.fromMask(mask) imageBBox = mask.getBBox() return spans, imageBBox
def testRemoveAndClearMaskPlane(self): mMask = self.mMask1 # Add mask plane FOO and test clearing it without removing plane from # default dict mMask.addMaskPlane("FOO") mMask.removeAndClearMaskPlane("FOO") self.assertNotIn("FOO", mMask.getMaskPlaneDict()) self.assertIn("FOO", Mask().getMaskPlaneDict()) # Now also remove it from default dict mMask.addMaskPlane("FOO") mMask.removeAndClearMaskPlane("FOO", removeFromDefault=True) self.assertNotIn("FOO", mMask.getMaskPlaneDict()) self.assertNotIn("FOO", Mask().getMaskPlaneDict()) # Now remove and clear the EDGE mask plane and make sure all of the planes # in the MultibandMask (i.e. the "singles") got updated accordingly mMask.removeAndClearMaskPlane("EDGE", removeFromDefault=True) self.assertNotIn("EDGE", mMask.getMaskPlaneDict()) self.assertNotIn("EDGE", Mask().getMaskPlaneDict()) # Assert that all mask planes were updated (i.e. having EDGE removed) self.assertTrue( np.all([ s.array == self.values1[n] & ~self.EDGE for n, s in enumerate(mMask.singles) ]))
def modelToHeavy(source, mExposure, blend, xy0=Point2I(), dtype=np.float32): """Convert a scarlet model to a `MultibandFootprint`. Parameters ---------- source : `scarlet.Component` The source to convert to a `HeavyFootprint`. mExposure : `lsst.image.MultibandExposure` The multiband exposure containing the image, mask, and variance data. blend : `scarlet.Blend` The `Blend` object that contains information about the observation, PSF, etc, used to convolve the scarlet model to the observed seeing in each band. xy0 : `lsst.geom.Point2I` `(x,y)` coordinates of the lower-left pixel of the entire blend. dtype : `numpy.dtype` The data type for the returned `HeavyFootprint`. Returns ------- mHeavy : `lsst.detection.MultibandFootprint` The multi-band footprint containing the model for the source. """ # We want to convolve the model with the observed PSF, # which means we need to grow the model box by the PSF to # account for all of the flux after convolution. # FYI: The `scarlet.Box` class implements the `&` operator # to take the intersection of two boxes. # Get the PSF size and radii to grow the box py, px = blend.observations[0].psf.get_model().shape[1:] dh = py // 2 dw = px // 2 shape = (source.bbox.shape[0], source.bbox.shape[1] + py, source.bbox.shape[2] + px) origin = (source.bbox.origin[0], source.bbox.origin[1] - dh, source.bbox.origin[2] - dw) # Create the larger box to fit the model + PSf bbox = Box(shape, origin=origin) # Only use the portion of the convolved model that fits in the image overlap = bbox & source.frame.bbox # Load the full multiband model in the larger box model = source.model_to_box(overlap) # Convolve the model with the PSF in each band # Always use a real space convolution to limit artifacts model = blend.observations[0].renderer.convolve( model, convolution_type="real").astype(dtype) # Update xy0 with the origin of the sources box xy0 = Point2I(overlap.origin[-1] + xy0.x, overlap.origin[-2] + xy0.y) # Create the spans for the footprint valid = np.max(np.array(model), axis=0) != 0 valid = Mask(valid.astype(np.int32), xy0=xy0) spans = SpanSet.fromMask(valid) # Add the location of the source to the peak catalog peakCat = PeakCatalog(source.detectedPeak.table) peakCat.append(source.detectedPeak) # Create the MultibandHeavyFootprint foot = Footprint(spans) foot.setPeakCatalog(peakCat) model = MultibandImage(mExposure.filters, model, valid.getBBox()) mHeavy = MultibandFootprint.fromImages(mExposure.filters, model, footprint=foot) return mHeavy