Coverage for tests/test_coordinates.py : 8%

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"""
23Tests for geom.Point, geom.Extent, geom.CoordinateExpr
25Run with:
26 ./Coordinates.py
27or
28 python
29 >>> import coordinates; coordinates.run()
30"""
32import unittest
33import math
34import operator
36import numpy as np
38import lsst.utils.tests
39import lsst.geom as geom
42class CoordinateTestCase:
43 """Mixin for some of the tests below.
44 """
46 def testAccessors(self):
47 for dtype, cls, rnd in self.classes:
48 vector1 = rnd()
49 p = cls(*vector1)
50 self.assertEqual(p.__class__, cls)
51 self.assertEqual(tuple(p), tuple(vector1))
52 self.assertEqual(tuple(p.clone()), tuple(p))
53 self.assertIsNot(p.clone(), p)
54 vector2 = rnd()
55 for n in range(cls.dimensions):
56 p[n] = vector2[n]
57 self.assertEqual(tuple(p), tuple(vector2))
59 def testComparison(self):
60 for dtype, cls, rnd in self.classes:
61 CoordinateExpr = geom.CoordinateExpr[cls.dimensions]
62 vector1 = rnd()
63 vector2 = rnd()
64 p1 = cls(*vector1)
65 p2 = cls(*vector2)
67 self.assertEqual(p1 == p2, all(p1.eq(p2)))
68 self.assertEqual(p1 != p2, any(p1.ne(p2)))
69 self.assertIsNotNone(p1) # should not throw
70 self.assertNotEqual(p1, tuple(p1)) # should not throw
72 self.assertEqual(
73 tuple(p1.eq(p2)),
74 tuple([v1 == v2 for v1, v2 in zip(vector1, vector2)]))
75 self.assertEqual(
76 tuple(p1.ne(p2)),
77 tuple([v1 != v2 for v1, v2 in zip(vector1, vector2)]))
78 self.assertEqual(
79 tuple(p1.lt(p2)),
80 tuple([v1 < v2 for v1, v2 in zip(vector1, vector2)]))
81 self.assertEqual(
82 tuple(p1.le(p2)),
83 tuple([v1 <= v2 for v1, v2 in zip(vector1, vector2)]))
84 self.assertEqual(
85 tuple(p1.gt(p2)),
86 tuple([v1 > v2 for v1, v2 in zip(vector1, vector2)]))
87 self.assertEqual(
88 tuple(p1.ge(p2)),
89 tuple([v1 >= v2 for v1, v2 in zip(vector1, vector2)]))
90 self.assertEqual(type(p1.eq(p2)), CoordinateExpr)
91 self.assertEqual(type(p1.ne(p2)), CoordinateExpr)
92 self.assertEqual(type(p1.lt(p2)), CoordinateExpr)
93 self.assertEqual(type(p1.le(p2)), CoordinateExpr)
94 self.assertEqual(type(p1.gt(p2)), CoordinateExpr)
95 self.assertEqual(type(p1.ge(p2)), CoordinateExpr)
96 scalar = dtype(rnd()[0])
97 self.assertEqual(tuple(p1.eq(scalar)),
98 tuple([v1 == scalar for v1 in vector1]))
99 self.assertEqual(tuple(p1.ne(scalar)),
100 tuple([v1 != scalar for v1 in vector1]))
101 self.assertEqual(tuple(p1.lt(scalar)),
102 tuple([v1 < scalar for v1 in vector1]))
103 self.assertEqual(tuple(p1.le(scalar)),
104 tuple([v1 <= scalar for v1 in vector1]))
105 self.assertEqual(tuple(p1.gt(scalar)),
106 tuple([v1 > scalar for v1 in vector1]))
107 self.assertEqual(tuple(p1.ge(scalar)),
108 tuple([v1 >= scalar for v1 in vector1]))
109 self.assertEqual(type(p1.eq(scalar)), CoordinateExpr)
110 self.assertEqual(type(p1.ne(scalar)), CoordinateExpr)
111 self.assertEqual(type(p1.lt(scalar)), CoordinateExpr)
112 self.assertEqual(type(p1.le(scalar)), CoordinateExpr)
113 self.assertEqual(type(p1.gt(scalar)), CoordinateExpr)
114 self.assertEqual(type(p1.ge(scalar)), CoordinateExpr)
117class PointTestCase(CoordinateTestCase, lsst.utils.tests.TestCase):
118 """A test case for Point"""
120 def setUp(self):
121 np.random.seed(1)
122 self.classes = [
123 (float, geom.Point2D, lambda: [float(x)
124 for x in np.random.randn(2)]),
125 (int, geom.Point2I, lambda: [int(x)
126 for x in np.random.randint(-5, 5, 2)]),
127 (float, geom.Point3D, lambda: [float(x)
128 for x in np.random.randn(3)]),
129 (int, geom.Point3I, lambda: [int(x)
130 for x in np.random.randint(-5, 5, 3)]),
131 ]
133 def testConstructors(self):
134 # test 2-d
135 e1 = geom.Point2I(1, 2)
136 e2 = geom.Point2I(e1)
137 self.assertAlmostEqual(tuple(e1), tuple(e2))
139 e1 = geom.Point2D(1.2, 3.4)
140 e2 = geom.Point2D(e1)
141 self.assertAlmostEqual(tuple(e1), tuple(e2))
143 e1 = geom.Point2I(1, 3)
144 e2 = geom.Point2D(e1)
145 self.assertAlmostEqual(tuple(e1), tuple(e2))
147 # test 3-d
148 e1 = geom.Point3I(1, 2, 3)
149 e2 = geom.Point3I(e1)
150 self.assertAlmostEqual(tuple(e1), tuple(e2))
152 e1 = geom.Point3D(1.2, 3.4, 5.6)
153 e2 = geom.Point3D(e1)
154 self.assertAlmostEqual(tuple(e1), tuple(e2))
156 e1 = geom.Point3I(1, 2, 3)
157 e2 = geom.Point3D(e1)
158 self.assertAlmostEqual(tuple(e1), tuple(e2))
160 # test rounding to integral coordinates
161 e1 = geom.Point2D(1.2, 3.4)
162 e2 = geom.Point2I(e1)
163 self.assertAlmostEqual(
164 tuple([math.floor(v + 0.5) for v in e1]), tuple(e2))
166 e1 = geom.Point3D(1.2, 3.4, 5.6)
167 e2 = geom.Point3I(e1)
168 self.assertAlmostEqual(
169 tuple([math.floor(v + 0.5) for v in e1]), tuple(e2))
172class ExtentTestCase(CoordinateTestCase, lsst.utils.tests.TestCase):
173 """A test case for Extent"""
175 def setUp(self):
176 np.random.seed(1)
177 self.classes = [
178 (float, geom.Extent2D, lambda: [float(x)
179 for x in np.random.randn(2)]),
180 (int, geom.Extent2I, lambda: [int(x)
181 for x in np.random.randint(-5, 5, 2)]),
182 (float, geom.Extent3D, lambda: [float(x)
183 for x in np.random.randn(3)]),
184 (int, geom.Extent3I, lambda: [int(x)
185 for x in np.random.randint(-5, 5, 3)]),
186 ]
188 def testRounding(self):
189 e1 = geom.Extent2D(1.2, -3.4)
190 self.assertEqual(e1.floor(), geom.Extent2I(1, -4))
191 self.assertEqual(e1.ceil(), geom.Extent2I(2, -3))
192 self.assertEqual(e1.truncate(), geom.Extent2I(1, -3))
194 def testConstructors(self):
195 # test extent from extent 2-d
196 e1 = geom.Extent2I(1, 2)
197 e2 = geom.Extent2I(e1)
198 self.assertAlmostEqual(tuple(e1), tuple(e2))
200 e1 = geom.Extent2D(1.2, 3.4)
201 e2 = geom.Extent2D(e1)
202 self.assertAlmostEqual(tuple(e1), tuple(e2))
204 e1 = geom.Extent2I(1, 2)
205 e2 = geom.Extent2D(e1)
206 self.assertAlmostEqual(tuple(e1), tuple(e2))
208 # test extent from extent 3-d
209 e1 = geom.Extent3I(1, 2, 3)
210 e2 = geom.Extent3I(e1)
211 self.assertAlmostEqual(tuple(e1), tuple(e2))
213 e1 = geom.Extent3D(1.2, 3.4, 5.6)
214 e2 = geom.Extent3D(e1)
215 self.assertAlmostEqual(tuple(e1), tuple(e2))
217 e1 = geom.Extent3I(1, 2, 3)
218 e2 = geom.Extent3D(e1)
219 self.assertAlmostEqual(tuple(e1), tuple(e2))
221 # test extent from point 2-d
222 e1 = geom.Point2I(1, 2)
223 e2 = geom.Extent2I(e1)
224 self.assertAlmostEqual(tuple(e1), tuple(e2))
226 e1 = geom.Point2D(1.2, 3.4)
227 e2 = geom.Extent2D(e1)
228 self.assertAlmostEqual(tuple(e1), tuple(e2))
230 e1 = geom.Point2I(1, 2)
231 e2 = geom.Extent2D(e1)
232 self.assertAlmostEqual(tuple(e1), tuple(e2))
234 # test extent from point 3-d
235 e1 = geom.Point3I(1, 2, 3)
236 e2 = geom.Extent3I(e1)
237 self.assertAlmostEqual(tuple(e1), tuple(e2))
239 e1 = geom.Point3D(1.2, 3.4, 5.6)
240 e2 = geom.Extent3D(e1)
241 self.assertAlmostEqual(tuple(e1), tuple(e2))
243 e1 = geom.Point3I(1, 2, 3)
244 e2 = geom.Extent3D(e1)
245 self.assertAlmostEqual(tuple(e1), tuple(e2))
248class OperatorTestCase(lsst.utils.tests.TestCase):
250 @staticmethod
251 def makeRandom(cls):
252 """Make a random Point, Extent, int, or float of the given type."""
253 if cls is int:
254 v = 0
255 while v == 0:
256 v = int(np.random.randn()*10)
257 elif cls is float:
258 v = float(np.random.randn()*10)
259 else:
260 v = cls()
261 t = type(v[0])
262 for i in range(len(v)):
263 while v[i] == 0:
264 v[i] = t(np.random.randn()*10)
265 return v
267 def checkOperator(self, op, lhs, rhs, expected, inPlace=False):
268 """Check that the type and result of applying operator 'op' to types 'lhs' and 'rhs'
269 yield a result of type 'expected', and that the computed value is correct. If
270 'expected' is an Exception subclass, instead check that attempting to apply the
271 operator raises that exception.
272 """
273 v1 = self.makeRandom(lhs)
274 v2 = self.makeRandom(rhs)
275 if issubclass(expected, Exception):
276 with self.assertRaises(expected):
277 op(v1, v2)
278 else:
279 check = op(np.array(v1), np.array(v2))
280 result = op(v1, v2)
281 if type(result) != expected:
282 self.fail("%s(%s, %s): expected %s, got %s" %
283 (op.__name__, lhs.__name__, rhs.__name__,
284 expected.__name__, type(result).__name__))
285 if not np.allclose(result, check):
286 self.fail("%s(%s, %s): expected %s, got %s" %
287 (op.__name__, lhs.__name__, rhs.__name__, tuple(check), tuple(result)))
288 if inPlace and result is not v1:
289 self.fail("%s(%s, %s): result is not self" %
290 (op.__name__, lhs.__name__, rhs.__name__))
292 def testPointAsExtent(self):
293 for n in (2, 3):
294 for t in (int, float):
295 p = self.makeRandom(geom.Point[t, n])
296 e = p.asExtent()
297 self.assertEqual(type(e), geom.Extent[t, n])
298 self.assertFloatsAlmostEqual(
299 np.array(p), np.array(e), rtol=0.0, atol=0.0)
301 def testExtentAsPoint(self):
302 for n in (2, 3):
303 for t in (int, float):
304 e = self.makeRandom(geom.Extent[t, n])
305 p = e.asPoint()
306 self.assertEqual(type(p), geom.Point[t, n])
307 self.assertFloatsAlmostEqual(
308 np.array(p), np.array(e), rtol=0.0, atol=0.0)
310 def testUnaryOperators(self):
311 for n in (2, 3):
312 for t in (int, float):
313 e1 = self.makeRandom(geom.Extent[t, n])
314 e2 = +e1
315 self.assertEqual(type(e1), type(e2))
316 self.assertFloatsAlmostEqual(
317 np.array(e1), np.array(e2), rtol=0.0, atol=0.0)
318 e3 = -e1
319 self.assertEqual(type(e1), type(e3))
320 self.assertFloatsAlmostEqual(
321 np.array(e3), -np.array(e1), rtol=0.0, atol=0.0)
323 def testBinaryOperators(self):
324 for n in (2, 3):
325 pD = geom.Point[float, n]
326 pI = geom.Point[int, n]
327 eD = geom.Extent[float, n]
328 eI = geom.Extent[int, n]
329 # Addition
330 self.checkOperator(operator.add, pD, pD, TypeError)
331 self.checkOperator(operator.add, pD, pI, TypeError)
332 self.checkOperator(operator.add, pD, eD, pD)
333 self.checkOperator(operator.add, pD, eI, pD)
334 self.checkOperator(operator.add, pI, pD, TypeError)
335 self.checkOperator(operator.add, pI, pI, TypeError)
336 self.checkOperator(operator.add, pI, eD, pD)
337 self.checkOperator(operator.add, pI, eI, pI)
338 self.checkOperator(operator.add, eD, pD, pD)
339 self.checkOperator(operator.add, eD, pI, pD)
340 self.checkOperator(operator.add, eD, eI, eD)
341 self.checkOperator(operator.add, eD, eD, eD)
342 self.checkOperator(operator.add, eI, pD, pD)
343 self.checkOperator(operator.add, eI, pI, pI)
344 self.checkOperator(operator.add, eI, eD, eD)
345 self.checkOperator(operator.add, eI, eI, eI)
346 # Subtraction
347 self.checkOperator(operator.sub, pD, pD, eD)
348 self.checkOperator(operator.sub, pD, pI, eD)
349 self.checkOperator(operator.sub, pD, eD, pD)
350 self.checkOperator(operator.sub, pD, eI, pD)
351 self.checkOperator(operator.sub, pI, pD, eD)
352 self.checkOperator(operator.sub, pI, pI, eI)
353 self.checkOperator(operator.sub, pI, eD, pD)
354 self.checkOperator(operator.sub, pI, eI, pI)
355 self.checkOperator(operator.sub, eD, pD, TypeError)
356 self.checkOperator(operator.sub, eD, pI, TypeError)
357 self.checkOperator(operator.sub, eD, eD, eD)
358 self.checkOperator(operator.sub, eD, eI, eD)
359 self.checkOperator(operator.sub, eI, pD, TypeError)
360 self.checkOperator(operator.sub, eI, pI, TypeError)
361 self.checkOperator(operator.sub, eI, eD, eD)
362 self.checkOperator(operator.sub, eI, eI, eI)
363 # Multiplication
364 self.checkOperator(operator.mul, eD, int, eD)
365 self.checkOperator(operator.mul, eD, float, eD)
366 self.checkOperator(operator.mul, eI, int, eI)
367 self.checkOperator(operator.mul, eI, float, eD)
368 self.checkOperator(operator.mul, int, eD, eD)
369 self.checkOperator(operator.mul, float, eD, eD)
370 self.checkOperator(operator.mul, int, eI, eI)
371 self.checkOperator(operator.mul, float, eI, eD)
372 # New-Style Division
373 self.checkOperator(operator.truediv, eD, int, eD)
374 self.checkOperator(operator.truediv, eD, float, eD)
375 self.checkOperator(operator.truediv, eI, int, eD)
376 self.checkOperator(operator.truediv, eI, float, eD)
377 # Floor Division
378 self.checkOperator(operator.floordiv, eD, int, TypeError)
379 self.checkOperator(operator.floordiv, eD, float, TypeError)
380 self.checkOperator(operator.floordiv, eI, int, eI)
381 self.checkOperator(operator.floordiv, eI, float, TypeError)
383 def testInPlaceOperators(self):
384 for n in (2, 3):
385 pD = geom.Point[float, n]
386 pI = geom.Point[int, n]
387 eD = geom.Extent[float, n]
388 eI = geom.Extent[int, n]
389 # Addition
390 self.checkOperator(operator.iadd, pD, pD, TypeError)
391 self.checkOperator(operator.iadd, pD, pI, TypeError)
392 self.checkOperator(operator.iadd, pD, eD, pD, inPlace=True)
393 self.checkOperator(operator.iadd, pD, eI, pD, inPlace=True)
394 self.checkOperator(operator.iadd, pI, pD, TypeError)
395 self.checkOperator(operator.iadd, pI, pI, TypeError)
396 self.checkOperator(operator.iadd, pI, eD, TypeError)
397 self.checkOperator(operator.iadd, pI, eI, pI, inPlace=True)
398 self.checkOperator(operator.iadd, eD, pD, TypeError)
399 self.checkOperator(operator.iadd, eD, pI, TypeError)
400 self.checkOperator(operator.iadd, eD, eI, eD, inPlace=True)
401 self.checkOperator(operator.iadd, eD, eD, eD, inPlace=True)
402 self.checkOperator(operator.iadd, eI, pD, TypeError)
403 self.checkOperator(operator.iadd, eI, pI, TypeError)
404 self.checkOperator(operator.iadd, eI, eD, TypeError)
405 self.checkOperator(operator.iadd, eI, eI, eI, inPlace=True)
406 # Subtraction
407 self.checkOperator(operator.isub, pD, pD, TypeError)
408 self.checkOperator(operator.isub, pD, pI, TypeError)
409 self.checkOperator(operator.isub, pD, eD, pD, inPlace=True)
410 self.checkOperator(operator.isub, pD, eI, pD, inPlace=True)
411 self.checkOperator(operator.isub, pI, pD, TypeError)
412 self.checkOperator(operator.isub, pI, pI, TypeError)
413 self.checkOperator(operator.isub, pI, eD, TypeError)
414 self.checkOperator(operator.isub, pI, eI, pI, inPlace=True)
415 self.checkOperator(operator.isub, eD, pD, TypeError)
416 self.checkOperator(operator.isub, eD, pI, TypeError)
417 self.checkOperator(operator.isub, eD, eD, eD, inPlace=True)
418 self.checkOperator(operator.isub, eD, eI, eD, inPlace=True)
419 self.checkOperator(operator.isub, eI, pD, TypeError)
420 self.checkOperator(operator.isub, eI, pI, TypeError)
421 self.checkOperator(operator.isub, eI, eD, TypeError)
422 self.checkOperator(operator.isub, eI, eI, eI, inPlace=True)
423 # Multiplication
424 self.checkOperator(operator.imul, eD, int, eD, inPlace=True)
425 self.checkOperator(operator.imul, eD, float, eD, inPlace=True)
426 self.checkOperator(operator.imul, eI, int, eI, inPlace=True)
427 self.checkOperator(operator.imul, eI, float, TypeError)
428 # New-Style Division
429 self.checkOperator(operator.itruediv, eD, int, eD, inPlace=True)
430 self.checkOperator(operator.itruediv, eD, float, eD, inPlace=True)
431 self.checkOperator(operator.itruediv, eI, int, TypeError)
432 self.checkOperator(operator.itruediv, eI, float, TypeError)
433 # Floor Division
434 self.checkOperator(operator.floordiv, eD, int, TypeError)
435 self.checkOperator(operator.floordiv, eD, float, TypeError)
436 self.checkOperator(operator.floordiv, eI, int, eI)
437 self.checkOperator(operator.floordiv, eI, float, TypeError)
440class MemoryTester(lsst.utils.tests.MemoryTestCase):
441 pass
444def setup_module(module):
445 lsst.utils.tests.init()
448if __name__ == "__main__": 448 ↛ 449line 448 didn't jump to line 449, because the condition on line 448 was never true
449 lsst.utils.tests.init()
450 unittest.main()