Coverage for tests/test_spatialCell.py: 16%

178 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-03-29 02: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/>. 

21 

22import unittest 

23 

24import lsst.utils.tests 

25import lsst.pex.exceptions as pexExcept 

26import lsst.geom 

27import lsst.afw.math as afwMath 

28from lsst.afw.image import LOCAL 

29 

30 

31def getFlux(x): 

32 return 1000 - 10*x 

33 

34 

35class SpatialCellTestCase(unittest.TestCase): 

36 

37 def setUp(self): 

38 candidateList = [] 

39 self.nCandidate = 5 

40 for i in (0, 1, 4, 3, 2): # must be all numbers in range(self.nCandidate) 

41 x, y = i, 5*i 

42 candidateList.append(afwMath.TestCandidate(x, y, getFlux(x))) 

43 

44 self.cell = afwMath.SpatialCell("Test", lsst.geom.Box2I(), candidateList) 

45 self.assertEqual(self.cell.getLabel(), "Test") 

46 

47 def testCandidateList(self): 

48 """Check that we can retrieve candidates, and that they are sorted by ranking""" 

49 self.assertEqual(self.cell[0].getXCenter(), 0) 

50 self.assertEqual(self.cell[1].getXCenter(), 1) 

51 self.assertEqual(self.cell[1].getYCenter(), 5) 

52 

53 def testBuildCandidateListByInsertion(self): 

54 """Build a candidate list by inserting candidates""" 

55 

56 self.cell = afwMath.SpatialCell("Test", lsst.geom.Box2I()) 

57 

58 for x, y in ([5, 0], [1, 1], [2, 2], [0, 0], [4, 4], [3, 4]): 

59 self.cell.insertCandidate(afwMath.TestCandidate(x, y, getFlux(x))) 

60 

61 self.assertEqual(self.cell[0].getXCenter(), 0) 

62 

63 def testIterators(self): 

64 """Test the SpatialCell iterators""" 

65 # Count the candidates 

66 self.assertEqual(self.cell.size(), self.nCandidate) 

67 self.assertEqual(self.cell.end() - self.cell.begin(), self.nCandidate) 

68 

69 ptr = self.cell.begin() 

70 ptr.__incr__() 

71 self.assertEqual(self.cell.end() - ptr, self.nCandidate - 1) 

72 

73 self.assertEqual(ptr - self.cell.begin(), 1) 

74 

75 # Now label one candidate as bad 

76 self.cell[2].setStatus(afwMath.SpatialCellCandidate.BAD) 

77 

78 self.assertEqual(self.cell.size(), self.nCandidate - 1) 

79 self.assertEqual(self.cell.end() - self.cell.begin(), 

80 self.nCandidate - 1) 

81 

82 self.cell.setIgnoreBad(False) 

83 self.assertEqual(self.cell.size(), self.nCandidate) 

84 self.assertEqual(self.cell.end() - self.cell.begin(), self.nCandidate) 

85 

86 def testGetCandidateById(self): 

87 """Check that we can lookup candidates by ID""" 

88 id = self.cell[1].getId() 

89 self.assertEqual(self.cell.getCandidateById(id).getId(), id) 

90 

91 self.assertEqual(self.cell.getCandidateById(-1, True), None) 

92 with self.assertRaises(pexExcept.NotFoundError): 

93 self.cell.getCandidateById(-1) 

94 

95 def testSetIteratorBad(self): 

96 """Setting a candidate BAD shouldn't stop us seeing the rest of the candidates""" 

97 i = 0 

98 for cand in self.cell: 

99 if i == 1: 

100 cand.setStatus(afwMath.SpatialCellCandidate.BAD) 

101 i += 1 

102 

103 self.assertEqual(i, self.nCandidate) 

104 

105 def testSortCandidates(self): 

106 """Check that we can update ratings and maintain order""" 

107 ratings0 = [cand.getCandidateRating() for cand in self.cell] 

108 

109 # Change a rating 

110 i, flux = 1, 9999 

111 self.cell[i].setCandidateRating(flux) 

112 ratings0[i] = flux 

113 

114 self.assertEqual(ratings0, [cand.getCandidateRating() 

115 for cand in self.cell]) 

116 

117 self.cell.sortCandidates() 

118 self.assertNotEqual( 

119 ratings0, [cand.getCandidateRating() for cand in self.cell]) 

120 

121 def sortKey(a): 

122 return -a 

123 self.assertEqual(sorted(ratings0, key=sortKey), 

124 [cand.getCandidateRating() for cand in self.cell]) 

125 

126 def testStr(self): 

127 expect = ("Test: bbox=(minimum=(0, 0), maximum=(-1, -1)), ignoreBad=True, candidates=[\n" 

128 "(center=(0.0,0.0), status=UNKNOWN, rating=1000.0)\n" 

129 "(center=(1.0,5.0), status=UNKNOWN, rating=990.0)\n" 

130 "(center=(2.0,10.0), status=UNKNOWN, rating=980.0)\n" 

131 "(center=(3.0,15.0), status=UNKNOWN, rating=970.0)\n" 

132 "(center=(4.0,20.0), status=UNKNOWN, rating=960.0)]") 

133 self.assertEqual(str(self.cell), expect) 

134 

135 # Check that a SpatialCell containing no candidates fits on one line. 

136 emptyCell = afwMath.SpatialCell("Test2", lsst.geom.Box2I(), []) 

137 expect = "Test2: bbox=(minimum=(0, 0), maximum=(-1, -1)), ignoreBad=True, candidates=[]" 

138 self.assertEqual(str(emptyCell), expect) 

139 

140 

141class SpatialCellSetTestCase(unittest.TestCase): 

142 

143 def setUp(self): 

144 self.cellSet = afwMath.SpatialCellSet(lsst.geom.Box2I( 

145 lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(501, 501)), 260, 200) 

146 

147 def makeTestCandidateCellSet(self): 

148 """Populate a SpatialCellSet""" 

149 # ensure we're starting with a list of empty cells 

150 self.assertEqual(len(self.cellSet.getCellList()), 6) 

151 

152 # number of candidates 

153 self.NTestCandidates = 0 

154 for x, y in ([5, 0], [1, 1], [2, 2], [0, 0], [4, 4], [3, 4]): # all in cell0 

155 self.cellSet.insertCandidate(afwMath.TestCandidate(x, y, -x)) 

156 self.NTestCandidates += 1 

157 

158 # in cell1 

159 self.cellSet.insertCandidate(afwMath.TestCandidate(305, 0, 100)) 

160 self.NTestCandidates += 1 

161 # the top right corner of cell5 

162 self.cellSet.insertCandidate(afwMath.TestCandidate(500, 500, 100)) 

163 self.NTestCandidates += 1 

164 

165 def testNoCells(self): 

166 """Test that we check for a request to make a SpatialCellSet with no cells""" 

167 def tst(): 

168 afwMath.SpatialCellSet(lsst.geom.Box2I( 

169 lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(500, 500)), 0, 3) 

170 

171 self.assertRaises(pexExcept.LengthError, tst) 

172 

173 def testInsertCandidate(self): 

174 """Test inserting candidates into the SpatialCellSet""" 

175 self.makeTestCandidateCellSet() 

176 

177 # we can't insert outside the box 

178 with self.assertRaises(pexExcept.OutOfRangeError): 

179 self.cellSet.insertCandidate(afwMath.TestCandidate(501, 501, 100)) 

180 

181 cell0 = self.cellSet.getCellList()[0] 

182 self.assertFalse(cell0.empty()) 

183 self.assertEqual(cell0[0].getXCenter(), 0.0) 

184 

185 self.assertEqual(self.cellSet.getCellList()[1][0].getXCenter(), 305.0) 

186 

187 self.assertTrue(self.cellSet.getCellList()[2].empty()) 

188 

189 def tst1(): 

190 self.cellSet.getCellList()[2][0] 

191 self.assertRaises(IndexError, tst1) 

192 

193 def tst2(): 

194 self.cellSet.getCellList()[2].begin().__deref__() 

195 self.assertRaises(pexExcept.NotFoundError, tst2) 

196 

197 self.assertFalse(self.cellSet.getCellList()[5].empty()) 

198 

199 def testVisitor(self): 

200 """Test the candidate visitors""" 

201 self.makeTestCandidateCellSet() 

202 

203 visitor = afwMath.TestCandidateVisitor() 

204 

205 self.cellSet.visitCandidates(visitor) 

206 self.assertEqual(visitor.getN(), self.NTestCandidates) 

207 

208 self.cellSet.visitCandidates(visitor, 1) 

209 self.assertEqual(visitor.getN(), 3) 

210 

211 def testGetCandidateById(self): 

212 """Check that we can lookup candidates by ID""" 

213 self.makeTestCandidateCellSet() 

214 

215 id = self.cellSet.getCellList()[0][1].getId() 

216 self.assertEqual(self.cellSet.getCandidateById(id).getId(), id) 

217 

218 def tst(): 

219 self.cellSet.getCandidateById(-1) # non-existent ID 

220 

221 self.assertEqual(self.cellSet.getCandidateById(-1, True), None) 

222 self.assertRaises(pexExcept.NotFoundError, tst) 

223 

224 def testSpatialCell(self): 

225 dx, dy, sx, sy = 100, 100, 50, 50 

226 for x0, y0 in [(0, 0), (100, 100)]: 

227 # only works for tests where dx,dx is some multiple of sx,sy 

228 assert(dx//sx == float(dx)/float(sx)) 

229 assert(dy//sy == float(dy)/float(sy)) 

230 

231 bbox = lsst.geom.Box2I(lsst.geom.Point2I(x0, y0), 

232 lsst.geom.Extent2I(dx, dy)) 

233 cset = afwMath.SpatialCellSet(bbox, sx, sy) 

234 for cell in cset.getCellList(): 

235 label = cell.getLabel() 

236 nx, ny = [int(z) for z in label.split()[1].split('x')] 

237 

238 cbbox = cell.getBBox() 

239 

240 self.assertEqual(cbbox.getMinX(), nx*sx + x0) 

241 self.assertEqual(cbbox.getMinY(), ny*sy + y0) 

242 self.assertEqual(cbbox.getMaxX(), (nx+1)*sx + x0 - 1) 

243 self.assertEqual(cbbox.getMaxY(), (ny+1)*sy + y0 - 1) 

244 

245 def testSortCandidates(self): 

246 """Check that we can update ratings and maintain order""" 

247 self.makeTestCandidateCellSet() 

248 

249 cell1 = self.cellSet.getCellList()[0] 

250 self.assertFalse(cell1.empty()) 

251 

252 ratings0 = [cand.getCandidateRating() for cand in cell1] 

253 

254 # Change a rating 

255 i, flux = 1, 9999 

256 cell1[i].setCandidateRating(flux) 

257 ratings0[i] = flux 

258 

259 self.assertEqual( 

260 ratings0, [cand.getCandidateRating() for cand in cell1]) 

261 

262 self.cellSet.sortCandidates() 

263 self.assertNotEqual( 

264 ratings0, [cand.getCandidateRating() for cand in cell1]) 

265 

266 def sortKey(a): 

267 return -a 

268 self.assertEqual(sorted(ratings0, key=sortKey), 

269 [cand.getCandidateRating() for cand in cell1]) 

270 

271 def testStr(self): 

272 expect = ("bbox=(minimum=(0, 0), maximum=(500, 500)), 6 cells\n" 

273 "Cell 0x0: bbox=(minimum=(0, 0), maximum=(259, 199)), ignoreBad=True, candidates=[]\n" 

274 "Cell 1x0: bbox=(minimum=(260, 0), maximum=(500, 199)), ignoreBad=True, candidates=[]\n" 

275 "Cell 0x1: bbox=(minimum=(0, 200), maximum=(259, 399)), ignoreBad=True, candidates=[]\n" 

276 "Cell 1x1: bbox=(minimum=(260, 200), maximum=(500, 399)), ignoreBad=True, candidates=[]\n" 

277 "Cell 0x2: bbox=(minimum=(0, 400), maximum=(259, 500)), ignoreBad=True, candidates=[]\n" 

278 "Cell 1x2: bbox=(minimum=(260, 400), maximum=(500, 500)), ignoreBad=True, candidates=[]") 

279 self.assertEqual(str(self.cellSet), expect) 

280 

281 

282class SpatialCellImageCandidateTestCase(unittest.TestCase): 

283 

284 def setUp(self): 

285 # To ensure consistency across tests: width/height are static members 

286 # of SpatialCellImageCandidate, and tests can run in any order. 

287 self.width = 15 

288 self.height = 21 

289 self.cellSet = afwMath.SpatialCellSet(lsst.geom.Box2I( 

290 lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(501, 501)), 2, 3) 

291 

292 def testInsertCandidate(self): 

293 """Test that we can use SpatialCellMaskedImageCandidate""" 

294 flux = 10 

295 self.cellSet.insertCandidate(afwMath.TestImageCandidate(0, 0, flux)) 

296 

297 cand = self.cellSet.getCellList()[0][0] 

298 

299 cand.setWidth(self.width) 

300 cand.setHeight(self.height) 

301 

302 im = cand.getMaskedImage().getImage() 

303 # This is how TestMaskedImageCandidate sets its pixels 

304 self.assertEqual(im[0, 0, LOCAL], flux) 

305 self.assertEqual(im.getWidth(), self.width) 

306 self.assertEqual(im.getHeight(), self.height) 

307 

308 def testStr(self): 

309 candidate = afwMath.TestImageCandidate(1, 2, 3) 

310 candidate.setChi2(4) 

311 candidate.setWidth(self.width) 

312 candidate.setHeight(self.height) 

313 expect = "center=(1.0,2.0), status=UNKNOWN, rating=3.0, size=(15, 21), chi2=4.0" 

314 self.assertEqual(str(candidate), expect) 

315 

316 

317class TestMemory(lsst.utils.tests.MemoryTestCase): 

318 pass 

319 

320 

321def setup_module(module): 

322 lsst.utils.tests.init() 

323 

324 

325if __name__ == "__main__": 325 ↛ 326line 325 didn't jump to line 326, because the condition on line 325 was never true

326 lsst.utils.tests.init() 

327 unittest.main()