Esempio n. 1
0
    def setUp(self):
        # We create an image that has a ramp (unique values for each pixel),
        # with a single high pixel that allows for centering
        self.width, self.height = 50, 50
        self.xcen, self.ycen = self.width // 2, self.height // 2
        self.image = afwImage.ImageF(afwGeom.ExtentI(self.width, self.height))
        for y in range(self.height):
            for x in range(self.width):
                self.image.set(x, y, self.width * y + x)
        self.image.set(self.xcen, self.ycen, 1234567.89)
        self.exp = afwImage.makeExposure(afwImage.makeMaskedImage(self.image))
        self.exp.getMaskedImage().getVariance().set(1.0)
        scale = 0.2 / 3600
        wcs = afwImage.makeWcs(
            afwCoord.Coord(0 * afwGeom.degrees, 0 * afwGeom.degrees),
            afwGeom.Point2D(self.xcen, self.ycen), scale, 0, 0, scale)
        self.exp.setWcs(wcs)

        if display:
            frame = 1
            ds9.mtv(self.exp, frame=frame, title="Single pixel")

        # We will use a GaussianCentroid to tweak the center (it should not, for forced measurement)
        # and a NaiveFlux to measure the single pixel.  We'll start offset from the high pixel,
        # so that a forced measurement should yield a flux of zero, while a measurement that was allowed to
        # center should yield a flux of unity.
        # Note that previous versions used NaiveCentroid, which was so nonrobust that it failed to get
        # right answer when the input value was round-tripped through Wcs and modified by ~1E-8.
        gaussianCentroid = measAlg.GaussianCentroidControl()
        naiveFlux = measAlg.NaiveFluxControl()
        naiveFlux.radius = 0.5
        self.x, self.y = self.xcen - 1, self.ycen - 1

        self.foot = afwDetection.Footprint(afwGeom.Point2I(self.x, self.y), 2)
        self.foot.addPeak(self.x, self.y, float("NaN"))

        schema = afwTable.SourceTable.makeMinimalSchema()
        msb = measAlg.MeasureSourcesBuilder()
        msb.addAlgorithm(naiveFlux)
        msb.setCentroider(gaussianCentroid)
        self.measurer = msb.build(schema)
        self.table = afwTable.SourceTable.make(schema)
        self.table.defineCentroid("centroid.gaussian")

        schemaF = afwTable.SourceTable.makeMinimalSchema()
        msbF = measAlg.MeasureSourcesBuilder("", True)
        msbF.addAlgorithm(naiveFlux)
        msbF.setCentroider(gaussianCentroid)
        self.measurerF = msbF.build(schemaF)
        self.tableF = afwTable.SourceTable.make(schemaF)
        self.tableF.defineCentroid("centroid.gaussian")
    def testApertureMeasure(self):
        mi = afwImage.MaskedImageF(afwGeom.ExtentI(100, 200))
        mi.set(10)
        #
        # Create our measuring engine
        #

        radii = (1.0, 5.0, 10.0)  # radii to use
        fluxes = [50.0, 810.0, 3170.0]  # corresponding correct fluxes

        control = measAlg.ApertureFluxControl()
        control.radii = radii

        exp = afwImage.makeExposure(mi)
        x0, y0 = 1234, 5678
        exp.setXY0(afwGeom.Point2I(x0, y0))

        schema = afwTable.SourceTable.makeMinimalSchema()
        mp = measAlg.MeasureSourcesBuilder().addAlgorithm(control).build(
            schema)
        table = afwTable.SourceTable.make(schema)
        source = table.makeRecord()

        mp.apply(source, exp, afwGeom.Point2D(30 + x0, 50 + y0))
        measured = source[control.name]
        for i, f in enumerate(fluxes):
            self.assertEqual(f, measured[i])
Esempio n. 3
0
 def doMeasure(exposure, config):
     schema = afwTable.SourceTable.makeMinimalSchema()
     shapeFinder = algorithms.MeasureSourcesBuilder().addAlgorithm(
         config.makeControl()).build(schema)
     table = afwTable.SourceTable.make(schema)
     record = table.makeRecord()
     shapeFinder.apply(record, exposure, afwGeom.Point2D(0.0, 0.0))
     return record
    def do_testAstrometry(self, control, bkgd):
        """Test that we can instantiate and play with a centroiding algorithms"""

        x0, y0 = 12345, 54321
        for imageFactory in (
                afwImage.MaskedImageF,
                afwImage.MaskedImageD,
        ):

            im = imageFactory(afwGeom.ExtentI(100, 100))
            im.setXY0(afwGeom.Point2I(x0, y0))
            psf = testLib.makeTestPsf(im)

            exp = afwImage.makeExposure(im)
            exp.setPsf(psf)
            schema = afwTable.SourceTable.makeMinimalSchema()
            centroider = algorithms.MeasureSourcesBuilder().addAlgorithm(
                control).build(schema)

            #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

            im.set(bkgd)
            x, y = 30, 20
            im.set(x, y, (1010, ))

            table = afwTable.SourceTable.make(schema)
            table.defineCentroid(control.name)
            source = table.makeRecord()
            foot = afwDetection.Footprint(exp.getBBox())
            source.setFootprint(foot)

            centroider.apply(source, exp, afwGeom.Point2D(x + x0, y + y0))

            self.assertEqual(x + x0, source.getX())
            self.assertEqual(y + y0, source.getY())
            self.assertFalse(source.get(control.name + ".flags"))

            #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

            im.set(bkgd)
            im.set(10, 20, (1010, ))
            im.set(10, 21, (1010, ))
            im.set(11, 20, (1010, ))
            im.set(11, 21, (1010, ))

            x, y = 10.5 + x0, 20.5 + y0
            centroider.apply(source, exp,
                             afwGeom.Point2D(x + 0.123, y - 0.123))

            self.assertEqual(x, source.getX())
            self.assertEqual(y, source.getY())
            self.assertFalse(source.get(control.name + ".flags"))
Esempio n. 5
0
    def setUp(self):
        self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(100, 100))
        self.mi.set(0, 0x0, 1)
        self.exp = afwImage.makeExposure(self.mi)

        builder = measAlgorithms.MeasureSourcesBuilder()

        for conf in (
                measAlgorithms.NaiveFluxConfig(radius=10.0),
                measAlgorithms.PsfFluxConfig(),
                measAlgorithms.SincFluxConfig(radius2=3.0),
        ):
            builder.addAlgorithm(conf.makeControl())
        self.schema = afwTable.SourceTable.makeMinimalSchema()
        self.measurePhotom = builder.build(self.schema)
    def setUp(self):
        # We create an image that has a ramp (unique values for each pixel),
        # with a single high pixel that allows for centering
        self.width, self.height = 50, 50
        self.xcen, self.ycen = self.width // 2, self.height // 2
        self.image = afwImage.ImageF(afwGeom.ExtentI(self.width, self.height))
        for y in range(self.height):
            for x in range(self.width):
                self.image.set(x, y, self.width * y + x)
        self.image.set(self.xcen, self.ycen, 1234567.89)
        self.exp = afwImage.makeExposure(afwImage.makeMaskedImage(self.image))
        self.exp.getMaskedImage().getVariance().set(1.0)
        scale = 0.2 / 3600
        wcs = afwImage.makeWcs(
            afwCoord.Coord(0 * afwGeom.degrees, 0 * afwGeom.degrees),
            afwGeom.Point2D(self.xcen, self.ycen), scale, 0, 0, scale)
        self.exp.setWcs(wcs)

        if display:
            frame = 1
            ds9.mtv(self.exp, frame=frame, title="Single pixel")

        # We will use a NaiveCentroid (peak over 3x3) to tweak the center (it should not, for forced
        # measurement) and a NaiveFlux to measure the single pixel.  We'll start offset from the high pixel,
        # so that a forced measurement should yield a flux of zero, while a measurement that was allowed to
        # center should yield a flux of unity.
        naiveCentroid = measAlg.NaiveCentroidControl()
        naiveFlux = measAlg.NaiveFluxControl()
        naiveFlux.radius = 0.5
        self.x, self.y = self.xcen - 1, self.ycen - 1

        self.foot = afwDetection.Footprint(afwGeom.Point2I(self.x, self.y), 2)
        peak = afwDetection.Peak(self.x, self.y)
        self.foot.getPeaks().push_back(peak)

        schema = afwTable.SourceTable.makeMinimalSchema()
        msb = measAlg.MeasureSourcesBuilder()
        msb.addAlgorithm(naiveFlux)
        msb.setCentroider(naiveCentroid)
        self.measurer = msb.build(schema)
        self.table = afwTable.SourceTable.make(schema)
        self.table.defineCentroid("centroid.naive")
    def testNaiveMeasure(self):
        mi = afwImage.MaskedImageF(afwGeom.ExtentI(100, 200))
        mi.set(10)
        #
        # Create our measuring engine
        #
        exp = afwImage.makeExposure(mi)
        x0, y0 = 1234, 5678
        exp.setXY0(afwGeom.Point2I(x0, y0))

        control = measAlg.NaiveFluxControl()
        control.radius = 10.0
        schema = afwTable.SourceTable.makeMinimalSchema()
        mp = measAlg.MeasureSourcesBuilder().addAlgorithm(control).build(
            schema)
        table = afwTable.SourceTable.make(schema)
        source = table.makeRecord()
        mp.apply(source, exp, afwGeom.Point2D(30 + x0, 50 + y0))
        flux = 3170.0
        self.assertEqual(source.get(control.name), flux)
    def testMeasureCentroid(self):
        """Test that we can instantiate and play with SillyMeasureCentroid"""

        for imageFactory in (
                afwImage.MaskedImageF,
                afwImage.MaskedImageD,
        ):
            im = imageFactory(afwGeom.ExtentI(100, 100))
            exp = afwImage.makeExposure(im)
            control1 = testLib.SillyCentroidControl()
            control1.name = "silly1"
            control1.priority = 0.0
            control1.param = 0
            control2 = testLib.SillyCentroidControl()
            control2.name = "silly2"
            control2.priority = 1.0
            control2.param = 1
            control3 = testLib.SillyCentroidControl()
            control3.name = "silly3"
            control3.priority = 2.0
            control3.param = 2
            schema = afwTable.SourceTable.makeMinimalSchema()
            builder = algorithms.MeasureSourcesBuilder()
            builder.addAlgorithm(control1)
            builder.addAlgorithm(control2)
            builder.addAlgorithm(control3)
            centroider = builder.build(schema)
            table = afwTable.SourceTable.make(schema)
            source = table.makeRecord()
            x, y = 10, 20
            centroider.apply(source, exp, afwGeom.Point2D(x, y))
            table.defineCentroid(control1.name)
            self.assertEqual(x, source.getX() - 0)
            self.assertEqual(y, source.getY() - 0)
            table.defineCentroid(control2.name)
            self.assertEqual(x, source.getX() - 1)
            self.assertEqual(y, source.getY() - 1)
            table.defineCentroid(control3.name)
            self.assertEqual(x, source.getX() - 2)
            self.assertEqual(y, source.getY() - 2)
    def setUp(self):
        im = afwImage.ImageF(self.monetFile("small.fits"))
        self.mi = afwImage.MaskedImageF(im, afwImage.MaskU(im.getDimensions()),
                                        afwImage.ImageF(im.getDimensions()))
        self.ds = afwDetection.FootprintSet(self.mi,
                                            afwDetection.Threshold(100))

        if display:
            ds9.mtv(self.mi.getImage())
            ds9.erase()

        for foot in self.ds.getFootprints():
            bbox = foot.getBBox()
            x0, y0 = bbox.getMinX(), bbox.getMinY()
            x1, y1 = bbox.getMaxX(), bbox.getMaxY()
            xc = (x0 + x1) / 2.0
            yc = (y0 + y1) / 2.0

            if display:
                ds9.dot("+", xc, yc, ctype=ds9.BLUE)

                if False:
                    x0 -= 0.5
                    y0 -= 0.5
                    x1 += 0.5
                    y1 += 0.5

                    ds9.line([(x0, y0), (x1, y0), (x1, y1), (x0, y1),
                              (x0, y0)],
                             ctype=ds9.RED)

        self.control = algorithms.GaussianCentroidControl()
        schema = afwTable.SourceTable.makeMinimalSchema()
        self.centroider = algorithms.MeasureSourcesBuilder().addAlgorithm(
            self.control).build(schema)
        self.ssMeasured = afwTable.SourceCatalog(schema)
        self.ssMeasured.table.defineCentroid(self.control.name)
        self.ssTruth = afwTable.SourceCatalog(schema)
        self.readTruth(self.monetFile("positions.dat-original"))
Esempio n. 10
0
    def testEllipticalGaussian(self):
        """Test measuring elliptical aperture mags for an elliptical Gaussian"""

        width, height = 200, 200
        xcen, ycen = 0.5 * width, 0.5 * height
        #
        # Make the object
        #
        gal = afwImage.ImageF(afwGeom.ExtentI(width, height))
        a, b, theta = float(10), float(5), 20
        flux = 1e4
        I0 = flux / (2 * math.pi * a * b)

        c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta))
        for y in range(height):
            for x in range(width):
                dx, dy = x - xcen, y - ycen
                u = c * dx + s * dy
                v = -s * dx + c * dy
                val = I0 * math.exp(-0.5 * ((u / a)**2 + (v / b)**2))
                if val < 0:
                    val = 0
                gal.set(x, y, val)

        objImg = afwImage.makeExposure(afwImage.makeMaskedImage(gal))
        del gal

        if display:
            frame = 0
            ds9.mtv(objImg, frame=frame, title="Elliptical")

        self.assertAlmostEqual(
            1.0,
            afwMath.makeStatistics(objImg.getMaskedImage().getImage(),
                                   afwMath.SUM).getValue() / flux)
        #
        # Now measure some annuli
        #
        sincConfig = measAlgorithms.SincFluxConfig(radius1=0.0,
                                                   radius2=0.0,
                                                   angle=math.radians(theta),
                                                   ellipticity=(1 - b / a))
        for r1, r2 in [
            (0., 0.45 * a),
            (0.45 * a, 1.0 * a),
            (1.0 * a, 2.0 * a),
            (2.0 * a, 3.0 * a),
            (3.0 * a, 5.0 * a),
            (3.0 * a, 10.0 * a),
        ]:
            sincConfig.radius1 = r1
            sincConfig.radius2 = r2
            schema = afwTable.SourceTable.makeMinimalSchema()
            mp = measAlgorithms.MeasureSourcesBuilder().addAlgorithm(
                sincConfig.makeControl()).build(schema)

            if display:  # draw the inner and outer boundaries of the aperture
                Mxx = 1
                Myy = (b / a)**2

                mxx, mxy, myy = c**2 * Mxx + s**2 * Myy, c * s * (
                    Mxx - Myy), s**2 * Mxx + c**2 * Myy
                for r in (r1, r2):
                    ds9.dot("@:%g,%g,%g" %
                            (r**2 * mxx, r**2 * mxy, r**2 * myy),
                            xcen,
                            ycen,
                            frame=frame)

            table = afwTable.SourceTable.make(schema)
            source = table.makeRecord()
            center = afwGeom.Point2D(xcen, ycen)

            mp.apply(source, objImg, center)

            self.assertAlmostEqual(
                math.exp(-0.5 * (r1 / a)**2) - math.exp(-0.5 * (r2 / a)**2),
                source["flux.sinc"] / flux, 5)
    def testPixelFlags(self):
        width, height = 100, 100
        mi = afwImage.MaskedImageF(width, height)
        exp = afwImage.makeExposure(mi)
        mi.getImage().set(0)
        mask = mi.getMask()
        sat = mask.getPlaneBitMask('SAT')
        interp = mask.getPlaneBitMask('INTRP')
        edge = mask.getPlaneBitMask('EDGE')
        bad = mask.getPlaneBitMask('BAD')
        mask.set(0)
        mask.set(20, 20, sat)
        mask.set(60, 60, interp)
        mask.set(40, 20, bad)
        mask.Factory(
            mask,
            afwGeom.Box2I(afwGeom.Point2I(0, 0),
                          afwGeom.Extent2I(3, height))).set(edge)

        x0, y0 = 1234, 5678
        exp.setXY0(afwGeom.Point2I(x0, y0))

        control = measAlg.PixelFlagControl()
        schema = afwTable.SourceTable.makeMinimalSchema()
        mp = measAlg.MeasureSourcesBuilder().addAlgorithm(control).build(
            schema)
        table = afwTable.SourceTable.make(schema)

        allFlags = [
            "flags.pixel.edge",
            "flags.pixel.bad",
            "flags.pixel.saturated.center",
            "flags.pixel.saturated.any",
            "flags.pixel.interpolated.center",
            "flags.pixel.interpolated.any",
        ]
        for x, y, setFlags in [
            (1, 50, ["flags.pixel.edge"]),
            (40, 20, ["flags.pixel.bad"]),
            (20, 20,
             ["flags.pixel.saturated.center", "flags.pixel.saturated.any"]),
            (20, 22, ["flags.pixel.saturated.any"]),
            (60, 60, [
                "flags.pixel.interpolated.center",
                "flags.pixel.interpolated.any"
            ]),
            (60, 62, ["flags.pixel.interpolated.any"]),
            (float("NAN"), 50, ["flags.pixel.edge"]),
        ]:
            source = table.makeRecord()
            foot = afwDetection.Footprint(
                afwGeom.Point2I(afwGeom.Point2D(x + x0, y + y0)), 5)
            source.setFootprint(foot)
            mp.apply(source, exp, afwGeom.Point2D(x + x0, y + y0))
            for flag in allFlags:
                value = source.get(flag)
                if flag in setFlags:
                    self.assertTrue(
                        value,
                        "Flag %s should be set for %f,%f" % (flag, x, y))
                else:
                    self.assertFalse(
                        value,
                        "Flag %s should not be set for %f,%f" % (flag, x, y))
    def testPeakLikelihoodFlux(self):
        """Test measurement with PeakLikelihoodFlux
        """
        # make mp: a flux measurer
        measControl = measAlg.PeakLikelihoodFluxControl()
        schema = afwTable.SourceTable.makeMinimalSchema()
        mp = measAlg.MeasureSourcesBuilder().addAlgorithm(measControl).build(
            schema)

        # make and measure a series of exposures containing just one star, approximately centered
        bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(100, 101))
        kernelWidth = 35
        var = 100
        fwhm = 3.0
        sigma = fwhm / FwhmPerSigma
        convolutionControl = afwMath.ConvolutionControl()
        psf = measAlg.SingleGaussianPsf(kernelWidth, kernelWidth, sigma)
        psfKernel = psf.getLocalKernel()
        psfImage = psf.computeKernelImage()
        sumPsfSq = numpy.sum(psfImage.getArray()**2)
        psfSqArr = psfImage.getArray()**2
        for flux in (1000, 10000):
            ctrInd = afwGeom.Point2I(50, 51)
            ctrPos = afwGeom.Point2D(ctrInd)

            kernelBBox = psfImage.getBBox(afwImage.PARENT)
            kernelBBox.shift(afwGeom.Extent2I(ctrInd))

            # compute predicted flux error
            unshMImage = makeFakeImage(bbox, [ctrPos], [flux], fwhm, var)

            # filter image by PSF
            unshFiltMImage = afwImage.MaskedImageF(
                unshMImage.getBBox(afwImage.PARENT))
            afwMath.convolve(unshFiltMImage, unshMImage, psfKernel,
                             convolutionControl)

            # compute predicted flux = value of image at peak / sum(PSF^2)
            # this is a sanity check of the algorithm, as much as anything
            predFlux = unshFiltMImage.getImage().get(ctrInd[0],
                                                     ctrInd[1]) / sumPsfSq
            self.assertLess(abs(flux - predFlux), flux * 0.01)

            # compute predicted flux error based on filtered pixels
            # = sqrt(value of filtered variance at peak / sum(PSF^2)^2)
            predFluxErr = math.sqrt(unshFiltMImage.getVariance().get(
                ctrInd[0], ctrInd[1])) / sumPsfSq

            # compute predicted flux error based on unfiltered pixels
            # = sqrt(sum(unfiltered variance * PSF^2)) / sum(PSF^2)
            # and compare to that derived from filtered pixels;
            # again, this is a test of the algorithm
            varView = afwImage.ImageF(unshMImage.getVariance(), kernelBBox)
            varArr = varView.getArray()
            unfiltPredFluxErr = math.sqrt(numpy.sum(
                varArr * psfSqArr)) / sumPsfSq
            self.assertLess(abs(unfiltPredFluxErr - predFluxErr),
                            predFluxErr * 0.01)

            for fracOffset in (afwGeom.Extent2D(0, 0),
                               afwGeom.Extent2D(0.2, -0.3)):
                adjCenter = ctrPos + fracOffset
                if fracOffset == (0, 0):
                    maskedImage = unshMImage
                    filteredImage = unshFiltMImage
                else:
                    maskedImage = makeFakeImage(bbox, [adjCenter], [flux],
                                                fwhm, var)
                    # filter image by PSF
                    filteredImage = afwImage.MaskedImageF(
                        maskedImage.getBBox(afwImage.PARENT))
                    afwMath.convolve(filteredImage, maskedImage, psfKernel,
                                     convolutionControl)

                exposure = afwImage.makeExposure(filteredImage)
                exposure.setPsf(psf)

                table = afwTable.SourceTable.make(schema)
                source = table.makeRecord()
                mp.apply(source, exposure, afwGeom.Point2D(*adjCenter))
                measFlux = source.get(measControl.name)
                measFluxErr = source.get(measControl.name + ".err")
                self.assertFalse(source.get(measControl.name + ".flags"))
                self.assertLess(abs(measFlux - flux), flux * 0.003)

                self.assertLess(abs(measFluxErr - predFluxErr),
                                predFluxErr * 0.2)

                # try nearby points and verify that the flux is smaller;
                # this checks that the sub-pixel shift is performed in the correct direction
                for dx in (-0.2, 0, 0.2):
                    for dy in (-0.2, 0, 0.2):
                        if dx == dy == 0:
                            continue
                        offsetCtr = afwGeom.Point2D(adjCenter[0] + dx,
                                                    adjCenter[1] + dy)
                        table = afwTable.SourceTable.make(schema)
                        source = table.makeRecord()
                        mp.apply(source, exposure, offsetCtr)
                        offsetFlux = source.get(measControl.name)
                        self.assertLess(offsetFlux, measFlux)

        # source so near edge of image that PSF does not overlap exposure should result in failure

        for edgePos in (
            (1, 50),
            (50, 1),
            (50, bbox.getHeight() - 1),
            (bbox.getWidth() - 1, 50),
        ):
            table = afwTable.SourceTable.make(schema)
            source = table.makeRecord()
            mp.apply(source, exposure, afwGeom.Point2D(*edgePos))
            self.assertTrue(source.get(measControl.name + ".flags"))

        # no PSF should result in failure: flags set
        noPsfExposure = afwImage.ExposureF(filteredImage)
        table = afwTable.SourceTable.make(schema)
        source = table.makeRecord()
        mp.apply(source, noPsfExposure, afwGeom.Point2D(*adjCenter))
        self.assertTrue(source.get(measControl.name + ".flags"))
    def testEllipticalGaussian(self):
        """Test measuring the properties of an elliptical Gaussian"""

        width, height = 200, 200
        xcen, ycen = 0.5 * width, 0.5 * height
        #
        # Make the object
        #
        gal = afwImage.ImageF(afwGeom.ExtentI(width, height))
        a, b, theta = float(10), float(5), 20
        flux = 1e4
        I0 = flux / (2 * math.pi * a * b)

        c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta))
        for y in range(height):
            for x in range(width):
                dx, dy = x - xcen, y - ycen
                u = c * dx + s * dy
                v = -s * dx + c * dy
                val = I0 * math.exp(-0.5 * ((u / a)**2 + (v / b)**2))
                if val < 0:
                    val = 0
                gal.set(x, y, val)

        objImg = afwImage.makeExposure(afwImage.makeMaskedImage(gal))
        objImg.getMaskedImage().getVariance().set(1.0)
        del gal
        objImg.setXY0(afwGeom.Point2I(1234, 5678))
        #
        # We need a PSF to be able to centroid well.  Cf. #2540
        #
        FWHM = 5
        ksize = 25  # size of desired kernel
        objImg.setPsf(
            measAlg.DoubleGaussianPsf(ksize, ksize,
                                      FWHM / (2 * math.sqrt(2 * math.log(2))),
                                      1, 0.1))

        if display:
            frame = 0
            ds9.mtv(objImg, frame=frame, title="Elliptical")

        self.assertAlmostEqual(
            1.0,
            afwMath.makeStatistics(objImg.getMaskedImage().getImage(),
                                   afwMath.SUM).getValue() / flux)
        #
        # Test elliptical apertures
        #
        #
        msConfig = measAlg.SourceMeasurementConfig()
        msConfig.algorithms.names.add("flux.aperture.elliptical")
        radii = math.sqrt(a * b) * numpy.array([
            0.45,
            1.0,
            2.0,
            3.0,
            10.0,
        ])

        msConfig.algorithms["flux.aperture.elliptical"].radii = radii
        schema = afwTable.SourceTable.makeMinimalSchema()
        ms = msConfig.makeMeasureSources(schema)

        table = afwTable.SourceTable.make(schema)
        msConfig.slots.setupTable(table)
        source = table.makeRecord()

        ss = afwDetection.FootprintSet(objImg.getMaskedImage(),
                                       afwDetection.Threshold(0.1))
        fp = ss.getFootprints()[0]
        source.setFootprint(fp)

        center = fp.getPeaks()[0].getF()
        ms.apply(source, objImg, center)

        self.assertEqual(source.get("flux.aperture.elliptical.nProfile"),
                         len(radii))

        r0 = 0.0
        if display:
            shape = source.getShape().clone()
            xy = afwGeom.ExtentD(source.getCentroid()) - afwGeom.ExtentD(
                objImg.getXY0())
            ds9.dot("x", xcen, ycen, ctype=ds9.RED)
            ds9.dot("+", *xy, frame=frame)
        with ds9.Buffering():
            for r, apFlux in zip(radii,
                                 source.get("flux.aperture.elliptical")):
                if display:  # draw the inner and outer boundaries of the aperture
                    shape.scale(r / shape.getDeterminantRadius())
                    ds9.dot(shape, *xy, frame=frame)

                trueFlux = flux * (math.exp(-r0**2 / (2 * a * b)) -
                                   math.exp(-r**2 / (2 * a * b)))
                if verbose:
                    print "%5.2f %6.3f%%" % (r, 100 *
                                             ((trueFlux - apFlux) / flux))
                self.assertAlmostEqual(trueFlux / flux, apFlux / flux, 5)
                r0 = r
        #
        # Now measure some annuli "by hand" (we'll repeat this will EllipticalAperture algorithm soon)
        #

        for r1, r2 in [
            (0.0, 0.45 * a),
            (0.45 * a, 1.0 * a),
            (1.0 * a, 2.0 * a),
            (2.0 * a, 3.0 * a),
            (3.0 * a, 5.0 * a),
            (3.0 * a, 10.0 * a),
        ]:
            control = measAlg.SincFluxControl()
            control.radius1 = r1
            control.radius2 = r2
            control.angle = math.radians(theta)
            control.ellipticity = 1 - b / a

            schema = afwTable.SourceTable.makeMinimalSchema()
            mp = measAlg.MeasureSourcesBuilder().addAlgorithm(control).build(
                schema)
            table = afwTable.SourceTable.make(schema)
            source = table.makeRecord()

            if display:  # draw the inner and outer boundaries of the aperture
                Mxx = 1
                Myy = (b / a)**2

                mxx, mxy, myy = c**2 * Mxx + s**2 * Myy, c * s * (
                    Mxx - Myy), s**2 * Mxx + c**2 * Myy
                for r in (r1, r2):
                    ds9.dot("@:%g,%g,%g" %
                            (r**2 * mxx, r**2 * mxy, r**2 * myy),
                            xcen,
                            ycen,
                            frame=frame)

            mp.apply(source, objImg, center)

            self.assertAlmostEqual(
                math.exp(-0.5 * (r1 / a)**2) - math.exp(-0.5 * (r2 / a)**2),
                source.get(control.name) / flux, 5)

        control = measAlg.GaussianFluxControl()

        schema = afwTable.SourceTable.makeMinimalSchema()
        mp = measAlg.MeasureSourcesBuilder().addAlgorithm(control).build(
            schema)
        table = afwTable.SourceTable.make(schema)
        source = table.makeRecord()

        objImg.setPsf(None)  # no Psf
        mp.apply(source, objImg, center)
        # we haven't provided a PSF, so the built-in aperture correction won't work...but we'll get
        # a result anyway
        # Note that flags.psffactor==True sets flags=True IFF we attempt aperture corrections
        self.assertEqual(source.get(control.name + ".flags"), False)
        self.assertEqual(source.get(control.name + ".flags.psffactor"), True)
        gflux = source.get(control.name)
        err = gflux / flux - 1
        if abs(err) > 1.5e-5:
            self.assertEqual(gflux, flux,
                             ("%g, %g: error is %g" % (gflux, flux, err)))
Esempio n. 14
0
    def do_testmeasureShape(self):
        """Test that we can instantiate and play with a measureShape"""

        algorithmName = "shape.sdss"
        algorithmConfig = algorithms.SdssShapeConfig()

        im = afwImage.ImageF(afwGeom.ExtentI(100))
        msk = afwImage.MaskU(im.getDimensions())
        msk.set(0)
        var = afwImage.ImageF(im.getDimensions())
        var.set(10)
        mi = afwImage.MaskedImageF(im, msk, var)
        del im
        del msk
        del var
        exp = afwImage.makeExposure(mi)

        #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
        #
        # Add a Gaussian to the image
        #
        for a, b, phi, tol in [  # n.b. phi in degrees
            (2.5, 1.5, 90.0, 1e-3),
            (1.5, 2.5, 0.0, 1e-3),
            (1.5, 2.5, 45.0, 1e-3),
            (1.5, 2.5, 90.0, 1e-3),
            (3.0, 2.5, 0.0, 1e-3),
            (3.0, 12.5, 0.0, 1e-3),
            (3.0, 12.5, 0.0, 2e-4),
            (1.0, 1.0, 0.0, 4e-3),
            (1.0, 0.75, 0.0, 2e-2),
                #(0.75, 0.75, 0.0, 1e-1),
        ]:
            if b > a:
                a, b = b, a
                phi -= 90
            a, b, phi = float(a), float(b), math.radians(phi)

            im = mi.getImage()
            bkgd = 100.0
            x, y = 30, 40  # centre of object
            im[:] = bkgd

            axes = afwGeom.ellipses.Axes(a, b, phi, True)
            quad = afwGeom.ellipses.Quadrupole(axes)
            if False:
                a0, b0 = a, b
                pixellatedAxes = axes.convolve(
                    afwGeom.ellipses.Quadrupole(1 / 6.0, 1 / 6.0))
                a, b = pixellatedAxes.getA(), pixellatedAxes.getB()
                print a, b, a0, b0
            sigma_xx, sigma_yy, sigma_xy = quad.getIxx(), quad.getIyy(
            ), quad.getIxy()

            ksize = 2 * int(4 * max(a, b)) + 1
            c, s = math.cos(phi), math.sin(phi)

            sum, sumxx, sumxy, sumyy = 4 * [0.0] if False else 4 * [None]
            for dx in range(-ksize / 2, ksize / 2 + 1):
                for dy in range(-ksize / 2, ksize / 2 + 1):
                    u, v = c * dx + s * dy, s * dx - c * dy
                    I = 1000 * math.exp(-0.5 * ((u / a)**2 + (v / b)**2))
                    im[x + dx, y + dy] += I

                    if sum is not None:
                        sum += I
                        sumxx += I * dx * dx
                        sumxy += I * dx * dy
                        sumyy += I * dy * dy

            if sum is not None:
                sumxx /= sum
                sumxy /= sum
                sumyy /= sum
                print "RHL %g %g %g" % (sumxx, sumyy, sumxy)

            algorithmConfig.background = bkgd
            schema = afwTable.SourceTable.makeMinimalSchema()
            shapeFinder = algorithms.MeasureSourcesBuilder()\
                .addAlgorithm(algorithmConfig.makeControl())\
                .build(schema)

            if display:
                ds9.mtv(im)

            table = afwTable.SourceTable.make(schema)
            table.defineShape(algorithmName)
            table.defineCentroid(algorithmName + ".centroid")
            source = table.makeRecord()
            center = afwGeom.Point2D(x, y)

            shapeFinder.apply(source, exp, center)

            if False:
                Ixx, Iyy, Ixy = source.getIxx(), source.getIyy(
                ), source.getIxy()
                A2 = 0.5 * (Ixx + Iyy) + math.sqrt((0.5 *
                                                    (Ixx - Iyy))**2 + Ixy**2)
                B2 = 0.5 * (Ixx + Iyy) - math.sqrt((0.5 *
                                                    (Ixx - Iyy))**2 + Ixy**2)

                print "I_xx:  %.5f %.5f" % (Ixx, sigma_xx)
                print "I_xy:  %.5f %.5f" % (Ixy, sigma_xy)
                print "I_yy:  %.5f %.5f" % (Iyy, sigma_yy)
                print "A2, B2 = %.5f, %.5f" % (A2, B2)

            self.assertTrue(
                abs(x - source.getX()) < 1e-4, "%g v. %g" % (x, source.getX()))
            self.assertTrue(
                abs(y - source.getY()) < 1e-4, "%g v. %g" % (y, source.getY()))
            self.assertTrue(
                abs(source.getIxx() - sigma_xx) < tol * (1 + sigma_xx),
                "%g v. %g" % (sigma_xx, source.getIxx()))
            self.assertTrue(
                abs(source.getIxy() - sigma_xy) < tol * (1 + abs(sigma_xy)),
                "%g v. %g" % (sigma_xy, source.getIxy()))
            self.assertTrue(
                abs(source.getIyy() - sigma_yy) < tol * (1 + sigma_yy),
                "%g v. %g" % (sigma_yy, source.getIyy()))
Esempio n. 15
0
def showKernelMosaic(bbox, kernel, nx=7, ny=None, frame=None, title=None, 
                     showCenter=True, showEllipticity=True):
    """Show a mosaic of Kernel images.
    """
    mos = displayUtils.Mosaic()

    x0 = bbox.getBeginX()
    y0 = bbox.getBeginY()
    width = bbox.getWidth()
    height = bbox.getHeight()

    if not ny:
        ny = int(nx*float(height)/width + 0.5)
        if not ny:
            ny = 1

    schema = afwTable.SourceTable.makeMinimalSchema()
    control = measAlg.GaussianCentroidControl()
    centroider = measAlg.MeasureSourcesBuilder().addAlgorithm(control).build(schema)
    sdssShape = measAlg.SdssShapeControl()
    shaper = measAlg.MeasureSourcesBuilder().addAlgorithm(sdssShape).build(schema)
    table = afwTable.SourceTable.make(schema)
    table.defineCentroid(control.name)
    table.defineShape(sdssShape.name)

    centers = []
    shapes = []
    for iy in range(ny):
        for ix in range(nx):
            x = int(ix*(width-1)/(nx-1)) + x0
            y = int(iy*(height-1)/(ny-1)) + y0

            im = afwImage.ImageD(kernel.getDimensions())
            ksum = kernel.computeImage(im, False, x, y)
            lab = "Kernel(%d,%d)=%.2f" % (x, y, ksum) if False else ""
            mos.append(im, lab)

            exp = afwImage.makeExposure(afwImage.makeMaskedImage(im))
            w, h = im.getWidth(), im.getHeight()
            cen = afwGeom.PointD(w//2, h//2)
            src = table.makeRecord()
            foot = afwDet.Footprint(exp.getBBox())
            src.setFootprint(foot)

            centroider.apply(src, exp, cen)
            centers.append((src.getX(), src.getY()))

            shaper.apply(src, exp, cen)
            shapes.append((src.getIxx(), src.getIxy(), src.getIyy()))

    mos.makeMosaic(frame=frame, title=title if title else "Model Kernel", mode=nx)

    if centers and frame is not None:
        i = 0
        with ds9.Buffering():
            for cen, shape in zip(centers, shapes):
                bbox = mos.getBBox(i); i += 1
                xc, yc = cen[0] + bbox.getMinX(),  cen[1] + bbox.getMinY()
                if showCenter:
                    ds9.dot("+", xc, yc,  ctype=ds9.BLUE, frame=frame)

                if showEllipticity:
                    ixx, ixy, iyy = shape
                    ds9.dot("@:%g,%g,%g" % (ixx, ixy, iyy), xc, yc, frame=frame, ctype=ds9.RED)

    return mos