Coverage for tests/test_ampOffset.py: 22%

92 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 11:41 +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 

23 

24import lsst.utils.tests 

25from lsst.ip.isr.ampOffset import AmpOffsetConfig, AmpOffsetTask 

26from lsst.ip.isr.isrMock import IsrMock 

27 

28 

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 

65 

66 def tearDown(self): 

67 del self.mock 

68 

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 

79 

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) 

90 

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) 

107 

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) 

128 

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 ) 

138 

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 ) 

147 

148 

149class TestMemory(lsst.utils.tests.MemoryTestCase): 

150 pass 

151 

152 

153def setup_module(module): 

154 lsst.utils.tests.init() 

155 

156 

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