Coverage for tests/test_overscanAmpConfig.py: 12%
135 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-05 03:23 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-05 03:23 -0700
1#
2# LSST Data Management System
3# Copyright 2023 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 copy
24import tempfile
25import unittest
27import lsst.utils.tests
28import lsst.afw.cameraGeom as cameraGeom
30from lsst.ip.isr.overscanAmpConfig import (
31 OverscanAmpConfig,
32 OverscanDetectorConfig,
33 OverscanCameraConfig,
34)
37class OverscanAmpConfigTestCase(lsst.utils.tests.TestCase):
38 def _makeCamera(self):
39 self.detectors = {
40 "detector0": (0, "0010"),
41 "detector1": (1, "0011"),
42 "detector2": (2, "0012"),
43 }
44 self.amps = ["amp0", "amp1", "amp2", "amp3"]
46 cameraBuilder = cameraGeom.Camera.Builder("Fake Camera")
47 for detector in self.detectors:
48 detectorBuilder = cameraBuilder.add(detector, self.detectors[detector][0])
49 detectorBuilder.setSerial(self.detectors[detector][1])
51 for amp in self.amps:
52 ampBuilder = cameraGeom.Amplifier.Builder()
53 ampBuilder.setName(amp)
54 detectorBuilder.append(ampBuilder)
56 return cameraBuilder.finish()
58 def _serializeAndReadConfig(self, configIn):
59 # This bit of code serializes and reads the config
60 # to ensure that everything here works as expected
61 # with the nested dictionaries of configs.
63 with tempfile.NamedTemporaryFile(suffix=".py") as f:
64 configIn.save(f.name)
65 configOut = OverscanCameraConfig()
66 configOut.load(f.name)
68 return configOut
70 def _checkOverscanConfig(
71 self,
72 overscanAmpConfig,
73 doSerialOverscan=True,
74 doParallelOverscanCrosstalk=True,
75 doParallelOverscan=True,
76 serialFitType="MEDIAN_PER_ROW",
77 parallelFitType="MEDIAN_PER_ROW",
78 ):
79 self.assertEqual(overscanAmpConfig.doSerialOverscan, doSerialOverscan)
80 self.assertEqual(overscanAmpConfig.doParallelOverscanCrosstalk, doParallelOverscanCrosstalk)
81 self.assertEqual(overscanAmpConfig.doParallelOverscan, doParallelOverscan)
82 self.assertEqual(overscanAmpConfig.serialOverscanConfig.fitType, serialFitType)
83 self.assertEqual(overscanAmpConfig.parallelOverscanConfig.fitType, parallelFitType)
85 def _checkAnyOverscanConfig(
86 self,
87 config,
88 doSerialOverscan=True,
89 doParallelOverscan=True,
90 doParallelOverscanCrosstalk=True,
91 ):
92 self.assertEqual(config.doAnySerialOverscan, doSerialOverscan)
93 self.assertEqual(config.doAnyParallelOverscan, doParallelOverscan)
94 self.assertEqual(config.doAnyParallelOverscanCrosstalk, doParallelOverscanCrosstalk)
96 def testAmpConfigNoOverrides(self):
97 camera = self._makeCamera()
99 config = OverscanCameraConfig()
101 config = self._serializeAndReadConfig(config)
103 for detector in camera:
104 for amp in detector:
105 detectorConfig = config.getOverscanDetectorConfig(detector)
106 ampConfig = detectorConfig.getOverscanAmpConfig(amp)
107 self._checkOverscanConfig(ampConfig)
109 self._checkAnyOverscanConfig(config)
111 def testAmpConfigOverrideDetectorDefault(self):
112 camera = self._makeCamera()
114 overscanAmpConfig = OverscanAmpConfig(
115 doSerialOverscan=False,
116 doParallelOverscan=False,
117 doParallelOverscanCrosstalk=False,
118 )
120 overscanDetectorConfig = OverscanDetectorConfig(defaultAmpConfig=overscanAmpConfig)
122 config = OverscanCameraConfig(defaultDetectorConfig=overscanDetectorConfig)
124 config = self._serializeAndReadConfig(config)
126 for detector in camera:
127 for amp in detector:
128 detectorConfig = config.getOverscanDetectorConfig(detector)
129 overscanAmpConfig = detectorConfig.getOverscanAmpConfig(amp)
130 self._checkOverscanConfig(
131 overscanAmpConfig,
132 doSerialOverscan=False,
133 doParallelOverscan=False,
134 doParallelOverscanCrosstalk=False,
135 )
137 self._checkAnyOverscanConfig(
138 config,
139 doSerialOverscan=False,
140 doParallelOverscan=False,
141 doParallelOverscanCrosstalk=False,
142 )
144 def testAmpConfigOverrideDetectorDefaultWithOneAmp(self):
145 camera = self._makeCamera()
147 overscanAmpConfigOverride = OverscanAmpConfig()
148 overscanAmpConfigOverride.parallelOverscanConfig.fitType = "MEDIAN"
150 overscanDetectorConfig = OverscanDetectorConfig()
151 overscanDetectorConfig.ampRules["amp2"] = overscanAmpConfigOverride
153 config = OverscanCameraConfig(defaultDetectorConfig=overscanDetectorConfig)
155 config = self._serializeAndReadConfig(config)
157 for detector in camera:
158 for amp in detector:
159 detectorConfig = config.getOverscanDetectorConfig(detector)
160 ampConfig = detectorConfig.getOverscanAmpConfig(amp)
161 if amp.getName() == "amp2":
162 self._checkOverscanConfig(ampConfig, parallelFitType="MEDIAN")
163 else:
164 self._checkOverscanConfig(ampConfig)
166 self._checkAnyOverscanConfig(config)
168 def testAmpConfigOverrideOneDetector(self):
169 camera = self._makeCamera()
171 overscanAmpConfigOverride = OverscanAmpConfig(doParallelOverscanCrosstalk=False)
172 overscanDetectorConfigOverride = OverscanDetectorConfig(defaultAmpConfig=overscanAmpConfigOverride)
174 for keyType in ["NAME", "SERIAL", "ID"]:
175 config = OverscanCameraConfig()
177 match keyType:
178 case "NAME":
179 key = camera[1].getName()
180 case "SERIAL":
181 key = camera[1].getSerial()
182 case "ID":
183 key = str(camera[1].getId())
185 config.detectorRuleKeyType = keyType
186 config.detectorRules[key] = overscanDetectorConfigOverride
188 config = self._serializeAndReadConfig(config)
190 for detector in camera:
191 for amp in detector:
192 detectorConfig = config.getOverscanDetectorConfig(detector)
193 ampConfig = detectorConfig.getOverscanAmpConfig(amp)
194 if detector.getName() == camera[1].getName():
195 self._checkOverscanConfig(ampConfig, doParallelOverscanCrosstalk=False)
196 else:
197 self._checkOverscanConfig(ampConfig)
199 self._checkAnyOverscanConfig(config)
201 def testAmpConfigOverrideOneDetectorOneAmp(self):
202 camera = self._makeCamera()
204 overscanAmpConfigOverride = OverscanAmpConfig()
205 overscanAmpConfigOverride.serialOverscanConfig.fitType = "MEDIAN"
206 overscanDetectorConfigOverride = OverscanDetectorConfig()
207 overscanDetectorConfigOverride.ampRules["amp3"] = overscanAmpConfigOverride
209 config = OverscanCameraConfig()
210 config.detectorRules["detector0"] = overscanDetectorConfigOverride
212 config = self._serializeAndReadConfig(config)
214 for detector in camera:
215 for amp in detector:
216 detectorConfig = config.getOverscanDetectorConfig(detector)
217 ampConfig = detectorConfig.getOverscanAmpConfig(amp)
218 if detector.getName() == "detector0" and amp.getName() == "amp3":
219 self._checkOverscanConfig(ampConfig, serialFitType="MEDIAN")
220 else:
221 self._checkOverscanConfig(ampConfig)
223 self._checkAnyOverscanConfig(config)
225 def testAmpConfigMd5(self):
226 # Check a default detectorConfig
227 detectorConfig1 = OverscanDetectorConfig()
228 configMd51 = detectorConfig1.md5
230 # Make sure copying it has the same hash.
231 detectorConfig2 = copy.copy(detectorConfig1)
232 configMd52 = detectorConfig2.md5
234 self.assertEqual(configMd51, configMd52)
236 # Make a new one with an amp override.
237 overscanAmpConfigOverride = OverscanAmpConfig()
238 overscanAmpConfigOverride.parallelOverscanConfig.fitType = "MEDIAN"
240 detectorConfig3 = OverscanDetectorConfig()
241 detectorConfig3.ampRules["amp2"] = overscanAmpConfigOverride
243 self.assertNotEqual(detectorConfig3.md5, detectorConfig1.md5)
245 # Override another amp but with the default. This should
246 # give the same answer because amp overrides that match the default
247 # are not hashed.
248 detectorConfig4 = copy.copy(detectorConfig3)
249 detectorConfig4.ampRules["amp3"] = OverscanAmpConfig()
251 self.assertEqual(detectorConfig4.md5, detectorConfig3.md5)
254class MemoryTester(lsst.utils.tests.MemoryTestCase):
255 pass
258def setup_module(module):
259 lsst.utils.tests.init()
262if __name__ == "__main__": 262 ↛ 263line 262 didn't jump to line 263, because the condition on line 262 was never true
263 lsst.utils.tests.init()
264 unittest.main()