def testPlateScale(self): """Test that we can measure the area of a pixel""" p00 = afwGeom.Point2D(10, 10) p00 = afwGeom.Point2D(self.metadata.getAsDouble("CRPIX1"), self.metadata.getAsDouble("CRPIX2")) sky00 = self.wcs.pixelToSky(p00) cosdec = math.cos(sky00[1]) side = 1e-3 icrs = afwCoord.ICRS degrees = afwCoord.DEGREES sky10 = afwCoord.makeCoord(icrs, sky00 + afwGeom.Extent2D(side/cosdec, 0), degrees) sky01 = afwCoord.makeCoord(icrs, sky00 + afwGeom.Extent2D(0,side), degrees) p10 = self.wcs.skyToPixel(sky10) - p00 p01 = self.wcs.skyToPixel(sky01) - p00 area = side*side/abs(p10.getX()*p01.getY() - p01.getX()*p10.getY()) self.assertAlmostEqual(math.sqrt(self.wcs.pixArea(p00)), math.sqrt(area)) # # Now check that the area's the same as the CD matrix gives. # cd = [self.metadata.get("CD1_1"), self.metadata.get("CD1_2"), self.metadata.get("CD2_1"), self.metadata.get("CD2_2")] area = math.fabs(cd[0]*cd[3] - cd[1]*cd[2]) self.assertAlmostEqual(math.sqrt(self.wcs.pixArea(p00)), math.sqrt(area))
def testPlateScale(self): """Test that we can measure the area of a pixel""" p00 = afwGeom.Point2D(10, 10) p00 = afwGeom.Point2D(self.metadata.getAsDouble("CRPIX1"), self.metadata.getAsDouble("CRPIX2")) sky00 = self.wcs.pixelToSky(p00) cosdec = math.cos(sky00[1]) side = 1e-3 icrs = afwCoord.ICRS sky10 = afwCoord.makeCoord( icrs, sky00.getPosition(afwGeom.degrees) + afwGeom.Extent2D(side/cosdec, 0), afwGeom.degrees ) sky01 = afwCoord.makeCoord( icrs, sky00.getPosition(afwGeom.degrees) + afwGeom.Extent2D(0,side), afwGeom.degrees ) p10 = self.wcs.skyToPixel(sky10) - p00 p01 = self.wcs.skyToPixel(sky01) - p00 area = side*side/abs(p10.getX()*p01.getY() - p01.getX()*p10.getY()) self.assertAlmostEqual(math.sqrt(self.wcs.pixArea(p00)), math.sqrt(area)) # # Now check that the area's the same as the CD matrix gives. # cd = [self.metadata.get("CD1_1"), self.metadata.get("CD1_2"), self.metadata.get("CD2_1"), self.metadata.get("CD2_2")] area = math.fabs(cd[0]*cd[3] - cd[1]*cd[2]) self.assertAlmostEqual(math.sqrt(self.wcs.pixArea(p00)), math.sqrt(area))
def localMakeCoord(coordSys, posDeg, equinox): """Make a coord, ignoring equinox if necessary """ if coordSys in (afwCoord.ICRS, afwCoord.GALACTIC): return afwCoord.makeCoord(coordSys, posDeg[0] * afwGeom.degrees, posDeg[1] * afwGeom.degrees) return afwCoord.makeCoord(coordSys, posDeg[0] * afwGeom.degrees, posDeg[1] * afwGeom.degrees, equinox)
def testPythonLevelMakeWcs(self): """Verify that we can make a Wcs by providing the CD matrix elements in python.""" m = self.metadata crval = afwCoord.makeCoord(afwCoord.ICRS, m.getDouble("CRVAL1") * afwGeom.degrees, m.getDouble("CRVAL2") * afwGeom.degrees) crpix = afwGeom.Point2D(m.getDouble("CRPIX1"), m.getDouble("CRPIX2")) cd11, cd12 = m.getDouble("CD1_1"), m.getDouble("CD1_2") cd21, cd22 = m.getDouble("CD2_1"), m.getDouble("CD2_2") print 'CRVAL:', crval # this is defined at the c++ level in src/image/makeWcs.cc wcsMade = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) # trivial test ... verify that we get back what we put in. for wcs in [wcsMade]: crvalTest = wcs.getSkyOrigin().getPosition(afwGeom.degrees) crpixTest = wcs.getPixelOrigin() CD = wcs.getCDMatrix() self.assertAlmostEqual(crvalTest[0], crval.getLongitude().asDegrees()) self.assertAlmostEqual(crvalTest[1], crval.getLatitude().asDegrees()) self.assertAlmostEqual(crpixTest[0], crpix[0]) self.assertAlmostEqual(crpixTest[1], crpix[1]) self.assertAlmostEqual(CD[0, 0], cd11) self.assertAlmostEqual(CD[0, 1], cd12) self.assertAlmostEqual(CD[1, 0], cd21) self.assertAlmostEqual(CD[1, 1], cd22)
def testPythonLevelMakeWcs(self): """Verify that we can make a Wcs by providing the CD matrix elements in python.""" m = self.metadata crval = afwCoord.makeCoord(afwCoord.ICRS, m.getDouble("CRVAL1") * afwGeom.degrees, m.getDouble("CRVAL2") * afwGeom.degrees) crpix = afwGeom.Point2D(m.getDouble("CRPIX1"), m.getDouble("CRPIX2")) cd11, cd12 = m.getDouble("CD1_1"), m.getDouble("CD1_2") cd21, cd22 = m.getDouble("CD2_1"), m.getDouble("CD2_2") print 'CRVAL:', crval # this is defined at the c++ level in src/image/makeWcs.cc wcsMade = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) # trivial test ... verify that we get back what we put in. for wcs in [wcsMade]: crvalTest = wcs.getSkyOrigin().getPosition(afwGeom.degrees) crpixTest = wcs.getPixelOrigin() CD = wcs.getCDMatrix() self.assertAlmostEqual(crvalTest[0], crval.getLongitude().asDegrees()) self.assertAlmostEqual(crvalTest[1], crval.getLatitude().asDegrees()) self.assertAlmostEqual(crpixTest[0], crpix[0]) self.assertAlmostEqual(crpixTest[1], crpix[1]) self.assertAlmostEqual(CD[0,0], cd11) self.assertAlmostEqual(CD[0,1], cd12) self.assertAlmostEqual(CD[1,0], cd21) self.assertAlmostEqual(CD[1,1], cd22)
def testInvalidRaDec(self): """Test a conversion for an invalid position. Well, "test" isn't quite right as the result is invalid, but make sure that it still is""" raDec = afwCoord.makeCoord(afwCoord.ICRS, 1 * afwGeom.degrees, 2 * afwGeom.degrees) self.assertRaises(lsst.pex.exceptions.Exception, self.wcs.skyToPixel, raDec)
def coordFromVec(vec, defRA=None): """Convert an ICRS cartesian vector to an ICRS Coord @param[in] vec: an ICRS catesian vector as a sequence of three floats @param[in] defRA: the RA to use if the vector is too near a pole (an afwGeom Angle); ignored if not near a pole @throw RuntimeError if vec too near a pole and defRA is None """ if abs(vec[0]) < _TinyFloat and abs(vec[1]) < _TinyFloat: if defRA is None: raise RuntimeError("At pole and defRA==None") if vec[2] > 0: dec = 90.0 else: dec = -90.0 return afwCoord.makeCoord(afwCoord.ICRS, defRA, afwGeom.Angle(dec, afwGeom.degrees)) return afwCoord.makeCoord(afwCoord.ICRS, afwGeom.Point3D(*vec))
def testTicket1394(self): """Ticket #1394 bug: coord within epsilon of RA=0 leads to negative RA and fails bounds check. """ # the problem was that the coordinate is < epsilon close to RA==0 # and bounds checking was getting a -ve RA. c = afwCoord.makeCoord(afwCoord.ICRS, afwGeom.Point3D(0.6070619982, -1.264309928e-16, 0.7946544723)) self.assertEqual(c[0], 0.0)
def testAffineTransform(self): sky00g = afwGeom.Point2D(10, 10) sky00c = afwCoord.makeCoord(afwCoord.ICRS, sky00g, afwGeom.degrees) a = self.wcs.linearizeSkyToPixel(sky00c) pix00g = self.wcs.skyToPixel(sky00c) pix00gApprox = a(sky00g); self.assertAlmostEqual(pix00g.getX(), pix00gApprox.getX()) self.assertAlmostEqual(pix00g.getY(), pix00gApprox.getY()) b = a.invert() self.assertAlmostEqual(self.wcs.pixArea(sky00g), abs(b[b.XX]* b[b.YY] - b[b.XY]*b[b.YX]))
def testAffineTransform(self): sky00g = afwGeom.Point2D(10, 10) sky00c = afwCoord.makeCoord(afwCoord.ICRS, sky00g, afwGeom.degrees) a = self.wcs.linearizeSkyToPixel(sky00c) pix00g = self.wcs.skyToPixel(sky00c) pix00gApprox = a(sky00g) self.assertAlmostEqual(pix00g.getX(), pix00gApprox.getX()) self.assertAlmostEqual(pix00g.getY(), pix00gApprox.getY()) b = a.invert() self.assertAlmostEqual(self.wcs.pixArea(sky00g), abs(b[b.XX] * b[b.YY] - b[b.XY] * b[b.YX]))
def makeitLsst(prefs, context, saveWcs=False, plot=dict()): """This is the python wrapper that reads lsst tables""" # Create an array of PSFs (one PSF for each extension) if prefs.getVerboseType() != prefs.QUIET: print("----- %d input catalogues:" % prefs.getNcat()) if saveWcs: # only needed for making plots wcssList = [] fields = psfexLib.vectorField() for cat in prefs.getCatalogs(): field = psfexLib.Field(cat) wcss = [] wcssList.append(wcss) with pyfits.open(cat): # Hack: I want the WCS so I'll guess where the calexp is to be found calexpFile = guessCalexp(cat) md = afwImage.readMetadata(calexpFile) wcs = afwImage.makeWcs(md) if not wcs: crval = afwCoord.makeCoord(afwCoord.ICRS, 0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees) wcs = afwImage.makeWcs(crval, afwGeom.PointD(0, 0), 1.0, 0, 0, 1.0) naxis1, naxis2 = md.get("NAXIS1"), md.get("NAXIS2") # Find how many rows there are in the catalogue md = afwImage.readMetadata(cat) field.addExt(wcs, naxis1, naxis2, md.get("NAXIS2")) if saveWcs: wcss.append((wcs, naxis1, naxis2)) field.finalize() fields.append(field) fields[0].getNext() # number of extensions prefs.getPsfStep() sets = psfexLib.vectorSet() for set in load_samplesLsst(prefs, context, plot=plot): sets.append(set) psfexLib.makeit(fields, sets) ret = [[f.getPsfs() for f in fields], sets] if saveWcs: ret.append(wcssList) return ret
def runMeasurement(self, algorithmName, imageid, x, y, v): """Run the measurement algorithm on an image""" # load the test image imgFile = os.path.join(self.dataDir, "image.%d.fits" % imageid) img = afwImage.ImageF(imgFile) img -= self.bkgd nx, ny = img.getWidth(), img.getHeight() msk = afwImage.Mask(afwGeom.Extent2I(nx, ny), 0x0) var = afwImage.ImageF(afwGeom.Extent2I(nx, ny), v) mimg = afwImage.MaskedImageF(img, msk, var) msk.getArray()[:] = np.where(np.fabs(img.getArray()) < 1.0e-8, msk.getPlaneBitMask("BAD"), 0) # Put it in a bigger image, in case it matters big = afwImage.MaskedImageF(self.offset + mimg.getDimensions()) big.getImage().set(0) big.getMask().set(0) big.getVariance().set(v) subBig = afwImage.MaskedImageF(big, afwGeom.Box2I(big.getXY0() + self.offset, mimg.getDimensions())) subBig <<= mimg mimg = big mimg.setXY0(self.xy0) exposure = afwImage.makeExposure(mimg) exposure.setWcs(afwImage.makeWcs(afwCoord.makeCoord(afwCoord.ICRS, 0. * afwGeom.degrees, 0. * afwGeom.degrees), afwGeom.Point2D(1.0, 1.0), 1.0/(2.53*3600.0), 0.0, 0.0, 1.0/(2.53*3600.0))) # load the corresponding test psf psfFile = os.path.join(self.dataDir, "psf.%d.fits" % imageid) psfImg = afwImage.ImageD(psfFile) psfImg -= self.bkgd kernel = afwMath.FixedKernel(psfImg) kernelPsf = algorithms.KernelPsf(kernel) exposure.setPsf(kernelPsf) # perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() alg = base.SingleFramePlugin.registry[algorithmName].PluginClass.AlgClass control = base.SingleFramePlugin.registry[algorithmName].PluginClass.ConfigClass().makeControl() msConfig.algorithms.names = [algorithmName] # Note: It is essential to remove the floating point part of the position for the # Algorithm._apply. Otherwise, when the PSF is realised it will have been warped # to account for the sub-pixel offset and we won't get *exactly* this PSF. plugin, table = makePluginAndCat(alg, algorithmName, control, centroid="centroid") center = afwGeom.Point2D(int(x), int(y)) + afwGeom.Extent2D(self.offset + afwGeom.Extent2I(self.xy0)) source = table.makeRecord() source.set("centroid_x", center.getX()) source.set("centroid_y", center.getY()) source.setFootprint(afwDetection.Footprint(afwGeom.SpanSet(exposure.getBBox(afwImage.PARENT)))) plugin.measure(source, exposure) return source
def runMeasurement(self, algorithmName, imageid, x, y, v): """Run the measurement algorithm on an image""" # load the test image imgFile = os.path.join(self.dataDir, "image.%d.fits" % imageid) img = afwImage.ImageF(imgFile) img -= self.bkgd nx, ny = img.getWidth(), img.getHeight() msk = afwImage.MaskU(afwGeom.Extent2I(nx, ny), 0x0) var = afwImage.ImageF(afwGeom.Extent2I(nx, ny), v) mimg = afwImage.MaskedImageF(img, msk, var) msk.getArray()[:] = np.where(np.fabs(img.getArray()) < 1.0e-8, msk.getPlaneBitMask("BAD"), 0) # Put it in a bigger image, in case it matters big = afwImage.MaskedImageF(self.offset + mimg.getDimensions()) big.getImage().set(0) big.getMask().set(0) big.getVariance().set(v) subBig = afwImage.MaskedImageF(big, afwGeom.Box2I(big.getXY0() + self.offset, mimg.getDimensions())) subBig <<= mimg mimg = big mimg.setXY0(self.xy0) exposure = afwImage.makeExposure(mimg) exposure.setWcs(afwImage.makeWcs(afwCoord.makeCoord(afwCoord.ICRS, 0. * afwGeom.degrees, 0. * afwGeom.degrees), afwGeom.Point2D(1.0,1.0), 1.0/(2.53*3600.0), 0.0, 0.0, 1.0/(2.53*3600.0))) # load the corresponding test psf psfFile = os.path.join(self.dataDir, "psf.%d.fits" % imageid) psfImg = afwImage.ImageD(psfFile) psfImg -= self.bkgd kernel = afwMath.FixedKernel(psfImg) kernelPsf = algorithms.KernelPsf(kernel) exposure.setPsf(kernelPsf) # perform the shape measurement msConfig = base.SingleFrameMeasurementConfig() alg = base.SingleFramePlugin.registry[algorithmName].PluginClass.AlgClass control = base.SingleFramePlugin.registry[algorithmName].PluginClass.ConfigClass().makeControl() msConfig.algorithms.names = [algorithmName] # Note: It is essential to remove the floating point part of the position for the # Algorithm._apply. Otherwise, when the PSF is realised it will have been warped # to account for the sub-pixel offset and we won't get *exactly* this PSF. plugin, table = makePluginAndCat(alg, algorithmName, control, centroid="centroid") center = afwGeom.Point2D(int(x), int(y)) + afwGeom.Extent2D(self.offset + afwGeom.Extent2I(self.xy0)) source = table.makeRecord() source.set("centroid_x", center.getX()) source.set("centroid_y", center.getY()) source.setFootprint(afwDetection.Footprint(exposure.getBBox(afwImage.PARENT))) plugin.measure(source, exposure) return source
def testFactory(self): """Test the Factory function makeCoord()""" # make a (eg galactic) coord with the constructor, and with the factory # and see if they agree. for constructor, enum, cast, stringName in self.coordList: con = constructor(self.l * afwGeom.degrees, self.b * afwGeom.degrees) self.assertEqual(con.getCoordSystem(), enum) factories = [] factories.append(afwCoord.makeCoord(enum, self.l * afwGeom.degrees, self.b * afwGeom.degrees)) factories.append(afwCoord.makeCoord(afwCoord.makeCoordEnum(stringName), self.l * afwGeom.degrees, self.b * afwGeom.degrees)) factories.append(afwCoord.makeCoord(enum, afwGeom.Point2D(self.l, self.b), afwGeom.degrees)) print("Factory: ") for fac in factories: self.assertEqual(fac.getCoordSystem(), enum) self.assertAlmostEqual(con[0], fac[0]) self.assertAlmostEqual(con[1], fac[1]) print(" tried ", fac[0], fac[1], "(expected ", con[0], con[1], ")") # can we create an empty coord, and use reset() to fill it? c = afwCoord.makeCoord(enum) c.reset(1.0 * afwGeom.degrees, 1.0 * afwGeom.degrees, 2000.0) myCoord = cast(c) self.assertEqual(myCoord.getLongitude().asDegrees(), 1.0) self.assertEqual(myCoord.getLatitude().asDegrees(), 1.0) # verify that makeCoord throws when given an epoch for an epochless system self.assertRaises(pexEx.Exception, lambda: afwCoord.makeCoord(afwCoord.GALACTIC, self.l * afwGeom.degrees, self.b * afwGeom.degrees, 2000.0)) self.assertRaises(pexEx.Exception, lambda: afwCoord.makeCoord(afwCoord.ICRS, self.l * afwGeom.degrees, self.b * afwGeom.degrees, 2000.0))
def makeitLsst(prefs, context, saveWcs=False, plot=dict()): """This is the python wrapper that reads lsst tables""" # Create an array of PSFs (one PSF for each extension) if prefs.getVerboseType() != prefs.QUIET: print "----- %d input catalogues:" % prefs.getNcat() if saveWcs: # only needed for making plots wcssList = [] fields = psfex.vectorField() for cat in prefs.getCatalogs(): field = psfex.Field(cat) wcss = [] wcssList.append(wcss) with pyfits.open(cat) as pf: # Hack: I want the WCS so I'll guess where the calexp is to be found calexpFile = guessCalexp(cat) md = afwImage.readMetadata(calexpFile) wcs = afwImage.makeWcs(md) if not wcs: crval = afwCoord.makeCoord(afwCoord.ICRS, 0.0*afwGeom.degrees, 0.0*afwGeom.degrees) wcs = afwImage.makeWcs(crval, afwGeom.PointD(0, 0), 1.0, 0, 0, 1.0) naxis1, naxis2 = md.get("NAXIS1"), md.get("NAXIS2") # Find how many rows there are in the catalogue md = afwImage.readMetadata(cat) field.addExt(wcs, naxis1, naxis2, md.get("NAXIS2")) if saveWcs: wcss.append((wcs, naxis1, naxis2)) field.finalize() fields.append(field) next = fields[0].getNext() # number of extensions psfstep = prefs.getPsfStep() sets = psfex.vectorSet() for set in load_samplesLsst(prefs, context, plot=plot): sets.append(set) psfex.makeit(fields, sets) ret = [[f.getPsfs() for f in fields], sets] if saveWcs: ret.append(wcssList) return ret
def testRaDecUnits(self): # LSST decrees radians. # In the setUp() above, the RAs set could reasonably be interpreted as radians. sources = self.dsv2.getSources() # check that getRa() returns in radians # MAGIC 0.349... = math.radians(20.) self.assertAlmostEqual(sources[1].getRa().asRadians(), 0.3490658503988659) # These tests don't make so much sense now that we use Angle! # check that setRaDec() getRaDec() round-trips. ra,dec = 100., 50. # makeCoord takes degrees. c1 = afwCoord.makeCoord(afwCoord.ICRS, ra * afwGeom.degrees, dec * afwGeom.degrees) # (test that by using degrees explicitly) c2 = afwCoord.makeCoord(afwCoord.ICRS, afwGeom.Point2D(ra, dec), afwGeom.degrees) self.assertAlmostEqual(c1.toIcrs().getRa().asDegrees(), c2.toIcrs().getRa().asDegrees()) self.assertAlmostEqual(c1.toIcrs().getDec().asDegrees(), c2.toIcrs().getDec().asDegrees()) src = afwDet.Source() src.setRaDec(c1) # get it back in ICRS by default c1b = src.getRaDec() self.assertAlmostEqual(c1.toIcrs().getDec().asDegrees(), c1b.toIcrs().getDec().asDegrees()) self.assertAlmostEqual(c1.toIcrs().getRa().asDegrees(), c1b.toIcrs().getRa().asDegrees()) self.assertAlmostEqual(src.getRa().asDegrees(), ra) self.assertAlmostEqual(src.getDec().asDegrees(), dec) src.setRa(math.pi * afwGeom.radians) src.setDec(math.pi / 4. * afwGeom.radians) c1c = src.getRaDec() self.assertAlmostEqual(c1c.getLongitude().asDegrees(), 180.) self.assertAlmostEqual(c1c.getLatitude().asDegrees(), 45.)
def testAffineTransform(self): a = self.wcs.getLinearTransform() l = self.wcs.getCDMatrix() #print print a[a.XX], a[a.XY], a[a.YX], a[a.YY] sky00g = afwGeom.Point2D(10, 10) sky00i = afwGeom.Point2D(sky00g.getX(), sky00g.getY()) sky00c = afwCoord.makeCoord(afwCoord.ICRS, sky00i, afwCoord.DEGREES) a = self.wcs.linearizeSkyToPixel(sky00c) pix00i = self.wcs.skyToPixel(sky00c) pix00g = afwGeom.Point2D(pix00i.getX(), pix00i.getY()) sky00gApprox = a(pix00g); self.assertAlmostEqual(sky00g.getX(), sky00gApprox.getX()) self.assertAlmostEqual(sky00g.getY(), sky00gApprox.getY()) self.assertAlmostEqual(self.wcs.pixArea(sky00i), abs(a[a.XX]* a[a.YY] - a[a.XY]*a[a.YX])) a.invert()
def testXyToRaDecArguments(self): """Check that conversion of xy to ra dec (and back again) works""" xy = afwGeom.Point2D(110, 123) raDec = self.wcs.pixelToSky(xy) xy2 = self.wcs.skyToPixel(raDec) self.assertAlmostEqual(xy.getX(), xy2.getX()) self.assertAlmostEqual(xy.getY(), xy2.getY()) raDec = afwCoord.makeCoord(afwCoord.ICRS, 245.167400 * afwGeom.degrees, +19.1976583 * afwGeom.degrees) xy = self.wcs.skyToPixel(raDec) raDec2 = self.wcs.pixelToSky(xy) self.assertAlmostEqual(raDec[0].asDegrees(), raDec2[0].asDegrees()) self.assertAlmostEqual(raDec[1].asDegrees(), raDec2[1].asDegrees())
def testIdentity(self): """Convert from ra, dec to col, row and back again""" raDec = afwCoord.makeCoord(afwCoord.ICRS, 244 * afwGeom.degrees, 20 * afwGeom.degrees) print 'testIdentity' print 'wcs:' for x in self.wcs.getFitsMetadata().toList(): print ' ', x print 'raDec:', raDec print type(self.wcs) rowCol = self.wcs.skyToPixel(raDec) print 'rowCol:', rowCol raDec2 = self.wcs.pixelToSky(rowCol) print 'raDec2:', raDec2 p1 = raDec.getPosition() p2 = raDec.getPosition() print 'p1,p2', p1,p2 self.assertAlmostEqual(p1[0], p2[0]) self.assertAlmostEqual(p1[1], p2[1])
def findWcsCoveringSkyTile(skyPixelization, skyTileId, imageRes): """Computes and returns a TAN WCS such that a 2D image with the given WCS and the following properties completely covers the sky-tile with the given pixel id: - NAXIS1/NAXIS2 >= imageRes - CRPIX1 = NAXIS1 / 2 + 0.5 - CRPIX2 = NAXIS2 / 2 + 0.5 """ if not isinstance(imageRes, (int, long)): raise TypeError("Image resolution must be an integer") if imageRes < 1: raise RuntimeError("Image resolution must be at least 1") crpix = afwGeom.Point2D(0.5 * (imageRes + 1), 0.5 * (imageRes + 1)) crval = geom.sphericalCoords(skyPixelization.getCenter(skyTileId)) crval = afwCoord.makeCoord(afwCoord.ICRS, crval[0] * afwGeom.degrees, crval[1] * afwGeom.degrees) skyTile = skyPixelization.getGeometry(skyTileId) # Start with a huge TAN image centered at the sky-tile center, # then shrink it using binary search to determine suitable # CD matrix coefficients scale = 1000.0 # deg/pixel, ridiculously large delta = 0.5 * scale frac = 0.01 # desired relative accuracy of CD matrix coeffs wcs = afwImage.makeWcs(crval, crpix, scale, 0.0, 0.0, scale) imagePoly = skypix.imageToPolygon(wcs, imageRes, imageRes) # Make sure the initial guess really is too large if not imagePoly.contains(skyTile): raise RuntimeError("Failed to construct image WCS covering sky-tile") # Search for a WCS with a tight fit to the sky-tile. Note that the # tightness of fit could be further improved by searching for a rotation # and not just a pixel scale. while delta >= frac * scale: tmp = scale - delta wcs = afwImage.makeWcs(crval, crpix, tmp, 0.0, 0.0, tmp) imagePoly = skypix.imageToPolygon(wcs, imageRes, imageRes) delta *= 0.5 if imagePoly.contains(skyTile): scale = tmp return afwImage.makeWcs(crval, crpix, scale, 0.0, 0.0, scale)
def findWcsCoveringSkyTile(skyPixelization, skyTileId, imageRes): """Computes and returns a TAN WCS such that a 2D image with the given WCS and the following properties completely covers the sky-tile with the given pixel id: - NAXIS1/NAXIS2 >= imageRes - CRPIX1 = NAXIS1 / 2 + 0.5 - CRPIX2 = NAXIS2 / 2 + 0.5 """ if not isinstance(imageRes, (int, long)): raise TypeError("Image resolution must be an integer") if imageRes < 1: raise RuntimeError("Image resolution must be at least 1") crpix = afwGeom.Point2D(0.5*(imageRes + 1), 0.5*(imageRes + 1)) crval = geom.sphericalCoords(skyPixelization.getCenter(skyTileId)) crval = afwCoord.makeCoord(afwCoord.ICRS, crval[0] * afwGeom.degrees, crval[1] * afwGeom.degrees) skyTile = skyPixelization.getGeometry(skyTileId) # Start with a huge TAN image centered at the sky-tile center, # then shrink it using binary search to determine suitable # CD matrix coefficients scale = 1000.0 # deg/pixel, ridiculously large delta = 0.5*scale frac = 0.01 # desired relative accuracy of CD matrix coeffs wcs = afwImage.makeWcs(crval, crpix, scale, 0.0, 0.0, scale) imagePoly = skypix.imageToPolygon(wcs, imageRes, imageRes) # Make sure the initial guess really is too large if not imagePoly.contains(skyTile): raise RuntimeError("Failed to construct image WCS covering sky-tile") # Search for a WCS with a tight fit to the sky-tile. Note that the # tightness of fit could be further improved by searching for a rotation # and not just a pixel scale. while delta >= frac * scale: tmp = scale - delta wcs = afwImage.makeWcs(crval, crpix, tmp, 0.0, 0.0, tmp) imagePoly = skypix.imageToPolygon(wcs, imageRes, imageRes) delta *= 0.5 if imagePoly.contains(skyTile): scale = tmp return afwImage.makeWcs(crval, crpix, scale, 0.0, 0.0, scale)
def std_raw(self, item, dataId): """ Added because there are no valid Wcs in fits headers Convert the raw DecoratedImage to an Exposure, set metadata and wcs. """ exp = exposureFromImage(item) md = exp.getMetadata() rawPath = self.map_raw(dataId).getLocations()[0] headerPath = re.sub(r'[\[](\d+)[\]]$', "[0]", rawPath) md0 = afwImage.readMetadata(headerPath) crval = afwCoord.makeCoord(afwCoord.ICRS, 0 * afwGeom.degrees, 0 * afwGeom.degrees) crpix = afwGeom.PointD(0, 0) wcs = afwImage.makeWcs(crval, crpix, 1, 0, 0, 1) exp.setWcs(wcs) exposureId = self._computeCcdExposureId(dataId) visitInfo = self.makeRawVisitInfo(md=md0, exposureId=exposureId) exp.getInfo().setVisitInfo(visitInfo) return self._standardizeExposure(self.exposures['raw'], exp, dataId, trimmed=True)
def testIdentity(self): """Convert from ra, dec to col, row and back again""" raDec = afwCoord.makeCoord(afwCoord.ICRS, 244 * afwGeom.degrees, 20 * afwGeom.degrees) if verbose: print 'testIdentity' print 'wcs:' for x in self.wcs.getFitsMetadata().toList(): print ' ', x print 'raDec:', raDec print type(self.wcs) rowCol = self.wcs.skyToPixel(raDec) raDec2 = self.wcs.pixelToSky(rowCol) if verbose: print 'rowCol:', rowCol print 'raDec2:', raDec2 p1 = raDec.getPosition() p2 = raDec.getPosition() if verbose: print 'p1,p2', p1,p2 self.assertAlmostEqual(p1[0], p2[0]) self.assertAlmostEqual(p1[1], p2[1])
def apply_cutout(self, src_img, metadata, ra, dec, width, height, qresults, cutout_type="arcsecond"): """Return an image centered on ra and dec (in degrees) with dimensions height and width (in arcseconds by default). Returns None if no image is found. This function assumes the entire image is valid. (no overscan, etc.) Sequence of events: - dataId is the image id for the butler - Use the results of the query to get an image and metadata from the butler. - Map ra, dec, width, and height to a box. - If a pixel cutout, trim the dimesions to fit in the source image and return. - and return the cutout. - Otherwise, the height and width are in arcseconds. - Determine approximate pixels per arcsecond in the image by calculating the length of line from the upper right corner of the image to the lower left corner in pixels and arcseconds. (This will fail at or very near the pole.) - Use that to define a box for the cutout. - Trim the box so it is entirely within the source image. Returns ------- afw_image the cutout image """ self._log.debug("getImage %f %f %f %f", ra, dec, width, height) img_w = src_img.getWidth() img_h = src_img.getHeight() self._log.debug("img_w=%d img_h=%d", img_w, img_h) wcs = lsst.afw.image.makeWcs(metadata, False) ra_dec = afw_coord.makeCoord(afw_coord.ICRS, ra * afw_geom.degrees, dec * afw_geom.degrees) xy_wcs = wcs.skyToPixel(ra_dec) x0, y0 = src_img.getX0(), src_img.getY0() xy_center_x = xy_wcs.getX() - x0 xy_center_y = xy_wcs.getY() - y0 self._log.info( "ra=%f dec=%f xy_wcs=(%f,%f) x0y0=(%f,%f) " "xy_center=(%f,%f)", ra, dec, xy_wcs.getX(), xy_wcs.getY(), x0, y0, xy_center_x, xy_center_y) if cutout_type == 'pixel': img = self._cutoutbox_pixels(src_img, xy_center_x, xy_center_y, width, height, wcs, self._log) return img # Determine approximate pixels per arcsec - find image corners in RA and Dec # and compare that distance with the number of pixels. ra_dec_ul = wcs.pixelToSky(afw_geom.Point2D(0, 0)) ra_dec_lr = wcs.pixelToSky(afw_geom.Point2D(img_w - 1, img_h - 1)) self._log.debug("ra_dec_ul 0=%f 1=%f", ra_dec_ul[0].asDegrees(), ra_dec_ul[1].asDegrees()) self._log.debug("ra_dec_lr 0=%f 1=%f", ra_dec_lr[0].asDegrees(), ra_dec_lr[1].asDegrees()) # length of a line from upper left (UL) to lower right (LR) dec_dist = ra_dec_ul[1].asArcseconds() - ra_dec_lr[1].asArcseconds() ra_lr = self._keep_within_180(ra_dec_ul[0].asDegrees(), ra_dec_lr[0].asDegrees()) ra_lr *= 3600.0 # convert degrees to arcseconds # Correct distance in RA for the declination cos_dec = math.cos(dec * afw_geom.degrees) ra_dist = cos_dec * (ra_dec_ul[0].asArcseconds() - ra_lr) ra_dec_dist = math.sqrt( math.pow(dec_dist, 2.0) + math.pow(ra_dist, 2.0)) self._log.debug("ra_dec_dist=%f", ra_dec_dist) pixel_dist = math.sqrt(math.pow(img_w, 2.0) + math.pow(img_h, 2.0)) pixel_per_arcsec = pixel_dist / ra_dec_dist self._log.debug("pixel_per_arcsec=%f", pixel_per_arcsec) # Need Upper Left corner and dimensions for Box2I pix_w = width * pixel_per_arcsec pix_h = height * pixel_per_arcsec self._log.info( "ra=%f dec=%f xy_wcs=(%f,%f) x0y0=(%f,%f) " "xyCenter=(%f,%f)", ra, dec, xy_wcs.getX(), xy_wcs.getY(), x0, y0, xy_center_x, xy_center_y) img = self._cutoutbox_pixels(src_img, xy_center_x, xy_center_y, pix_w, pix_h, wcs, self._log) return img
def setUp(self): width, height = 110, 301 self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height)) self.mi.set(0) sd = 3 # standard deviation of image self.mi.getVariance().set(sd*sd) self.mi.getMask().addMaskPlane("DETECTED") self.FWHM = 5 self.ksize = 31 # size of desired kernel sigma1 = 1.75 sigma2 = 2*sigma1 self.exposure = afwImage.makeExposure(self.mi) self.exposure.setPsf(measAlg.DoubleGaussianPsf(self.ksize, self.ksize, 1.5*sigma1, 1, 0.1)) crval = afwCoord.makeCoord(afwCoord.ICRS, 0.0*afwGeom.degrees, 0.0*afwGeom.degrees) wcs = afwImage.makeWcs(crval, afwGeom.PointD(0, 0), 1.0, 0, 0, 1.0) self.exposure.setWcs(wcs) # # Make a kernel with the exactly correct basis functions. Useful for debugging # basisKernelList = afwMath.KernelList() for sigma in (sigma1, sigma2): basisKernel = afwMath.AnalyticKernel(self.ksize, self.ksize, afwMath.GaussianFunction2D(sigma, sigma)) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImage /= np.sum(basisImage.getArray()) if sigma == sigma1: basisImage0 = basisImage else: basisImage -= basisImage0 basisKernelList.append(afwMath.FixedKernel(basisImage)) order = 1 # 1 => up to linear spFunc = afwMath.PolynomialFunction2D(order) exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) exactKernel.setSpatialParameters([[1.0, 0, 0], [0.0, 0.5*1e-2, 0.2e-2]]) rand = afwMath.Random() # make these tests repeatable by setting seed addNoise = True if addNoise: im = self.mi.getImage() afwMath.randomGaussianImage(im, rand) # N(0, 1) im *= sd # N(0, sd^2) del im xarr, yarr = [], [] for x, y in [(20, 20), (60, 20), (30, 35), (50, 50), (20, 90), (70, 160), (25, 265), (75, 275), (85, 30), (50, 120), (70, 80), (60, 210), (20, 210), ]: xarr.append(x) yarr.append(y) for x, y in zip(xarr, yarr): dx = rand.uniform() - 0.5 # random (centered) offsets dy = rand.uniform() - 0.5 k = exactKernel.getSpatialFunction(1)(x, y) # functional variation of Kernel ... b = (k*sigma1**2/((1 - k)*sigma2**2)) # ... converted double Gaussian's "b" #flux = 80000 - 20*x - 10*(y/float(height))**2 flux = 80000*(1 + 0.1*(rand.uniform() - 0.5)) I0 = flux*(1 + b)/(2*np.pi*(sigma1**2 + b*sigma2**2)) for iy in range(y - self.ksize//2, y + self.ksize//2 + 1): if iy < 0 or iy >= self.mi.getHeight(): continue for ix in range(x - self.ksize//2, x + self.ksize//2 + 1): if ix < 0 or ix >= self.mi.getWidth(): continue I = I0*psfVal(ix, iy, x + dx, y + dy, sigma1, sigma2, b) Isample = rand.poisson(I) if addNoise else I self.mi.getImage().set(ix, iy, self.mi.getImage().get(ix, iy) + Isample) self.mi.getVariance().set(ix, iy, self.mi.getVariance().get(ix, iy) + I) bbox = afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(width, height)) self.cellSet = afwMath.SpatialCellSet(bbox, 100) self.footprintSet = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(100), "DETECTED") self.catalog = SpatialModelPsfTestCase.measure(self.footprintSet, self.exposure) for source in self.catalog: try: cand = measAlg.makePsfCandidate(source, self.exposure) self.cellSet.insertCandidate(cand) except Exception, e: print e continue
# This version seems to get overwritten by fitscopy later on the # process; just make the correct output file in the first place sys.exit(1) print "# id,dbid,raJ2000,decJ2000,glat,glon,uDerived,gDerived,rDerived,iDerived,zDerived,yDerived,isStar,varClass,objClass,redshift,semiMajorBulge,semiMinorBulge,semiMajorDisk,semiMinorDisk,sedFilename,properMotionRa,properMotionDec,parallax,radialVelocity" for line in open(sys.argv[1]).readlines(): if not line.startswith("object"): continue obj, oid, ra, decl, rmag, sed, a, b, c, d, e, f, star, g, h = line.split() c = afwCoord.makeCoord(afwCoord.FK5, float(ra) * afwGeom.degrees, float(decl) * afwGeom.degrees) glat = c.toGalactic()[0].asDegrees() glon = c.toGalactic()[1].asDegrees() sedKey = sed.split("/")[-1] umag = float(rmag) + colors_vs_r[sedKey]["u"] gmag = float(rmag) + colors_vs_r[sedKey]["g"] imag = float(rmag) + colors_vs_r[sedKey]["i"] zmag = float(rmag) + colors_vs_r[sedKey]["z"] ymag = float(rmag) + colors_vs_r[sedKey]["y"] print ",".join(map(str, (oid, oid, ra, decl, glat, glon, umag, gmag, rmag, imag, zmag, ymag, 1, 0, 5, None, None, None, None, None, sed, 0., 0., 0., 0.)))
def localMakeCoord(coordSys, posDeg, equinox): """Make a coord, ignoring equinox if necessary """ if coordSys in (afwCoord.ICRS, afwCoord.GALACTIC): return afwCoord.makeCoord(coordSys, posDeg[0]*afwGeom.degrees, posDeg[1]*afwGeom.degrees) return afwCoord.makeCoord(coordSys, posDeg[0]*afwGeom.degrees, posDeg[1]*afwGeom.degrees, equinox)
ds9.ds9Cmd("mask transparency 80") # Skip the at zenith one if suffixI != "C": # Epoch of image obsDate = dafBase.DateTime(mjdI, dafBase.DateTime.MJD, dafBase.DateTime.TAI) epoch = obsDate.get(dafBase.DateTime.EPOCH) for match in matches: refObj = match.first #ra = 79.6892650466 #decl = -29.6666669861 ra = refObj.getCoord()[0].asDegrees() + 0.003 # Offset a bit decl = refObj.getCoord()[1].asDegrees() + 0.003 wcs = diffim.getWcs() center = afwCoord.makeCoord(afwCoord.FK5, ra*afwGeom.degrees, decl*afwGeom.degrees, epoch) xyc = wcs.skyToPixel(center) raoff = afwCoord.makeCoord(afwCoord.FK5, (ra+0.003)*afwGeom.degrees, decl*afwGeom.degrees, epoch) xydra = wcs.skyToPixel(raoff) decoff = afwCoord.makeCoord(afwCoord.FK5, ra*afwGeom.degrees, (decl+0.003)*afwGeom.degrees, epoch) xyddec = wcs.skyToPixel(decoff) cmd = "regions command {line %f %f %f %f # color=magenta width=3}" % (xyc[0], xyc[1], xydra[0], xydra[1]) # East ds9.ds9Cmd(cmd, silent=False) cmd = "regions command {line %f %f %f %f # color=yellow width=3}" % (xyc[0], xyc[1], xyddec[0], xyddec[1]) # North ds9.ds9Cmd(cmd, silent=False) centeraa = center.toTopocentric(lsst, obsDate) # az, alt azoff = afwCoord.TopocentricCoord((centeraa.getAzimuth().asDegrees() + 0.003)*afwGeom.degrees, centeraa.getAltitude().asDegrees()*afwGeom.degrees, epoch, lsst) altoff = afwCoord.TopocentricCoord(centeraa.getAzimuth().asDegrees()*afwGeom.degrees, (centeraa.getAltitude().asDegrees() + 0.003)*afwGeom.degrees, epoch, lsst)
def getImage(self, ra, dec, width, height, cutoutType="arcsecond"): '''Return an image centered on ra and dec (in degrees) with dimensions height and width (in arcseconds). Returns None if no image is found. This function assumes the entire image is valid. (no overscan, etc.) Sequence of events: - Use ra, dec, width, and height to find an image from the database. - Use the results of the query to get an image and metadata from the butler. - Map ra, dec, width, and height to a box. - If a pixel cutout, trim the dimesions to fit in the source image and return. - and return the cutout. - Otherwise, the height and width are inarcseconds. - Determine approximate pixels per arcsecond in the image by calculating the length of line from the upper right corner of the image to the lower left corner in pixels and arcseconds. (This will fail at or very near the pole.) - Use that to define a box for the cutout. - Trim the box so it is entirely within the source image. - Make and return the cutout. ''' self._log.debug("getImage %f %f %f %f", ra, dec, width, height) # Find the nearest image to ra and dec containing at least part of the box. qresult = self._findNearestImageContaining(ra, dec, width, height) img, butler = self._getImageButler(qresult) if img == None: # @todo html error handling see DM-1980 return None imgW = img.getWidth() imgH = img.getHeight() self._log.debug("imgW=%d imgH=%d", imgW, imgH) # Get the metadata for the source image. metadata = self._getMetadata(butler, qresult) wcs = lsst.afw.image.makeWcs(metadata, False) raDec = afwCoord.makeCoord(afwCoord.ICRS, ra * afwGeom.degrees, dec * afwGeom.degrees) xyWcs = wcs.skyToPixel(raDec) x0 = img.getX0() y0 = img.getY0() xyCenter = afwGeom.Point2D(xyWcs.getX() - x0, xyWcs.getY() - y0) if cutoutType == 'pixel': imgSub = _cutoutBoxPixels(img, xyCenter, width, height, self._log) return imgSub self._log.info("ra=%f dec=%f xyWcs=(%f,%f) x0y0=(%f,%f) xyCenter=(%f,%f)", ra, dec, xyWcs.getX(), xyWcs.getY(), x0, y0, xyCenter.getX(), xyCenter.getY()) # Determine approximate pixels per arcsec - find image corners in RA and Dec # and compare that distance with the number of pixels. raDecUL = wcs.pixelToSky(afwGeom.Point2D(0, 0)) raDecLR = wcs.pixelToSky(afwGeom.Point2D(imgW - 1, imgH - 1)) self._log.debug("raDecUL 0=%f 1=%f", raDecUL[0].asDegrees(), raDecUL[1].asDegrees()) self._log.debug("raDecLR 0=%f 1=%f", raDecLR[0].asDegrees(), raDecLR[1].asDegrees()) # length of a line from upper left (UL) to lower right (LR) decDist = raDecUL[1].asArcseconds() - raDecLR[1].asArcseconds() raLR = _keepWithin180(raDecUL[0].asDegrees(), raDecLR[0].asDegrees()) raLR *= 3600.0 # convert degrees to arcseconds #Correct distance in RA for the declination cosDec = math.cos(dec*afwGeom.degrees) raDist = cosDec * (raDecUL[0].asArcseconds() - raLR) raDecDist = math.sqrt(math.pow(decDist, 2.0) + math.pow(raDist, 2.0)) self._log.debug("raDecDist=%f", raDecDist) pixelDist = math.sqrt(math.pow(imgW, 2.0) + math.pow(imgH, 2.0)) pixelPerArcsec = pixelDist/raDecDist self._log.debug("pixelPerArcsec=%f", pixelPerArcsec) # Need Upper Left corner and dimensions for Box2I pixW = width*pixelPerArcsec pixH = height*pixelPerArcsec imgSub = _cutoutBoxPixels(img, xyCenter, pixW, pixH, self._log) return imgSub
def setUp(self): width, height = 110, 301 self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height)) self.mi.set(0) sd = 3 # standard deviation of image self.mi.getVariance().set(sd*sd) self.mi.getMask().addMaskPlane("DETECTED") self.FWHM = 5 self.ksize = 31 # size of desired kernel sigma1 = 1.75 sigma2 = 2*sigma1 self.exposure = afwImage.makeExposure(self.mi) self.exposure.setPsf(measAlg.DoubleGaussianPsf(self.ksize, self.ksize, 1.5*sigma1, 1, 0.1)) crval = afwCoord.makeCoord(afwCoord.ICRS, 0.0*afwGeom.degrees, 0.0*afwGeom.degrees) wcs = afwImage.makeWcs(crval, afwGeom.PointD(0, 0), 1.0, 0, 0, 1.0) self.exposure.setWcs(wcs) ccd = cameraGeom.Ccd(cameraGeom.Id(1)) ccd.addAmp(cameraGeom.Amp(cameraGeom.Id(0), afwGeom.BoxI(afwGeom.PointI(0,0), self.exposure.getDimensions()), afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(0,0)), afwGeom.BoxI(afwGeom.PointI(0,0), self.exposure.getDimensions()), cameraGeom.ElectronicParams(1.0, 100.0, 65535))) self.exposure.setDetector(ccd) self.exposure.getDetector().setDistortion(None) # # Make a kernel with the exactly correct basis functions. Useful for debugging # basisKernelList = afwMath.KernelList() for sigma in (sigma1, sigma2): basisKernel = afwMath.AnalyticKernel(self.ksize, self.ksize, afwMath.GaussianFunction2D(sigma, sigma)) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImage /= np.sum(basisImage.getArray()) if sigma == sigma1: basisImage0 = basisImage else: basisImage -= basisImage0 basisKernelList.append(afwMath.FixedKernel(basisImage)) order = 1 # 1 => up to linear spFunc = afwMath.PolynomialFunction2D(order) exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) exactKernel.setSpatialParameters([[1.0, 0, 0], [0.0, 0.5*1e-2, 0.2e-2]]) rand = afwMath.Random() # make these tests repeatable by setting seed addNoise = True if addNoise: im = self.mi.getImage() afwMath.randomGaussianImage(im, rand) # N(0, 1) im *= sd # N(0, sd^2) del im xarr, yarr = [], [] for x, y in [(20, 20), (60, 20), (30, 35), (50, 50), (20, 90), (70, 160), (25, 265), (75, 275), (85, 30), (50, 120), (70, 80), (60, 210), (20, 210), ]: xarr.append(x) yarr.append(y) for x, y in zip(xarr, yarr): dx = rand.uniform() - 0.5 # random (centered) offsets dy = rand.uniform() - 0.5 k = exactKernel.getSpatialFunction(1)(x, y) # functional variation of Kernel ... b = (k*sigma1**2/((1 - k)*sigma2**2)) # ... converted double Gaussian's "b" #flux = 80000 - 20*x - 10*(y/float(height))**2 flux = 80000*(1 + 0.1*(rand.uniform() - 0.5)) I0 = flux*(1 + b)/(2*np.pi*(sigma1**2 + b*sigma2**2)) for iy in range(y - self.ksize//2, y + self.ksize//2 + 1): if iy < 0 or iy >= self.mi.getHeight(): continue for ix in range(x - self.ksize//2, x + self.ksize//2 + 1): if ix < 0 or ix >= self.mi.getWidth(): continue I = I0*psfVal(ix, iy, x + dx, y + dy, sigma1, sigma2, b) Isample = rand.poisson(I) if addNoise else I self.mi.getImage().set(ix, iy, self.mi.getImage().get(ix, iy) + Isample) self.mi.getVariance().set(ix, iy, self.mi.getVariance().get(ix, iy) + I) # bbox = afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(width, height)) self.cellSet = afwMath.SpatialCellSet(bbox, 100) self.footprintSet = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(100), "DETECTED") self.catalog = SpatialModelPsfTestCase.measure(self.footprintSet, self.exposure) for source in self.catalog: try: cand = measAlg.makePsfCandidate(source, self.exposure) self.cellSet.insertCandidate(cand) except Exception, e: print e continue