예제 #1
0
    def drawLabels(self, labels=None, frame=None):
        """Draw the list labels at the corners of each panel.  If labels is None, use the ones
        specified by Mosaic.append()"""

        if frame is None:
            return

        if not labels:
            labels = self.labels

        if not labels:
            return

        if len(labels) != self.nImage:
            raise RuntimeError, ("You provided %d labels for %d panels" % (len(labels), self.nImage))

        with ds9.Buffering():
            for i in range(len(labels)):
                if labels[i]:
                    label, ctype = labels[i], None
                    try:
                        label, ctype = label
                    except:
                        pass

                    if not label:
                        continue

                    ds9.dot(str(label), self.getBBox(i).getMinX(), self.getBBox(i).getMinY(),
                            frame=frame, ctype=ctype)
예제 #2
0
    def testLinearRamp(self):
        """Fit a ramp"""

        binsize = 1
        ramp, rampCoeffs, xVec, yVec = self.makeRamp(binsize)
        #
        # Add a (labelled) bad value
        #
        ramp.set(ramp.getWidth() // 2, ramp.getHeight() // 2, (0, 0x1, np.nan))

        if display:
            ds9.mtv(ramp, title="Input", frame=0)
        #
        # Here's the range that the approximation should be valid (and also the
        # bbox of the image returned by getImage)
        #
        bbox = afwGeom.BoxI(
            afwGeom.PointI(0, 0), afwGeom.PointI(binsize * ramp.getWidth() - 1, binsize * ramp.getHeight() - 1)
        )

        order = 3  # 1 would be enough to fit the ramp
        actrl = afwMath.ApproximateControl(afwMath.ApproximateControl.CHEBYSHEV, order)
        approx = afwMath.makeApproximate(xVec, yVec, ramp, bbox, actrl)

        for i, aim in enumerate([approx.getImage(), approx.getMaskedImage().getImage()]):
            if i == 0 and display:
                ds9.mtv(aim, title="interpolated", frame=1)
                with ds9.Buffering():
                    for x in xVec:
                        for y in yVec:
                            ds9.dot("+", x, y, size=0.4, frame=1)

            for x, y in aim.getBBox().getCorners():
                self.assertEqual(aim.get(x, y), rampCoeffs[0] + rampCoeffs[1] * x + rampCoeffs[1] * y)
예제 #3
0
def view(cat=None, exp=None, tract=None, patch=None, ID=None, coords=None, filter='I', frame=0, scale="zscale",\
         zoom="to fit", trans=80, draw_ells=True, maxsep=None, shape_model='shape.hsm.moments', pcolor=ds9.GREEN, ccolor=ds9.RED):

    if cat is None:
        assert (tract is not None) and (patch is not None), 'if no cat is given, must give tract and patch'
        exp = butler.get("deepCoadd_calexp", tract=tract, patch=patch, filter='HSC-'+filter, immediate=True)
        cat = butler.get("deepCoadd_meas", tract=tract, patch=patch, filter='HSC-'+filter, immediate=True)
    else:
        assert exp is not None, 'if cat is given, must also give exp'
    x0, y0 = exp.getXY0()
    settings = {'scale':scale, 'zoom': zoom, 'mask' : 'transparency %d' %(trans)}
    ds9.mtv(exp, frame=frame, settings=settings)

    #########################################################
    # maxsep is used if you only want to draw ellipses around
    # objects within a distance maxsep from a candidate
    #########################################################
    if maxsep is not None:
        if ID is not None:
            obj = cat.find(ID)
            ra0, dec0 = obj.getRa().asDegrees(), obj.getDec().asDegrees()
        else:
            ra0, dec0 = coords
        ra, dec = cat.get('coord.ra')*180./np.pi, cat.get('coord.dec')*180./np.pi
        seps = angsep(ra0, dec0, ra, dec)
        cut = seps < maxsep
        cat = cat[seps < maxsep].copy(deep=True)

    if draw_ells:
        with ds9.Buffering(): 
            for i,source in enumerate(cat):
                ellcolor = pcolor if source.get('parent')==0 else ccolor
                ixx, ixy, iyy = [source.get(shape_model+_x) for _x in ['.xx', '.xy', '.yy']]
                symbol = "@:{ixx},{ixy},{iyy}".format(ixx=ixx, ixy=ixy, iyy=iyy)
                ds9.dot(symbol, source.getX()-x0, source.getY()-y0, ctype=ellcolor, frame=frame)
def showStandards(standardStarSet, exp, frame, countsMin=None, flagMask=None, rmsMax=None, ctype=ds9.RED):
    """Show all the standards that are visible on this exposure

    If countsMin is not None, only show brighter Sources

    If flagMask is not None, ignore sources that have (flags & ~flagMask) != 0
    """

    wcs = exp.getWcs()
    width, height = exp.getMaskedImage().getWidth(), exp.getMaskedImage().getHeight()
    
    for s in standardStarSet:
        x,y = wcs.skyToPixel(s.getRaDec())

        if x < 0 or x >= width or y < 0 or y >= height:
            continue

        counts = s.getPsfFlux()

        if counts < countsMin and countsMin is not None:
            continue

        if flagMask is not None:
            if (s.getFlagForDetection() & ~flagMask) != 0:
                continue

        rms = math.sqrt(s.getIxx() + s.getIyy())
        if rmsMax is not None and rms > rmsMax:
            continue

        if False:
            pt = "%.1f" % (rms)
        else:
            pt = "+"
        ds9.dot(pt, x, y, frame=frame, ctype=ctype)
예제 #5
0
파일: muon.py 프로젝트: mmmerlin/my_code
def main(expName, config, display=False):
    exp = afwImage.ExposureF(expName)

    # Assume exposure is bias-subtracted, CCD-assembled, has variance and mask plane.
    # If not, put code here to fix what's lacking.

    bg, bgSubExp = estimateBackground(exp, config.background, subtract=True)

    detection = SourceDetectionTask(config=config.detection)
    detResults = detection.detectFootprints(bgSubExp, sigma=config.psfSigma)

    fpSet = detResults.positive

    print "Found %d positive footprints" % len(fpSet.getFootprints())

    if display:
        print "Displaying results..."
        import lsst.afw.display.ds9 as ds9
        frame = 1
        ds9.mtv(bgSubExp, frame=frame, title="Background-subtracted exposure")
        with ds9.Buffering():
            for fp in fpSet.getFootprints():
                peakList = fp.getPeaks()
                for p in peakList:
                    ds9.dot("x", p.getFx(), p.getFy(), frame=frame)

    # XXX Work with footprints here

    psf = measAlg.SingleGaussianPsf(config.psfSize, config.psfSize, config.psfSigma)
    exp.setPsf(psf)

    cosmicray(exp, config.cosmicray, display=display)
예제 #6
0
def main(rootDir, visit, ccd, frame=1, title="", scale="zscale", zoom="to fit", trans=60, useEllipse=False):

    # make a butler and specify your dataId
    butler = dafPersist.Butler(rootDir)
    dataId = {'visit': visit, 'ccd':ccd}

    # get the exposure from the butler
    exposure = butler.get('calexp', dataId)

    # put the settings in a dict object and call ds9.mtv()
    settings = {'scale':scale, 'zoom': zoom, 'mask' : 'transparency %d' %(trans)}
    ds9.mtv(exposure, frame=frame, title=title, settings=settings)


    # now get the source catalog and overplot the points

    sources = butler.get('src', dataId)

    with ds9.Buffering():
        for i,source in enumerate(sources):
            color = ds9.RED
            size = 5.0
            
            if useEllipse:
                # show an ellipse symbol
                symbol = "@:{ixx},{ixy},{iyy}".format(ixx=source.getIxx(),
                                                      ixy=source.getIxy(),
                                                      iyy=source.getIyy())
            else:
                # just a simple point (symbols +, x, *, o are all accepted)
                symbol = "o"
                
            ds9.dot(symbol, source.getX(), source.getY(), ctype=color,
                    size=size, frame=frame, silent=True)
예제 #7
0
    def testFootprintFromEllipse(self):
        """Create an elliptical Footprint"""
        cen = afwGeom.Point2D(23, 25)
        a, b, theta = 25, 15, 30
        ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(a, b, math.radians(theta)),  cen)
        foot = afwDetect.Footprint(ellipse, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(50, 60)))

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

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

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

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

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

        self.assertEqual(foot.getCentroid(), cen)
        self.assertTrue(abs(a - axes.getA()) < 0.15, "a: %g v. %g" % (a, axes.getA()))
        self.assertTrue(abs(b - axes.getB()) < 0.02, "b: %g v. %g" % (b, axes.getB()))
        self.assertTrue(abs(theta - math.degrees(axes.getTheta())) < 0.2,
                        "theta: %g v. %g" % (theta, math.degrees(axes.getTheta())))
예제 #8
0
    def setUp(self):
        im = afwImage.ImageF(self.monetFile("small.fits"))
        self.mi = afwImage.MaskedImageF(im, afwImage.MaskU(im.getDimensions()),
                                        afwImage.ImageF(im.getDimensions()));
        self.ds = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(100))

        if display:
            ds9.mtv(self.mi.getImage())
            ds9.erase()
            
        for foot in self.ds.getFootprints():
            bbox = foot.getBBox()
            x0, y0 = bbox.getMinX(), bbox.getMinY()
            x1, y1 = bbox.getMaxX(), bbox.getMaxY()
            xc = (x0 + x1)/2.0
            yc = (y0 + y1)/2.0
            
            if display:
                ds9.dot("+", xc, yc, ctype=ds9.BLUE)

                if False:
                    x0 -= 0.5; y0 -= 0.5
                    x1 += 0.5; y1 += 0.5
                    
                    ds9.line([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)], ctype=ds9.RED)

        self.control = algorithms.GaussianCentroidControl()
        schema = afwTable.SourceTable.makeMinimalSchema()
        self.centroider = algorithms.MeasureSourcesBuilder().addAlgorithm(self.control).build(schema)
        self.ssMeasured = afwTable.SourceCatalog(schema)
        self.ssMeasured.table.defineCentroid(self.control.name)
        self.ssTruth = afwTable.SourceCatalog(schema)
        self.readTruth(self.monetFile("positions.dat-original"))
예제 #9
0
파일: utils.py 프로젝트: RayPlante/DMS.afw
def showCamera(camera, imageSource=SynthesizeCcdImage(), imageFactory=afwImage.ImageU,
               frame=None, overlay=True, bin=1):
    """Show a Camera on ds9 (with the specified frame); if overlay show the IDs and amplifier boundaries

If imageSource is provided its getImage method will be called to return a CCD image (e.g. a
cameraGeom.GetCcdImage object); if it is "", an image will be created based on the properties
of the detectors"""

    if imageSource is None:
        cameraImage = None
    elif isinstance(imageSource, GetCcdImage):
        cameraImage = makeImageFromCamera(camera, imageSource, bin=bin, imageFactory=imageFactory)
    else:
        cameraImage = imageSource

    if cameraImage:
        ds9.mtv(cameraImage, frame=frame, title=camera.getId().getName())

    for det in camera:
        raft = cameraGeom.cast_Raft(det)
        
        center = camera.getCenterPixel() + afwGeom.Extent2D(raft.getCenterPixel())

        if overlay:
            bbox = raft.getAllPixels()
            ds9.dot(raft.getId().getName(), center[0]/bin, center[1]/bin, frame=frame)

        showRaft(raft, None, frame=frame, overlay=overlay,
                 raftOrigin=center - afwGeom.makeExtentD(raft.getAllPixels().getWidth()/2,
                                                         raft.getAllPixels().getHeight()/2), 
                 bin=bin)
예제 #10
0
 def plotPeaks(fps, ctype):
     if fps is None:
         return
     with ds9.Buffering():
         for fp in fps.getFootprints():
             for pp in fp.getPeaks():
                 ds9.dot("+", pp.getFx() - x0, pp.getFy() - y0, ctype=ctype)
예제 #11
0
def run(display=False):
    #
    # Create the task
    #
    config = CalibrateTask.ConfigClass()
    config.initialPsf.pixelScale = 0.185 # arcsec per pixel
    config.initialPsf.fwhm = 1.0
    config.astrometry.retarget(MyAstrometryTask)
    calibrateTask = CalibrateTask(config=config)
    #
    # Process the data
    #
    exposure = loadData(config.initialPsf.pixelScale)
    result = calibrateTask.run(exposure)

    exposure0, exposure = exposure, result.exposure
    sources = result.sources

    if display:                         # display on ds9 (see also --debug argparse option)
        frame = 1
        ds9.mtv(exposure, frame=frame)

        with ds9.Buffering():
            for s in sources:
                xy = s.getCentroid()
                ds9.dot('+', *xy, ctype=ds9.CYAN if s.get("flags_negative") else ds9.GREEN, frame=frame)
예제 #12
0
def main(rootDir, visit, ccd, frame=1, title="", scale="zscale", zoom="to fit", trans=60, useEllipse=False):

    # butler を開き読み込みたいデータの dataId を指定する
    butler = dafPersist.Butler(rootDir)
    dataId = {'visit': visit, 'ccd':ccd}

    # butler から一次処理済データを読み込む
    exposure = butler.get('calexp', dataId)

    # 読み込みたい天体情報を設定し、ds9.mtv() を読み込む
    settings = {'scale':scale, 'zoom': zoom, 'mask' : 'transparency %d' %(trans)}
    ds9.mtv(exposure, frame=frame, title=title, settings=settings)


    # 天体カタログを取得し、データ点を重ねて表示する

    sources = butler.get('src', dataId)

    with ds9.Buffering():
        for i,source in enumerate(sources):
            color = ds9.RED
            size = 5.0
            
            if useEllipse:
                # 楕円体のシンボルで表示
                symbol = "@:{ixx},{ixy},{iyy}".format(ixx=source.getIxx(),
                                                      ixy=source.getIxy(),
                                                      iyy=source.getIyy())
            else:
                # シンプルなシンボルで表示(例えば、 +, x, *, o が使える)
                symbol = "o"
                
            ds9.dot(symbol, source.getX(), source.getY(), ctype=color,
                    size=size, frame=frame, silent=True)
def detectSources(exposure, threshold, psf=None):
    """Detect sources above positiveThreshold in the provided exposure returning the sourceList
    """

    if not psf:
        FWHM = 5
        psf = algorithms.createPSF("DoubleGaussian", 15, 15, FWHM/(2*math.sqrt(2*math.log(2))))

    #
    # Subtract background
    #
    mi = exposure.getMaskedImage()
    bctrl = afwMath.BackgroundControl(afwMath.NATURAL_SPLINE);
    bctrl.setNxSample(int(mi.getWidth()/256) + 1);
    bctrl.setNySample(int(mi.getHeight()/256) + 1);
    backobj = afwMath.makeBackground(mi.getImage(), bctrl)

    img = mi.getImage(); img -= backobj.getImageF(); del img

    if display:
        ds9.mtv(exposure)

    ds = detectFootprints(exposure, threshold)

    objects = ds.getFootprints()
    #
    # Time to actually measure
    #
    measPipelineDir = lsst.utils.getPackageDir('meas_pipeline')
    moPolicy = policy.Policy.createPolicy(os.path.join(measPipelineDir,
                                                       "policy", "MeasureSources.paf"))
    moPolicy = moPolicy.getPolicy("measureObjects")

    measureSources = algorithms.makeMeasureSources(exposure, moPolicy, psf)

    sourceList = afwDetection.SourceSet()
    for i in range(len(objects)):
        source = afwDetection.Source()
        sourceList.append(source)

        source.setId(i)
        source.setFlagForDetection(source.getFlagForDetection() | algorithms.Flags.BINNED1);

        try:
            measureSources.apply(source, objects[i])
        except Exception:
            pass

        if source.getFlagForDetection() & algorithms.Flags.EDGE:
            continue

        if display:
            xc, yc = source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0()
            if False:
                ds9.dot("%.1f %d" % (source.getPsfFlux(), source.getId()), xc, yc+1)

            ds9.dot("+", xc, yc, size=1)

    return sourceList
예제 #14
0
def main(rootDir, visit, ccd, filter=None,
         frame=1, title="", scale="zscale", zoom="to fit", trans=60,
         useEllipse=False, maskOnly=False):

    if ccd.find(",") < 0:
        ccd = int(ccd)

    pipeVersion = dafPersist.eupsVersions.EupsVersions().versions['hscPipe']
    if StrictVersion(pipeVersion) >= StrictVersion('3.9.0'):
        coaddData = "deepCoadd_calexp"
        coaddCat  = "meas"
    else:
        coaddData = "deepCoadd"
        coaddCat  = "src"

    print "Read in %s image"%coaddData

    # make a butler and specify your dataId
    butler = dafPersist.Butler(rootDir)
    if filter:
        dataId = {'tract': visit, 'patch':ccd, 'filter': filter}
        exposure = butler.get(coaddData, dataId, immediate=True)
        butlerTarget='deepCoadd_'
        sources = butler.get(butlerTarget + coaddCat, dataId)
    else:
        dataId = {'visit': visit, 'ccd':ccd}
        exposure = butler.get("calexp", dataId, immediate=True)
        butlerTarget=""
        sources = butler.get(butlerTarget + 'src', dataId)

    # put the settings in a dict object and call ds9.mtv()
    settings = {'scale':scale, 'zoom': zoom, 'mask' : 'transparency %d' %(trans)}
    ds9.setMaskPlaneColor('FAKE', color=ds9.CYAN)
    if not maskOnly:
        ds9.mtv(exposure, frame=frame, title=title, settings=settings)
    else:
        msk = exposure.getMaskedImage().getMask()
        msk &= msk.getPlaneBitMask('FAKE')
        ds9.mtv(msk, frame=frame, title=title, settings=settings)

    with ds9.Buffering():
        print len(sources)
        x0, y0 = exposure.getXY0()
        print x0, y0
        for i,source in enumerate(sources):
            color = ds9.RED
            size = 5.0

            if useEllipse:
                # show an ellipse symbol
                symbol = "@:{ixx},{ixy},{iyy}".format(ixx=source.getIxx(),
                                                      ixy=source.getIxy(),
                                                      iyy=source.getIyy())
            else:
                # just a simple point (symbols +, x, *, o are all accepted)
                symbol = "o"

            ds9.dot(symbol, source.getX()-x0, source.getY()-y0, ctype=color,
                    size=size, frame=frame, silent=True)
def selectPsfSources(exposure, matches, psfPolicy):
    """Get a list of suitable stars to construct a PSF."""

    import lsstDebug
    display = lsstDebug.Info(__name__).display
    displayExposure = lsstDebug.Info(__name__).displayExposure     # display the Exposure + spatialCells
    #
    # Unpack policy
    #
    kernelSize   = psfPolicy.get("kernelSize")
    borderWidth  = psfPolicy.get("borderWidth")
    sizePsfCellX = psfPolicy.get("sizeCellX")
    sizePsfCellY = psfPolicy.get("sizeCellY")
    #
    mi = exposure.getMaskedImage()

    if display and displayExposure:
        frame = 0
        ds9.mtv(mi, frame=frame, title="PSF candidates")

    psfCellSet = afwMath.SpatialCellSet(mi.getBBox(), sizePsfCellX, sizePsfCellY)
    psfStars = []

    for val in matches:
        ref, source = val[0:2]
        if not (ref.getFlagForDetection() & measAlg.Flags.STAR) or \
               (source.getFlagForDetection() & measAlg.Flags.BAD):
            continue

        try:
            cand = measAlg.makePsfCandidate(source, mi)
            #
            # The setXXX methods are class static, but it's convenient to call them on
            # an instance as we don't know Exposure's pixel type (and hence cand's exact type)
            if cand.getWidth() == 0:
                cand.setBorderWidth(borderWidth)
                cand.setWidth(kernelSize + 2*borderWidth)
                cand.setHeight(kernelSize + 2*borderWidth)

            im = cand.getMaskedImage().getImage()
            max = afwMath.makeStatistics(im, afwMath.MAX).getValue()
            if not numpy.isfinite(max):
                continue

            psfCellSet.insertCandidate(cand)

            if display and displayExposure:
                ds9.dot("+", source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0(),
                        size=4, frame=frame, ctype=ds9.CYAN)
                ds9.dot("o", source.getXAstrom() - mi.getX0(), source.getYAstrom() - mi.getY0(),
                        size=4, frame=frame, ctype=ds9.CYAN)
        except Exception:
            continue

        source.setFlagForDetection(source.getFlagForDetection() | measAlg.Flags.STAR)
        psfStars += [source]

    return psfStars, psfCellSet
예제 #16
0
def DrawStat(stat, zoom_to_point = False):
#    if stat.ellipse_b == 0:
#        ds9.zoom(22, stat.centroid_x,stat.centroid_y, 0) # use to zoom to a single point
    argstring = "@:"+str(4*stat.ellipse_Ixx)+','+str(4*stat.ellipse_Ixy)+','+str(4*stat.ellipse_Iyy) #multiply by four just to make it more exaggerated otherwise they all look like cirlces
    ds9.dot(argstring,stat.centroid_x,stat.centroid_y) #ellipse around the centroid
    ds9.dot("x",stat.centroid_x,stat.centroid_y)# cross on the peak
    displayUtils.drawBBox(stat.BBox, borderWidth=0.5) # border to fully encompass the bbox and no more
    if zoom_to_point: ds9.zoom(22, stat.centroid_x,stat.centroid_y, 0) # use to zoom to a single point
    print 'length (diag,px) = %s, length (3D,true,um) = %s, flux = %s, npix = %s, dedx = %s' %(stat.diagonal_length_pixels, stat.length_true_um, stat.flux, stat.npix, stat.de_dx)
    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)
예제 #18
0
    def testFootprintsMeasure(self):
        """Check that we can measure the objects in a detectionSet"""

        xcentroid = [10.0, 14.0,        9.0]
        ycentroid = [8.0, 11.5061728,  14.0]
        flux = [51.0, 101.0,         20.0]
        wflux = [51.0, 101.0,        20.0]
        
        ds = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(10), "DETECTED")

        if display:
            ds9.mtv(self.mi, frame=0)
            ds9.mtv(self.mi.getVariance(), frame=1)

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

        ds.makeSources(catalog)

        sigma = 1e-10; psf = algorithms.DoubleGaussianPsf(11, 11, sigma) # i.e. a single pixel
        self.exposure.setPsf(psf)

        for i, source in enumerate(catalog):

            ms.applyWithPeak(source, self.exposure)

            xc, yc = source.getX() - self.mi.getX0(), source.getY() - self.mi.getY0()

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

            self.assertAlmostEqual(source.getX(), xcentroid[i], 6)
            self.assertAlmostEqual(source.getY(), ycentroid[i], 6)
            self.assertEqual(source.getApFlux(), flux[i])
            self.assertAlmostEqual(source.getApFluxErr(), math.sqrt(29), 6) # 29 pixels in 3pixel circular ap.
            # We're using a delta-function PSF, so the psfFlux should be the pixel under the centroid,
            # iff the object's centred in the pixel
            if xc == int(xc) and yc == int(yc):
                self.assertAlmostEqual(source.getPsfFlux(),
                                       self.exposure.getMaskedImage().getImage().get(int(xc + 0.5),
                                                                                 int(yc + 0.5)))
                self.assertAlmostEqual(source.getPsfFluxErr(),
                                       self.exposure.getMaskedImage().getVariance().get(int(xc + 0.5),
                                                                                    int(yc + 0.5)))
    def makeAndMeasure(self, measureKron, a, b, theta, dx=0.0, dy=0.0, nsigma=6, kfac=2, nIterForRadius=1,
                       xcen=None, ycen=None,
                       makeImage=True,
                       apCorrValue=None, # if a numeric value, use as the constant value of aperture correction
                       ):
        """Make and measure an elliptical Gaussian"""

        if xcen is None:
            xcen = 0.5*self.width + dx
        if ycen is None:
            ycen = 0.5*self.height + dy
        #
        # Make the object
        #
        if a < b:
            a, b = b, a
            theta += 90

        if self.objImg is None:
            makeImage = True
        if makeImage:
            self.objImg = makeGalaxy(self.width, self.height, self.flux, a, b, theta, dx, dy,
                                     afwGeom.Point2I(10, 10), xcen=xcen, ycen=ycen)

            if display:
                ds9.mtv(self.objImg, frame=ds9Frame, title="%g %g" % (a, b))

        doApplyApCorr = "noButWarn"
        if apCorrValue != None:
            addApCorrMap(self.objImg, apCorrValue)
            doApplyApCorr = "yes"

        if display:
            if not makeImage:
                ds9.erase(frame=ds9Frame)

            ds9.dot("+", xcen - self.objImg.getX0(), ycen - self.objImg.getY0(),
                    size=1, ctype=ds9.RED, frame=ds9Frame)
            ds9.pan(xcen - self.objImg.getX0(), ycen - self.objImg.getY0(), frame=ds9Frame)
            c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta))
            # N.b. add 1/12 in quadrature to allow for pixellisation
            ds9.dot("@:%f,%f,%f" % (nsigma**2*((a**2 + 1/12.0)*c**2 + (b**2 + 1/12.0)*s**2),
                                    nsigma**2*(a**2 - b**2)*c*s,
                                    nsigma**2*((a**2 + 1/12.0)*s**2 + (b**2 + 1/12.0)*c**2)),
                    xcen - self.objImg.getX0(), ycen - self.objImg.getY0(),
                    size=1, ctype=ds9.RED, frame=ds9Frame, silent=True)
        #
        # Do the measuring
        #
        FWHM = 5
        ksize = 25                      # size of desired kernel
        self.objImg.setPsf(measAlg.DoubleGaussianPsf(ksize, ksize,
                                                     FWHM/(2*math.sqrt(2*math.log(2))), 1, 0.1))

        return measureKron(self.objImg, xcen, ycen, nsigma, kfac, nIterForRadius, doApplyApCorr)
예제 #20
0
def DrawStatFromScratch(stat, bgsubtract):
    metadata_filename = '/home/mmmerlin/useful/herring_bone.fits'
    image = AssembleImage(stat.filename, metadata_filename, bgsubtract)
    print "track at %s,%s in %s"%(stat.centroid_x,stat.centroid_y,stat.filename)
    ds9.mtv(image)
#    exit()
    argstring = "@:"+str(4*stat.ellipse_Ixx)+','+str(4*stat.ellipse_Ixy)+','+str(4*stat.ellipse_Iyy) #multiply by four just to make it more exaggerated otherwise they all look like cirlces
    ds9.dot(argstring,stat.centroid_x,stat.centroid_y) #ellipse around the centroid
    ds9.dot("x",stat.centroid_x,stat.centroid_y)# cross on the peak
    displayUtils.drawBBox(stat.BBox, borderWidth=0.5) # border to fully encompass the bbox and no more
    ds9.zoom(22, stat.centroid_x,stat.centroid_y, 0) # use to zoom to a single point
예제 #21
0
    def testGrowFootprints3(self):
        """Test that we can grow footprints, correctly merging those that now totally overwritten"""

        self.im = afwImage.MaskedImageF(14, 11)

        self.im.getImage().set(0)
        self.peaks = []
        
        I = 11
        for x, y in [(4, 7), (5, 7), (6, 7), (7, 7), (8, 7),
                     (4, 6),                                     (8, 6),
                     (4, 5),                                     (8, 5),
                     (4, 4),                                     (8, 4),
                     (4, 3),                                     (8, 3),
                     ]:
            self.im.getImage().set(x, y, I)
            I -= 1e-3

        self.im.getImage().set(4, 7, 15)
        self.peaks.append([(4, 7,),])
        
        self.im.getImage().set(6, 5, 30)
        self.peaks[0].append((6, 5,))

        self.fs = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10), "BINNED1")
        #
        # The disappearing Footprint special case only shows up if the outer Footprint is grown
        # _after_ the inner one.  So arrange the order properly
        feet = self.fs.getFootprints()
        feet[0], feet[1] = feet[1], feet[0]

        msk = self.im.getMask()

        grow = 2
        self.fs = afwDetect.FootprintSet(self.fs, grow, False)
        afwDetect.setMaskFromFootprintList(msk, self.fs.getFootprints(),
                                           msk.getPlaneBitMask("DETECTED_NEGATIVE"))

        if display:
            frame = 0

            ds9.mtv(self.im, frame=frame)

            with ds9.Buffering():
                for i, foot in enumerate(self.fs.getFootprints()):
                    for p in foot.getPeaks():
                        ds9.dot("+", p.getIx(), p.getIy(), size=0.4, frame=frame)

                    if i < len(self.peaks):
                        for trueX, trueY in self.peaks[i]:
                            ds9.dot("x", trueX, trueY, size=0.4, ctype=ds9.RED, frame=frame)

        self.assertEqual(len(self.fs.getFootprints()), 1)
        self.assertEqual(len(self.fs.getFootprints()[0].getPeaks()), len(self.peaks[0]))
예제 #22
0
def showSourceSet(sSet, xy0=(0, 0), frame=0, ctype=ds9.GREEN, symb="+", size=2):
    """Draw the (XAstrom, YAstrom) positions of a set of Sources.  Image has the given XY0"""

    with ds9.Buffering():
        for s in sSet:
            xc, yc = s.getXAstrom() - xy0[0], s.getYAstrom() - xy0[1]

            if symb == "id":
                ds9.dot(str(splitId(s.getId(), True)["objId"]), xc, yc, frame=frame, ctype=ctype, size=size)
            else:
                ds9.dot(symb, xc, yc, frame=frame, ctype=ctype, size=size)
예제 #23
0
def showPsfSpatialCells(exposure, cellSet, showBadCandidates, frame=1):
    maUtils.showPsfSpatialCells(exposure, cellSet,
                                symb="o", ctype=ds9.CYAN, ctypeUnused=ds9.YELLOW,
                                size=4, frame=frame)
    for cell in cellSet.getCellList():
        for cand in cell.begin(not showBadCandidates): # maybe include bad candidates
            cand = measAlg.cast_PsfCandidateF(cand)
            status = cand.getStatus()
            ds9.dot('+', *cand.getSource().getCentroid(), frame=frame,
                    ctype=ds9.GREEN if status == afwMath.SpatialCellCandidate.GOOD else
                    ds9.YELLOW if status == afwMath.SpatialCellCandidate.UNKNOWN else ds9.RED)
예제 #24
0
파일: footprint2.py 프로젝트: rbiswas4/afw
    def checkPeaks(self, dwidth=0, dheight=0, frame=3):
        """Check that we got the peaks right"""
        feet = self.fs.getFootprints()
        #
        # Check that we found all the peaks
        #
        self.assertEqual(sum([len(f.getPeaks()) for f in feet]), sum([len(f.getPeaks()) for f in feet]))

        if display:
            ds9.mtv(self.im, frame=frame)

            with ds9.Buffering():
                for i, foot in enumerate(feet):
                    for p in foot.getPeaks():
                        ds9.dot("+", p.getIx(), p.getIy(), size=0.4, frame=frame)

                    if i < len(self.peaks):
                        for trueX, trueY, peakVal in self.peaks[i]:
                            ds9.dot("x", trueX, trueY, size=0.4, ctype=ds9.RED, frame=frame)

        for i, foot in enumerate(feet):
            npeak = None
            #
            # Peaks that touch the edge are handled differently, as only the single highest/lowest pixel
            # is treated as a Peak
            #
            if dwidth != 0 or dheight != 0:
                if (
                    foot.getBBox().getMinX() == 0
                    or foot.getBBox().getMaxX() == self.im.getWidth() - 1
                    or foot.getBBox().getMinY() == 0
                    or foot.getBBox().getMaxY() == self.im.getHeight() - 1
                ):
                    npeak = 1

            if npeak is None:
                npeak = len(self.peaks[i])

            if npeak != len(foot.getPeaks()):
                print "RHL", foot.repr()
                # print "RHL", [(p.repr().split(":")[0], p.getIx(), p.getIy()) for p in foot.getPeaks()]
                print "RHL", [(p.getId(), p.getIx(), p.getIy()) for p in foot.getPeaks()]
                print "RHL", [p[0:2] for p in self.peaks[i]]

            self.assertEqual(len(foot.getPeaks()), npeak)

            for j, p in enumerate(foot.getPeaks()):
                trueX, trueY, peakVal = self.peaks[i][j]
                if (p.getIx(), p.getIy()) != (trueX, trueY):
                    print "RHL", [(pp.getId(), pp.getIx(), pp.getIy()) for pp in foot.getPeaks()]
                    print "RHL", [pp[0:2] for pp in self.peaks[i]]

                self.assertEqual((p.getIx(), p.getIy()), (trueX, trueY))
예제 #25
0
파일: testDs9.py 프로젝트: rbiswas4/afw
    def testDrawing(self):
        """Test drawing lines and glyphs"""
        ds9.erase()

        exp = afwImage.ExposureF(300, 350)
        ds9.mtv(exp, title="parent") # tells display0 about the image's xy0
        
        with ds9.Buffering():
            ds9.dot('o', 200, 220)
            vertices = [(200, 220), (210, 230), (224, 230), (214, 220), (200, 220)]
            ds9.line(vertices, ctype=ds9.CYAN)
            ds9.line(vertices[:-1], symbs="+x+x", size=3)
예제 #26
0
    def testFootprintsMeasure(self):
        """Check that we can measure the objects in a detectionSet"""

        xcentroid = [10.0, 14.0,        9.0]
        ycentroid = [8.0, 11.5061728,  14.0]
        flux = [51.0, 101.0,         20.0]

        ds = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(10), "DETECTED")

        if display:
            ds9.mtv(self.mi, frame=0)
            ds9.mtv(self.mi.getVariance(), frame=1)

        measureSourcesConfig = measBase.SingleFrameMeasurementConfig()
        measureSourcesConfig.algorithms["base_CircularApertureFlux"].radii = [3.0]
        measureSourcesConfig.algorithms.names = ["base_NaiveCentroid", "base_SdssShape", "base_PsfFlux",
                                                 "base_CircularApertureFlux"]
        measureSourcesConfig.slots.centroid = "base_NaiveCentroid"
        measureSourcesConfig.slots.psfFlux = "base_PsfFlux"
        measureSourcesConfig.slots.apFlux = "base_CircularApertureFlux_3_0"
        measureSourcesConfig.slots.modelFlux = None
        measureSourcesConfig.slots.instFlux = None
        measureSourcesConfig.slots.calibFlux = None

        schema = afwTable.SourceTable.makeMinimalSchema()
        task = measBase.SingleFrameMeasurementTask(schema, config=measureSourcesConfig)
        measCat = afwTable.SourceCatalog(schema)
        # now run the SFM task with the test plugin
        sigma = 1e-10
        psf = algorithms.DoubleGaussianPsf(11, 11, sigma) # i.e. a single pixel
        self.exposure.setPsf(psf)
        task.run(measCat, self.exposure)


        for i, source in enumerate(measCat):

            xc, yc = source.getX() - self.mi.getX0(), source.getY() - self.mi.getY0()
            if display:
                ds9.dot("+", xc, yc)

            self.assertAlmostEqual(source.getX(), xcentroid[i], 6)
            self.assertAlmostEqual(source.getY(), ycentroid[i], 6)
            self.assertEqual(source.getApFlux(), flux[i])
            self.assertAlmostEqual(source.getApFluxErr(), math.sqrt(29), 6) # 29 pixels in 3pixel circular ap.
            # We're using a delta-function PSF, so the psfFlux should be the pixel under the centroid,
            # iff the object's centred in the pixel
            if xc == int(xc) and yc == int(yc):
                self.assertAlmostEqual(source.getPsfFlux(),
                                       self.exposure.getMaskedImage().getImage().get(int(xc + 0.5),
                                                                                 int(yc + 0.5)))
                self.assertAlmostEqual(source.getPsfFluxErr(),
                                       self.exposure.getMaskedImage().getVariance().get(int(xc + 0.5),
                                                                                    int(yc + 0.5)))
예제 #27
0
def showAstrometry(exposure, wcs, allMatches, useMatches, frame=0, title=None, pause=False):
    """Show results of astrometry fitting

    @param exposure: Image to display
    @param wcs: Astrometric solution
    @param allMatches: List of all astrometric matches (including rejects)
    @param useMatches: List of used astrometric matches
    @param frame: Frame number for display
    @param title: Title for display
    @param pause: Pause to allow viewing of the display and optional debugging?
    """
    import lsst.afw.display.ds9 as ds9
    ds9.mtv(exposure, frame=frame, title=title)

    useIndices = set(m.second.getId() for m in useMatches)

    radii = []
    with ds9.Buffering():
        for i, m in enumerate(allMatches):
            x, y = m.second.getX(), m.second.getY()
            pix = wcs.skyToPixel(m.first.getCoord())

            isUsed = m.second.getId() in useIndices
            if isUsed:
                radii.append(numpy.hypot(pix[0] - x, pix[1] - y))

            color = ds9.YELLOW if isUsed else ds9.RED

            ds9.dot("+", x, y, size=10, frame=frame, ctype=color)
            ds9.dot("x", pix[0], pix[1], size=10, frame=frame, ctype=color)

    radii = numpy.array(radii)
    print "<dr> = %.4g +- %.4g pixels [%d/%d matches]" % (radii.mean(), radii.std(),
                                                          len(useMatches), len(allMatches))

    if pause:
        import sys
        while True:
            try:
                reply = raw_input("Debugging? [p]db [q]uit; any other key to continue... ").strip()
            except EOFError:
                reply = ""

            reply = reply.split()
            if len(reply) > 1:
                reply, _ = reply[0], reply[1:]
            if reply == "p":
                import pdb;pdb.set_trace()
            elif reply == "q":
                sys.exit(1)
            else:
                break
예제 #28
0
def showPeaks(im=None, fs=None, frame=0):
    """Show the image and peaks"""
    if frame is None:
        return

    if im:
        ds9.mtv(im, frame=frame)

    if fs:
        with ds9.Buffering():  # turn on buffering of ds9's slow "region" writes
            for foot in fs.getFootprints():
                for p in foot.getPeaks():
                    ds9.dot("+", p.getIx(), p.getIy(), size=0.4, ctype=ds9.RED, frame=frame)
예제 #29
0
def DEBUG(image, footprintset):
    ds9.mtv(image)
    
    for footprint in footprintset:
        from lsst.afw.image.imageLib import MaskedImageF
        masked_imaged = MaskedImageF(image)
        heavy_footprint = afwDetect.HeavyFootprintF(footprint, masked_imaged)
        stat = GetTrackStats(heavy_footprint, image, False)
    
        argstring = "@:"+str(4*stat.ellipse_Ixx)+','+str(4*stat.ellipse_Ixy)+','+str(4*stat.ellipse_Iyy) #multiply by four just to make it more exaggerated otherwise they all look like cirlces
        ds9.dot(argstring,stat.centroid_x,stat.centroid_y) #ellipse around the centroid
        ds9.dot("x",stat.centroid_x,stat.centroid_y)# cross on the peak
        displayUtils.drawBBox(stat.BBox, borderWidth=0.5) # border to fully encompass the bbox and no more
예제 #30
0
파일: medpict.py 프로젝트: lsst-dm/fe55
def showMedpict(fileName="events.dat", events=None, image=None):
    medpictEvents = ras.readEventFile(fileName)

    #
    # Look for events that medpict missed
    #
    if events:
        x = np.empty(len(medpictEvents))
        y = np.empty(len(medpictEvents))

        for i, ev in enumerate(medpictEvents):
            x[i] = ev.x
            y[i] = ev.y

        for ev in events:
            if events:
                d = np.hypot(x - ev.x, y - ev.y)
                dmin = np.min(d)
                if dmin > 0:
                    print "medpict missed:", " ".join([str(_) for _ in zip(x[d == dmin], y[d == dmin])])

                    ds9.dot("o", ev.x, ev.y, size=5, ctype=ds9.GREEN)
                    if False:
                        ds9.pan(ev.x, ev.y)
                        ds9.flush()
                        import pdb; pdb.set_trace() 
        #
        # Look for events that the DM stack missed
        #
        if events:
            x = np.empty(len(events))
            y = np.empty(len(events))

            for i, ev in enumerate(events):
                x[i] = ev.x
                y[i] = ev.y

    with ds9.Buffering():
        for ev in medpictEvents:
            if events:
                d = np.hypot(x - ev.x, y - ev.y)
                dmin = np.min(d)
                if dmin > 0:
                    print "DM missed:", " ".join([str(_) for _ in zip(x[d == dmin], y[d == dmin])])
                    
                    ds9.dot("o", ev.x, ev.y, size=5, ctype=ds9.RED)
                    if False:
                        ds9.pan(ev.x, ev.y)
                        ds9.flush()
                        import pdb; pdb.set_trace() 
예제 #31
0
    def showImage(self, image, sources, title, frame):
        """Display an image

        Images are only displayed if 'display' is turned on.

        @param image: Image to display
        @param sources: Sources to mark on the display
        @param title: Title to give frame
        @param frame: Frame on which to display
        """
        if not display:
            return
        ds9.mtv(image, title=title, frame=frame)
        with ds9.Buffering():
            for s in sources:
                center = s.getCentroid()
                ds9.dot("o", center.getX(), center.getY(), frame=frame)
예제 #32
0
    def testText(self):
        """Test drawing text"""
        ds9.erase()

        exp = afwImage.ExposureF(300, 350)
        ds9.mtv(exp, title="parent")  # tells display0 about the image's xy0

        with ds9.Buffering():
            ds9.dot('hello', 200, 200)
            ds9.dot('hello', 200, 210, size=1.25)
            ds9.dot('hello', 200, 220, size=3, fontFamily="times")
            ds9.dot('hello', 200, 230, fontFamily="helvetica bold italic")
예제 #33
0
def drawFootprint(foot, borderWidth=0.5, origin=None, XY0=None, frame=None, ctype=None, bin=1,
                  peaks=False, symb="+", size=0.4, ctypePeak=None):
    """Draw an afwDetection::Footprint on a ds9 frame with the specified ctype.  Include an extra borderWidth
pixels If origin is present, it's Added to the Footprint; if XY0 is present is Subtracted from the Footprint

If peaks is True, also show the object's Peaks using the specified symbol and size and ctypePeak

All Footprint coordinates are divided by bin, as is right and proper for overlaying on a binned image
    """

    if XY0:
        if origin:
            raise RuntimeError("You may not specify both origin and XY0")
        origin = (-XY0[0], -XY0[1])

    with ds9.Buffering():
        borderWidth /= bin
        for s in foot.getSpans():
            y, x0, x1 = s.getY(), s.getX0(), s.getX1()

            if origin:
                x0 += origin[0]; x1 += origin[0]
                y += origin[1]

            x0 /= bin; x1 /= bin; y /= bin

            ds9.line([(x0 - borderWidth, y - borderWidth),
                      (x0 - borderWidth, y + borderWidth),
                      (x1 + borderWidth, y + borderWidth),
                      (x1 + borderWidth, y - borderWidth),
                      (x0 - borderWidth, y - borderWidth),
                      ], frame=frame, ctype=ctype)

        if peaks:
            for p in foot.getPeaks():
                x, y = p.getIx(), p.getIy()

                if origin:
                    x += origin[0]; y += origin[1]

                x /= bin; y /= bin

                ds9.dot(symb, x, y, size=size, ctype=ctypePeak, frame=frame)
def createFakeSource(x, y, catalog, exposure, threshold=0.1):
    """Create a fake source at the given x/y centroid location.

    Parameters
    ----------
    x,y : `int`
        The x and y centroid coordinates to place the image at.
    catalog : `lsst.afw.table.SourceCatalog`
        The catalog to add the new source to.
    exposure : `lsst.afw.image.Exposure`
        The exposure to add the source to.
    threshold : `float`, optional
        The footprint threshold for identifying the source.

    Returns
    -------
    source : `lsst.afw.table.SourceRecord`
        The created source record that was added to ``catalog``.
    """
    source = catalog.addNew()
    source['centroid_x'] = x
    source['centroid_y'] = y

    exposure.getMaskedImage().getImage()[x, y] = 1.0
    fpSet = afwDet.FootprintSet(exposure.getMaskedImage(),
                                afwDet.Threshold(threshold), "DETECTED")
    if display:
        ds9.mtv(exposure, frame=1)
        for fp in fpSet.getFootprints():
            for peak in fp.getPeaks():
                ds9.dot("x", peak.getIx(), peak.getIy(), frame=1)

    # There might be multiple footprints; only the one around x,y should go in the source
    found = False
    for fp in fpSet.getFootprints():
        if fp.contains(afwGeom.Point2I(x, y)):
            found = True
            break
    # We cannot continue if the the created source wasn't found.
    assert found, "Unable to find central peak in footprint: faulty test"

    source.setFootprint(fp)
    return source
예제 #35
0
def showPsfSpatialCells(exposure, cellSet, showBadCandidates, frame=1):
    maUtils.showPsfSpatialCells(exposure,
                                cellSet,
                                symb="o",
                                ctype=ds9.CYAN,
                                ctypeUnused=ds9.YELLOW,
                                size=4,
                                frame=frame)
    for cell in cellSet.getCellList():
        for cand in cell.begin(
                not showBadCandidates):  # maybe include bad candidates
            status = cand.getStatus()
            ds9.dot(
                '+',
                *cand.getSource().getCentroid(),
                frame=frame,
                ctype=ds9.GREEN
                if status == afwMath.SpatialCellCandidate.GOOD else ds9.YELLOW
                if status == afwMath.SpatialCellCandidate.UNKNOWN else ds9.RED)
예제 #36
0
def showPeaks(im=None, fs=None, frame=0):
    """Show the image and peaks"""
    if frame is None:
        return

    if im:
        ds9.mtv(im, frame=frame)

    if fs:
        with ds9.Buffering(
        ):  # turn on buffering of ds9's slow "region" writes
            for foot in fs.getFootprints():
                for p in foot.getPeaks():
                    ds9.dot("+",
                            p.getIx(),
                            p.getIy(),
                            size=0.4,
                            ctype=ds9.RED,
                            frame=frame)
예제 #37
0
    def displayDipoles(self, exposure, sources):
        """!Display debugging information on the detected dipoles

        @param exposure  Image the dipoles were measured on
        @param sources   The set of diaSources that were measured"""

        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayDiaSources = lsstDebug.Info(__name__).displayDiaSources
        maskTransparency = lsstDebug.Info(__name__).maskTransparency
        if not maskTransparency:
            maskTransparency = 90
        ds9.setMaskTransparency(maskTransparency)
        ds9.mtv(exposure, frame=lsstDebug.frame)

        if display and displayDiaSources:
            with ds9.Buffering():
                for source in sources:
                    cenX, cenY = source.get("ipdiffim_DipolePsfFlux_centroid")
                    if np.isinf(cenX) or np.isinf(cenY):
                        cenX, cenY = source.getCentroid()

                    isdipole = source.get("classification.dipole")
                    if isdipole and np.isfinite(isdipole):
                        # Dipole
                        ctype = "green"
                    else:
                        # Not dipole
                        ctype = "red"

                    ds9.dot("o", cenX, cenY, size=2, ctype=ctype, frame=lsstDebug.frame)

                    negCenX = source.get("ip_diffim_PsfDipoleFlux_neg_centroid_x")
                    negCenY = source.get("ip_diffim_PsfDipoleFlux_neg_centroid_y")
                    posCenX = source.get("ip_diffim_PsfDipoleFlux_pos_centroid_x")
                    posCenY = source.get("ip_diffim_PsfDipoleFlux_pos_centroid_y")
                    if (np.isinf(negCenX) or np.isinf(negCenY) or np.isinf(posCenX) or np.isinf(posCenY)):
                        continue

                    ds9.line([(negCenX, negCenY), (posCenX, posCenY)], ctype="yellow", frame=lsstDebug.frame)

            lsstDebug.frame += 1
예제 #38
0
def showStandards(standardStarSet,
                  exp,
                  frame,
                  countsMin=None,
                  flagMask=None,
                  rmsMax=None,
                  ctype=ds9.RED):
    """Show all the standards that are visible on this exposure

    If countsMin is not None, only show brighter Sources

    If flagMask is not None, ignore sources that have (flags & ~flagMask) != 0
    """

    wcs = exp.getWcs()
    width, height = exp.getMaskedImage().getWidth(), exp.getMaskedImage(
    ).getHeight()

    for s in standardStarSet:
        x, y = wcs.skyToPixel(s.getRaDec())

        if x < 0 or x >= width or y < 0 or y >= height:
            continue

        counts = s.getPsfFlux()

        if counts < countsMin and countsMin is not None:
            continue

        if flagMask is not None:
            if (s.getFlagForDetection() & ~flagMask) != 0:
                continue

        rms = math.sqrt(s.getIxx() + s.getIyy())
        if rmsMax is not None and rms > rmsMax:
            continue

        if False:
            pt = "%.1f" % (rms)
        else:
            pt = "+"
        ds9.dot(pt, x, y, frame=frame, ctype=ctype)
예제 #39
0
    def testLinearRamp(self):
        """Fit a ramp"""

        binsize = 1
        ramp, rampCoeffs, xVec, yVec = self.makeRamp(binsize)
        #
        # Add a (labelled) bad value
        #
        ramp.set(ramp.getWidth() // 2, ramp.getHeight() // 2, (0, 0x1, np.nan))

        if display:
            ds9.mtv(ramp, title="Input", frame=0)
        #
        # Here's the range that the approximation should be valid (and also the
        # bbox of the image returned by getImage)
        #
        bbox = afwGeom.BoxI(
            afwGeom.PointI(0, 0),
            afwGeom.PointI(binsize * ramp.getWidth() - 1,
                           binsize * ramp.getHeight() - 1))

        order = 3  # 1 would be enough to fit the ramp
        actrl = afwMath.ApproximateControl(
            afwMath.ApproximateControl.CHEBYSHEV, order)
        approx = afwMath.makeApproximate(xVec, yVec, ramp, bbox, actrl)

        for i, aim in enumerate([
                approx.getImage(),
                approx.getMaskedImage().getImage(),
        ]):
            if i == 0 and display:
                ds9.mtv(aim, title="interpolated", frame=1)
                with ds9.Buffering():
                    for x in xVec:
                        for y in yVec:
                            ds9.dot('+', x, y, size=0.4, frame=1)

            for x, y in aim.getBBox().getCorners():
                self.assertEqual(
                    aim.get(x, y),
                    rampCoeffs[0] + rampCoeffs[1] * x + rampCoeffs[1] * y)
    def assess(self, cand, kFn1, bgFn1, kFn2, bgFn2, frame0):
        tmi   = cand.getTemplateMaskedImage()
        smi   = cand.getScienceMaskedImage()
        
        im1   = afwImage.ImageD(kFn1.getDimensions())
        kFn1.computeImage(im1, False,
                          afwImage.indexToPosition(int(cand.getXCenter())),
                          afwImage.indexToPosition(int(cand.getYCenter())))
        fk1   = afwMath.FixedKernel(im1)
        bg1   = bgFn1(afwImage.indexToPosition(int(cand.getXCenter())),
                      afwImage.indexToPosition(int(cand.getYCenter())))
        d1    = ipDiffim.convolveAndSubtract(tmi, smi, fk1, bg1)

        ####
        
        im2   = afwImage.ImageD(kFn2.getDimensions())
        kFn2.computeImage(im2, False,
                          afwImage.indexToPosition(int(cand.getXCenter())),
                          afwImage.indexToPosition(int(cand.getYCenter())))
        fk2   = afwMath.FixedKernel(im2)
        bg2   = bgFn2(afwImage.indexToPosition(int(cand.getXCenter())),
                      afwImage.indexToPosition(int(cand.getYCenter())))
        d2    = ipDiffim.convolveAndSubtract(tmi, smi, fk2, bg2)

        if display:
            ds9.mtv(tmi, frame=frame0+0)
            ds9.dot("Cand %d" % (cand.getId()), 0, 0, frame=frame0+0)
            
            ds9.mtv(smi, frame=frame0+1)
            ds9.mtv(im1, frame=frame0+2)
            ds9.mtv(d1,  frame=frame0+3)
            ds9.mtv(im2, frame=frame0+4)
            ds9.mtv(d2,  frame=frame0+5)

        pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                     "Full Spatial Model")
        self.stats(cand.getId(), d1)

        pexLog.Trace("lsst.ip.diffim.JackknifeResampleKernel", 1,
                     "N-1 Spatial Model")
        self.stats(cand.getId(), d2)
예제 #41
0
def showSourceSet(sSet,
                  xy0=(0, 0),
                  frame=0,
                  ctype=ds9.GREEN,
                  symb="+",
                  size=2):
    """Draw the (XAstrom, YAstrom) positions of a set of Sources.  Image has the given XY0"""

    with ds9.Buffering():
        for s in sSet:
            xc, yc = s.getXAstrom() - xy0[0], s.getYAstrom() - xy0[1]

            if symb == "id":
                ds9.dot(str(splitId(s.getId(), True)["objId"]),
                        xc,
                        yc,
                        frame=frame,
                        ctype=ctype,
                        size=size)
            else:
                ds9.dot(symb, xc, yc, frame=frame, ctype=ctype, size=size)
예제 #42
0
    def testFootprintFromEllipse(self):
        """Create an elliptical Footprint"""
        cen = afwGeom.Point2D(23, 25)
        a, b, theta = 25, 15, 30
        ellipse = afwGeomEllipses.Ellipse(
            afwGeomEllipses.Axes(a, b, math.radians(theta)), cen)
        spanSet = afwGeom.SpanSet.fromShape(ellipse)
        foot = afwDetect.Footprint(
            spanSet,
            afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(50, 60)))

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

        foot.spans.setImage(idImage, foot.getId())

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

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

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

        self.assertEqual(foot.getCentroid(), cen)
        self.assertLess(abs(a - axes.getA()), 0.15,
                        "a: %g v. %g" % (a, axes.getA()))
        self.assertLess(abs(b - axes.getB()), 0.02,
                        "b: %g v. %g" % (b, axes.getB()))
        self.assertLess(
            abs(theta - math.degrees(axes.getTheta())), 0.2,
            "theta: %g v. %g" % (theta, math.degrees(axes.getTheta())))
예제 #43
0
def displayCutout(subImage, origin=None, catSubImage=None, frame=0):
    """
    Display a subImage. If catSubImage is not None then the centroids of the records in the catalog
    are also displayed, this catalog is meant to be the catalog of records in the subImage's
    bounding box.
    """

    ds9.mtv(subImage, frame=frame)

    if origin is not None and catSubImage is not None:
        for s in catSubImage:
            centroid = s.getCentroid() - origin
            if s.get('deblend.nchild') == 0:
                ds9.dot('+',
                        centroid[0],
                        centroid[1],
                        ctype=ds9.GREEN,
                        frame=frame)
            else:
                ds9.dot('+',
                        centroid[0],
                        centroid[1],
                        ctype=ds9.RED,
                        frame=frame)
            if s.getParent() == 0:
                ds9.dot('o',
                        centroid[0],
                        centroid[1],
                        ctype=ds9.CYAN,
                        frame=frame)
예제 #44
0
def run(display=False):
    exposure = loadData()
    schema = afwTable.SourceTable.makeMinimalSchema()
    #
    # Create the detection and measurement Tasks
    #
    config = SourceDetectionTask.ConfigClass()
    config.reEstimateBackground = False
    detectionTask = SourceDetectionTask(config=config, schema=schema)

    config = SingleFrameMeasurementTask.ConfigClass()
    # Use the minimum set of plugins required.
    config.plugins.names.clear()
    for plugin in [
            "base_SdssCentroid", "base_SdssShape", "base_CircularApertureFlux",
            "base_PixelFlags"
    ]:
        config.plugins.names.add(plugin)
    config.plugins["base_CircularApertureFlux"].radii = [7.0]
    # Use of the PSF flux is hardcoded in secondMomentStarSelector
    config.slots.psfFlux = "base_CircularApertureFlux_7_0"
    measureTask = SingleFrameMeasurementTask(schema, config=config)
    #
    # Create the measurePsf task
    #
    config = MeasurePsfTask.ConfigClass()

    psfDeterminer = config.psfDeterminer.apply()
    psfDeterminer.config.sizeCellX = 128
    psfDeterminer.config.sizeCellY = 128
    psfDeterminer.config.spatialOrder = 1
    psfDeterminer.config.nEigenComponents = 3

    measurePsfTask = MeasurePsfTask(config=config, schema=schema)
    #
    # Create the output table
    #
    tab = afwTable.SourceTable.make(schema)
    #
    # Process the data
    #
    sources = detectionTask.run(tab, exposure, sigma=2).sources
    measureTask.measure(exposure, sources)

    result = measurePsfTask.run(exposure, sources)
    psf = result.psf
    cellSet = result.cellSet

    if display:  # display on ds9 (see also --debug argparse option)
        frame = 1
        ds9.mtv(exposure, frame=frame)

        with ds9.Buffering():
            for s in sources:
                xy = s.getCentroid()
                ds9.dot('+', *xy, frame=frame)
                if s.get("calib.psf.candidate"):
                    ds9.dot('x', *xy, ctype=ds9.YELLOW, frame=frame)
                if s.get("calib.psf.used"):
                    ds9.dot('o', *xy, size=4, ctype=ds9.RED, frame=frame)
예제 #45
0
    def testGetImage(self):
        """Test returning a realisation of the dgPsf"""

        xcen = self.psf.getKernel().getWidth()//2
        ycen = self.psf.getKernel().getHeight()//2

        stamps = []
        trueCenters = []
        for x, y in ([10, 10], [9.4999, 10.4999], [10.5001, 10.5001]):
            fx, fy = x - int(x), y - int(y)
            if fx >= 0.5:
                fx -= 1.0
            if fy >= 0.5:
                fy -= 1.0

            im = self.psf.computeImage(afwGeom.Point2D(x, y)).convertF()

            stamps.append(im.Factory(im, True))
            trueCenters.append([xcen + fx, ycen + fy])

        if display:
            mos = displayUtils.Mosaic()     # control mosaics
            ds9.mtv(mos.makeMosaic(stamps))

            for i in range(len(trueCenters)):
                bbox = mos.getBBox(i)

                ds9.dot("+",
                        bbox.getMinX() + xcen, bbox.getMinY() + ycen, ctype = ds9.RED, size = 1)
                ds9.dot("+",
                        bbox.getMinX() + trueCenters[i][0], bbox.getMinY() + trueCenters[i][1])

                ds9.dot("%.2f, %.2f" % (trueCenters[i][0], trueCenters[i][1]),
                        bbox.getMinX() + xcen, bbox.getMinY() + 2)
    def setUp(self):
        im = afwImage.ImageF(self.monetFile("small.fits"))
        self.mi = afwImage.MaskedImageF(im, afwImage.MaskU(im.getDimensions()),
                                        afwImage.ImageF(im.getDimensions()))
        self.ds = afwDetection.FootprintSet(self.mi,
                                            afwDetection.Threshold(100))

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

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

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

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

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

        self.control = algorithms.GaussianCentroidControl()
        schema = afwTable.SourceTable.makeMinimalSchema()
        self.centroider = algorithms.MeasureSourcesBuilder().addAlgorithm(
            self.control).build(schema)
        self.ssMeasured = afwTable.SourceCatalog(schema)
        self.ssMeasured.table.defineCentroid(self.control.name)
        self.ssTruth = afwTable.SourceCatalog(schema)
        self.readTruth(self.monetFile("positions.dat-original"))
예제 #47
0
def showFrames(mos, frame0=1, R=23, subtractSky=True):
    visits = sorted(position.keys())

    frame = frame0 - 1
    for v in visits:
        frame += 1

        xc, yc = position[v]
        xc -= mos[v].getX0()
        yc -= mos[v].getY0()

        im = mos[v]
        if subtractSky:
            im = im.clone()
            im[2121:2230, 590:830] = np.nan # QE for this chip is bad

            ima = im.getArray()
            im[:] -= np.percentile(ima, 25)

        ds9.mtv(im, title=v, frame=frame)
        ds9.dot("o", xc, yc, size=R, frame=frame,
                ctype=ds9.GREEN if yc < mos[v].getHeight() else ds9.RED)
예제 #48
0
    def testSetIntegerOffset(self):
        """Test that we can offset by positive and negative amounts"""

        self.inImage.set(50, 50, 400)

        if False and display:
            frame = 0
            ds9.mtv(self.inImage, frame=frame)
            ds9.pan(50, 50, frame=frame)
            ds9.dot("+", 50, 50, frame=frame)

        for algorithm in ("lanczos5", "bilinear", "nearest"):
            for delta in [-0.49, 0.51]:
                for dx, dy in [(2, 3), (-2, 3), (-2, -3), (2, -3)]:
                    outImage = afwMath.offsetImage(self.inImage, dx + delta, dy + delta, algorithm)

                    if False and display:
                        frame += 1
                        ds9.mtv(outImage, frame=frame)
                        ds9.pan(50, 50, frame=frame)
                        ds9.dot("+", 50 + dx + delta - outImage.getX0(), 50 + dy + delta - outImage.getY0(),
                                frame=frame)
    def testMeasureCentroid(self):
        """Test that we can instantiate and play with a measureCentroid"""
        exposure = afwImage.makeExposure(self.mi)
        self.ds.makeSources(self.ssMeasured)
        ID = 1
        for s in self.ssMeasured:
            s.setId(ID)
            ID += 1
            foot = s.getFootprint()
            bbox = foot.getBBox()
            xc = (bbox.getMinX() + bbox.getMaxX()) // 2
            yc = (bbox.getMinY() + bbox.getMaxY()) // 2

            self.centroider.apply(s, exposure, afwGeom.Point2D(xc, yc))

            if display:
                ds9.dot("x", c.getX(), c.getY(), ctype=ds9.GREEN)
        #
        # OK, we've measured all the sources.  Compare positions with Dave Monet's values
        #

        # FIXME: this test will fail until source matching in afw is updated to use afw/table
        mat = afwTable.matchXy(self.ssTruth, self.ssMeasured, 1.0)
        #self.assertEqual(ID, len(mat))  # we matched all the input sources

        eps = 6e-6  # offset in pixels between measured centroid and the Truth
        for match in mat:
            dx = match[0].getX() - match[1].getX()
            dy = match[0].getY() - match[1].getY()

            good = True if math.hypot(dx, dy) < eps else False
            if not good:
                msg = "Star at (%.1f, %.1f): (dx, dy) = %g, %g)" % \
                    (match[0].getXAstrom(), match[0].getYAstrom(), dx, dy)
                if True:
                    print msg
                else:
                    self.assertTrue(good, msg)
예제 #50
0
    def displaySources(self, exposure, matches, reserved, frame=1):
        """Display sources we'll use for photocal

        Sources that will be actually used will be green.
        Sources reserved from the fit will be red.

        Parameters
        ----------
        exposure : `lsst.afw.image.ExposureF`
            Exposure to display.
        matches : `list` of `lsst.afw.table.RefMatch`
            Matches used for photocal.
        reserved : `numpy.ndarray` of type `bool`
            Boolean array indicating sources that are reserved.
        frame : `int`
            Frame number for display.
        """
        ds9.mtv(exposure, frame=frame, title="photocal")
        with ds9.Buffering():
            for mm, rr in zip(matches, reserved):
                x, y = mm.second.getCentroid()
                ctype = ds9.RED if rr else ds9.GREEN
                ds9.dot("o", x, y, size=4, frame=frame, ctype=ctype)
예제 #51
0
    def testMeasureCentroid(self):
        """Test that we can instantiate and play with a measureCentroid"""
        exposure = afwImage.makeExposure(self.mi)
        self.ds.makeSources(self.ssMeasured)
        ID = 1
        self.task.run(self.ssMeasured, exposure)
        for s in self.ssMeasured:
            s.setId(ID)
            ID += 1
            foot = s.getFootprint()
            bbox = foot.getBBox()
            xc = (bbox.getMinX() + bbox.getMaxX()) // 2
            yc = (bbox.getMinY() + bbox.getMaxY()) // 2

            if display:
                ds9.dot("x", xc, yc, ctype=ds9.GREEN)
        #
        # OK, we've measured all the sources.  Compare positions with Dave Monet's values
        #

        mat = afwTable.matchXy(self.ssTruth, self.ssMeasured, 1.0)
        self.assertEqual(ID, len(mat))  # we matched all the input sources

        # offset in pixels between measured centroid and the Truth
        eps = 6e-6
        for match in mat:
            dx = match[0].getX() - match[1].getX()
            dy = match[0].getY() - match[1].getY()

            good = True if math.hypot(dx, dy) < eps else False
            if not good:
                msg = "Star at (%.1f, %.1f): (dx, dy) = %g, %g)" % \
                    (match[0].getXAstrom(), match[0].getYAstrom(), dx, dy)
                if True:
                    print(msg)
                else:
                    self.assertTrue(good, msg)
예제 #52
0
def run(display=False):
    exposure = loadData()
    schema = afwTable.SourceTable.makeMinimalSchema()
    #
    # Create the detection task
    #
    config = SourceDetectionTask.ConfigClass()
    config.thresholdPolarity = "both"
    config.background.isNanSafe = True
    config.thresholdValue = 3
    detectionTask = SourceDetectionTask(config=config, schema=schema)
    #
    # And the measurement Task
    #
    config = SingleFrameMeasurementTask.ConfigClass()

    config.algorithms.names = ["base_SdssCentroid", "base_SdssShape", "base_CircularApertureFlux"]
    config.algorithms["base_CircularApertureFlux"].radii = [1, 2, 4, 8, 16] # pixels

    config.slots.instFlux = None
    config.slots.modelFlux = None
    config.slots.psfFlux = None

    algMetadata = dafBase.PropertyList()
    measureTask = SingleFrameMeasurementTask(schema, algMetadata=algMetadata, config=config)
    radii = algMetadata.get("base_CircularApertureFlux_radii")
    #
    # Create the output table
    #
    tab = afwTable.SourceTable.make(schema)
    #
    # Process the data
    #
    result = detectionTask.run(tab, exposure)

    sources = result.sources

    print("Found %d sources (%d +ve, %d -ve)" % (len(sources), result.fpSets.numPos, result.fpSets.numNeg))

    measureTask.run(sources, exposure)
    if display:                         # display on ds9 (see also --debug argparse option)
        frame = 1
        ds9.mtv(exposure, frame=frame)

        with ds9.Buffering():
            for s in sources:
                xy = s.getCentroid()
                ds9.dot('+', *xy, ctype=ds9.CYAN if s.get("flags.negative") else ds9.GREEN, frame=frame)
                ds9.dot(s.getShape(), *xy, ctype=ds9.RED, frame=frame)

                for i in range(s.get("flux.aperture.nProfile")):
                    ds9.dot('o', *xy, size=radii[i], ctype=ds9.YELLOW, frame=frame)
예제 #53
0
def showPsfSpatialCells(exposure, psfCellSet, nMaxPerCell=-1, showChi2=False, showMoments=False,
                        symb=None, ctype=None, ctypeUnused=None, ctypeBad=None, size=2, frame=None):
    """Show the SpatialCells.  If symb is something that ds9.dot understands (e.g. "o"), the
    top nMaxPerCell candidates will be indicated with that symbol, using ctype and size"""

    with ds9.Buffering():
        origin = [-exposure.getMaskedImage().getX0(), -exposure.getMaskedImage().getY0()]
        for cell in psfCellSet.getCellList():
            displayUtils.drawBBox(cell.getBBox(), origin=origin, frame=frame)

            if nMaxPerCell < 0:
                nMaxPerCell = 0

            i = 0
            goodies = ctypeBad is None
            for cand in cell.begin(goodies):
                if nMaxPerCell > 0:
                    i += 1

                cand = algorithmsLib.cast_PsfCandidateF(cand)

                xc, yc = cand.getXCenter() + origin[0], cand.getYCenter() + origin[1]

                if i > nMaxPerCell:
                    if not ctypeUnused:
                        continue

                color = ctypeBad if cand.isBad() else ctype

                if symb:
                    if i > nMaxPerCell:
                        ct = ctypeUnused
                    else:
                        ct = ctype

                    ds9.dot(symb, xc, yc, frame=frame, ctype=ct, size=size)

                source = cand.getSource()

                if showChi2:
                    rchi2 = cand.getChi2()
                    if rchi2 > 1e100:
                        rchi2 = numpy.nan
                    ds9.dot("%d %.1f" % (splitId(source.getId(), True)["objId"], rchi2),
                            xc - size, yc - size - 4, frame=frame, ctype=color, size=2)

                if showMoments:
                    ds9.dot("%.2f %.2f %.2f" % (source.getIxx(), source.getIxy(), source.getIyy()),
                            xc-size, yc + size + 4, frame=frame, ctype=color, size=size)
예제 #54
0
    def measureKron(self, objImg, xcen, ycen, nsigma, kfac, nIterForRadius):
        """Measure Kron quantities using the C++ code"""
        #
        # Now measure things
        #
        center = afwGeom.Point2D(xcen, ycen)
        msConfig = makeSourceMeasurementConfig(nsigma, nIterForRadius, kfac)
        source = measureFree(objImg, center, msConfig)

        R_K = source.get("flux.kron.radius")
        flux_K = source.get("flux.kron")
        fluxErr_K = source.get("flux.kron.err")
        flags_K = source.get("flux.kron.flags")

        if not flags_K:
            # Forced measurement on the same image should produce exactly the same result
            forced = measureForced(objImg, source, objImg.getWcs(), msConfig)
            for field in ("flux.kron", "flux.kron.err", "flux.kron.radius", "flux.kron.flags"):
                try:
                    if np.isnan(source.get(field)):
                        self.assertTrue(np.isnan(forced.get(field)))
                    else:
                        self.assertClose(source.get(field), forced.get(field), rtol=1.0e-6, atol=None)
                except AssertionError:
                    print "Failed:", field, source.get(field), forced.get(field)
                    raise

        if display:
            xc, yc = xcen - objImg.getX0(), ycen - objImg.getY0()
            ds9.dot("x", xc, yc, ctype=ds9.MAGENTA, size=1, frame=ds9Frame)
            displayUtils.drawFootprint(source.getFootprint(), XY0=objImg.getXY0())

            shape = source.getShape()
            if True:                    # nsigma*shape, the radius used to estimate R_K
                shape = shape.clone()
                shape.scale(source.get("flux.kron.radiusForRadius")/shape.getDeterminantRadius())
                ds9.dot(shape, xc, yc, ctype=ds9.MAGENTA, frame=ds9Frame)
            # Show R_K
            shape = shape.clone()
            for r, ct in [(R_K, ds9.BLUE), (R_K*kfac, ds9.CYAN),]:
                shape.scale(r/shape.getDeterminantRadius())
                ds9.dot(shape, xc, yc, ctype=ct, frame=ds9Frame)

        return R_K, flux_K, fluxErr_K, flags_K, \
            source.get("flux.kron.flags.radius"), source.get("flux.kron.flags.smallRadius")
예제 #55
0
    def testDistortedImage(self):

        detector = self.detector

        psfSigma = 1.5
        stars = plantSources(self.x0, self.y0, self.nx, self.ny, self.sky, self.nObj, psfSigma, detector)
        expos, starXy = stars[0], stars[1]

        # add some faint round galaxies ... only slightly bigger than the psf
        gxy = plantSources(self.x0, self.y0, self.nx, self.ny, self.sky, 10, 1.07*psfSigma, detector)
        mi = expos.getMaskedImage()
        mi += gxy[0].getMaskedImage()
        gxyXy = gxy[1]

        kwid = 15 #int(10*psfSigma) + 1
        psf = measAlg.SingleGaussianPsf(kwid, kwid, psfSigma)
        expos.setPsf(psf)


        expos.setDetector(detector)

        ########################
        # try without distorter
        expos.setDetector(self.flatDetector)
        print "Testing PSF selection *without* distortion"
        sourceList       = self.detectAndMeasure(expos)
        psfCandidateList = self.starSelector.run(expos, sourceList).psfCandidates

        ########################
        # try with distorter
        expos.setDetector(self.detector)
        print "Testing PSF selection *with* distortion"
        sourceList       = self.detectAndMeasure(expos)
        psfCandidateListCorrected = self.starSelector.run(expos, sourceList).psfCandidates

        def countObjects(candList):
            nStar, nGxy = 0, 0
            for c in candList:
                s = c.getSource()
                x, y = s.getX(), s.getY()
                for xs,ys in starXy:
                    if abs(x-xs) < 2.0 and abs(y-ys) < 2.0:
                        nStar += 1
                for xg,yg in gxyXy:
                    if abs(x-xg) < 2.0 and abs(y-yg) < 2.0:
                        nGxy += 1
            return nStar, nGxy

        nstar, ngxy = countObjects(psfCandidateList)
        nstarC, ngxyC = countObjects(psfCandidateListCorrected)

        print "uncorrected nStar, nGxy: ", nstar, "/", len(starXy),"   ", ngxy, '/', len(gxyXy)
        print "dist-corrected nStar, nGxy: ", nstarC, '/', len(starXy),"   ", ngxyC, '/', len(gxyXy)

        ########################
        # display
        if display:
            iDisp = 1
            ds9.mtv(expos, frame=iDisp)
            size = 40
            for c in psfCandidateList:
                s = c.getSource()
                ixx, iyy, ixy = size*s.getIxx(), size*s.getIyy(), size*s.getIxy()
                ds9.dot("@:%g,%g,%g" % (ixx, ixy, iyy), s.getX(), s.getY(),
                        frame=iDisp, ctype=ds9.RED)
            size *= 2.0
            for c in psfCandidateListCorrected:
                s = c.getSource()
                ixx, iyy, ixy = size*s.getIxx(), size*s.getIyy(), size*s.getIxy()
                ds9.dot("@:%g,%g,%g" % (ixx, ixy, iyy), s.getX(), s.getY(),
                        frame=iDisp, ctype=ds9.GREEN)

        # we shouldn't expect to get all available stars without distortion correcting
        self.assertLess(nstar, len(starXy))

        # here we should get all of them, occassionally 1 or 2 might get missed
        self.assertGreaterEqual(nstarC, 0.95*len(starXy))

        # no contamination by small gxys
        self.assertEqual(ngxyC, 0)
예제 #56
0
    def testEllipticalGaussian(self):
        """Test measuring elliptical aperture mags for an elliptical Gaussian"""

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

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

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

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

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

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

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

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

            mp.apply(source, objImg, center)

            self.assertAlmostEqual(
                math.exp(-0.5 * (r1 / a)**2) - math.exp(-0.5 * (r2 / a)**2),
                source["flux.sinc"] / flux, 5)
    def selectStars(self, exposure, sourceCat, matches=None):
        """!Return a list of PSF candidates that represent likely stars

        A list of PSF candidates may be used by a PSF fitter to construct a PSF.

        \param[in] exposure  the exposure containing the sources
        \param[in] sourceCat  catalog of sources that may be stars (an lsst.afw.table.SourceCatalog)
        \param[in] matches  astrometric matches; ignored by this star selector

        \return an lsst.pipe.base.Struct containing:
        - starCat  catalog of selected stars (a subset of sourceCat)
        """
        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayExposure = lsstDebug.Info(
            __name__).displayExposure  # display the Exposure + spatialCells
        plotMagSize = lsstDebug.Info(
            __name__).plotMagSize  # display the magnitude-size relation
        dumpData = lsstDebug.Info(
            __name__).dumpData  # dump data to pickle file?

        detector = exposure.getDetector()
        pixToTanXYTransform = None
        if detector is not None:
            tanSys = detector.makeCameraSys(TAN_PIXELS)
            pixToTanXYTransform = detector.getTransformMap().get(tanSys)
        #
        # Look at the distribution of stars in the magnitude-size plane
        #
        flux = sourceCat.get(self.config.sourceFluxField)

        xx = numpy.empty(len(sourceCat))
        xy = numpy.empty_like(xx)
        yy = numpy.empty_like(xx)
        for i, source in enumerate(sourceCat):
            Ixx, Ixy, Iyy = source.getIxx(), source.getIxy(), source.getIyy()
            if pixToTanXYTransform:
                p = afwGeom.Point2D(source.getX(), source.getY())
                linTransform = pixToTanXYTransform.linearizeForwardTransform(
                    p).getLinear()
                m = Quadrupole(Ixx, Iyy, Ixy)
                m.transform(linTransform)
                Ixx, Iyy, Ixy = m.getIxx(), m.getIyy(), m.getIxy()

            xx[i], xy[i], yy[i] = Ixx, Ixy, Iyy

        width = numpy.sqrt(0.5 * (xx + yy))

        bad = reduce(lambda x, y: numpy.logical_or(x, sourceCat.get(y)),
                     self.config.badFlags, False)
        bad = numpy.logical_or(bad, flux < self.config.fluxMin)
        bad = numpy.logical_or(bad, numpy.logical_not(numpy.isfinite(width)))
        bad = numpy.logical_or(bad, numpy.logical_not(numpy.isfinite(flux)))
        bad = numpy.logical_or(bad, width < self.config.widthMin)
        bad = numpy.logical_or(bad, width > self.config.widthMax)
        if self.config.fluxMax > 0:
            bad = numpy.logical_or(bad, flux > self.config.fluxMax)
        good = numpy.logical_not(bad)

        if not numpy.any(good):
            raise RuntimeError(
                "No objects passed our cuts for consideration as psf stars")

        mag = -2.5 * numpy.log10(flux[good])
        width = width[good]
        #
        # Look for the maximum in the size histogram, then search upwards for the minimum that separates
        # the initial peak (of, we presume, stars) from the galaxies
        #
        if dumpData:
            import os
            import pickle as pickle
            _ii = 0
            while True:
                pickleFile = os.path.expanduser(
                    os.path.join("~", "widths-%d.pkl" % _ii))
                if not os.path.exists(pickleFile):
                    break
                _ii += 1

            with open(pickleFile, "wb") as fd:
                pickle.dump(mag, fd, -1)
                pickle.dump(width, fd, -1)

        centers, clusterId = _kcenters(
            width,
            nCluster=4,
            useMedian=True,
            widthStdAllowed=self.config.widthStdAllowed)

        if display and plotMagSize:
            fig = plot(
                mag,
                width,
                centers,
                clusterId,
                magType=self.config.sourceFluxField.split(".")[-1].title(),
                marker="+",
                markersize=3,
                markeredgewidth=None,
                ltype=':',
                clear=True)
        else:
            fig = None

        clusterId = _improveCluster(
            width,
            centers,
            clusterId,
            nsigma=self.config.nSigmaClip,
            widthStdAllowed=self.config.widthStdAllowed)

        if display and plotMagSize:
            plot(mag,
                 width,
                 centers,
                 clusterId,
                 marker="x",
                 markersize=3,
                 markeredgewidth=None,
                 clear=False)

        stellar = (clusterId == 0)
        #
        # We know enough to plot, if so requested
        #
        frame = 0

        if fig:
            if display and displayExposure:
                ds9.mtv(exposure.getMaskedImage(),
                        frame=frame,
                        title="PSF candidates")

                global eventHandler
                eventHandler = EventHandler(fig.get_axes()[0],
                                            mag,
                                            width,
                                            sourceCat.getX()[good],
                                            sourceCat.getY()[good],
                                            frames=[frame])

            fig.show()

            while True:
                try:
                    reply = input("continue? [c h(elp) q(uit) p(db)] ").strip()
                except EOFError:
                    reply = None
                if not reply:
                    reply = "c"

                if reply:
                    if reply[0] == "h":
                        print("""\
    We cluster the points; red are the stellar candidates and the other colours are other clusters.
    Points labelled + are rejects from the cluster (only for cluster 0).

    At this prompt, you can continue with almost any key; 'p' enters pdb, and 'h' prints this text

    If displayExposure is true, you can put the cursor on a point and hit 'p' to see it in ds9.
    """)
                    elif reply[0] == "p":
                        import pdb
                        pdb.set_trace()
                    elif reply[0] == 'q':
                        sys.exit(1)
                    else:
                        break

        if display and displayExposure:
            mi = exposure.getMaskedImage()

            with ds9.Buffering():
                for i, source in enumerate(sourceCat):
                    if good[i]:
                        ctype = ds9.GREEN  # star candidate
                    else:
                        ctype = ds9.RED  # not star

                    ds9.dot("+",
                            source.getX() - mi.getX0(),
                            source.getY() - mi.getY0(),
                            frame=frame,
                            ctype=ctype)

        starCat = SourceCatalog(sourceCat.table)
        goodSources = [s for g, s in zip(good, sourceCat) if g]
        for isStellar, source in zip(stellar, goodSources):
            if isStellar:
                starCat.append(source)

        return Struct(starCat=starCat, )
    def selectStars(self, exposure, catalog, matches=None):
        """Return a list of PSF candidates that represent likely stars
        
        A list of PSF candidates may be used by a PSF fitter to construct a PSF.
        
        @param[in] exposure: the exposure containing the sources
        @param[in] catalog: a SourceCatalog containing sources that may be stars
        @param[in] matches: astrometric matches; ignored by this star selector
        
        @return psfCandidateList: a list of PSF candidates.
        """
        import lsstDebug
        display = lsstDebug.Info(__name__).display
        displayExposure = lsstDebug.Info(
            __name__).displayExposure  # display the Exposure + spatialCells
        plotMagSize = lsstDebug.Info(
            __name__).plotMagSize  # display the magnitude-size relation
        dumpData = lsstDebug.Info(
            __name__).dumpData  # dump data to pickle file?

        # create a log for my application
        logger = pexLogging.Log(pexLogging.getDefaultLog(),
                                "meas.algorithms.objectSizeStarSelector")

        detector = exposure.getDetector()
        distorter = None
        xy0 = afwGeom.Point2D(0, 0)
        if not detector is None:
            cPix = detector.getCenterPixel()
            detSize = detector.getSize()
            xy0.setX(cPix.getX() - int(0.5 * detSize.getMm()[0]))
            xy0.setY(cPix.getY() - int(0.5 * detSize.getMm()[1]))
            distorter = detector.getDistortion()
        #
        # Look at the distribution of stars in the magnitude-size plane
        #
        flux = catalog.get(self._sourceFluxField)

        xx = numpy.empty(len(catalog))
        xy = numpy.empty_like(xx)
        yy = numpy.empty_like(xx)
        for i, source in enumerate(catalog):
            Ixx, Ixy, Iyy = source.getIxx(), source.getIxy(), source.getIyy()
            if distorter:
                xpix, ypix = source.getX() + xy0.getX(), source.getY(
                ) + xy0.getY()
                p = afwGeom.Point2D(xpix, ypix)
                m = distorter.undistort(p, geomEllip.Quadrupole(Ixx, Iyy, Ixy),
                                        detector)
                Ixx, Ixy, Iyy = m.getIxx(), m.getIxy(), m.getIyy()

            xx[i], xy[i], yy[i] = Ixx, Ixy, Iyy

        width = numpy.sqrt(xx + yy)

        bad = reduce(lambda x, y: numpy.logical_or(x, catalog.get(y)),
                     self._badFlags, False)
        bad = numpy.logical_or(bad, flux < self._fluxMin)
        bad = numpy.logical_or(bad, numpy.logical_not(numpy.isfinite(width)))
        bad = numpy.logical_or(bad, numpy.logical_not(numpy.isfinite(flux)))
        bad = numpy.logical_or(bad, width < self._widthMin)
        bad = numpy.logical_or(bad, width > self._widthMax)
        if self._fluxMax > 0:
            bad = numpy.logical_or(bad, flux > self._fluxMax)
        good = numpy.logical_not(bad)

        if not numpy.any(good):
            raise RuntimeError(
                "No objects passed our cuts for consideration as psf stars")

        mag = -2.5 * numpy.log10(flux[good])
        width = width[good]
        #
        # Look for the maximum in the size histogram, then search upwards for the minimum that separates
        # the initial peak (of, we presume, stars) from the galaxies
        #
        if dumpData:
            import os, cPickle as pickle
            _ii = 0
            while True:
                pickleFile = os.path.expanduser(
                    os.path.join("~", "widths-%d.pkl" % _ii))
                if not os.path.exists(pickleFile):
                    break
                _ii += 1

            with open(pickleFile, "wb") as fd:
                pickle.dump(mag, fd, -1)
                pickle.dump(width, fd, -1)

        centers, clusterId = _kcenters(width, nCluster=4, useMedian=True)

        if display and plotMagSize and pyplot:
            fig = plot(mag,
                       width,
                       centers,
                       clusterId,
                       marker="+",
                       markersize=3,
                       markeredgewidth=None,
                       ltype=':',
                       clear=True)
        else:
            fig = None

        clusterId = _improveCluster(width, centers, clusterId)

        if display and plotMagSize and pyplot:
            plot(mag,
                 width,
                 centers,
                 clusterId,
                 marker="x",
                 markersize=3,
                 markeredgewidth=None)

        stellar = (clusterId == 0)
        #
        # We know enough to plot, if so requested
        #
        frame = 0

        if fig:
            if display and displayExposure:
                ds9.mtv(exposure.getMaskedImage(),
                        frame=frame,
                        title="PSF candidates")

                global eventHandler
                eventHandler = EventHandler(fig.get_axes()[0],
                                            mag,
                                            width,
                                            catalog.getX()[good],
                                            catalog.getY()[good],
                                            frames=[frame])

            fig.show()

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

            while True:
                try:
                    reply = raw_input(
                        "continue? [c h(elp) q(uit) p(db)] ").strip()
                except EOFError:
                    reply = "y"

                if reply:
                    if reply[0] == "h":
                        print """\
    We cluster the points; red are the stellar candidates and the other colours are other clusters.
    Points labelled + are rejects from the cluster (only for cluster 0).

    At this prompt, you can continue with almost any key; 'p' enters pdb, and 'h' prints this text

    If displayExposure is true, you can put the cursor on a point and hit 'p' to see it in ds9.
    """
                    elif reply[0] == "p":
                        import pdb
                        pdb.set_trace()
                    elif reply[0] == 'q':
                        sys.exit(1)
                    else:
                        break

        if display and displayExposure:
            mi = exposure.getMaskedImage()

            with ds9.Buffering():
                for i, source in enumerate(catalog):
                    if good[i]:
                        ctype = ds9.GREEN  # star candidate
                    else:
                        ctype = ds9.RED  # not star

                    ds9.dot("+",
                            source.getX() - mi.getX0(),
                            source.getY() - mi.getY0(),
                            frame=frame,
                            ctype=ctype)
        #
        # Time to use that stellar classification to generate psfCandidateList
        #
        with ds9.Buffering():
            psfCandidateList = []
            for isStellar, source in zip(
                    stellar, [s for g, s in zip(good, catalog) if g]):
                if not isStellar:
                    continue

                try:
                    psfCandidate = algorithmsLib.makePsfCandidate(
                        source, exposure)
                    # The setXXX methods are class static, but it's convenient to call them on
                    # an instance as we don't know Exposure's pixel type
                    # (and hence psfCandidate's exact type)
                    if psfCandidate.getWidth() == 0:
                        psfCandidate.setBorderWidth(self._borderWidth)
                        psfCandidate.setWidth(self._kernelSize +
                                              2 * self._borderWidth)
                        psfCandidate.setHeight(self._kernelSize +
                                               2 * self._borderWidth)

                    im = psfCandidate.getMaskedImage().getImage()
                    vmax = afwMath.makeStatistics(im, afwMath.MAX).getValue()
                    if not numpy.isfinite(vmax):
                        continue
                    psfCandidateList.append(psfCandidate)

                    if display and displayExposure:
                        ds9.dot("o",
                                source.getX() - mi.getX0(),
                                source.getY() - mi.getY0(),
                                size=4,
                                frame=frame,
                                ctype=ds9.CYAN)
                except Exception as err:
                    logger.log(
                        pexLogging.Log.INFO,
                        "Failed to make a psfCandidate from source %d: %s" %
                        (source.getId(), err))

        return psfCandidateList
예제 #59
0
    def testBasics(self):
        bbox = afwGeom.Box2I(afwGeom.Point2I(256, 100),
                             afwGeom.Extent2I(128, 127))
        minCounts = 2000
        maxCounts = 20000
        starSigma = 1.5
        numX = 4
        numY = 4
        coordList = self.makeCoordList(
            bbox=bbox,
            numX=numX,
            numY=numY,
            minCounts=minCounts,
            maxCounts=maxCounts,
            sigma=starSigma,
        )
        kwid = 11
        sky = 2000
        addPoissonNoise = True
        exposure = plantSources(bbox=bbox,
                                kwid=kwid,
                                sky=sky,
                                coordList=coordList,
                                addPoissonNoise=addPoissonNoise)

        if display:
            ds9.mtv(exposure)

        schema = afwTable.SourceTable.makeMinimalSchema()
        config = SourceDetectionTask.ConfigClass()
        config.reEstimateBackground = False
        config.thresholdPolarity = 'both'
        detection = SourceDetectionTask(config=config, schema=schema)
        algMetadata = dafBase.PropertyList()
        measurement = SourceMeasurementTask(schema=schema,
                                            algMetadata=algMetadata)

        table = afwTable.SourceTable.make(schema)
        detections = detection.makeSourceCatalog(table, exposure)
        sources = detections.sources
        fpSets = detections.fpSets

        self.assertEqual(len(sources), numX * numY)
        self.assertEqual(fpSets.numPos, numX * numY / 2)
        self.assertEqual(fpSets.numNeg, numX * numY / 2)

        measurement.run(sources, exposure)

        nGoodCent = 0
        nGoodShape = 0
        for s in sources:
            cent = s.getCentroid()
            shape = s.getShape()

            if cent[0] == cent[0] and cent[1] == cent[1]:
                nGoodCent += 1

            if (shape.getIxx() == shape.getIxx()
                    and shape.getIyy() == shape.getIyy()
                    and shape.getIxy() == shape.getIxy()):
                nGoodShape += 1

            if display:
                xy = cent[0] - exposure.getX0(), cent[1] - exposure.getY0()
                ds9.dot('+', *xy)
                ds9.dot(shape, *xy, ctype=ds9.RED)

        self.assertEqual(nGoodCent, numX * numY)
        self.assertEqual(nGoodShape, numX * numY)
    def getClumps(self, sigma=1.0, display=False):
        if self._num <= 0:
            raise RuntimeError("No candidate PSF sources")

        psfImage = self.getImage()
        #
        # Embed psfImage into a larger image so we can smooth when measuring it
        #
        width, height = psfImage.getWidth(), psfImage.getHeight()
        largeImg = psfImage.Factory(afwGeom.ExtentI(2 * width, 2 * height))
        largeImg.set(0)

        bbox = afwGeom.BoxI(afwGeom.PointI(width, height),
                            afwGeom.ExtentI(width, height))
        largeImg.assign(psfImage, bbox, afwImage.LOCAL)
        #
        # Now measure that image, looking for the highest peak.  Start by building an Exposure
        #
        msk = afwImage.MaskU(largeImg.getDimensions())
        msk.set(0)
        var = afwImage.ImageF(largeImg.getDimensions())
        var.set(1)
        mpsfImage = afwImage.MaskedImageF(largeImg, msk, var)
        mpsfImage.setXY0(afwGeom.PointI(-width, -height))
        del msk
        del var
        exposure = afwImage.makeExposure(mpsfImage)

        #
        # Next run an object detector
        #
        maxVal = afwMath.makeStatistics(psfImage, afwMath.MAX).getValue()
        threshold = maxVal - sigma * math.sqrt(maxVal)
        if threshold <= 0.0:
            threshold = maxVal

        threshold = afwDetection.Threshold(threshold)

        ds = afwDetection.FootprintSet(mpsfImage, threshold, "DETECTED")
        #
        # And measure it.  This policy isn't the one we use to measure
        # Sources, it's only used to characterize this PSF histogram
        #
        schema = SourceTable.makeMinimalSchema()
        psfImageConfig = SingleFrameMeasurementConfig()
        psfImageConfig.slots.centroid = "base_SdssCentroid"
        psfImageConfig.plugins["base_SdssCentroid"].doFootprintCheck = False
        psfImageConfig.slots.psfFlux = None  # "base_PsfFlux"
        psfImageConfig.slots.apFlux = "base_CircularApertureFlux_3_0"
        psfImageConfig.slots.modelFlux = None
        psfImageConfig.slots.instFlux = None
        psfImageConfig.slots.calibFlux = None
        psfImageConfig.slots.shape = "base_SdssShape"
        #   Formerly, this code had centroid.sdss, flux.psf, flux.naive,
        #   flags.pixel, and shape.sdss
        psfImageConfig.algorithms.names = [
            "base_SdssCentroid", "base_CircularApertureFlux", "base_SdssShape"
        ]
        psfImageConfig.algorithms["base_CircularApertureFlux"].radii = [3.0]
        psfImageConfig.validate()
        task = SingleFrameMeasurementTask(schema, config=psfImageConfig)

        sourceCat = SourceCatalog(schema)

        gaussianWidth = 1.5  # Gaussian sigma for detection convolution
        exposure.setPsf(algorithmsLib.DoubleGaussianPsf(11, 11, gaussianWidth))

        ds.makeSources(sourceCat)
        #
        # Show us the Histogram
        #
        if display:
            frame = 1
            dispImage = mpsfImage.Factory(
                mpsfImage,
                afwGeom.BoxI(afwGeom.PointI(width, height),
                             afwGeom.ExtentI(width, height)), afwImage.LOCAL)
            ds9.mtv(dispImage, title="PSF Selection Image", frame=frame)

        clumps = list()  # List of clumps, to return
        e = None  # thrown exception
        IzzMin = 1.0  # Minimum value for second moments
        IzzMax = (
            self._xSize /
            8.0)**2  # Max value ... clump radius should be < clumpImgSize/8
        apFluxes = []
        task.run(
            sourceCat,
            exposure)  # notes that this is backwards for the new framework
        for i, source in enumerate(sourceCat):
            if source.getCentroidFlag():
                continue
            x, y = source.getX(), source.getY()

            apFluxes.append(source.getApFlux())

            val = mpsfImage.getImage().get(int(x) + width, int(y) + height)

            psfClumpIxx = source.getIxx()
            psfClumpIxy = source.getIxy()
            psfClumpIyy = source.getIyy()

            if display:
                if i == 0:
                    ds9.pan(x, y, frame=frame)

                ds9.dot("+", x, y, ctype=ds9.YELLOW, frame=frame)
                ds9.dot("@:%g,%g,%g" % (psfClumpIxx, psfClumpIxy, psfClumpIyy),
                        x,
                        y,
                        ctype=ds9.YELLOW,
                        frame=frame)

            if psfClumpIxx < IzzMin or psfClumpIyy < IzzMin:
                psfClumpIxx = max(psfClumpIxx, IzzMin)
                psfClumpIyy = max(psfClumpIyy, IzzMin)
                if display:
                    ds9.dot("@:%g,%g,%g" %
                            (psfClumpIxx, psfClumpIxy, psfClumpIyy),
                            x,
                            y,
                            ctype=ds9.RED,
                            frame=frame)

            det = psfClumpIxx * psfClumpIyy - psfClumpIxy * psfClumpIxy
            try:
                a, b, c = psfClumpIyy / det, -psfClumpIxy / det, psfClumpIxx / det
            except ZeroDivisionError:
                a, b, c = 1e4, 0, 1e4

            clumps.append(
                Clump(peak=val,
                      x=x,
                      y=y,
                      a=a,
                      b=b,
                      c=c,
                      ixx=psfClumpIxx,
                      ixy=psfClumpIxy,
                      iyy=psfClumpIyy))

        if len(clumps) == 0:
            msg = "Failed to determine center of PSF clump"
            if e:
                msg += ": %s" % e
            raise RuntimeError(msg)

        # if it's all we got return it
        if len(clumps) == 1:
            return clumps

        # which clump is the best?
        # if we've undistorted the moments, stars should only have 1 clump
        # use the apFlux from the clump measurement, and take the highest
        # ... this clump has more psf star candidate neighbours than the others.

        # get rid of any that are huge, and thus poorly defined
        goodClumps = []
        for clump in clumps:
            if clump.ixx < IzzMax and clump.iyy < IzzMax:
                goodClumps.append(clump)

        # if culling > IzzMax cost us all clumps, we'll have to take what we have
        if len(goodClumps) == 0:
            goodClumps = clumps

        # use the 'brightest' clump
        iBestClump = numpy.argsort(apFluxes)[0]
        clumps = [clumps[iBestClump]]
        return clumps