Exemplo n.º 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)
Exemplo n.º 2
0
def doDetection(exp,
                threshold=5.0,
                thresholdType='pixel_stdev',
                thresholdPolarity='positive',
                doSmooth=True,
                doMeasure=True,
                asDF=False):
    # Modeled from meas_algorithms/tests/testMeasure.py
    schema = afwTable.SourceTable.makeMinimalSchema()
    config = measAlg.SourceDetectionTask.ConfigClass()
    config.thresholdPolarity = thresholdPolarity
    config.reEstimateBackground = False
    config.thresholdValue = threshold
    config.thresholdType = thresholdType
    detectionTask = measAlg.SourceDetectionTask(config=config, schema=schema)
    detectionTask.log.setLevel(log_level)

    # Do measurement too, so we can get x- and y-coord centroids

    config = measBase.SingleFrameMeasurementTask.ConfigClass()
    # Use the minimum set of plugins required.
    config.plugins = [
        "base_CircularApertureFlux",
        "base_PixelFlags",
        "base_SkyCoord",
        "base_PsfFlux",
        "base_GaussianCentroid",
        "base_GaussianFlux",
        "base_PeakLikelihoodFlux",
        "base_PeakCentroid",
        "base_SdssCentroid",
        "base_SdssShape",
        "base_NaiveCentroid",
        #"ip_diffim_NaiveDipoleCentroid",
        #"ip_diffim_NaiveDipoleFlux",
        "ip_diffim_PsfDipoleFlux",
        "ip_diffim_ClassificationDipole",
    ]
    config.slots.centroid = "base_GaussianCentroid"  #"ip_diffim_NaiveDipoleCentroid"
    #config.plugins["base_CircularApertureFlux"].radii = [3.0, 7.0, 15.0, 25.0]
    #config.slots.psfFlux = "base_CircularApertureFlux_7_0" # Use of the PSF flux is hardcoded in secondMomentStarSelector
    config.slots.calibFlux = None
    config.slots.modelFlux = None
    config.slots.instFlux = None
    config.slots.shape = "base_SdssShape"
    config.doReplaceWithNoise = False
    measureTask = measBase.SingleFrameMeasurementTask(schema, config=config)
    measureTask.log.setLevel(log_level)

    table = afwTable.SourceTable.make(schema)
    sources = detectionTask.run(table, exp, doSmooth=doSmooth).sources

    measureTask.measure(sources, exposure=exp)

    if asDF:
        sources = catalogToDF(
            sources
        )  #pd.DataFrame({col: sources.columns[col] for col in sources.schema.getNames()})

    return sources
Exemplo n.º 3
0
def createDipole(w, h, xc, yc, scaling=100.0, fracOffset=1.2):
    # Make random noise image: set image plane to normal distribution
    image = afwImage.MaskedImageF(w, h)
    image.set(0)
    array = image.getImage().getArray()
    array[:, :] = np.random.randn(w, h)
    # Set variance to 1.0
    var = image.getVariance()
    var.set(1.0)

    if display:
        ds9.mtv(image, frame=1, title="Original image")
        ds9.mtv(image.getVariance(), frame=2, title="Original variance")

    # Create Psf for dipole creation and measurement
    psfSize = 17
    psf = measAlg.DoubleGaussianPsf(psfSize, psfSize, 2.0, 3.5, 0.1)
    psfFwhmPix = sigma2fwhm * psf.computeShape().getDeterminantRadius()
    psfim = psf.computeImage().convertF()
    psfim *= scaling / psf.computePeak()
    psfw, psfh = psfim.getDimensions()
    psfSum = np.sum(psfim.getArray())

    # Create the dipole, offset by fracOffset of the Psf FWHM (pixels)
    offset = fracOffset * psfFwhmPix // 2
    array = image.getImage().getArray()
    xp, yp = xc - psfw // 2 + offset, yc - psfh // 2 + offset
    array[yp:yp + psfh, xp:xp + psfw] += psfim.getArray()

    xn, yn = xc - psfw // 2 - offset, yc - psfh // 2 - offset
    array[yn:yn + psfh, xn:xn + psfw] -= psfim.getArray()

    if display:
        ds9.mtv(image, frame=3, title="With dipole")

    # Create an exposure, detect positive and negative peaks separately
    exp = afwImage.makeExposure(image)
    exp.setPsf(psf)
    config = measAlg.SourceDetectionConfig()
    config.thresholdPolarity = "both"
    config.reEstimateBackground = False
    schema = afwTable.SourceTable.makeMinimalSchema()
    task = measAlg.SourceDetectionTask(schema, config=config)
    table = afwTable.SourceTable.make(schema)
    results = task.makeSourceCatalog(table, exp)
    if display:
        ds9.mtv(image, frame=4, title="Detection plane")

    # Merge them together
    assert (len(results.sources) == 2)
    fpSet = results.fpSets.positive
    fpSet.merge(results.fpSets.negative, 0, 0, False)
    sources = afwTable.SourceCatalog(table)
    fpSet.makeSources(sources)
    assert (len(sources) == 1)
    s = sources[0]
    assert (len(s.getFootprint().getPeaks()) == 2)

    return psf, psfSum, exp, s
def detectAndMeasure(exposure, detConfig, measConfig):
    schema = afwTable.SourceTable.makeMinimalSchema()
    detConfig.validate()
    measConfig.validate()
    detTask = measAlg.SourceDetectionTask(config=detConfig, schema=schema)
    measTask = measAlg.SourceMeasurementTask(config=measConfig, schema=schema)
    # detect
    table = afwTable.SourceTable.make(schema)
    sources = detTask.makeSourceCatalog(table, exposure).sources
    # ... and measure
    measTask.run(exposure, sources)
    return sources
Exemplo n.º 5
0
    def test1(self):
        #exposure = afwImage.ExposureF('mini-v85408556-fr-R23-S11.fits')
        #exposure = afwImage.ExposureF('../afwdata/ImSim/calexp/v85408556-fr/R23/S11.fits')
        #bb = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Point2I(511,511))
        #exposure = afwImage.ExposureF('data/goodSeeingCoadd/r/3/113,0/coadd-r-3-113,0.fits', 0, bb)
        #exposure.writeFits('mini-r-3-113,0.fits')
        fn = os.path.join(os.path.dirname(__file__), 'data',
                          'mini-r-3-113,0.fits.gz')
        print 'Reading image', fn
        exposure = afwImage.ExposureF(fn)
        exposure.setPsf(afwDetection.GaussianPsf(15, 15, 3))
        schema = afwTable.SourceTable.makeMinimalSchema()
        idFactory = afwTable.IdFactory.makeSimple()

        dconf = measAlg.SourceDetectionConfig()
        dconf.reEstimateBackground = False
        dconf.includeThresholdMultiplier = 5.

        mconf = SingleFrameMeasurementConfig()

        aconf = ANetAstrometryConfig()
        aconf.forceKnownWcs = True

        det = measAlg.SourceDetectionTask(schema=schema, config=dconf)
        meas = SingleFrameMeasurementTask(schema, config=mconf)
        astrom = ANetAstrometryTask(schema, config=aconf, name='astrom')

        astrom.log.setThreshold(pexLog.Log.DEBUG)

        inwcs = exposure.getWcs()
        print 'inwcs:', inwcs
        instr = inwcs.getFitsMetadata().toString()
        print 'inwcs:', instr
        table = afwTable.SourceTable.make(schema, idFactory)
        sources = det.makeSourceCatalog(table, exposure, sigma=1).sources
        meas.measure(exposure, sources)

        for dosip in [False, True]:
            aconf.solver.calculateSip = dosip
            ast = astrom.run(sourceCat=sources, exposure=exposure)
            outwcs = exposure.getWcs()
            outstr = outwcs.getFitsMetadata().toString()
            if dosip is False:
                self.assertEqual(inwcs, outwcs)
                self.assertEqual(instr, outstr)
            print 'inwcs:', instr
            print 'outwcs:', outstr
            print len(ast.matches), 'matches'
            self.assertTrue(len(ast.matches) > 10)
Exemplo n.º 6
0
    def test1(self):
        fn = os.path.join(os.path.dirname(__file__), 'data',
                          'mini-r-3-113,0.fits.gz')
        print('Reading image', fn)
        exposure = afwImage.ExposureF(fn)
        exposure.setPsf(afwDetection.GaussianPsf(15, 15, 3))
        schema = afwTable.SourceTable.makeMinimalSchema()
        idFactory = afwTable.IdFactory.makeSimple()

        dconf = measAlg.SourceDetectionConfig()
        dconf.reEstimateBackground = False
        dconf.includeThresholdMultiplier = 5.

        mconf = SingleFrameMeasurementConfig()

        aconf = ANetAstrometryConfig()
        aconf.forceKnownWcs = True

        det = measAlg.SourceDetectionTask(schema=schema, config=dconf)
        meas = SingleFrameMeasurementTask(schema, config=mconf)
        astrom = ANetAstrometryTask(schema, config=aconf, name='astrom')

        astrom.log.setLevel(astrom.log.TRACE)

        inwcs = exposure.getWcs()
        print('inwcs:', inwcs)
        instr = inwcs.getFitsMetadata().toString()
        print('inwcs:', instr)
        table = afwTable.SourceTable.make(schema, idFactory)
        sources = det.makeSourceCatalog(table, exposure, sigma=1).sources
        meas.measure(sources, exposure)

        for dosip in [False, True]:
            aconf.solver.calculateSip = dosip
            ast = astrom.run(sourceCat=sources, exposure=exposure)
            outwcs = exposure.getWcs()
            outstr = outwcs.getFitsMetadata().toString()
            if not dosip:
                self.assertEqual(inwcs, outwcs)
                self.assertEqual(instr, outstr)
            print('inwcs:', instr)
            print('outwcs:', outstr)
            print(len(ast.matches), 'matches')
            self.assertGreater(len(ast.matches), 10)
Exemplo n.º 7
0
    def detectDipoleSources(self, doMerge=True, diffim=None, detectSigma=5.5, grow=3):
        """!Utility function for detecting dipoles.

        Detect pos/neg sources in the diffim, then merge them. A
        bigger "grow" parameter leads to a larger footprint which
        helps with dipole measurement for faint dipoles.
        """

        if diffim is None:
            diffim = self.diffim

        # Start with a minimal schema - only the fields all SourceCatalogs need
        schema = afwTable.SourceTable.makeMinimalSchema()

        # Customize the detection task a bit (optional)
        detectConfig = measAlg.SourceDetectionConfig()
        detectConfig.returnOriginalFootprints = False  # should be the default

        psfSigma = diffim.getPsf().computeShape().getDeterminantRadius()

        # code from imageDifference.py:
        detectConfig.thresholdPolarity = "both"
        detectConfig.thresholdValue = detectSigma
        # detectConfig.nSigmaToGrow = psfSigma
        detectConfig.reEstimateBackground = True  # if False, will fail often for faint sources on gradients?
        detectConfig.thresholdType = "pixel_stdev"

        # Create the detection task. We pass the schema so the task can declare a few flag fields
        detectTask = measAlg.SourceDetectionTask(schema, config=detectConfig)

        table = afwTable.SourceTable.make(schema)
        catalog = detectTask.makeSourceCatalog(table, diffim, sigma=psfSigma)

        # Now do the merge.
        if doMerge:
            fpSet = catalog.fpSets.positive
            fpSet.merge(catalog.fpSets.negative, grow, grow, False)
            sources = afwTable.SourceCatalog(table)
            fpSet.makeSources(sources)

            return sources

        else:
            return detectTask, schema
def runMeasure(task, schema, exposure):
    """
    Run a measurement task which has previously been initialized on a single source
    """
    cat = afwTable.SourceCatalog(schema)
    source = cat.addNew()
    dettask = measAlg.SourceDetectionTask()

    # Suppress non-essential task output.
    dettask.log.setLevel(dettask.log.WARN)

    # We are expecting this task to log an error. Suppress it, so that it
    # doesn't appear on the console or in logs, and incorrectly cause the user
    # to assume a failure.
    task.log.setLevel(task.log.FATAL)
    footprints = dettask.detectFootprints(exposure,
                                          sigma=4.0).positive.getFootprints()
    source.setFootprint(footprints[0])
    task.run(cat, exposure)
    return source
Exemplo n.º 9
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 detector with distortion
        self.detector = DetectorWrapper(
            bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(self.nx, self.ny)),
            orientation = cameraGeom.Orientation(afwGeom.Point2D(255.0, 255.0)),
            radialDistortion = 0.925,
        ).detector

        # make a detector with no distortion
        self.flatDetector = DetectorWrapper(
            bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(self.nx, self.ny)),
            orientation = cameraGeom.Orientation(afwGeom.Point2D(255.0, 255.0)),
            radialDistortion = 0.0,
        ).detector

        # detection policies
        detConfig = measAlg.SourceDetectionConfig()
        # Cannot use default background approximation order (6) for such a small image.
        detConfig.background.approxOrderX = 4

        # measurement policies
        measConfig = measBase.SingleFrameMeasurementConfig()
        measConfig.algorithms.names = [
                 "base_SdssCentroid",
                 "base_SdssShape",
                 "base_GaussianFlux",
                 "base_PsfFlux",
                 ]
        measConfig.slots.centroid = "base_SdssCentroid"
        measConfig.slots.shape = "base_SdssShape"
        measConfig.slots.psfFlux = "base_PsfFlux"
        measConfig.slots.apFlux = None
        measConfig.slots.modelFlux = None
        measConfig.slots.instFlux = None
        measConfig.slots.calibFlux = None

        self.schema = afwTable.SourceTable.makeMinimalSchema()
        detConfig.validate()
        measConfig.validate()
        self.detTask = measAlg.SourceDetectionTask(config=detConfig, schema=self.schema)
        self.measTask = measBase.SingleFrameMeasurementTask(config=measConfig, schema=self.schema)

        # psf star selector
        starSelectorConfig = measAlg.SecondMomentStarSelectorTask.ConfigClass()
        starSelectorConfig.fluxLim = 5000.0
        starSelectorConfig.histSize = 32
        starSelectorConfig.clumpNSigma = 1.0
        starSelectorConfig.badFlags = []
        self.starSelector = measAlg.SecondMomentStarSelectorTask(
            config=starSelectorConfig, schema=self.schema
        )

        # 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)
Exemplo n.º 10
0
    def detectDipoleSources(self, doMerge=True, diffim=None, detectSigma=5.5, grow=3, minBinSize=32):
        """Utility function for detecting dipoles.

        Detect pos/neg sources in the diffim, then merge them. A
        bigger "grow" parameter leads to a larger footprint which
        helps with dipole measurement for faint dipoles.

        Parameters
        ----------
        doMerge : `bool`
           Whether to merge the positive and negagive detections into a single
           source table.
        diffim : `lsst.afw.image.exposure.exposure.ExposureF`
           Difference image on which to perform detection.
        detectSigma : `float`
           Threshold for object detection.
        grow : `int`
           Number of pixels to grow the footprints before merging.
        minBinSize : `int`
           Minimum bin size for the background (re)estimation (only applies if
           the default leads to min(nBinX, nBinY) < fit order so the default
           config parameter needs to be decreased, but not to a value smaller
           than ``minBinSize``, in which case the fitting algorithm will take
           over and decrease the fit order appropriately.)

        Returns
        -------
        sources : `lsst.afw.table.SourceCatalog`
           If doMerge=True, the merged source catalog is returned OR
        detectTask : `lsst.meas.algorithms.SourceDetectionTask`
        schema : `lsst.afw.table.Schema`
           If doMerge=False, the source detection task and its schema are
           returned.
        """
        if diffim is None:
            diffim = self.diffim

        # Start with a minimal schema - only the fields all SourceCatalogs need
        schema = afwTable.SourceTable.makeMinimalSchema()

        # Customize the detection task a bit (optional)
        detectConfig = measAlg.SourceDetectionConfig()
        detectConfig.returnOriginalFootprints = False  # should be the default

        psfSigma = diffim.getPsf().computeShape().getDeterminantRadius()

        # code from imageDifference.py:
        detectConfig.thresholdPolarity = "both"
        detectConfig.thresholdValue = detectSigma
        # detectConfig.nSigmaToGrow = psfSigma
        detectConfig.reEstimateBackground = True  # if False, will fail often for faint sources on gradients?
        detectConfig.thresholdType = "pixel_stdev"
        # Test images are often quite small, so may need to adjust background binSize
        while ((min(diffim.getWidth(), diffim.getHeight()))//detectConfig.background.binSize <
               detectConfig.background.approxOrderX and detectConfig.background.binSize > minBinSize):
            detectConfig.background.binSize = max(minBinSize, detectConfig.background.binSize//2)

        # Create the detection task. We pass the schema so the task can declare a few flag fields
        detectTask = measAlg.SourceDetectionTask(schema, config=detectConfig)

        table = afwTable.SourceTable.make(schema)
        catalog = detectTask.run(table, diffim, sigma=psfSigma)

        # Now do the merge.
        if doMerge:
            fpSet = catalog.fpSets.positive
            fpSet.merge(catalog.fpSets.negative, grow, grow, False)
            sources = afwTable.SourceCatalog(table)
            fpSet.makeSources(sources)

            return sources

        else:
            return detectTask, schema
Exemplo n.º 11
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
Exemplo n.º 12
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)
Exemplo n.º 13
0
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',
    'shape.sdss.centroid',
    # 'shape.sdss.centroid.err',
    'shape.sdss.flags',