Coverage for tests/test_ampOffset.py: 22%
92 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-11 18:34 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-11 18:34 +0000
1# This file is part of ip_isr.
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/>.
21import unittest
22import numpy as np
24import lsst.utils.tests
25from lsst.ip.isr.ampOffset import AmpOffsetConfig, AmpOffsetTask
26from lsst.ip.isr.isrMock import IsrMock
29class AmpOffsetTest(lsst.utils.tests.TestCase):
30 def setUp(self):
31 # Test with a single detector featuring 4x2 amplifiers to ensure
32 # functionality in a general 2-dimensional scenario.
33 config = IsrMock.ConfigClass()
34 config.isLsstLike = True
35 config.doAddBias = False
36 config.doAddDark = False
37 config.doAddFlat = False
38 config.doAddFringe = False
39 config.doGenerateImage = True
40 config.doGenerateData = True
41 config.doGenerateAmpDict = True
42 self.mock = IsrMock(config=config)
43 self.measuredValuesBackground = [
44 0.13336708,
45 0.06299729,
46 0.34589145,
47 0.27551733,
48 -0.27551731,
49 -0.34589142,
50 -0.06299731,
51 -0.1333671,
52 ]
53 self.measuredValuesRampBackground = [
54 0.19094621,
55 0.21447723,
56 0.19441773,
57 0.21793666,
58 -0.21794104,
59 -0.1944167,
60 -0.21447818,
61 -0.19094191,
62 ]
63 self.measuredSigmaBackground = 1.7861559064582404
64 self.measuredSigmaRampBackground = 1.8148713749702268
66 def tearDown(self):
67 del self.mock
69 def buildExposure(self, addBackground=False):
70 exp = self.mock.getExposure()
71 detector = exp.getDetector()
72 amps = detector.getAmplifiers()
73 self.values = np.linspace(-2.5, 2.5, len(amps))
74 for amp, value in zip(amps, self.values):
75 exp.image[amp.getBBox()] = value
76 if addBackground:
77 exp.image.array += 100
78 return exp
80 def testAmpOffset(self):
81 exp = self.buildExposure(addBackground=False)
82 config = AmpOffsetConfig()
83 config.doBackground = False
84 config.doDetection = False
85 task = AmpOffsetTask(config=config)
86 pedestals = task.run(exp).pedestals
87 self.assertEqual(np.sum(exp.image.array), 0)
88 for pedestal, value in zip(pedestals, self.values):
89 self.assertAlmostEqual(pedestal, value, 6)
91 def testAmpOffsetWithBackground(self):
92 exp = self.buildExposure(addBackground=True)
93 amps = exp.getDetector().getAmplifiers()
94 config = AmpOffsetConfig()
95 config.doBackground = True
96 config.doDetection = True
97 task = AmpOffsetTask(config=config)
98 pedestals = task.run(exp).pedestals
99 nAmps = len(amps)
100 for i in range(nAmps // 2):
101 self.assertAlmostEqual(pedestals[i], -pedestals[nAmps - i - 1], 5)
102 for pedestal, value in zip(pedestals, self.measuredValuesBackground):
103 self.assertAlmostEqual(pedestal, value, 5)
104 # If we are getting it wrong, let's not get it wrong by more than some
105 # specified DN.
106 self.assertAlmostEqual(np.std(pedestals - self.values), self.measuredSigmaBackground, 5)
108 def testAmpOffsetWithRampBackground(self):
109 exp = self.buildExposure(addBackground=True)
110 amps = exp.getDetector().getAmplifiers()
111 yscale = 100.0
112 xscale = 0.0
113 # Add a gradient.
114 self.amplifierAddYGradient(exp.image, 0.0, yscale)
115 # Add another gradient to the other direction.
116 self.amplifierAddXGradient(exp.image, 0.0, xscale)
117 config = AmpOffsetConfig()
118 config.doBackground = True
119 config.doDetection = True
120 task = AmpOffsetTask(config=config)
121 pedestals = task.run(exp).pedestals
122 nAmps = len(amps)
123 for i in range(nAmps // 2):
124 self.assertAlmostEqual(pedestals[i], -pedestals[nAmps - i - 1], 5)
125 for pedestal, value in zip(pedestals, self.measuredValuesRampBackground):
126 self.assertAlmostEqual(pedestal, value, 5)
127 self.assertAlmostEqual(np.std(pedestals - self.values), self.measuredSigmaRampBackground)
129 # The two static methods below are taken from ip_isr/isrMock.
130 @staticmethod
131 def amplifierAddYGradient(ampData, start, end):
132 nPixY = ampData.getDimensions().getY()
133 ampArr = ampData.array
134 ampArr[:] = ampArr[:] + (
135 np.interp(range(nPixY), (0, nPixY - 1), (start, end)).reshape(nPixY, 1)
136 + np.zeros(ampData.getDimensions()).transpose()
137 )
139 @staticmethod
140 def amplifierAddXGradient(ampData, start, end):
141 nPixX = ampData.getDimensions().getX()
142 ampArr = ampData.array
143 ampArr[:] = ampArr[:] + (
144 np.interp(range(nPixX), (0, nPixX - 1), (start, end)).reshape(1, nPixX)
145 + np.zeros(ampData.getDimensions()).transpose()
146 )
149class TestMemory(lsst.utils.tests.MemoryTestCase):
150 pass
153def setup_module(module):
154 lsst.utils.tests.init()
157if __name__ == "__main__": 157 ↛ 158line 157 didn't jump to line 158, because the condition on line 157 was never true
158 lsst.utils.tests.init()
159 unittest.main()