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
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
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/>.
22import numpy as np
23import unittest
25import lsst.utils.tests
26import lsst.ip.isr.isrMock as isrMock
27import lsst.cp.verify as cpVerify
28import lsst.ip.isr.isrFunctions as isrFunctions
31def updateMockExp(exposure, addCR=True):
32 """Update an exposure with a mask and variance plane.
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
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)
52class ToySubClass(cpVerify.CpVerifyStatsTask):
53 """The CpVerifyStatsTask requires an implentation of verify.
54 """
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
61 return verifiedStats, successValue
64class VerifyStatsTestCase(lsst.utils.tests.TestCase):
65 """Unit test for stats code.
66 """
68 def setUp(self):
69 """Generate a mock exposure/camera to test."""
70 self.inputExp = isrMock.CalibratedRawMock().run()
71 self.camera = isrMock.IsrMock().getCamera()
73 updateMockExp(self.inputExp)
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)
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)
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)
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)
115 results = task.run(self.inputExp, self.camera)
116 resultStats = results.outputStats
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)
123 self.assertTrue(resultStats['VERIFY']['A REAL TEST'])
124 self.assertFalse(resultStats['VERIFY']['A BAD TEST'])
126 self.assertTrue(resultStats['SUCCESS'])
129class VerifyBiasTestCase(lsst.utils.tests.TestCase):
130 """Unit test for stats code - bias cases."""
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()
139 config.rngSeed = 54321
140 fakeBias = isrMock.BiasMock(config=config).run()
142 self.inputExp = biasExposure.clone()
143 mi = self.inputExp.getMaskedImage()
144 mi.scaledMinus(1.0, fakeBias.getMaskedImage())
145 updateMockExp(self.inputExp)
147 self.camera = isrMock.IsrMock().getCamera()
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
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)
163 self.assertIn(biasStats['SUCCESS'], [True, False])
166class VerifyDarkTestCase(lsst.utils.tests.TestCase):
167 """Unit test for stats code - dark cases.
168 """
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()
177 config.rngSeed = 54321
178 fakeDark = isrMock.DarkMock(config=config).run()
180 self.inputExp = darkExposure.clone()
181 mi = self.inputExp.getMaskedImage()
182 mi.scaledMinus(1.0, fakeDark.getMaskedImage())
183 updateMockExp(self.inputExp)
185 self.camera = isrMock.IsrMock().getCamera()
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
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)
201 self.assertIn(darkStats['SUCCESS'], [True, False])
204class VerifyDefectsTestCase(lsst.utils.tests.TestCase):
205 """Unit test for stats code - defect cases."""
207 defectFlux = 100000 # Flux to use for simulated defect.
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
224 config.skyLevel = 1000
225 config.rngSeed = 12345
226 self.inputExp = isrMock.IsrMock(config=config).run()
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
233 updateMockExp(self.inputExp, addCR=False)
235 self.inputExp.getMask().getArray()[0, 0] = 1
236 self.inputExp.getMask().getArray()[40, 50] = 1
237 self.inputExp.getMask().getArray()[75, 50] = 1
239 self.camera = isrMock.IsrMock().getCamera()
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
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)
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)
262 self.assertIn(defectStats['SUCCESS'], [True, False])
265class MemoryTester(lsst.utils.tests.MemoryTestCase):
266 pass
269def setup_module(module):
270 lsst.utils.tests.init()
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()