Coverage for tests / test_flatAndIlluminationCorrection.py: 25%
94 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-26 09:10 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-26 09:10 +0000
1#
2# LSST Data Management System
3# Copyright 2008, 2009, 2010 LSST Corporation.
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 <http://www.lsstcorp.org/LegalNotices/>.
21#
23import unittest
25import math
26import numpy as np
28import lsst.utils.tests
29import lsst.geom
30import lsst.afw.image as afwImage
31import lsst.ip.isr as ipIsr
33from lsst.afw.cameraGeom import Amplifier
34from lsst.afw.cameraGeom.testUtils import DetectorWrapper
35from lsst.ip.isr import IsrTask
36from lsst.ip.isr import PhotonTransferCurveDataset
39class IsrTestCases(unittest.TestCase):
41 def setUp(self):
42 self.pmin = lsst.geom.Point2I(1, 1)
43 self.pmax = lsst.geom.Point2I(10, 10)
44 self.flatScaleKeyword = "IMMODE"
45 self.filenameKeyword = "filename"
47 def tearDown(self):
48 del self.pmin
49 del self.pmax
50 del self.flatScaleKeyword
51 del self.filenameKeyword
53 def doFlat(self, scaling):
54 maskedImage = afwImage.MaskedImageF(lsst.geom.Box2I(self.pmin, self.pmax))
55 maskedImage.getImage().set(10)
57 flat = afwImage.MaskedImageF(lsst.geom.Box2I(self.pmin, self.pmax))
58 flat.getImage().set(1)
59 flatexposure = afwImage.ExposureF(flat, None)
60 dmetadata = flatexposure.getMetadata()
61 dmetadata.setString(self.filenameKeyword, 'Unittest Flat')
63 ipIsr.flatCorrection(maskedImage, flatexposure.getMaskedImage(), 'USER', scaling)
65 height = maskedImage.getHeight()
66 width = maskedImage.getWidth()
67 for j in range(height):
68 for i in range(width):
69 self.assertAlmostEqual(maskedImage.image[i, j, afwImage.LOCAL], 10 / (1./scaling), 5)
71 def testFlat1(self):
72 self.doFlat(scaling=10)
74 def testFlat2(self):
75 self.doFlat(scaling=0.1)
77 def testFlat3(self):
78 self.doFlat(scaling=3.7)
80 def doIllum(self, scaling):
81 maskedImage = afwImage.MaskedImageF(lsst.geom.Box2I(self.pmin, self.pmax))
82 maskedImage.getImage().set(10)
84 illum = afwImage.MaskedImageF(lsst.geom.Box2I(self.pmin, self.pmax))
85 illum.getImage().set(1)
86 illumexposure = afwImage.ExposureF(illum, None)
87 dmetadata = illumexposure.getMetadata()
88 dmetadata.setString(self.filenameKeyword, 'Unittest Illum')
90 ipIsr.illuminationCorrection(maskedImage, illumexposure.getMaskedImage(), scaling)
92 height = maskedImage.getHeight()
93 width = maskedImage.getWidth()
94 for j in range(height):
95 for i in range(width):
96 self.assertAlmostEqual(maskedImage.image[i, j, afwImage.LOCAL], 10 / (1./scaling), 5)
98 def testIllum1(self):
99 self.doIllum(scaling=10)
101 def testIllum2(self):
102 self.doIllum(scaling=0.1)
104 def testIllum3(self):
105 self.doIllum(scaling=3.7)
107 def testGainAndReadnoise(self):
109 isrTask = IsrTask()
111 detector = DetectorWrapper().detector
112 raw = afwImage.ExposureF(detector.getBBox())
114 level = 10
115 readNoise = 1.5 # electrons
116 raw.image.set(level)
118 amp = detector[0]
119 ampName = amp.getName()
120 for gain in [-1, 0, 0.1, 1, np.nan]:
121 # Because amplifiers are immutable, we can't change the gain or
122 # read noise in-place. Instead, we clone, and update the clone.
123 testAmp = Amplifier.Builder()
124 testAmp.assign(amp)
125 testAmp.setReadNoise(readNoise)
126 testAmp.setGain(gain)
127 testAmp.finish()
129 # Effective PTC will have the gain and the noise
130 effectivePtc = PhotonTransferCurveDataset([ampName], "TEST_PTC", 1)
131 effectivePtc.gain[ampName] = gain
132 effectivePtc.noise[ampName] = readNoise
133 effectivePtc.validateGainNoiseTurnoffValues(ampName)
134 isrTask.updateVariance(raw, testAmp, effectivePtc)
135 if gain <= 0: # behave the same way as amp.setGain
136 gain = 1
137 if math.isnan(gain):
138 gain = 1
139 # isrTask.updateVariance assumes that the input image will always
140 # be in adu and the noise will always be in electrons, and we will
141 # output the variance plane in the image units (adu^2). This is
142 # always true at the location that updateVariance() is called when
143 # isr_config.doVariance=True.
144 self.assertEqual(raw.variance[0, 0, afwImage.LOCAL], level/gain + (readNoise/gain)**2)
147class MemoryTester(lsst.utils.tests.MemoryTestCase):
148 pass
151def setup_module(module):
152 lsst.utils.tests.init()
155if __name__ == "__main__": 155 ↛ 156line 155 didn't jump to line 156 because the condition on line 155 was never true
156 lsst.utils.tests.init()
157 unittest.main()