コード例 #1
0
    def testMeasureCentroid(self):
        """Test that we can use our silly centroid through the usual Tasks"""
        algorithms.AlgorithmRegistry.register("centroid.silly",
                                              testLib.SillyCentroidControl)

        x, y = 10, 20

        im = afwImage.MaskedImageF(afwGeom.ExtentI(512, 512))
        im.set(0)
        arr = im.getImage().getArray()
        arr[y, x] = 1
        exp = afwImage.makeExposure(im)

        schema = afwTable.SourceTable.makeMinimalSchema()

        detConfig = algorithms.SourceDetectionConfig()
        detConfig.thresholdValue = 0.5
        detConfig.thresholdType = "value"
        measConfig = algorithms.SourceMeasurementConfig()
        measConfig.algorithms.names.add("centroid.silly")
        measConfig.slots.centroid = "centroid.silly"
        measConfig.algorithms["centroid.silly"].param = 5
        measConfig.doReplaceWithNoise = False

        det = algorithms.SourceDetectionTask(schema=schema, config=detConfig)
        meas = algorithms.SourceMeasurementTask(schema, config=measConfig)

        table = afwTable.SourceTable.make(schema)
        sources = det.makeSourceCatalog(table, exp, doSmooth=False,
                                        sigma=1.0).sources
        self.assertEqual(len(sources), 1)
        meas.run(exp, sources)
        self.assertEqual(len(sources), 1)
        self.assertEqual(sources[0].getY(), y + 5)
コード例 #2
0
    def measure(footprintSet, exposure):
        """Measure a set of Footprints, returning a SourceCatalog"""
        config = measAlg.SourceMeasurementConfig()
        config.prefix = "initial."
        config.algorithms.names = ["flags.pixel", "flux.psf", "flux.sinc", "flux.gaussian", "shape.sdss"]
        config.centroider.name = "centroid.sdss"
        config.algorithms["flux.naive"].radius = 3.0
        config.slots.centroid = "initial.centroid.sdss"
        config.slots.psfFlux = "initial.flux.psf"
        config.slots.apFlux = "initial.flux.sinc"
        config.slots.modelFlux = None
        config.slots.instFlux = None
        config.slots.calibFlux = None
        config.slots.shape = "initial.shape.sdss"

        schema = afwTable.SourceTable.makeMinimalSchema()
        measureSources = config.makeMeasureSources(schema)
        catalog = afwTable.SourceCatalog(schema)
        config.slots.setupTable(catalog.table)

        if display:
            ds9.mtv(exposure, title="Original", frame=0)

        footprintSet.makeSources(catalog)

        for i, source in enumerate(catalog):
            measureSources.applyWithPeak(source, exposure)

        return catalog
コード例 #3
0
def makeSourceMeasurementConfig(nsigma=6.0, nIterForRadius=1, kfac=2.5):
    """Construct a SourceMeasurementConfig with the requested parameters"""
    msConfig = measAlg.SourceMeasurementConfig()
    if False:                       # requires #2546
        msConfig.centroider = None
        msConfig.slots.centroid = None
    msConfig.algorithms.names.add("flux.kron")
    msConfig.algorithms.names.remove("correctfluxes")
    msConfig.algorithms["flux.kron"].nSigmaForRadius = nsigma
    msConfig.algorithms["flux.kron"].nIterForRadius = nIterForRadius
    msConfig.algorithms["flux.kron"].nRadiusForFlux = kfac
    msConfig.algorithms["flux.kron"].enforceMinimumRadius = False
    return msConfig
コード例 #4
0
    def measureRotAngle(self, exposure, x, y):
        """Measure rotation angle quantities using the C++ code"""
        msConfig = measAlg.SourceMeasurementConfig()
        msConfig.algorithms.names.add("rotAngle")
        schema = afwTable.SourceTable.makeMinimalSchema()
        ms = msConfig.makeMeasureSources(schema)
        table = afwTable.SourceTable.make(schema)
        msConfig.slots.setupTable(table)
        source = table.makeRecord()
        fp = afwDetection.Footprint(exposure.getBBox())
        source.setFootprint(fp)
        center = afwGeom.Point2D(x, y)
        ms.apply(source, exposure, center)

        return source.get("rotAngle.north"), source.get("rotAngle.east")
コード例 #5
0
    def mySetup(self, runCentroider=True):
        msConfig = algorithms.SourceMeasurementConfig()
        if not runCentroider:
            msConfig.centroider = None
            msConfig.slots.centroid = None

        schema = afwTable.SourceTable.makeMinimalSchema()
        ms = msConfig.makeMeasureSources(schema)

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

        fp = afwDetection.Footprint(self.exp.getBBox())
        source.setFootprint(fp)
        ms.apply(source, self.exp, afwGeom.Point2D(self.xcen, self.ycen))

        return source
コード例 #6
0
    def setUp(self):
        self.config = measAlg.SourceMeasurementConfig()

        self.config.algorithms.names = ["flux.psf",
                                        "flux.aperture",
                                        "classification.extendedness"]
        self.config.algorithms["flux.aperture"].maxSincRadius = 10.0
        self.config.algorithms["flux.aperture"].radii = [3.0, 6.0, 9.0, 12.0, 15.0, 40, 65.0]
        self.config.slots.psfFlux = "flux.psf"

        schema = afwTable.SourceTable.makeMinimalSchema()
        schema.addField(afwTable.Field[int]("deblend.nchild", ""))

        task = measAlg.SourceMeasurementTask(config=self.config, schema=schema) # adds to schema

        sources = afwTable.SourceCatalog(schema)
        sources.definePsfFlux("flux.psf")
        sources.setMetadata(dafBase.PropertyList())
        sources.getMetadata().set("flux_aperture_radii", self.config.algorithms["flux.aperture"].radii)

        self.schema = schema
        self.sources = sources
コード例 #7
0
    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)))
コード例 #8
0
    def setUp(self):
        self.x0, self.y0 = 0, 0
        self.nx, self.ny = 512, 512  #2048, 4096
        self.sky = 100.0
        self.nObj = 100

        # make a distorter
        # This is a lot of distortion ... from circle r=1, to ellipse with a=1.3 (ie. 30%)
        # For suprimecam, we expect only about 5%
        self.distCoeffs = [0.0, 1.0, 2.0e-04, 3.0e-8]
        lanczosOrder = 3
        coefficientsDistort = True
        self.distorter = cameraGeom.RadialPolyDistortion(
            self.distCoeffs, coefficientsDistort, lanczosOrder)

        # make a detector
        self.detector = cameraUtils.makeDefaultCcd(
            afwGeom.Box2I(afwGeom.Point2I(0, 0),
                          afwGeom.Extent2I(self.nx, self.ny)))
        self.detector.setDistortion(self.distorter)
        self.detector.setCenter(cameraGeom.FpPoint(
            255.5, 255.5))  # move boresight from center to 0,0

        if False:
            for x, y in [(0, 0), (0, 511), (511, 0), (511, 511)]:
                p = afwGeom.Point2D(x, y)
                iqq = self.distorter.distort(p, geomEllip.Quadrupole(),
                                             self.detector)
                print x, y, geomEllip.Axes(iqq)
                print self.detector.getPositionFromPixel(p).getMm()

        print "Max distortion on this detector: ", self.distorter.computeMaxShear(
            self.detector)

        # detection policies
        self.detConfig = measAlg.SourceDetectionConfig()

        # measurement policies
        self.measSrcConfig = measAlg.SourceMeasurementConfig()

        # psf star selector
        starSelectorFactory = measAlg.starSelectorRegistry["secondMoment"]
        starSelectorConfig = starSelectorFactory.ConfigClass()
        starSelectorConfig.fluxLim = 5000.0
        starSelectorConfig.histSize = 32
        starSelectorConfig.clumpNSigma = 1.0
        starSelectorConfig.badFlags = []
        self.starSelector = starSelectorFactory(starSelectorConfig)

        # psf determiner
        psfDeterminerFactory = measAlg.psfDeterminerRegistry["pca"]
        psfDeterminerConfig = psfDeterminerFactory.ConfigClass()
        width, height = self.nx, self.ny
        nEigenComponents = 3
        psfDeterminerConfig.sizeCellX = width // 3
        psfDeterminerConfig.sizeCellY = height // 3
        psfDeterminerConfig.nEigenComponents = nEigenComponents
        psfDeterminerConfig.spatialOrder = 1
        psfDeterminerConfig.kernelSizeMin = 31
        psfDeterminerConfig.nStarPerCell = 0
        psfDeterminerConfig.nStarPerCellSpatialFit = 0  # unlimited
        self.psfDeterminer = psfDeterminerFactory(psfDeterminerConfig)
コード例 #9
0
    def test2(self):
        # Check that doReplaceWithNoise works with deblended source
        # hierarchies.
        seed = 42
        rand = afwMath.Random(afwMath.Random.MT19937, seed)

        psf = self.getpsf()
        im = afwImage.ImageF(200, 50)
        skystd = 100
        afwMath.randomGaussianImage(im, rand)
        im *= skystd
        imorig = afwImage.ImageF(im, True)
        noiseim = imorig

        mi = afwImage.MaskedImageF(im)
        mi.getVariance().set(skystd**2)
        exposure = afwImage.makeExposure(mi)
        exposure.setPsf(psf)

        detconf = measAlg.SourceDetectionConfig()
        detconf.returnOriginalFootprints = True
        detconf.reEstimateBackground = False
        measconf = measAlg.SourceMeasurementConfig()
        measconf.doReplaceWithNoise = True
        measconf.replaceWithNoise.noiseSeed = 42

        schema = afwTable.SourceTable.makeMinimalSchema()
        detect = measAlg.SourceDetectionTask(config=detconf, schema=schema)
        measure = MySourceMeasurementTask(config=measconf,
                                          schema=schema,
                                          doplot=plots)
        table = afwTable.SourceTable.make(schema)
        table.preallocate(10)

        # We're going to fake up a perfect deblend hierarchy here, by
        # creating individual images containing single sources and
        # measuring them, and then creating a deblend hierarchy where
        # the children have the correct HeavyFootprints.  We want to
        # find that the measurements on the deblend hierarchy and the
        # blended image are equal to the individual images.
        #
        # Note that in the normal setup we don't expect the
        # measurements to be *identical* because of the faint wings of
        # the objects; when measuring a deblended child, we pick up
        # the wings of the other objects.
        #
        # In order to get exactly equal measurements, we'll fake some
        # sources that have no wings -- we'll copy just the source
        # pixels within the footprint.  This means that all the
        # footprints are the same, and the pixels inside the footprint
        # are the same.

        fullim = None
        sources = None
        # "normal" measurements
        xx0, yy0, vx0, vy0 = [], [], [], []
        # "no-wing" measurements
        xx1, yy1, vx1, vy1 = [], [], [], []

        y = 25
        for i in range(5):
            # no-noise source image
            sim = afwImage.ImageF(imorig.getWidth(), imorig.getHeight())
            # Put all four sources in the parent (i==0), and one
            # source in each child (i=[1 to 4])
            if i in [0, 1]:
                addPsf(sim, psf, 20, y, 1000)
            if i in [0, 2]:
                addGaussian(sim, 40, y, 10, 3, 2e5)
            if i in [0, 3]:
                addGaussian(sim, 75, y, 10, 3, 2e5)
            if i in [0, 4]:
                addPsf(sim, psf, 95, y, 1000)
            imcopy = afwImage.ImageF(imorig, True)
            imcopy += sim
            # copy the pixels into the exposure object
            im <<= imcopy

            if i == 0:
                detected = detect.makeSourceCatalog(table, exposure)
                sources = detected.sources
                print 'detected', len(sources), 'sources'
                self.assertEqual(len(sources), 1)
            else:
                fpSets = detect.detectFootprints(exposure)
                print 'detected', fpSets.numPos, 'sources'
                fpSets.positive.makeSources(sources)
                self.assertEqual(fpSets.numPos, 1)
                print len(sources), 'sources total'

            measure.plotpat = 'single-%i.png' % i
            measure.run(exposure, sources[-1:])
            s = sources[-1]
            fp = s.getFootprint()
            if i == 0:
                # This is the blended image
                fullim = imcopy
            else:
                print 'Creating heavy footprint...'
                heavy = afwDet.makeHeavyFootprint(fp, mi)
                s.setFootprint(heavy)

            # Record the single-source measurements.
            xx0.append(s.getX())
            yy0.append(s.getY())
            vx0.append(s.getIxx())
            vy0.append(s.getIyy())

            # "no-wings": add just the source pixels within the footprint
            im <<= sim
            h = afwDet.makeHeavyFootprint(fp, mi)
            sim2 = afwImage.ImageF(imorig.getWidth(), imorig.getHeight())
            h.insert(sim2)
            imcopy = afwImage.ImageF(imorig, True)
            imcopy += sim2
            im <<= imcopy
            measure.plotpat = 'single2-%i.png' % i
            measure.run(exposure, sources[i:i + 1], noiseImage=noiseim)
            s = sources[i]
            xx1.append(s.getX())
            yy1.append(s.getY())
            vx1.append(s.getIxx())
            vy1.append(s.getIyy())
            if i == 0:
                fullim2 = imcopy

        # Now we'll build the fake deblended hierarchy.
        parent = sources[0]
        kids = sources[1:]
        # Ensure that the parent footprint contains all the child footprints
        pfp = parent.getFootprint()
        for s in kids:
            for span in s.getFootprint().getSpans():
                pfp.addSpan(span)
        pfp.normalize()
        #parent.setFootprint(pfp)
        # The parent-child relationship is established through the IDs
        parentid = parent.getId()
        for s in kids:
            s.setParent(parentid)

        # Reset all the measurements
        shkey = sources.getTable().getShapeKey()
        ckey = sources.getTable().getCentroidKey()
        for s in sources:
            sh = s.get(shkey)
            sh.setIxx(np.nan)
            sh.setIyy(np.nan)
            sh.setIxy(np.nan)
            s.set(shkey, sh)
            c = s.get(ckey)
            c.setX(np.nan)
            c.setY(np.nan)
            s.set(ckey, c)

        # Measure the "deblended" normal sources
        im <<= fullim
        measure.plotpat = 'joint-%(sourcenum)i.png'
        measure.run(exposure, sources)
        xx2, yy2, vx2, vy2 = [], [], [], []
        for s in sources:
            xx2.append(s.getX())
            yy2.append(s.getY())
            vx2.append(s.getIxx())
            vy2.append(s.getIyy())

        # Measure the "deblended" no-wings sources
        im <<= fullim2
        measure.plotpat = 'joint2-%(sourcenum)i.png'
        measure.run(exposure, sources, noiseImage=noiseim)
        xx3, yy3, vx3, vy3 = [], [], [], []
        for s in sources:
            xx3.append(s.getX())
            yy3.append(s.getY())
            vx3.append(s.getIxx())
            vy3.append(s.getIyy())

        print 'Normal:'
        print 'xx  ', xx0
        print '  vs', xx2
        print 'yy  ', yy0
        print '  vs', yy2
        print 'vx  ', vx0
        print '  vs', vx2
        print 'vy  ', vy0
        print '  vs', vy2

        print 'No wings:'
        print 'xx  ', xx1
        print '  vs', xx3
        print 'yy  ', yy1
        print '  vs', yy3
        print 'vx  ', vx1
        print '  vs', vx3
        print 'vy  ', vy1
        print '  vs', vy3

        # These "normal" tests are not very stringent.
        # 0.1-pixel centroids
        self.assertTrue(all([abs(v1 - v2) < 0.1 for v1, v2 in zip(xx0, xx2)]))
        self.assertTrue(all([abs(v1 - v2) < 0.1 for v1, v2 in zip(yy0, yy2)]))
        # 10% variances
        self.assertTrue(
            all([
                abs(v1 - v2) / ((v1 + v2) / 2.) < 0.1
                for v1, v2 in zip(vx0, vx2)
            ]))
        self.assertTrue(
            all([
                abs(v1 - v2) / ((v1 + v2) / 2.) < 0.1
                for v1, v2 in zip(vy0, vy2)
            ]))

        # The "no-wings" tests should be exact.
        self.assertTrue(xx1 == xx3)
        self.assertTrue(yy1 == yy3)
        self.assertTrue(vx1 == vx3)
        self.assertTrue(vy1 == vy3)

        # Reset sources
        for s in sources:
            sh = s.get(shkey)
            sh.setIxx(np.nan)
            sh.setIyy(np.nan)
            sh.setIxy(np.nan)
            s.set(shkey, sh)
            c = s.get(ckey)
            c.setX(np.nan)
            c.setY(np.nan)
            s.set(ckey, c)

        # Test that the parent/child order is unimportant.
        im <<= fullim2
        measure.doplot = False
        sources2 = sources.copy()
        perm = [2, 1, 0, 3, 4]
        for i, j in enumerate(perm):
            sources2[i] = sources[j]
            # I'm not convinced that HeavyFootprints get copied correctly...
            sources2[i].setFootprint(sources[j].getFootprint())
        measure.run(exposure, sources2, noiseImage=noiseim)
        # "measure.run" reorders the sources!
        xx3, yy3, vx3, vy3 = [], [], [], []
        for s in sources:
            xx3.append(s.getX())
            yy3.append(s.getY())
            vx3.append(s.getIxx())
            vy3.append(s.getIyy())
        self.assertTrue(xx1 == xx3)
        self.assertTrue(yy1 == yy3)
        self.assertTrue(vx1 == vx3)
        self.assertTrue(vy1 == vy3)

        # Reset sources
        for s in sources:
            sh = s.get(shkey)
            sh.setIxx(np.nan)
            sh.setIyy(np.nan)
            sh.setIxy(np.nan)
            s.set(shkey, sh)
            c = s.get(ckey)
            c.setX(np.nan)
            c.setY(np.nan)
            s.set(ckey, c)

        # Test that it still works when the parent ID falls in the middle of
        # the child IDs.
        im <<= fullim2
        measure.doplot = False
        sources2 = sources.copy()
        parentid = 3
        ids = [parentid, 1, 2, 4, 5]
        for i, s in enumerate(sources2):
            s.setId(ids[i])
            if i != 0:
                s.setParent(parentid)
            s.setFootprint(sources[i].getFootprint())

        measure.run(exposure, sources2, noiseImage=noiseim)
        # The sources get reordered!
        xx3, yy3, vx3, vy3 = [], [], [], []
        xx3, yy3, vx3, vy3 = [0] * 5, [0] * 5, [0] * 5, [0] * 5
        for i, j in enumerate(ids):
            xx3[i] = sources2[j - 1].getX()
            yy3[i] = sources2[j - 1].getY()
            vx3[i] = sources2[j - 1].getIxx()
            vy3[i] = sources2[j - 1].getIyy()
        self.assertTrue(xx1 == xx3)
        self.assertTrue(yy1 == yy3)
        self.assertTrue(vx1 == vx3)
        self.assertTrue(vy1 == vy3)
コード例 #10
0
    def runone(self, kk, rand):
        psf = self.getpsf()

        im = afwImage.ImageF(120, 200)
        skystd = 100
        afwMath.randomGaussianImage(im, rand)
        im *= skystd

        # The SDSS adaptive moments code seems sometimes to latch onto
        # an incorrect answer (maybe from a noise spike or something).
        # None of the flags seem to be set.  The result are variance
        # measurements a bit bigger than the PSF.  With different
        # noise draws the source values here will show this effect
        # (hence the loop in "test1" to try "runone" will different
        # noise draws).

        # The real point of this test case, though, is to show that
        # replacing other detections by noise results in better
        # measurements.  We do this by constructing a fake image
        # containing six rows.  In the top three rows, we have a
        # galaxy flanked by two stars that are far enough away that
        # they don't confuse the SDSS adaptive moments code.  In the
        # bottom three rows, they're close enough that the detections
        # don't merge, but the stars cause the variance of the galaxy
        # to be mis-estimated.  We want to show that with the
        # "doReplaceWithNoise" option, the measurements on the
        # bottom three improve.

        # If you love ASCII art (and who doesn't, really), the
        # synthetic image is going to look like this:
        #
        #    *     GGG     *
        #    *     GGG     *
        #    *     GGG     *
        #       *  GGG  *
        #       *  GGG  *
        #       *  GGG  *

        # We have three of each to work around the instability
        # mentioned above.

        x = 60
        y0 = 16
        ystep = 33
        for i in range(6):
            dx = [28, 29, 30, 35, 36, 37][i]
            y = y0 + i * ystep
            #                x y sx sy flux
            addGaussian(im, x, y, 10, 3, 2e5)
            addPsf(im, psf, x + dx, y, 1000)
            addPsf(im, psf, x - dx, y, 1000)

        #im.writeFits('im.fits')

        mi = afwImage.MaskedImageF(im)
        var = mi.getVariance()
        var.set(skystd**2)
        exposure = afwImage.makeExposure(mi)
        exposure.setPsf(psf)

        detconf = measAlg.SourceDetectionConfig()
        detconf.returnOriginalFootprints = True
        detconf.reEstimateBackground = False

        measconf = measAlg.SourceMeasurementConfig()
        measconf.doReplaceWithNoise = False

        #newalgs = [ 'shape.hsm.ksb', 'shape.hsm.bj', 'shape.hsm.linear' ]
        #measconf.algorithms = list(measconf.algorithms.names) + newalgs

        schema = afwTable.SourceTable.makeMinimalSchema()
        detect = measAlg.SourceDetectionTask(config=detconf, schema=schema)
        measure = measAlg.SourceMeasurementTask(config=measconf, schema=schema)

        print 'Running detection...'
        table = afwTable.SourceTable.make(schema)
        detected = detect.makeSourceCatalog(table, exposure)
        sources = detected.sources

        # We don't want the sources to be close enough that their
        # detection masks touch.
        self.assertEqual(len(sources), 18)

        # Run measurement with and without "doReplaceWithNoise"...
        for jj in range(2):

            print 'Running measurement...'
            measure.run(exposure, sources)

            #fields = schema.getNames()
            #print 'Fields:', fields
            fields = [
                'centroid.sdss',
                'shape.sdss',
                #'shape.hsm.bj.moments',
                #'shape.hsm.ksb.moments',
                #'shape.hsm.linear.moments',
                #'shape.sdss.flags.maxiter', 'shape.sdss.flags.shift',
                #'shape.sdss.flags.unweighted', 'shape.sdss.flags.unweightedbad'
            ]
            keys = [schema.find(f).key for f in fields]
            xx, yy, vx, vy = [], [], [], []
            for source in sources:
                #print '  ', source
                #for f,k in zip(fields, keys):
                #    val = source.get(k)
                #    print '    ', f, val
                xx.append(source.getX())
                yy.append(source.getY())
                vx.append(source.getIxx())
                vy.append(source.getIyy())

            if plots:
                plotSources(im, sources, schema)
                plt.savefig('%i%s.png' % (kk, chr(ord('a') + jj)))

            # Now we want to find the galaxy variance measurements...
            # Sort, first vertically then horizontally
            # iy ~ row number
            iy = [int(round((y - y0) / float(ystep))) for y in yy]
            iy = np.array(iy)
            xx = np.array(xx)
            vx = np.array(vx)
            vy = np.array(vy)
            I = np.argsort(iy * 1000 + xx)
            vx = vx[I]
            vy = vy[I]
            # The "left" stars will be indices 0, 3, 6, ...
            # The galaxies will be 1, 4, 7, ...
            vx = vx[slice(1, 18, 3)]

            # Bottom three galaxies may be contaminated by the stars
            bad = vx[:3]
            # Top three should be clean
            good = vx[3:]

            # When SdssShape fails, we get variance ~ 11

            I = np.flatnonzero(bad > 50.)
            # Hope that we got at least one valid measurement
            self.assertTrue(len(I) > 0)
            bad = bad[I]
            I = np.flatnonzero(good > 50.)
            self.assertTrue(len(I) > 0)
            good = good[I]

            print 'bad:', bad
            print 'good:', good

            # Typical:
            # bad: [ 209.78476672  192.35271583  176.76274525]
            # good: [  99.40557099  110.5701382 ]

            oklo, okhi = 80, 120
            self.assertTrue(all((good > oklo) * (good < okhi)))
            if jj == 0:
                # Without "doReplaceWithNoise", we expect to find the variances
                # overestimated.
                self.assertTrue(all(bad > okhi))
            else:
                # With "doReplaceWithNoise", no problem!
                self.assertTrue(all((bad > oklo) * (bad < okhi)))

            # Set "doReplaceWithNoise" for the second time through the loop...
            measconf.doReplaceWithNoise = True
コード例 #11
0
ファイル: variance.py プロジェクト: laurenam/meas_algorithms
    def testVariance(self):
        size = 128  # size of image (pixels)
        center = afwGeom.Point2D(size // 2, size // 2)  # object center
        width = 2.0  # PSF width
        flux = 10.0  # Flux of object
        variance = 1.0  # Variance value

        # Initial setup of an image
        exp = afwImage.ExposureF(size, size)
        image = exp.getMaskedImage().getImage()
        mask = exp.getMaskedImage().getMask()
        var = exp.getMaskedImage().getVariance()
        image.set(0.0)
        mask.set(0)
        var.set(variance)

        # Put down a PSF
        psf = measAlg.DoubleGaussianPsf(int(5 * width), int(5 * width), width)
        exp.setPsf(psf)
        psfImage = psf.computeImage(center).convertF()
        psfImage *= flux
        image.Factory(image,
                      psfImage.getBBox(afwImage.PARENT)).__iadd__(psfImage)
        var.Factory(var, psfImage.getBBox(afwImage.PARENT)).__iadd__(psfImage)

        # Put in some bad pixels to ensure they're ignored
        for i in range(-5, 6):
            bad = size // 2 + i * width
            var.getArray()[bad, :] = float("nan")
            mask.getArray()[bad, :] = mask.getPlaneBitMask("BAD")
            var.getArray()[:, bad] = float("nan")
            mask.getArray()[:, bad] = mask.getPlaneBitMask("BAD")

        if display:
            import lsst.afw.display.ds9 as ds9
            ds9.mtv(image, frame=1)
            ds9.mtv(mask, frame=2)
            ds9.mtv(var, frame=3)

        config = measAlg.SourceMeasurementConfig()
        config.algorithms.names = ["centroid.naive", "shape.sdss", "variance"]
        config.slots.centroid = "centroid.naive"
        config.slots.psfFlux = None
        config.slots.apFlux = None
        config.slots.modelFlux = None
        config.slots.instFlux = None
        config.slots.calibFlux = None
        config.slots.shape = "shape.sdss"
        config.algorithms["variance"].mask = ["BAD", "SAT"]

        config.validate()
        schema = afwTable.SourceTable.makeMinimalSchema()
        ms = config.makeMeasureSources(schema)
        catalog = afwTable.SourceCatalog(schema)
        config.slots.setupTable(catalog.getTable())

        foot = afwDetection.Footprint(afwGeom.Point2I(center), width)
        peak = foot.getPeaks().addNew()
        peak.setIx(int(center.getX()))
        peak.setIy(int(center.getY()))
        peak.setFx(center.getX())
        peak.setFy(center.getY())
        peak.setPeakValue(flux)

        source = catalog.addNew()
        source.setFootprint(foot)
        ms.applyWithPeak(source, exp)

        self.assertEqual(source.get("variance"), variance)
コード例 #12
0
ファイル: testAlgorithms.py プロジェクト: dr-guangtou/hs_hsc
    def testAlgorithms(self):
        """Test that we can instantiate and use algorithms"""

        config = measAlg.SourceMeasurementConfig()
        config.algorithms.names = measAlg.AlgorithmRegistry.all.keys()
        config.algorithms.names.discard(config.centroider.name)
        config.doReplaceWithNoise = False

        config.algorithms.names.discard("flux.peakLikelihood")

        if False:
            log = pexLog.getDefaultLog()
            log.setThreshold(log.DEBUG)

        schema = afwTable.SourceTable.makeMinimalSchema()
        task = measAlg.SourceMeasurementTask(schema, config=config)
        catalog = afwTable.SourceCatalog(schema)
        source = catalog.addNew()
        source.set("id", 12345)

        size = 256
        xStar, yStar = 65.432, 76.543
        width = 3.21
        x0, y0 = 12345, 54321
        x, y = numpy.indices((size, size))
        im = afwImage.MaskedImageF(afwGeom.ExtentI(size, size))
        im.setXY0(afwGeom.Point2I(x0, y0))
        im.getVariance().set(1.0)
        arr = im.getImage().getArray()
        arr[y,
            x] = numpy.exp(-0.5 * ((x - xStar)**2 + (y - yStar)**2) / width**2)
        psf = testLib.makeTestPsf(im)
        exp = afwImage.makeExposure(im)
        exp.setPsf(psf)
        exp.setXY0(afwGeom.Point2I(x0, y0))
        scale = 1.0e-5
        wcs = afwImage.makeWcs(
            afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees),
            afwGeom.Point2D(0.0, 0.0), scale, 0.0, 0.0, scale)
        exp.setWcs(wcs)

        point = afwGeom.Point2I(int(xStar + x0), int(yStar + y0))
        bbox = im.getBBox()
        bbox.shift(afwGeom.Extent2I(x0, y0))
        foot = afwDetection.Footprint(point, width, bbox)
        foot.addPeak(point.getX(), point.getY(), 1.0)
        afwDetection.setMaskFromFootprint(exp.getMaskedImage().getMask(), foot,
                                          1)
        source.setFootprint(foot)

        if display:
            ds9.mtv(exp, frame=1)

        task.run(exp, catalog)

        for alg in config.algorithms:
            flagName = alg + ".flags"
            if False:
                print(alg,
                      source.get(flagName) if flagName in schema else None,
                      source.get(alg) if alg in schema else None)
            elif flagName in schema:
                self.assertFalse(source.get(alg + ".flags"))
コード例 #13
0
ファイル: processSpots.py プロジェクト: wmwv/brighter-fatter
import lsst.afw.math as afwMath
import lsst.afw.table as afwTable
import lsst.afw.image as afwImg
import lsst.afw.detection as afwDetect

import lsst.meas.algorithms as measAlg

statFlags = (afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV | afwMath.MAX
             | afwMath.MIN | afwMath.ERRORS)
print "The statistics flags are set to %s." % bin(statFlags)
print "Errors will be calculated.\n"

# Configure the detection and measurement algorithms
schema = afwTable.SourceTable.makeMinimalSchema()
detectSourcesConfig = measAlg.SourceDetectionConfig(thresholdType='value')
measureSourcesConfig = measAlg.SourceMeasurementConfig()

# Setup the detection and measurement tasks
detect = measAlg.SourceDetectionTask(config=detectSourcesConfig, schema=schema)
measure = measAlg.SourceMeasurementTask(config=measureSourcesConfig,
                                        schema=schema)

#  Choose algorithms to look at the output of.
fields = [  #'centroid.naive', 
    #'centroid.naive.err', 'centroid.naive.flags',
    #'centroid.gaussian',
    #'centroid.gaussian.err',
    'centroid.sdss',
    'centroid.sdss.flags',
    'shape.sdss',
    'shape.sdss.err',
コード例 #14
0
ファイル: psfIO.py プロジェクト: dr-guangtou/hs_hsc
    def setUp(self):
        width, height = 100, 300
        self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height))
        self.mi.set(0)
        self.mi.getVariance().set(10)
        self.mi.getMask().addMaskPlane("DETECTED")

        self.FWHM = 5
        self.ksize = 25  # size of desired kernel

        self.exposure = afwImage.makeExposure(self.mi)

        psf = roundTripPsf(
            2,
            algorithms.DoubleGaussianPsf(self.ksize, self.ksize,
                                         self.FWHM / (2 * sqrt(2 * log(2))), 1,
                                         0.1))
        self.exposure.setPsf(psf)

        for x, y in [
            (20, 20),
                #(30, 35), (50, 50),
            (60, 20),
            (60, 210),
            (20, 210)
        ]:

            flux = 10000 - 0 * x - 10 * y

            sigma = 3 + 0.01 * (y - self.mi.getHeight() / 2)
            psf = roundTripPsf(
                3,
                algorithms.DoubleGaussianPsf(self.ksize, self.ksize, sigma, 1,
                                             0.1))
            im = psf.computeImage().convertF()
            im *= flux
            smi = self.mi.getImage().Factory(
                self.mi.getImage(),
                afwGeom.BoxI(
                    afwGeom.PointI(x - self.ksize / 2, y - self.ksize / 2),
                    afwGeom.ExtentI(self.ksize)), afwImage.LOCAL)

            if False:  # Test subtraction with non-centered psfs
                im = afwMath.offsetImage(im, 0.5, 0.5)

            smi += im
            del psf
            del im
            del smi

        psf = roundTripPsf(
            4,
            algorithms.DoubleGaussianPsf(self.ksize, self.ksize,
                                         self.FWHM / (2 * sqrt(2 * log(2))), 1,
                                         0.1))

        self.cellSet = afwMath.SpatialCellSet(
            afwGeom.BoxI(afwGeom.PointI(0, 0), afwGeom.ExtentI(width, height)),
            100)
        ds = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(10),
                                       "DETECTED")
        #
        # Prepare to measure
        #
        msConfig = algorithms.SourceMeasurementConfig()
        msConfig.load("tests/config/MeasureSources.py")
        schema = afwTable.SourceTable.makeMinimalSchema()
        measureSources = msConfig.makeMeasureSources(schema)
        catalog = afwTable.SourceCatalog(schema)
        msConfig.slots.calibFlux = None
        msConfig.slots.setupTable(catalog.table)
        ds.makeSources(catalog)
        for i, source in enumerate(catalog):
            measureSources.applyWithPeak(source, self.exposure)
            self.cellSet.insertCandidate(
                algorithms.makePsfCandidate(source, self.exposure))
コード例 #15
0
    def testCountInputs(self):
        num = 3  # Number of images
        size = 10  # Size of images (pixels)
        shift = 4  # Shift to apply between images (pixels)
        value = 100.0  # Value to give objects
        offset = 12345  # x0,y0

        cdMatrix = (1.0e-5, 0.0, 0.0, 1.0e-5)
        crval = afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees)

        positions = [
            afwGeom.Point2D(size // 2 + shift * (i - num // 2) + offset,
                            size // 2 + shift * (i - num // 2) + offset)
            for i in range(num)
        ]
        wcsList = [
            afwImage.makeWcs(crval, pos - afwGeom.Extent2D(offset, offset),
                             *cdMatrix) for pos in positions
        ]
        imageBox = afwGeom.Box2I(afwGeom.Point2I(0, 0),
                                 afwGeom.Extent2I(size, size))
        wcsRef = afwImage.makeWcs(crval, afwGeom.Point2D(offset, offset),
                                  *cdMatrix)

        exp = afwImage.ExposureF(size, size)
        exp.setXY0(afwGeom.Point2I(offset, offset))
        exp.setWcs(wcsRef)
        exp.setPsf(measAlg.DoubleGaussianPsf(5, 5, 1.0))
        exp.getInfo().setCoaddInputs(
            afwImage.CoaddInputs(afwTable.ExposureTable.makeMinimalSchema(),
                                 afwTable.ExposureTable.makeMinimalSchema()))
        ccds = exp.getInfo().getCoaddInputs().ccds
        for wcs in wcsList:
            record = ccds.addNew()
            record.setWcs(wcs)
            record.setBBox(imageBox)
            record.setValidPolygon(Polygon(afwGeom.Box2D(imageBox)))

        exp.getMaskedImage().getImage().set(0)
        exp.getMaskedImage().getMask().set(0)
        exp.getMaskedImage().getVariance().set(1.0)
        for pp in positions:
            x, y = map(int, pp)
            exp.getMaskedImage().getImage().set0(x, y, value)
            exp.getMaskedImage().getMask().set(x - offset, y - offset, value)

        measureSourcesConfig = measAlg.SourceMeasurementConfig()
        measureSourcesConfig.algorithms.names = [
            "centroid.naive", "countInputs"
        ]
        measureSourcesConfig.slots.centroid = "centroid.naive"
        measureSourcesConfig.slots.psfFlux = None
        measureSourcesConfig.slots.apFlux = None
        measureSourcesConfig.slots.modelFlux = None
        measureSourcesConfig.slots.instFlux = None
        measureSourcesConfig.slots.calibFlux = None
        measureSourcesConfig.slots.shape = None
        measureSourcesConfig.validate()
        schema = afwTable.SourceTable.makeMinimalSchema()
        ms = measureSourcesConfig.makeMeasureSources(schema)
        catalog = afwTable.SourceCatalog(schema)
        measureSourcesConfig.slots.setupTable(catalog.getTable())

        for pp in positions:
            foot = afwDetection.Footprint(afwGeom.Point2I(pp), 1.0)
            peak = foot.getPeaks().addNew()
            peak.setIx(int(pp[0]))
            peak.setIy(int(pp[1]))
            peak.setFx(pp[0])
            peak.setFy(pp[1])
            peak.setPeakValue(value)

            source = catalog.addNew()
            source.setFootprint(foot)

            ms.applyWithPeak(source, exp)

            number = sum(
                afwGeom.Box2D(imageBox).contains(
                    wcs.skyToPixel(wcsRef.pixelToSky(pp))) for wcs in wcsList)
            self.assertEqual(source.get("countInputs"), number)
コード例 #16
0
    def measureKronInPython(self, objImg, xcen, ycen, nsigma, kfac, nIterForRadius, makeImage=None):
        """Measure the Kron quantities of an elliptical Gaussian in python

        N.b. only works for XY0 == (0, 0)
        """
        #
        # Measure moments using SDSS shape algorithm
        #
        msConfig = measAlg.SourceMeasurementConfig()
        if False:                       # requires #2546
            msConfig.centroider = None
            msConfig.slots.centroid = None

        schema = afwTable.SourceTable.makeMinimalSchema()
        ms = msConfig.makeMeasureSources(schema)
        table = afwTable.SourceTable.make(schema)
        msConfig.slots.setupTable(table)
        source = table.makeRecord()
        fp = afwDetection.Footprint(objImg.getBBox())
        source.setFootprint(fp)
        center = afwGeom.Point2D(xcen, ycen)
        ms.apply(source, objImg, center)

        Mxx = source.getIxx()
        Mxy = source.getIxy()
        Myy = source.getIyy()
        #
        # Calculate principal axes
        #
        Muu_p_Mvv = Mxx + Myy
        Muu_m_Mvv = math.sqrt((Mxx - Myy)**2 + 4*Mxy**2)
        Muu = 0.5*(Muu_p_Mvv + Muu_m_Mvv)
        Mvv = 0.5*(Muu_p_Mvv - Muu_m_Mvv)
        theta = 0.5*math.atan2(2*Mxy, Mxx - Myy)
        a = math.sqrt(Muu)
        b = math.sqrt(Mvv)
        ab = a/b
        #
        # Get footprint
        #
        ellipse = afwEllipses.Ellipse(afwEllipses.Axes(nsigma*a, nsigma*b, theta),
                                      afwGeom.Point2D(xcen - objImg.getX0(), ycen - objImg.getY0()))
        fpEllipse = afwDetection.Footprint(ellipse)
        
        sumI = 0.0
        sumR = 0.38259771140356325/ab*(1 + math.sqrt(2)*math.hypot(math.fmod(xcen, 1), math.fmod(ycen, 1)))*\
               objImg.getMaskedImage().getImage().get(int(xcen), int(ycen))
               
        gal = objImg.getMaskedImage().getImage()

        c, s = math.cos(theta), math.sin(theta)
        for sp in fpEllipse.getSpans():
            y, x0, x1 = sp.getY(), sp.getX0(), sp.getX1()

            for x in range(x0, x1 + 1):
                dx, dy = x - xcen, y - ycen
                u =  c*dx + s*dy
                v = -s*dx + c*dy

                r = math.hypot(u, v*ab)
                try:
                    val = gal.get(x, y)
                except:
                    continue

                sumI += val
                sumR += val*r

        R_K = sumR/sumI

        sumI = 0.0
        for y in range(self.height):
            for x in range(self.width):
                dx, dy = x - xcen, y - ycen
                u =  c*dx + s*dy
                v = -s*dx + c*dy
                if math.hypot(u/a, v/b) < kfac:
                    sumI += gal.get(x, y)

        return R_K, sumI, 0, False, False, False
コード例 #17
0
    def check(self, psfFwhm=0.5, flux=1000.0):
        """Check that we can measure convolved fluxes
    
        We create an image with a Gaussian PSF and a single point source.
        Measurements of the point source should match expectations for a
        Gaussian of the known sigma and known aperture radius.

        @param psfFwhm: PSF FWHM in arcsec
        @param flux: source flux in ADU
        """
        bbox = afwGeom.Box2I(afwGeom.Point2I(12345, 6789),
                             afwGeom.Extent2I(200, 300))

        # We'll only achieve the target accuracy if the pixel scale is rather smaller than Gaussians
        # involved. Otherwise it's important to consider the convolution with the pixel grid, and we're
        # not doing that here.
        scale = 0.1 * afwGeom.arcseconds

        exposure, center = makeExposure(bbox, scale, psfFwhm, flux)
        msConfig = measAlg.SourceMeasurementConfig()
        msConfig.algorithms.names.add("flux.convolved")
        values = [ii / scale.asArcseconds() for ii in (0.6, 0.8, 1.0, 1.2)]
        msConfig.algorithms["flux.convolved"].seeing = values
        msConfig.algorithms["flux.convolved"].radius = values

        schema = afwTable.SourceTable.makeMinimalSchema()
        ms = msConfig.makeMeasureSources(schema)

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

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

        ms.apply(source, exposure, center)

        if display:
            ds9.mtv(exposure, frame=frame)
            ds9.dot("x",
                    center.getX() - exposure.getX0(),
                    center.getY() - exposure.getY0(),
                    frame=frame)
            import pdb
            pdb.set_trace()

        self.assertFalse(
            source.get("flux.convolved.flag"))  # algorithm succeeded
        for ii, seeing in enumerate(
                msConfig.algorithms["flux.convolved"].seeing):
            deconvolve = seeing < psfFwhm / scale.asArcseconds()
            self.assertTrue(
                source.get("flux.convolved.%d.deconv" % ii) == deconvolve)
            if deconvolve:
                # Not worth checking anything else
                continue
            for jj, radius in enumerate(
                    msConfig.algorithms["flux.convolved"].radius):
                sigma = seeing / SIGMA_TO_FWHM
                expected = flux * (1.0 - math.exp(-0.5 * (radius / sigma)**2))
                name = "flux.convolved.%d.%d" % (ii, jj)
                self.assertClose(expected, source.get(name), rtol=1.0e-3)
                self.assertFalse(source.get(name + ".flags"))
                self.assertGreater(source.get(name + ".err"), 0)