Coverage for tests/test_spatialCell.py: 17%
170 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-13 16:27 -0700
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-13 16:27 -0700
1# This file is part of afw.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22"""
23Tests for SpatialCell
25Run with:
26 python test_spatialCell.py
27or
28 pytest test_spatialCell.py
29"""
30import unittest
32import lsst.utils.tests
33import lsst.pex.exceptions as pexExcept
34import lsst.geom
35import lsst.afw.math as afwMath
36from lsst.afw.image import LOCAL
39def getFlux(x):
40 return 1000 - 10*x
43class SpatialCellTestCase(unittest.TestCase):
44 """A test case for SpatialCell"""
46 def setUp(self):
47 candidateList = []
48 self.nCandidate = 5
49 for i in (0, 1, 4, 3, 2): # must be all numbers in range(self.nCandidate)
50 x, y = i, 5*i
51 candidateList.append(afwMath.TestCandidate(x, y, getFlux(x)))
53 self.cell = afwMath.SpatialCell("Test", lsst.geom.Box2I(), candidateList)
54 self.assertEqual(self.cell.getLabel(), "Test")
56 def tearDown(self):
57 del self.cell
59 def testCandidateList(self):
60 """Check that we can retrieve candidates, and that they are sorted by ranking"""
61 self.assertEqual(self.cell[0].getXCenter(), 0)
62 self.assertEqual(self.cell[1].getXCenter(), 1)
63 self.assertEqual(self.cell[1].getYCenter(), 5)
65 def testBuildCandidateListByInsertion(self):
66 """Build a candidate list by inserting candidates"""
68 self.cell = afwMath.SpatialCell("Test", lsst.geom.Box2I())
70 for x, y in ([5, 0], [1, 1], [2, 2], [0, 0], [4, 4], [3, 4]):
71 self.cell.insertCandidate(afwMath.TestCandidate(x, y, getFlux(x)))
73 self.assertEqual(self.cell[0].getXCenter(), 0)
75 def testIterators(self):
76 """Test the SpatialCell iterators"""
78 #
79 # Count the candidates
80 #
81 self.assertEqual(self.cell.size(), self.nCandidate)
82 self.assertEqual(self.cell.end() - self.cell.begin(), self.nCandidate)
84 ptr = self.cell.begin()
85 ptr.__incr__()
86 self.assertEqual(self.cell.end() - ptr, self.nCandidate - 1)
88 self.assertEqual(ptr - self.cell.begin(), 1)
89 #
90 # Now label one candidate as bad
91 #
92 self.cell[2].setStatus(afwMath.SpatialCellCandidate.BAD)
94 self.assertEqual(self.cell.size(), self.nCandidate - 1)
95 self.assertEqual(self.cell.end() - self.cell.begin(),
96 self.nCandidate - 1)
98 self.cell.setIgnoreBad(False)
99 self.assertEqual(self.cell.size(), self.nCandidate)
100 self.assertEqual(self.cell.end() - self.cell.begin(), self.nCandidate)
102 def testGetCandidateById(self):
103 """Check that we can lookup candidates by ID"""
104 id = self.cell[1].getId()
105 self.assertEqual(self.cell.getCandidateById(id).getId(), id)
107 self.assertEqual(self.cell.getCandidateById(-1, True), None)
108 with self.assertRaises(pexExcept.NotFoundError):
109 self.cell.getCandidateById(-1)
111 def testSetIteratorBad(self):
112 """Setting a candidate BAD shouldn't stop us seeing the rest of the candidates"""
113 i = 0
114 for cand in self.cell:
115 if i == 1:
116 cand.setStatus(afwMath.SpatialCellCandidate.BAD)
117 i += 1
119 self.assertEqual(i, self.nCandidate)
121 def testSortCandidates(self):
122 """Check that we can update ratings and maintain order"""
123 ratings0 = [cand.getCandidateRating() for cand in self.cell]
124 #
125 # Change a rating
126 #
127 i, flux = 1, 9999
128 self.cell[i].setCandidateRating(flux)
129 ratings0[i] = flux
131 self.assertEqual(ratings0, [cand.getCandidateRating()
132 for cand in self.cell])
134 self.cell.sortCandidates()
135 self.assertNotEqual(
136 ratings0, [cand.getCandidateRating() for cand in self.cell])
138 def sortKey(a):
139 return -a
140 self.assertEqual(sorted(ratings0, key=sortKey),
141 [cand.getCandidateRating() for cand in self.cell])
144class SpatialCellSetTestCase(unittest.TestCase):
145 """A test case for SpatialCellSet"""
147 def setUp(self):
148 self.cellSet = afwMath.SpatialCellSet(lsst.geom.Box2I(
149 lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(501, 501)), 260, 200)
151 def makeTestCandidateCellSet(self):
152 """Populate a SpatialCellSet"""
154 if False: # Print the bboxes for the cells
155 print()
156 for i in range(len(self.cellSet.getCellList())):
157 cell = self.cellSet.getCellList()[i]
158 print(i, f"{cell.getBBox().getMinX():3d},{cell.getBBox().getMinY():3d} -- "
159 f"{cell.getBBox().getMaxX():3d},{cell.getBBox().getMaxY():3d}",
160 cell.getLabel())
161 self.assertEqual(len(self.cellSet.getCellList()), 6)
163 # number of candidates
164 self.NTestCandidates = 0
165 for x, y in ([5, 0], [1, 1], [2, 2], [0, 0], [4, 4], [3, 4]): # all in cell0
166 self.cellSet.insertCandidate(afwMath.TestCandidate(x, y, -x))
167 self.NTestCandidates += 1
169 # in cell1
170 self.cellSet.insertCandidate(afwMath.TestCandidate(305, 0, 100))
171 self.NTestCandidates += 1
172 # the top right corner of cell5
173 self.cellSet.insertCandidate(afwMath.TestCandidate(500, 500, 100))
174 self.NTestCandidates += 1
176 def tearDown(self):
177 del self.cellSet
179 def testNoCells(self):
180 """Test that we check for a request to make a SpatialCellSet with no cells"""
181 def tst():
182 afwMath.SpatialCellSet(lsst.geom.Box2I(
183 lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(500, 500)), 0, 3)
185 self.assertRaises(pexExcept.LengthError, tst)
187 def testInsertCandidate(self):
188 """Insert candidates into the SpatialCellSet"""
190 self.makeTestCandidateCellSet()
192 def tst():
193 # Doesn't fit
194 self.cellSet.insertCandidate(afwMath.TestCandidate(501, 501, 100))
195 self.assertRaises(pexExcept.OutOfRangeError, tst)
196 #
197 # OK, the SpatialCellList is populated
198 #
199 cell0 = self.cellSet.getCellList()[0]
200 self.assertFalse(cell0.empty())
201 self.assertEqual(cell0[0].getXCenter(), 0.0)
203 self.assertEqual(self.cellSet.getCellList()[1][0].getXCenter(), 305.0)
205 self.assertTrue(self.cellSet.getCellList()[2].empty())
207 def tst1():
208 self.cellSet.getCellList()[2][0]
209 self.assertRaises(IndexError, tst1)
211 def tst2():
212 self.cellSet.getCellList()[2].begin().__deref__()
213 self.assertRaises(pexExcept.NotFoundError, tst2)
215 self.assertFalse(self.cellSet.getCellList()[5].empty())
217 def testVisitor(self):
218 """Test the candidate visitors"""
220 self.makeTestCandidateCellSet()
222 visitor = afwMath.TestCandidateVisitor()
224 self.cellSet.visitCandidates(visitor)
225 self.assertEqual(visitor.getN(), self.NTestCandidates)
227 self.cellSet.visitCandidates(visitor, 1)
228 self.assertEqual(visitor.getN(), 3)
230 def testGetCandidateById(self):
231 """Check that we can lookup candidates by ID"""
233 self.makeTestCandidateCellSet()
234 #
235 # OK, the SpatialCellList is populated
236 #
237 id = self.cellSet.getCellList()[0][1].getId()
238 self.assertEqual(self.cellSet.getCandidateById(id).getId(), id)
240 def tst():
241 self.cellSet.getCandidateById(-1) # non-existent ID
243 self.assertEqual(self.cellSet.getCandidateById(-1, True), None)
244 self.assertRaises(pexExcept.NotFoundError, tst)
246 def testSpatialCell(self):
247 dx, dy, sx, sy = 100, 100, 50, 50
248 for x0, y0 in [(0, 0), (100, 100)]:
249 # only works for tests where dx,dx is some multiple of sx,sy
250 assert(dx//sx == float(dx)/float(sx))
251 assert(dy//sy == float(dy)/float(sy))
253 bbox = lsst.geom.Box2I(lsst.geom.Point2I(x0, y0),
254 lsst.geom.Extent2I(dx, dy))
255 cset = afwMath.SpatialCellSet(bbox, sx, sy)
256 for cell in cset.getCellList():
257 label = cell.getLabel()
258 nx, ny = [int(z) for z in label.split()[1].split('x')]
260 cbbox = cell.getBBox()
262 self.assertEqual(cbbox.getMinX(), nx*sx + x0)
263 self.assertEqual(cbbox.getMinY(), ny*sy + y0)
264 self.assertEqual(cbbox.getMaxX(), (nx+1)*sx + x0 - 1)
265 self.assertEqual(cbbox.getMaxY(), (ny+1)*sy + y0 - 1)
267 def testSortCandidates(self):
268 """Check that we can update ratings and maintain order"""
270 self.makeTestCandidateCellSet()
272 cell1 = self.cellSet.getCellList()[0]
273 self.assertFalse(cell1.empty())
275 ratings0 = [cand.getCandidateRating() for cand in cell1]
276 #
277 # Change a rating
278 #
279 i, flux = 1, 9999
280 cell1[i].setCandidateRating(flux)
281 ratings0[i] = flux
283 self.assertEqual(
284 ratings0, [cand.getCandidateRating() for cand in cell1])
286 self.cellSet.sortCandidates()
287 self.assertNotEqual(
288 ratings0, [cand.getCandidateRating() for cand in cell1])
290 def sortKey(a):
291 return -a
292 self.assertEqual(sorted(ratings0, key=sortKey),
293 [cand.getCandidateRating() for cand in cell1])
296class TestImageCandidateCase(unittest.TestCase):
297 """A test case for TestImageCandidate"""
299 def setUp(self):
300 self.cellSet = afwMath.SpatialCellSet(lsst.geom.Box2I(
301 lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(501, 501)), 2, 3)
303 def tearDown(self):
304 del self.cellSet
306 def testInsertCandidate(self):
307 """Test that we can use SpatialCellMaskedImageCandidate"""
309 flux = 10
310 self.cellSet.insertCandidate(afwMath.TestImageCandidate(0, 0, flux))
312 cand = self.cellSet.getCellList()[0][0]
314 width, height = 15, 21
315 cand.setWidth(width)
316 cand.setHeight(height)
318 im = cand.getMaskedImage().getImage()
319 # This is how TestMaskedImageCandidate sets its pixels
320 self.assertEqual(im[0, 0, LOCAL], flux)
321 self.assertEqual(im.getWidth(), width)
322 self.assertEqual(im.getHeight(), height)
325class TestMemory(lsst.utils.tests.MemoryTestCase):
326 pass
329def setup_module(module):
330 lsst.utils.tests.init()
333if __name__ == "__main__": 333 ↛ 334line 333 didn't jump to line 334, because the condition on line 333 was never true
334 lsst.utils.tests.init()
335 unittest.main()