Coverage for tests/test_overscanAmpConfig.py: 12%

135 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-03-26 03:19 -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# 

22 

23import copy 

24import tempfile 

25import unittest 

26 

27import lsst.utils.tests 

28import lsst.afw.cameraGeom as cameraGeom 

29 

30from lsst.ip.isr.overscanAmpConfig import ( 

31 OverscanAmpConfig, 

32 OverscanDetectorConfig, 

33 OverscanCameraConfig, 

34) 

35 

36 

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"] 

45 

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]) 

50 

51 for amp in self.amps: 

52 ampBuilder = cameraGeom.Amplifier.Builder() 

53 ampBuilder.setName(amp) 

54 detectorBuilder.append(ampBuilder) 

55 

56 return cameraBuilder.finish() 

57 

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. 

62 

63 with tempfile.NamedTemporaryFile(suffix=".py") as f: 

64 configIn.save(f.name) 

65 configOut = OverscanCameraConfig() 

66 configOut.load(f.name) 

67 

68 return configOut 

69 

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) 

84 

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) 

95 

96 def testAmpConfigNoOverrides(self): 

97 camera = self._makeCamera() 

98 

99 config = OverscanCameraConfig() 

100 

101 config = self._serializeAndReadConfig(config) 

102 

103 for detector in camera: 

104 for amp in detector: 

105 detectorConfig = config.getOverscanDetectorConfig(detector) 

106 ampConfig = detectorConfig.getOverscanAmpConfig(amp) 

107 self._checkOverscanConfig(ampConfig) 

108 

109 self._checkAnyOverscanConfig(config) 

110 

111 def testAmpConfigOverrideDetectorDefault(self): 

112 camera = self._makeCamera() 

113 

114 overscanAmpConfig = OverscanAmpConfig( 

115 doSerialOverscan=False, 

116 doParallelOverscan=False, 

117 doParallelOverscanCrosstalk=False, 

118 ) 

119 

120 overscanDetectorConfig = OverscanDetectorConfig(defaultAmpConfig=overscanAmpConfig) 

121 

122 config = OverscanCameraConfig(defaultDetectorConfig=overscanDetectorConfig) 

123 

124 config = self._serializeAndReadConfig(config) 

125 

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 ) 

136 

137 self._checkAnyOverscanConfig( 

138 config, 

139 doSerialOverscan=False, 

140 doParallelOverscan=False, 

141 doParallelOverscanCrosstalk=False, 

142 ) 

143 

144 def testAmpConfigOverrideDetectorDefaultWithOneAmp(self): 

145 camera = self._makeCamera() 

146 

147 overscanAmpConfigOverride = OverscanAmpConfig() 

148 overscanAmpConfigOverride.parallelOverscanConfig.fitType = "MEDIAN" 

149 

150 overscanDetectorConfig = OverscanDetectorConfig() 

151 overscanDetectorConfig.ampRules["amp2"] = overscanAmpConfigOverride 

152 

153 config = OverscanCameraConfig(defaultDetectorConfig=overscanDetectorConfig) 

154 

155 config = self._serializeAndReadConfig(config) 

156 

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) 

165 

166 self._checkAnyOverscanConfig(config) 

167 

168 def testAmpConfigOverrideOneDetector(self): 

169 camera = self._makeCamera() 

170 

171 overscanAmpConfigOverride = OverscanAmpConfig(doParallelOverscanCrosstalk=False) 

172 overscanDetectorConfigOverride = OverscanDetectorConfig(defaultAmpConfig=overscanAmpConfigOverride) 

173 

174 for keyType in ["NAME", "SERIAL", "ID"]: 

175 config = OverscanCameraConfig() 

176 

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()) 

184 

185 config.detectorRuleKeyType = keyType 

186 config.detectorRules[key] = overscanDetectorConfigOverride 

187 

188 config = self._serializeAndReadConfig(config) 

189 

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) 

198 

199 self._checkAnyOverscanConfig(config) 

200 

201 def testAmpConfigOverrideOneDetectorOneAmp(self): 

202 camera = self._makeCamera() 

203 

204 overscanAmpConfigOverride = OverscanAmpConfig() 

205 overscanAmpConfigOverride.serialOverscanConfig.fitType = "MEDIAN" 

206 overscanDetectorConfigOverride = OverscanDetectorConfig() 

207 overscanDetectorConfigOverride.ampRules["amp3"] = overscanAmpConfigOverride 

208 

209 config = OverscanCameraConfig() 

210 config.detectorRules["detector0"] = overscanDetectorConfigOverride 

211 

212 config = self._serializeAndReadConfig(config) 

213 

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) 

222 

223 self._checkAnyOverscanConfig(config) 

224 

225 def testAmpConfigMd5(self): 

226 # Check a default detectorConfig 

227 detectorConfig1 = OverscanDetectorConfig() 

228 configMd51 = detectorConfig1.md5 

229 

230 # Make sure copying it has the same hash. 

231 detectorConfig2 = copy.copy(detectorConfig1) 

232 configMd52 = detectorConfig2.md5 

233 

234 self.assertEqual(configMd51, configMd52) 

235 

236 # Make a new one with an amp override. 

237 overscanAmpConfigOverride = OverscanAmpConfig() 

238 overscanAmpConfigOverride.parallelOverscanConfig.fitType = "MEDIAN" 

239 

240 detectorConfig3 = OverscanDetectorConfig() 

241 detectorConfig3.ampRules["amp2"] = overscanAmpConfigOverride 

242 

243 self.assertNotEqual(detectorConfig3.md5, detectorConfig1.md5) 

244 

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() 

250 

251 self.assertEqual(detectorConfig4.md5, detectorConfig3.md5) 

252 

253 

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

255 pass 

256 

257 

258def setup_module(module): 

259 lsst.utils.tests.init() 

260 

261 

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()