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))
Example #2
0
    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
Example #4
0
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()
Example #5
0
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
Example #8
0
    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))