Coverage for tests/test_verifyStats.py: 18%

Shortcuts on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

150 statements  

1# This file is part of cp_verify. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22import numpy as np 

23import unittest 

24 

25import lsst.utils.tests 

26import lsst.ip.isr.isrMock as isrMock 

27import lsst.cp.verify as cpVerify 

28import lsst.ip.isr.isrFunctions as isrFunctions 

29 

30 

31def updateMockExp(exposure, addCR=True): 

32 """Update an exposure with a mask and variance plane. 

33 

34 Parameters 

35 ---------- 

36 exposure : `lsst.afw.image.Exposure` 

37 Exposure to be modified in place. 

38 addCR : `bool` 

39 Whether a known cosmic ray should be added to ``exposure``. 

40 """ 

41 if addCR: 

42 # Add a cosmic ray 

43 image = exposure.getImage() 

44 image.getArray()[50, 50] = 10000.0 

45 

46 # Set the mask and variance planes: 

47 mask = exposure.getMask() 

48 mask.getArray()[:, 10] = 1 

49 isrFunctions.updateVariance(exposure.getMaskedImage(), 1.0, 5.0) 

50 

51 

52class ToySubClass(cpVerify.CpVerifyStatsTask): 

53 """The CpVerifyStatsTask requires an implentation of verify. 

54 """ 

55 

56 def verify(self, inputExp, outputStats): 

57 # Docstring inherited from CpVerifyStatsTask.verify() 

58 verifiedStats = {'A REAL TEST': True, 'A BAD TEST': False} 

59 successValue = True 

60 

61 return verifiedStats, successValue 

62 

63 

64class VerifyStatsTestCase(lsst.utils.tests.TestCase): 

65 """Unit test for stats code. 

66 """ 

67 

68 def setUp(self): 

69 """Generate a mock exposure/camera to test.""" 

70 self.inputExp = isrMock.CalibratedRawMock().run() 

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

72 

73 updateMockExp(self.inputExp) 

74 

75 def test_failures(self): 

76 """Test that all the NotImplementedError methods fail correctly.""" 

77 results = None 

78 with self.assertRaises(NotImplementedError): 

79 # We have not implemented a verify method 

80 config = cpVerify.CpVerifyStatsConfig() 

81 config.numSigmaClip = 3.0 

82 task = cpVerify.CpVerifyStatsTask(config=config) 

83 results = task.run(self.inputExp, self.camera) 

84 

85 # Or the catalog stats 

86 config.catalogStatKeywords = {'CAT_MEAN', 'MEDIAN'} 

87 task = cpVerify.CpVerifyStatsTask(config=config) 

88 results = task.run(self.inputExp, self.camera) 

89 

90 # Or the detector stats 

91 config.catalogStatKeywords = {} 

92 config.detectorStatKeywords = {'DET_SIGMA', 'STDEV'} 

93 task = cpVerify.CpVerifyStatsTask(config=config) 

94 results = task.run(self.inputExp, self.camera) 

95 self.assertIsNone(results) 

96 

97 def test_generic(self): 

98 """Test a subset of the output values to identify that the 

99 image stat methods haven't changed. 

100 """ 

101 config = cpVerify.CpVerifyStatsConfig() 

102 config.imageStatKeywords = {'MEAN': 'MEAN', 'MEDIAN': 'MEDIAN', 'CLIPPED': 'MEANCLIP', 

103 'SIGMA': 'STDEV'} 

104 config.unmaskedImageStatKeywords = {'un_MEAN': 'MEAN', 'un_MEDIAN': 'MEDIAN', 

105 'un_CLIPPED': 'MEANCLIP', 

106 'un_SIGMA': 'STDEV'} 

107 config.crImageStatKeywords = {'cr_MEAN': 'MEAN', 'cr_MEDIAN': 'MEDIAN', 'cr_CLIPPED': 'MEANCLIP', 

108 'cr_SIGMA': 'STDEV'} 

109 config.normImageStatKeywords = {'norm_MEAN': 'MEAN', 'norm_MEDIAN': 'MEDIAN', 

110 'norm_CLIPPED': 'MEANCLIP', 

111 'norm_SIGMA': 'STDEV'} 

112 config.numSigmaClip = 3.0 

113 task = ToySubClass(config=config) 

114 

115 results = task.run(self.inputExp, self.camera) 

116 resultStats = results.outputStats 

117 

118 self.assertAlmostEqual(resultStats['AMP']['C:0,0']['MEAN'], 1506.06976, 4) 

119 self.assertAlmostEqual(resultStats['AMP']['C:0,0']['un_MEAN'], 1501.0299, 4) 

120 self.assertAlmostEqual(resultStats['AMP']['C:0,0']['norm_MEAN'], 301.213957, 4) 

121 self.assertAlmostEqual(resultStats['AMP']['C:0,0']['cr_MEAN'], 1504.2776, 4) 

122 

123 self.assertTrue(resultStats['VERIFY']['A REAL TEST']) 

124 self.assertFalse(resultStats['VERIFY']['A BAD TEST']) 

125 

126 self.assertTrue(resultStats['SUCCESS']) 

127 

128 

129class VerifyBiasTestCase(lsst.utils.tests.TestCase): 

130 """Unit test for stats code - bias cases.""" 

131 

132 def setUp(self): 

133 """Generate a mock exposure/camera to test.""" 

134 config = isrMock.IsrMockConfig() 

135 config.isTrimmed = True 

136 config.rngSeed = 12345 

137 biasExposure = isrMock.BiasMock(config=config).run() 

138 

139 config.rngSeed = 54321 

140 fakeBias = isrMock.BiasMock(config=config).run() 

141 

142 self.inputExp = biasExposure.clone() 

143 mi = self.inputExp.getMaskedImage() 

144 mi.scaledMinus(1.0, fakeBias.getMaskedImage()) 

145 updateMockExp(self.inputExp) 

146 

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

148 

149 def test_bias(self): 

150 """Test a subset of the output values to identify that the 

151 image stat methods haven't changed. 

152 """ 

153 config = cpVerify.CpVerifyBiasConfig() 

154 config.numSigmaClip = 3.0 

155 task = cpVerify.CpVerifyBiasTask(config=config) 

156 results = task.run(self.inputExp, self.camera) 

157 biasStats = results.outputStats 

158 

159 self.assertAlmostEqual(biasStats['AMP']['C:0,0']['MEAN'], 2.08672, 4) 

160 self.assertAlmostEqual(biasStats['AMP']['C:0,0']['NOISE'], 13.99547, 4) 

161 self.assertAlmostEqual(biasStats['AMP']['C:0,0']['CR_NOISE'], 14.11526, 4) 

162 

163 self.assertIn(biasStats['SUCCESS'], [True, False]) 

164 

165 

166class VerifyDarkTestCase(lsst.utils.tests.TestCase): 

167 """Unit test for stats code - dark cases. 

168 """ 

169 

170 def setUp(self): 

171 """Generate a mock exposure/camera to test.""" 

172 config = isrMock.IsrMockConfig() 

173 config.isTrimmed = True 

174 config.rngSeed = 12345 

175 darkExposure = isrMock.DarkMock(config=config).run() 

176 

177 config.rngSeed = 54321 

178 fakeDark = isrMock.DarkMock(config=config).run() 

179 

180 self.inputExp = darkExposure.clone() 

181 mi = self.inputExp.getMaskedImage() 

182 mi.scaledMinus(1.0, fakeDark.getMaskedImage()) 

183 updateMockExp(self.inputExp) 

184 

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

186 

187 def test_dark(self): 

188 """Test a subset of the output values to identify that the 

189 image stat methods haven't changed. 

190 """ 

191 config = cpVerify.CpVerifyDarkConfig() 

192 config.numSigmaClip = 3.0 

193 task = cpVerify.CpVerifyDarkTask(config=config) 

194 results = task.run(self.inputExp, self.camera) 

195 darkStats = results.outputStats 

196 

197 self.assertAlmostEqual(darkStats['AMP']['C:0,0']['MEAN'], 2.0043, 4) 

198 self.assertAlmostEqual(darkStats['AMP']['C:0,0']['NOISE'], 3.12948, 4) 

199 self.assertAlmostEqual(darkStats['AMP']['C:0,0']['CR_NOISE'], 3.15946, 4) 

200 

201 self.assertIn(darkStats['SUCCESS'], [True, False]) 

202 

203 

204class VerifyDefectsTestCase(lsst.utils.tests.TestCase): 

205 """Unit test for stats code - defect cases.""" 

206 

207 defectFlux = 100000 # Flux to use for simulated defect. 

208 

209 def setUp(self): 

210 """Generate a mock exposure/camera to test.""" 

211 config = isrMock.IsrMockConfig() 

212 config.isTrimmed = True 

213 config.doGenerateImage = True 

214 config.doAddFringe = False 

215 config.doAddSource = False 

216 config.doAddSky = True 

217 config.doAddOverscan = False 

218 config.doAddCrosstalk = False 

219 config.doAddBias = False 

220 config.doAddDark = False 

221 config.doAddFlat = False 

222 config.doAddFringe = False 

223 

224 config.skyLevel = 1000 

225 config.rngSeed = 12345 

226 self.inputExp = isrMock.IsrMock(config=config).run() 

227 

228 # These are simulated defects 

229 self.inputExp.getImage().getArray()[0, 0] = -1.0 * self.defectFlux 

230 self.inputExp.getImage().getArray()[40, 50] = self.defectFlux 

231 self.inputExp.getImage().getArray()[75, 50] = np.nan 

232 

233 updateMockExp(self.inputExp, addCR=False) 

234 

235 self.inputExp.getMask().getArray()[0, 0] = 1 

236 self.inputExp.getMask().getArray()[40, 50] = 1 

237 self.inputExp.getMask().getArray()[75, 50] = 1 

238 

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

240 

241 def test_defects(self): 

242 """Test a subset of the output values to identify that the 

243 image stat methods haven't changed. 

244 """ 

245 config = cpVerify.CpVerifyDefectsConfig() 

246 config.numSigmaClip = 3.0 

247 task = cpVerify.CpVerifyDefectsTask(config=config) 

248 results = task.run(self.inputExp, self.camera) 

249 defectStats = results.outputStats 

250 

251 self.assertEqual(defectStats['AMP']['C:0,0']['DEFECT_PIXELS'], 53) 

252 self.assertEqual(defectStats['AMP']['C:0,0']['OUTLIERS'], 17) 

253 self.assertEqual(defectStats['AMP']['C:0,0']['STAT_OUTLIERS'], 3) 

254 self.assertAlmostEqual(defectStats['AMP']['C:0,0']['MEDIAN'], 999.466, 4) 

255 self.assertAlmostEqual(defectStats['AMP']['C:0,0']['STDEV'], 30.96303, 4) 

256 self.assertAlmostEqual(defectStats['AMP']['C:0,0']['MIN'], 881.56146, 4) 

257 self.assertAlmostEqual(defectStats['AMP']['C:0,0']['MAX'], 1124.19934, 4) 

258 

259 self.assertEqual(defectStats['AMP']['C:0,0']['UNMASKED_MIN'], -1.0 * self.defectFlux, 4) 

260 self.assertEqual(defectStats['AMP']['C:0,0']['UNMASKED_MAX'], self.defectFlux, 4) 

261 

262 self.assertIn(defectStats['SUCCESS'], [True, False]) 

263 

264 

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

266 pass 

267 

268 

269def setup_module(module): 

270 lsst.utils.tests.init() 

271 

272 

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

274 lsst.utils.tests.init() 

275 unittest.main()