def checkMakeFlippedWcs(self, skyWcs, skyAtol=1e-7 * arcseconds): """Check makeFlippedWcs on the provided WCS """ # make an arbitrary bbox, but one that includes zero in one axis # and does not include zero in the other axis # the center of the bbox is used as the center of flipping # and the corners of the bbox are the input positions that are tested bbox = Box2D(Point2D(-100, 1000), Extent2D(2000, 1501)) # dict of (isRight, isTop): position minPos = bbox.getMin() maxPos = bbox.getMax() center = bbox.getCenter() cornerDict = { (False, False): minPos, (False, True): Point2D(minPos[0], maxPos[1]), (True, False): Point2D(maxPos[0], minPos[1]), (True, True): maxPos, } for flipLR, flipTB in itertools.product((False, True), (False, True)): flippedWcs = makeFlippedWcs(wcs=skyWcs, flipLR=flipLR, flipTB=flipTB, center=center) # the center is unchanged self.assertSpherePointsAlmostEqual(skyWcs.pixelToSky(center), flippedWcs.pixelToSky(center), maxSep=skyAtol) for isR, isT in itertools.product((False, True), (False, True)): origPos = cornerDict[(isR, isT)] flippedPos = cornerDict[(isR ^ flipLR, isT ^ flipTB)] self.assertSpherePointsAlmostEqual( skyWcs.pixelToSky(origPos), flippedWcs.pixelToSky(flippedPos), maxSep=skyAtol)
def setUp(self): SkyWcsBaseTestCase.setUp(self) crpix = Point2D(100, 100) crvalList = [ SpherePoint(0 * degrees, 45 * degrees), SpherePoint(0.00001 * degrees, 45 * degrees), SpherePoint(359.99999 * degrees, 45 * degrees), SpherePoint(30 * degrees, 89.99999 * degrees), ] orientationList = [ 0 * degrees, 0.00001 * degrees, -0.00001 * degrees, -45 * degrees, 90 * degrees, ] scale = 1.0 * arcseconds self.wcsList = [] for crval in crvalList: for orientation in orientationList: cd = makeCdMatrix(scale=scale, orientation=orientation) self.wcsList.append( makeSkyWcs(crpix=crpix, crval=crval, cdMatrix=cd)) self.pixelPoints = [ Point2D(x, y) for x, y in itertools.product((0.0, -2.0, 42.5, 1042.3), (27.6, -0.1, 0.0, 196.0)) ]
def setUp(self): # Test geometry: # # -100,99 99,99 # +--------------------+ # |AAAAAAAAAACCCCCDDDDD| A == only in epoch A # |AAAAAAAAAACCCCCDDDDD| B == only in epoch B # |AAAAAAAAAACCCCCDDDDD| C == in both epoch A and epoch B # |AAAAAAAAAACCCCCDDDDD| D == in epoch A; in B's bbox but outside its ValidPolygon # |AAAAAAAAAACCCCCDDDDD| # | BBBBBBBBBB| All WCSs have the same CRVAL and CD. # | BBBBBBBBBB| # | BBBBBBBBBB| Coadd has CRPIX=(0, 0) # | BBBBBBBBBB| Epoch A has CRPIX=(0, -50) # | BBBBBBBBBB| Epoch B has CRPIX=(-50, 0) # +--------------------+ # -100,-100 99,-100 # self.rng = np.random.RandomState(50) crval = SpherePoint(45.0, 45.0, degrees) cdMatrix = makeCdMatrix(scale=5E-5 * degrees, flipX=True) self.wcsCoadd = makeSkyWcs(crpix=Point2D(0.0, 0.0), crval=crval, cdMatrix=cdMatrix) self.wcsA = makeSkyWcs(crpix=Point2D(0.0, -50.0), crval=crval, cdMatrix=cdMatrix) self.wcsB = makeSkyWcs(crpix=Point2D(-50.0, 0.0), crval=crval, cdMatrix=cdMatrix) self.bboxCoadd = Box2I(Point2I(-100, -100), Point2I(99, 99)) self.bboxA = Box2I(Point2I(-100, -50), Point2I(99, 49)) self.bboxB = Box2I(Point2I(-50, -100), Point2I(49, 99)) self.polygonA = None polygonD = Polygon(Box2D(Box2I(Point2I(0, 0), Point2I(49, 99)))) self.polygonB, = polygonD.symDifference(Polygon(Box2D(self.bboxB))) self.curveA = makeRandomTransmissionCurve(self.rng) self.curveB = makeRandomTransmissionCurve(self.rng) self.weightA = 0.6 self.weightB = 0.2 schema = ExposureTable.makeMinimalSchema() weightKey = schema.addField("weight", type=float, doc="relative weight of image in Coadd") catalog = ExposureCatalog(schema) recordA = catalog.addNew() recordA[weightKey] = self.weightA recordA.setWcs(self.wcsA) recordA.setValidPolygon(self.polygonA) recordA.setBBox(self.bboxA) recordA.setTransmissionCurve(self.curveA) recordB = catalog.addNew() recordB[weightKey] = self.weightB recordB.setWcs(self.wcsB) recordB.setValidPolygon(self.polygonB) recordB.setBBox(self.bboxB) recordB.setTransmissionCurve(self.curveB) self.curveCoadd = makeCoaddTransmissionCurve(self.wcsCoadd, catalog)
def setUp(self): # Set up a Coadd with CoaddInputs tables that have blank filter columns to be filled # in by later test code. self.coadd = ExposureF(30, 90) # WCS is arbitrary, since it'll be the same for all images wcs = makeSkyWcs(crpix=Point2D(0, 0), crval=SpherePoint(45.0, 45.0, degrees), cdMatrix=makeCdMatrix(scale=0.17 * degrees)) self.coadd.setWcs(wcs) schema = ExposureCatalog.Table.makeMinimalSchema() self.filterKey = schema.addField("filter", type=str, doc="", size=16) weightKey = schema.addField("weight", type=float, doc="") # First input image covers the first 2/3, second covers the last 2/3, so they # overlap in the middle 1/3. inputs = ExposureCatalog(schema) self.input1 = inputs.addNew() self.input1.setId(1) self.input1.setBBox(Box2I(Point2I(0, 0), Point2I(29, 59))) self.input1.setWcs(wcs) self.input1.set(weightKey, 2.0) self.input2 = inputs.addNew() self.input2.setId(2) self.input2.setBBox(Box2I(Point2I(0, 30), Point2I(29, 89))) self.input2.setWcs(wcs) self.input2.set(weightKey, 3.0) # Use the same catalog for visits and CCDs since the algorithm we're testing only cares # about CCDs. self.coadd.getInfo().setCoaddInputs(CoaddInputs(inputs, inputs)) # Set up a catalog with centroids and a FilterFraction plugin. # We have one record in each region (first input only, both inputs, second input only) schema = SourceCatalog.Table.makeMinimalSchema() centroidKey = Point2DKey.addFields(schema, "centroid", doc="position", unit="pixel") schema.getAliasMap().set("slot_Centroid", "centroid") self.plugin = FilterFractionPlugin( config=FilterFractionPlugin.ConfigClass(), schema=schema, name="subaru_FilterFraction", metadata=PropertyList()) catalog = SourceCatalog(schema) self.record1 = catalog.addNew() self.record1.set(centroidKey, Point2D(14.0, 14.0)) self.record12 = catalog.addNew() self.record12.set(centroidKey, Point2D(14.0, 44.0)) self.record2 = catalog.addNew() self.record2.set(centroidKey, Point2D(14.0, 74.0))
def testReadOldTanFits(self): """Test reading a FITS file containing data for an lsst::afw::image::TanWcs That file was made using the same metadata follows (like self.metadata without the distortion) """ tanMetadata = PropertyList() # the following was fit using CreateWcsWithSip from meas_astrom # and is valid over this bbox: (minimum=(0, 0), maximum=(3030, 3030)) # This same metadata was used to create testdata/oldTanSipwWs.fits for name, value in ( ("RADESYS", "ICRS"), ("CTYPE1", "RA---TAN"), ("CTYPE2", "DEC--TAN"), ("CRPIX1", 1531.1824767147), ("CRPIX2", 1531.1824767147), ("CRVAL1", 43.035511801383), ("CRVAL2", 44.305697682784), ("CUNIT1", "deg"), ("CUNIT2", "deg"), ("CD1_1", 0.00027493991598151), ("CD1_2", -3.2758487104158e-06), ("CD2_1", 3.2301310675830e-06), ("CD2_2", 0.00027493937506632), ): tanMetadata.set(name, value) dataDir = os.path.join(os.path.split(__file__)[0], "data") filePath = os.path.join(dataDir, "oldTanWcs.fits") wcsFromFits = SkyWcs.readFits(filePath) wcsFromMetadata = makeSkyWcs(tanMetadata) bbox = Box2D(Point2D(-1000, -1000), Extent2D(3000, 3000)) self.assertWcsAlmostEqualOverBBox(wcsFromFits, wcsFromMetadata, bbox)
def testMakeTanSipWcs(self): referenceWcs = makeSkyWcs(self.metadata, strip=False) crpix = Point2D( self.metadata.get("CRPIX1") - 1, self.metadata.get("CRPIX2") - 1) crval = SpherePoint( self.metadata.get("CRVAL1") * degrees, self.metadata.get("CRVAL2") * degrees) cdMatrix = getCdMatrixFromMetadata(self.metadata) sipA = getSipMatrixFromMetadata(self.metadata, "A") sipB = getSipMatrixFromMetadata(self.metadata, "B") sipAp = getSipMatrixFromMetadata(self.metadata, "AP") sipBp = getSipMatrixFromMetadata(self.metadata, "BP") skyWcs1 = makeTanSipWcs(crpix=crpix, crval=crval, cdMatrix=cdMatrix, sipA=sipA, sipB=sipB) skyWcs2 = makeTanSipWcs(crpix=crpix, crval=crval, cdMatrix=cdMatrix, sipA=sipA, sipB=sipB, sipAp=sipAp, sipBp=sipBp) self.assertWcsAlmostEqualOverBBox(referenceWcs, skyWcs1, self.bbox) self.assertWcsAlmostEqualOverBBox(referenceWcs, skyWcs2, self.bbox) self.checkMakeFlippedWcs(skyWcs1) self.checkMakeFlippedWcs(skyWcs2)
def getCrpix(self, metadata): """Get CRPIX from metadata using the LSST convention: 0-based in parent coordinates """ return Point2D( # zero-based, hence the - 1 metadata.get("CRPIX1") + metadata.get("CRVAL1A") - 1, metadata.get("CRPIX2") + metadata.get("CRVAL2A") - 1, )
def __init__(self, n=5, chips=['R00_S22', 'R04_S20', 'R40_S02', 'R44_S00'], mag=17, sed='../sky/sed_500.txt'): super().__init__() # lazy imports from lsst.obs.lsst.phosim import PhosimMapper from lsst.afw.cameraGeom import PIXELS, FIELD_ANGLE from lsst.afw.geom import Point2D camera = PhosimMapper().camera for chip in chips: det = camera[chip] cornersPix = [Point2D(x) for x in det.getBBox().getCorners()] pixels2Field = camera.getTransform(det.makeCameraSys(PIXELS), FIELD_ANGLE) corners = pixels2Field.applyForward(cornersPix) ras = np.rad2deg([c.getX() for c in corners]) decs = np.rad2deg([c.getY() for c in corners]) for ra in np.linspace(min(ras), max(ras), n + 2)[1:-1]: for dec in np.linspace(min(decs), max(decs), n + 2)[1:-1]: self.addSource(ra, dec, mag, sed)
def testFullAffine(self): """Test affine = AffineXYTransform with just linear coefficients """ affineClass = xyTransformRegistry["affine"] affineConfig = affineClass.ConfigClass() affineConfig.translation = (-2.1, 3.4) rotAng = 0.832 # radians xScale = 3.7 yScale = 45.3 affineConfig.linear = ( math.cos(rotAng) * xScale, math.sin(rotAng) * yScale, -math.sin(rotAng) * xScale, math.cos(rotAng) * yScale, ) with lsst.utils.tests.getTempFilePath(".py") as filePath: self.checkConfig(affineClass, affineConfig, filePath) affine = affineClass(affineConfig) for fromPoint in self.fromIter(): toPoint = affine.forwardTransform(fromPoint) predToPoint = Point2D( affineConfig.linear[0] * fromPoint[0] + affineConfig.linear[1] * fromPoint[1], affineConfig.linear[2] * fromPoint[0] + affineConfig.linear[3] * fromPoint[1], ) predToPoint = predToPoint + Extent2D(*affineConfig.translation) for i in range(2): self.assertAlmostEqual(toPoint[i], predToPoint[i])
def testRadial(self): """Test radial = RadialXYTransform """ radialClass = xyTransformRegistry["radial"] radialConfig = radialClass.ConfigClass() radialConfig.coeffs = (0, 1.05, 0.1) with lsst.utils.tests.getTempFilePath(".py") as filePath: self.checkConfig(radialClass, radialConfig, filePath) radial = radialClass(radialConfig) self.assertEquals(type(radial), RadialXYTransform) self.assertEquals(len(radial.getCoeffs()), len(radialConfig.coeffs)) for coeff, predCoeff in itertools.izip(radial.getCoeffs(), radialConfig.coeffs): self.assertAlmostEqual(coeff, predCoeff) self.checkBasics(radial) for fromPoint in self.fromIter(): fromRadius = math.hypot(fromPoint[0], fromPoint[1]) fromAngle = math.atan2(fromPoint[1], fromPoint[0]) predToRadius = fromRadius * ( radialConfig.coeffs[2] * fromRadius + radialConfig.coeffs[1]) predToPoint = Point2D(predToRadius * math.cos(fromAngle), predToRadius * math.sin(fromAngle)) toPoint = radial.forwardTransform(fromPoint) for i in range(2): self.assertAlmostEqual(toPoint[i], predToPoint[i])
def testFilters(self): wavelengths = np.linspace(3000, 12000, 1000) point = Point2D(1000, -500) def check(curve, central, w1, w2): # check that throughput within w1 of central is strictly greater # than throughput outside w2 of central throughput = curve.sampleAt(point, wavelengths) mid = np.logical_and(wavelengths > central - w1, wavelengths < central + w1) outer = np.logical_or(wavelengths < central - w2, wavelengths > central + w2) self.assertGreater(throughput[mid].min(), throughput[outer].max()) for curves in makeTransmissionCurves.getFilterTransmission().values(): check(curves["NB0387"], 3870, 50, 100) check(curves["NB0816"], 8160, 50, 100) check(curves["NB0921"], 9210, 50, 100) check(curves["HSC-G"], 4730, 500, 1500) check(curves["HSC-R"], 6230, 500, 1500) check(curves["HSC-R2"], 6230, 500, 1500) check(curves["HSC-I"], 7750, 500, 1500) check(curves["HSC-I2"], 7750, 500, 1500) check(curves["HSC-Z"], 8923, 500, 1500) check(curves["HSC-Y"], 10030, 500, 1500)
def testNormalizationFk5(self): """Test that readLsstSkyWcs correctly normalizes FK5 1975 to ICRS """ equinox = 1975.0 metadata = self.metadata metadata.set("RADESYS", "FK5") metadata.set("EQUINOX", equinox) crpix = Point2D(metadata.get("CRPIX1") - 1, metadata.get("CRPIX2") - 1) # record the original CRVAL before reading and stripping metadata crvalFk5Deg = (metadata.get("CRVAL1"), metadata.get("CRVAL2")) # create the wcs and retrieve crval skyWcs = makeSkyWcs(metadata) crval = skyWcs.getSkyOrigin() # compare to computed crval computedCrval = skyWcs.pixelToSky(crpix) self.assertSpherePointsAlmostEqual(crval, computedCrval) # get predicted crval by converting with astropy crvalFk5 = astropy.coordinates.SkyCoord(crvalFk5Deg[0], crvalFk5Deg[1], frame="fk5", equinox="J%f" % (equinox, ), unit="deg") predictedCrvalIcrs = crvalFk5.icrs predictedCrval = SpherePoint(predictedCrvalIcrs.ra.radian * radians, predictedCrvalIcrs.dec.radian * radians) self.assertSpherePointsAlmostEqual(crval, predictedCrval, maxSep=0.002 * arcseconds)
def testNormalizationDecRa(self): """Test that a Dec, RA WCS is normalized to RA, Dec """ crpix = Point2D( self.metadata.get("CRPIX1") - 1, self.metadata.get("CRPIX2") - 1) # swap RA, Decaxes in metadata crvalIn = SpherePoint( self.metadata.get("CRVAL1") * degrees, self.metadata.get("CRVAL2") * degrees) self.metadata.set("CRVAL1", crvalIn[1].asDegrees()) self.metadata.set("CRVAL2", crvalIn[0].asDegrees()) self.metadata.set("CTYPE1", "DEC--TAN") self.metadata.set("CTYPE2", "RA---TAN") # create the wcs skyWcs = makeSkyWcs(self.metadata) # compare pixel origin to input crval crval = skyWcs.getSkyOrigin() self.assertSpherePointsAlmostEqual(crval, crvalIn) # compare to computed crval computedCrval = skyWcs.pixelToSky(crpix) self.assertSpherePointsAlmostEqual(crval, computedCrval)
def testMakeSimpleWcsMetadata(self): crpix = Point2D(111.1, 222.2) crval = SpherePoint(45.6 * degrees, 12.3 * degrees) scale = 1 * arcseconds for orientation in (0 * degrees, 21 * degrees): cdMatrix = makeCdMatrix(scale=scale, orientation=orientation) for projection in ("TAN", "STG"): metadata = makeSimpleWcsMetadata(crpix=crpix, crval=crval, cdMatrix=cdMatrix, projection=projection) desiredLength = 12 if orientation == 0 * degrees else 14 self.assertEqual(len(metadata.names()), desiredLength) self.assertEqual(metadata.get("RADESYS"), "ICRS") self.assertAlmostEqual(metadata.get("EQUINOX"), 2000.0) self.assertEqual(metadata.get("CTYPE1"), "RA---" + projection) self.assertEqual(metadata.get("CTYPE2"), "DEC--" + projection) for i in range(2): self.assertAlmostEqual(metadata.get("CRPIX%d" % (i + 1,)), crpix[i] + 1) self.assertAlmostEqual(metadata.get("CRVAL%d" % (i + 1,)), crval[i].asDegrees()) self.assertEqual(metadata.get("CUNIT%d" % (i + 1,)), "deg") for i in range(2): for j in range(2): name = "CD%d_%d" % (i + 1, j + 1) if cdMatrix[i, j] != 0: self.assertAlmostEqual(metadata.get(name), cdMatrix[i, j]) else: self.assertFalse(metadata.exists(name))
def testCD_PC(self): """Test that we can read a FITS file with both CD and PC keys (like early Suprimecam files)""" md = PropertyList() for k, v in ( ("EQUINOX", 2000.0), ("RADESYS", "ICRS"), ("CRPIX1", 5353.0), ("CRPIX2", -35.0), ("CD1_1", 0.0), ("CD1_2", -5.611E-05), ("CD2_1", -5.611E-05), ("CD2_2", -0.0), ("CRVAL1", 4.5789875), ("CRVAL2", 16.30004444), ("CUNIT1", "deg"), ("CUNIT2", "deg"), ("CTYPE1", "RA---TAN"), ("CTYPE2", "DEC--TAN"), ("CDELT1", -5.611E-05), ("CDELT2", 5.611E-05), ): md.set(k, v) wcs = makeSkyWcs(md, strip=False) pixPos = Point2D(1000, 2000) pred_skyPos = SpherePoint(4.459815023498577 * degrees, 16.544199850984768 * degrees) skyPos = wcs.pixelToSky(pixPos) self.assertSpherePointsAlmostEqual(skyPos, pred_skyPos) for badPC in (False, True): for k, v in ( ("PC001001", 0.0), ("PC001002", -1.0 if badPC else 1.0), ("PC002001", 1.0 if badPC else -1.0), ("PC002002", 0.0), ): md.set(k, v) # Check Greisen and Calabretta A&A 395 1061 (2002), Eq. 3 if not badPC: for i in ( 1, 2, ): for j in ( 1, 2, ): self.assertEqual( md.get("CD%d_%d" % (i, j)), md.get("CDELT%d" % i) * md.get("PC00%d00%d" % (i, j))) wcs2 = makeSkyWcs(md, strip=False) skyPos2 = wcs2.pixelToSky(pixPos) self.assertSpherePointsAlmostEqual(skyPos2, pred_skyPos)
def testAgainstAstropyWcs(self): skyWcs = makeSkyWcs(self.metadata, strip=False) header = makeLimitedFitsHeader(self.metadata) astropyWcs = astropy.wcs.WCS(header) bbox = Box2D(Point2D(-1000, -1000), Extent2D(3000, 3000)) self.assertSkyWcsAstropyWcsAlmostEqual(skyWcs=skyWcs, astropyWcs=astropyWcs, bbox=bbox)
def testOptics(self): wavelengths = np.linspace(4000, 10000, 100) point = Point2D(1000, -500) for curve in makeTransmissionCurves.getOpticsTransmission().values(): if curve is None: continue throughputs = curve.sampleAt(point, wavelengths) self.assertTrue((throughputs > 0.70).all())
def testMakeModifiedWcsNoActualPixels(self): """Test makeModifiedWcs on a SkyWcs that has no ACTUAL_PIXELS frame """ cdMatrix = makeCdMatrix(scale=self.scale) originalWcs = makeSkyWcs(crpix=self.crpix, crval=self.crvalList[0], cdMatrix=cdMatrix) originalFrameDict = originalWcs.getFrameDict() # make an arbitrary but reasonable transform to insert using makeModifiedWcs pixelTransform = makeRadialTransform([0.0, 1.0, 0.0, 0.0011]) # the result of the insertion should be as follows desiredPixelsToSky = pixelTransform.then(originalWcs.getTransform()) pixPointList = ( # arbitrary but reasonable Point2D(0.0, 0.0), Point2D(1000.0, 0.0), Point2D(0.0, 2000.0), Point2D(-1111.0, -2222.0), ) for modifyActualPixels in (False, True): modifiedWcs = makeModifiedWcs( pixelTransform=pixelTransform, wcs=originalWcs, modifyActualPixels=modifyActualPixels) modifiedFrameDict = modifiedWcs.getFrameDict() skyList = modifiedWcs.pixelToSky(pixPointList) # compare pixels to sky desiredSkyList = desiredPixelsToSky.applyForward(pixPointList) self.assertSpherePointListsAlmostEqual(skyList, desiredSkyList) # compare pixels to IWC pixelsToIwc = TransformPoint2ToPoint2( modifiedFrameDict.getMapping("PIXELS", "IWC")) desiredPixelsToIwc = TransformPoint2ToPoint2( pixelTransform.getMapping().then( originalFrameDict.getMapping("PIXELS", "IWC"))) self.assertPairListsAlmostEqual( pixelsToIwc.applyForward(pixPointList), desiredPixelsToIwc.applyForward(pixPointList)) self.checkNonFitsWcs(modifiedWcs)
def testSensors(self): wavelengths = np.linspace(4000, 12000, 100) point = Point2D(200, 10) for sensors in makeTransmissionCurves.getSensorTransmission().values(): for i in range(112): curve = sensors[i] throughputs = curve.sampleAt(point, wavelengths) siliconTransparent = wavelengths > 11000 self.assertTrue((throughputs[siliconTransparent] < 0.01).all()) midR = np.logical_and(wavelengths > 6000, wavelengths < 6300) self.assertTrue((throughputs[midR] > 0.9).all())
def checkPersistence(self, skyWcs, bbox): """Check persistence of a SkyWcs """ className = "SkyWcs" # check writeString and readString skyWcsStr = skyWcs.writeString() serialVersion, serialClassName, serialRest = skyWcsStr.split(" ", 2) self.assertEqual(int(serialVersion), 1) self.assertEqual(serialClassName, className) badStr1 = " ".join(["2", serialClassName, serialRest]) with self.assertRaises(lsst.pex.exceptions.TypeError): skyWcs.readString(badStr1) badClassName = "x" + serialClassName badStr2 = " ".join(["1", badClassName, serialRest]) with self.assertRaises(lsst.pex.exceptions.TypeError): skyWcs.readString(badStr2) skyWcsFromStr1 = skyWcs.readString(skyWcsStr) self.assertEqual(skyWcs, skyWcsFromStr1) self.assertEqual(type(skyWcs), type(skyWcsFromStr1)) self.assertEqual(skyWcs.getFrameDict(), skyWcsFromStr1.getFrameDict()) pixelPoints = [ Point2D(0, 0), Point2D(1000, 0), Point2D(0, 1000), Point2D(-50, -50), ] skyPoints = skyWcs.pixelToSky(pixelPoints) pixelPoints2 = skyWcs.skyToPixel(skyPoints) assert_allclose(pixelPoints, pixelPoints2, atol=1e-7) # check that WCS is properly saved as part of an exposure FITS file exposure = ExposureF(100, 100, skyWcs) with lsst.utils.tests.getTempFilePath(".fits") as outFile: exposure.writeFits(outFile) exposureRoundTrip = ExposureF(outFile) wcsFromExposure = exposureRoundTrip.getWcs() self.assertWcsAlmostEqualOverBBox(skyWcs, wcsFromExposure, bbox)
def extractCtorArgs(md): wcs = makeSkyWcs(makePropertyListFromDict(md)) kwds = { "pixelToIwc": getPixelToIntermediateWorldCoords(wcs), "bbox": Box2D(Box2I(Point2I(0, 0), Extent2I(md["NAXES1"], md["NAXES2"]))), "crpix": Point2D(md["CRPIX1"] - 1.0, md["CRPIX2"] - 1.0), # -1 for LSST vs. FITS conventions "cd": np.array([[md["CD1_1"], md["CD1_2"]], [md["CD2_1"], md["CD2_2"]]]), } return kwds
def testReadOldTanSipFits(self): """Test reading a FITS file containing data for an lsst::afw::image::TanWcs That file was made using the same metadata as this test """ dataDir = os.path.join(os.path.split(__file__)[0], "data") filePath = os.path.join(dataDir, "oldTanSipWcs.fits") wcsFromFits = SkyWcs.readFits(filePath) wcsFromMetadata = makeSkyWcs(self.metadata) bbox = Box2D(Point2D(-1000, -1000), Extent2D(3000, 3000)) self.assertWcsAlmostEqualOverBBox(wcsFromFits, wcsFromMetadata, bbox)
def testAtmosphere(self): wavelengths = np.linspace(4000, 12000, 100) point = Point2D(1000, -500) for curve in makeTransmissionCurves.getAtmosphereTransmission().values( ): if curve is None: continue throughputs = curve.sampleAt(point, wavelengths) ohAbsorption = np.logical_and(wavelengths > 11315, wavelengths < 11397) midR = np.logical_and(wavelengths > 6000, wavelengths < 6300) self.assertTrue( (throughputs[ohAbsorption] < throughputs[midR]).all())
def setUp(self): xy0 = Point2I(12345, 67890) # xy0 for image dims = Extent2I(2345, 2345) # Dimensions of image box = Box2I(xy0, dims) # Bounding box of image sigma = 3.21 # PSF sigma buffer = 4.0 # Buffer for star centers around edge nSigmaForKernel = 5.0 # Number of PSF sigmas for kernel sky = 12345.6 # Sky level numStars = 100 # Number of stars noise = np.sqrt(sky) * np.pi * sigma**2 # Poisson noise per PSF faint = 1.0 * noise # Faintest level for star fluxes bright = 100.0 * noise # Brightest level for star fluxes starBox = Box2I(box) # Area on image in which we can put star centers starBox.grow(-int(buffer * sigma)) scale = 1.0e-5 * degrees # Pixel scale np.random.seed(12345) stars = [(xx, yy, ff, sigma) for xx, yy, ff in zip( np.random.uniform(starBox.getMinX(), starBox.getMaxX(), numStars), np.random.uniform(starBox.getMinY(), starBox.getMaxY(), numStars), np.linspace(faint, bright, numStars))] self.exposure = plantSources(box, 2 * int(nSigmaForKernel * sigma) + 1, sky, stars, True) self.exposure.setWcs( makeSkyWcs(crpix=Point2D(0, 0), crval=SpherePoint(0, 0, degrees), cdMatrix=makeCdMatrix(scale=scale))) # Make a large area of extra background; we should be robust against it # Unfortunately, some tuning is required here to get something challenging but not impossible: # * A very large box will cause failures because the "extra" and the "normal" are reversed. # * A small box will not be challenging because it's simple to clip out. # * A large value will cause failures because it produces large edges in background-subtrction that # broaden flux distributions. # * A small value will not be challenging because it has little effect. extraBox = Box2I(xy0 + Extent2I(345, 456), Extent2I(1234, 1234)) # Box for extra background extraValue = 0.5 * noise # Extra background value to add in self.exposure.image[extraBox, PARENT] += extraValue self.config = DynamicDetectionTask.ConfigClass() self.config.skyObjects.nSources = 300 self.config.reEstimateBackground = False self.config.doTempWideBackground = True self.config.thresholdType = "pixel_stdev" # Relative tolerance for tweak factor # Not sure why this isn't smaller; maybe due to use of Poisson instead of Gaussian noise? self.rtol = 0.1
def testGetIntermediateWorldCoordsToSky(self): """Test getIntermediateWorldCoordsToSky and getPixelToIntermediateWorldCoords """ crpix = Extent2D( self.metadata.get("CRPIX1") - 1, self.metadata.get("CRPIX2") - 1) skyWcs = makeSkyWcs(self.metadata, strip=False) for simplify in (False, True): pixelToIwc = getPixelToIntermediateWorldCoords(skyWcs, simplify) iwcToSky = getIntermediateWorldCoordsToSky(skyWcs, simplify) self.assertTrue(isinstance(pixelToIwc, TransformPoint2ToPoint2)) self.assertTrue(isinstance(iwcToSky, TransformPoint2ToSpherePoint)) if simplify: self.assertTrue(pixelToIwc.getMapping().isSimple) self.assertTrue(iwcToSky.getMapping().isSimple) # else the mapping may have already been simplified inside the WCS, # so don't assert isSimple is false # check that the chained transforms produce the same results as the WCS # in the forward and inverse direction pixPosList = [] for dx in (0, 1000): for dy in (0, 1000): pixPosList.append(Point2D(dx, dy) + crpix) iwcPosList = pixelToIwc.applyForward(pixPosList) skyPosList = iwcToSky.applyForward(iwcPosList) self.assertSpherePointListsAlmostEqual( skyPosList, skyWcs.pixelToSky(pixPosList)) self.assertPairListsAlmostEqual( pixelToIwc.applyInverse(iwcToSky.applyInverse(skyPosList)), skyWcs.skyToPixel(skyPosList)) self.assertPairListsAlmostEqual(iwcPosList, iwcToSky.applyInverse(skyPosList)) self.assertPairListsAlmostEqual( pixPosList, pixelToIwc.applyInverse(iwcPosList)) # compare extracted pixelToIwc to a version of pixelToIwc computed directly from the metadata ourPixelToIwc = makeSipPixelToIwc(self.metadata) self.assertPairListsAlmostEqual( pixelToIwc.applyForward(pixPosList), ourPixelToIwc.applyForward(pixPosList)) # compare extracted iwcToPixel to a version of iwcToPixel computed directly from the metadata ourIwcToPixel = makeSipIwcToPixel(self.metadata) self.assertPairListsAlmostEqual( pixelToIwc.applyInverse(iwcPosList), ourIwcToPixel.applyForward(iwcPosList))
def assertSkyWcsAstropyWcsAlmostEqual(self, skyWcs, astropyWcs, bbox, pixAtol=1e-4, skyAtol=1e-4 * arcseconds, checkRoundTrip=True): """Assert that a SkyWcs and the corresponding astropy.wcs.WCS agree over a specified bounding box """ bbox = Box2D(bbox) center = bbox.getCenter() xArr = bbox.getMinX(), center[0], bbox.getMaxX() yArr = bbox.getMinY(), center[1], bbox.getMaxY() pixPosList = [Point2D(x, y) for x, y in itertools.product(xArr, yArr)] # pixelToSky skyPosList = skyWcs.pixelToSky(pixPosList) astropySkyPosList = self.astropyPixelsToSky(astropyWcs=astropyWcs, pixPosList=pixPosList) self.assertSpherePointListsAlmostEqual(skyPosList, astropySkyPosList, maxSep=skyAtol) if not checkRoundTrip: return # astropy round trip astropyPixPosRoundTrip = self.astropySkyToPixels( astropyWcs=astropyWcs, skyPosList=astropySkyPosList) self.assertPairListsAlmostEqual(pixPosList, astropyPixPosRoundTrip, maxDiff=pixAtol) # SkyWcs round trip pixPosListRoundTrip = skyWcs.skyToPixel(skyPosList) self.assertPairListsAlmostEqual(pixPosList, pixPosListRoundTrip, maxDiff=pixAtol) # skyToPixel astropy vs SkyWcs astropyPixPosList2 = self.astropySkyToPixels(astropyWcs=astropyWcs, skyPosList=skyPosList) self.assertPairListsAlmostEqual(pixPosListRoundTrip, astropyPixPosList2, maxDiff=pixAtol)
def testReadV1Catalog(self): testDir = os.path.dirname(__file__) v1CatalogPath = os.path.join( testDir, "data", "exposure_catalog_v1.fits") catV1 = lsst.afw.table.ExposureCatalog.readFits(v1CatalogPath) self.assertEqual(self.cat[0].get(self.ka), catV1[0].get(self.ka)) self.assertEqual(self.cat[0].get(self.kb), catV1[0].get(self.kb)) self.comparePsfs(self.cat[0].getPsf(), catV1[0].getPsf()) bbox = Box2D(Point2D(0, 0), Extent2D(2000, 2000)) self.assertWcsAlmostEqualOverBBox(self.cat[0].getWcs(), catV1[0].getWcs(), bbox) self.assertEqual(self.cat[1].get(self.ka), catV1[1].get(self.ka)) self.assertEqual(self.cat[1].get(self.kb), catV1[1].get(self.kb)) self.assertEqual(self.cat[1].getWcs(), catV1[1].getWcs()) self.assertIsNone(self.cat[1].getPsf()) self.assertIsNone(self.cat[1].getPhotoCalib()) self.assertEqual(self.cat[0].getPhotoCalib(), catV1[0].getPhotoCalib()) self.assertIsNone(catV1[0].getVisitInfo()) self.assertIsNone(catV1[1].getVisitInfo())
def setUp(self): TransformTestBaseClass.setUp(self) self.crpix = Point2D(100, 100) self.crvalList = [ IcrsCoord(0 * degrees, 45 * degrees), IcrsCoord(0.00001 * degrees, 45 * degrees), IcrsCoord(359.99999 * degrees, 45 * degrees), IcrsCoord(30 * degrees, 89.99999 * degrees), IcrsCoord(30 * degrees, -89.99999 * degrees), ] self.orientationList = [ 0 * degrees, 0.00001 * degrees, -0.00001 * degrees, -45 * degrees, 90 * degrees, ] self.scale = 1.0 * arcseconds self.tinyPixels = 10 * sys.float_info.epsilon self.tinyAngle = 10 * sys.float_info.epsilon * radians
def setUp(self): self.crpix = Point2D(100, 100) self.crvalList = [ SpherePoint(0 * degrees, 45 * degrees), SpherePoint(0.00001 * degrees, 45 * degrees), SpherePoint(359.99999 * degrees, 45 * degrees), SpherePoint(30 * degrees, 89.99999 * degrees), SpherePoint(30 * degrees, -89.99999 * degrees), ] self.orientationList = [ 0 * degrees, 0.00001 * degrees, -0.00001 * degrees, -45 * degrees, 90 * degrees, ] self.scale = 1.0 * arcseconds self.tinyPixels = 1.0e-10 self.tinyAngle = 1.0e-10 * radians self.bbox = Box2I(Point2I(-1000, -1000), Extent2I(2000, 2000)) # arbitrary but reasonable
def testAgainstAstropyWcs(self): bbox = Box2D(Point2D(-1000, -1000), Extent2D(2000, 2000)) for crval, orientation, flipX, projection in itertools.product( self.crvalList, self.orientationList, (False, True), ("TAN", "STG", "CEA", "AIT")): cdMatrix = makeCdMatrix(scale=self.scale, orientation=orientation, flipX=flipX) metadata = makeSimpleWcsMetadata(crpix=self.crpix, crval=crval, cdMatrix=cdMatrix, projection=projection) header = makeLimitedFitsHeader(metadata) astropyWcs = astropy.wcs.WCS(header) skyWcs = makeSkyWcs(crpix=self.crpix, crval=crval, cdMatrix=cdMatrix, projection=projection) # Most projections only seem to agree to within 1e-4 in the round trip test self.assertSkyWcsAstropyWcsAlmostEqual(skyWcs=skyWcs, astropyWcs=astropyWcs, bbox=bbox)