def testTicket1761(self): """Ticket 1761 found that non-normalized inputs caused failures. """ c = afwCoord.Coord(afwGeom.Point3D(0,1,0)) dfltLong = 0.0 * afwGeom.radians norm = False c1 = afwCoord.Coord(afwGeom.Point3D(0.1, 0.1, 0.1), 2000.0, norm, dfltLong) c2 = afwCoord.Coord(afwGeom.Point3D(0.6, 0.6 ,0.6), 2000.0, norm, dfltLong) sep1 = c.angularSeparation(c1).asDegrees() sep2 = c.angularSeparation(c2).asDegrees() known1 = 45.286483672428574 known2 = 55.550098012046512 print("sep: ", sep1, sep2, known1, known2) # these weren't normalized, and should get the following *incorrect* answers self.assertAlmostEqual(sep1, known1) self.assertAlmostEqual(sep2, known2) ###################### # normalize and sep1, sep2 should both equal 54.7356 norm = True c1 = afwCoord.Coord(afwGeom.Point3D(0.1, 0.1, 0.1), 2000.0, norm, dfltLong) c2 = afwCoord.Coord(afwGeom.Point3D(0.6, 0.6 ,0.6), 2000.0, norm, dfltLong) sep1 = c.angularSeparation(c1).asDegrees() sep2 = c.angularSeparation(c2).asDegrees() known = 54.735610317245339 print("sep: ", sep1, sep2, known) # these weren't normalized, and should get the following *incorrect* answers self.assertAlmostEqual(sep1, known) self.assertAlmostEqual(sep2, known)
def _bbox_for_coords(wcs, center_coord, width, height, units): """Returns a Box2I object representing the bounding box in pixels of the target region. @wcs: WCS object for the target region. @center_coord: RA and Dec coordinate for the center of the target region. @width: Width of the target region with units indicated by 'units' below. @height: Height of the target region with units indicated by 'units' below. @units: Units for height and width. 'pixel' or 'arcsecond' """ if units == 'arcsecond': # center_coord center, RA and Dec with width and height in arcseconds width_half_a = afw_geom.Angle((width / 2.0), afw_geom.arcseconds) height_half_a = afw_geom.Angle((height / 2.0), afw_geom.arcseconds) min_ra = center_coord.getLongitude() - width_half_a min_dec = center_coord.getLatitude() - height_half_a max_ra = center_coord.getLongitude() + width_half_a max_dec = center_coord.getLatitude() + height_half_a ll_coord = afw_coord.Coord(min_ra, min_dec, center_coord.getEpoch()) ll_coord_pix = wcs.skyToPixel(ll_coord) ur_coord = afw_coord.Coord(max_ra, max_dec, center_coord.getEpoch()) ur_coord_pix = wcs.skyToPixel(ur_coord) p2i_min = afw_geom.Point2I(ll_coord_pix) p2i_max = afw_geom.Point2I(ur_coord_pix) bbox = afw_geom.Box2I(p2i_min, p2i_max) elif units == 'pixel': # center_coord center, RA and Dec with width and height in pixels ctr_coord_pix = wcs.skyToPixel(center_coord) min_ra_pix = int(ctr_coord_pix.getX() - width // 2) min_dec_pix = int(ctr_coord_pix.getY() - height // 2) p2i = afw_geom.Point2I(min_ra_pix, min_dec_pix) bbox = afw_geom.Box2I(p2i, afw_geom.Extent2I(width, height)) else: raise Exception("invalid units {}".format(units)) return bbox
def _transformAndCheck(self, measConf, schema, transformTask): """Check the results of applying transformTask to a SourceCatalog. @param[in] measConf Measurement plugin configuration. @param[in] schema Input catalog schema. @param[in] transformTask Instance of TransformTask to be applied. For internal use by this test case. """ # There should now be one transformation registered per measurement plugin. self.assertEqual(len(measConf.plugins.names), len(transformTask.transforms)) # Rather than do a real measurement, we use a dummy source catalog # containing a source at an arbitrary position. inCat = afwTable.SourceCatalog(schema) r = inCat.addNew() r.setCoord(afwCoord.Coord("00:00:00", "11:11:11")) r[PLUGIN_NAME] = 1.0 wcs, calib = Placeholder(), Placeholder() outCat = transformTask.run(inCat, wcs, calib) # Check that all sources have been transformed appropriately. for inSrc, outSrc in zip(inCat, outCat): self.assertEqual(outSrc[PLUGIN_NAME], inSrc[PLUGIN_NAME]) self.assertEqual(outSrc[PLUGIN_NAME + "_transform"], inSrc[PLUGIN_NAME] * -1.0) for field in transformTask.config.toDict()['copyFields']: self.assertEqual(outSrc.get(field), inSrc.get(field)) # Check that the wcs and calib objects were accessed once per transform. self.assertEqual(wcs.count, len(transformTask.transforms)) self.assertEqual(calib.count, len(transformTask.transforms))
def testNames(self): """Test the names of the Coords (Useful with Point2D form)""" # verify that each coordinate type can tell you what its components are called. radec1, known1 = afwCoord.Coord( self.ra, self.dec).getCoordNames(), ["RA", "Dec"] radec3, known3 = afwCoord.Fk5Coord( self.ra, self.dec).getCoordNames(), ["RA", "Dec"] radec4, known4 = afwCoord.IcrsCoord( self.ra, self.dec).getCoordNames(), ["RA", "Dec"] lb, known5 = afwCoord.GalacticCoord( self.ra, self.dec).getCoordNames(), ["L", "B"] lambet, known6 = afwCoord.EclipticCoord( self.ra, self.dec).getCoordNames(), ["Lambda", "Beta"] observatory = afwCoord.Observatory(0 * afwGeom.degrees, 0 * afwGeom.degrees, 0) altaz = afwCoord.TopocentricCoord(self.ra, self.dec, 2000.0, observatory).getCoordNames() known7 = ["Az", "Alt"] pairs = [ [radec1, known1], [radec3, known3], [radec4, known4], [lb, known5], [lambet, known6], [altaz, known7], ] for pair, known in (pairs): self.assertEqual(pair[0], known[0]) self.assertEqual(pair[1], known[1])
def makeMatches(self, refCat, srcCat, nSrc): for i in range(nSrc): refSrc = refCat.addNew() srcSrc = srcCat.addNew() coord = afwCoord.Coord(afwGeom.Point2D(*np.random.randn(2)), afwGeom.degrees) refSrc.set("g_flux", 10**(-0.4 * 18)) refSrc.set("r_flux", 10**(-0.4 * 18)) refSrc.set("resolved", False) refSrc.set("photometric", True) refSrc.setCoord(coord) srcSrc.setCoord(coord) srcSrc.set(srcSrc.getTable().getPsfFluxKey(), 10.) srcSrc.set(srcSrc.getTable().getPsfFluxErrKey(), 1.) for flag in self.sourceSelector.config.badFlags: srcSrc.set(flag, False) mat = afwTable.matchRaDec(refCat, srcCat, 1.0 * afwGeom.arcseconds, False) self.assertEqual(len(mat), nSrc) return mat
def test(self): schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("ccd", np.int32, doc="CCD number") schema.addField("visit", np.int32, doc="Visit number") schema.addField("goodpix", np.int32, doc="Number of good pixels") schema.addField("weight", float, doc="Weighting for this CCD") ccds = afwTable.ExposureCatalog(schema) wcs = afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), 1.0e-4, 0.0, 0.0, 1.0e-4) new = ccds.addNew() new.set("id", 0) new.set("bbox_min_x", 0) new.set("bbox_min_y", 0) new.set("bbox_max_x", 1024) new.set("bbox_max_y", 1024) # The following lines are critical for reproducing the bug, because # the code is reading a double starting at the 'ccd' (offset 24), and # it sees a zero (from the zero in 'ccd' and the leading zeros in 'visit'). new.set("ccd", 0) new.set("visit", 6789) new.set("goodpix", 987654321) new.set("weight", 1.0) new.setPsf(measAlg.SingleGaussianPsf(23, 23, 2.345)) new.setWcs(wcs) # In the presence of the bug, the following fails with # lsst::pex::exceptions::RuntimeError thrown in src/CoaddPsf.cc # with message: "Could not find a valid average position for CoaddPsf" measAlg.CoaddPsf(ccds, wcs)
def makeExposure(bbox, scale, psfFwhm, flux): """Make a fake exposure @param bbox: Bounding box for image (Box2I) @param scale: Pixel scale (Angle) @param psfFwhm: PSF FWHM (arcseconds) @param flux: PSF flux (ADU) @return Exposure, source center """ image = afwImage.ImageF(bbox) image.set(0) center = afwGeom.Box2D(bbox).getCenter() psfSigma = psfFwhm / SIGMA_TO_FWHM / scale.asArcseconds() psfWidth = 2 * int(4.0 * psfSigma) + 1 psf = afwDetection.GaussianPsf(psfWidth, psfWidth, psfSigma) psfImage = psf.computeImage(center).convertF() psfFlux = psfImage.getArray().sum() psfImage *= flux / psfFlux subImage = afwImage.ImageF(image, psfImage.getBBox(afwImage.PARENT), afwImage.PARENT) subImage += psfImage exp = afwImage.makeExposure(afwImage.makeMaskedImage(image)) exp.setPsf(psf) exp.getMaskedImage().getVariance().set(1.0) exp.getMaskedImage().getMask().set(0) exp.setWcs( afwImage.makeWcs( afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees), center, scale.asDegrees(), 0.0, 0.0, scale.asDegrees())) return exp, center
def test(self): schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("ccd", int, doc="CCD number") schema.addField("visit", long, doc="Visit number") schema.addField("goodpix", int, doc="Number of good pixels") schema.addField("weight", float, doc="Weighting for this CCD") ccds = afwTable.ExposureCatalog(schema) wcs = afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), 1.0e-4, 0.0, 0.0, 1.0e-4) new = ccds.addNew() new.set("id", 0) new.set("bbox.min", afwGeom.Point2I(0,0)) new.set("bbox.max", afwGeom.Point2I(1024,1024)) # The following lines are critical for reproducing the bug, because # the code is reading a double starting at the 'ccd' (offset 24), and # it sees a zero (from the zero in 'ccd' and the leading zeros in 'visit'). new.set("ccd", 0) new.set("visit", 6789) new.set("goodpix", 987654321) new.set("weight", 1.0) new.setPsf(measAlg.SingleGaussianPsf(23, 23, 2.345)) new.setWcs(wcs) # In the presence of the bug, the following fails with: # LsstCppException: 0: lsst::pex::exceptions::RuntimeErrorException thrown at src/CoaddPsf.cc:134 in lsst::afw::geom::Point2D lsst::meas::algorithms::{anonymous}::computeAveragePosition(const ExposureCatalog&, const lsst::afw::image::Wcs&, lsst::afw::table::Key<double>) # 0: Message: Could not find a valid average position for CoaddPsf measAlg.CoaddPsf(ccds, wcs)
def testValidPolygonPsf(self): """Test that we can use the validPolygon on exposures in the coadd psf""" print "ValidPolygonTest" # this is the coadd Wcs we want cd11 = 5.55555555e-05 cd12 = 0.0 cd21 = 0.0 cd22 = 5.55555555e-05 crval1 = 0.0 crval2 = 0.0 crpix = afwGeom.PointD(1000, 1000) crval = afwCoord.Coord(afwGeom.Point2D(crval1, crval2)) wcsref = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("weight", type="D", doc="Coadd weight") mycatalog = afwTable.ExposureCatalog(schema) # Each of the 9 has its peculiar Psf, Wcs, weight, bounding box, and valid region. for i in range(1, 10, 1): record = mycatalog.getTable().makeRecord() psf = measAlg.DoubleGaussianPsf(100, 100, i, 1.00, 0.0) record.setPsf(psf) crpix = afwGeom.PointD(1000 - 10.0 * i, 1000.0 - 10.0 * i) wcs = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) record.setWcs(wcs) record['weight'] = 1.0 * (i + 1) record['id'] = i bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000)) record.setBBox(bbox) validPolygon_bbox = afwGeom.Box2D( afwGeom.Point2D(0, 0), afwGeom.Extent2D(i * 100, i * 100)) validPolygon = Polygon(validPolygon_bbox) record.setValidPolygon(validPolygon) mycatalog.append(record) # Create the coaddpsf and check at three different points to ensure that the validPolygon is working mypsf = measAlg.CoaddPsf(mycatalog, wcsref, 'weight') m1coadd, m2coadd = getCoaddSecondMoments(mypsf, afwGeom.Point2D(50, 50), True) m1, m2 = getPsfSecondMoments(mypsf, afwGeom.Point2D(50, 50)) self.assertTrue(testRelDiff(m1, m1coadd, .01)) self.assertTrue(testRelDiff(m2, m2coadd, .01)) m1coadd, m2coadd = getCoaddSecondMoments(mypsf, afwGeom.Point2D(500, 500), True) m1, m2 = getPsfSecondMoments(mypsf, afwGeom.Point2D(500, 500)) self.assertTrue(testRelDiff(m1, m1coadd, .01)) self.assertTrue(testRelDiff(m2, m2coadd, .01)) m1coadd, m2coadd = getCoaddSecondMoments(mypsf, afwGeom.Point2D(850, 850), True) m1, m2 = getPsfSecondMoments(mypsf, afwGeom.Point2D(850, 850)) self.assertTrue(testRelDiff(m1, m1coadd, .01)) self.assertTrue(testRelDiff(m2, m2coadd, .01))
def makeWcs(pixScale, nx, ny, rotation=0., raCen=180.0, decCen=0.0): """Create a TAN WCS with pixScale/nx/ny, plus rotation (degrees) and RA/Dec center (degrees). """ #Hardcoding TAN projection since this application is for focal plane size at most wcsFactory = WcsFactory(pixScale, 'TAN', rotation=rotation*afwGeom.radians) crpix_x = float(nx-1)/2. crpix_y = float(ny-1)/2. crval = afwCoord.Coord(afwGeom.Angle(raCen*afwGeom.degrees), afwGeom.Angle(decCen*afwGeom.degrees)) return wcsFactory.makeWcs(afwGeom.Point2D(crpix_x, crpix_y), crval)
def testCreate(self): """Check that we can create a CoaddPsf with 9 elements""" print "CreatePsfTest" # this is the coadd Wcs we want cd11 = 5.55555555e-05 cd12 = 0.0 cd21 = 0.0 cd22 = 5.55555555e-05 crval1 = 0.0 crval2 = 0.0 crpix = afwGeom.PointD(1000, 1000) crval = afwCoord.Coord(afwGeom.Point2D(crval1, crval2)) wcsref = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) #also test that the weight field name is correctly observed schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("customweightname", type="D", doc="Coadd weight") mycatalog = afwTable.ExposureCatalog(schema) # Each of the 9 has its peculiar Psf, Wcs, weight, and bounding box. for i in range(1, 10, 1): record = mycatalog.getTable().makeRecord() psf = measAlg.DoubleGaussianPsf(100, 100, i, 1.00, 0.0) record.setPsf(psf) crpix = afwGeom.PointD(i * 1000.0, i * 1000.0) wcs = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) record.setWcs(wcs) record['customweightname'] = 1.0 * (i + 1) record['id'] = i bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(i * 1000, i * 1000)) record.setBBox(bbox) mycatalog.append(record) #create the coaddpsf mypsf = measAlg.CoaddPsf(mycatalog, wcsref, 'customweightname') # check to be sure that we got the right number of components, in the right order self.assertTrue(mypsf.getComponentCount() == 9) for i in range(1, 10, 1): wcs = mypsf.getWcs(i - 1) psf = mypsf.getPsf(i - 1) bbox = mypsf.getBBox(i - 1) weight = mypsf.getWeight(i - 1) id = mypsf.getId(i - 1) self.assertTrue(i == id) self.assertTrue(weight == 1.0 * (i + 1)) self.assertTrue(bbox.getBeginX() == 0) self.assertTrue(bbox.getBeginY() == 0) self.assertTrue(bbox.getEndX() == 1000 * i) self.assertTrue(bbox.getEndY() == 1000 * i) self.assertTrue(wcs.getPixelOrigin().getX() == (1000.0 * i)) self.assertTrue(wcs.getPixelOrigin().getY() == (1000.0 * i)) m0, xbar, ybar, mxx, myy, x0, y0 = getPsfMoments( psf, afwGeom.Point2D(0, 0)) self.assertTrue(testRelDiff(i * i, mxx, .01)) self.assertTrue(testRelDiff(i * i, myy, .01))
def testOffsetTangentPlane(self): """Testing of offsets on a tangent plane (good for small angles)""" c0 = afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees) for dRa in (0.0123, 0.0, -0.0321): for dDec in (0.0543, 0.0, -0.0987): c1 = afwCoord.Coord(dRa*afwGeom.degrees, dDec*afwGeom.degrees) offset = c0.getTangentPlaneOffset(c1) # This more-or-less works for small angles because c0 is 0,0 expE = math.degrees(math.tan(math.radians(dRa))) expN = math.degrees(math.tan(math.radians(dDec))) print("TP: ", dRa, dDec, offset[0].asDegrees(), offset[1].asDegrees(), expE, expN) self.assertAlmostEqual(offset[0].asDegrees(), expE) self.assertAlmostEqual(offset[1].asDegrees(), expN)
def getRandomRaDec(nRand, minRa, maxRa, minDec, maxDec, rad=None): """ Randomly select Ra,Dec pairs from the input Ra,Dec range """ if minRa > maxRa or minDec > maxDec: raise Exception('Please provide appropriate Ra,Dec range !') if rad is None: raArr = uniform(low=minRa, high=maxRa, size=nRand) decArr = uniform(low=minDec, high=maxDec, size=nRand) return zip(raArr, decArr) else: import lsst.afw.coord as afwCoord import lsst.afw.geom as afwGeom minSep = float(rad) raArr = [] decArr = [] numTry = 0 while len(raArr) < nRand: if numTry == 0: raArr.append(uniform(low=minRa, high=maxRa)) decArr.append(uniform(low=minDec, high=maxDec)) numTry += 1 else: raTry = uniform(low=minRa, high=maxRa) decTry = uniform(low=minDec, high=maxDec) coordTry = afwCoord.Coord(afwGeom.Point2D(raTry, decTry)) nExist = len(raArr) sepGood = True for ii in range(nExist): coordTest = afwCoord.Coord(afwGeom.Point2D(raArr[ii], decArr[ii])) sep = coordTry.angularSeparation(coordTest).asArcseconds() if sep <= minSep: print "## BAD ONE %8d : %8d -- %f10 <= %f10 !!" % (len(raArr), ii, sep, minSep) sepGood = False break if sepGood: raArr.append(raTry) decArr.append(decTry) return zip(raArr, decArr)
def testTransform(self): dims = afwGeom.Extent2I(512, 512) bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), dims) radius = 5 offset = afwGeom.Extent2D(123, 456) crval = afwCoord.Coord(0 * afwGeom.degrees, 0 * afwGeom.degrees) crpix = afwGeom.Point2D(0, 0) cdMatrix = [1.0e-5, 0.0, 0.0, 1.0e-5] source = afwImage.makeWcs(crval, crpix, *cdMatrix) target = afwImage.makeWcs(crval, crpix + offset, *cdMatrix) sourceSpanSet = afwGeom.SpanSet.fromShape(radius, afwGeom.Stencil.CIRCLE) sourceSpanSet = sourceSpanSet.shiftedBy(12, 34) fpSource = afwDetect.Footprint(sourceSpanSet, bbox) fpTarget = fpSource.transform(source, target, bbox) self.assertEqual(len(fpSource.getSpans()), len(fpTarget.getSpans())) self.assertEqual(fpSource.getArea(), fpTarget.getArea()) imSource = afwImage.ImageU(dims) fpSource.spans.setImage(imSource, 1) imTarget = afwImage.ImageU(dims) fpTarget.spans.setImage(imTarget, 1) subSource = imSource.Factory(imSource, fpSource.getBBox()) subTarget = imTarget.Factory(imTarget, fpTarget.getBBox()) self.assertTrue(np.all(subSource.getArray() == subTarget.getArray())) # make a bbox smaller than the target footprint bbox2 = afwGeom.Box2I(fpTarget.getBBox()) bbox2.grow(-1) fpTarget2 = fpSource.transform(source, target, bbox2) # this one clips fpTarget3 = fpSource.transform(source, target, bbox2, False) # this one doesn't self.assertTrue(bbox2.contains(fpTarget2.getBBox())) self.assertFalse(bbox2.contains(fpTarget3.getBBox())) self.assertNotEqual(fpTarget.getArea(), fpTarget2.getArea()) self.assertEqual(fpTarget.getArea(), fpTarget3.getArea()) # Test that peakCatalogs get Transformed correctly truthList = [(x, y, 10) for x, y in zip(range(-2, 2), range(-1, 3))] for value in truthList: fpSource.addPeak(*value) scaleFactor = 2 linTrans = afwGeom.LinearTransform( np.matrix([[scaleFactor, 0], [0, scaleFactor]], dtype=float)) linTransFootprint = fpSource.transform(linTrans, fpSource.getBBox(), False) for peak, truth in zip(linTransFootprint.peaks, truthList): # Multiplied by two because that is the linear transform scaling # factor self.assertEqual(peak.getIx(), truth[0] * scaleFactor) self.assertEqual(peak.getIy(), truth[1] * scaleFactor)
def validate(xs, ys, mapper, wcs): dists = [] for i in range(len(xs)): tuple1 = mapper.xyToRaDec(xs[i], ys[i]) coord1 = afwCoord.Coord(afwGeom.Point2D(tuple1[0], tuple1[1]), afwGeom.radians) coord2 = wcs.pixelToSky(xs[i], ys[i]) dist = coord1.angularSeparation(coord2).asArcseconds() dists.append(dist) print(np.mean(dists), np.std(dists))
def setUp(self): ra = 10.0 * afwGeom.degrees dec = 1.0 * afwGeom.degrees epoch = 2000.0 self.data = [ afwCoord.Coord(ra, dec, epoch), afwCoord.Fk5Coord(ra, dec, epoch), afwCoord.IcrsCoord(ra, dec), afwCoord.GalacticCoord(ra, dec), afwCoord.EclipticCoord(ra, dec), # TopocentricCoord is not currently picklable ]
def testSelectFluxMag0(self): """Test SelectFluxMag0""" config = SelectSdssFluxMag0Task.ConfigClass() config.database = "test_select_sdss_images" task = SelectSdssFluxMag0Task(config=config) run = 4192 filter = 'i' dataId = {'run': run, "filter": filter} coordList = [ afwCoord.Coord(5.62839 * afwGeom.radians, -5.66359e-05 * afwGeom.radians), afwCoord.Coord(5.62444 * afwGeom.radians, -5.66359e-05 * afwGeom.radians), afwCoord.Coord(5.62444 * afwGeom.radians, 0.00371974 * afwGeom.radians), afwCoord.Coord(5.62839 * afwGeom.radians, 0.00371974 * afwGeom.radians) ] fmInfoStruct = task.run(dataId, coordList) fmInfoList = fmInfoStruct.fluxMagInfoList self.assertEqual(2, len(fmInfoList))
def testMaskedImage(self): scale = (1.0 * afwGeom.arcseconds).asDegrees() wcs = afwImage.makeWcs( afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), scale, 0.0, 0.0, scale) for MaskedImage in ( afwImage.MaskedImageF, afwImage.MaskedImageD, ): image = self.createMaskedImage(MaskedImage) self.checkImages(image) exposure = afwImage.makeExposure(image, wcs) self.checkExposures(exposure)
def setUp(self): # We create an image that has a ramp (unique values for each pixel), # with a single high pixel that allows for centering self.width, self.height = 50, 50 self.xcen, self.ycen = self.width // 2, self.height // 2 self.image = afwImage.ImageF(afwGeom.ExtentI(self.width, self.height)) for y in range(self.height): for x in range(self.width): self.image.set(x, y, self.width * y + x) self.image.set(self.xcen, self.ycen, 1234567.89) self.exp = afwImage.makeExposure(afwImage.makeMaskedImage(self.image)) self.exp.getMaskedImage().getVariance().set(1.0) scale = 0.2 / 3600 wcs = afwImage.makeWcs( afwCoord.Coord(0 * afwGeom.degrees, 0 * afwGeom.degrees), afwGeom.Point2D(self.xcen, self.ycen), scale, 0, 0, scale) self.exp.setWcs(wcs) if display: frame = 1 ds9.mtv(self.exp, frame=frame, title="Single pixel") # We will use a GaussianCentroid to tweak the center (it should not, for forced measurement) # and a NaiveFlux to measure the single pixel. We'll start offset from the high pixel, # so that a forced measurement should yield a flux of zero, while a measurement that was allowed to # center should yield a flux of unity. # Note that previous versions used NaiveCentroid, which was so nonrobust that it failed to get # right answer when the input value was round-tripped through Wcs and modified by ~1E-8. gaussianCentroid = measAlg.GaussianCentroidControl() naiveFlux = measAlg.NaiveFluxControl() naiveFlux.radius = 0.5 self.x, self.y = self.xcen - 1, self.ycen - 1 self.foot = afwDetection.Footprint(afwGeom.Point2I(self.x, self.y), 2) self.foot.addPeak(self.x, self.y, float("NaN")) schema = afwTable.SourceTable.makeMinimalSchema() msb = measAlg.MeasureSourcesBuilder() msb.addAlgorithm(naiveFlux) msb.setCentroider(gaussianCentroid) self.measurer = msb.build(schema) self.table = afwTable.SourceTable.make(schema) self.table.defineCentroid("centroid.gaussian") schemaF = afwTable.SourceTable.makeMinimalSchema() msbF = measAlg.MeasureSourcesBuilder("", True) msbF.addAlgorithm(naiveFlux) msbF.setCentroider(gaussianCentroid) self.measurerF = msbF.build(schemaF) self.tableF = afwTable.SourceTable.make(schemaF) self.tableF.defineCentroid("centroid.gaussian")
def setUp(self): self.cd11 = 5.55555555e-05 self.cd12 = 0.0 self.cd21 = 0.0 self.cd22 = 5.55555555e-05 self.crval1 = 0.0 self.crval2 = 0.0 self.crpix = afwGeom.PointD(1000, 1000) self.crval = afwCoord.Coord(afwGeom.Point2D(self.crval1, self.crval2)) self.wcsref = afwImage.makeWcs(self.crval, self.crpix, self.cd11, self.cd12, self.cd21, self.cd22) schema = afwTable.ExposureTable.makeMinimalSchema() self.weightKey = schema.addField("weight", type="D", doc="Coadd weight") self.mycatalog = afwTable.ExposureCatalog(schema)
def makeGalaxy(width, height, flux, a, b, theta, dx=0.0, dy=0.0, xy0=None, xcen=None, ycen=None): """Make a fake galaxy image""" gal = afwImage.ImageF(width, height) if xcen is None: xcen = 0.5*width + dx if ycen is None: ycen = 0.5*height + dy I0 = flux/(2*math.pi*a*b) if xy0 is not None: gal.setXY0(xy0) c, s = math.cos(math.radians(theta)), math.sin(math.radians(theta)) I, Iuu, Ivv = 0.0, 0.0, 0.0 for y in range(height): for x in range(width): dx, dy = x + gal.getX0() - xcen, y + gal.getY0() - ycen if math.hypot(dx, dy) < 10.5: nsample = float(5) subZ = np.linspace(-0.5*(1 - 1/nsample), 0.5*(1 - 1/nsample), nsample) else: nsample = 1 subZ = [0.0] val = 0 for sx in subZ: for sy in subZ: u = c*(dx + sx) + s*(dy + sy) v = -s*(dx + sx) + c*(dy + sy) val += I0*math.exp(-0.5*((u/a)**2 + (v/b)**2)) if val < 0: val = 0 gal.set(x, y, val/nsample**2) I += val Iuu += val*u**2 Ivv += val*v**2 Iuu /= I; Ivv /= I exp = afwImage.makeExposure(afwImage.makeMaskedImage(gal)) exp.getMaskedImage().getVariance().setXY0(exp.getXY0()) # workaround #2577 exp.getMaskedImage().getVariance().set(1.0) exp.setWcs(afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), 1.0e-4, 0.0, 0.0, 1.0e-4)) return exp
def makeExposure(bbox, scale, psfFwhm, flux): """Make a fake exposure Parameters ---------- bbox : `lsst.afw.geom.Box2I` Bounding box for image. scale : `lsst.afw.geom.Angle` Pixel scale. psfFwhm : `float` PSF FWHM (arcseconds) flux : `float` PSF flux (ADU) Returns ------- exposure : `lsst.afw.image.ExposureF` Fake exposure. center : `lsst.afw.geom.Point2D` Position of fake source. """ image = afwImage.ImageF(bbox) image.set(0) center = afwGeom.Box2D(bbox).getCenter() psfSigma = psfFwhm / SIGMA_TO_FWHM / scale.asArcseconds() psfWidth = 2 * int(4.0 * psfSigma) + 1 psf = afwDetection.GaussianPsf(psfWidth, psfWidth, psfSigma) psfImage = psf.computeImage(center).convertF() psfFlux = psfImage.getArray().sum() psfImage *= flux / psfFlux subImage = afwImage.ImageF(image, psfImage.getBBox(afwImage.PARENT), afwImage.PARENT) subImage += psfImage exp = afwImage.makeExposure(afwImage.makeMaskedImage(image)) exp.setPsf(psf) exp.getMaskedImage().getVariance().set(1.0) exp.getMaskedImage().getMask().set(0) exp.setWcs( afwImage.makeWcs( afwCoord.Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees), center, scale.asDegrees(), 0.0, 0.0, scale.asDegrees())) return exp, center
def testDefaultSize(self): """Test of both default size and specified size""" print "DefaultSizeTest" sigma0 = 5 # set the peak of the outer guassian to 0 so this is really a single gaussian. psf = measAlg.DoubleGaussianPsf(60, 60, 1.5 * sigma0, 1, 0.0) if False and display: im = psf.computeImage(afwGeom.PointD(xwid / 2, ywid / 2)) ds9.mtv(im, title="N(%g) psf" % sigma0, frame=0) # this is the coadd Wcs we want cd11 = 5.55555555e-05 cd12 = 0.0 cd21 = 0.0 cd22 = 5.55555555e-05 crval1 = 0.0 crval2 = 0.0 crpix = afwGeom.PointD(1000, 1000) crval = afwCoord.Coord(afwGeom.Point2D(crval1, crval2)) wcsref = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) # Now make the catalog schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("weight", type="D", doc="Coadd weight") mycatalog = afwTable.ExposureCatalog(schema) record = mycatalog.getTable().makeRecord() psf = measAlg.DoubleGaussianPsf(100, 100, 10.0, 1.00, 1.0) record.setPsf(psf) wcs = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) record.setWcs(wcs) record['weight'] = 1.0 record['id'] = 1 bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(2000, 2000)) record.setBBox(bbox) mycatalog.append(record) mypsf = measAlg.CoaddPsf(mycatalog, wcsref) #, 'weight') m1coadd, m2coadd = getCoaddSecondMoments(mypsf, afwGeom.Point2D(0, 0)) m1, m2 = getPsfSecondMoments(mypsf, afwGeom.Point2D(1000, 1000)) self.assertTrue(testRelDiff(m1, m1coadd, .01)) self.assertTrue(testRelDiff(m2, m2coadd, .01))
def testFractionalPixel(self): """Check that we can create a CoaddPsf with 10 elements""" print "FractionalPixelTest" # this is the coadd Wcs we want cd11 = 5.55555555e-05 cd12 = 0.0 cd21 = 0.0 cd22 = 5.55555555e-05 crval1 = 0.0 crval2 = 0.0 crpix = afwGeom.PointD(1000, 1000) crval = afwCoord.Coord(afwGeom.Point2D(crval1, crval2)) wcsref = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) cd21 = 5.55555555e-05 cd12 = 5.55555555e-05 cd11 = 0.0 cd22 = 0.0 wcs = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("weight", type="D", doc="Coadd weight") mycatalog = afwTable.ExposureCatalog(schema) # make a single record with an oblong Psf record = mycatalog.getTable().makeRecord() psf = makeBiaxialGaussianPsf(100, 100, 6.0, 6.0, 0.0) record.setPsf(psf) record.setWcs(wcs) record['weight'] = 1.0 record['id'] = 1 bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(2000, 2000)) record.setBBox(bbox) mycatalog.append(record) mypsf = measAlg.CoaddPsf(mycatalog, wcsref) img = psf.computeImage(afwGeom.PointD(0.25, 0.75)) img = psf.computeImage(afwGeom.PointD(0.25, 0.75)) img = psf.computeImage(afwGeom.PointD(1000, 1000)) m0, xbar, ybar, mxx, myy, x0, y0 = getPsfMoments( psf, afwGeom.Point2D(0.25, 0.75)) cm0, cxbar, cybar, cmxx, cmyy, cx0, cy0 = getPsfMoments( mypsf, afwGeom.Point2D(0.25, 0.75)) self.assertTrue(testRelDiff(x0 + xbar, cx0 + cxbar, .01)) self.assertTrue(testRelDiff(y0 + ybar, cy0 + cybar, .01))
def testValidPolygonPsf(self): """Demonstrate that we can use the validPolygon on Exposures in the CoaddPsf""" cd11, cd12, cd21, cd22 = 5.55555555e-05, 0.0, 0.0, 5.55555555e-05 crval1, crval2 = 0.0, 0.0 crpix = afwGeom.PointD(1000, 1000) crval = afwCoord.Coord(afwGeom.Point2D(crval1, crval2)) wcsref = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("weight", type="D", doc="Coadd weight") mycatalog = afwTable.ExposureCatalog(schema) # Create 9 separate records, each with its own peculiar Psf, Wcs, # weight, bounding box, and valid region. for i in range(1, 10): record = mycatalog.getTable().makeRecord() record.setPsf(measAlg.DoubleGaussianPsf(100, 100, i, 1.00, 0.0)) crpix = afwGeom.PointD(1000 - 10.0 * i, 1000.0 - 10.0 * i) wcs = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) record.setWcs(wcs) record['weight'] = 1.0 * (i + 1) record['id'] = i record.setBBox( afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1000, 1000))) validPolygon = Polygon( afwGeom.Box2D(afwGeom.Point2D(0, 0), afwGeom.Extent2D(i * 100, i * 100))) record.setValidPolygon(validPolygon) mycatalog.append(record) # Create the CoaddPsf and check at three different points to ensure that the validPolygon is working mypsf = measAlg.CoaddPsf(mycatalog, wcsref, 'weight') for position in [ afwGeom.Point2D(50, 50), afwGeom.Point2D(500, 500), afwGeom.Point2D(850, 850) ]: m1coadd, m2coadd = getCoaddSecondMoments(mypsf, position, True) m1, m2 = getPsfSecondMoments(mypsf, position) self.assertAlmostEqual(m1, m1coadd, delta=0.01) self.assertAlmostEqual(m2, m2coadd, delta=0.01)
def testGoodPix(self): """Demonstrate that we can goodPix information in the CoaddPsf""" cd11, cd12, cd21, cd22 = 5.55555555e-05, 0.0, 0.0, 5.55555555e-05 crval1, crval2 = 0.0, 0.0 bboxSize = afwGeom.Extent2I(2000, 2000) crpix = afwGeom.PointD(bboxSize / 2.0) crval = afwCoord.Coord(afwGeom.Point2D(crval1, crval2)) wcsref = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) schema = afwTable.ExposureTable.makeMinimalSchema() schema.addField("weight", type="D", doc="Coadd weight") schema.addField("goodpix", type="I", doc="Number of good pixels") mycatalog = afwTable.ExposureCatalog(schema) # Create several records, each with its own peculiar center and numGoodPixels. # Each PSF has the same shape and size, and the position offsets are small # relative to the FWHM, in order to make it easy to predict the resulting # weighted mean position. xwsum = 0 ywsum = 0 wsum = 0 for i, (xOff, yOff, numGoodPix) in enumerate(( (30.0, -20.0, 25), (32.0, -21.0, 10), (28.0, -19.0, 30), )): xwsum -= xOff * numGoodPix ywsum -= yOff * numGoodPix wsum += numGoodPix record = mycatalog.getTable().makeRecord() record.setPsf(measAlg.DoubleGaussianPsf(25, 25, 10, 1.00, 0.0)) offPix = crpix + afwGeom.Extent2D(xOff, yOff) wcs = afwImage.makeWcs(crval, offPix, cd11, cd12, cd21, cd22) record.setWcs(wcs) record['weight'] = 1.0 record['id'] = i record['goodpix'] = numGoodPix record.setBBox(afwGeom.Box2I(afwGeom.Point2I(0, 0), bboxSize)) mycatalog.append(record) mypsf = measAlg.CoaddPsf(mycatalog, wcsref, 'weight') predPos = afwGeom.Point2D(xwsum / wsum, ywsum / wsum) self.assertPairsNearlyEqual(predPos, mypsf.getAveragePosition())
def setUp(self): # We create an image that has a ramp (unique values for each pixel), # with a single high pixel that allows for centering self.width, self.height = 50, 50 self.xcen, self.ycen = self.width // 2, self.height // 2 self.image = afwImage.ImageF(afwGeom.ExtentI(self.width, self.height)) for y in range(self.height): for x in range(self.width): self.image.set(x, y, self.width * y + x) self.image.set(self.xcen, self.ycen, 1234567.89) self.exp = afwImage.makeExposure(afwImage.makeMaskedImage(self.image)) self.exp.getMaskedImage().getVariance().set(1.0) scale = 0.2 / 3600 wcs = afwImage.makeWcs( afwCoord.Coord(0 * afwGeom.degrees, 0 * afwGeom.degrees), afwGeom.Point2D(self.xcen, self.ycen), scale, 0, 0, scale) self.exp.setWcs(wcs) if display: frame = 1 ds9.mtv(self.exp, frame=frame, title="Single pixel") # We will use a NaiveCentroid (peak over 3x3) to tweak the center (it should not, for forced # measurement) and a NaiveFlux to measure the single pixel. We'll start offset from the high pixel, # so that a forced measurement should yield a flux of zero, while a measurement that was allowed to # center should yield a flux of unity. naiveCentroid = measAlg.NaiveCentroidControl() naiveFlux = measAlg.NaiveFluxControl() naiveFlux.radius = 0.5 self.x, self.y = self.xcen - 1, self.ycen - 1 self.foot = afwDetection.Footprint(afwGeom.Point2I(self.x, self.y), 2) peak = afwDetection.Peak(self.x, self.y) self.foot.getPeaks().push_back(peak) schema = afwTable.SourceTable.makeMinimalSchema() msb = measAlg.MeasureSourcesBuilder() msb.addAlgorithm(naiveFlux) msb.setCentroider(naiveCentroid) self.measurer = msb.build(schema) self.table = afwTable.SourceTable.make(schema) self.table.defineCentroid("centroid.naive")
def _stiched_image_cutout(_request, units): """Get a stitched together deepCoadd image from /lsst/releaseW13EP deepCoadd_skyMap """ source = _request.args.get("source", None) if not source: # Use a default source = current_app.config["DAX_IMG_DATASOURCE"]+"coadd/" # Be safe and encode source to utf8, just in case source = source.encode('utf8') log.debug("Using filesystem source: " + source) map_type = "deepCoadd_skyMap" ra = _request.args.get('ra') dec = _request.args.get('dec') filter = _request.args.get('filter') width = _request.args.get('width') height = _request.args.get('height') # check inputs - Many valid filter names are unknown and can't be checked. try: ra, dec = _assert_ra_dec(ra, dec) try: width = float(width) height = float(height) except ValueError: msg = "INVALID_INPUT width={} height={}".format(width, height) raise ValueError(msg) except ValueError as e: return _error(ValueError.__name__, e.args[0], BAD_REQUEST) log.info("skymap cutout pixel ra={} dec={} filter={} width={} height={}".format( ra, dec, filter, width, height)) # fetch the image here ra_angle = afw_geom.Angle(ra, afw_geom.degrees) dec_angle = afw_geom.Angle(dec, afw_geom.degrees) center_coord = afw_coord.Coord(ra_angle, dec_angle, 2000.0) try: expo = getSkyMap(center_coord, int(width), int(height), filter, units, source, map_type) except RuntimeError as e: return _error("RuntimeError", e.message, INTERNAL_SERVER_ERROR) if expo is None: return _image_not_found() return _file_response(expo, "cutout.fits")
def testValidClipboard(self): dataPolicy1 = pexPolicy.Policy() dataPolicy1.add("inputKey", "sourceSet0") dataPolicy1.add("outputKey", "diaSourceSet0") dataPolicy2 = pexPolicy.Policy() dataPolicy2.add("inputKey", "sourceSet1") dataPolicy2.add("outputKey", "diaSourceSet1") stagePolicy = pexPolicy.Policy() stagePolicy.add("data", dataPolicy1) stagePolicy.add("data", dataPolicy2) stagePolicy.add("ccdWcsKey", "ccdWcs") stagePolicy.add("ampBBoxKey", "ampBBox") sourceSet = afwDet.SourceSet() for i in xrange(5): sourceSet.append(afwDet.Source()) point = afwGeom.Point2D(0.0, 0.0) wcs = afwImage.makeWcs(afwCoord.Coord(point, afwGeom.degrees), point, 1., 0., 0., 1.) ampBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(1, 1)) tester = SimpleStageTester( measPipe.SourceToDiaSourceStage(stagePolicy)) clipboard = pexClipboard.Clipboard() clipboard.put(dataPolicy1.get("inputKey"), sourceSet) clipboard.put(dataPolicy2.get("inputKey"), sourceSet) clipboard.put(stagePolicy.get("ccdWcsKey"), wcs) clipboard.put(stagePolicy.get("ampBBoxKey"), ampBBox) outWorker = tester.runWorker(clipboard) for policy in stagePolicy.getPolicyArray("data"): assert (outWorker.contains(policy.get("inputKey"))) assert (outWorker.contains(policy.get("outputKey"))) assert (outWorker.contains("persistable_" + policy.get("outputKey"))) diaSourceSet = outWorker.get(policy.get("outputKey")) assert (diaSourceSet.size() == sourceSet.size())
def coordIter(self, includeCoord=True): """Return a collection of coords, one per class @param[in] includeCoord if True then include lsst.afw.coord.Coord (the base class) in the list of classes instantiated """ if includeCoord: yield afwCoord.Coord(self.l * afwGeom.degrees, self.b * afwGeom.degrees) for coordClass, enum, cast, stringName in self.coordList: yield coordClass(self.l * afwGeom.degrees, self.b * afwGeom.degrees) obs = afwCoord.Observatory(-74.659 * afwGeom.degrees, 40.384 * afwGeom.degrees, 100.0) # peyton obsDate = dafBase.DateTime(2010, 3, 3, 0, 0, 0, dafBase.DateTime.TAI) epoch = obsDate.get(dafBase.DateTime.EPOCH) yield afwCoord.TopocentricCoord( 23.4 * afwGeom.degrees, 45.6 * afwGeom.degrees, epoch, obs, )