22"""Utilities that should be imported into the lsst.afw.geom namespace when lsst.afw.geom is used
24In the case of the assert functions, importing them makes them available in lsst.utils.tests.TestCase
26__all__ = [
"wcsAlmostEqualOverBBox"]
35from ._geom
import GenericEndpoint, Point2Endpoint, SpherePointEndpoint
38def _compareWcsOverBBox(wcs0, wcs1, bbox, maxDiffSky=0.01*lsst.geom.arcseconds,
39 maxDiffPix=0.01, nx=5, ny=5, doShortCircuit=True):
40 """Compare two :py:class:`WCS <lsst.afw.geom.SkyWcs>` over a rectangular grid of pixel positions
49 boundaries of pixel grid over which to compare the WCSs
51 maximum separation between sky positions computed using Wcs.pixelToSky
53 maximum separation between pixel positions computed using Wcs.skyToPixel
55 number of points
in x
for the grid of pixel positions
57 number of points
in y
for the grid of pixel positions
58 doShortCircuit : `bool`
59 if True then stop at the first error,
else test all values
in the grid
60 and return information about the worst violations found
65 an empty string
if the WCS are sufficiently close;
else return a string describing
66 the largest error measured
in pixel coordinates (
if sky to pixel error was excessive)
67 and sky coordinates (
if pixel to sky error was excessive). If doShortCircuit
is true
68 then the reported error
is likely to be much less than the maximum error across the
72 raise RuntimeError(f
"nx = {nx} and ny = {ny} must both be positive")
73 if maxDiffSky < 0*lsst.geom.arcseconds:
74 raise RuntimeError(f
"maxDiffSky = {maxDiffSky} must not be negative")
76 raise RuntimeError(f
"maxDiffPix = {maxDiffPix} must not be negative")
79 xList = np.linspace(bboxd.getMinX(), bboxd.getMaxX(), nx)
80 yList = np.linspace(bboxd.getMinY(), bboxd.getMaxY(), ny)
83 measDiffSky = (maxDiffSky,
"?")
84 measDiffPix = (maxDiffPix,
"?")
85 for x, y
in itertools.product(xList, yList):
87 sky0 = wcs0.pixelToSky(fromPixPos)
88 sky1 = wcs1.pixelToSky(fromPixPos)
89 diffSky = sky0.separation(sky1)
90 if diffSky > measDiffSky[0]:
91 measDiffSky = (diffSky, fromPixPos)
95 toPixPos0 = wcs0.skyToPixel(sky0)
96 toPixPos1 = wcs1.skyToPixel(sky0)
97 diffPix = math.hypot(*(toPixPos0 - toPixPos1))
98 if diffPix > measDiffPix[0]:
99 measDiffPix = (diffPix, sky0)
104 if measDiffSky[0] > maxDiffSky:
105 msgList.append(f
"{measDiffSky[0].asArcseconds()} arcsec max measured sky error "
106 f
"> {maxDiffSky.asArcseconds()} arcsec max allowed sky error "
107 f
"at pix pos=measDiffSky[1]")
108 if measDiffPix[0] > maxDiffPix:
109 msgList.append(f
"{measDiffPix[0]} max measured pix error "
110 f
"> {maxDiffPix} max allowed pix error "
111 f
"at sky pos={measDiffPix[1]}")
113 return "; ".join(msgList)
117 maxDiffPix=0.01, nx=5, ny=5):
118 """Test if two :py:class:`WCS <lsst.afw.geom.SkyWcs>` are almost equal over a grid of pixel positions.
127 boundaries of pixel grid over which to compare the WCSs
129 maximum separation between sky positions computed using Wcs.pixelToSky
131 maximum separation between pixel positions computed using Wcs.skyToPixel
133 number of points
in x
for the grid of pixel positions
135 number of points
in y
for the grid of pixel positions
140 `
True`
if two WCS are almost equal over a grid of pixel positions,
else `
False`
142 return not bool(_compareWcsOverBBox(
146 maxDiffSky=maxDiffSky,
147 maxDiffPix=maxDiffPix,
154@lsst.utils.tests.inTestCase
155def assertWcsAlmostEqualOverBBox(testCase, wcs0, wcs1, bbox, maxDiffSky=0.01*lsst.geom.arcseconds,
156 maxDiffPix=0.01, nx=5, ny=5, msg="WCSs differ"):
157 """Assert that two :py:class:`WCS <lsst.afw.geom.SkyWcs>` are almost equal over a grid of pixel positions
159 Compare pixelToSky and skyToPixel
for two WCS over a rectangular grid of pixel positions.
160 If the WCS are too divergent at any point, call testCase.fail; the message describes
161 the largest error measured
in pixel coordinates (
if sky to pixel error was excessive)
162 and sky coordinates (
if pixel to sky error was excessive) across the entire pixel grid.
166 testCase : `unittest.TestCase`
167 test case the test
is part of; an object supporting one method: fail(self, msgStr)
173 boundaries of pixel grid over which to compare the WCSs
175 maximum separation between sky positions computed using Wcs.pixelToSky
177 maximum separation between pixel positions computed using Wcs.skyToPixel
179 number of points
in x
for the grid of pixel positions
181 number of points
in y
for the grid of pixel positions
183 exception message prefix; details of the error are appended after
": "
185 errMsg = _compareWcsOverBBox(
189 maxDiffSky=maxDiffSky,
190 maxDiffPix=maxDiffPix,
193 doShortCircuit=False,
196 testCase.fail(f
"{msg}: {errMsg}")
199@lsst.utils.tests.inTestCase
201 """Generate a representative sample of ``Endpoints``.
205 testCase : `unittest.TestCase`
206 test case the test is part of; an object supporting one method: fail(self, msgStr)
211 List of endpoints
with enough diversity to exercise ``Endpoint``-related
212 code. Each invocation of this method shall
return independent objects.
214 return [GenericEndpoint(n)
for n
in range(1, 6)] + \
215 [Point2Endpoint(), SpherePointEndpoint()]
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
A class representing an angle.
A floating-point coordinate rectangle geometry.
An integer coordinate rectangle.
def wcsAlmostEqualOverBBox(wcs0, wcs1, bbox, maxDiffSky=0.01 *lsst.geom.arcseconds, maxDiffPix=0.01, nx=5, ny=5)
def makeEndpoints(testCase)