Coverage for python/lsst/geom/testUtils.py : 19%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#
2# Developed for the LSST Data Management System.
3# This product includes software developed by the LSST Project
4# (https://www.lsst.org).
5# See the COPYRIGHT file at the top-level directory of this distribution
6# for details of code ownership.
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program. If not, see <https://www.gnu.org/licenses/>.
20#
22"""Utilities that should be imported into the lsst.geom namespace when
23lsst.geom is used
25In the case of the assert functions, importing them makes them available in lsst.utils.tests.TestCase
26"""
27__all__ = []
29import math
31import numpy as np
33import lsst.utils.tests
34from ._geom import arcseconds
37def extraMsg(msg):
38 """Format extra error message, if any
39 """
40 if msg:
41 return ": " + msg
42 return ""
45@lsst.utils.tests.inTestCase
46def assertAnglesAlmostEqual(testCase, ang0, ang1, maxDiff=0.001*arcseconds,
47 ignoreWrap=True, msg="Angles differ"):
48 r"""Assert that two `~lsst.geom.Angle`\ s are almost equal, ignoring
49 wrap differences by default.
51 If both arguments are NaN the assert will pass. If one of the arguments
52 is NaN but the other is not the assert will fail.
54 Parameters
55 ----------
56 testCase : `unittest.TestCase`
57 test case the test is part of; an object supporting one method:
58 fail(self, msgStr)
59 ang0 : `lsst.geom.Angle`
60 angle 0
61 ang1 : `lsst.geom.Angle`
62 angle 1
63 maxDiff : `lsst.geom.Angle`
64 maximum difference between the two angles
65 ignoreWrap : `bool`
66 ignore wrap when comparing the angles?
67 - if True then wrap is ignored, e.g. 0 and 360 degrees are considered
68 equal
69 - if False then wrap matters, e.g. 0 and 360 degrees are considered
70 different
71 msg : `str`
72 exception message prefix; details of the error are appended after ": "
74 Raises
75 ------
76 AssertionError
77 Raised if the difference is greater than ``maxDiff``
78 """
79 isNan0 = math.isnan(ang0.asRadians())
80 isNan1 = math.isnan(ang1.asRadians())
81 if isNan0 and isNan1:
82 return
83 if isNan0:
84 testCase.fail("ang0 is NaN")
85 if isNan1:
86 testCase.fail("ang1 is NaN")
87 measDiff = ang1 - ang0
88 if ignoreWrap:
89 measDiff = measDiff.wrapCtr()
90 if abs(measDiff) > maxDiff:
91 testCase.fail("%s: measured difference %s arcsec > max allowed %s arcsec" %
92 (msg, measDiff.asArcseconds(), maxDiff.asArcseconds()))
95@lsst.utils.tests.inTestCase
96def assertPairsAlmostEqual(testCase, pair0, pair1, maxDiff=1e-7, msg="Pairs differ"):
97 """Assert that two Cartesian points are almost equal.
99 Each point can be any indexable pair of two floats, including
100 Point2D or Extent2D, a list or a tuple.
102 Parameters
103 ----------
104 testCase : `unittest.TestCase`
105 test case the test is part of; an object supporting one method: fail(self, msgStr)
106 pair0 : pair of `float`
107 pair 0
108 pair1 : pair of `floats`
109 pair 1
110 maxDiff : `float`
111 maximum radial separation between the two points
112 msg : `str`
113 exception message prefix; details of the error are appended after ": "
115 Raises
116 ------
117 AssertionError
118 Raised if the radial difference is greater than ``maxDiff``
120 Notes
121 -----
122 .. warning::
124 Does not compare types, just compares values.
125 """
126 if len(pair0) != 2:
127 raise RuntimeError("len(pair0)=%s != 2" % (len(pair0),))
128 if len(pair1) != 2:
129 raise RuntimeError("len(pair1)=%s != 2" % (len(pair1),))
131 pairDiff = [float(pair1[i] - pair0[i]) for i in range(2)]
132 measDiff = math.hypot(*pairDiff)
133 if measDiff > maxDiff:
134 testCase.fail("%s: measured radial distance = %s > maxDiff = %s, pair0=(%r, %r), pair1=(%r, %r)" %
135 (msg, measDiff, maxDiff, pair0[0], pair0[1], pair1[0], pair1[1]))
138@lsst.utils.tests.inTestCase
139def assertPairListsAlmostEqual(testCase, list0, list1, maxDiff=1e-7, msg=None):
140 """Assert that two lists of Cartesian points are almost equal
142 Each point can be any indexable pair of two floats, including
143 Point2D or Extent2D, a list or a tuple.
145 Parameters
146 ----------
147 testCase : `unittest.TestCase`
148 test case the test is part of; an object supporting one method: fail(self, msgStr)
149 list0 : `list` of pairs of `float`
150 list of pairs 0
151 list1 : `list` of pairs of `float`
152 list of pairs 1
153 maxDiff : `float`
154 maximum radial separation between the two points
155 msg : `str`
156 additional information for the error message; appended after ": "
158 Raises
159 ------
160 AssertionError
161 Raised if the radial difference is greater than ``maxDiff``
163 Notes
164 -----
165 .. warning::
167 Does not compare types, just values.
168 """
169 testCase.assertEqual(len(list0), len(list1))
170 lenList1 = np.array([len(val) for val in list0])
171 lenList2 = np.array([len(val) for val in list1])
172 testCase.assertTrue(np.all(lenList1 == 2))
173 testCase.assertTrue(np.all(lenList2 == 2))
175 diffArr = np.array([(val0[0] - val1[0], val0[1] - val1[1])
176 for val0, val1 in zip(list0, list1)], dtype=float)
177 sepArr = np.hypot(diffArr[:, 0], diffArr[:, 1])
178 badArr = sepArr > maxDiff
179 if np.any(badArr):
180 maxInd = np.argmax(sepArr)
181 testCase.fail("PairLists differ in %s places; max separation is at %s: %s > %s%s" %
182 (np.sum(badArr), maxInd, sepArr[maxInd], maxDiff, extraMsg(msg)))
185@lsst.utils.tests.inTestCase
186def assertSpherePointsAlmostEqual(testCase, sp0, sp1, maxSep=0.001*arcseconds, msg=""):
187 r"""Assert that two `~lsst.geom.SpherePoint`\ s are almost equal
189 Parameters
190 ----------
191 testCase : `unittest.TestCase`
192 test case the test is part of; an object supporting one method:
193 fail(self, msgStr)
194 sp0 : `lsst.geom.SpherePoint`
195 SpherePoint 0
196 sp1 : `lsst.geom.SpherePoint`
197 SpherePoint 1
198 maxSep : `lsst.geom.Angle`
199 maximum separation
200 msg : `str`
201 extra information to be printed with any error message
203 Raises
204 ------
205 AssertionError
206 The SpherePoints are not equal.
207 """
208 if sp0.separation(sp1) > maxSep:
209 testCase.fail("Angular separation between %s and %s = %s\" > maxSep = %s\"%s" %
210 (sp0, sp1, sp0.separation(sp1).asArcseconds(), maxSep.asArcseconds(), extraMsg(msg)))
213@lsst.utils.tests.inTestCase
214def assertSpherePointListsAlmostEqual(testCase, splist0, splist1, maxSep=0.001*arcseconds, msg=None):
215 r"""Assert that two lists of `~lsst.geom.SpherePoint`\ s are almost equal
217 Parameters
218 ----------
219 testCase : `unittest.TestCase`
220 test case the test is part of; an object supporting one method:
221 fail(self, msgStr)
222 splist0 : `list` of `lsst.geom.SpherePoint`
223 list of SpherePoints 0
224 splist1 : `list` of `lsst.geom.SpherePoint`
225 list of SpherePoints 1
226 maxSep : `lsst.geom.Angle`
227 maximum separation
228 msg : `str`
229 exception message prefix; details of the error are appended after ": "
231 Raises
232 ------
233 AssertionError
234 The SpherePoint lists are not equal.
235 """
236 testCase.assertEqual(len(splist0), len(splist1), msg=msg)
237 sepArr = np.array([sp0.separation(sp1)
238 for sp0, sp1 in zip(splist0, splist1)])
239 badArr = sepArr > maxSep
240 if np.any(badArr):
241 maxInd = np.argmax(sepArr)
242 testCase.fail("SpherePointLists differ in %s places; max separation is at %s: %s\" > %s\"%s" %
243 (np.sum(badArr), maxInd, sepArr[maxInd].asArcseconds(),
244 maxSep.asArcseconds(), extraMsg(msg)))
247@lsst.utils.tests.inTestCase
248def assertBoxesAlmostEqual(testCase, box0, box1, maxDiff=1e-7, msg="Boxes differ"):
249 """Assert that two boxes (`~lsst.geom.Box2D` or `~lsst.geom.Box2I`) are
250 almost equal
252 Parameters
253 ----------
254 testCase : `unittest.TestCase`
255 test case the test is part of; an object supporting one method:
256 fail(self, msgStr)
257 box0 : `lsst.geom.Box2D` or `lsst.geom.Box2I`
258 box 0
259 box1 : `lsst.geom.Box2D` or `lsst.geom.Box2I`
260 box 1
261 maxDiff : `float`
262 maximum radial separation between the min points and max points
263 msg : `str`
264 exception message prefix; details of the error are appended after ": "
266 Raises
267 ------
268 AssertionError
269 Raised if the radial difference of the min points or max points is
270 greater than maxDiff
272 Notes
273 -----
274 .. warning::
276 Does not compare types, just compares values.
277 """
278 assertPairsAlmostEqual(testCase, box0.getMin(),
279 box1.getMin(), maxDiff=maxDiff, msg=msg + ": min")
280 assertPairsAlmostEqual(testCase, box0.getMax(),
281 box1.getMax(), maxDiff=maxDiff, msg=msg + ": max")