LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
testUtils.py
Go to the documentation of this file.
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#
21
22"""Utilities that should be imported into the lsst.geom namespace when
23lsst.geom is used
24
25In the case of the assert functions, importing them makes them available in lsst.utils.tests.TestCase
26"""
27__all__ = []
28
29import math
30
31import numpy as np
32
34from ._geom import arcseconds
35
36
37def extraMsg(msg):
38 """Format extra error message, if any
39 """
40 if msg:
41 return ": " + msg
42 return ""
43
44
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.
50
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.
53
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
68 - if True then wrap is ignored, e.g. 0 and 360 degrees are considered
69 equal
70 - if False then wrap matters, e.g. 0 and 360 degrees are considered
71 different
72
73 msg : `str`
74 exception message prefix; details of the error are appended after ": "
75
76 Raises
77 ------
78 AssertionError
79 Raised if the difference is greater than ``maxDiff``
80 """
81 isNan0 = math.isnan(ang0.asRadians())
82 isNan1 = math.isnan(ang1.asRadians())
83 if isNan0 and isNan1:
84 return
85 if isNan0:
86 testCase.fail("ang0 is NaN")
87 if isNan1:
88 testCase.fail("ang1 is NaN")
89 measDiff = ang1 - ang0
90 if ignoreWrap:
91 measDiff = measDiff.wrapCtr()
92 if abs(measDiff) > maxDiff:
93 testCase.fail("%s: measured difference %s arcsec > max allowed %s arcsec" %
94 (msg, measDiff.asArcseconds(), maxDiff.asArcseconds()))
95
96
97@lsst.utils.tests.inTestCase
98def assertPairsAlmostEqual(testCase, pair0, pair1, maxDiff=1e-7, msg="Pairs differ"):
99 """Assert that two Cartesian points are almost equal.
100
101 Each point can be any indexable pair of two floats, including
102 Point2D or Extent2D, a list or a tuple.
103
104 Parameters
105 ----------
106 testCase : `unittest.TestCase`
107 test case the test is part of; an object supporting one method: fail(self, msgStr)
108 pair0 : pair of `float`
109 pair 0
110 pair1 : pair of `floats`
111 pair 1
112 maxDiff : `float`
113 maximum radial separation between the two points
114 msg : `str`
115 exception message prefix; details of the error are appended after ": "
116
117 Raises
118 ------
119 AssertionError
120 Raised if the radial difference is greater than ``maxDiff``
121
122 Notes
123 -----
124 .. warning::
125
126 Does not compare types, just compares values.
127 """
128 if len(pair0) != 2:
129 raise RuntimeError("len(pair0)=%s != 2" % (len(pair0),))
130 if len(pair1) != 2:
131 raise RuntimeError("len(pair1)=%s != 2" % (len(pair1),))
132
133 pairDiff = [float(pair1[i] - pair0[i]) for i in range(2)]
134 measDiff = math.hypot(*pairDiff)
135 if measDiff > maxDiff:
136 testCase.fail("%s: measured radial distance = %s > maxDiff = %s, pair0=(%r, %r), pair1=(%r, %r)" %
137 (msg, measDiff, maxDiff, pair0[0], pair0[1], pair1[0], pair1[1]))
138
139
140@lsst.utils.tests.inTestCase
141def assertPairListsAlmostEqual(testCase, list0, list1, maxDiff=1e-7, msg=None):
142 """Assert that two lists of Cartesian points are almost equal
143
144 Each point can be any indexable pair of two floats, including
145 Point2D or Extent2D, a list or a tuple.
146
147 Parameters
148 ----------
149 testCase : `unittest.TestCase`
150 test case the test is part of; an object supporting one method: fail(self, msgStr)
151 list0 : `list` of pairs of `float`
152 list of pairs 0
153 list1 : `list` of pairs of `float`
154 list of pairs 1
155 maxDiff : `float`
156 maximum radial separation between the two points
157 msg : `str`
158 additional information for the error message; appended after ": "
159
160 Raises
161 ------
162 AssertionError
163 Raised if the radial difference is greater than ``maxDiff``
164
165 Notes
166 -----
167 .. warning::
168
169 Does not compare types, just values.
170 """
171 testCase.assertEqual(len(list0), len(list1))
172 lenList1 = np.array([len(val) for val in list0])
173 lenList2 = np.array([len(val) for val in list1])
174 testCase.assertTrue(np.all(lenList1 == 2))
175 testCase.assertTrue(np.all(lenList2 == 2))
176
177 diffArr = np.array([(val0[0] - val1[0], val0[1] - val1[1])
178 for val0, val1 in zip(list0, list1)], dtype=float)
179 sepArr = np.hypot(diffArr[:, 0], diffArr[:, 1])
180 badArr = sepArr > maxDiff
181 if np.any(badArr):
182 maxInd = np.argmax(sepArr)
183 testCase.fail("PairLists differ in %s places; max separation is at %s: %s > %s%s" %
184 (np.sum(badArr), maxInd, sepArr[maxInd], maxDiff, extraMsg(msg)))
185
186
187@lsst.utils.tests.inTestCase
188def assertSpherePointsAlmostEqual(testCase, sp0, sp1, maxSep=0.001*arcseconds, msg=""):
189 r"""Assert that two `~lsst.geom.SpherePoint`\ s are almost equal
190
191 Parameters
192 ----------
193 testCase : `unittest.TestCase`
194 test case the test is part of; an object supporting one method:
195 fail(self, msgStr)
196 sp0 : `lsst.geom.SpherePoint`
197 SpherePoint 0
198 sp1 : `lsst.geom.SpherePoint`
199 SpherePoint 1
200 maxSep : `lsst.geom.Angle`
201 maximum separation
202 msg : `str`
203 extra information to be printed with any error message
204
205 Raises
206 ------
207 AssertionError
208 The SpherePoints are not equal.
209 """
210 if sp0.separation(sp1) > maxSep:
211 testCase.fail("Angular separation between %s and %s = %s\" > maxSep = %s\"%s" %
212 (sp0, sp1, sp0.separation(sp1).asArcseconds(), maxSep.asArcseconds(), extraMsg(msg)))
213
214
215@lsst.utils.tests.inTestCase
216def assertSpherePointListsAlmostEqual(testCase, splist0, splist1, maxSep=0.001*arcseconds, msg=None):
217 r"""Assert that two lists of `~lsst.geom.SpherePoint`\ s are almost equal
218
219 Parameters
220 ----------
221 testCase : `unittest.TestCase`
222 test case the test is part of; an object supporting one method:
223 fail(self, msgStr)
224 splist0 : `list` of `lsst.geom.SpherePoint`
225 list of SpherePoints 0
226 splist1 : `list` of `lsst.geom.SpherePoint`
227 list of SpherePoints 1
228 maxSep : `lsst.geom.Angle`
229 maximum separation
230 msg : `str`
231 exception message prefix; details of the error are appended after ": "
232
233 Raises
234 ------
235 AssertionError
236 The SpherePoint lists are not equal.
237 """
238 testCase.assertEqual(len(splist0), len(splist1), msg=msg)
239 sepArr = np.array([sp0.separation(sp1)
240 for sp0, sp1 in zip(splist0, splist1)])
241 badArr = sepArr > maxSep
242 if np.any(badArr):
243 maxInd = np.argmax(sepArr)
244 testCase.fail("SpherePointLists differ in %s places; max separation is at %s: %s\" > %s\"%s" %
245 (np.sum(badArr), maxInd, sepArr[maxInd].asArcseconds(),
246 maxSep.asArcseconds(), extraMsg(msg)))
247
248
249@lsst.utils.tests.inTestCase
250def assertBoxesAlmostEqual(testCase, box0, box1, maxDiff=1e-7, msg="Boxes differ"):
251 """Assert that two boxes (`~lsst.geom.Box2D` or `~lsst.geom.Box2I`) are
252 almost equal
253
254 Parameters
255 ----------
256 testCase : `unittest.TestCase`
257 test case the test is part of; an object supporting one method:
258 fail(self, msgStr)
259 box0 : `lsst.geom.Box2D` or `lsst.geom.Box2I`
260 box 0
261 box1 : `lsst.geom.Box2D` or `lsst.geom.Box2I`
262 box 1
263 maxDiff : `float`
264 maximum radial separation between the min points and max points
265 msg : `str`
266 exception message prefix; details of the error are appended after ": "
267
268 Raises
269 ------
270 AssertionError
271 Raised if the radial difference of the min points or max points is
272 greater than maxDiff
273
274 Notes
275 -----
276 .. warning::
277
278 Does not compare types, just compares values.
279 """
280 assertPairsAlmostEqual(testCase, box0.getMin(),
281 box1.getMin(), maxDiff=maxDiff, msg=msg + ": min")
282 assertPairsAlmostEqual(testCase, box0.getMax(),
283 box1.getMax(), maxDiff=maxDiff, msg=msg + ": max")
assertPairsAlmostEqual(testCase, pair0, pair1, maxDiff=1e-7, msg="Pairs differ")
Definition testUtils.py:98
assertSpherePointListsAlmostEqual(testCase, splist0, splist1, maxSep=0.001 *arcseconds, msg=None)
Definition testUtils.py:216
assertBoxesAlmostEqual(testCase, box0, box1, maxDiff=1e-7, msg="Boxes differ")
Definition testUtils.py:250
assertAnglesAlmostEqual(testCase, ang0, ang1, maxDiff=0.001 *arcseconds, ignoreWrap=True, msg="Angles differ")
Definition testUtils.py:47
assertSpherePointsAlmostEqual(testCase, sp0, sp1, maxSep=0.001 *arcseconds, msg="")
Definition testUtils.py:188
assertPairListsAlmostEqual(testCase, list0, list1, maxDiff=1e-7, msg=None)
Definition testUtils.py:141