Coverage for tests/test_isrTask.py: 11%

373 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-01 04:11 -0700

1# 

2# LSST Data Management System 

3# Copyright 2008-2017 AURA/LSST. 

4# 

5# This product includes software developed by the 

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

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

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

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

21# 

22 

23import unittest 

24import numpy as np 

25 

26import lsst.afw.image as afwImage 

27import lsst.ip.isr.isrMock as isrMock 

28import lsst.utils.tests 

29from lsst.ip.isr.isrTask import (IsrTask, IsrTaskConfig) 

30from lsst.ip.isr.isrQa import IsrQaConfig 

31from lsst.pipe.base import Struct 

32from lsst.ip.isr import PhotonTransferCurveDataset 

33 

34 

35def countMaskedPixels(maskedImage, maskPlane): 

36 """Function to count the number of masked pixels of a given type. 

37 

38 Parameters 

39 ---------- 

40 maskedImage : `lsst.afw.image.MaskedImage` 

41 Image to measure the mask on. 

42 maskPlane : `str` 

43 Name of the mask plane to count 

44 

45 Returns 

46 ------- 

47 nMask : `int` 

48 Number of masked pixels. 

49 """ 

50 bitMask = maskedImage.getMask().getPlaneBitMask(maskPlane) 

51 isBit = maskedImage.getMask().getArray() & bitMask > 0 

52 numBit = np.sum(isBit) 

53 return numBit 

54 

55 

56def computeImageMedianAndStd(image): 

57 """Function to calculate median and std of image data. 

58 

59 Parameters 

60 ---------- 

61 image : `lsst.afw.image.Image` 

62 Image to measure statistics on. 

63 

64 Returns 

65 ------- 

66 median : `float` 

67 Image median. 

68 std : `float` 

69 Image stddev. 

70 """ 

71 median = np.nanmedian(image.getArray()) 

72 std = np.nanstd(image.getArray()) 

73 return (median, std) 

74 

75 

76class IsrTaskTestCases(lsst.utils.tests.TestCase): 

77 """Test IsrTask methods with trimmed raw data. 

78 """ 

79 def setUp(self): 

80 self.config = IsrTaskConfig() 

81 self.config.overscan.doParallelOverscan = True 

82 self.config.qa = IsrQaConfig() 

83 self.task = IsrTask(config=self.config) 

84 self.camera = isrMock.IsrMock().getCamera() 

85 

86 self.inputExp = isrMock.TrimmedRawMock().run() 

87 self.amp = self.inputExp.getDetector()[0] 

88 self.mi = self.inputExp.getMaskedImage() 

89 

90 def validateIsrData(self, results): 

91 """results should be a struct with components that are 

92 not None if included in the configuration file. 

93 """ 

94 self.assertIsInstance(results, Struct) 

95 if self.config.doBias is True: 

96 self.assertIsNotNone(results.bias) 

97 if self.config.doDark is True: 

98 self.assertIsNotNone(results.dark) 

99 if self.config.doFlat is True: 

100 self.assertIsNotNone(results.flat) 

101 if self.config.doFringe is True: 

102 self.assertIsNotNone(results.fringes) 

103 if self.config.doDefect is True: 

104 self.assertIsNotNone(results.defects) 

105 if self.config.doBrighterFatter is True: 

106 self.assertIsNotNone(results.bfKernel) 

107 if self.config.doAttachTransmissionCurve is True: 

108 self.assertIsNotNone(results.opticsTransmission) 

109 self.assertIsNotNone(results.filterTransmission) 

110 self.assertIsNotNone(results.sensorTransmission) 

111 self.assertIsNotNone(results.atmosphereTransmission) 

112 

113 def test_ensureExposure(self): 

114 """Test that an exposure has a usable instance class. 

115 """ 

116 self.assertIsInstance(self.task.ensureExposure(self.inputExp, self.camera, 0), 

117 afwImage.Exposure) 

118 

119 def test_convertItoF(self): 

120 """Test conversion from integer to floating point pixels. 

121 """ 

122 result = self.task.convertIntToFloat(self.inputExp) 

123 self.assertEqual(result.getImage().getArray().dtype, np.dtype("float32")) 

124 self.assertEqual(result, self.inputExp) 

125 

126 def test_updateVariance(self): 

127 """Expect The variance image should have a larger median value after 

128 this operation. 

129 """ 

130 ampName = self.amp.getName() 

131 effectivePtc = PhotonTransferCurveDataset([ampName], "TEST_PTC", 1) 

132 effectivePtc.gain[ampName] = self.amp.getGain() 

133 effectivePtc.noise[ampName] = self.amp.getReadNoise() 

134 statBefore = computeImageMedianAndStd(self.inputExp.variance[self.amp.getBBox()]) 

135 # effectivePtc will have noise and gain. 

136 self.task.updateVariance(self.inputExp, self.amp, effectivePtc) 

137 statAfter = computeImageMedianAndStd(self.inputExp.variance[self.amp.getBBox()]) 

138 self.assertGreater(statAfter[0], statBefore[0]) 

139 self.assertFloatsAlmostEqual(statBefore[0], 0.0, atol=1e-2) 

140 self.assertFloatsAlmostEqual(statAfter[0], 8170.0195, atol=1e-2) 

141 

142 def test_defineEffectivePtc(self): 

143 ampName = self.amp.getName() 

144 inputPtc = PhotonTransferCurveDataset([ampName], "TEST_PTC", 1) 

145 inputPtc.gain[ampName] = 1.2 

146 inputPtc.noise[ampName] = 5 

147 

148 exposureMetadata = self.inputExp.getMetadata() 

149 detector = self.inputExp.getDetector() 

150 overscans = [self.task.overscanCorrection(self.inputExp, self.amp)] 

151 bfGains = {ampName: 1.5} 

152 

153 # Defaults 

154 # doEmpiricalReadNoise = False 

155 # usePtcReadNoise = False 

156 # usePtcGains = False 

157 # doRaiseOnCalibMismatch= False 

158 effectivePtc = self.task.defineEffectivePtc(inputPtc, detector, bfGains, 

159 overscans, 

160 exposureMetadata) 

161 self.assertEqual(effectivePtc.gain[ampName], self.amp.getGain()) 

162 self.assertEqual(effectivePtc.noise[ampName], self.amp.getReadNoise()) 

163 

164 # Use input PTC values 

165 self.config.usePtcGains = True 

166 self.config.usePtcReadNoise = True 

167 effectivePtc = self.task.defineEffectivePtc(inputPtc, detector, bfGains, 

168 overscans, 

169 exposureMetadata) 

170 self.assertEqual(effectivePtc.gain[ampName], inputPtc.gain[ampName]) 

171 self.assertEqual(effectivePtc.noise[ampName], inputPtc.noise[ampName]) 

172 

173 # use empirical readout noise from overscan and PTC gain 

174 self.config.usePtcGains = True 

175 self.config.doEmpiricalReadNoise = True 

176 effectivePtc = self.task.defineEffectivePtc(inputPtc, detector, bfGains, 

177 overscans, 

178 exposureMetadata) 

179 self.assertFloatsAlmostEqual(effectivePtc.noise[ampName], 39.8794613621691) 

180 self.assertEqual(effectivePtc.gain[ampName], inputPtc.gain[ampName]) 

181 

182 # Raise if the PTC and BFK gains don't match 

183 results = None 

184 with self.assertRaises(RuntimeError): 

185 self.config.doRaiseOnCalibMismatch = True 

186 results = self.task.defineEffectivePtc(inputPtc, detector, bfGains, 

187 overscans, 

188 exposureMetadata) 

189 self.assertIsNone(results) 

190 

191 def test_darkCorrection(self): 

192 """Expect the median image value should decrease after this operation. 

193 """ 

194 darkIm = isrMock.DarkMock().run() 

195 

196 statBefore = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()]) 

197 self.task.darkCorrection(self.inputExp, darkIm) 

198 statAfter = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()]) 

199 self.assertLess(statAfter[0], statBefore[0]) 

200 self.assertFloatsAlmostEqual(statBefore[0], 8070.0195, atol=1e-2) 

201 self.assertFloatsAlmostEqual(statAfter[0], 8045.7773, atol=1e-2) 

202 

203 def test_darkCorrection_noVisitInfo(self): 

204 """Expect the median image value should decrease after this operation. 

205 """ 

206 darkIm = isrMock.DarkMock().run() 

207 darkIm.getInfo().setVisitInfo(None) 

208 

209 statBefore = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()]) 

210 self.task.darkCorrection(self.inputExp, darkIm) 

211 statAfter = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()]) 

212 self.assertLess(statAfter[0], statBefore[0]) 

213 self.assertFloatsAlmostEqual(statBefore[0], 8070.0195, atol=1e-2) 

214 self.assertFloatsAlmostEqual(statAfter[0], 8045.7773, atol=1e-2) 

215 

216 def test_flatCorrection(self): 

217 """Expect the image median should increase (divide by < 1). 

218 """ 

219 flatIm = isrMock.FlatMock().run() 

220 

221 statBefore = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()]) 

222 self.task.flatCorrection(self.inputExp, flatIm) 

223 statAfter = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()]) 

224 self.assertGreater(statAfter[1], statBefore[1]) 

225 self.assertFloatsAlmostEqual(statAfter[1], 147407.02, atol=1e-2) 

226 self.assertFloatsAlmostEqual(statBefore[1], 147.55304, atol=1e-2) 

227 

228 def test_saturationDetection(self): 

229 """Expect the saturation level detection/masking to scale with 

230 threshold. 

231 """ 

232 ampB = self.amp.rebuild() 

233 ampB.setSaturation(9000.0) 

234 self.task.saturationDetection(self.inputExp, ampB.finish()) 

235 countBefore = countMaskedPixels(self.mi, "SAT") 

236 

237 ampB.setSaturation(8250.0) 

238 self.task.saturationDetection(self.inputExp, ampB.finish()) 

239 countAfter = countMaskedPixels(self.mi, "SAT") 

240 

241 self.assertLessEqual(countBefore, countAfter) 

242 self.assertEqual(countBefore, 43) 

243 self.assertEqual(countAfter, 136) 

244 

245 def test_measureBackground(self): 

246 """Expect the background measurement runs successfully and to save 

247 metadata values. 

248 """ 

249 self.config.qa.flatness.meshX = 20 

250 self.config.qa.flatness.meshY = 20 

251 self.task.measureBackground(self.inputExp, self.config.qa) 

252 self.assertIsNotNone(self.inputExp.getMetadata().getScalar('SKYLEVEL')) 

253 

254 def test_flatContext(self): 

255 """Expect the flat context manager runs successfully (applying both 

256 flat and dark within the context), and results in the same 

257 image data after completion. 

258 """ 

259 darkExp = isrMock.DarkMock().run() 

260 flatExp = isrMock.FlatMock().run() 

261 

262 mi = self.inputExp.getMaskedImage().clone() 

263 with self.task.flatContext(self.inputExp, flatExp, darkExp): 

264 contextStat = computeImageMedianAndStd(self.inputExp.getMaskedImage().getImage()) 

265 self.assertFloatsAlmostEqual(contextStat[0], 37165.594, atol=1e-2) 

266 

267 self.assertMaskedImagesAlmostEqual(mi, self.inputExp.getMaskedImage()) 

268 

269 

270class IsrTaskUnTrimmedTestCases(lsst.utils.tests.TestCase): 

271 """Test IsrTask methods using untrimmed raw data. 

272 """ 

273 def setUp(self): 

274 self.config = IsrTaskConfig() 

275 self.config.overscan.doParallelOverscan = True 

276 self.config.qa = IsrQaConfig() 

277 self.task = IsrTask(config=self.config) 

278 

279 self.mockConfig = isrMock.IsrMockConfig() 

280 self.mockConfig.isTrimmed = False 

281 self.doGenerateImage = True 

282 self.dataContainer = isrMock.MockDataContainer(config=self.mockConfig) 

283 self.camera = isrMock.IsrMock(config=self.mockConfig).getCamera() 

284 

285 self.inputExp = isrMock.RawMock(config=self.mockConfig).run() 

286 self.amp = self.inputExp.getDetector()[0] 

287 self.mi = self.inputExp.getMaskedImage() 

288 

289 def batchSetConfiguration(self, value): 

290 """Set the configuration state to a consistent value. 

291 

292 Disable options we do not need as well. 

293 

294 Parameters 

295 ---------- 

296 value : `bool` 

297 Value to switch common ISR configuration options to. 

298 """ 

299 self.config.qa.flatness.meshX = 20 

300 self.config.qa.flatness.meshY = 20 

301 self.config.doWrite = False 

302 self.config.doLinearize = False 

303 self.config.doCrosstalk = False 

304 

305 self.config.doConvertIntToFloat = value 

306 self.config.doSaturation = value 

307 self.config.doSuspect = value 

308 self.config.doSetBadRegions = value 

309 self.config.doOverscan = value 

310 self.config.doBias = value 

311 self.config.doVariance = value 

312 self.config.doWidenSaturationTrails = value 

313 self.config.doBrighterFatter = value 

314 self.config.doDefect = value 

315 self.config.doSaturationInterpolation = value 

316 self.config.doDark = value 

317 self.config.doStrayLight = value 

318 self.config.doFlat = value 

319 self.config.doFringe = value 

320 self.config.doMeasureBackground = value 

321 self.config.doVignette = value 

322 self.config.doAttachTransmissionCurve = value 

323 self.config.doUseOpticsTransmission = value 

324 self.config.doUseFilterTransmission = value 

325 self.config.doUseSensorTransmission = value 

326 self.config.doUseAtmosphereTransmission = value 

327 self.config.qa.saveStats = value 

328 self.config.qa.doThumbnailOss = value 

329 self.config.qa.doThumbnailFlattened = value 

330 

331 self.config.doApplyGains = not value 

332 self.config.doCameraSpecificMasking = value 

333 

334 def validateIsrResults(self): 

335 """results should be a struct with components that are 

336 not None if included in the configuration file. 

337 

338 Returns 

339 ------- 

340 results : `pipeBase.Struct` 

341 Results struct generated from the current ISR configuration. 

342 """ 

343 self.task = IsrTask(config=self.config) 

344 results = self.task.run(self.inputExp, 

345 camera=self.camera, 

346 bias=self.dataContainer.get("bias"), 

347 dark=self.dataContainer.get("dark"), 

348 flat=self.dataContainer.get("flat"), 

349 bfKernel=self.dataContainer.get("bfKernel"), 

350 defects=self.dataContainer.get("defects"), 

351 fringes=Struct(fringes=self.dataContainer.get("fringe"), seed=1234), 

352 opticsTransmission=self.dataContainer.get("transmission_"), 

353 filterTransmission=self.dataContainer.get("transmission_"), 

354 sensorTransmission=self.dataContainer.get("transmission_"), 

355 atmosphereTransmission=self.dataContainer.get("transmission_") 

356 ) 

357 

358 self.assertIsInstance(results, Struct) 

359 self.assertIsInstance(results.exposure, afwImage.Exposure) 

360 return results 

361 

362 def test_run_allTrue(self): 

363 """Expect successful run with expected outputs when all non-exclusive 

364 configuration options are on. 

365 

366 Output results should be tested more precisely by the 

367 individual function tests. 

368 

369 """ 

370 self.batchSetConfiguration(True) 

371 self.validateIsrResults() 

372 

373 def test_run_allFalse(self): 

374 """Expect successful run with expected outputs when all non-exclusive 

375 configuration options are off. 

376 

377 Output results should be tested more precisely by the 

378 individual function tests. 

379 

380 """ 

381 self.batchSetConfiguration(False) 

382 self.validateIsrResults() 

383 

384 def test_failCases(self): 

385 """Expect failure with crosstalk enabled. 

386 

387 Output results should be tested more precisely by the 

388 individual function tests. 

389 """ 

390 self.batchSetConfiguration(True) 

391 

392 # This breaks it 

393 self.config.doCrosstalk = True 

394 

395 with self.assertRaises(RuntimeError): 

396 self.validateIsrResults() 

397 

398 def test_maskingCase_negativeVariance(self): 

399 """Test masking cases of configuration parameters. 

400 """ 

401 self.batchSetConfiguration(True) 

402 self.config.overscan.doParallelOverscan = False 

403 self.config.overscan.fitType = "POLY" 

404 self.config.overscan.order = 1 

405 

406 self.config.doSaturation = False 

407 self.config.doWidenSaturationTrails = False 

408 self.config.doSaturationInterpolation = False 

409 self.config.doSuspect = False 

410 self.config.doSetBadRegions = False 

411 self.config.doDefect = False 

412 self.config.doBrighterFatter = False 

413 

414 self.config.maskNegativeVariance = True 

415 self.config.doInterpolate = False 

416 

417 results = self.validateIsrResults() 

418 

419 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

420 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0) 

421 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0) 

422 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 40800) 

423 

424 def test_maskingCase_noMasking(self): 

425 """Test masking cases of configuration parameters. 

426 """ 

427 self.batchSetConfiguration(True) 

428 self.config.overscan.fitType = "POLY" 

429 self.config.overscan.order = 1 

430 

431 self.config.doSaturation = False 

432 self.config.doWidenSaturationTrails = False 

433 self.config.doSaturationInterpolation = False 

434 self.config.doSuspect = False 

435 self.config.doSetBadRegions = False 

436 self.config.doDefect = False 

437 self.config.doBrighterFatter = False 

438 

439 self.config.maskNegativeVariance = False 

440 self.config.doInterpolate = False 

441 

442 results = self.validateIsrResults() 

443 

444 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

445 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0) 

446 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0) 

447 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0) 

448 

449 def test_maskingCase_satMasking(self): 

450 """Test masking cases of configuration parameters. 

451 """ 

452 self.batchSetConfiguration(True) 

453 self.config.overscan.fitType = "POLY" 

454 self.config.overscan.order = 1 

455 

456 self.config.saturation = 20000.0 

457 self.config.doSaturation = True 

458 self.config.doWidenSaturationTrails = True 

459 

460 self.config.doSaturationInterpolation = False 

461 self.config.doSuspect = False 

462 self.config.doSetBadRegions = False 

463 self.config.doDefect = False 

464 self.config.doBrighterFatter = False 

465 

466 self.config.maskNegativeVariance = False # These are mock images. 

467 

468 results = self.validateIsrResults() 

469 

470 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

471 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0) 

472 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0) 

473 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0) 

474 

475 def test_maskingCase_satMaskingAndInterp(self): 

476 """Test masking cases of configuration parameters. 

477 """ 

478 self.batchSetConfiguration(True) 

479 self.config.overscan.fitType = "POLY" 

480 self.config.overscan.order = 1 

481 

482 self.config.saturation = 20000.0 

483 self.config.doSaturation = True 

484 self.config.doWidenSaturationTrails = True 

485 self.config.doSaturationInterpolation = True 

486 

487 self.config.doSuspect = False 

488 self.config.doSetBadRegions = False 

489 self.config.doDefect = False 

490 self.config.doBrighterFatter = False 

491 

492 self.config.maskNegativeVariance = False # These are mock images. 

493 

494 results = self.validateIsrResults() 

495 

496 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

497 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0) 

498 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0) 

499 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0) 

500 

501 def test_maskingCase_throughEdge(self): 

502 """Test masking cases of configuration parameters. 

503 """ 

504 self.batchSetConfiguration(True) 

505 self.config.overscan.fitType = "POLY" 

506 self.config.overscan.order = 1 

507 

508 self.config.saturation = 20000.0 

509 self.config.doSaturation = True 

510 self.config.doWidenSaturationTrails = True 

511 self.config.doSaturationInterpolation = True 

512 self.config.numEdgeSuspect = 5 

513 self.config.doSuspect = True 

514 

515 self.config.doSetBadRegions = False 

516 self.config.doDefect = False 

517 self.config.doBrighterFatter = False 

518 

519 self.config.maskNegativeVariance = False # These are mock images. 

520 

521 results = self.validateIsrResults() 

522 

523 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

524 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0) 

525 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0) 

526 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0) 

527 

528 def test_maskingCase_throughDefects(self): 

529 """Test masking cases of configuration parameters. 

530 """ 

531 self.batchSetConfiguration(True) 

532 self.config.overscan.fitType = "POLY" 

533 self.config.overscan.order = 1 

534 

535 self.config.saturation = 20000.0 

536 self.config.doSaturation = True 

537 self.config.doWidenSaturationTrails = True 

538 self.config.doSaturationInterpolation = True 

539 self.config.numEdgeSuspect = 5 

540 self.config.doSuspect = True 

541 self.config.doDefect = True 

542 

543 self.config.doSetBadRegions = False 

544 self.config.doBrighterFatter = False 

545 

546 self.config.maskNegativeVariance = False # These are mock images. 

547 

548 results = self.validateIsrResults() 

549 

550 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

551 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000) 

552 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 3940) 

553 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000) 

554 

555 def test_maskingCase_throughDefectsAmpEdges(self): 

556 """Test masking cases of configuration parameters. 

557 """ 

558 self.batchSetConfiguration(True) 

559 self.config.overscan.fitType = "POLY" 

560 self.config.overscan.order = 1 

561 

562 self.config.saturation = 20000.0 

563 self.config.doSaturation = True 

564 self.config.doWidenSaturationTrails = True 

565 self.config.doSaturationInterpolation = True 

566 self.config.numEdgeSuspect = 5 

567 self.config.doSuspect = True 

568 self.config.doDefect = True 

569 self.config.edgeMaskLevel = 'AMP' 

570 

571 self.config.doSetBadRegions = False 

572 self.config.doBrighterFatter = False 

573 

574 self.config.maskNegativeVariance = False # These are mock images. 

575 

576 results = self.validateIsrResults() 

577 

578 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

579 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000) 

580 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 11280) 

581 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000) 

582 

583 def test_maskingCase_throughBad(self): 

584 """Test masking cases of configuration parameters. 

585 """ 

586 self.batchSetConfiguration(True) 

587 self.config.overscan.fitType = "POLY" 

588 self.config.overscan.order = 1 

589 

590 self.config.saturation = 20000.0 

591 self.config.doSaturation = True 

592 self.config.doWidenSaturationTrails = True 

593 self.config.doSaturationInterpolation = True 

594 

595 self.config.doSuspect = True 

596 self.config.doDefect = True 

597 self.config.doSetBadRegions = True 

598 self.config.doBrighterFatter = False 

599 

600 self.config.maskNegativeVariance = False # These are mock images. 

601 

602 results = self.validateIsrResults() 

603 

604 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0) 

605 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000) 

606 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0) 

607 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000) 

608 

609 def test_binnedExposures(self): 

610 """Ensure that binned exposures have correct sizes.""" 

611 self.batchSetConfiguration(True) 

612 self.config.doBinnedExposures = True 

613 self.config.binFactor1 = 8 

614 self.config.binFactor2 = 64 

615 

616 results = self.validateIsrResults() 

617 

618 original = results.exposure.image.array.shape 

619 bin1 = results.outputBin1Exposure.image.array.shape 

620 bin2 = results.outputBin2Exposure.image.array.shape 

621 

622 # Binning truncates, so check that the original and obtained 

623 # binned images have the correct offset. 

624 self.assertEqual(original[0] - bin1[0] * 8, 4) 

625 self.assertEqual(original[1] - bin1[1] * 8, 0) 

626 self.assertEqual(original[0] - bin2[0] * 64, 12) 

627 self.assertEqual(original[1] - bin2[1] * 64, 8) 

628 

629 

630class MemoryTester(lsst.utils.tests.MemoryTestCase): 

631 pass 

632 

633 

634def setup_module(module): 

635 lsst.utils.tests.init() 

636 

637 

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

639 lsst.utils.tests.init() 

640 unittest.main(failfast=True)