Coverage for tests/test_multiband.py: 11%

570 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-28 03:10 -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# (http://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 <http://www.gnu.org/licenses/>. 

21 

22""" 

23Tests for Multiband objects 

24""" 

25import unittest 

26import operator 

27 

28import numpy as np 

29 

30import lsst.utils 

31import lsst.utils.tests 

32from lsst.geom import Point2I, Box2I, Extent2I 

33from lsst.afw.geom import SpanSet, Stencil 

34from lsst.afw.detection import GaussianPsf, Footprint, makeHeavyFootprint, MultibandFootprint, HeavyFootprintF 

35from lsst.afw.image import ImageF, Mask, MaskPixel, MaskedImage, ExposureF, MaskedImageF, LOCAL 

36from lsst.afw.image import MultibandPixel, MultibandImage, MultibandMask, MultibandMaskedImage 

37from lsst.afw.image import MultibandExposure 

38 

39 

40def _testImageFilterSlicing(testCase, mImage, singleType, bbox, value): 

41 """Test slicing by filters for image-like objects""" 

42 testCase.assertIsInstance(mImage["R"], singleType) 

43 testCase.assertIsInstance(mImage[:], type(mImage)) 

44 

45 testCase.assertEqual(mImage["G", -1, -1, LOCAL], value) 

46 testCase.assertEqual(mImage["G"].array.shape, (100, 200)) 

47 testCase.assertEqual(mImage[:"I"].array.shape, (2, 100, 200)) 

48 testCase.assertEqual(mImage[:"I"].filters, ("G", "R")) 

49 testCase.assertEqual(mImage[:"I"].getBBox(), bbox) 

50 testCase.assertEqual(mImage[["G", "I"]].array.shape, (2, 100, 200)) 

51 testCase.assertEqual(mImage[["G", "I"]].filters, ("G", "I")) 

52 testCase.assertEqual(mImage[["G", "I"]].getBBox(), bbox) 

53 

54 testCase.assertEqual(mImage["G":"R"].filters, ("G",)) 

55 

56 if "Z" in mImage.filters: 

57 filterSlice = slice("R", "Z") 

58 else: 

59 filterSlice = slice("R", None) 

60 testCase.assertEqual(mImage[filterSlice].filters, ("R", "I")) 

61 testCase.assertEqual(mImage.filters, tuple(testCase.filters)) 

62 

63 

64def _testImageSlicing(testCase, mImage, gVal, rVal, iVal): 

65 """Test slicing in the spatial dimensions for image-like objects""" 

66 testCase.assertIsInstance(mImage[:, -1, -1, LOCAL], MultibandPixel) 

67 testCase.assertEqual(mImage["G", -1, -1, LOCAL], gVal) 

68 

69 testCase.assertEqual(mImage[:, 1100:, 2025:].getBBox(), Box2I(Point2I(1100, 2025), Extent2I(100, 75))) 

70 testCase.assertEqual(mImage[:, -20:-10, -10:-5, LOCAL].getBBox(), 

71 Box2I(Point2I(1180, 2090), Extent2I(10, 5))) 

72 testCase.assertEqual(mImage[:, :1100, :2050].getBBox(), Box2I(Point2I(1000, 2000), Extent2I(100, 50))) 

73 coord = Point2I(1075, 2015) 

74 bbox = Box2I(Point2I(1050, 2010), coord) 

75 testCase.assertEqual(mImage[:, bbox].getBBox(), bbox) 

76 testCase.assertEqual(mImage[:, 1010, 2010].getBBox().getMin(), Point2I(1010, 2010)) 

77 testCase.assertEqual(mImage[:, Point2I(1075, 2015)].getBBox().getMin(), coord) 

78 

79 testCase.assertEqual(mImage["G", 1100:, 2025:].getBBox(), Box2I(Point2I(1100, 2025), Extent2I(100, 75))) 

80 testCase.assertEqual(mImage["R", -20:-10, -10:-5, LOCAL].getBBox(), 

81 Box2I(Point2I(1180, 2090), Extent2I(10, 5))) 

82 testCase.assertEqual(mImage["I", :1100, :2050].getBBox(), Box2I(Point2I(1000, 2000), Extent2I(100, 50))) 

83 testCase.assertEqual(mImage["R", bbox].getBBox(), bbox) 

84 testCase.assertEqual(mImage["I", 1010, 2010], iVal) 

85 testCase.assertEqual(mImage["R", Point2I(1075, 2015)], rVal) 

86 

87 with testCase.assertRaises(TypeError): 

88 mImage[:, 0] 

89 with testCase.assertRaises(TypeError): 

90 mImage[:, 10:] 

91 with testCase.assertRaises(TypeError): 

92 mImage[:, :10] 

93 with testCase.assertRaises(TypeError): 

94 mImage[:, :, 0] 

95 

96 

97def _testImageModification(testCase, mImage1, mImage2, bbox1, bbox2, value1, value2): 

98 """Test the image-like objects can be modified""" 

99 mImage1[:"R", bbox2].array = value2 

100 testCase.assertFloatsEqual(mImage1["G", bbox2].array, mImage2["G"].array) 

101 testCase.assertFloatsEqual(mImage1["R"].array, value1) 

102 mImage1.setXY0(Point2I(500, 150)) 

103 testCase.assertEqual(mImage1.getBBox(), Box2I(Point2I(500, 150), Extent2I(bbox1.getDimensions()))) 

104 

105 mImage1["G"].array[:] = value2 

106 testCase.assertFloatsEqual(mImage1["G"].array, value2) 

107 testCase.assertFloatsEqual(mImage1.array[0], value2) 

108 

109 if "Z" in mImage1.filters: 

110 filterSlice = slice("R", "Z") 

111 else: 

112 filterSlice = slice("R", None) 

113 mImage1[filterSlice].array[:] = 7 

114 testCase.assertFloatsEqual(mImage1["I"].array, 7) 

115 newBBox = Box2I(Point2I(10000, 20000), mImage1.getBBox().getDimensions()) 

116 mImage1.setXY0(newBBox.getMin()) 

117 testCase.assertEqual(mImage1.getBBox(), newBBox) 

118 for image in mImage1: 

119 testCase.assertEqual(image.getBBox(), newBBox) 

120 

121 # Uncomment this test when DM-10781 is implemented 

122 # offset = Extent2I(-9000, -18000) 

123 # mImage1.shiftedBy(offset) 

124 # newBBox = Box2I(Point2I(1000, 2000), newBBox.getDimensions()) 

125 # testCase.assertEqual(mImage1.getBBox(), newBBox) 

126 # for image in mImage1: 

127 # testCase.assertEqual(image.getBBox(), newBBox) 

128 

129 

130def _testImageCopy(testCase, mImage1, value1, value2): 

131 """Test copy and deep copy in image-like objects""" 

132 mImage2 = mImage1.clone() 

133 mImage2.setXY0(Point2I(11, 23)) 

134 testCase.assertEqual(mImage2.getBBox(), Box2I(Point2I(11, 23), Extent2I(200, 100))) 

135 testCase.assertEqual(mImage1.getBBox(), Box2I(Point2I(1000, 2000), Extent2I(200, 100))) 

136 testCase.assertTrue(np.all([s.getBBox() == mImage1.getBBox() for s in mImage1.singles])) 

137 testCase.assertTrue(np.all([s.getBBox() == mImage2.getBBox() for s in mImage2.singles])) 

138 mImage2.array[:] = 17 

139 testCase.assertNotEqual(mImage1.array[0, 0, 0], 17) 

140 

141 mImage2.array[:] = value2 

142 testCase.assertFloatsEqual(mImage1.array, value1) 

143 testCase.assertFloatsEqual(mImage2.array, value2) 

144 testCase.assertFloatsEqual(mImage1["G"].array, value1) 

145 testCase.assertFloatsEqual(mImage2["G"].array, value2) 

146 

147 mImage2 = mImage1.clone(False) 

148 mImage2.setXY0(Point2I(11, 23)) 

149 mImage2.array[:] = 17 

150 testCase.assertFloatsEqual(mImage2.array, mImage1.array) 

151 

152 mImage2.array[:] = value2 

153 testCase.assertFloatsEqual(mImage1.array, value2) 

154 testCase.assertFloatsEqual(mImage2.array, value2) 

155 testCase.assertFloatsEqual(mImage1["G"].array, value2) 

156 testCase.assertFloatsEqual(mImage2["G"].array, value2) 

157 

158 

159class MultibandPixelTestCase(lsst.utils.tests.TestCase): 

160 """Test case for MultibandPixel 

161 """ 

162 def setUp(self): 

163 np.random.seed(1) 

164 self.bbox = Point2I(101, 502) 

165 self.filters = ["G", "R", "I", "Z", "Y"] 

166 singles = np.arange(5, dtype=float) 

167 self.pixel = MultibandPixel(self.filters, singles, self.bbox) 

168 

169 def tearDown(self): 

170 del self.bbox 

171 del self.filters 

172 del self.pixel 

173 

174 def testFilterSlicing(self): 

175 pixel = self.pixel 

176 self.assertEqual(pixel["R"], 1.) 

177 self.assertFloatsEqual(pixel.array, np.arange(5)) 

178 self.assertFloatsEqual(pixel.singles, np.arange(5)) 

179 self.assertFloatsEqual(pixel[["G", "I"]].array, [0, 2]) 

180 

181 def testPixelBBoxModification(self): 

182 pixel = self.pixel.clone() 

183 otherPixel = pixel.clone() 

184 pixel.getBBox().shift(Extent2I(9, -2)) 

185 self.assertEqual(pixel.getBBox().getMin(), Point2I(110, 500)) 

186 self.assertEqual(otherPixel.getBBox().getMin(), Point2I(101, 502)) 

187 

188 pixel = self.pixel.clone() 

189 otherPixel = pixel.clone(False) 

190 pixel.getBBox().shift(Extent2I(9, -2)) 

191 self.assertEqual(pixel.getBBox().getMin(), Point2I(110, 500)) 

192 self.assertEqual(otherPixel.getBBox().getMin(), Point2I(110, 500)) 

193 

194 def testPixelModification(self): 

195 pixel = self.pixel 

196 otherPixel = pixel.clone() 

197 otherPixel.array = np.arange(10, 15) 

198 self.assertFloatsEqual(otherPixel.array, np.arange(10, 15)) 

199 self.assertFloatsEqual(pixel.array, np.arange(0, 5)) 

200 

201 

202class MultibandImageTestCase(lsst.utils.tests.TestCase): 

203 """Test case for MultibandImage""" 

204 

205 def setUp(self): 

206 np.random.seed(1) 

207 self.bbox1 = Box2I(Point2I(1000, 2000), Extent2I(200, 100)) 

208 self.filters = ["G", "R", "I", "Z", "Y"] 

209 self.value1, self.value2 = 10, 100 

210 images = [ImageF(self.bbox1, self.value1) for f in self.filters] 

211 self.mImage1 = MultibandImage.fromImages(self.filters, images) 

212 self.bbox2 = Box2I(Point2I(1100, 2025), Extent2I(30, 50)) 

213 images = [ImageF(self.bbox2, self.value2) for f in self.filters] 

214 self.mImage2 = MultibandImage.fromImages(self.filters, images) 

215 

216 def tearDown(self): 

217 del self.bbox1 

218 del self.bbox2 

219 del self.filters 

220 del self.value1 

221 del self.value2 

222 del self.mImage1 

223 del self.mImage2 

224 

225 def testFilterSlicing(self): 

226 _testImageFilterSlicing(self, self.mImage1, ImageF, self.bbox1, self.value1) 

227 

228 def testImageSlicing(self): 

229 _testImageSlicing(self, self.mImage1, self.value1, self.value1, self.value1) 

230 

231 def testImageModification(self): 

232 _testImageModification(self, self.mImage1, self.mImage2, self.bbox1, self.bbox2, 

233 self.value1, self.value2) 

234 

235 def testImageCopy(self): 

236 _testImageCopy(self, self.mImage1, self.value1, 5.) 

237 

238 

239class MultibandMaskTestCase(lsst.utils.tests.TestCase): 

240 """A test case for Mask""" 

241 

242 def setUp(self): 

243 np.random.seed(1) 

244 self.filters = ["G", "R", "I"] 

245 self.Mask = Mask[MaskPixel] 

246 

247 # Store the default mask planes for later use 

248 maskPlaneDict = self.Mask().getMaskPlaneDict() 

249 self.defaultMaskPlanes = sorted(maskPlaneDict, key=maskPlaneDict.__getitem__) 

250 

251 # reset so tests will be deterministic 

252 self.Mask.clearMaskPlaneDict() 

253 for p in ("BAD", "SAT", "INTRP", "CR", "EDGE"): 

254 self.Mask.addMaskPlane(p) 

255 

256 self.BAD = self.Mask.getPlaneBitMask("BAD") 

257 self.CR = self.Mask.getPlaneBitMask("CR") 

258 self.EDGE = self.Mask.getPlaneBitMask("EDGE") 

259 

260 self.values1 = [self.BAD | self.CR, self.BAD | self.EDGE, self.BAD | self.CR | self.EDGE] 

261 self.bbox = Box2I(Point2I(1000, 2000), Extent2I(200, 100)) 

262 singles = [self.Mask(self.bbox) for f in range(len(self.filters))] 

263 for n in range(len(singles)): 

264 singles[n].set(self.values1[n]) 

265 self.mMask1 = MultibandMask.fromMasks(self.filters, singles) 

266 

267 self.values2 = [self.EDGE, self.BAD, self.CR | self.EDGE] 

268 singles = [self.Mask(self.bbox) for f in range(len(self.filters))] 

269 for n in range(len(singles)): 

270 singles[n].set(self.values2[n]) 

271 self.mMask2 = MultibandMask.fromMasks(self.filters, singles) 

272 

273 def tearDown(self): 

274 del self.mMask1 

275 del self.mMask2 

276 del self.bbox 

277 del self.values1 

278 del self.values2 

279 # Reset the mask plane to the default 

280 self.Mask.clearMaskPlaneDict() 

281 for p in self.defaultMaskPlanes: 

282 self.Mask.addMaskPlane(p) 

283 self.defaultMaskPlanes 

284 

285 def testInitializeMasks(self): 

286 self.assertTrue(np.all([s.getBBox() == self.mMask1.getBBox() for s in self.mMask1.singles])) 

287 self.assertTrue(np.all([s.array == self.values1[n] for n, s in enumerate(self.mMask1.singles)])) 

288 

289 def _bitOperator(self, op): 

290 op(self.mMask2, self.mMask1) 

291 for n, mask in enumerate(self.mMask1): 

292 op(mask, self.values2[n]) 

293 

294 self.assertFloatsEqual(self.mMask1.array, self.mMask2.array) 

295 expect = np.empty_like(self.mMask1.array) 

296 expect[:] = op(np.array(self.values1), np.array(self.values2))[:, None, None] 

297 self.assertFloatsEqual(self.mMask1.array, expect) 

298 

299 def testOrMasks(self): 

300 self._bitOperator(operator.ior) 

301 

302 def testAndMasks(self): 

303 self._bitOperator(operator.iand) 

304 

305 def testXorMasks(self): 

306 self._bitOperator(operator.ixor) 

307 

308 def testSetMask(self): 

309 mMask = self.mMask1.clone() 

310 mMask[:] = self.CR 

311 self.assertFloatsEqual(mMask.array, self.CR) 

312 mMask["G"] = self.EDGE 

313 self.assertFloatsEqual(mMask["R":].array, self.CR) 

314 self.assertFloatsEqual(mMask["G"].array, self.EDGE) 

315 mMask["R":] = self.BAD 

316 self.assertFloatsEqual(mMask["R":].array, self.BAD) 

317 mMask["R", 1100, 2050] = self.CR | self.EDGE 

318 self.assertEqual(mMask["R", 1100, 2050], self.CR | self.EDGE) 

319 self.assertEqual(mMask["R", 1101, 2051], self.BAD) 

320 

321 def testMaskPlanes(self): 

322 planes = self.mMask1.getMaskPlaneDict() 

323 self.assertEqual(len(planes), self.mMask1.getNumPlanesUsed()) 

324 

325 for k in sorted(planes.keys()): 

326 self.assertEqual(planes[k], self.mMask1.getMaskPlane(k)) 

327 

328 def testRemoveMaskPlane(self): 

329 mMask = self.mMask1 

330 # Add mask plane FOO and make sure it got added properly 

331 mMask.addMaskPlane("FOO") 

332 self.assertIn("FOO", mMask.getMaskPlaneDict()) 

333 self.assertIn("FOO", Mask().getMaskPlaneDict()) 

334 # Remove plane FOO, noting that removeMaskPlane removes it from the 

335 # default, but each instance remembers the version of the mask 

336 # dictionary that was current when it was created, so it will still 

337 # be in the mMask dict. 

338 mMask.removeMaskPlane("FOO") 

339 self.assertIn("FOO", mMask.getMaskPlaneDict()) 

340 self.assertNotIn("FOO", Mask().getMaskPlaneDict()) 

341 

342 def testRemoveAndClearMaskPlane(self): 

343 mMask = self.mMask1 

344 # Add mask plane FOO and test clearing it without removing plane from 

345 # default dict 

346 mMask.addMaskPlane("FOO") 

347 mMask.removeAndClearMaskPlane("FOO") 

348 self.assertNotIn("FOO", mMask.getMaskPlaneDict()) 

349 self.assertIn("FOO", Mask().getMaskPlaneDict()) 

350 # Now also remove it from default dict 

351 mMask.addMaskPlane("FOO") 

352 mMask.removeAndClearMaskPlane("FOO", removeFromDefault=True) 

353 self.assertNotIn("FOO", mMask.getMaskPlaneDict()) 

354 self.assertNotIn("FOO", Mask().getMaskPlaneDict()) 

355 # Now remove and clear the EDGE mask plane and make sure all of the planes 

356 # in the MultibandMask (i.e. the "singles") got updated accordingly 

357 mMask.removeAndClearMaskPlane("EDGE", removeFromDefault=True) 

358 self.assertNotIn("EDGE", mMask.getMaskPlaneDict()) 

359 self.assertNotIn("EDGE", Mask().getMaskPlaneDict()) 

360 # Assert that all mask planes were updated (i.e. having EDGE removed) 

361 self.assertTrue(np.all([s.array == self.values1[n] & ~self.EDGE for 

362 n, s in enumerate(mMask.singles)])) 

363 

364 def testFilterSlicing(self): 

365 _testImageFilterSlicing(self, self.mMask1, Mask, self.bbox, self.values1[0]) 

366 

367 def testImageSlicing(self): 

368 _testImageSlicing(self, self.mMask1, *self.values1) 

369 

370 def testImageModification(self): 

371 mMask1 = self.mMask1 

372 value1 = self.CR 

373 value2 = self.EDGE 

374 mMask1[:] = value1 

375 

376 bbox2 = Box2I(Point2I(1100, 2025), Extent2I(30, 50)) 

377 singles = [self.Mask(bbox2) for f in range(len(self.filters))] 

378 for n in range(len(singles)): 

379 singles[n].set(value2) 

380 mMask2 = MultibandMask.fromMasks(self.filters, singles) 

381 

382 _testImageModification(self, mMask1, mMask2, self.bbox, bbox2, value1, value2) 

383 

384 def testImageCopy(self): 

385 mMask = self.mMask1 

386 value1 = self.CR 

387 value2 = self.EDGE 

388 mMask[:] = value1 

389 _testImageCopy(self, mMask, value1, value2) 

390 

391 

392def _testMaskedImageFilters(testCase, maskedImage, singleType): 

393 testCase.assertIsInstance(maskedImage["R"], singleType) 

394 testCase.assertIsInstance(maskedImage.image["G"], ImageF) 

395 testCase.assertIsInstance(maskedImage.mask["R"], Mask) 

396 testCase.assertIsInstance(maskedImage.variance["I"], ImageF) 

397 

398 testCase.assertEqual(maskedImage["G"].image.array.shape, (100, 200)) 

399 testCase.assertEqual(maskedImage[:"I"].mask.array.shape, (2, 100, 200)) 

400 testCase.assertEqual(maskedImage[:"I"].filters, ("G", "R")) 

401 testCase.assertEqual(maskedImage[:"I"].getBBox(), testCase.bbox) 

402 testCase.assertEqual(maskedImage[["G", "I"]].getBBox(), testCase.bbox) 

403 

404 testCase.assertEqual(maskedImage.filters, tuple(testCase.filters)) 

405 

406 

407def _testMaskedImageSlicing(testCase, maskedImage): 

408 subBox = Box2I(Point2I(1100, 2025), Extent2I(30, 50)) 

409 testCase.assertEqual(maskedImage[:, subBox].getBBox(), subBox) 

410 testCase.assertEqual(maskedImage[:, subBox].image.getBBox(), subBox) 

411 testCase.assertEqual(maskedImage[:, subBox].mask.getBBox(), subBox) 

412 testCase.assertEqual(maskedImage[:, subBox].variance.getBBox(), subBox) 

413 

414 maskedPixel = maskedImage[:, 1100, 2025] 

415 testCase.assertFloatsEqual(maskedPixel[0].array, np.array([10., 10., 10.])) 

416 testCase.assertFloatsEqual(maskedPixel[1].array, np.array([1, 1, 1])) 

417 testCase.assertFloatsAlmostEqual(maskedPixel[2].array, np.array([.01, .01, .01]), 1e-6) 

418 

419 newBox = Box2I(Point2I(100, 500), Extent2I(200, 100)) 

420 maskedImage.setXY0(newBox.getMin()) 

421 testCase.assertEqual(maskedImage.getBBox(), newBox) 

422 testCase.assertEqual(maskedImage.image.getBBox(), newBox) 

423 testCase.assertEqual(maskedImage.mask.getBBox(), newBox) 

424 testCase.assertEqual(maskedImage.variance.getBBox(), newBox) 

425 testCase.assertEqual(maskedImage["G"].getBBox(), newBox) 

426 testCase.assertEqual(maskedImage["G"].image.getBBox(), newBox) 

427 testCase.assertEqual(maskedImage["R"].mask.getBBox(), newBox) 

428 testCase.assertEqual(maskedImage["I"].variance.getBBox(), newBox) 

429 

430 

431def _testMaskedmageModification(testCase, maskedImage): 

432 images = [ImageF(testCase.bbox, 10*testCase.imgValue) for f in testCase.filters] 

433 mImage = MultibandImage.fromImages(testCase.filters, images) 

434 maskedImage.image.array = mImage.array 

435 testCase.assertFloatsEqual(maskedImage.image["G"].array, mImage.array[0]) 

436 testCase.assertFloatsEqual(maskedImage["G"].image.array, mImage.array[0]) 

437 

438 singles = [testCase.Mask(testCase.bbox) for f in range(len(testCase.filters))] 

439 for n in range(len(singles)): 

440 singles[n].set(testCase.maskValue*2) 

441 mMask = MultibandMask.fromMasks(testCase.filters, singles) 

442 maskedImage.mask.array = mMask.array 

443 testCase.assertFloatsEqual(maskedImage.mask["G"].array, mMask.array[0]) 

444 testCase.assertFloatsEqual(maskedImage["G"].mask.array, mMask.array[0]) 

445 

446 images = [ImageF(testCase.bbox, .1 * testCase.varValue) for f in testCase.filters] 

447 mVariance = MultibandImage.fromImages(testCase.filters, images) 

448 maskedImage.variance.array = mVariance.array 

449 testCase.assertFloatsEqual(maskedImage.variance["G"].array, mVariance.array[0]) 

450 testCase.assertFloatsEqual(maskedImage["G"].variance.array, mVariance.array[0]) 

451 

452 subBox = Box2I(Point2I(1100, 2025), Extent2I(30, 50)) 

453 maskedImage.image[:, subBox].array = 12 

454 testCase.assertFloatsEqual(maskedImage.image["G", subBox].array, 12) 

455 testCase.assertFloatsEqual(maskedImage["G", subBox].image.array, 12) 

456 maskedImage["R", subBox].image[:] = 15 

457 testCase.assertFloatsEqual(maskedImage.image["R", subBox].array, 15) 

458 testCase.assertFloatsEqual(maskedImage["R", subBox].image.array, 15) 

459 

460 maskedImage.mask[:, subBox].array = 64 

461 testCase.assertFloatsEqual(maskedImage.mask["G", subBox].array, 64) 

462 testCase.assertFloatsEqual(maskedImage["G", subBox].mask.array, 64) 

463 maskedImage["R", subBox].mask[:] = 128 

464 testCase.assertFloatsEqual(maskedImage.mask["R", subBox].array, 128) 

465 testCase.assertFloatsEqual(maskedImage["R", subBox].mask.array, 128) 

466 

467 maskedImage.variance[:, subBox].array = 1e-6 

468 testCase.assertFloatsEqual(maskedImage.variance["G", subBox].array, 1e-6) 

469 testCase.assertFloatsEqual(maskedImage["G", subBox].variance.array, 1e-6) 

470 maskedImage["R", subBox].variance[:] = 1e-7 

471 testCase.assertFloatsEqual(maskedImage.variance["R", subBox].array, 1e-7) 

472 testCase.assertFloatsEqual(maskedImage["R", subBox].variance.array, 1e-7) 

473 

474 

475def _testMaskedImageCopy(testCase, maskedImage1): 

476 maskedImage2 = maskedImage1.clone() 

477 

478 maskedImage2.setXY0(Point2I(11, 23)) 

479 testCase.assertEqual(maskedImage2.getBBox(), Box2I(Point2I(11, 23), Extent2I(200, 100))) 

480 testCase.assertEqual(maskedImage1.getBBox(), Box2I(Point2I(1000, 2000), Extent2I(200, 100))) 

481 testCase.assertTrue(np.all([img.getBBox() == maskedImage1.getBBox() for img in maskedImage1.image])) 

482 testCase.assertTrue(np.all([img.getBBox() == maskedImage2.getBBox() for img in maskedImage2.image])) 

483 

484 maskedImage2.image.array = 1 

485 testCase.assertFloatsEqual(maskedImage1.image.array, testCase.imgValue) 

486 testCase.assertFloatsEqual(maskedImage2.image.array, 1) 

487 testCase.assertFloatsEqual(maskedImage1["G"].image.array, testCase.imgValue) 

488 testCase.assertFloatsEqual(maskedImage2["G"].image.array, 1) 

489 

490 maskedImage2 = maskedImage1.clone(False) 

491 maskedImage2.image.array = 1 

492 testCase.assertFloatsEqual(maskedImage1.image.array, 1) 

493 testCase.assertFloatsEqual(maskedImage2.image.array, 1) 

494 testCase.assertFloatsEqual(maskedImage1["G"].image.array, 1) 

495 testCase.assertFloatsEqual(maskedImage2["G"].image.array, 1) 

496 

497 

498class MultibandMaskedImageTestCase(lsst.utils.tests.TestCase): 

499 """Test case for MultibandMaskedImage""" 

500 

501 def setUp(self): 

502 np.random.seed(1) 

503 self.bbox = Box2I(Point2I(1000, 2000), Extent2I(200, 100)) 

504 self.filters = ["G", "R", "I"] 

505 

506 self.imgValue = 10 

507 images = [ImageF(self.bbox, self.imgValue) for f in self.filters] 

508 mImage = MultibandImage.fromImages(self.filters, images) 

509 

510 self.Mask = Mask[MaskPixel] 

511 # Store the default mask planes for later use 

512 maskPlaneDict = self.Mask().getMaskPlaneDict() 

513 self.defaultMaskPlanes = sorted(maskPlaneDict, key=maskPlaneDict.__getitem__) 

514 

515 # reset so tests will be deterministic 

516 self.Mask.clearMaskPlaneDict() 

517 for p in ("BAD", "SAT", "INTRP", "CR", "EDGE"): 

518 self.Mask.addMaskPlane(p) 

519 

520 self.maskValue = self.Mask.getPlaneBitMask("BAD") 

521 singles = [self.Mask(self.bbox) for f in range(len(self.filters))] 

522 for n in range(len(singles)): 

523 singles[n].set(self.maskValue) 

524 mMask = MultibandMask.fromMasks(self.filters, singles) 

525 

526 self.varValue = 1e-2 

527 images = [ImageF(self.bbox, self.varValue) for f in self.filters] 

528 mVariance = MultibandImage.fromImages(self.filters, images) 

529 

530 self.maskedImage = MultibandMaskedImage(self.filters, image=mImage, mask=mMask, variance=mVariance) 

531 

532 def tearDown(self): 

533 del self.maskedImage 

534 del self.bbox 

535 del self.imgValue 

536 del self.maskValue 

537 del self.varValue 

538 # Reset the mask plane to the default 

539 self.Mask.clearMaskPlaneDict() 

540 for p in self.defaultMaskPlanes: 

541 self.Mask.addMaskPlane(p) 

542 del self.defaultMaskPlanes 

543 

544 def testFilterSlicing(self): 

545 _testMaskedImageFilters(self, self.maskedImage, MaskedImage) 

546 

547 def testImageSlicing(self): 

548 _testMaskedImageSlicing(self, self.maskedImage) 

549 

550 def testModification(self): 

551 _testMaskedmageModification(self, self.maskedImage) 

552 

553 def testCopy(self): 

554 _testMaskedImageCopy(self, self.maskedImage) 

555 

556 

557class MultibandExposureTestCase(lsst.utils.tests.TestCase): 

558 """ 

559 A test case for the Exposure Class 

560 """ 

561 

562 def setUp(self): 

563 np.random.seed(1) 

564 self.bbox = Box2I(Point2I(1000, 2000), Extent2I(200, 100)) 

565 self.filters = ["G", "R", "I"] 

566 

567 self.imgValue = 10 

568 images = [ImageF(self.bbox, self.imgValue) for f in self.filters] 

569 mImage = MultibandImage.fromImages(self.filters, images) 

570 

571 self.Mask = Mask[MaskPixel] 

572 # Store the default mask planes for later use 

573 maskPlaneDict = self.Mask().getMaskPlaneDict() 

574 self.defaultMaskPlanes = sorted(maskPlaneDict, key=maskPlaneDict.__getitem__) 

575 

576 # reset so tests will be deterministic 

577 self.Mask.clearMaskPlaneDict() 

578 for p in ("BAD", "SAT", "INTRP", "CR", "EDGE"): 

579 self.Mask.addMaskPlane(p) 

580 

581 self.maskValue = self.Mask.getPlaneBitMask("BAD") 

582 singles = [self.Mask(self.bbox) for f in range(len(self.filters))] 

583 for n in range(len(singles)): 

584 singles[n].set(self.maskValue) 

585 mMask = MultibandMask.fromMasks(self.filters, singles) 

586 

587 self.varValue = 1e-2 

588 images = [ImageF(self.bbox, self.varValue) for f in self.filters] 

589 mVariance = MultibandImage.fromImages(self.filters, images) 

590 

591 self.kernelSize = 51 

592 self.psfs = [GaussianPsf(self.kernelSize, self.kernelSize, 4.0) for f in self.filters] 

593 self.psfImage = np.array([p.computeKernelImage().array for p in self.psfs]) 

594 

595 self.exposure = MultibandExposure(image=mImage, mask=mMask, variance=mVariance, 

596 psfs=self.psfs, filters=self.filters) 

597 

598 def tearDown(self): 

599 del self.exposure 

600 del self.psfs 

601 del self.bbox 

602 del self.imgValue 

603 del self.maskValue 

604 del self.varValue 

605 # Reset the mask plane to the default 

606 self.Mask.clearMaskPlaneDict() 

607 for p in self.defaultMaskPlanes: 

608 self.Mask.addMaskPlane(p) 

609 del self.defaultMaskPlanes 

610 

611 def testConstructor(self): 

612 exposures = self.exposure.singles 

613 print(exposures[0].getPsf()) 

614 filters = self.exposure.filters 

615 newExposure = MultibandExposure.fromExposures(filters, exposures) 

616 for exposure in newExposure.singles: 

617 self.assertIsNotNone(exposure.getPsf()) 

618 

619 def testFilterSlicing(self): 

620 _testMaskedImageFilters(self, self.exposure, ExposureF) 

621 

622 def testImageSlicing(self): 

623 _testMaskedImageSlicing(self, self.exposure) 

624 

625 def testModification(self): 

626 _testMaskedmageModification(self, self.exposure) 

627 

628 def testCopy(self): 

629 _testMaskedImageCopy(self, self.exposure) 

630 

631 def testPsf(self): 

632 psfImage = self.exposure.computePsfKernelImage(self.exposure.getBBox().getCenter()) 

633 self.assertFloatsAlmostEqual(psfImage, self.psfImage) 

634 

635 newPsfs = [GaussianPsf(self.kernelSize, self.kernelSize, 1.0) for f in self.filters] 

636 newPsfImage = [p.computeImage().array for p in newPsfs] 

637 for psf, exposure in zip(newPsfs, self.exposure.singles): 

638 exposure.setPsf(psf) 

639 psfImage = self.exposure.computePsfKernelImage(self.exposure.getBBox().getCenter()) 

640 self.assertFloatsAlmostEqual(psfImage, newPsfImage) 

641 

642 psfImage = self.exposure.computePsfImage(self.exposure.getBBox().getCenter())[0] 

643 self.assertFloatsAlmostEqual(psfImage, self.exposure["G"].getPsf().computeImage().array) 

644 

645 

646class MultibandFootprintTestCase(lsst.utils.tests.TestCase): 

647 """ 

648 A test case for the Exposure Class 

649 """ 

650 

651 def setUp(self): 

652 np.random.seed(1) 

653 self.spans = SpanSet.fromShape(2, Stencil.CIRCLE) 

654 self.footprint = Footprint(self.spans) 

655 self.footprint.addPeak(3, 4, 10) 

656 self.footprint.addPeak(8, 1, 2) 

657 fp = Footprint(self.spans) 

658 for peak in self.footprint.getPeaks(): 

659 fp.addPeak(peak["f_x"], peak["f_y"], peak["peakValue"]) 

660 self.peaks = fp.getPeaks() 

661 self.bbox = self.footprint.getBBox() 

662 self.filters = ("G", "R", "I") 

663 singles = [] 

664 images = [] 

665 for n, f in enumerate(self.filters): 

666 image = ImageF(self.spans.getBBox()) 

667 image.set(n) 

668 images.append(image.array) 

669 maskedImage = MaskedImageF(image) 

670 heavy = makeHeavyFootprint(self.footprint, maskedImage) 

671 singles.append(heavy) 

672 self.image = np.array(images) 

673 self.mFoot = MultibandFootprint(self.filters, singles) 

674 

675 def tearDown(self): 

676 del self.spans 

677 del self.footprint 

678 del self.peaks 

679 del self.bbox 

680 del self.filters 

681 del self.mFoot 

682 del self.image 

683 

684 def verifyPeaks(self, peaks1, peaks2): 

685 self.assertEqual(len(peaks1), len(peaks2)) 

686 for n in range(len(peaks1)): 

687 pk1 = peaks1[n] 

688 pk2 = peaks2[n] 

689 # self.assertEqual(pk1["id"], pk2["id"]) 

690 self.assertEqual(pk1["f_x"], pk2["f_x"]) 

691 self.assertEqual(pk1["f_y"], pk2["f_y"]) 

692 self.assertEqual(pk1["i_x"], pk2["i_x"]) 

693 self.assertEqual(pk1["i_y"], pk2["i_y"]) 

694 self.assertEqual(pk1["peakValue"], pk2["peakValue"]) 

695 

696 def testConstructor(self): 

697 def projectSpans(radius, value, bbox, asArray): 

698 ss = SpanSet.fromShape(radius, Stencil.CIRCLE, offset=(10, 10)) 

699 image = ImageF(bbox) 

700 ss.setImage(image, value) 

701 if asArray: 

702 return image.array 

703 else: 

704 return image 

705 

706 def runTest(images, mFoot, peaks=self.peaks, footprintBBox=Box2I(Point2I(6, 6), Extent2I(9, 9))): 

707 self.assertEqual(mFoot.getBBox(), footprintBBox) 

708 try: 

709 fpImage = np.array(images)[:, 1:-1, 1:-1] 

710 except IndexError: 

711 fpImage = np.array([img.array for img in images])[:, 1:-1, 1:-1] 

712 # result = mFoot.getImage(fill=0).image.array 

713 self.assertFloatsAlmostEqual(mFoot.getImage(fill=0).image.array, fpImage) 

714 if peaks is not None: 

715 self.verifyPeaks(mFoot.getPeaks(), peaks) 

716 

717 bbox = Box2I(Point2I(5, 5), Extent2I(11, 11)) 

718 xy0 = Point2I(5, 5) 

719 

720 images = np.array([projectSpans(n, 5-n, bbox, True) for n in range(2, 5)]) 

721 mFoot = MultibandFootprint.fromArrays(self.filters, images, xy0=xy0, peaks=self.peaks) 

722 runTest(images, mFoot) 

723 

724 mFoot = MultibandFootprint.fromArrays(self.filters, images) 

725 runTest(images, mFoot, None, Box2I(Point2I(1, 1), Extent2I(9, 9))) 

726 

727 images = [projectSpans(n, 5-n, bbox, False) for n in range(2, 5)] 

728 mFoot = MultibandFootprint.fromImages(self.filters, images, peaks=self.peaks) 

729 runTest(images, mFoot) 

730 

731 images = np.array([projectSpans(n, n, bbox, True) for n in range(2, 5)]) 

732 mFoot = MultibandFootprint.fromArrays(self.filters, images, peaks=self.peaks, xy0=bbox.getMin()) 

733 runTest(images, mFoot) 

734 

735 images = np.array([projectSpans(n, 5-n, bbox, True) for n in range(2, 5)]) 

736 thresh = [1, 2, 2.5] 

737 mFoot = MultibandFootprint.fromArrays(self.filters, images, xy0=bbox.getMin(), thresh=thresh) 

738 footprintBBox = Box2I(Point2I(8, 8), Extent2I(5, 5)) 

739 self.assertEqual(mFoot.getBBox(), footprintBBox) 

740 

741 fpImage = np.array(images)[:, 3:-3, 3:-3] 

742 mask = np.all(fpImage <= np.array(thresh)[:, None, None], axis=0) 

743 fpImage[:, mask] = 0 

744 self.assertFloatsAlmostEqual(mFoot.getImage(fill=0).image.array, fpImage) 

745 img = mFoot.getImage().image.array 

746 img[~np.isfinite(img)] = 1.1 

747 self.assertFloatsAlmostEqual(mFoot.getImage(fill=1.1).image.array, img) 

748 

749 def testSlicing(self): 

750 self.assertIsInstance(self.mFoot["R"], HeavyFootprintF) 

751 self.assertIsInstance(self.mFoot[:], MultibandFootprint) 

752 

753 self.assertEqual(self.mFoot["I"], self.mFoot["I"]) 

754 self.assertEqual(self.mFoot[:"I"].filters, ("G", "R")) 

755 self.assertEqual(self.mFoot[:"I"].getBBox(), self.bbox) 

756 self.assertEqual(self.mFoot[["G", "I"]].filters, ("G", "I")) 

757 self.assertEqual(self.mFoot[["G", "I"]].getBBox(), self.bbox) 

758 

759 with self.assertRaises(TypeError): 

760 self.mFoot["I", 4, 5] 

761 self.mFoot["I", :, :] 

762 with self.assertRaises(IndexError): 

763 self.mFoot[:, :, :] 

764 

765 def testSpans(self): 

766 self.assertEqual(self.mFoot.getSpans(), self.spans) 

767 for footprint in self.mFoot.singles: 

768 self.assertEqual(footprint.getSpans(), self.spans) 

769 

770 def testPeaks(self): 

771 self.verifyPeaks(self.peaks, self.footprint.getPeaks()) 

772 for footprint in self.mFoot.singles: 

773 self.verifyPeaks(footprint.getPeaks(), self.peaks) 

774 

775 

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

777 pass 

778 

779 

780def setup_module(module): 

781 lsst.utils.tests.init() 

782 

783 

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

785 lsst.utils.tests.init() 

786 unittest.main()