Example #1
0
    def __init__(self, config, *, display=None, **kwargs):
        super().__init__(config=config, **kwargs)
        self.makeSubtask("installPsf")

        self.display = None
        if display:
            self.display = display

        self.centroidName = "base_SdssCentroid"
        self.shapeName = "base_SdssShape"
        self.schema = afwTable.SourceTable.makeMinimalSchema()
        self.schema.getAliasMap().set("slot_Centroid", self.centroidName)
        self.schema.getAliasMap().set("slot_Shape", self.shapeName)
        self.control = measBase.SdssCentroidControl()
        self.centroider = measBase.SdssCentroidAlgorithm(
            self.control, self.centroidName, self.schema)
        self.sdssShape = measBase.SdssShapeControl()
        self.shaper = measBase.SdssShapeAlgorithm(self.sdssShape,
                                                  self.shapeName, self.schema)
        self.apFluxControl = measBase.ApertureFluxControl()
        md = dafBase.PropertySet()
        self.apFluxer = measBase.CircularApertureFluxAlgorithm(
            self.apFluxControl, "aperFlux", self.schema, md)

        self.table = afwTable.SourceTable.make(
            self.schema)  # make sure to call this last!
Example #2
0
def showPsfMosaic(exposure, psf=None, nx=7, ny=None, showCenter=True, showEllipticity=False,
                  showFwhm=False, stampSize=0, display=None, title=None):
    """Show a mosaic of Psf images.  exposure may be an Exposure (optionally with PSF),
    or a tuple (width, height)

    If stampSize is > 0, the psf images will be trimmed to stampSize*stampSize
    """

    scale = 1.0
    if showFwhm:
        showEllipticity = True
        scale = 2*math.log(2)         # convert sigma^2 to HWHM^2 for a Gaussian

    mos = displayUtils.Mosaic()

    try:                                # maybe it's a real Exposure
        width, height = exposure.getWidth(), exposure.getHeight()
        x0, y0 = exposure.getXY0()
        if not psf:
            psf = exposure.getPsf()
    except AttributeError:
        try:                            # OK, maybe a list [width, height]
            width, height = exposure[0], exposure[1]
            x0, y0 = 0, 0
        except TypeError:               # I guess not
            raise RuntimeError("Unable to extract width/height from object of type %s" % type(exposure))

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

    centroidName = "SdssCentroid"
    shapeName = "base_SdssShape"

    schema = afwTable.SourceTable.makeMinimalSchema()
    schema.getAliasMap().set("slot_Centroid", centroidName)
    schema.getAliasMap().set("slot_Centroid_flag", centroidName+"_flag")

    control = measBase.SdssCentroidControl()
    centroider = measBase.SdssCentroidAlgorithm(control, centroidName, schema)

    sdssShape = measBase.SdssShapeControl()
    shaper = measBase.SdssShapeAlgorithm(sdssShape, shapeName, schema)
    table = afwTable.SourceTable.make(schema)

    table.defineCentroid(centroidName)
    table.defineShape(shapeName)

    bbox = None
    if stampSize > 0:
        w, h = psf.computeImage(lsst.geom.PointD(0, 0)).getDimensions()
        if stampSize <= w and stampSize <= h:
            bbox = lsst.geom.BoxI(lsst.geom.PointI((w - stampSize)//2, (h - stampSize)//2),
                                  lsst.geom.ExtentI(stampSize, stampSize))

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

            im = psf.computeImage(lsst.geom.PointD(x, y)).convertF()
            imPeak = psf.computePeak(lsst.geom.PointD(x, y))
            im /= imPeak
            if bbox:
                im = im.Factory(im, bbox)
            lab = "PSF(%d,%d)" % (x, y) if False else ""
            mos.append(im, lab)

            exp = afwImage.makeExposure(afwImage.makeMaskedImage(im))
            exp.setPsf(psf)
            w, h = im.getWidth(), im.getHeight()
            centerX = im.getX0() + w//2
            centerY = im.getY0() + h//2
            src = table.makeRecord()
            spans = afwGeom.SpanSet(exp.getBBox())
            foot = afwDet.Footprint(spans)
            foot.addPeak(centerX, centerY, 1)
            src.setFootprint(foot)

            try:
                centroider.measure(src, exp)
                centers.append((src.getX() - im.getX0(), src.getY() - im.getY0()))

                shaper.measure(src, exp)
                shapes.append((src.getIxx(), src.getIxy(), src.getIyy()))
            except Exception:
                pass

    if not display:
        display = afwDisplay.Display()
    mos.makeMosaic(display=display, title=title if title else "Model Psf", mode=nx)

    if centers and display:
        with display.Buffering():
            for i, (cen, shape) in enumerate(zip(centers, shapes)):
                bbox = mos.getBBox(i)
                xc, yc = cen[0] + bbox.getMinX(), cen[1] + bbox.getMinY()
                if showCenter:
                    display.dot("+", xc, yc, ctype=afwDisplay.BLUE)

                if showEllipticity:
                    ixx, ixy, iyy = shape
                    ixx *= scale
                    ixy *= scale
                    iyy *= scale
                    display.dot("@:%g,%g,%g" % (ixx, ixy, iyy), xc, yc, ctype=afwDisplay.RED)

    return mos
Example #3
0
def showKernelMosaic(bbox, kernel, nx=7, ny=None, frame=None, title=None,
                     showCenter=True, showEllipticity=True):
    """Show a mosaic of Kernel images.
    """
    mos = afwDisplay.utils.Mosaic()

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

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

    schema = afwTable.SourceTable.makeMinimalSchema()
    centroidName = "base_SdssCentroid"
    shapeName = "base_SdssShape"
    control = measBase.SdssCentroidControl()
    schema.getAliasMap().set("slot_Centroid", centroidName)
    schema.getAliasMap().set("slot_Centroid_flag", centroidName + "_flag")
    centroider = measBase.SdssCentroidAlgorithm(control, centroidName, schema)
    sdssShape = measBase.SdssShapeControl()
    shaper = measBase.SdssShapeAlgorithm(sdssShape, shapeName, schema)
    table = afwTable.SourceTable.make(schema)
    table.defineCentroid(centroidName)
    table.defineShape(shapeName)

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

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

            # SdssCentroidAlgorithm.measure requires an exposure of floats
            exp = afwImage.makeExposure(afwImage.makeMaskedImage(im.convertF()))

            w, h = im.getWidth(), im.getHeight()
            centerX = im.getX0() + w//2
            centerY = im.getY0() + h//2
            src = table.makeRecord()
            spans = afwGeom.SpanSet(exp.getBBox())
            foot = afwDet.Footprint(spans)
            foot.addPeak(centerX, centerY, 1)
            src.setFootprint(foot)

            try:  # The centroider requires a psf, so this will fail if none is attached to exp
                centroider.measure(src, exp)
                centers.append((src.getX(), src.getY()))

                shaper.measure(src, exp)
                shapes.append((src.getIxx(), src.getIxy(), src.getIyy()))
            except Exception:
                pass

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

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

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

    return mos
Example #4
0
    def do_testmeasureShape(self):
        """Test that we can instantiate and play with a measureShape"""

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

        bkgd = 100.0
        control = measBase.SdssShapeControl()
        control.background = bkgd
        control.maxShift = 2
        plugin, cat = makePluginAndCat(measBase.SdssShapeAlgorithm,
                                       "test",
                                       control,
                                       centroid="centroid")

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

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

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

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

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

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

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

            if display:
                ds9.mtv(im)

            footprint = afwDetection.FootprintSet(
                im, afwDetection.Threshold(110)).getFootprints()[0]
            source = cat.addNew()
            source.setFootprint(footprint)
            source.set("centroid_x",
                       footprint.getPeaks()[0].getCentroid().getX())
            source.set("centroid_y",
                       footprint.getPeaks()[0].getCentroid().getY())
            plugin.measure(source, exp)

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

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

            print source.getX(), source.getY(), x, y
            print source.getIxx(), sigma_xx, source.getIyy(
            ), sigma_yy, source.getIxy(), sigma_xy
            self.assertTrue(
                abs(x - source.getX()) < 1e-4, "%g v. %g" % (x, source.getX()))
            self.assertTrue(
                abs(y - source.getY()) < 1e-4, "%g v. %g" % (y, source.getY()))
            self.assertTrue(
                abs(source.getIxx() - sigma_xx) < tol * (1 + sigma_xx),
                "%g v. %g" % (sigma_xx, source.getIxx()))
            self.assertTrue(
                abs(source.getIxy() - sigma_xy) < tol * (1 + abs(sigma_xy)),
                "%g v. %g" % (sigma_xy, source.getIxy()))
            self.assertTrue(
                abs(source.getIyy() - sigma_yy) < tol * (1 + sigma_yy),
                "%g v. %g" % (sigma_yy, source.getIyy()))