Coverage for tests / test_spanSets.py: 13%

314 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-05-21 01:29 -0700

1# 

2# LSST Data Management System 

3# 

4# Copyright 2008-2016 AURA/LSST. 

5# 

6# This product includes software developed by the 

7# LSST Project (http://www.lsst.org/). 

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 LSST License Statement and 

20# the GNU General Public License along with this program. If not, 

21# see <https://www.lsstcorp.org/LegalNotices/>. 

22# 

23 

24import unittest 

25import numpy as np 

26 

27import lsst.utils.tests 

28import lsst.geom 

29import lsst.afw.geom as afwGeom 

30import lsst.afw.geom.ellipses as afwGeomEllipses 

31import lsst.afw.image as afwImage 

32 

33 

34class SpanSetTestCase(lsst.utils.tests.TestCase): 

35 ''' 

36 This is a python level unit test of the SpanSets class. It is mean to work in conjuction 

37 with the c++ unit test. The C++ test has much more coverage, and tests some features which 

38 are not exposed to python. This test serves mainly as a way to test that the python bindings 

39 correctly work. Many of these tests are smaller versions of the C++ tests. 

40 ''' 

41 

42 def testNullSpanSet(self): 

43 nullSS = afwGeom.SpanSet() 

44 self.assertEqual(nullSS.getArea(), 0) 

45 self.assertEqual(len(nullSS), 0) 

46 self.assertEqual(nullSS.getBBox().getDimensions().getX(), 0) 

47 self.assertEqual(nullSS.getBBox().getDimensions().getY(), 0) 

48 

49 def testBBoxSpanSet(self): 

50 boxSS = afwGeom.SpanSet(lsst.geom.Box2I(lsst.geom.Point2I(2, 2), 

51 lsst.geom.Point2I(6, 6))) 

52 self.assertEqual(boxSS.getArea(), 25) 

53 bBox = boxSS.getBBox() 

54 self.assertEqual(bBox.getMinX(), 2) 

55 self.assertEqual(bBox.getMinY(), 2) 

56 

57 def testIteratorConstructor(self): 

58 spans = [afwGeom.Span(0, 2, 4), afwGeom.Span(1, 2, 4), 

59 afwGeom.Span(2, 2, 4)] 

60 spanSetFromList = afwGeom.SpanSet(spans) 

61 spanSetFromArray = afwGeom.SpanSet(np.array(spans)) 

62 

63 self.assertEqual(spanSetFromList.getBBox().getMinX(), 2) 

64 self.assertEqual(spanSetFromList.getBBox().getMaxX(), 4) 

65 self.assertEqual(spanSetFromList.getBBox().getMinY(), 0) 

66 

67 self.assertEqual(spanSetFromArray.getBBox().getMinX(), 2) 

68 self.assertEqual(spanSetFromArray.getBBox().getMaxX(), 4) 

69 self.assertEqual(spanSetFromArray.getBBox().getMinY(), 0) 

70 

71 def testIsContiguous(self): 

72 spanSetConList = [afwGeom.Span(0, 2, 5), afwGeom.Span(1, 5, 8)] 

73 spanSetCon = afwGeom.SpanSet(spanSetConList) 

74 self.assertTrue(spanSetCon.isContiguous()) 

75 

76 spanSetNotConList = [afwGeom.Span(0, 2, 5), afwGeom.Span(1, 20, 25)] 

77 spanSetNotCon = afwGeom.SpanSet(spanSetNotConList) 

78 self.assertFalse(spanSetNotCon.isContiguous()) 

79 

80 def testSplit(self): 

81 spanSetOne = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX).shiftedBy(2, 2) 

82 spanSetTwo = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX).shiftedBy(8, 8) 

83 

84 spanSetList = [] 

85 for spn in spanSetOne: 

86 spanSetList.append(spn) 

87 for spn in spanSetTwo: 

88 spanSetList.append(spn) 

89 spanSetTogether = afwGeom.SpanSet(spanSetList) 

90 

91 spanSetSplit = spanSetTogether.split() 

92 self.assertEqual(len(spanSetSplit), 2) 

93 

94 for a, b in zip(spanSetOne, spanSetSplit[0]): 

95 self.assertEqual(a, b) 

96 

97 for a, b in zip(spanSetTwo, spanSetSplit[1]): 

98 self.assertEqual(a, b) 

99 

100 def testTransform(self): 

101 transform = lsst.geom.LinearTransform(np.array([[2.0, 0.0], [0.0, 2.0]])) 

102 spanSetPreScale = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.CIRCLE) 

103 spanSetPostScale = spanSetPreScale.transformedBy(transform) 

104 

105 self.assertEqual(spanSetPostScale.getBBox().getMinX(), -4) 

106 self.assertEqual(spanSetPostScale.getBBox().getMinY(), -4) 

107 

108 def testOverlaps(self): 

109 spanSetNoShift = afwGeom.SpanSet.fromShape(4, afwGeom.Stencil.CIRCLE) 

110 spanSetShift = spanSetNoShift.shiftedBy(2, 2) 

111 

112 self.assertTrue(spanSetNoShift.overlaps(spanSetShift)) 

113 

114 def testContains(self): 

115 spanSetLarge = afwGeom.SpanSet.fromShape(4, afwGeom.Stencil.CIRCLE) 

116 spanSetSmall = afwGeom.SpanSet.fromShape(1, afwGeom.Stencil.CIRCLE) 

117 

118 self.assertTrue(spanSetLarge.contains(spanSetSmall)) 

119 self.assertFalse(spanSetSmall.contains(lsst.geom.Point2I(100, 100))) 

120 

121 def testComputeCentroid(self): 

122 spanSetShape = afwGeom.SpanSet.fromShape(4, afwGeom.Stencil.CIRCLE).shiftedBy(2, 2) 

123 center = spanSetShape.computeCentroid() 

124 

125 self.assertEqual(center.getX(), 2) 

126 self.assertEqual(center.getY(), 2) 

127 

128 def testComputeShape(self): 

129 spanSetShape = afwGeom.SpanSet.fromShape(1, afwGeom.Stencil.CIRCLE) 

130 quad = spanSetShape.computeShape() 

131 

132 self.assertEqual(quad.getIxx(), 0.4) 

133 self.assertEqual(quad.getIyy(), 0.4) 

134 self.assertEqual(quad.getIxy(), 0) 

135 

136 def testdilated(self): 

137 spanSetPredilated = afwGeom.SpanSet.fromShape(1, afwGeom.Stencil.CIRCLE) 

138 spanSetPostdilated = spanSetPredilated.dilated(1) 

139 

140 bBox = spanSetPostdilated.getBBox() 

141 self.assertEqual(bBox.getMinX(), -2) 

142 self.assertEqual(bBox.getMinY(), -2) 

143 

144 def testErode(self): 

145 spanSetPreErode = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.CIRCLE) 

146 spanSetPostErode = spanSetPreErode.eroded(1) 

147 

148 bBox = spanSetPostErode.getBBox() 

149 self.assertEqual(bBox.getMinX(), -1) 

150 self.assertEqual(bBox.getMinY(), -1) 

151 

152 def testFlatten(self): 

153 # Give an initial value to an input array 

154 inputArray = np.ones((6, 6)) * 9 

155 inputArray[1, 1] = 1 

156 inputArray[1, 2] = 2 

157 inputArray[2, 1] = 3 

158 inputArray[2, 2] = 4 

159 

160 inputSpanSet = afwGeom.SpanSet([afwGeom.Span(0, 0, 1), 

161 afwGeom.Span(1, 0, 1)]) 

162 flatArr = inputSpanSet.flatten(inputArray, lsst.geom.Point2I(-1, -1)) 

163 

164 self.assertEqual(flatArr.size, inputSpanSet.getArea()) 

165 

166 # Test flatttening a 3D array 

167 spanSetArea = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX) 

168 spanSetArea = spanSetArea.shiftedBy(2, 2) 

169 

170 testArray = np.arange(5*5*3).reshape(5, 5, 3) 

171 flattened2DArray = spanSetArea.flatten(testArray) 

172 

173 truthArray = np.arange(5*5*3).reshape(5*5, 3) 

174 self.assertFloatsAlmostEqual(flattened2DArray, truthArray) 

175 

176 def testUnflatten(self): 

177 inputArray = np.ones(6) * 4 

178 inputSpanSet = afwGeom.SpanSet([afwGeom.Span(9, 2, 3), 

179 afwGeom.Span(10, 3, 4), 

180 afwGeom.Span(11, 2, 3)]) 

181 outputArray = inputSpanSet.unflatten(inputArray) 

182 

183 arrayShape = outputArray.shape 

184 bBox = inputSpanSet.getBBox() 

185 self.assertEqual(arrayShape[0], bBox.getHeight()) 

186 self.assertEqual(arrayShape[1], bBox.getWidth()) 

187 

188 # Test unflattening a 2D array 

189 spanSetArea = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX) 

190 spanSetArea = spanSetArea.shiftedBy(2, 2) 

191 

192 testArray = np.arange(5*5*3).reshape(5*5, 3) 

193 unflattened3DArray = spanSetArea.unflatten(testArray) 

194 

195 truthArray = np.arange(5*5*3).reshape(5, 5, 3) 

196 self.assertFloatsAlmostEqual(unflattened3DArray, truthArray) 

197 

198 def populateMask(self): 

199 msk = afwImage.Mask(10, 10, 1) 

200 spanSetMask = afwGeom.SpanSet.fromShape(3, afwGeom.Stencil.CIRCLE).shiftedBy(5, 5) 

201 spanSetMask.setMask(msk, 2) 

202 return msk, spanSetMask 

203 

204 def testSetMask(self): 

205 mask, spanSetMask = self.populateMask() 

206 mskArray = mask.getArray() 

207 for i in range(mskArray.shape[0]): 

208 for j in range(mskArray.shape[1]): 

209 if lsst.geom.Point2I(i, j) in spanSetMask: 

210 self.assertEqual(mskArray[i, j], 3) 

211 else: 

212 self.assertEqual(mskArray[i, j], 1) 

213 

214 def testClearMask(self): 

215 mask, spanSetMask = self.populateMask() 

216 spanSetMask.clearMask(mask, 2) 

217 mskArray = mask.getArray() 

218 for i in range(mskArray.shape[0]): 

219 for j in range(mskArray.shape[1]): 

220 self.assertEqual(mskArray[i, j], 1) 

221 

222 def makeOverlapSpanSets(self): 

223 firstSpanSet = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX).shiftedBy(2, 4) 

224 secondSpanSet = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX).shiftedBy(2, 2) 

225 return firstSpanSet, secondSpanSet 

226 

227 def makeMaskAndSpanSetForOperationTest(self): 

228 firstMaskPart = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX).shiftedBy(3, 2) 

229 secondMaskPart = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX).shiftedBy(3, 8) 

230 spanSetMaskOperation = afwGeom.SpanSet.fromShape(2, afwGeom.Stencil.BOX).shiftedBy(3, 5) 

231 

232 mask = afwImage.Mask(20, 20) 

233 firstMaskPart.setMask(mask, 3) 

234 secondMaskPart.setMask(mask, 3) 

235 spanSetMaskOperation.setMask(mask, 4) 

236 

237 return mask, spanSetMaskOperation 

238 

239 def testIntersection(self): 

240 firstSpanSet, secondSpanSet = self.makeOverlapSpanSets() 

241 

242 overlap = firstSpanSet.intersect(secondSpanSet) 

243 for i, span in enumerate(overlap): 

244 self.assertEqual(span.getY(), i+2) 

245 self.assertEqual(span.getMinX(), 0) 

246 self.assertEqual(span.getMaxX(), 4) 

247 

248 mask, spanSetMaskOperation = self.makeMaskAndSpanSetForOperationTest() 

249 spanSetIntersectMask = spanSetMaskOperation.intersect(mask, 2) 

250 

251 expectedYRange = [3, 4, 6, 7] 

252 for expected, val in zip(expectedYRange, spanSetIntersectMask): 

253 self.assertEqual(expected, val.getY()) 

254 

255 def testIntersectionWithGap(self): 

256 # This test was created in DM-47945 to fix a bug where the 

257 # intersection of two spansets where multiple spans have the same 

258 # y-value would fail. 

259 spans1 = afwGeom.SpanSet([afwGeom.Span(1, 0, 3), afwGeom.Span(1, 5, 7)]) 

260 spans2 = afwGeom.SpanSet([afwGeom.Span(1, 2, 6)]) 

261 intersection = spans1.intersect(spans2) 

262 trueIntersection = afwGeom.SpanSet([afwGeom.Span(1, 2, 3), afwGeom.Span(1, 5, 6)]) 

263 

264 self.assertEqual(len(intersection), 2) 

265 

266 for a, b in zip(intersection, trueIntersection): 

267 self.assertEqual(a, b) 

268 

269 def testIntersectNot(self): 

270 firstSpanSet, secondSpanSet = self.makeOverlapSpanSets() 

271 

272 overlap = firstSpanSet.intersectNot(secondSpanSet) 

273 for yVal, span in enumerate(overlap): 

274 self.assertEqual(span.getY(), yVal+5) 

275 self.assertEqual(span.getMinX(), 0) 

276 self.assertEqual(span.getMaxX(), 4) 

277 

278 mask, spanSetMaskOperation = self.makeMaskAndSpanSetForOperationTest() 

279 

280 spanSetIntersectNotMask = spanSetMaskOperation.intersectNot(mask, 2) 

281 

282 self.assertEqual(len(spanSetIntersectNotMask), 1) 

283 self.assertEqual(next(iter(spanSetIntersectNotMask)).getY(), 5) 

284 

285 # More complicated intersection with disconnected SpanSets 

286 spanList1 = [afwGeom.Span(0, 0, 10), 

287 afwGeom.Span(1, 0, 10), 

288 afwGeom.Span(2, 0, 10)] 

289 

290 spanList2 = [afwGeom.Span(1, 2, 4), afwGeom.Span(1, 7, 8)] 

291 

292 resultList = [afwGeom.Span(0, 0, 10), 

293 afwGeom.Span(1, 0, 1), 

294 afwGeom.Span(1, 5, 6), 

295 afwGeom.Span(1, 9, 10), 

296 afwGeom.Span(2, 0, 10)] 

297 

298 spanSet1 = afwGeom.SpanSet(spanList1) 

299 spanSet2 = afwGeom.SpanSet(spanList2) 

300 expectedSpanSet = afwGeom.SpanSet(resultList) 

301 

302 outputSpanSet = spanSet1.intersectNot(spanSet2) 

303 

304 self.assertEqual(outputSpanSet, expectedSpanSet) 

305 

306 numIntersectNotTrials = 100 

307 spanRow = 5 

308 # Set a seed for random functions 

309 np.random.seed(400) 

310 for N in range(numIntersectNotTrials): 

311 # Create two random SpanSets, both with holes in them 

312 listOfRandomSpanSets = [] 

313 for i in range(2): 

314 # Make two rectangles to be turned into a SpanSet 

315 rand1 = np.random.randint(0, 26, 2) 

316 rand2 = np.random.randint(rand1.max(), 51, 2) 

317 tempList = [afwGeom.Span(spanRow, rand1.min(), rand1.max()), 

318 afwGeom.Span(spanRow, rand2.min(), rand2.max())] 

319 listOfRandomSpanSets.append(afwGeom.SpanSet(tempList)) 

320 

321 # IntersectNot the SpanSets, randomly choosing which one is the one 

322 # to be the negated SpanSet 

323 randChoice = np.random.randint(0, 2) 

324 negatedRandChoice = int(not randChoice) 

325 sourceSpanSet = listOfRandomSpanSets[randChoice] 

326 targetSpanSet = listOfRandomSpanSets[negatedRandChoice] 

327 resultSpanSet = sourceSpanSet.intersectNot(targetSpanSet) 

328 for span in resultSpanSet: 

329 for point in span: 

330 self.assertTrue(sourceSpanSet.contains(point)) 

331 self.assertFalse(targetSpanSet.contains(point)) 

332 

333 for x in range(51): 

334 point = lsst.geom.Point2I(x, spanRow) 

335 if sourceSpanSet.contains(point) and not\ 

336 targetSpanSet.contains(point): 

337 self.assertTrue(resultSpanSet.contains(point)) 

338 

339 def testIntersectNotWithGap(self): 

340 # This test was created in DM-47945 to fix a bug where the 

341 # intersection of two spansets where multiple spans have the same 

342 # y-value would fail. 

343 spans1 = afwGeom.SpanSet([afwGeom.Span(1, 0, 3), afwGeom.Span(1, 5, 7)]) 

344 spans2 = afwGeom.SpanSet([afwGeom.Span(1, 2, 6)]) 

345 intersectNot = spans1.intersectNot(spans2) 

346 trueIntersectNot = afwGeom.SpanSet([afwGeom.Span(1, 0, 1), afwGeom.Span(1, 7, 7)]) 

347 

348 self.assertEqual(len(intersectNot), 2) 

349 

350 for a, b in zip(intersectNot, trueIntersectNot): 

351 self.assertEqual(a, b) 

352 

353 def testUnion(self): 

354 firstSpanSet, secondSpanSet = self.makeOverlapSpanSets() 

355 

356 overlap = firstSpanSet.union(secondSpanSet) 

357 

358 for yVal, span in enumerate(overlap): 

359 self.assertEqual(span.getY(), yVal) 

360 self.assertEqual(span.getMinX(), 0) 

361 self.assertEqual(span.getMaxX(), 4) 

362 

363 mask, spanSetMaskOperation = self.makeMaskAndSpanSetForOperationTest() 

364 

365 spanSetUnion = spanSetMaskOperation.union(mask, 2) 

366 

367 for yVal, span in enumerate(spanSetUnion): 

368 self.assertEqual(span.getY(), yVal) 

369 

370 def testMaskToSpanSet(self): 

371 mask, _ = self.makeMaskAndSpanSetForOperationTest() 

372 spanSetFromMask = afwGeom.SpanSet.fromMask(mask) 

373 

374 for yCoord, span in enumerate(spanSetFromMask): 

375 self.assertEqual(span, afwGeom.Span(yCoord, 1, 5)) 

376 

377 def testFromMask(self): 

378 xy0 = lsst.geom.Point2I(12345, 67890) # xy0 for image 

379 dims = lsst.geom.Extent2I(123, 45) # Dimensions of image 

380 box = lsst.geom.Box2I(xy0, dims) # Bounding box of image 

381 value = 32 

382 other = 16 

383 assert value & other == 0 # Setting 'other' unsets 'value' 

384 point = lsst.geom.Point2I(3 + xy0.getX(), 3 + xy0.getY()) # Point in the image 

385 

386 mask = afwImage.Mask(box) 

387 mask.set(value) 

388 

389 # We can create a SpanSet from bit planes 

390 spans = afwGeom.SpanSet.fromMask(mask, value) 

391 self.assertEqual(spans.getArea(), box.getArea()) 

392 self.assertEqual(spans.getBBox(), box) 

393 self.assertTrue(point in spans) 

394 

395 # Pixels not matching the desired bit plane are ignored as they should be 

396 mask[point] = other # unset one pixel 

397 spans = afwGeom.SpanSet.fromMask(mask, value) 

398 self.assertEqual(spans.getArea(), box.getArea() - 1) 

399 self.assertEqual(spans.getBBox(), box) 

400 self.assertFalse(point in spans) 

401 

402 def testEquality(self): 

403 firstSpanSet, secondSpanSet = self.makeOverlapSpanSets() 

404 secondSpanSetShift = secondSpanSet.shiftedBy(0, 2) 

405 

406 self.assertFalse(firstSpanSet == secondSpanSet) 

407 self.assertTrue(firstSpanSet != secondSpanSet) 

408 self.assertTrue(firstSpanSet == secondSpanSetShift) 

409 self.assertFalse(firstSpanSet != secondSpanSetShift) 

410 

411 def testSpanSetFromEllipse(self): 

412 axes = afwGeomEllipses.Axes(6, 6, 0) 

413 ellipse = afwGeom.Ellipse(axes, lsst.geom.Point2D(5, 6)) 

414 spanSet = afwGeom.SpanSet.fromShape(ellipse) 

415 for ss, es in zip(spanSet, afwGeomEllipses.PixelRegion(ellipse)): 

416 self.assertEqual(ss, es) 

417 

418 def testfromShapeOffset(self): 

419 shift = lsst.geom.Point2I(2, 2) 

420 spanSetShifted = afwGeom.SpanSet.fromShape(2, offset=shift) 

421 bbox = spanSetShifted.getBBox() 

422 self.assertEqual(bbox.getMinX(), 0) 

423 self.assertEqual(bbox.getMinY(), 0) 

424 

425 def testFindEdgePixels(self): 

426 spanSet = afwGeom.SpanSet.fromShape(6, afwGeom.Stencil.CIRCLE) 

427 spanSetEdge = spanSet.findEdgePixels() 

428 

429 truthSpans = [afwGeom.Span(-6, 0, 0), 

430 afwGeom.Span(-5, -3, -1), 

431 afwGeom.Span(-5, 1, 3), 

432 afwGeom.Span(-4, -4, -4), 

433 afwGeom.Span(-4, 4, 4), 

434 afwGeom.Span(-3, -5, -5), 

435 afwGeom.Span(-3, 5, 5), 

436 afwGeom.Span(-2, -5, -5), 

437 afwGeom.Span(-2, 5, 5), 

438 afwGeom.Span(-1, -5, -5), 

439 afwGeom.Span(-1, 5, 5), 

440 afwGeom.Span(0, -6, -6), 

441 afwGeom.Span(0, 6, 6), 

442 afwGeom.Span(1, -5, -5), 

443 afwGeom.Span(1, 5, 5), 

444 afwGeom.Span(2, -5, -5), 

445 afwGeom.Span(2, 5, 5), 

446 afwGeom.Span(3, -5, -5), 

447 afwGeom.Span(3, 5, 5), 

448 afwGeom.Span(4, -4, -4), 

449 afwGeom.Span(4, 4, 4), 

450 afwGeom.Span(5, -3, -1), 

451 afwGeom.Span(5, 1, 3), 

452 afwGeom.Span(6, 0, 0)] 

453 truthSpanSet = afwGeom.SpanSet(truthSpans) 

454 self.assertEqual(spanSetEdge, truthSpanSet) 

455 

456 def testIndices(self): 

457 dataArray = np.zeros((5, 5)) 

458 spanSet = afwGeom.SpanSet.fromShape(2, 

459 afwGeom.Stencil.BOX, 

460 offset=(2, 2)) 

461 yind, xind = spanSet.indices() 

462 dataArray[yind, xind] = 9 

463 self.assertTrue((dataArray == 9).all()) 

464 

465 def testSpanIteration(self): 

466 span = afwGeom.Span(4, 3, 8) 

467 points = list(span) 

468 self.assertEqual(len(span), len(points)) 

469 self.assertEqual(points, [lsst.geom.Point2I(x, 4) for x in range(3, 9)]) 

470 

471 def testAsArray(self): 

472 spans = afwGeom.SpanSet(lsst.geom.Box2I(lsst.geom.Point2I(2, 3), lsst.geom.Point2I(6, 7))) 

473 truth = np.ones((5, 5), dtype=bool) 

474 arr = spans.asArray() 

475 np.testing.assert_array_equal(arr, truth) 

476 

477 shape = (10, 10) 

478 truth = np.zeros(shape, dtype=bool) 

479 truth[:5, :5] = 1 

480 arr = spans.asArray(shape) 

481 np.testing.assert_array_equal(arr, truth) 

482 

483 truth = np.zeros(shape, dtype=bool) 

484 truth[3:8, 2:7] = 1 

485 arr = spans.asArray(shape, (0, 0)) 

486 np.testing.assert_array_equal(arr, truth) 

487 

488 

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

490 pass 

491 

492 

493def setup_module(module): 

494 lsst.utils.tests.init() 

495 

496 

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

498 lsst.utils.tests.init() 

499 unittest.main()