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!
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
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
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()))