示例#1
0
    def setUp(self):
        """Build up three different sets of objects that are to be merged"""
        pos1 = [(40, 40), (220, 35), (40, 48), (220, 50),
                (67, 67), (150, 50), (40, 90), (70, 160),
                (35, 255), (70, 180), (250, 200), (120, 120),
                (170, 180), (100, 210), (20, 210),
                ]
        pos2 = [(43, 45), (215, 31), (171, 258), (211, 117),
                (48, 99), (70, 160), (125, 45), (251, 33),
                (37, 170), (134, 191), (79, 223), (258, 182)
                ]
        pos3 = [(70, 170), (219, 41), (253, 173), (253, 192)]

        box = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Point2I(300, 300))
        psfsig = 1.
        kernelSize = 41
        flux = 1000

        # Create a different sized psf for each image and insert them at the
        # desired positions
        im1 = afwImage.MaskedImageD(box)
        psf1 = afwDetect.GaussianPsf(kernelSize, kernelSize, psfsig)

        im2 = afwImage.MaskedImageD(box)
        psf2 = afwDetect.GaussianPsf(kernelSize, kernelSize, 2*psfsig)

        im3 = afwImage.MaskedImageD(box)
        psf3 = afwDetect.GaussianPsf(kernelSize, kernelSize, 1.3*psfsig)

        insertPsf(pos1, im1, psf1, kernelSize, flux)
        insertPsf(pos2, im2, psf2, kernelSize, flux)
        insertPsf(pos3, im3, psf3, kernelSize, flux)

        schema = afwTable.SourceTable.makeMinimalSchema()
        self.idFactory = afwTable.IdFactory.makeSimple()
        self.table = afwTable.SourceTable.make(schema, self.idFactory)

        # Create SourceCatalogs from these objects
        fp1 = afwDetect.FootprintSet(
            im1, afwDetect.Threshold(0.001), "DETECTED")
        self.catalog1 = afwTable.SourceCatalog(self.table)
        fp1.makeSources(self.catalog1)

        fp2 = afwDetect.FootprintSet(
            im2, afwDetect.Threshold(0.001), "DETECTED")
        self.catalog2 = afwTable.SourceCatalog(self.table)
        fp2.makeSources(self.catalog2)

        fp3 = afwDetect.FootprintSet(
            im3, afwDetect.Threshold(0.001), "DETECTED")
        self.catalog3 = afwTable.SourceCatalog(self.table)
        fp3.makeSources(self.catalog3)
示例#2
0
def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True):
    """Make an exposure with stars (modelled as Gaussians)."""
    """
    @param bbox: parent bbox of exposure
    @param kwid: kernel width (and height; kernel is square)
    @param sky: amount of sky background (counts)
    @param coordList: a list of [x, y, counts, sigma], where:
        * x,y are relative to exposure origin
        * counts is the integrated counts for the star
        * sigma is the Gaussian sigma in pixels
    @param addPoissonNoise: add Poisson noise to the exposure?
    """
    # make an image with sources
    img = afwImage.ImageD(bbox)
    meanSigma = 0.0
    for coord in coordList:
        x, y, counts, sigma = coord
        meanSigma += sigma

        # make a single gaussian psf
        psf = afwDetection.GaussianPsf(kwid, kwid, sigma)

        # make an image of it and scale to the desired number of counts
        thisPsfImg = psf.computeImage(lsst.geom.PointD(int(x), int(y)))
        thisPsfImg *= counts

        # bbox a window in our image and add the fake star image
        imgSeg = img.Factory(img, thisPsfImg.getBBox())
        imgSeg += thisPsfImg
    meanSigma /= len(coordList)

    img += sky

    # add Poisson noise
    if (addPoissonNoise):
        np.random.seed(seed=1)  # make results reproducible
        imgArr = img.getArray()
        imgArr[:] = np.random.poisson(imgArr)

    # bundle into a maskedimage and an exposure
    mask = afwImage.Mask(bbox)
    var = img.convertFloat()
    img -= sky
    mimg = afwImage.MaskedImageF(img.convertFloat(), mask, var)
    exposure = afwImage.makeExposure(mimg)

    # insert an approximate psf
    psf = afwDetection.GaussianPsf(kwid, kwid, meanSigma)
    exposure.setPsf(psf)

    return exposure
示例#3
0
    def testHsmPsfMoments(self):
        for width in (2.0, 3.0, 4.0):
            psf = afwDetection.GaussianPsf(35, 35, width)
            exposure = afwImage.ExposureF(45, 56)
            exposure.getMaskedImage().set(1.0, 0, 1.0)
            exposure.setPsf(psf)

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

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

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

            self.assertAlmostEqual(xx, expected.getIxx(), SHAPE_DECIMALS)
            self.assertAlmostEqual(xy, expected.getIxy(), SHAPE_DECIMALS)
            self.assertAlmostEqual(yy, expected.getIyy(), SHAPE_DECIMALS)
示例#4
0
def makeExposure(bbox, scale, psfFwhm, flux):
    """Make a fake exposure

    @param bbox: Bounding box for image (Box2I)
    @param scale: Pixel scale (Angle)
    @param psfFwhm: PSF FWHM (arcseconds)
    @param flux: PSF flux (ADU)
    @return Exposure, source center
    """
    image = afwImage.ImageF(bbox)
    image.set(0)
    center = afwGeom.Box2D(bbox).getCenter()
    psfSigma = psfFwhm / SIGMA_TO_FWHM / scale.asArcseconds()
    psfWidth = 2 * int(4.0 * psfSigma) + 1
    psf = afwDetection.GaussianPsf(psfWidth, psfWidth, psfSigma)
    psfImage = psf.computeImage(center).convertF()
    psfFlux = psfImage.getArray().sum()
    psfImage *= flux / psfFlux

    subImage = afwImage.ImageF(image, psfImage.getBBox(afwImage.PARENT),
                               afwImage.PARENT)
    subImage += psfImage

    exp = afwImage.makeExposure(afwImage.makeMaskedImage(image))
    exp.setPsf(psf)
    exp.getMaskedImage().getVariance().set(1.0)
    exp.getMaskedImage().getMask().set(0)

    exp.setWcs(
        afwImage.makeWcs(
            afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees),
            center, scale.asDegrees(), 0.0, 0.0, scale.asDegrees()))
    return exp, center
示例#5
0
    def getPsf(self, exposure, sigma=None):
        """Retrieve the PSF for an exposure

        If ``sigma`` is provided, we make a ``GaussianPsf`` with that,
        otherwise use the one from the ``exposure``.

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            Exposure from which to retrieve the PSF.
        sigma : `float`, optional
            Gaussian sigma to use if provided.

        Returns
        -------
        psf : `lsst.afw.detection.Psf`
            PSF to use for detection.
        """
        if sigma is None:
            psf = exposure.getPsf()
            if psf is None:
                raise RuntimeError("Unable to determine PSF to use for detection: no sigma provided")
            sigma = psf.computeShape().getDeterminantRadius()
        size = self.calculateKernelSize(sigma)
        psf = afwDet.GaussianPsf(size, size, sigma)
        return psf
示例#6
0
    def testMeasurePsf(self):
        """Test that we measure the Psf only when we want to and fail when we can't."""
        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

        psf = afwDetection.GaussianPsf(101, 101, 3.0)
        psfImage = psf.computeKernelImage()
        exposure1 = afwImage.ExposureF(psfImage.getBBox(afwImage.PARENT))
        exposure1.getMaskedImage().getImage().getArray(
        )[:, :] = psfImage.getArray()
        exposure1.getMaskedImage().getVariance().set(0.1)
        # We try to measure the Psf shape, but we don't have one: flag should be set
        record1 = doMeasure(exposure1, algorithms.SdssShapeConfig())
        self.assertTrue(record1.get("shape.sdss.flags.psf"))
        # We don't try to measure the Psf shape: extra fields should not be present
        record2 = doMeasure(exposure1,
                            algorithms.SdssShapeConfig(doMeasurePsf=False))
        self.assertFalse("shape.sdss.flags.psf" in record2.schema)
        self.assertFalse("shape.sdss.psf" in record2.schema)
        # We try to measure the Psf shape, and do have one: shape of image should match shape of Psf
        exposure1.setPsf(psf)
        record3 = doMeasure(exposure1, algorithms.SdssShapeConfig())
        self.assertFalse(record3.get("shape.sdss.flags.psf"))
        self.assertFalse(record3.get("shape.sdss.flags"))
        self.assertClose(record3.get("shape.sdss.psf").getParameterVector(),
                         record3.get("shape.sdss").getParameterVector(),
                         rtol=1E-4)
示例#7
0
    def setUp(self):
        """Make the image we'll measure.
        """

        self.exp = afwImage.ExposureF(100, 100)
        psf = afwDetection.GaussianPsf(15, 15, 3.0)
        self.exp.setPsf(psf)
        self.I0, self.xcen, self.ycen = 1000.0, 50.5, 50.0
        im = self.exp.getMaskedImage().getImage()

        for i in (-1, 0, 1):
            for j in (-1, 0, 1):
                im[int(self.xcen) + i, int(self.ycen) + j, afwImage.LOCAL] = \
                    self.I0*(1 - 0.5*math.hypot(i - 0.5, j))
示例#8
0
    def do_testAstrometry(self, alg, bkgd, control):
        """Test that we can instantiate and play with a centroiding algorithm.
        """

        schema = afwTable.SourceTable.makeMinimalSchema()
        schema.getAliasMap().set("slot_Centroid", "test")
        centroider = alg(control, "test", schema)
        table = afwTable.SourceCatalog(schema)

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

            im = imageFactory(lsst.geom.ExtentI(100, 100))
            im.setXY0(lsst.geom.Point2I(x0, y0))

            # This fixed DoubleGaussianPsf replaces a computer generated one.
            # The values are not anything in particular, just a reasonable size.
            psf = afwDetection.GaussianPsf(15, 15, 3.0)
            exp = afwImage.makeExposure(im)
            exp.setPsf(psf)

            im.set(bkgd)
            x, y = 30, 20
            im.image[x, y, afwImage.LOCAL] = 1010

            source = table.addNew()
            spans = afwGeom.SpanSet(exp.getBBox(afwImage.LOCAL))
            foot = afwDetection.Footprint(spans)
            foot.addPeak(x + x0, y + y0, 1010)
            source.setFootprint(foot)
            centroider.measure(source, exp)

            self.assertFloatsAlmostEqual(x + x0, source.getX(), rtol=.00001)
            self.assertFloatsAlmostEqual(y + y0, source.getY(), rtol=.00001)
            self.assertFalse(source.get("test_flag"))

            im.set(bkgd)
            im.image[10, 20, afwImage.LOCAL] = 1010
            im.image[10, 21, afwImage.LOCAL] = 1010
            im.image[11, 20, afwImage.LOCAL] = 1010
            im.image[11, 21, afwImage.LOCAL] = 1010

            x, y = 10.5 + x0, 20.5 + y0
            source = table.addNew()
            source.set('test_x', x)
            source.set('test_y', y)
            centroider.measure(source, exp)
            self.assertFloatsAlmostEqual(x, source.getX(), rtol=.00001)
            self.assertFloatsAlmostEqual(y, source.getY(), rtol=.00001)
            self.assertFalse(source.get("test_flag"))
示例#9
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)
示例#10
0
def makeExposure(bbox, scale, psfFwhm, flux):
    """Make a fake exposure

    Parameters
    ----------

    bbox : `lsst.afw.geom.Box2I`
        Bounding box for image.
    scale : `lsst.afw.geom.Angle`
        Pixel scale.
    psfFwhm : `float`
        PSF FWHM (arcseconds)
    flux : `float`
        PSF flux (ADU)

    Returns
    -------
    exposure : `lsst.afw.image.ExposureF`
        Fake exposure.
    center : `lsst.afw.geom.Point2D`
        Position of fake source.
    """
    image = afwImage.ImageF(bbox)
    image.set(0)
    center = afwGeom.Box2D(bbox).getCenter()
    psfSigma = psfFwhm / SIGMA_TO_FWHM / scale.asArcseconds()
    psfWidth = 2 * int(4.0 * psfSigma) + 1
    psf = afwDetection.GaussianPsf(psfWidth, psfWidth, psfSigma)
    psfImage = psf.computeImage(center).convertF()
    psfFlux = psfImage.getArray().sum()
    psfImage *= flux / psfFlux

    subImage = afwImage.ImageF(image, psfImage.getBBox(afwImage.PARENT),
                               afwImage.PARENT)
    subImage += psfImage

    exp = afwImage.makeExposure(afwImage.makeMaskedImage(image))
    exp.setPsf(psf)
    exp.getMaskedImage().getVariance().set(1.0)
    exp.getMaskedImage().getMask().set(0)

    cdMatrix = afwGeom.makeCdMatrix(scale=scale)
    exp.setWcs(
        afwGeom.makeSkyWcs(crpix=center,
                           crval=afwGeom.SpherePoint(0.0, 0.0,
                                                     afwGeom.degrees),
                           cdMatrix=cdMatrix))
    return exp, center
示例#11
0
    def testDM17431(self):
        """Test that priority order is respected

        specifically when lower priority footprints overlap two previously
        disconnected higher priority footprints.
        """
        box = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                              lsst.geom.Point2I(100, 100))
        psfsig = 1.
        kernelSize = 41
        flux = 1000
        cat1 = {}
        cat2 = {}
        peakDist = 10
        samePeakDist = 3

        # cat2 connects cat1's 2 separated footprints.
        # 65 and 70 are too close to be new or same peaks.
        # 70 is higher priority and should be in the catalog instead of 65.
        cat1['pos'] = [(50, 50), (70, 50)]
        cat2['pos'] = [(55, 50), (65, 50)]
        schema = afwTable.SourceTable.makeMinimalSchema()
        idFactory = afwTable.IdFactory.makeSimple()
        table = afwTable.SourceTable.make(schema, idFactory)

        for (cat, psfFactor) in zip([cat1, cat2], [1, 2]):
            cat['mi'] = afwImage.MaskedImageD(box)
            cat['psf'] = afwDetect.GaussianPsf(kernelSize, kernelSize,
                                               psfFactor * psfsig)
            insertPsf(cat['pos'], cat['mi'], cat['psf'], kernelSize, flux)
            fp = afwDetect.FootprintSet(cat['mi'], afwDetect.Threshold(0.001),
                                        "DETECTED")
            cat['catalog'] = afwTable.SourceCatalog(table)
            fp.makeSources(cat['catalog'])

        merge, nob, npeak = mergeCatalogs([cat1['catalog'], cat2['catalog']],
                                          ["1", "2"],
                                          peakDist,
                                          idFactory,
                                          samePeakDist=samePeakDist)

        # Check that both higher-priority cat1 records survive peak merging
        for record in cat1['catalog']:
            for peak in record.getFootprint().getPeaks():
                self.assertTrue(isPeakInCatalog(peak, merge))
示例#12
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)
def makeGalaxy(width,
               height,
               flux,
               a,
               b,
               theta,
               dx=0.0,
               dy=0.0,
               xy0=None,
               xcen=None,
               ycen=None):
    """Make a fake galaxy image.
    """
    gal = afwImage.ImageF(width, height)
    if xcen is None:
        xcen = 0.5 * width + dx
    if ycen is None:
        ycen = 0.5 * height + dy
    I0 = flux / (2 * math.pi * a * b)

    if xy0 is not None:
        gal.setXY0(xy0)

    c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta))
    ii, iuu, ivv = 0.0, 0.0, 0.0
    for y in range(height):
        for x in range(width):
            dx, dy = x + gal.getX0() - xcen, y + gal.getY0() - ycen
            if math.hypot(dx, dy) < 10.5:
                nsample = 5
                subZ = np.linspace(-0.5 * (1 - 1 / nsample),
                                   0.5 * (1 - 1 / nsample), nsample)
            else:
                nsample = 1
                subZ = [0.0]

            val = 0
            for sx in subZ:
                for sy in subZ:
                    u = c * (dx + sx) + s * (dy + sy)
                    v = -s * (dx + sx) + c * (dy + sy)
                    val += I0 * math.exp(-0.5 * ((u / a)**2 + (v / b)**2))

            if val < 0:
                val = 0
            gal[afwGeom.Point2I(x, y), afwImage.LOCAL] = val / nsample**2

            ii += val
            iuu += val * u**2
            ivv += val * v**2

    iuu /= ii
    ivv /= ii

    exp = afwImage.makeExposure(afwImage.makeMaskedImage(gal))
    exp.getMaskedImage().getVariance().set(1.0)
    scale = 1.0e-4 * afwGeom.degrees
    cdMatrix = afwGeom.makeCdMatrix(scale=scale, flipX=True)
    exp.setWcs(
        afwGeom.makeSkyWcs(crpix=afwGeom.Point2D(0.0, 0.0),
                           crval=afwGeom.SpherePoint(0.0, 0.0,
                                                     afwGeom.degrees),
                           cdMatrix=cdMatrix))
    # add a dummy Psf.  The new SdssCentroid needs one
    exp.setPsf(afwDetection.GaussianPsf(11, 11, 0.01))
    return exp
示例#14
0
def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True):
    """Make an exposure with stars (modelled as Gaussians).

    Parameters
    ----------
    bbox : `lsst.afw.geom.Box2I`
        Parent bounding box of output exposure.
    kwid : `float`
        Kernel width (and height; kernel is square).
    sky : `float`
        Amount of sky background (counts)
    coordList : iterable of `list`
        Where:
           - ``coordList[0]`` is the X coord of the star relative to the origin
           - ``coordList[1]`` is the Y coord of the star relative to the origin
           - ``coordList[2]`` is the integrated counts in the star
           - ``coordlist[3]`` is the Gaussian sigma in pixels.
    addPoissonNoise : `bool`, optional
        Add Poisson noise to the output exposure?

    Returns
    -------
    exposure : `lsst.afw.image.ExposureF`
        Resulting exposure with simulated stars.
    """
    # make an image with sources
    img = afwImage.ImageD(bbox)
    meanSigma = 0.0
    for coord in coordList:
        x, y, counts, sigma = coord
        meanSigma += sigma

        # make a single gaussian psf
        psf = afwDetection.GaussianPsf(kwid, kwid, sigma)

        # make an image of it and scale to the desired number of counts
        thisPsfImg = psf.computeImage(lsst.geom.PointD(int(x), int(y)))
        thisPsfImg *= counts

        # bbox a window in our image and add the fake star image
        imgSeg = img.Factory(img, thisPsfImg.getBBox())
        imgSeg += thisPsfImg
    meanSigma /= len(coordList)

    img += sky

    # add Poisson noise
    if (addPoissonNoise):
        np.random.seed(seed=1)  # make results reproducible
        imgArr = img.getArray()
        imgArr[:] = np.random.poisson(imgArr)

    # bundle into a maskedimage and an exposure
    mask = afwImage.Mask(bbox)
    var = img.convertFloat()
    img -= sky
    mimg = afwImage.MaskedImageF(img.convertFloat(), mask, var)
    exposure = afwImage.makeExposure(mimg)

    # insert an approximate psf
    psf = afwDetection.GaussianPsf(kwid, kwid, meanSigma)
    exposure.setPsf(psf)

    return exposure
示例#15
0
    rand.uniformInt(im.getWidth() - 2 * buffer_xy) + buffer_xy
    for i in xrange(n_objects)
]
y_positions = [
    rand.uniformInt(im.getHeight() - 2 * buffer_xy) + buffer_xy
    for i in xrange(n_objects)
]

print("x_positions , y_positions = ", x_positions, y_positions)

display = afwDisplay.getDisplay()
display.setMaskTransparency(50, None)
psf_size = 121  # This has to be odd
sigma = 0.7 / 0.2  # seeing in arcsec/pixel size in arcsec
peak_val = 6000
psf = afwDetect.GaussianPsf(psf_size, psf_size, sigma)
psf_im = psf.computeImage()

print("psf = ", psf)

print("psf_im = ", psf_im)

for x, y in zip(x_positions, y_positions):
    x0 = x - (psf_size - 1) / 2
    y0 = y - (psf_size - 1) / 2
    box = afwGeom.BoxI(afwGeom.PointI(x0, y0),
                       afwGeom.ExtentI(psf_size, psf_size))
    subim = afwImage.ImageF(im, box, afwImage.LOCAL)

try:
    subim += psf_im
示例#16
0
def main():

    date = datetime.datetime.now().strftime("%a %Y-%m-%d %H:%M:%S")

    ########################################################################
    # command line arguments and options
    ########################################################################

    parser = optparse.OptionParser(usage = __doc__)
    #parser.add_option("-a", "--aa", dest="aa", type=float,
    #                  default=1.0, help="default=%default")

    opts, args = parser.parse_args()

    if len(args) == 0:
        r1, r2, dr = 3.0, 3.0, 0.5
    elif len(args) == 3:
        r1, r2, dr = map(float, args)
    else:
        parser.print_help()
        sys.exit(1)


    # make a list of radii to compute the growthcurve points
    radius = []
    nR = int( (r2 - r1)/dr + 1 )
    for iR in range(nR):
        radius.append(r1 + iR*dr)


    # make an image big enough to hold the largest requested aperture
    xwidth = 2*(0 + 128)
    ywidth = xwidth

    # initializations
    sigmas = [1.5, 2.5]  # the Gaussian widths of the psfs we'll use
    nS = len(sigmas)
    a = 100.0
    aptaper = 2.0
    xcen = xwidth/2
    ycen = ywidth/2
    alg = measBase.PsfFluxAlgorithm
    schema = afwTable.SourceTable.makeMinimalSchema()
    schema.addField("centroid_x", type=float)
    schema.addField("centroid_y", type=float)
    plugin = alg(measBase.PsfFluxControl(), "test", schema)
    cat = afwTable.SourceCatalog(schema)
    cat.defineCentroid("centroid")
    print "# sig rad  Naive Sinc Psf"
    for iS in range(nS):
        sigma = sigmas[iS];

        # make a Gaussian star to measure
        gauss  = afwMath.GaussianFunction2D(sigma, sigma)
        kernel = afwMath.AnalyticKernel(xwidth, ywidth, gauss)
        kimg   = afwImage.ImageD(kernel.getDimensions())
        kernel.computeImage(kimg, False)
        kimg  *= 100.0
        mimg   = afwImage.MaskedImageF(kimg.convertFloat(),
                                       afwImage.MaskU(kimg.getDimensions(), 0x0),
                                       afwImage.ImageF(kimg.getDimensions(), 0.0))
        exposure = afwImage.ExposureF(mimg)

        # loop over all the radii in the growthcurve
        for iR in range(nR):

            psfH = int(2.0*(r2 + 2.0)) + 1
            psfW = int(2.0*(r2 + 2.0)) + 1

            # this test uses a single Gaussian instead of the original double gaussian
            psf = afwDet.GaussianPsf(psfW, psfH, sigma)

            # get the aperture fluxes for Naive and Sinc methods

            axes = afwGeom.ellipses.Axes(radius[iR], radius[iR], math.radians(0));
            center = afwGeom.Point2D(0,0)
            ellipse = afwGeom.ellipses.Ellipse(axes, center)
            resultSinc = measBase.ApertureFluxAlgorithm.computeSincFlux(mimg.getImage(), ellipse)
            resultNaive = measBase.ApertureFluxAlgorithm.computeNaiveFlux(mimg.getImage(), ellipse)
            source = cat.addNew()
            source["centroid_x"] = 0
            source["centroid_y"] = 0
            exposure.setPsf(psf)
            plugin.measure(source, exposure)
            fluxNaive = resultNaive.flux
            fluxSinc = resultSinc.flux
            fluxPsf   = source["test_flux"]

            # get the exact flux for the theoretical smooth PSF
            # rpsf = RGaussian(sigma, a, radius[iR], aptaper)
            # *** not sure how to integrate a python functor ***

            print "%.2f %.2f  %.3f %.3f %.3f" % (sigma, radius[iR], fluxNaive, fluxSinc, fluxPsf)
示例#17
0
    def testPeakLikelihoodFlux(self):
        """Test measurement with PeakLikelihoodFlux
        """
        # 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 = afwDetection.GaussianPsf(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()
            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())
            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())
                    afwMath.convolve(filteredImage, maskedImage, psfKernel,
                                     convolutionControl)

                exp = afwImage.makeExposure(filteredImage)
                exp.setPsf(psf)
                control = measBase.PeakLikelihoodFluxControl()
                plugin, cat = makePluginAndCat(
                    measBase.PeakLikelihoodFluxAlgorithm,
                    "test",
                    control,
                    centroid="centroid")
                source = cat.makeRecord()
                source.set("centroid_x", adjCenter.getX())
                source.set("centroid_y", adjCenter.getY())
                plugin.measure(source, exp)
                measFlux = source.get("test_flux")
                measFluxErr = source.get("test_fluxSigma")
                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)
                        source = cat.makeRecord()
                        source.set("centroid_x", offsetCtr.getX())
                        source.set("centroid_y", offsetCtr.getY())
                        plugin.measure(source, exp)
                        self.assertLess(source.get("test_flux"), 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),
        ):
            source = cat.makeRecord()
            source.set("centroid_x", edgePos[0])
            source.set("centroid_y", edgePos[1])
            self.assertRaises(
                lsst.pex.exceptions.RangeError,
                plugin.measure,
                source,
                exp,
            )

        # no PSF should result in failure: flags set
        noPsfExposure = afwImage.ExposureF(filteredImage)
        source = cat.makeRecord()
        source.set("centroid_x", edgePos[0])
        source.set("centroid_y", edgePos[1])
        self.assertRaises(
            lsst.pex.exceptions.InvalidParameterError,
            plugin.measure,
            source,
            noPsfExposure,
        )
示例#18
0
    def setUp(self):
        size = 128  # size of image (pixels)
        center = afwGeom.Point2D(size // 2, size // 2)  # object center
        width = 2  # PSF width
        flux = 10.0  # Flux of object
        variance = 1.0  # Mean variance value
        varianceStd = 0.1  # Standard deviation of the variance value

        # Set a seed for predictable randomness
        np.random.seed(300)

        # Create a random image to be used as variance plane
        variancePlane = np.random.normal(variance, varianceStd,
                                         size * size).reshape(size, size)

        # 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.getArray()[:, :] = variancePlane

        # Put down a PSF
        psfSize = int(6 * width + 1)  # Size of PSF image; must be odd
        psf = afwDetection.GaussianPsf(psfSize, psfSize, 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")

        # Put in some unmasked bad pixels outside the expected aperture, to ensure the aperture is working
        var.getArray()[0, 0] = float("nan")
        var.getArray()[0, -1] = float("nan")
        var.getArray()[-1, 0] = float("nan")
        var.getArray()[-1, -1] = float("nan")

        if display:
            import lsst.afw.display as afwDisplay
            afwDisplay.getDisplay(1).mtv(image)
            afwDisplay.getDisplay(2).mtv(mask)
            afwDisplay.getDisplay(3).mtv(var)

        config = measBase.SingleFrameMeasurementConfig()
        config.plugins.names = [
            "base_NaiveCentroid", "base_SdssShape", "base_Variance"
        ]
        config.slots.centroid = "base_NaiveCentroid"
        config.slots.psfFlux = None
        config.slots.apFlux = None
        config.slots.modelFlux = None
        config.slots.instFlux = None
        config.slots.calibFlux = None
        config.slots.shape = "base_SdssShape"
        config.slots.psfShape = None
        config.plugins["base_Variance"].mask = ["BAD", "SAT"]

        config.validate()
        schema = afwTable.SourceTable.makeMinimalSchema()

        task = measBase.SingleFrameMeasurementTask(schema, config=config)
        catalog = afwTable.SourceCatalog(schema)

        spans = afwGeom.SpanSet.fromShape(int(width))
        spans = spans.shiftedBy(int(center.getX()), int(center.getY()))
        foot = afwDetection.Footprint(spans)
        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)

        self.variance = variance
        self.varianceStd = varianceStd
        self.mask = mask
        self.catalog = catalog
        self.exp = exp
        self.task = task
        self.source = source
    def testForced(self):
        """Check that forced photometry works in the presence of rotations and translations.
        """
        kfac = 2.5
        warper = afwMath.Warper("lanczos4")
        a = 13
        for axisRatio in (0.25, 1.0):
            b = a * axisRatio
            for theta in (0, 30, 45):
                width, height = 256, 256
                center = afwGeom.Point2D(0.5 * width, 0.5 * height)
                original = makeGalaxy(width, height, 1000.0, a, b, theta)
                msConfig = makeMeasurementConfig(forced=False, kfac=kfac)
                source = measureFree(original, center, msConfig)
                algMeta = source.getTable().getMetadata()
                self.assertTrue(
                    algMeta.exists(
                        'ext_photometryKron_KronFlux_nRadiusForFlux'))
                if source.get("ext_photometryKron_KronFlux_flag"):
                    continue

                angleList = [val * afwGeom.degrees for val in (45, 90)]
                scaleList = [1.0, 0.5]
                offsetList = [(1.23, 4.56), (12.3, 45.6)]

                for angle, scale, offset in itertools.product(
                        angleList, scaleList, offsetList):
                    dx, dy = offset
                    pixelScale = original.getWcs().getPixelScale() * scale
                    cdMatrix = afwGeom.makeCdMatrix(scale=pixelScale,
                                                    orientation=angle,
                                                    flipX=True)
                    wcs = afwGeom.makeSkyWcs(crpix=afwGeom.Point2D(dx, dy),
                                             crval=afwGeom.SpherePoint(
                                                 0.0, 0.0, afwGeom.degrees),
                                             cdMatrix=cdMatrix)

                    warped = warper.warpExposure(wcs, original)
                    # add a Psf if there is none.  The new SdssCentroid needs a Psf.
                    if warped.getPsf() is None:
                        warped.setPsf(afwDetection.GaussianPsf(11, 11, 0.01))
                    msConfig = makeMeasurementConfig(kfac=kfac, forced=True)
                    forced = measureForced(warped, source, original.getWcs(),
                                           msConfig)
                    algMeta = source.getTable().getMetadata()
                    self.assertTrue(
                        algMeta.exists(
                            'ext_photometryKron_KronFlux_nRadiusForFlux'))

                    if display:
                        disp1 = afwDisplay.Display(frame=1)
                        disp1.mtv(original,
                                  title=self._testMethodName +
                                  ": original image")
                        shape = source.getShape().clone()
                        xc, yc = source.getCentroid()
                        radius = source.get(
                            "ext_photometryKron_KronFlux_radius")
                        for r, ct in [
                            (radius, afwDisplay.BLUE),
                            (radius * kfac, afwDisplay.CYAN),
                        ]:
                            shape.scale(r / shape.getDeterminantRadius())
                            disp1.dot(shape, xc, yc, ctype=ct)
                        disp2 = afwDisplay.Display(frame=2)
                        disp2.mtv(warped,
                                  title=self._testMethodName +
                                  ": warped image")
                        transform = (wcs.linearizeSkyToPixel(
                            source.getCoord(), lsst.geom.degrees) *
                                     original.getWcs().linearizePixelToSky(
                                         source.getCoord(), lsst.geom.degrees))
                        shape = shape.transform(transform.getLinear())
                        radius = source.get(
                            "ext_photometryKron_KronFlux_radius")
                        xc, yc = wcs.skyToPixel(source.getCoord())
                        for r, ct in [
                            (radius, afwDisplay.BLUE),
                            (radius * kfac, afwDisplay.CYAN),
                        ]:
                            shape.scale(r / shape.getDeterminantRadius())
                            disp2.dot(shape, xc, yc, ctype=ct)
                    try:
                        self.assertFloatsAlmostEqual(
                            source.get("ext_photometryKron_KronFlux_instFlux"),
                            forced.get("ext_photometryKron_KronFlux_instFlux"),
                            rtol=1.0e-3)
                        self.assertFloatsAlmostEqual(
                            source.get("ext_photometryKron_KronFlux_radius"),
                            scale *
                            forced.get("ext_photometryKron_KronFlux_radius"),
                            rtol=1.0e-3)
                        self.assertEqual(
                            source.get("ext_photometryKron_KronFlux_flag"),
                            forced.get("ext_photometryKron_KronFlux_flag"))
                    except Exception:
                        print(("Failed:", angle, scale, offset, [
                            (source.get(f), forced.get(f))
                            for f in ("ext_photometryKron_KronFlux_instFlux",
                                      "ext_photometryKron_KronFlux_radius",
                                      "ext_photometryKron_KronFlux_flag")
                        ]))
                        raise
示例#20
0
    def test(self):
        """Check that we can measure an aperture correction"""
        width, height = 1234, 2345
        edge = 25  # buffer around edge
        numStars = 10  # in each dimension
        size = 15  # Size of PSF
        sigma = 3.0  # PSF sigma

        measureConfig = SourceMeasurementConfig()
        measureConfig.algorithms["flux.sinc"].radius = size
        apCorrConfig = MeasureApCorrTask.ConfigClass()
        apCorrConfig.inputFilterFlag = "use.this"

        schema = afwTable.SourceTable.makeMinimalSchema()
        measurer = measureConfig.makeMeasureSources(schema)
        schema.addField("use.this",
                        type="Flag",
                        doc="use this for aperture correction")
        apCorr = MeasureApCorrTask(config=apCorrConfig, schema=schema)

        # Generate an image with a bunch of sources
        exposure = afwImage.ExposureF(width, height)
        psf = afwDetection.GaussianPsf(size, size, sigma)
        exposure.setPsf(psf)
        image = exposure.getMaskedImage().getImage()
        mask = exposure.getMaskedImage().getMask()
        mask.addMaskPlane("DETECTED")
        detected = mask.getPlaneBitMask("DETECTED")
        xList = numpy.linspace(edge, width - edge, numStars)
        yList = numpy.linspace(edge, height - edge, numStars)
        for x in xList:
            for y in yList:
                psfImage = psf.computeImage(afwGeom.Point2D(x, y)).convertF()
                psfImage *= 10000
                bbox = psfImage.getBBox(afwImage.PARENT)
                subImage = image.Factory(image, bbox)
                subImage += psfImage

        # Detect and measure those sources
        catalog = afwTable.SourceCatalog(schema)
        measureConfig.slots.setupTable(catalog.table)
        feet = afwDetection.FootprintSet(exposure.getMaskedImage(),
                                         afwDetection.Threshold(0.1),
                                         "DETECTED")
        feet.makeSources(catalog)
        self.assertGreater(len(catalog), 0)
        for source in catalog:
            measurer.applyWithPeak(source, exposure)
            source.set("use.this", True)

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

        # Cheat in order to trigger clipping in aperture correction measurement
        good = numpy.ones(len(catalog), dtype=bool)
        good[len(catalog) // 3] = False
        catalog[apCorrConfig.reference][numpy.where(good == 0)] *= 2

        apCorrMap = apCorr.run(exposure.getBBox(), catalog)

        # Validate answers
        self.assertGreater(len(apCorrMap),
                           0)  # Or we're not really testing anything
        for name in apCorrMap:
            expected = (catalog[apCorrConfig.reference][good] /
                        catalog[name][good]).mean()
            corr = apCorrMap[name]
            for x in xList:
                for y in yList:
                    value = corr.evaluate(x, y)
                    if name.endswith(".err"):
                        self.assertLess(value, 5.0e-4)
                    else:
                        self.assertClose(corr.evaluate(x, y),
                                         expected,
                                         atol=5.0e-4)

            if not name.endswith(".err"):
                self.assertTrue(
                    numpy.all(catalog["apcorr." + name +
                                      ".used"] == good))  # Used only good srcs