Пример #1
0
    def testCopy(self):
        bbox = lsst.geom.BoxI(lsst.geom.PointI(0, 2), lsst.geom.PointI(5, 6))

        fp = afwDetect.Footprint(afwGeom.SpanSet(bbox), bbox)

        # test copy construct
        fp2 = afwDetect.Footprint(fp)

        self.assertEqual(fp2.getBBox(), bbox)
        self.assertEqual(fp2.getRegion(), bbox)
        self.assertEqual(fp2.getArea(), bbox.getArea())

        y = bbox.getMinY()
        for s in fp2.getSpans():
            self.assertEqual(s.getY(), y)
            self.assertEqual(s.getX0(), bbox.getMinX())
            self.assertEqual(s.getX1(), bbox.getMaxX())
            y += 1

        # test assignment
        fp3 = afwDetect.Footprint()
        fp3.assign(fp)
        self.assertEqual(fp3.getBBox(), bbox)
        self.assertEqual(fp3.getRegion(), bbox)
        self.assertEqual(fp3.getArea(), bbox.getArea())

        y = bbox.getMinY()
        for s in fp3.getSpans():
            self.assertEqual(s.getY(), y)
            self.assertEqual(s.getX0(), bbox.getMinX())
            self.assertEqual(s.getX1(), bbox.getMaxX())
            y += 1
Пример #2
0
 def testInclude(self):
     """Test that we can expand a Footprint to include the union of itself and all others
     provided (must be non-disjoint).
     """
     region = afwGeom.Box2I(afwGeom.Point2I(-6, -6), afwGeom.Point2I(6, 6))
     parent = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-2, -2), afwGeom.Point2I(2, 2)), region)
     parent.addPeak(0, 0, float("NaN"))
     child1 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-3, 0), afwGeom.Point2I(0, 3)), region)
     child1.addPeak(-1, 1, float("NaN"))
     child2 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-4, -3), afwGeom.Point2I(-1, 0)), region)
     child3 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(4, -1), afwGeom.Point2I(6, 1)))
     merge12 = afwDetect.Footprint(parent)
     merge12.include([child1, child2])
     self.assertTrue(merge12.getBBox().contains(parent.getBBox()))
     self.assertTrue(merge12.getBBox().contains(child1.getBBox()))
     self.assertTrue(merge12.getBBox().contains(child2.getBBox()))
     mask12a = afwImage.MaskU(region)
     mask12b = afwImage.MaskU(region)
     afwDetect.setMaskFromFootprint(mask12a, parent, 1)
     afwDetect.setMaskFromFootprint(mask12a, child1, 1)
     afwDetect.setMaskFromFootprint(mask12a, child2, 1)
     afwDetect.setMaskFromFootprint(mask12b, merge12, 1)
     self.assertEqual(mask12a.getArray().sum(), merge12.getArea())
     self.assertClose(mask12a.getArray(), mask12b.getArray(), rtol=0, atol=0)
     self.assertRaisesLsstCpp(pexExcept.RuntimeError, parent.include, [child1, child2, child3])
Пример #3
0
    def testDot(self):
        """Test HeavyFootprint::dot"""
        size = 20, 20
        for xOffset, yOffset in [(0, 0), (0, 3), (3, 0), (2, 2)]:
            mi1 = afwImage.MaskedImageF(*size)
            mi2 = afwImage.MaskedImageF(*size)
            mi1.set(0)
            mi2.set(0)

            fp1 = afwDetect.Footprint()
            fp2 = afwDetect.Footprint()
            for y, x0, x1 in [(5, 3, 7),
                              (6, 3, 4),
                              (6, 6, 7),
                              (7, 3, 7),]:
                fp1.addSpan(y, x0, x1)
                fp2.addSpan(y + yOffset, x0 + xOffset, x1 + xOffset)
                for x in range(x0, x1 + 1):
                    value = (x + y, 0, 1.0)
                    mi1.set(x, y, value)
                    mi2.set(x + xOffset, y + yOffset, value)

            hfp1 = afwDetect.makeHeavyFootprint(fp1, mi1)
            hfp2 = afwDetect.makeHeavyFootprint(fp2, mi2)
            hfp1.normalize()
            hfp2.normalize()

            dot = np.vdot(mi1.getImage().getArray(), mi2.getImage().getArray())
            self.assertEqual(hfp1.dot(hfp2), dot)
            self.assertEqual(hfp2.dot(hfp1), dot)
Пример #4
0
    def testDot(self):
        """Test HeavyFootprint::dot"""
        size = 20, 20
        for xOffset, yOffset in [(0, 0), (0, 3), (3, 0), (2, 2)]:
            mi1 = afwImage.MaskedImageF(*size)
            mi2 = afwImage.MaskedImageF(*size)
            mi1.set(0)
            mi2.set(0)

            spanList1 = []
            spanList2 = []
            for y, x0, x1 in [
                (5, 3, 7),
                (6, 3, 4),
                (6, 6, 7),
                (7, 3, 7),
            ]:
                spanList1.append(afwGeom.Span(y, x0, x1))
                spanList2.append(
                    afwGeom.Span(y + yOffset, x0 + xOffset, x1 + xOffset))
                for x in range(x0, x1 + 1):
                    value = (x + y, 0, 1.0)
                    mi1[x, y, afwImage.LOCAL] = value
                    mi2[x + xOffset, y + yOffset, afwImage.LOCAL] = value

            fp1 = afwDetect.Footprint(afwGeom.SpanSet(spanList1))
            fp2 = afwDetect.Footprint(afwGeom.SpanSet(spanList2))

            hfp1 = afwDetect.makeHeavyFootprint(fp1, mi1)
            hfp2 = afwDetect.makeHeavyFootprint(fp2, mi2)

            dot = np.vdot(mi1.getImage().getArray(), mi2.getImage().getArray())
            self.assertEqual(hfp1.dot(hfp2), dot)
            self.assertEqual(hfp2.dot(hfp1), dot)
Пример #5
0
    def testSpanShift(self):
        """Test our ability to shift spans"""

        span = afwDetect.Span(10, 100, 105)
        foot = afwDetect.Footprint()

        foot.addSpan(span, 1, 2)

        bbox = foot.getBBox()
        self.assertEqual(bbox.getWidth(), 6)
        self.assertEqual(bbox.getHeight(), 1)
        self.assertEqual(bbox.getMinX(), 101)
        self.assertEqual(bbox.getMinY(), 12)
        #
        # Shift that span using Span.shift
        #
        foot = afwDetect.Footprint()
        span.shift(-1, -2)
        foot.addSpan(span)

        bbox = foot.getBBox()
        self.assertEqual(bbox.getWidth(), 6)
        self.assertEqual(bbox.getHeight(), 1)
        self.assertEqual(bbox.getMinX(), 99)
        self.assertEqual(bbox.getMinY(), 8)
Пример #6
0
    def testGrow(self):
        """Test growing a footprint"""
        x0, y0 = 20, 20
        width, height = 20, 30
        spanSet = afwGeom.SpanSet(
            lsst.geom.Box2I(lsst.geom.Point2I(x0, y0),
                            lsst.geom.Extent2I(width, height)))
        foot1 = afwDetect.Footprint(
            spanSet,
            lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                            lsst.geom.Extent2I(100, 100)))

        # Add some peaks and check that they get copied into the new grown footprint
        foot1.addPeak(20, 20, 1)
        foot1.addPeak(30, 35, 2)
        foot1.addPeak(25, 45, 3)
        self.assertEqual(len(foot1.getPeaks()), 3)

        bbox1 = foot1.getBBox()

        self.assertEqual(bbox1.getMinX(), x0)
        self.assertEqual(bbox1.getMaxX(), x0 + width - 1)
        self.assertEqual(bbox1.getWidth(), width)

        self.assertEqual(bbox1.getMinY(), y0)
        self.assertEqual(bbox1.getMaxY(), y0 + height - 1)
        self.assertEqual(bbox1.getHeight(), height)

        ngrow = 5
        for isotropic in (True, False):
            foot2 = afwDetect.Footprint().assign(foot1)
            stencil = afwGeom.Stencil.CIRCLE if isotropic else \
                afwGeom.Stencil.MANHATTAN
            foot2.dilate(ngrow, stencil)

            # Check that the grown footprint is bigger than the original
            self.assertGreater(foot2.getArea(), foot1.getArea())

            # Check that peaks got copied into grown footprint
            self.assertEqual(len(foot2.getPeaks()), 3)
            for peak in foot2.getPeaks():
                self.assertIn((peak.getIx(), peak.getIy()),
                              [(20, 20), (30, 35), (25, 45)])

            bbox2 = foot2.getBBox()

            # check bbox2
            self.assertEqual(bbox2.getMinX(), x0 - ngrow)
            self.assertEqual(bbox2.getWidth(), width + 2 * ngrow)

            self.assertEqual(bbox2.getMinY(), y0 - ngrow)
            self.assertEqual(bbox2.getHeight(), height + 2 * ngrow)
            # Check that region was preserved
            self.assertEqual(foot1.getRegion(), foot2.getRegion())
Пример #7
0
 def testConstructors(self):
     '''
     Test that each of the constructors constructs a valid Footprint,
     if any of these fails, an exception will be raised and the test
     will fail.
     '''
     self.footprint = afwDet.Footprint(self.spans)
     self.footprintWithRegion = afwDet.Footprint(self.spans, self.region)
     self.footprintWithSchema = afwDet.Footprint(self.spans, self.schema)
     self.footprintWithSchemaRegion = afwDet.Footprint(
         self.spans, self.schema, self.region)
     self.emptyFootprint = afwDet.Footprint()
     self.assertEqual(len(self.emptyFootprint.spans), 0)
     self.assertEqual(len(self.emptyFootprint.peaks), 0)
Пример #8
0
    def test1(self):
        task = measAlg.ReplaceWithNoiseTask()
        schema = afwTable.SourceTable.makeMinimalSchema()
        table = afwTable.SourceTable.make(schema)
        sources = afwTable.SourceCatalog(table)

        im = afwImage.ImageF(200, 50)
        seed = 42
        rand = afwMath.Random(afwMath.Random.MT19937, seed)
        afwMath.randomGaussianImage(im, rand)

        s = sources.addNew()
        s.setId(1)
        fp = afwDet.Footprint()
        y, x0, x1 = (10, 10, 190)
        im.getArray()[y, x0:x1] = 10
        fp.addSpan(y, x0, x1)
        s.setFootprint(fp)
        s = sources.addNew()
        s.setId(2)
        fp = afwDet.Footprint()
        y, x0, x1 = (40, 10, 190)
        im.getArray()[y, x0:x1] = 10
        fp.addSpan(y, x0, x1)
        s.setFootprint(fp)

        mi = afwImage.MaskedImageF(im)
        exposure = afwImage.makeExposure(mi)
        self._save(mi, 'a')
        task.begin(exposure, sources)
        self._save(mi, 'b')

        sourcei = 0
        task.insertSource(exposure, sourcei)
        self._save(mi, 'c')
        # do something
        task.removeSource(exposure, sources, sources[sourcei])
        self._save(mi, 'd')

        sourcei = 1
        task.insertSource(exposure, sourcei)
        self._save(mi, 'e')
        # do something
        task.removeSource(exposure, sources, sources[sourcei])
        self._save(mi, 'f')

        task.end(exposure, sources)
        self._save(mi, 'g')
def morphToHeavy(source, peakSchema, xy0=Point2I()):
    """Convert the morphology to a `HeavyFootprint`

    Parameters
    ----------
    source : `scarlet.Component`
        The scarlet source with a morphology to convert to
        a `HeavyFootprint`.
    peakSchema : `lsst.daf.butler.Schema`
        The schema for the `PeakCatalog` of the `HeavyFootprint`.
    xy0 : `tuple`
        `(x,y)` coordinates of the bounding box containing the
        `HeavyFootprint`.

    Returns
    -------
    heavy : `lsst.afw.detection.HeavyFootprint`
    """
    mask = afwImage.MaskX(np.array(source.morph > 0, dtype=np.int32), xy0=xy0)
    ss = SpanSet.fromMask(mask)

    if len(ss) == 0:
        return None

    tfoot = afwDet.Footprint(ss, peakSchema=peakSchema)
    cy, cx = source.pixel_center
    xmin, ymin = xy0
    # HeavyFootprints are not defined for 64 bit floats
    morph = source.morph.astype(np.float32)
    peakFlux = morph[cy, cx]
    tfoot.addPeak(cx + xmin, cy + ymin, peakFlux)
    timg = afwImage.ImageF(morph, xy0=xy0)
    timg = timg[tfoot.getBBox()]
    heavy = afwDet.makeHeavyFootprint(tfoot, afwImage.MaskedImageF(timg))
    return heavy
Пример #10
0
    def testShrink(self):
        width, height = 5, 10 # Size of footprint
        x0, y0 = 50, 50 # Position of footprint
        imwidth, imheight = 100, 100 # Size of image

        foot = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(width, height)),
                                   afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(imwidth, imheight)))
        self.assertEqual(foot.getNpix(), width*height)

        # Add some peaks to the original footprint and check that those lying outside
        # the shrunken footprint are omitted from the returned shrunken footprint.
        foot.addPeak(50, 50, 1) # should be omitted in shrunken footprint
        foot.addPeak(52, 52, 2) # should be kept in shrunken footprint
        foot.addPeak(50, 59, 3) # should be omitted in shrunken footprint
        self.assertEqual(len(foot.getPeaks()), 3) # check that all three peaks were added

        # Shrinking by one pixel makes each dimension *two* pixels shorter.
        shrunk = afwDetect.shrinkFootprint(foot, 1, True)
        self.assertEqual(3*8, shrunk.getNpix())

        # Shrunken footprint should now only contain one peak at (52, 52)
        self.assertEqual(len(shrunk.getPeaks()), 1)
        peak = shrunk.getPeaks()[0]
        self.assertEqual((peak.getIx(), peak.getIy()), (52, 52))

        # Without shifting the centroid
        self.assertEqual(shrunk.getCentroid(), foot.getCentroid())

        # Get the same result from a Manhattan shrink
        shrunk = afwDetect.shrinkFootprint(foot, 1, False)
        self.assertEqual(3*8, shrunk.getNpix())
        self.assertEqual(shrunk.getCentroid(), foot.getCentroid())

        # Shrinking by a large amount leaves nothing.
        self.assertEqual(afwDetect.shrinkFootprint(foot, 100, True).getNpix(), 0)
Пример #11
0
    def testFootprintFromEllipse(self):
        """Create an elliptical Footprint"""
        cen = afwGeom.Point2D(23, 25)
        a, b, theta = 25, 15, 30
        ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(a, b, math.radians(theta)),  cen)
        foot = afwDetect.Footprint(ellipse, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(50, 60)))

        idImage = afwImage.ImageU(afwGeom.Extent2I(foot.getRegion().getWidth(), foot.getRegion().getHeight()))
        idImage.set(0)

        foot.insertIntoImage(idImage, foot.getId())

        if display:
            ds9.mtv(idImage, frame=2)
            displayUtils.drawFootprint(foot, frame=2)
            shape = foot.getShape()
            shape.scale(2)              # <r^2> = 1/2 for a disk
            ds9.dot(shape, *cen, frame=2, ctype=ds9.RED)

            shape = foot.getShape()
            shape.scale(2)              # <r^2> = 1/2 for a disk
            ds9.dot(shape, *cen, frame=2, ctype=ds9.MAGENTA)

        axes = afwGeom.ellipses.Axes(foot.getShape())
        axes.scale(2)                   # <r^2> = 1/2 for a disk

        self.assertEqual(foot.getCentroid(), cen)
        self.assertTrue(abs(a - axes.getA()) < 0.15, "a: %g v. %g" % (a, axes.getA()))
        self.assertTrue(abs(b - axes.getB()) < 0.02, "b: %g v. %g" % (b, axes.getB()))
        self.assertTrue(abs(theta - math.degrees(axes.getTheta())) < 0.2,
                        "theta: %g v. %g" % (theta, math.degrees(axes.getTheta())))
Пример #12
0
    def testRejectBlends(self):
        """Test the PcaPsfDeterminer blend removal

        We give it a single blended source, asking it to remove blends,
        and check that it barfs in the expected way.
        """

        factory = measAlg.psfDeterminerRegistry["pca"]
        config = factory.ConfigClass()
        config.doRejectBlends = True
        psfDeterminer = factory(config)

        schema = afwTable.SourceTable.makeMinimalSchema()
        schema.addField("position", afwGeom.Point2D, doc="Position")
        schema.addField("flux.psf", float, doc="psf")
        schema.addField("flux.psf.flags", "Flag", doc="psf")

        catalog = afwTable.SourceCatalog(schema)
        catalog.defineCentroid("position")
        catalog.definePsfFlux("flux.psf")
        source = catalog.addNew()

        foot = afwDetection.Footprint(afwGeom.Point2I(123, 45), 6, self.exposure.getBBox())
        foot.addPeak(123, 45, 6)
        foot.addPeak(126, 47, 5)
        source.setFootprint(foot)

        candidates = [measAlg.makePsfCandidate(source, self.exposure)]
        metadata = dafBase.PropertyList()

        with self.assertRaises(RuntimeError) as cm:
            psfDeterminer.determinePsf(self.exposure, candidates, metadata)
        self.assertEqual(cm.exception.message, "All PSF candidates removed as blends")
Пример #13
0
    def testHsmPsfMoments(self):
        for width in (2.0, 3.0, 4.0):
            psf = afwDetection.GaussianPsf(35, 35, width)
            exposure = afwImage.ExposureF(45, 56)
            exposure.getMaskedImage().set(1.0, 0, 1.0)
            exposure.setPsf(psf)

            # perform the shape measurement
            msConfig = base.SingleFrameMeasurementConfig()
            msConfig.algorithms.names = ["ext_shapeHSM_HsmPsfMoments"]
            plugin, cat = makePluginAndCat(lsst.meas.extensions.shapeHSM.HsmPsfMomentsAlgorithm,
                                           "ext_shapeHSM_HsmPsfMoments", centroid="centroid",
                                           control=lsst.meas.extensions.shapeHSM.HsmPsfMomentsControl())
            source = cat.addNew()
            source.set("centroid_x", 23)
            source.set("centroid_y", 34)
            offset = afwGeom.Point2I(23, 34)
            tmpSpans = afwGeom.SpanSet.fromShape(int(width), offset=offset)
            source.setFootprint(afwDetection.Footprint(tmpSpans))
            plugin.measure(source, exposure)
            x = source.get("ext_shapeHSM_HsmPsfMoments_x")
            y = source.get("ext_shapeHSM_HsmPsfMoments_y")
            xx = source.get("ext_shapeHSM_HsmPsfMoments_xx")
            yy = source.get("ext_shapeHSM_HsmPsfMoments_yy")
            xy = source.get("ext_shapeHSM_HsmPsfMoments_xy")

            self.assertAlmostEqual(x, 0.0, 3)
            self.assertAlmostEqual(y, 0.0, 3)

            expected = afwEll.Quadrupole(afwEll.Axes(width, width, 0.0))

            self.assertAlmostEqual(xx, expected.getIxx(), SHAPE_DECIMALS)
            self.assertAlmostEqual(xy, expected.getIxy(), SHAPE_DECIMALS)
            self.assertAlmostEqual(yy, expected.getIyy(), SHAPE_DECIMALS)
Пример #14
0
    def run(self, exposure, catalog, flux_key):

        subtracted_exposure = afwImage.ExposureF(exposure, deep=True)
        model = self.modelImage.run(subtracted_exposure, catalog, flux_key)

        for source in catalog:
            with self.modelImage.replaced_source(subtracted_exposure, source,
                                                 flux_key):

                # This parameter is the radius of the spanset
                # Changing the radius doesn't seem to affect SDSS Centroid?
                spanSet = afwGeom.SpanSet.fromShape(3)
                spanSet = spanSet.shiftedBy(Extent2I(source.getCentroid()))
                footprint = afwDetection.Footprint(spanSet)
                peak = footprint.peaks.addNew()
                peak.setFx(source.getCentroid().getX())
                peak.setFy(source.getCentroid().getY())

                # Check for NaNs
                if (source.getCentroid().getX() == source.getCentroid().getX()
                    ):
                    peak.setIx(int(source.getCentroid().getX()))
                    peak.setIy(int(source.getCentroid().getY()))
                source.setFootprint(footprint)

                try:
                    self.sdssCentroid.measure(source, subtracted_exposure)
                except (MeasurementError):
                    pass
Пример #15
0
    def testCopyWithinFootprintOutside(self):
        """Copy a footprint that is larger than the image"""
        target = afwImage.ImageF(100, 100)
        target.set(0)
        subTarget = afwImage.ImageF(
            target,
            lsst.geom.Box2I(lsst.geom.Point2I(40, 40),
                            lsst.geom.Extent2I(20, 20)))
        source = afwImage.ImageF(10, 30)
        source.setXY0(45, 45)
        source.set(1.0)

        foot = afwDetect.Footprint()
        spanList = [
            afwGeom.Span(*s) for s in (
                (
                    50, 50, 60
                ),  # Oversized on the source image, right; only some pixels overlap
                (
                    60, 0, 100
                ),  # Oversized on the source, left and right; and on sub-target image, top
                (
                    99, 0, 1000
                ),  # Oversized on the source image, top, left and right; aiming for segfault
            )
        ]
        foot.spans = afwGeom.SpanSet(spanList)

        foot.spans.clippedTo(subTarget.getBBox()).clippedTo(source.getBBox()).\
            copyImage(source, subTarget)

        expected = np.zeros((100, 100))
        expected[50, 50:55] = 1.0

        self.assertTrue(np.all(target.getArray() == expected))
Пример #16
0
    def testSplit(self):
        spanList = [
            afwGeom.Span(0, 2, 4),
            afwGeom.Span(1, 2, 4),
            afwGeom.Span(2, 2, 4),
            afwGeom.Span(10, 4, 7),
            afwGeom.Span(11, 4, 7),
            afwGeom.Span(12, 4, 7)
        ]

        spans = afwGeom.SpanSet(spanList)
        region = lsst.geom.Box2I(lsst.geom.PointI(-6, -6),
                                 lsst.geom.PointI(20, 20))
        multiFoot = afwDet.Footprint(spans, region)

        records = [multiFoot.addPeak(3, 1, 100), multiFoot.addPeak(5, 11, 100)]

        # Verify that the footprint is multi-component
        self.assertFalse(multiFoot.isContiguous())

        footprintList = multiFoot.split()

        self.assertEqual(len(footprintList), 2)
        for i, fp in enumerate(footprintList):
            # check that the correct Spans are populated for each
            tempSpan = afwGeom.SpanSet(spanList[i * 3:i * 3 + 3])
            self.assertEqual(fp.spans, tempSpan)

            # check that the peaks are split properly
            self.assertEqual(len(fp.peaks), 1)
            self.assertEqual(fp.peaks[0], records[i])
Пример #17
0
def centroidsToCatalog(centroids, expWcs, transientsOnly=False):
    schema = afwTable.SourceTable.makeMinimalSchema()
    centroidKey = afwTable.Point2DKey.addFields(schema, 'centroid', 'centroid',
                                                'pixel')
    schema.getAliasMap().set('slot_Centroid', 'centroid')
    #schema.addField('centroid_x', type=float, doc='x pixel coord')
    #schema.addField('centroid_y', type=float, doc='y pixel coord')
    schema.addField('inputFlux_template',
                    type=float,
                    doc='input flux in template')
    schema.addField('inputFlux_science',
                    type=float,
                    doc='input flux in science image')
    table = afwTable.SourceTable.make(schema)
    sources = afwTable.SourceCatalog(table)

    footprint_radius = 5  # pixels

    for row in centroids:
        if transientsOnly and row[2] != 0.:
            continue
        record = sources.addNew()
        coord = expWcs.pixelToSky(row[0], row[1])
        record.setCoord(coord)
        record.set(centroidKey, afwGeom.Point2D(row[0], row[1]))
        record.set('inputFlux_template', row[2])
        record.set('inputFlux_science', row[3])

        fpCenter = afwGeom.Point2I(afwGeom.Point2D(
            row[0], row[1]))  #expWcs.skyToPixel(coord))
        footprint = afwDetection.Footprint(fpCenter, footprint_radius)
        record.setFootprint(footprint)

    sources = sources.copy(deep=True)  # make it contiguous
    return sources
Пример #18
0
    def getSkySourceFootprints(self, mergedList, skyInfo, seed):
        """!
        @brief Return a list of Footprints of sky objects which don't overlap with anything in mergedList

        @param mergedList  The merged Footprints from all the input bands
        @param skyInfo     A description of the patch
        @param seed        Seed for the random number generator
        """
        mask = afwImage.Mask(skyInfo.patchInfo.getOuterBBox())
        detected = mask.getPlaneBitMask("DETECTED")
        for s in mergedList:
            s.getFootprint().spans.setMask(mask, detected)

        footprints = self.skyObjects.run(mask, seed)
        if not footprints:
            return footprints

        # Need to convert the peak catalog's schema so we can set the "merge_peak_<skyFilterName>" flags
        schema = self.merged.getPeakSchema()
        mergeKey = schema.find("merge_peak_%s" % self.config.skyFilterName).key
        converted = []
        for oldFoot in footprints:
            assert len(oldFoot.getPeaks()) == 1, "Should be a single peak only"
            peak = oldFoot.getPeaks()[0]
            newFoot = afwDetect.Footprint(oldFoot.spans, schema)
            newFoot.addPeak(peak.getFx(), peak.getFy(), peak.getPeakValue())
            newFoot.getPeaks()[0].set(mergeKey, True)
            converted.append(newFoot)

        return converted
Пример #19
0
    def testCopyWithinFootprintOutside(self):
        """Copy a footprint that is larger than the image"""
        target = afwImage.ImageF(100, 100)
        target.set(0)
        subTarget = afwImage.ImageF(
            target,
            afwGeom.Box2I(afwGeom.Point2I(40, 40), afwGeom.Extent2I(20, 20)))
        source = afwImage.ImageF(10, 30)
        source.setXY0(45, 45)
        source.set(1.0)

        foot = afwDetect.Footprint()
        foot.addSpan(
            50, 50, 60
        )  # Oversized on the source image, right; only some pixels overlap
        foot.addSpan(
            60, 0, 100
        )  # Oversized on the source, left and right; and on sub-target image, top
        foot.addSpan(
            99, 0, 1000
        )  # Oversized on the source image, top, left and right; aiming for segfault

        afwDetect.copyWithinFootprintImage(foot, source, subTarget)

        expected = np.zeros((100, 100))
        expected[50, 50:55] = 1.0

        self.assertTrue(np.all(target.getArray() == expected))
Пример #20
0
    def attachTransformedFootprints(self, sources, refCat, exposure, expWcs):
        """Default implementation for attaching Footprints to blank sources prior to measurement
        Footprints for forced photometry must be in the pixel coordinate system of the image being
        measured, while we want to use RA, Dec position from an external catalog.
        This implementation takes RA, Dec from an external catalog, a fixed radius,
        and creates and sets footprints in the exposure's pixel system.
        Note that ForcedPhotImageTask delegates to this method in its own attachFootprints method.
        attachFootprints can then be overridden by its subclasses to define how their Footprints
        should be generated.
        See the documentation for run() for information about the relationships between run(),
        generateMeasCat(), and attachTransformedFootprints().
        """
        footprint_radius = 5  # pixels

        for srcRecord, refRecord in zip(sources, refCat):

            # Add footprints
            #  See https://community.lsst.org/t/how-do-i-do-forced-photometry-on-a-set-of-ra-dec/1074/9
            # From TallJimbo (Jim Bosch)
            # "There's a Footprint constructor that takes an integer position and a radius,
            #  so I think something like this should work:"
            # coord = lsst.afw.coord.IcrsCoord(lsst.afw.geom.Point2D(ra, dec), lsst.afw.geom.degrees)
            # fpCenter = lsst.afw.geom.Point2I(wcs.skyToPixel(coord))
            # footprint = lsst.afw.detection.Footprint(fpCenter, radius)

            # coord = afwCoord.IcrsCoord(afwGeom.Point2D(row['RA'], row['Dec']), degrees)
            coord = refRecord.getCoord()
            fpCenter = afwGeom.Point2I(expWcs.skyToPixel(coord))
            footprint = afwDetection.Footprint(fpCenter, footprint_radius)
            srcRecord.setFootprint(footprint)
Пример #21
0
    def testTransform(self):
        dims = lsst.geom.Extent2I(512, 512)
        bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), dims)
        radius = 5
        offset = lsst.geom.Extent2D(123, 456)
        crval = lsst.geom.SpherePoint(0, 0, lsst.geom.degrees)
        crpix = lsst.geom.Point2D(0, 0)
        cdMatrix = np.array([1.0e-5, 0.0, 0.0, 1.0e-5])
        cdMatrix.shape = (2, 2)
        source = afwGeom.makeSkyWcs(crval=crval,
                                    crpix=crpix,
                                    cdMatrix=cdMatrix)
        target = afwGeom.makeSkyWcs(crval=crval,
                                    crpix=crpix + offset,
                                    cdMatrix=cdMatrix)
        sourceSpanSet = afwGeom.SpanSet.fromShape(radius,
                                                  afwGeom.Stencil.CIRCLE)
        sourceSpanSet = sourceSpanSet.shiftedBy(12, 34)
        fpSource = afwDetect.Footprint(sourceSpanSet, bbox)

        fpTarget = fpSource.transform(source, target, bbox)

        self.assertEqual(len(fpSource.getSpans()), len(fpTarget.getSpans()))
        self.assertEqual(fpSource.getArea(), fpTarget.getArea())
        imSource = afwImage.ImageU(dims)
        fpSource.spans.setImage(imSource, 1)

        imTarget = afwImage.ImageU(dims)
        fpTarget.spans.setImage(imTarget, 1)

        subSource = imSource.Factory(imSource, fpSource.getBBox())
        subTarget = imTarget.Factory(imTarget, fpTarget.getBBox())
        self.assertTrue(np.all(subSource.getArray() == subTarget.getArray()))

        # make a bbox smaller than the target footprint
        bbox2 = lsst.geom.Box2I(fpTarget.getBBox())
        bbox2.grow(-1)
        fpTarget2 = fpSource.transform(source, target, bbox2)  # this one clips
        fpTarget3 = fpSource.transform(source, target, bbox2,
                                       False)  # this one doesn't
        self.assertTrue(bbox2.contains(fpTarget2.getBBox()))
        self.assertFalse(bbox2.contains(fpTarget3.getBBox()))
        self.assertNotEqual(fpTarget.getArea(), fpTarget2.getArea())
        self.assertEqual(fpTarget.getArea(), fpTarget3.getArea())

        # Test that peakCatalogs get Transformed correctly
        truthList = [(x, y, 10) for x, y in zip(range(-2, 2), range(-1, 3))]
        for value in truthList:
            fpSource.addPeak(*value)
        scaleFactor = 2
        linTrans = lsst.geom.LinearTransform(
            np.array([[scaleFactor, 0], [0, scaleFactor]], dtype=float))
        linTransFootprint = fpSource.transform(linTrans, fpSource.getBBox(),
                                               False)
        for peak, truth in zip(linTransFootprint.peaks, truthList):
            # Multiplied by two because that is the linear transform scaling
            # factor
            self.assertEqual(peak.getIx(), truth[0] * scaleFactor)
            self.assertEqual(peak.getIy(), truth[1] * scaleFactor)
Пример #22
0
    def _fig8Test(self, x1, y1, x2, y2):
        # Construct a "figure of 8" consisting of two circles touching at the
        # centre of an image, then demonstrate that it shrinks correctly.
        # (Helper method for tests below.)
        radius = 3
        imwidth, imheight = 100, 100
        nshrink = 1

        # These are the correct values for footprint sizes given the paramters
        # above.
        circle_npix = 29
        initial_npix = circle_npix * 2 - 1  # touch at one pixel
        shrunk_npix = 26

        box = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                              lsst.geom.Extent2I(imwidth, imheight))

        e1 = afwGeom.Ellipse(afwGeomEllipses.Axes(radius, radius, 0),
                             lsst.geom.Point2D(x1, y1))
        spanSet1 = afwGeom.SpanSet.fromShape(e1)
        f1 = afwDetect.Footprint(spanSet1, box)
        self.assertEqual(f1.getArea(), circle_npix)

        e2 = afwGeom.Ellipse(afwGeomEllipses.Axes(radius, radius, 0),
                             lsst.geom.Point2D(x2, y2))
        spanSet2 = afwGeom.SpanSet.fromShape(e2)
        f2 = afwDetect.Footprint(spanSet2, box)
        self.assertEqual(f2.getArea(), circle_npix)

        initial = afwDetect.mergeFootprints(f1, f2)
        initial.setRegion(
            f2.getRegion())  # merge does not propagate the region
        self.assertEqual(initial_npix, initial.getArea())

        shrunk = afwDetect.Footprint().assign(initial)
        shrunk.erode(nshrink)
        self.assertEqual(shrunk_npix, shrunk.getArea())

        if display:
            idImage = afwImage.ImageU(imwidth, imheight)
            for i, foot in enumerate([initial, shrunk]):
                print(foot.getArea())
                foot.spans.setImage(idImage, i + 1)
            afwDisplay.Display(frame=1).mtv(idImage,
                                            title=self._testMethodName +
                                            " image")
Пример #23
0
    def testSetFromFootprint(self):
        """Test setting mask/image pixels from a Footprint list"""
        mi = afwImage.MaskedImageF(lsst.geom.Extent2I(12, 8))
        im = mi.getImage()
        #
        # Objects that we should detect
        #
        self.objects = []
        self.objects += [Object(10, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])]
        self.objects += [Object(20, [(5, 7, 8), (5, 10, 10), (6, 8, 9)])]
        self.objects += [Object(20, [(6, 3, 3)])]

        im.set(0)                       # clear image
        for obj in self.objects:
            obj.insert(im)

        if False and display:
            ds9.mtv(mi, frame=0)

        ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(15))

        objects = ds.getFootprints()
        afwDetect.setMaskFromFootprintList(mi.getMask(), objects, 0x1)

        self.assertEqual(mi.getMask()[4, 2, afwImage.LOCAL], 0x0)
        self.assertEqual(mi.getMask()[3, 6, afwImage.LOCAL], 0x1)

        self.assertEqual(mi.getImage()[3, 6, afwImage.LOCAL], 20)
        for ft in objects:
            ft.spans.setImage(mi.getImage(), 5.0)
        self.assertEqual(mi.getImage()[4, 2, afwImage.LOCAL], 10)
        self.assertEqual(mi.getImage()[3, 6, afwImage.LOCAL], 5)

        if display:
            ds9.mtv(mi, frame=1)
        #
        # Check Footprint.contains() while we are about it
        #
        self.assertTrue(objects[0].contains(lsst.geom.Point2I(7, 5)))
        self.assertFalse(objects[0].contains(lsst.geom.Point2I(10, 6)))
        self.assertFalse(objects[0].contains(lsst.geom.Point2I(7, 6)))
        self.assertFalse(objects[0].contains(lsst.geom.Point2I(4, 2)))

        self.assertTrue(objects[1].contains(lsst.geom.Point2I(3, 6)))

        # Verify the FootprintSet footprint list setter can accept inputs from
        # the footprint list getter
        # Create a copy of the ds' FootprintList
        dsFpList = ds.getFootprints()
        footprintListCopy = [afwDetect.Footprint().assign(f) for f in dsFpList]
        # Use the FootprintList setter with the output from the getter
        ds.setFootprints(ds.getFootprints()[:-1])
        dsFpListNew = ds.getFootprints()
        self.assertTrue(len(dsFpListNew) == len(footprintListCopy)-1)
        for new, old in zip(dsFpListNew, footprintListCopy[:-1]):
            self.assertEqual(new, old)
Пример #24
0
 def testPeakSort(self):
     footprint = afwDetect.Footprint(
         afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Point2I(10, 10)))
     footprint.addPeak(4, 5, 1)
     footprint.addPeak(3, 2, 5)
     footprint.addPeak(7, 8, -2)
     footprint.addPeak(5, 7, 4)
     footprint.sortPeaks()
     self.assertEqual([peak.getIx() for peak in footprint.getPeaks()],
                      [3, 5, 4, 7])
Пример #25
0
    def setUp(self):
        self.mi = afwImage.MaskedImageF(20, 10)
        self.objectPixelVal = (10, 0x1, 100)

        self.foot = afwDetect.Footprint()
        for y, x0, x1 in [(2, 10, 13), (3, 11, 14)]:
            self.foot.addSpan(y, x0, x1)

            for x in range(x0, x1 + 1):
                self.mi.set(x, y, self.objectPixelVal)
    def runMeasurement(self, algorithmName, imageid, x, y, v):
        """Run the measurement algorithm on an image"""
        # load the test image
        imgFile = os.path.join(self.dataDir, "image.%d.fits" % imageid)
        img = afwImage.ImageF(imgFile)
        img -= self.bkgd
        nx, ny = img.getWidth(), img.getHeight()
        msk = afwImage.Mask(geom.Extent2I(nx, ny), 0x0)
        var = afwImage.ImageF(geom.Extent2I(nx, ny), v)
        mimg = afwImage.MaskedImageF(img, msk, var)
        msk.getArray()[:] = np.where(np.fabs(img.getArray()) < 1.0e-8, msk.getPlaneBitMask("BAD"), 0)

        # Put it in a bigger image, in case it matters
        big = afwImage.MaskedImageF(self.offset + mimg.getDimensions())
        big.getImage().set(0)
        big.getMask().set(0)
        big.getVariance().set(v)
        subBig = afwImage.MaskedImageF(big, geom.Box2I(big.getXY0() + self.offset, mimg.getDimensions()))
        subBig <<= mimg
        mimg = big
        mimg.setXY0(self.xy0)

        exposure = afwImage.makeExposure(mimg)
        cdMatrix = np.array([1.0/(2.53*3600.0), 0.0, 0.0, 1.0/(2.53*3600.0)])
        cdMatrix.shape = (2, 2)
        exposure.setWcs(afwGeom.makeSkyWcs(crpix=geom.Point2D(1.0, 1.0),
                                           crval=geom.SpherePoint(0, 0, geom.degrees),
                                           cdMatrix=cdMatrix))

        # load the corresponding test psf
        psfFile = os.path.join(self.dataDir, "psf.%d.fits" % imageid)
        psfImg = afwImage.ImageD(psfFile)
        psfImg -= self.bkgd

        kernel = afwMath.FixedKernel(psfImg)
        kernelPsf = algorithms.KernelPsf(kernel)
        exposure.setPsf(kernelPsf)

        # perform the shape measurement
        msConfig = base.SingleFrameMeasurementConfig()
        alg = base.SingleFramePlugin.registry[algorithmName].PluginClass.AlgClass
        control = base.SingleFramePlugin.registry[algorithmName].PluginClass.ConfigClass().makeControl()
        msConfig.algorithms.names = [algorithmName]
        # Note: It is essential to remove the floating point part of the position for the
        # Algorithm._apply.  Otherwise, when the PSF is realised it will have been warped
        # to account for the sub-pixel offset and we won't get *exactly* this PSF.
        plugin, table = makePluginAndCat(alg, algorithmName, control, centroid="centroid")
        center = geom.Point2D(int(x), int(y)) + geom.Extent2D(self.offset + geom.Extent2I(self.xy0))
        source = table.makeRecord()
        source.set("centroid_x", center.getX())
        source.set("centroid_y", center.getY())
        source.setFootprint(afwDetection.Footprint(afwGeom.SpanSet(exposure.getBBox(afwImage.PARENT))))
        plugin.measure(source, exposure)

        return source
Пример #27
0
    def testGrow(self):
        """Test growing a footprint"""
        x0, y0 = 20, 20
        width, height = 20, 30
        foot1 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(width, height)),
                                    afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(100, 100)))

        # Add some peaks and check that they get copied into the new grown footprint
        foot1.addPeak(20, 20, 1)
        foot1.addPeak(30, 35, 2)
        foot1.addPeak(25, 45, 3)
        self.assertEqual(len(foot1.getPeaks()), 3)

        bbox1 = foot1.getBBox()

        self.assertEqual(bbox1.getMinX(), x0)
        self.assertEqual(bbox1.getMaxX(), x0 + width - 1)
        self.assertEqual(bbox1.getWidth(), width)

        self.assertEqual(bbox1.getMinY(), y0)
        self.assertEqual(bbox1.getMaxY(), y0 + height - 1)
        self.assertEqual(bbox1.getHeight(), height)

        ngrow = 5
        for isotropic in (True, False):
            foot2 = afwDetect.growFootprint(foot1, ngrow, isotropic)

            # Check that peaks got copied into grown footprint
            self.assertEqual(len(foot2.getPeaks()), 3)
            for peak in foot2.getPeaks():
                self.assertTrue((peak.getIx(), peak.getIy()) in [(20, 20), (30, 35), (25, 45)])

            bbox2 = foot2.getBBox()

            if False and display:
                idImage = afwImage.ImageU(width, height)
                idImage.set(0)

                i = 1
                for foot in [foot1, foot2]:
                    foot.insertIntoImage(idImage, i)
                    i += 1

                metricImage = afwImage.ImageF("foo.fits")
                ds9.mtv(metricImage, frame=1)
                ds9.mtv(idImage)

            # check bbox2
            self.assertEqual(bbox2.getMinX(), x0 - ngrow)
            self.assertEqual(bbox2.getWidth(), width + 2*ngrow)

            self.assertEqual(bbox2.getMinY(), y0 - ngrow)
            self.assertEqual(bbox2.getHeight(), height + 2*ngrow)
            # Check that region was preserved
            self.assertEqual(foot1.getRegion(), foot2.getRegion())
Пример #28
0
    def setUp(self):
        self.mi = afwImage.MaskedImageF(20, 10)
        self.objectPixelVal = (10, 0x1, 100)

        spanList = []
        for y, x0, x1 in [(2, 10, 13), (3, 11, 14)]:
            spanList.append(afwGeom.Span(y, x0, x1))

            for x in range(x0, x1 + 1):
                self.mi[x, y, afwImage.LOCAL] = self.objectPixelVal
        self.foot = afwDetect.Footprint(afwGeom.SpanSet(spanList))
Пример #29
0
    def testGetBBox(self):
        """Check that Footprint.getBBox() returns a copy"""
        x0, y0, w, h = 9, 10, 7, 4
        foot = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(w, h)))
        bbox = foot.getBBox()

        dx, dy = 10, 20
        bbox.shift(afwGeom.Extent2I(dx, dy))

        self.assertEqual(bbox.getMinX(), x0 + dx)
        self.assertEqual(foot.getBBox().getMinX(), x0)
Пример #30
0
 def isMasked(self, footprint, mask):
     """Returns whether the footprint violates the mask limits"""
     size = float(footprint.getArea())
     for maskName, limit in self.config.maskLimits.iteritems():
         maskVal = mask.getPlaneBitMask(maskName)
         unmasked = afwDet.Footprint(footprint)
         unmasked.intersectMask(mask,
                                maskVal)  # footprint of unmasked pixels
         if (size - unmasked.getArea()) / size > limit:
             return True
     return False