def main(rootDir, visit, ccd, n=10): # butler を開き読み込みたいデータの dataId を指定する butler = dafPersist.Butler(rootDir) dataId = {'visit': visit, 'ccd':ccd} # butler から一次処理済データカタログと WCS データを読み込む sources = butler.get('src', dataId) exposure = butler.get('calexp', dataId, immediate=True) wcs = exposure.getWcs() #trans = wcs.getLinearTransform() pixScale = wcs.pixelScale().asArcseconds() for s in sources[:n]: # 全 CCD に対し変換をコメントアウトする trans = wcs.linearizePixelToSky(s.getCentroid(), afwGeom.arcseconds).getLinear() m0 = s.getShape() m_new = m0.transform(trans) # 座標系の変換前・後のサニティーチェックを出力する ms = m0, m_new pix = 1.0, pixScale for i in 0, 1: m = ms[i] ax = ellipses.Axes(m) # 座標変換後は Ixx, yy, xy は変わっているはず print "%6.3f %6.3f %6.3f " % (m.getIxx(), m.getIyy(), m.getIxy()), # 変換された座標系は pixelScale で割られているため、A, B は同じはず # --> theta は x-軸 に対して無変換で、*反時計回り* に増加する(デカルト座標系) # --> theta は RA-軸 に対して変換され、*時計回り* に増加する print "%6.3f %6.3f %6.3f " % (ax.getA()/pix[i], ax.getB()/pix[i], ax.getTheta()), print ""
def testHsmPsfMoments(self): for width in (2.0, 3.0, 4.0): psf = afwDetection.GaussianPsf(35, 35, width) exposure = afwImage.ExposureF(45, 56) exposure.getMaskedImage().set(1.0, 0, 1.0) exposure.setPsf(psf) # perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() msConfig.algorithms.names = ["ext_shapeHSM_HsmPsfMoments"] plugin, cat = makePluginAndCat(lsst.meas.extensions.shapeHSM.HsmPsfMomentsAlgorithm, "ext_shapeHSM_HsmPsfMoments", centroid="centroid", control=lsst.meas.extensions.shapeHSM.HsmPsfMomentsControl()) source = cat.addNew() source.set("centroid_x", 23) source.set("centroid_y", 34) offset = afwGeom.Point2I(23, 34) tmpSpans = afwGeom.SpanSet.fromShape(int(width), offset=offset) source.setFootprint(afwDetection.Footprint(tmpSpans)) plugin.measure(source, exposure) x = source.get("ext_shapeHSM_HsmPsfMoments_x") y = source.get("ext_shapeHSM_HsmPsfMoments_y") xx = source.get("ext_shapeHSM_HsmPsfMoments_xx") yy = source.get("ext_shapeHSM_HsmPsfMoments_yy") xy = source.get("ext_shapeHSM_HsmPsfMoments_xy") self.assertAlmostEqual(x, 0.0, 3) self.assertAlmostEqual(y, 0.0, 3) expected = afwEll.Quadrupole(afwEll.Axes(width, width, 0.0)) self.assertAlmostEqual(xx, expected.getIxx(), SHAPE_DECIMALS) self.assertAlmostEqual(xy, expected.getIxy(), SHAPE_DECIMALS) self.assertAlmostEqual(yy, expected.getIyy(), SHAPE_DECIMALS)
def main(): x = numpy.linspace(-5, 5, 101) y = numpy.linspace(-5, 5, 101) ellipse1 = ellipses.Ellipse(ellipses.Axes(1.0, 1.0, 0.3)) ellipse2 = ellipses.Ellipse(ellipses.Axes(1.0, 1.0, numpy.pi/2 + 0.3)) f1 = lsst.shapelet.ShapeletFunction(1, lsst.shapelet.HERMITE) f1.getCoefficients()[1] = 1.0 f1.setEllipse(ellipse1) f2 = lsst.shapelet.ShapeletFunction(2, lsst.shapelet.HERMITE) f2.getCoefficients()[4] = 1.0 f2.setEllipse(ellipse2) fC = f1.convolve(f2) plotShapeletFunction(pyplot.subplot(1, 3, 1), f1, x, y) plotShapeletFunction(pyplot.subplot(1, 3, 2), f2, x, y) plotShapeletFunction(pyplot.subplot(1, 3, 3), fC, x, y) pyplot.show()
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())))
def _fig8Test(self, x1, y1, x2, y2): # Construct a "figure of 8" consisting of two circles touching at the # centre of an image, then demonstrate that it shrinks correctly. # (Helper method for tests below.) radius = 3 imwidth, imheight = 100, 100 nshrink = 1 # These are the correct values for footprint sizes given the paramters # above. circle_npix = 29 initial_npix = circle_npix * 2 - 1 # touch at one pixel shrunk_npix = 26 box = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(imwidth, imheight)) e1 = afwGeom.Ellipse(afwGeomEllipses.Axes(radius, radius, 0), lsst.geom.Point2D(x1, y1)) spanSet1 = afwGeom.SpanSet.fromShape(e1) f1 = afwDetect.Footprint(spanSet1, box) self.assertEqual(f1.getArea(), circle_npix) e2 = afwGeom.Ellipse(afwGeomEllipses.Axes(radius, radius, 0), lsst.geom.Point2D(x2, y2)) spanSet2 = afwGeom.SpanSet.fromShape(e2) f2 = afwDetect.Footprint(spanSet2, box) self.assertEqual(f2.getArea(), circle_npix) initial = afwDetect.mergeFootprints(f1, f2) initial.setRegion( f2.getRegion()) # merge does not propagate the region self.assertEqual(initial_npix, initial.getArea()) shrunk = afwDetect.Footprint().assign(initial) shrunk.erode(nshrink) self.assertEqual(shrunk_npix, shrunk.getArea()) if display: idImage = afwImage.ImageU(imwidth, imheight) for i, foot in enumerate([initial, shrunk]): print(foot.getArea()) foot.spans.setImage(idImage, i + 1) afwDisplay.Display(frame=1).mtv(idImage, title=self._testMethodName + " image")
def testConvolution(self): if scipy is None: print("Skipping convolution test; scipy could not be imported.") return e1 = ellipses.Ellipse(ellipses.Axes(10, 8, 0.3), geom.Point2D(1.5, 2.0)) e2 = ellipses.Ellipse(ellipses.Axes(12, 9, -0.5), geom.Point2D(-1.0, -0.25)) f1 = lsst.shapelet.ShapeletFunction(3, lsst.shapelet.HERMITE, e1) f2 = lsst.shapelet.ShapeletFunction(2, lsst.shapelet.LAGUERRE, e2) f1.getCoefficients()[:] = np.random.randn(*f1.getCoefficients().shape) f2.getCoefficients()[:] = np.random.randn(*f2.getCoefficients().shape) fc1, fc2 = self.checkConvolution(f1, f2) self.assertEqual(fc1.getBasisType(), lsst.shapelet.HERMITE) self.assertEqual(fc2.getBasisType(), lsst.shapelet.LAGUERRE) self.assertFloatsAlmostEqual(fc1.getEllipse().getParameterVector(), fc2.getEllipse().getParameterVector()) self.assertEqual(fc1.getOrder(), fc2.getOrder()) fc2.changeBasisType(lsst.shapelet.HERMITE) self.assertFloatsAlmostEqual(fc1.getCoefficients(), fc2.getCoefficients(), 1E-8)
def main(): x = numpy.linspace(-5, 5, 101) y = numpy.linspace(-5, 5, 101) ellipses.Quadrupole(ellipses.Axes(1.2, 0.8, 0.3)) hermiteBasis = lsst.shapelet.BasisEvaluator(4, lsst.shapelet.HERMITE) laguerreBasis = lsst.shapelet.BasisEvaluator(4, lsst.shapelet.LAGUERRE) processBasis(hermiteBasis, x, y) processBasis(laguerreBasis, x, y) pyplot.show()
def setUp(self): self.ellipse = ellipses.Axes(10, 7, 0.3) self.center = geom.Point2D(10.1, 11.2) self.bbox = geom.Box2I(geom.Point2I(5, 6), geom.Point2I(13, 12)) self.image = lsst.afw.image.ImageF(self.bbox) x, y = numpy.meshgrid( numpy.arange(self.bbox.getBeginX(), self.bbox.getEndX()), numpy.arange(self.bbox.getBeginY(), self.bbox.getEndY())) # use exponential profile to ensure we don't get exact fit self.image.getArray()[:, :] = numpy.exp(-(x**2 + y**2)**0.5) self.inputs = ms.ModelInputHandler(self.image, self.center, self.bbox)
def _fig8Test(self, x1, y1, x2, y2): # Construct a "figure of 8" consisting of two circles touching at the # centre of an image, then demonstrate that it shrinks correctly. # (Helper method for tests below.) radius = 3 imwidth, imheight = 100, 100 nshrink = 1 # These are the correct values for footprint sizes given the paramters # above. circle_npix = 29 initial_npix = circle_npix * 2 - 1 # touch at one pixel shrunk_npix = 26 box = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(imwidth, imheight)) e1 = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(radius, radius, 0), afwGeom.Point2D(x1, y1)) f1 = afwDetect.Footprint(e1, box) self.assertEqual(f1.getNpix(), circle_npix) e2 = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(radius, radius, 0), afwGeom.Point2D(x2, y2)) f2 = afwDetect.Footprint(e2, box) self.assertEqual(f2.getNpix(), circle_npix) initial = afwDetect.mergeFootprints(f1, f2) initial.setRegion( f2.getRegion()) # merge does not propagate the region self.assertEqual(initial_npix, initial.getNpix()) shrunk = afwDetect.shrinkFootprint(initial, nshrink, True) self.assertEqual(shrunk_npix, shrunk.getNpix()) if display: idImage = afwImage.ImageU(imwidth, imheight) for i, foot in enumerate([initial, shrunk]): print(foot.getNpix()) foot.insertIntoImage(idImage, i + 1) ds9.mtv(idImage)
def testFootprintFromCircle(self): """Create an elliptical Footprint""" ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(6, 6, 0), afwGeom.Point2D(9,15)) foot = afwDetect.Footprint(ellipse, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(20, 30))) idImage = afwImage.ImageU(afwGeom.Extent2I(foot.getRegion().getWidth(), foot.getRegion().getHeight())) idImage.set(0) foot.insertIntoImage(idImage, foot.getId()) if False: ds9.mtv(idImage, frame=2)
def testShrinkIsoVsManhattan(self): # Demonstrate that isotropic and Manhattan shrinks are different. radius = 8 imwidth, imheight = 100, 100 x0, y0 = imwidth//2, imheight//2 nshrink = 4 ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(1.5*radius, 2*radius, 0), afwGeom.Point2D(x0,y0)) foot = afwDetect.Footprint(ellipse, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(imwidth, imheight))) self.assertNotEqual(afwDetect.shrinkFootprint(foot, nshrink, False), afwDetect.shrinkFootprint(foot, nshrink, True))
def testHsmPsfMoments(self, width, useSourceCentroidOffset, varyBBox, wrongBBox, center): psf = PyGaussianPsf(35, 35, width, varyBBox=varyBBox, wrongBBox=wrongBBox) exposure = afwImage.ExposureF(45, 56) exposure.getMaskedImage().set(1.0, 0, 1.0) exposure.setPsf(psf) # perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() msConfig.algorithms.names = ["ext_shapeHSM_HsmPsfMoments"] control = lsst.meas.extensions.shapeHSM.HsmPsfMomentsControl() self.assertFalse(control.useSourceCentroidOffset) control.useSourceCentroidOffset = useSourceCentroidOffset plugin, cat = makePluginAndCat( lsst.meas.extensions.shapeHSM.HsmPsfMomentsAlgorithm, "ext_shapeHSM_HsmPsfMoments", centroid="centroid", control=control) source = cat.addNew() source.set("centroid_x", center[0]) source.set("centroid_y", center[1]) offset = geom.Point2I(*center) tmpSpans = afwGeom.SpanSet.fromShape(int(width), offset=offset) source.setFootprint(afwDetection.Footprint(tmpSpans)) plugin.measure(source, exposure) x = source.get("ext_shapeHSM_HsmPsfMoments_x") y = source.get("ext_shapeHSM_HsmPsfMoments_y") xx = source.get("ext_shapeHSM_HsmPsfMoments_xx") yy = source.get("ext_shapeHSM_HsmPsfMoments_yy") xy = source.get("ext_shapeHSM_HsmPsfMoments_xy") self.assertFalse(source.get("ext_shapeHSM_HsmPsfMoments_flag")) self.assertFalse( source.get("ext_shapeHSM_HsmPsfMoments_flag_no_pixels")) self.assertFalse( source.get("ext_shapeHSM_HsmPsfMoments_flag_not_contained")) self.assertFalse( source.get("ext_shapeHSM_HsmPsfMoments_flag_parent_source")) self.assertAlmostEqual(x, 0.0, 3) self.assertAlmostEqual(y, 0.0, 3) expected = afwEll.Quadrupole(afwEll.Axes(width, width, 0.0)) self.assertAlmostEqual(xx, expected.getIxx(), SHAPE_DECIMALS) self.assertAlmostEqual(xy, expected.getIxy(), SHAPE_DECIMALS) self.assertAlmostEqual(yy, expected.getIyy(), SHAPE_DECIMALS)
def getExposurePsfSigma(exposure, minor=False): """Helper function to extract the PSF size from an afwImage.Exposure object @param exposure The exposure you want a PSF size for @param minor Return the minor axis size of the PSF (default will be sqrt(a*b)). """ nx, ny = exposure.getWidth(), exposure.getHeight() midpixel = afwGeom.Point2D(nx // 2, ny // 2) psfshape = exposure.getPsf().computeShape(midpixel) axes = ellipses.Axes(psfshape) if minor: return axes.getB() else: return np.sqrt(axes.getA() * axes.getB())
def setUp(self): np.random.seed(500) order = 4 self.ellipse = ellipses.Ellipse(ellipses.Axes(2.2, 0.8, 0.3), geom.Point2D(0.12, -0.08)) self.coefficients = np.random.randn(lsst.shapelet.computeSize(order)) self.x = np.random.randn(25) self.y = np.random.randn(25) self.bases = [ lsst.shapelet.BasisEvaluator(order, lsst.shapelet.HERMITE), lsst.shapelet.BasisEvaluator(order, lsst.shapelet.LAGUERRE), ] self.functions = [ lsst.shapelet.ShapeletFunction(order, lsst.shapelet.HERMITE, self.coefficients), lsst.shapelet.ShapeletFunction(order, lsst.shapelet.LAGUERRE, self.coefficients), ] for function in self.functions: function.setEllipse(self.ellipse)
def testTablePersistence(self): ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(8, 6, 0.25), afwGeom.Point2D(9,15)) fp1 = afwDetect.Footprint(ellipse) fp1.addPeak(6, 7, 2) fp1.addPeak(8, 9, 3) with utilsTests.getTempFilePath(".fits") as tmpFile: fp1.writeFits(tmpFile) fp2 = afwDetect.Footprint.readFits(tmpFile) self.assertEqual(fp1.getArea(), fp2.getArea()) self.assertEqual(list(fp1.getSpans()), list(fp2.getSpans())) # can't use Peak operator== for comparison because it compares IDs, not positions/values self.assertEqual(len(fp1.getPeaks()), len(fp2.getPeaks())) for peak1, peak2 in zip(fp1.getPeaks(), fp2.getPeaks()): self.assertEqual(peak1.getIx(), peak2.getIx()) self.assertEqual(peak1.getIy(), peak2.getIy()) self.assertEqual(peak1.getFx(), peak2.getFx()) self.assertEqual(peak1.getFy(), peak2.getFy()) self.assertEqual(peak1.getPeakValue(), peak2.getPeakValue())
def testFootprintFromCircle(self): """Create an elliptical Footprint""" ellipse = afwGeom.Ellipse(afwGeomEllipses.Axes(6, 6, 0), lsst.geom.Point2D(9, 15)) spanSet = afwGeom.SpanSet.fromShape(ellipse) foot = afwDetect.Footprint(spanSet, lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(20, 30))) idImage = afwImage.ImageU( lsst.geom.Extent2I(foot.getRegion().getWidth(), foot.getRegion().getHeight())) idImage.set(0) foot.spans.setImage(idImage, foot.getId()) if False: ds9.mtv(idImage, frame=2)
def main(rootDir, visit, ccd, n=5): # butler を開き読み込みたいデータの dataId を指定する butler = dafPersist.Butler(rootDir) dataId = {'visit': visit, 'ccd': ccd} # butler から一次処理済データのカタログファイルを抜き出す sources = butler.get('src', dataId) for src in sources[0:n]: # adaptive moment を取得する m = src.get('shape.sdss') ixx, ixy, iyy = m.getIxx(), m.getIxy(), m.getIyy() # 楕円体に変換(theta はラジアン表記にする) e = geomEllip.Axes(m) a, b, theta = e.getA(), e.getB(), e.getTheta() print ixx, ixy, iyy, " ", a, b, theta
def main(rootDir, visit, ccd, n=5): # make a butler and specify your dataId butler = dafPersist.Butler(rootDir) dataId = {'visit': visit, 'ccd':ccd} # get the exposure from the butler sources = butler.get('src', dataId) for src in sources[0:n]: # get the adaptive moments m = src.get('shape.sdss') ixx, ixy, iyy = m.getIxx(), m.getIxy(), m.getIyy() # convert to an ellipse (note that theta is in radians and is not an Angle object) e = geomEllip.Axes(m) a, b, theta = e.getA(), e.getB(), e.getTheta() print ixx, ixy, iyy, " ", a, b, theta
def testTablePersistence(self): ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(8, 6, 0.25), afwGeom.Point2D(9, 15)) fp1 = afwDetect.Footprint(ellipse) fp1.addPeak(6, 7, 2) fp1.addPeak(8, 9, 3) filename = "testFootprintTablePersistence.fits" fp1.writeFits(filename) fp2 = afwDetect.Footprint.readFits(filename) self.assertEqual(fp1.getArea(), fp2.getArea()) self.assertEqual(list(fp1.getSpans()), list(fp2.getSpans())) self.assertEqual(len(fp1.getPeaks()), len(fp2.getPeaks())) for peak1, peak2 in zip(fp1.getPeaks(), fp2.getPeaks()): self.assertEqual(peak1.getIx(), peak2.getIx()) self.assertEqual(peak1.getIy(), peak2.getIy()) self.assertEqual(peak1.getFx(), peak2.getFx()) self.assertEqual(peak1.getFy(), peak2.getFy()) self.assertEqual(peak1.getPeakValue(), peak2.getPeakValue()) os.remove(filename)
def testFootprintFromEllipse(self): """Create an elliptical Footprint""" cen = lsst.geom.Point2D(23, 25) a, b, theta = 25, 15, 30 ellipse = afwGeom.Ellipse( afwGeomEllipses.Axes(a, b, math.radians(theta)), cen) spanSet = afwGeom.SpanSet.fromShape(ellipse) foot = afwDetect.Footprint( spanSet, lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(50, 60))) idImage = afwImage.ImageU( lsst.geom.Extent2I(foot.getRegion().getWidth(), foot.getRegion().getHeight())) idImage.set(0) foot.spans.setImage(idImage, 42) if display: disp = afwDisplay.Display(frame=2) disp.mtv(idImage, title=self._testMethodName + " image") afwDisplay.utils.drawFootprint(foot, frame=2) shape = foot.getShape() shape.scale(2) # <r^2> = 1/2 for a disk disp.dot(shape, *cen, ctype=afwDisplay.RED) shape = foot.getShape() shape.scale(2) # <r^2> = 1/2 for a disk disp.dot(shape, *cen, ctype=afwDisplay.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, f"a: {a:g} vs. {axes.getA():g}") self.assertLess(abs(b - axes.getB()), 0.02, f"b: {b:g} va. {axes.getB():g}") self.assertLess( abs(theta - math.degrees(axes.getTheta())), 0.2, f"theta: {theta:g} vs. {math.degrees(axes.getTheta()):g}")
def testShrinkIsoVsManhattan(self): # Demonstrate that isotropic and Manhattan shrinks are different. radius = 8 imwidth, imheight = 100, 100 x0, y0 = imwidth // 2, imheight // 2 nshrink = 4 ellipse = afwGeom.Ellipse( afwGeomEllipses.Axes(1.5 * radius, 2 * radius, 0), lsst.geom.Point2D(x0, y0)) spanSet = afwGeom.SpanSet.fromShape(ellipse) foot = afwDetect.Footprint( spanSet, lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(imwidth, imheight))) footIsotropic = afwDetect.Footprint() footIsotropic.assign(foot) foot.erode(nshrink, afwGeom.Stencil.MANHATTAN) footIsotropic.erode(nshrink) self.assertNotEqual(foot, footIsotropic)
def determineKernelSize(self, psfCandidateList): """Sets self.kernelSize (logic in this routine is cut-and-paste from pcaPsfDeterminer)""" sizes = np.zeros(len(psfCandidateList)) for i, psfCandidate in enumerate(psfCandidateList): source = psfCandidate.getSource() quad = afwEll.Quadrupole(source.getIxx(), source.getIyy(), source.getIxy()) axes = afwEll.Axes(quad) sizes[i] = axes.getA() if self.config.kernelSize >= 15: print >> sys.stderr, "WARNING: NOT scaling kernelSize by stellar quadrupole moment, but using absolute value" self.kernelSize = int(self.config.kernelSize) else: self.kernelSize = 2 * int(self.config.kernelSize * np.sqrt(np.median(sizes)) + 0.5) + 1 self.kernelSize = max(self.kernelSize, self.config.kernelSizeMin) self.kernelSize = min(self.kernelSize, self.config.kernelSizeMax) print >> sys.stderr, 'setting kernelSize =', self.kernelSize
def isLargeFootprint(self, footprint): """Returns whether a Footprint is large 'Large' is defined by thresholds on the area, size and axis ratio. These may be disabled independently by configuring them to be non-positive. This is principally intended to get rid of satellite streaks, which the deblender or other downstream processing can have trouble dealing with (e.g., multiple large HeavyFootprints can chew up memory). """ if self.config.maxFootprintArea > 0 and footprint.getArea( ) > self.config.maxFootprintArea: return True if self.config.maxFootprintSize > 0: bbox = footprint.getBBox() if max(bbox.getWidth(), bbox.getHeight()) > self.config.maxFootprintSize: return True if self.config.minFootprintAxisRatio > 0: axes = afwEll.Axes(footprint.getShape()) if axes.getB() < self.config.minFootprintAxisRatio * axes.getA(): return True return False
def computeBoxRadius(self, source): """ Calculate the postage stamp "radius" for a source. TODO: make RADIUS_FACTOR and MIN_RADIUS configurable. """ conf = self.config min_radius = conf['min_box_size'] / 2 max_radius = conf['max_box_size'] / 2 sigma = afwEllipses.Axes(source.getShape()).getA() if numpy.isnan(sigma): sigma = 1.0 rad = conf['radius_factor'] * sigma if rad < min_radius: rad = min_radius elif rad > max_radius: rad = max_radius return int(numpy.ceil(rad))
def main(rootDir, visit, ccd, n=10): # make a butler and specify your dataId butler = dafPersist.Butler(rootDir) dataId = {'visit': visit, 'ccd': ccd} # get sources and wcs from the butler sources = butler.get('src', dataId) exposure = butler.get('calexp', dataId, immediate=True) wcs = exposure.getWcs() #trans = wcs.getLinearTransform() pixScale = wcs.pixelScale().asArcseconds() for s in sources[:n]: # the transform commented-out above is for the whole CCD. Let's use the local one trans = wcs.linearizePixelToSky(s.getCentroid(), afwGeom.arcseconds).getLinear() m0 = s.getShape() m_new = m0.transform(trans) # print before and after the transform as a sanity check ms = m0, m_new pix = 1.0, pixScale for i in 0, 1: m = ms[i] ax = ellipses.Axes(m) # Ixx,yy,xy should be different after the transform print "%6.3f %6.3f %6.3f " % (m.getIxx(), m.getIyy(), m.getIxy()), # but A,B should be the same since the transformed ones are divided by the pixelScale # --> untransformed theta is wrt x-axis and increases *counter-clockwise* (standard cartesian) # --> transformed theta is wrt RA-axis and increases *clockwise* print "%6.3f %6.3f %6.3f " % (ax.getA() / pix[i], ax.getB() / pix[i], ax.getTheta()), print ""
def determinePsf(self, exposure, psfCandidateList, metadata=None, flagKey=None): """!Determine a PCA PSF model for an exposure given a list of PSF candidates \param[in] exposure exposure containing the psf candidates (lsst.afw.image.Exposure) \param[in] psfCandidateList a sequence of PSF candidates (each an lsst.meas.algorithms.PsfCandidate); typically obtained by detecting sources and then running them through a star selector \param[in,out] metadata a home for interesting tidbits of information \param[in] flagKey schema key used to mark sources actually used in PSF determination \return a list of - psf: the measured PSF, an lsst.meas.algorithms.PcaPsf - cellSet: an lsst.afw.math.SpatialCellSet containing the PSF candidates """ import lsstDebug display = lsstDebug.Info(__name__).display displayExposure = lsstDebug.Info( __name__).displayExposure # display the Exposure + spatialCells displayPsfCandidates = lsstDebug.Info( __name__).displayPsfCandidates # show the viable candidates displayIterations = lsstDebug.Info( __name__).displayIterations # display on each PSF iteration displayPsfComponents = lsstDebug.Info( __name__).displayPsfComponents # show the PCA components displayResiduals = lsstDebug.Info( __name__).displayResiduals # show residuals displayPsfMosaic = lsstDebug.Info( __name__).displayPsfMosaic # show mosaic of reconstructed PSF(x,y) # match Kernel amplitudes for spatial plots matchKernelAmplitudes = lsstDebug.Info(__name__).matchKernelAmplitudes # Keep matplotlib alive post mortem keepMatplotlibPlots = lsstDebug.Info(__name__).keepMatplotlibPlots displayPsfSpatialModel = lsstDebug.Info( __name__).displayPsfSpatialModel # Plot spatial model? showBadCandidates = lsstDebug.Info( __name__).showBadCandidates # Include bad candidates # Normalize residuals by object amplitude normalizeResiduals = lsstDebug.Info(__name__).normalizeResiduals pause = lsstDebug.Info( __name__).pause # Prompt user after each iteration? if display > 1: pause = True mi = exposure.getMaskedImage() if len(psfCandidateList) == 0: raise RuntimeError("No PSF candidates supplied.") # construct and populate a spatial cell set bbox = mi.getBBox() psfCellSet = afwMath.SpatialCellSet(bbox, self.config.sizeCellX, self.config.sizeCellY) sizes = [] for i, psfCandidate in enumerate(psfCandidateList): if psfCandidate.getSource().getPsfFluxFlag(): # bad measurement continue try: psfCellSet.insertCandidate(psfCandidate) except Exception as e: self.log.debug("Skipping PSF candidate %d of %d: %s", i, len(psfCandidateList), e) continue source = psfCandidate.getSource() quad = afwEll.Quadrupole(source.getIxx(), source.getIyy(), source.getIxy()) axes = afwEll.Axes(quad) sizes.append(axes.getA()) if len(sizes) == 0: raise RuntimeError("No usable PSF candidates supplied") nEigenComponents = self.config.nEigenComponents # initial version if self.config.kernelSize >= 15: self.log.warn( "WARNING: NOT scaling kernelSize by stellar quadrupole moment " + "because config.kernelSize=%s >= 15; using config.kernelSize as as the width, instead", self.config.kernelSize) actualKernelSize = int(self.config.kernelSize) else: medSize = numpy.median(sizes) actualKernelSize = 2 * int(self.config.kernelSize * math.sqrt(medSize) + 0.5) + 1 if actualKernelSize < self.config.kernelSizeMin: actualKernelSize = self.config.kernelSizeMin if actualKernelSize > self.config.kernelSizeMax: actualKernelSize = self.config.kernelSizeMax if display: print("Median size=%s" % (medSize, )) self.log.trace("Kernel size=%s", actualKernelSize) # Set size of image returned around candidate psfCandidateList[0].setHeight(actualKernelSize) psfCandidateList[0].setWidth(actualKernelSize) if self.config.doRejectBlends: # Remove blended candidates completely blendedCandidates = [ ] # Candidates to remove; can't do it while iterating for cell, cand in candidatesIter(psfCellSet, False): if len(cand.getSource().getFootprint().getPeaks()) > 1: blendedCandidates.append((cell, cand)) continue if display: print("Removing %d blended Psf candidates" % len(blendedCandidates)) for cell, cand in blendedCandidates: cell.removeCandidate(cand) if sum(1 for cand in candidatesIter(psfCellSet, False)) == 0: raise RuntimeError("All PSF candidates removed as blends") if display: frame = 0 if displayExposure: ds9.mtv(exposure, frame=frame, title="psf determination") maUtils.showPsfSpatialCells(exposure, psfCellSet, self.config.nStarPerCell, symb="o", ctype=ds9.CYAN, ctypeUnused=ds9.YELLOW, size=4, frame=frame) # # Do a PCA decomposition of those PSF candidates # reply = "y" # used in interactive mode for iterNum in range(self.config.nIterForPsf): if display and displayPsfCandidates: # Show a mosaic of usable PSF candidates # import lsst.afw.display.utils as displayUtils stamps = [] for cell in psfCellSet.getCellList(): for cand in cell.begin(not showBadCandidates ): # maybe include bad candidates try: im = cand.getMaskedImage() chi2 = cand.getChi2() if chi2 > 1e100: chi2 = numpy.nan stamps.append( (im, "%d%s" % (maUtils.splitId(cand.getSource().getId(), True)["objId"], chi2), cand.getStatus())) except Exception as e: continue if len(stamps) == 0: print( "WARNING: No PSF candidates to show; try setting showBadCandidates=True" ) else: mos = displayUtils.Mosaic() for im, label, status in stamps: im = type(im)(im, True) try: im /= afwMath.makeStatistics( im, afwMath.MAX).getValue() except NotImplementedError: pass mos.append( im, label, ds9.GREEN if status == afwMath.SpatialCellCandidate.GOOD else ds9.YELLOW if status == afwMath.SpatialCellCandidate.UNKNOWN else ds9.RED) mos.makeMosaic(frame=8, title="Psf Candidates") # Re-fit until we don't have any candidates with naughty chi^2 values influencing the fit cleanChi2 = False # Any naughty (negative/NAN) chi^2 values? while not cleanChi2: cleanChi2 = True # # First, estimate the PSF # psf, eigenValues, nEigenComponents, fitChi2 = \ self._fitPsf(exposure, psfCellSet, actualKernelSize, nEigenComponents) # # In clipping, allow all candidates to be innocent until proven guilty on this iteration. # Throw out any prima facie guilty candidates (naughty chi^2 values) # for cell in psfCellSet.getCellList(): awfulCandidates = [] for cand in cell.begin(False): # include bad candidates cand.setStatus(afwMath.SpatialCellCandidate.UNKNOWN ) # until proven guilty rchi2 = cand.getChi2() if not numpy.isfinite(rchi2) or rchi2 <= 0: # Guilty prima facie awfulCandidates.append(cand) cleanChi2 = False self.log.debug("chi^2=%s; id=%s", cand.getChi2(), cand.getSource().getId()) for cand in awfulCandidates: if display: print("Removing bad candidate: id=%d, chi^2=%f" % \ (cand.getSource().getId(), cand.getChi2())) cell.removeCandidate(cand) # # Clip out bad fits based on reduced chi^2 # badCandidates = list() for cell in psfCellSet.getCellList(): for cand in cell.begin(False): # include bad candidates rchi2 = cand.getChi2( ) # reduced chi^2 when fitting PSF to candidate assert rchi2 > 0 if rchi2 > self.config.reducedChi2ForPsfCandidates: badCandidates.append(cand) badCandidates.sort(key=lambda x: x.getChi2(), reverse=True) numBad = numCandidatesToReject(len(badCandidates), iterNum, self.config.nIterForPsf) for i, c in zip(range(numBad), badCandidates): if display: chi2 = c.getChi2() if chi2 > 1e100: chi2 = numpy.nan print("Chi^2 clipping %-4d %.2g" % (c.getSource().getId(), chi2)) c.setStatus(afwMath.SpatialCellCandidate.BAD) # # Clip out bad fits based on spatial fitting. # # This appears to be better at getting rid of sources that have a single dominant kernel component # (other than the zeroth; e.g., a nearby contaminant) because the surrounding sources (which help # set the spatial model) don't contain that kernel component, and so the spatial modeling # downweights the component. # residuals = list() candidates = list() kernel = psf.getKernel() noSpatialKernel = psf.getKernel() for cell in psfCellSet.getCellList(): for cand in cell.begin(False): candCenter = afwGeom.PointD(cand.getXCenter(), cand.getYCenter()) try: im = cand.getMaskedImage(kernel.getWidth(), kernel.getHeight()) except Exception as e: continue fit = fitKernelParamsToImage(noSpatialKernel, im, candCenter) params = fit[0] kernels = fit[1] amp = 0.0 for p, k in zip(params, kernels): amp += p * k.getSum() predict = [ kernel.getSpatialFunction(k)(candCenter.getX(), candCenter.getY()) for k in range(kernel.getNKernelParameters()) ] #print cand.getSource().getId(), [a / amp for a in params], predict residuals.append( [a / amp - p for a, p in zip(params, predict)]) candidates.append(cand) residuals = numpy.array(residuals) for k in range(kernel.getNKernelParameters()): if False: # Straight standard deviation mean = residuals[:, k].mean() rms = residuals[:, k].std() elif False: # Using interquartile range sr = numpy.sort(residuals[:, k]) mean = sr[int(0.5*len(sr))] if len(sr) % 2 else \ 0.5 * (sr[int(0.5*len(sr))] + sr[int(0.5*len(sr))+1]) rms = 0.74 * (sr[int(0.75 * len(sr))] - sr[int(0.25 * len(sr))]) else: stats = afwMath.makeStatistics( residuals[:, k], afwMath.MEANCLIP | afwMath.STDEVCLIP) mean = stats.getValue(afwMath.MEANCLIP) rms = stats.getValue(afwMath.STDEVCLIP) rms = max( 1.0e-4, rms) # Don't trust RMS below this due to numerical issues if display: print("Mean for component %d is %f" % (k, mean)) print("RMS for component %d is %f" % (k, rms)) badCandidates = list() for i, cand in enumerate(candidates): if numpy.fabs(residuals[i, k] - mean) > self.config.spatialReject * rms: badCandidates.append(i) badCandidates.sort( key=lambda x: numpy.fabs(residuals[x, k] - mean), reverse=True) numBad = numCandidatesToReject(len(badCandidates), iterNum, self.config.nIterForPsf) for i, c in zip(range(min(len(badCandidates), numBad)), badCandidates): cand = candidates[c] if display: print("Spatial clipping %d (%f,%f) based on %d: %f vs %f" % \ (cand.getSource().getId(), cand.getXCenter(), cand.getYCenter(), k, residuals[badCandidates[i], k], self.config.spatialReject * rms)) cand.setStatus(afwMath.SpatialCellCandidate.BAD) # # Display results # if display and displayIterations: if displayExposure: if iterNum > 0: ds9.erase(frame=frame) maUtils.showPsfSpatialCells(exposure, psfCellSet, self.config.nStarPerCell, showChi2=True, symb="o", size=8, frame=frame, ctype=ds9.YELLOW, ctypeBad=ds9.RED, ctypeUnused=ds9.MAGENTA) if self.config.nStarPerCellSpatialFit != self.config.nStarPerCell: maUtils.showPsfSpatialCells( exposure, psfCellSet, self.config.nStarPerCellSpatialFit, symb="o", size=10, frame=frame, ctype=ds9.YELLOW, ctypeBad=ds9.RED) if displayResiduals: while True: try: maUtils.showPsfCandidates( exposure, psfCellSet, psf=psf, frame=4, normalize=normalizeResiduals, showBadCandidates=showBadCandidates) maUtils.showPsfCandidates( exposure, psfCellSet, psf=psf, frame=5, normalize=normalizeResiduals, showBadCandidates=showBadCandidates, variance=True) except: if not showBadCandidates: showBadCandidates = True continue break if displayPsfComponents: maUtils.showPsf(psf, eigenValues, frame=6) if displayPsfMosaic: maUtils.showPsfMosaic(exposure, psf, frame=7, showFwhm=True) ds9.scale('linear', 0, 1, frame=7) if displayPsfSpatialModel: maUtils.plotPsfSpatialModel( exposure, psf, psfCellSet, showBadCandidates=True, matchKernelAmplitudes=matchKernelAmplitudes, keepPlots=keepMatplotlibPlots) if pause: while True: try: reply = input( "Next iteration? [ynchpqQs] ").strip() except EOFError: reply = "n" reply = reply.split() if reply: reply, args = reply[0], reply[1:] else: reply = "" if reply in ("", "c", "h", "n", "p", "q", "Q", "s", "y"): if reply == "c": pause = False elif reply == "h": print("c[ontinue without prompting] h[elp] n[o] p[db] q[uit displaying] " \ "s[ave fileName] y[es]") continue elif reply == "p": import pdb pdb.set_trace() elif reply == "q": display = False elif reply == "Q": sys.exit(1) elif reply == "s": fileName = args.pop(0) if not fileName: print("Please provide a filename") continue print("Saving to %s" % fileName) maUtils.saveSpatialCellSet(psfCellSet, fileName=fileName) continue break else: print("Unrecognised response: %s" % reply, file=sys.stderr) if reply == "n": break # One last time, to take advantage of the last iteration psf, eigenValues, nEigenComponents, fitChi2 = \ self._fitPsf(exposure, psfCellSet, actualKernelSize, nEigenComponents) # # Display code for debugging # if display and reply != "n": if displayExposure: maUtils.showPsfSpatialCells(exposure, psfCellSet, self.config.nStarPerCell, showChi2=True, symb="o", ctype=ds9.YELLOW, ctypeBad=ds9.RED, size=8, frame=frame) if self.config.nStarPerCellSpatialFit != self.config.nStarPerCell: maUtils.showPsfSpatialCells( exposure, psfCellSet, self.config.nStarPerCellSpatialFit, symb="o", ctype=ds9.YELLOW, ctypeBad=ds9.RED, size=10, frame=frame) if displayResiduals: maUtils.showPsfCandidates( exposure, psfCellSet, psf=psf, frame=4, normalize=normalizeResiduals, showBadCandidates=showBadCandidates) if displayPsfComponents: maUtils.showPsf(psf, eigenValues, frame=6) if displayPsfMosaic: maUtils.showPsfMosaic(exposure, psf, frame=7, showFwhm=True) ds9.scale("linear", 0, 1, frame=7) if displayPsfSpatialModel: maUtils.plotPsfSpatialModel( exposure, psf, psfCellSet, showBadCandidates=True, matchKernelAmplitudes=matchKernelAmplitudes, keepPlots=keepMatplotlibPlots) # # Generate some QA information # # Count PSF stars # numGoodStars = 0 numAvailStars = 0 avgX = 0.0 avgY = 0.0 for cell in psfCellSet.getCellList(): for cand in cell.begin(False): # don't ignore BAD stars numAvailStars += 1 for cand in cell.begin(True): # do ignore BAD stars src = cand.getSource() if flagKey is not None: src.set(flagKey, True) avgX += src.getX() avgY += src.getY() numGoodStars += 1 avgX /= numGoodStars avgY /= numGoodStars if metadata is not None: metadata.set("spatialFitChi2", fitChi2) metadata.set("numGoodStars", numGoodStars) metadata.set("numAvailStars", numAvailStars) metadata.set("avgX", avgX) metadata.set("avgY", avgY) psf = PcaPsf(psf.getKernel(), afwGeom.Point2D(avgX, avgY)) return psf, psfCellSet
def setUp(self): self.x0, self.y0 = 0, 0 self.nx, self.ny = 512, 512 #2048, 4096 self.sky = 100.0 self.nObj = 100 # make a distorter # This is a lot of distortion ... from circle r=1, to ellipse with a=1.3 (ie. 30%) # For suprimecam, we expect only about 5% self.distCoeffs = [0.0, 1.0, 2.0e-04, 3.0e-8] lanczosOrder = 3 coefficientsDistort = True self.distorter = cameraGeom.RadialPolyDistortion( self.distCoeffs, coefficientsDistort, lanczosOrder) # make a detector self.detector = cameraUtils.makeDefaultCcd( afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(self.nx, self.ny))) self.detector.setDistortion(self.distorter) self.detector.setCenter(cameraGeom.FpPoint( 255.5, 255.5)) # move boresight from center to 0,0 if False: for x, y in [(0, 0), (0, 511), (511, 0), (511, 511)]: p = afwGeom.Point2D(x, y) iqq = self.distorter.distort(p, geomEllip.Quadrupole(), self.detector) print x, y, geomEllip.Axes(iqq) print self.detector.getPositionFromPixel(p).getMm() print "Max distortion on this detector: ", self.distorter.computeMaxShear( self.detector) # detection policies self.detConfig = measAlg.SourceDetectionConfig() # measurement policies self.measSrcConfig = measAlg.SourceMeasurementConfig() # psf star selector starSelectorFactory = measAlg.starSelectorRegistry["secondMoment"] starSelectorConfig = starSelectorFactory.ConfigClass() starSelectorConfig.fluxLim = 5000.0 starSelectorConfig.histSize = 32 starSelectorConfig.clumpNSigma = 1.0 starSelectorConfig.badFlags = [] self.starSelector = starSelectorFactory(starSelectorConfig) # psf determiner psfDeterminerFactory = measAlg.psfDeterminerRegistry["pca"] psfDeterminerConfig = psfDeterminerFactory.ConfigClass() width, height = self.nx, self.ny nEigenComponents = 3 psfDeterminerConfig.sizeCellX = width // 3 psfDeterminerConfig.sizeCellY = height // 3 psfDeterminerConfig.nEigenComponents = nEigenComponents psfDeterminerConfig.spatialOrder = 1 psfDeterminerConfig.kernelSizeMin = 31 psfDeterminerConfig.nStarPerCell = 0 psfDeterminerConfig.nStarPerCellSpatialFit = 0 # unlimited self.psfDeterminer = psfDeterminerFactory(psfDeterminerConfig)
def getCoeffCircle(self, radius2): circle = afwEll.Axes(radius2, radius2, 0.0) inner = self.radius1 / radius2 coeff1 = measAlgorithms.SincCoeffsF.get(circle, inner) coeff2 = measAlgorithms.SincCoeffsF.get(circle, inner) return coeff1, coeff2
def setUp(self): self.ellipse = afwEll.Axes(10.0, 5.0, 0.12345) self.radius1 = 0.1234 self.radius2 = 4.3210 self.inner = self.radius1 / self.radius2
def main(dataDir, visit, title="", outputTxtFileName=None, showFwhm=False, minFwhm=None, maxFwhm=None, correctDistortion=False, showEllipticity=False, ellipticityDirection=False, showNdataFwhm=False, showNdataEll=False, minNdata=None, maxNdata=None, gridPoints=30, verbose=False): butler = dafPersist.ButlerFactory(mapper=hscSim.HscSimMapper( root=dataDir)).create() camera = butler.get("camera") if not (showFwhm or showEllipticity or showNdataFwhm or showNdataEll or outputTxtFileName): showFwhm = True # # Get a dict of cameraGeom::Ccd indexed by serial number # ccds = {} for raft in camera: for ccd in raft: ccd.setTrimmed(True) ccds[ccd.getId().getSerial()] = ccd # # Read all the tableSeeingMap files, converting their (x, y) to focal plane coordinates # xArr = [] yArr = [] ellArr = [] fwhmArr = [] paArr = [] aArr = [] bArr = [] e1Arr = [] e2Arr = [] elle1e2Arr = [] for tab in butler.subset("tableSeeingMap", visit=visit): # we could use tab.datasetExists() but it prints a rude message fileName = butler.get("tableSeeingMap_filename", **tab.dataId)[0] if not os.path.exists(fileName): continue with open(fileName) as fd: ccd = None for line in fd.readlines(): if re.search(r"^\s*#", line): continue fields = [float(_) for _ in line.split()] if ccd is None: ccd = ccds[int(fields[0])] x, y, fwhm, ell, pa, a, b = fields[1:8] x, y = ccd.getPositionFromPixel(afwGeom.PointD(x, y)).getMm() xArr.append(x) yArr.append(y) ellArr.append(ell) fwhmArr.append(fwhm) paArr.append(pa) aArr.append(a) bArr.append(b) if len(fields) == 11: e1 = fields[8] e2 = fields[9] elle1e2 = fields[10] else: e1 = -9999. e2 = -9999. elle1e2 = -9999. e1Arr.append(e1) e2Arr.append(e2) elle1e2Arr.append(elle1e2) xArr = np.array(xArr) yArr = np.array(yArr) ellArr = np.array(ellArr) fwhmArr = np.array(fwhmArr) * 0.168 # arcseconds paArr = np.radians(np.array(paArr)) aArr = np.array(aArr) bArr = np.array(bArr) e1Arr = np.array(e1Arr) e2Arr = np.array(e2Arr) elle1e2Arr = np.array(elle1e2Arr) if correctDistortion: import lsst.afw.geom.ellipses as afwEllipses dist = camera.getDistortion() for i in range(len(aArr)): axes = afwEllipses.Axes(aArr[i], bArr[i], paArr[i]) if False: # testing only! axes = afwEllipses.Axes(1.0, 1.0, np.arctan2(yArr[i], xArr[i])) quad = afwEllipses.Quadrupole(axes) quad = quad.transform( dist.computeQuadrupoleTransform( afwGeom.PointD(xArr[i], yArr[i]), False)) axes = afwEllipses.Axes(quad) aArr[i], bArr[i], paArr[i] = axes.getA(), axes.getB( ), axes.getTheta() ellArr = 1 - bArr / aArr if len(xArr) == 0: gridPoints = 0 xs, ys = [], [] else: N = gridPoints * 1j extent = [min(xArr), max(xArr), min(yArr), max(yArr)] xs, ys = np.mgrid[extent[0]:extent[1]:N, extent[2]:extent[3]:N] title = [ title, ] title.append("\n#") if outputTxtFileName: f = open(outputTxtFileName, 'w') f.write("# %s visit %s\n" % (" ".join(title), visit)) for x, y, ell, fwhm, pa, a, b, e1, e2, elle1e2 in zip( xArr, yArr, ellArr, fwhmArr, paArr, aArr, bArr, e1Arr, e2Arr, elle1e2Arr): f.write('%f %f %f %f %f %f %f %f %f %f\n' % (x, y, ell, fwhm, pa, a, b, e1, e2, elle1e2)) if showFwhm: title.append("FWHM (arcsec)") if len(xs) > 0: fwhmResampled = griddata(xArr, yArr, fwhmArr, xs, ys) plt.imshow(fwhmResampled.T, extent=extent, vmin=minFwhm, vmax=maxFwhm, origin='lower') plt.colorbar() if outputTxtFileName: ndataGrids = getNumDataGrids(xArr, yArr, fwhmArr, xs, ys) f = open(outputTxtFileName + '-fwhm-grid.txt', 'w') f.write("# %s visit %s\n" % (" ".join(title), visit)) for xline, yline, fwhmline, ndataline in zip( xs.tolist(), ys.tolist(), fwhmResampled.tolist(), ndataGrids): for xx, yy, fwhm, ndata in zip(xline, yline, fwhmline, ndataline): if fwhm is None: fwhm = -9999 f.write('%f %f %f %d\n' % (xx, yy, fwhm, ndata)) elif showEllipticity: title.append("Ellipticity") scale = 4 if ellipticityDirection: # we don't care about the magnitude ellArr = 0.1 u = -ellArr * np.cos(paArr) v = -ellArr * np.sin(paArr) if gridPoints > 0: u = griddata(xArr, yArr, u, xs, ys) v = griddata(xArr, yArr, v, xs, ys) x, y = xs, ys else: x, y = xArr, yArr Q = plt.quiver( x, y, u, v, scale=scale, pivot="middle", headwidth=0, headlength=0, headaxislength=0, ) keyLen = 0.10 if not ellipticityDirection: # we care about the magnitude plt.quiverkey(Q, 0.20, 0.95, keyLen, "e=%g" % keyLen, labelpos='W') if outputTxtFileName: ndataGrids = getNumDataGrids(xArr, yArr, ellArr, xs, ys) f = open(outputTxtFileName + '-ell-grid.txt', 'w') f.write("# %s visit %s\n" % (" ".join(title), visit)) #f.write('# %f %f %f %f %f %f %f\n' % (x, y, ell, fwhm, pa, a, b)) for xline, yline, uline, vline, ndataline in zip( x.tolist(), y.tolist(), u.tolist(), v.tolist(), ndataGrids): for xx, yy, uu, vv, ndata in zip(xline, yline, uline, vline, ndataline): if uu is None: uu = -9999 if vv is None: vv = -9999 f.write('%f %f %f %f %d\n' % (xx, yy, uu, vv, ndata)) elif showNdataFwhm: title.append("N per fwhm grid") if len(xs) > 0: ndataGrids = getNumDataGrids(xArr, yArr, fwhmArr, xs, ys) plt.imshow(ndataGrids, interpolation='nearest', extent=extent, vmin=minNdata, vmax=maxNdata, origin='lower') plt.colorbar() else: pass elif showNdataEll: title.append("N per ell grid") if len(xs) > 0: ndataGrids = getNumDataGrids(xArr, yArr, ellArr, xs, ys) plt.imshow(ndataGrids, interpolation='nearest', extent=extent, vmin=minNdata, vmax=maxNdata, origin='lower') plt.colorbar() else: pass #plt.plot(xArr, yArr, "r.") #plt.plot(xs, ys, "b.") plt.axes().set_aspect('equal') plt.axis([-20000, 20000, -20000, 20000]) def frameInfoFrom(filepath): import pyfits with pyfits.open(filepath) as hdul: h = hdul[0].header 'object=ABELL2163 filter=HSC-I exptime=360.0 alt=62.11143274 azm=202.32265181 hst=(23:40:08.363-23:40:48.546)' return 'object=%s filter=%s exptime=%.1f azm=%.2f hst=%s' % ( h['OBJECT'], h['FILTER01'], h['EXPTIME'], h['AZIMUTH'], h['HST']) title.insert( 0, frameInfoFrom( butler.get('raw_filename', { 'visit': visit, 'ccd': 0 })[0])) title.append(r'$\langle$FWHM$\rangle %4.2f$"' % np.median(fwhmArr)) plt.title("%s visit=%s" % (" ".join(title), visit), fontsize=9) return plt