def testConstruction(self): poly = makeRandomPolynomialTransform(4, sip=True) cd = lsst.afw.geom.LinearTransform(np.random.randn(2, 2)) crpix = lsst.afw.geom.Point2D(*np.random.randn(2)) sip = SipForwardTransform(crpix, cd, poly) self.assertTransformsAlmostEqual( sip, lambda p: cd( (p - crpix) + poly(lsst.afw.geom.Point2D(p - crpix))))
def testMakeWcs(self): fwd = self.makeRandom() rev = SipReverseTransform( # this isn't actually the inverse of fwd, but that doesn't matter fwd.getPixelOrigin(), fwd.getCDMatrix(), makeRandomPolynomialTransform(4)) crval = lsst.afw.geom.Point2D(45.0, 45.0) wcs = lsst.meas.astrom.makeWcs( fwd, rev, lsst.afw.coord.IcrsCoord(crval, lsst.afw.geom.degrees)) self.assertFloatsAlmostEqual(fwd.getPoly().getXCoeffs(), wcs.getSipA()) self.assertFloatsAlmostEqual(fwd.getPoly().getYCoeffs(), wcs.getSipB()) self.assertFloatsAlmostEqual(rev.getPoly().getXCoeffs(), wcs.getSipAp()) self.assertFloatsAlmostEqual(rev.getPoly().getYCoeffs(), wcs.getSipBp()) # We can only test agreement with TanWcs in one direction, because # TanWcs doesn't provide an inverse to skyToIntermediateWorldCoord. def t1(p): sky = lsst.afw.coord.IcrsCoord(crval + lsst.afw.geom.Extent2D(p), lsst.afw.geom.degrees) return rev(wcs.skyToIntermediateWorldCoord(sky)) def t2(p): sky = lsst.afw.coord.IcrsCoord(crval + lsst.afw.geom.Extent2D(p), lsst.afw.geom.degrees) return wcs.skyToPixel(sky) self.assertTransformsAlmostEqual(t1, t2) fwd2 = SipForwardTransform.extract(wcs) rev2 = SipReverseTransform.extract(wcs) self.assertPairsAlmostEqual(fwd.getPixelOrigin(), fwd2.getPixelOrigin()) self.assertPairsAlmostEqual(rev.getPixelOrigin(), rev2.getPixelOrigin()) self.assertFloatsAlmostEqual(fwd.getCDMatrix().getMatrix(), fwd2.getCDMatrix().getMatrix()) self.assertFloatsAlmostEqual(rev.getCDMatrix().getMatrix(), rev2.getCDMatrix().getMatrix()) self.assertFloatsAlmostEqual(fwd.getPoly().getXCoeffs(), fwd2.getPoly().getXCoeffs()) self.assertFloatsAlmostEqual(fwd.getPoly().getYCoeffs(), fwd2.getPoly().getYCoeffs()) self.assertFloatsAlmostEqual(rev.getPoly().getXCoeffs(), rev2.getPoly().getXCoeffs()) self.assertFloatsAlmostEqual(rev.getPoly().getYCoeffs(), rev2.getPoly().getYCoeffs())
def makeRandomSipForwardTransform(order): return SipForwardTransform( lsst.afw.geom.Point2D(*np.random.randn(2)), lsst.afw.geom.LinearTransform(np.random.randn(2, 2)), makeRandomPolynomialTransform(order, sip=True))
def testMakeWcs(self): """Test SipForwardTransform, SipReverseTransform and makeWcs """ filename = os.path.join(os.path.dirname(__file__), 'imgCharSources-v85501867-R01-S00.sipheader') sipMetadata = readMetadata(filename) # We're building an ICRS-based TAN-SIP using coefficients read from metadata # so ignore the RADESYS in metadata (which is missing anyway, falling back to FK5) sipMetadata.set("RADESYS", "ICRS") crpix = lsst.afw.geom.Point2D( sipMetadata.get("CRPIX1") - 1, sipMetadata.get("CRPIX2") - 1, ) crval = lsst.afw.geom.SpherePoint( sipMetadata.get("CRVAL1"), sipMetadata.get("CRVAL2"), lsst.afw.geom.degrees, ) cdLinearTransform = lsst.afw.geom.LinearTransform( getCdMatrixFromMetadata(sipMetadata)) aArr = getSipMatrixFromMetadata(sipMetadata, "A") bArr = getSipMatrixFromMetadata(sipMetadata, "B") apArr = getSipMatrixFromMetadata(sipMetadata, "AP") bpArr = getSipMatrixFromMetadata(sipMetadata, "BP") abPoly = PolynomialTransform(aArr, bArr) abRevPoly = PolynomialTransform(apArr, bpArr) fwd = SipForwardTransform(crpix, cdLinearTransform, abPoly) rev = SipReverseTransform(crpix, cdLinearTransform, abRevPoly) wcsFromMakeWcs = lsst.meas.astrom.makeWcs(fwd, rev, crval) wcsFromMetadata = lsst.afw.geom.makeSkyWcs(sipMetadata, strip=False) # Check SipForwardTransform against a local implementation localPixelToIwc = makeSipPixelToIwc(sipMetadata) self.assertTransformsAlmostEqual(fwd, localPixelToIwc.applyForward, maxval=2000) # Compare SipReverseTransform against a local implementation # Use the forward direction first to get sensible inputs localIwcToPixel = makeSipIwcToPixel(sipMetadata) def fwdThenRev(p): return rev(fwd(p)) def fwdThenLocalRev(p): return localIwcToPixel.applyForward(fwd(p)) self.assertTransformsAlmostEqual(fwdThenRev, fwdThenLocalRev, maxval=2000) # Check that SipReverseTransform is the inverse of SipForwardTransform; # this is not perfect because the coefficients don't define a perfect inverse def nullTransform(p): return p self.assertTransformsAlmostEqual(fwdThenRev, nullTransform, maxval=2000, atol=1e-3) # Check SipForwardTransform against the one contained in wcsFromMakeWcs # (Don't bother with the other direction because the WCS transform is iterative, # so it doesn't tell us anything useful about SipReverseTransform pixelToIwc = lsst.afw.geom.getPixelToIntermediateWorldCoords( wcsFromMetadata) self.assertTransformsAlmostEqual(fwd, pixelToIwc.applyForward, maxval=2000) # Check a WCS constructed from SipForwardTransform, SipReverseTransform # against one constructed directly from the metadata bbox = lsst.afw.geom.Box2D(lsst.afw.geom.Point2D(0, 0), lsst.afw.geom.Extent2D(2000, 2000)) self.assertWcsAlmostEqualOverBBox(wcsFromMakeWcs, wcsFromMetadata, bbox)