Coverage for tests/test_isrTask.py: 92%
410 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-17 09:14 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-17 09:14 +0000
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#
23import unittest
24import unittest.mock
25import numpy as np
27import lsst.afw.image as afwImage
28import lsst.ip.isr.isrMock as isrMock
29import lsst.utils.tests
30from lsst.ip.isr.isrTask import (IsrTask, IsrTaskConfig)
31from lsst.ip.isr.masking import DECamEdgeBleedMaskTask
32from lsst.ip.isr.isrQa import IsrQaConfig
33from lsst.pipe.base import Struct
34from lsst.ip.isr import PhotonTransferCurveDataset
37def countMaskedPixels(maskedImage, maskPlane):
38 """Function to count the number of masked pixels of a given type.
40 Parameters
41 ----------
42 maskedImage : `lsst.afw.image.MaskedImage`
43 Image to measure the mask on.
44 maskPlane : `str`
45 Name of the mask plane to count
47 Returns
48 -------
49 nMask : `int`
50 Number of masked pixels.
51 """
52 bitMask = maskedImage.getMask().getPlaneBitMask(maskPlane)
53 isBit = maskedImage.getMask().getArray() & bitMask > 0
54 numBit = np.sum(isBit)
55 return numBit
58def computeImageMedianAndStd(image):
59 """Function to calculate median and std of image data.
61 Parameters
62 ----------
63 image : `lsst.afw.image.Image`
64 Image to measure statistics on.
66 Returns
67 -------
68 median : `float`
69 Image median.
70 std : `float`
71 Image stddev.
72 """
73 median = np.nanmedian(image.getArray())
74 std = np.nanstd(image.getArray())
75 return (median, std)
78class IsrTaskTestCases(lsst.utils.tests.TestCase):
79 """Test IsrTask methods with trimmed raw data.
80 """
81 def setUp(self):
82 self.config = IsrTaskConfig()
83 self.config.overscan.doParallelOverscan = True
84 self.config.qa = IsrQaConfig()
85 self.task = IsrTask(config=self.config)
86 self.camera = isrMock.IsrMock().getCamera()
88 self.inputExp = isrMock.TrimmedRawMock().run()
89 self.amp = self.inputExp.getDetector()[0]
90 self.mi = self.inputExp.getMaskedImage()
92 def validateIsrData(self, results):
93 """results should be a struct with components that are
94 not None if included in the configuration file.
95 """
96 self.assertIsInstance(results, Struct)
97 if self.config.doBias is True:
98 self.assertIsNotNone(results.bias)
99 if self.config.doDark is True:
100 self.assertIsNotNone(results.dark)
101 if self.config.doFlat is True:
102 self.assertIsNotNone(results.flat)
103 if self.config.doFringe is True:
104 self.assertIsNotNone(results.fringes)
105 if self.config.doDefect is True:
106 self.assertIsNotNone(results.defects)
107 if self.config.doBrighterFatter is True:
108 self.assertIsNotNone(results.bfKernel)
109 if self.config.doAttachTransmissionCurve is True:
110 self.assertIsNotNone(results.opticsTransmission)
111 self.assertIsNotNone(results.filterTransmission)
112 self.assertIsNotNone(results.sensorTransmission)
113 self.assertIsNotNone(results.atmosphereTransmission)
115 def test_ensureExposure(self):
116 """Test that an exposure has a usable instance class.
117 """
118 self.assertIsInstance(self.task.ensureExposure(self.inputExp, self.camera, 0),
119 afwImage.Exposure)
121 def test_convertItoF(self):
122 """Test conversion from integer to floating point pixels.
123 """
124 result = self.task.convertIntToFloat(self.inputExp)
125 self.assertEqual(result.getImage().getArray().dtype, np.dtype("float32"))
126 self.assertEqual(result, self.inputExp)
128 def test_updateVariance(self):
129 """Expect The variance image should have a larger median value after
130 this operation.
131 """
132 ampName = self.amp.getName()
133 effectivePtc = PhotonTransferCurveDataset([ampName], "TEST_PTC", 1)
134 effectivePtc.gain[ampName] = self.amp.getGain()
135 effectivePtc.noise[ampName] = self.amp.getReadNoise()
136 statBefore = computeImageMedianAndStd(self.inputExp.variance[self.amp.getBBox()])
137 # effectivePtc will have noise and gain.
138 self.task.updateVariance(self.inputExp, self.amp, effectivePtc)
139 statAfter = computeImageMedianAndStd(self.inputExp.variance[self.amp.getBBox()])
140 self.assertGreater(statAfter[0], statBefore[0])
141 self.assertFloatsAlmostEqual(statBefore[0], 0.0, atol=1e-2)
142 self.assertFloatsAlmostEqual(statAfter[0], 8170.0195, atol=1e-2)
144 def test_defineEffectivePtc(self):
145 ampName = self.amp.getName()
146 inputPtc = PhotonTransferCurveDataset([ampName], "TEST_PTC", 1)
147 inputPtc.gain[ampName] = 1.2
148 inputPtc.noise[ampName] = 5
150 exposureMetadata = self.inputExp.getMetadata()
151 detector = self.inputExp.getDetector()
152 overscans = [self.task.overscanCorrection(self.inputExp, self.amp)]
153 bfGains = {ampName: 1.5}
155 # Defaults
156 # doEmpiricalReadNoise = False
157 # usePtcReadNoise = False
158 # usePtcGains = False
159 # doRaiseOnCalibMismatch= False
160 effectivePtc = self.task.defineEffectivePtc(inputPtc, detector, bfGains,
161 overscans,
162 exposureMetadata)
163 self.assertEqual(effectivePtc.gain[ampName], self.amp.getGain())
164 self.assertEqual(effectivePtc.noise[ampName], self.amp.getReadNoise())
166 # Use input PTC values
167 self.config.usePtcGains = True
168 self.config.usePtcReadNoise = True
169 effectivePtc = self.task.defineEffectivePtc(inputPtc, detector, bfGains,
170 overscans,
171 exposureMetadata)
172 self.assertEqual(effectivePtc.gain[ampName], inputPtc.gain[ampName])
173 self.assertEqual(effectivePtc.noise[ampName], inputPtc.noise[ampName])
175 # use empirical readout noise from overscan and PTC gain
176 self.config.usePtcGains = True
177 self.config.doEmpiricalReadNoise = True
178 effectivePtc = self.task.defineEffectivePtc(inputPtc, detector, bfGains,
179 overscans,
180 exposureMetadata)
181 self.assertFloatsAlmostEqual(
182 effectivePtc.noise[ampName],
183 39.8794613621691*effectivePtc.gain[ampName],
184 )
185 self.assertEqual(effectivePtc.gain[ampName], inputPtc.gain[ampName])
187 # Raise if the PTC and BFK gains don't match
188 results = None
189 with self.assertRaises(RuntimeError):
190 self.config.doRaiseOnCalibMismatch = True
191 results = self.task.defineEffectivePtc(inputPtc, detector, bfGains,
192 overscans,
193 exposureMetadata)
194 self.assertIsNone(results)
196 def test_darkCorrection(self):
197 """Expect the median image value should decrease after this operation.
198 """
199 darkIm = isrMock.DarkMock().run()
201 statBefore = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()])
202 self.task.darkCorrection(self.inputExp, darkIm)
203 statAfter = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()])
204 self.assertLess(statAfter[0], statBefore[0])
205 self.assertFloatsAlmostEqual(statBefore[0], 8070.0195, atol=1e-2)
206 self.assertFloatsAlmostEqual(statAfter[0], 8045.7773, atol=1e-2)
208 def test_darkCorrection_noVisitInfo(self):
209 """Expect the median image value should decrease after this operation.
210 """
211 darkIm = isrMock.DarkMock().run()
212 darkIm.getInfo().setVisitInfo(None)
214 statBefore = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()])
215 self.task.darkCorrection(self.inputExp, darkIm)
216 statAfter = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()])
217 self.assertLess(statAfter[0], statBefore[0])
218 self.assertFloatsAlmostEqual(statBefore[0], 8070.0195, atol=1e-2)
219 self.assertFloatsAlmostEqual(statAfter[0], 8045.7773, atol=1e-2)
221 def test_flatCorrection(self):
222 """Expect the image median should increase (divide by < 1).
223 """
224 flatIm = isrMock.FlatMock().run()
226 statBefore = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()])
227 self.task.flatCorrection(self.inputExp, flatIm)
228 statAfter = computeImageMedianAndStd(self.inputExp.image[self.amp.getBBox()])
229 self.assertGreater(statAfter[1], statBefore[1])
230 self.assertFloatsAlmostEqual(statAfter[1], 147407.02, atol=1e-2)
231 self.assertFloatsAlmostEqual(statBefore[1], 147.55304, atol=1e-2)
233 def test_saturationDetection(self):
234 """Expect the saturation level detection/masking to scale with
235 threshold.
236 """
237 ampB = self.amp.rebuild()
238 ampB.setSaturation(9000.0)
239 self.task.saturationDetection(self.inputExp, ampB.finish())
240 countBefore = countMaskedPixels(self.mi, "SAT")
242 ampB.setSaturation(8250.0)
243 self.task.saturationDetection(self.inputExp, ampB.finish())
244 countAfter = countMaskedPixels(self.mi, "SAT")
246 self.assertLessEqual(countBefore, countAfter)
247 self.assertEqual(countBefore, 43)
248 self.assertEqual(countAfter, 136)
250 def test_measureBackground(self):
251 """Expect the background measurement runs successfully and to save
252 metadata values.
253 """
254 self.config.qa.flatness.meshX = 20
255 self.config.qa.flatness.meshY = 20
256 self.task.measureBackground(self.inputExp, self.config.qa)
257 self.assertIsNotNone(self.inputExp.getMetadata().getScalar('SKYLEVEL'))
259 def test_flatContext(self):
260 """Expect the flat context manager runs successfully (applying both
261 flat and dark within the context), and results in the same
262 image data after completion.
263 """
264 darkExp = isrMock.DarkMock().run()
265 flatExp = isrMock.FlatMock().run()
267 mi = self.inputExp.getMaskedImage().clone()
268 with self.task.flatContext(self.inputExp, flatExp, darkExp):
269 contextStat = computeImageMedianAndStd(self.inputExp.getMaskedImage().getImage())
270 self.assertFloatsAlmostEqual(contextStat[0], 37165.594, atol=1e-2)
272 self.assertMaskedImagesAlmostEqual(mi, self.inputExp.getMaskedImage())
275class IsrTaskUnTrimmedTestCases(lsst.utils.tests.TestCase):
276 """Test IsrTask methods using untrimmed raw data.
277 """
278 def setUp(self):
279 self.config = IsrTaskConfig()
280 self.config.overscan.doParallelOverscan = True
281 self.config.qa = IsrQaConfig()
282 self.task = IsrTask(config=self.config)
284 self.mockConfig = isrMock.IsrMockConfig()
285 self.mockConfig.isTrimmed = False
286 self.doGenerateImage = True
287 self.dataContainer = isrMock.MockDataContainer(config=self.mockConfig)
288 self.camera = isrMock.IsrMock(config=self.mockConfig).getCamera()
290 self.inputExp = isrMock.RawMock(config=self.mockConfig).run()
291 self.amp = self.inputExp.getDetector()[0]
292 self.mi = self.inputExp.getMaskedImage()
294 def batchSetConfiguration(self, value):
295 """Set the configuration state to a consistent value.
297 Disable options we do not need as well.
299 Parameters
300 ----------
301 value : `bool`
302 Value to switch common ISR configuration options to.
303 """
304 self.config.qa.flatness.meshX = 20
305 self.config.qa.flatness.meshY = 20
306 self.config.doWrite = False
307 self.config.doLinearize = False
308 self.config.doCrosstalk = False
310 self.config.doConvertIntToFloat = value
311 self.config.doSaturation = value
312 self.config.doSuspect = value
313 self.config.doSetBadRegions = value
314 self.config.doOverscan = value
315 self.config.doBias = value
316 self.config.doVariance = value
317 self.config.doWidenSaturationTrails = value
318 self.config.doBrighterFatter = value
319 self.config.doDefect = value
320 self.config.doSaturationInterpolation = value
321 self.config.doDark = value
322 self.config.doStrayLight = value
323 self.config.doFlat = value
324 self.config.doFringe = value
325 self.config.doMeasureBackground = value
326 self.config.doVignette = value
327 self.config.doAttachTransmissionCurve = value
328 self.config.doUseOpticsTransmission = value
329 self.config.doUseFilterTransmission = value
330 self.config.doUseSensorTransmission = value
331 self.config.doUseAtmosphereTransmission = value
332 self.config.qa.saveStats = value
333 self.config.qa.doThumbnailOss = value
334 self.config.qa.doThumbnailFlattened = value
336 self.config.doApplyGains = not value
337 self.config.doCameraSpecificMasking = value
339 def validateIsrResults(self):
340 """results should be a struct with components that are
341 not None if included in the configuration file.
343 Returns
344 -------
345 results : `pipeBase.Struct`
346 Results struct generated from the current ISR configuration.
347 """
348 self.task = IsrTask(config=self.config)
349 results = self.task.run(self.inputExp,
350 camera=self.camera,
351 bias=self.dataContainer.get("bias"),
352 dark=self.dataContainer.get("dark"),
353 flat=self.dataContainer.get("flat"),
354 bfKernel=self.dataContainer.get("bfKernel"),
355 defects=self.dataContainer.get("defects"),
356 fringes=Struct(fringes=self.dataContainer.get("fringe"), seed=1234),
357 opticsTransmission=self.dataContainer.get("transmission_"),
358 filterTransmission=self.dataContainer.get("transmission_"),
359 sensorTransmission=self.dataContainer.get("transmission_"),
360 atmosphereTransmission=self.dataContainer.get("transmission_")
361 )
363 self.assertIsInstance(results, Struct)
364 self.assertIsInstance(results.exposure, afwImage.Exposure)
365 return results
367 def test_run_allTrue(self):
368 """Expect successful run with expected outputs when all non-exclusive
369 configuration options are on.
371 Output results should be tested more precisely by the
372 individual function tests.
374 """
375 self.batchSetConfiguration(True)
376 self.validateIsrResults()
378 def test_run_allFalse(self):
379 """Expect successful run with expected outputs when all non-exclusive
380 configuration options are off.
382 Output results should be tested more precisely by the
383 individual function tests.
385 """
386 self.batchSetConfiguration(False)
387 self.validateIsrResults()
389 def test_failCases(self):
390 """Expect failure with crosstalk enabled.
392 Output results should be tested more precisely by the
393 individual function tests.
394 """
395 self.batchSetConfiguration(True)
397 # This breaks it
398 self.config.doCrosstalk = True
400 with self.assertRaises(RuntimeError):
401 self.validateIsrResults()
403 def test_maskingCase_negativeVariance(self):
404 """Test masking cases of configuration parameters.
405 """
406 self.batchSetConfiguration(True)
407 self.config.overscan.doParallelOverscan = False
408 self.config.overscan.fitType = "POLY"
409 self.config.overscan.order = 1
411 self.config.doSaturation = False
412 self.config.doWidenSaturationTrails = False
413 self.config.doSaturationInterpolation = False
414 self.config.doSuspect = False
415 self.config.doSetBadRegions = False
416 self.config.doDefect = False
417 self.config.doBrighterFatter = False
419 self.config.maskNegativeVariance = True
420 self.config.doInterpolate = False
422 results = self.validateIsrResults()
424 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
425 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
426 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
427 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 40800)
429 def test_maskingCase_noMasking(self):
430 """Test masking cases of configuration parameters.
431 """
432 self.batchSetConfiguration(True)
433 self.config.overscan.fitType = "POLY"
434 self.config.overscan.order = 1
436 self.config.doSaturation = False
437 self.config.doWidenSaturationTrails = False
438 self.config.doSaturationInterpolation = False
439 self.config.doSuspect = False
440 self.config.doSetBadRegions = False
441 self.config.doDefect = False
442 self.config.doBrighterFatter = False
444 self.config.maskNegativeVariance = False
445 self.config.doInterpolate = False
447 results = self.validateIsrResults()
449 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
450 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
451 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
452 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)
454 def test_maskingCase_satMasking(self):
455 """Test masking cases of configuration parameters.
456 """
457 self.batchSetConfiguration(True)
458 self.config.overscan.fitType = "POLY"
459 self.config.overscan.order = 1
461 self.config.saturation = 20000.0
462 self.config.doSaturation = True
463 self.config.doWidenSaturationTrails = True
465 self.config.doSaturationInterpolation = False
466 self.config.doSuspect = False
467 self.config.doSetBadRegions = False
468 self.config.doDefect = False
469 self.config.doBrighterFatter = False
471 self.config.maskNegativeVariance = False # These are mock images.
473 results = self.validateIsrResults()
475 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
476 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
477 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
478 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)
480 def test_maskingCase_decamEdgeBleedRetarget(self):
481 """Test that the DECam edge bleed masking subtask can be retargeted
482 into the camera-specific masking slot and its config reaches the
483 function.
484 """
485 self.batchSetConfiguration(True)
486 self.config.overscan.fitType = "POLY"
487 self.config.overscan.order = 1
488 self.config.doSaturationInterpolation = False
489 self.config.doBrighterFatter = False
490 self.config.maskNegativeVariance = False # These are mock images.
492 self.config.doCameraSpecificMasking = True
493 self.config.masking.retarget(DECamEdgeBleedMaskTask)
494 self.config.masking.satMinArea = 11
495 self.config.masking.approachRows = 33
496 self.config.masking.nSigma = 4.4
497 self.config.masking.nRowsCheck = 55
498 self.config.masking.nRowsCheckShort = 3
499 self.config.masking.minUsablePixelsPerRow = 66
500 self.config.masking.minLowFraction = 0.77
501 self.config.masking.minLowFractionExtent = 0.07
502 self.config.masking.minBlockedRows = 9
503 self.config.masking.marginFraction = 0.88
504 self.config.masking.saturatedMaskName = "SUSPECT"
506 with unittest.mock.patch("lsst.ip.isr.isrFunctions.maskDECamEdgeBleed") as mocked:
507 self.validateIsrResults()
509 mocked.assert_called_once()
510 kwargs = mocked.call_args.kwargs
511 self.assertEqual(kwargs["satMinArea"], 11)
512 self.assertEqual(kwargs["approachRows"], 33)
513 self.assertEqual(kwargs["nSigma"], 4.4)
514 self.assertEqual(kwargs["nRowsCheck"], 55)
515 self.assertEqual(kwargs["nRowsCheckShort"], 3)
516 self.assertEqual(kwargs["minUsablePixelsPerRow"], 66)
517 self.assertEqual(kwargs["minLowFraction"], 0.77)
518 self.assertEqual(kwargs["minLowFractionExtent"], 0.07)
519 self.assertEqual(kwargs["minBlockedRows"], 9)
520 self.assertEqual(kwargs["marginFraction"], 0.88)
521 self.assertEqual(kwargs["saturatedMaskName"], "SUSPECT")
523 def test_maskingCase_satMaskingAndInterp(self):
524 """Test masking cases of configuration parameters.
525 """
526 self.batchSetConfiguration(True)
527 self.config.overscan.fitType = "POLY"
528 self.config.overscan.order = 1
530 self.config.saturation = 20000.0
531 self.config.doSaturation = True
532 self.config.doWidenSaturationTrails = True
533 self.config.doSaturationInterpolation = True
535 self.config.doSuspect = False
536 self.config.doSetBadRegions = False
537 self.config.doDefect = False
538 self.config.doBrighterFatter = False
540 self.config.maskNegativeVariance = False # These are mock images.
542 results = self.validateIsrResults()
544 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
545 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
546 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
547 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)
549 def test_maskingCase_throughEdge(self):
550 """Test masking cases of configuration parameters.
551 """
552 self.batchSetConfiguration(True)
553 self.config.overscan.fitType = "POLY"
554 self.config.overscan.order = 1
556 self.config.saturation = 20000.0
557 self.config.doSaturation = True
558 self.config.doWidenSaturationTrails = True
559 self.config.doSaturationInterpolation = True
560 self.config.numEdgeSuspect = 5
561 self.config.doSuspect = True
563 self.config.doSetBadRegions = False
564 self.config.doDefect = False
565 self.config.doBrighterFatter = False
567 self.config.maskNegativeVariance = False # These are mock images.
569 results = self.validateIsrResults()
571 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
572 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 0)
573 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
574 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 0)
576 def test_maskingCase_throughDefects(self):
577 """Test masking cases of configuration parameters.
578 """
579 self.batchSetConfiguration(True)
580 self.config.overscan.fitType = "POLY"
581 self.config.overscan.order = 1
583 self.config.saturation = 20000.0
584 self.config.doSaturation = True
585 self.config.doWidenSaturationTrails = True
586 self.config.doSaturationInterpolation = True
587 self.config.numEdgeSuspect = 5
588 self.config.doSuspect = True
589 self.config.doDefect = True
591 self.config.doSetBadRegions = False
592 self.config.doBrighterFatter = False
594 self.config.maskNegativeVariance = False # These are mock images.
596 results = self.validateIsrResults()
598 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
599 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000)
600 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 3940)
601 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000)
603 def test_maskingCase_throughDefectsAmpEdges(self):
604 """Test masking cases of configuration parameters.
605 """
606 self.batchSetConfiguration(True)
607 self.config.overscan.fitType = "POLY"
608 self.config.overscan.order = 1
610 self.config.saturation = 20000.0
611 self.config.doSaturation = True
612 self.config.doWidenSaturationTrails = True
613 self.config.doSaturationInterpolation = True
614 self.config.numEdgeSuspect = 5
615 self.config.doSuspect = True
616 self.config.doDefect = True
617 self.config.edgeMaskLevel = 'AMP'
619 self.config.doSetBadRegions = False
620 self.config.doBrighterFatter = False
622 self.config.maskNegativeVariance = False # These are mock images.
624 results = self.validateIsrResults()
626 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
627 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000)
628 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 11280)
629 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000)
631 def test_maskingCase_throughBad(self):
632 """Test masking cases of configuration parameters.
633 """
634 self.batchSetConfiguration(True)
635 self.config.overscan.fitType = "POLY"
636 self.config.overscan.order = 1
638 self.config.saturation = 20000.0
639 self.config.doSaturation = True
640 self.config.doWidenSaturationTrails = True
641 self.config.doSaturationInterpolation = True
643 self.config.doSuspect = True
644 self.config.doDefect = True
645 self.config.doSetBadRegions = True
646 self.config.doBrighterFatter = False
648 self.config.maskNegativeVariance = False # These are mock images.
650 results = self.validateIsrResults()
652 self.assertEqual(countMaskedPixels(results.exposure, "SAT"), 0)
653 self.assertEqual(countMaskedPixels(results.exposure, "INTRP"), 2000)
654 self.assertEqual(countMaskedPixels(results.exposure, "SUSPECT"), 0)
655 self.assertEqual(countMaskedPixels(results.exposure, "BAD"), 2000)
657 def test_binnedExposures(self):
658 """Ensure that binned exposures have correct sizes."""
659 self.batchSetConfiguration(True)
660 self.config.doBinnedExposures = True
661 self.config.binFactor1 = 8
662 self.config.binFactor2 = 64
664 results = self.validateIsrResults()
666 original = results.exposure.image.array.shape
667 bin1 = results.outputBin1Exposure.image.array.shape
668 bin2 = results.outputBin2Exposure.image.array.shape
670 # Binning truncates, so check that the original and obtained
671 # binned images have the correct offset.
672 self.assertEqual(original[0] - bin1[0] * 8, 4)
673 self.assertEqual(original[1] - bin1[1] * 8, 0)
674 self.assertEqual(original[0] - bin2[0] * 64, 12)
675 self.assertEqual(original[1] - bin2[1] * 64, 8)
678class MemoryTester(lsst.utils.tests.MemoryTestCase):
679 pass
682def setup_module(module):
683 lsst.utils.tests.init()
686if __name__ == "__main__": 686 ↛ 687line 686 didn't jump to line 687 because the condition on line 686 was never true
687 lsst.utils.tests.init()
688 unittest.main(failfast=True)