Coverage for tests/test_deferredCharge.py: 21%

85 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-12-23 02:02 -0800

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 

23import tempfile 

24import lsst.utils.tests 

25 

26from lsst.ip.isr import DeferredChargeCalib, DeferredChargeTask, SerialTrap 

27 

28 

29class SerialTrapTestCase(lsst.utils.tests.TestCase): 

30 def setUp(self): 

31 self.nx = 64 

32 self.ny = 128 

33 self.prescan = 8 

34 self.trapSize = 10.0 

35 self.trapDecay = 3.0 

36 self.trapPixel = self.nx + self.prescan - 3 

37 self.trapCoeffs = [5.0, 1e-3] 

38 

39 def testTrapsLinear(self): 

40 trap = SerialTrap(self.trapSize, self.trapDecay, 

41 self.trapPixel, 'linear', self.trapCoeffs) 

42 trap.initialize(self.ny, self.nx, self.prescan) 

43 

44 signals = np.full((self.ny, self.nx + self.prescan), 100.0) 

45 signals[:, 0:self.prescan] = 0.0 

46 

47 freeCharge = np.full((self.ny, self.nx + self.prescan), 100.0) 

48 freeCharge[:, 0:self.prescan] = 0.0 

49 

50 # Captured charge is of size trapSize, stored in column 

51 # trapPixel, and introduced to all rows. 

52 capturedCharge = trap.trap_charge(signals) 

53 self.assertEqual(capturedCharge.shape, (self.ny, self.nx + self.prescan)) 

54 self.assertEqual(np.sum(capturedCharge), self.trapSize * (self.ny)) 

55 

56 # Released charge is the amount released after one decay. 

57 releasedCharge = trap.release_charge() 

58 self.assertEqual(releasedCharge.shape, (self.ny, self.nx + self.prescan)) 

59 self.assertAlmostEqual(np.sum(releasedCharge), 362.839922, 4) 

60 

61 def testTrapsLogistic(self): 

62 trap = SerialTrap(self.trapSize, self.trapDecay, 

63 self.trapPixel, 'logistic', self.trapCoeffs) 

64 trap.initialize(self.ny, self.nx, self.prescan) 

65 

66 signals = np.full((self.ny, self.nx + self.prescan), 100.0) 

67 freeCharge = np.full((self.ny, self.nx + self.prescan), 100.0) 

68 signals[:, 0:self.prescan] = 0.0 

69 freeCharge[:, 0:self.prescan] = 0.0 

70 

71 # Captured charge is of size trapSize, stored in column 

72 # trapPixel, and introduced to all rows. 

73 capturedCharge = trap.trap_charge(signals) 

74 self.assertEqual(capturedCharge.shape, (self.ny, self.nx + self.prescan)) 

75 self.assertAlmostEqual(np.sum(capturedCharge), 5.23732154 * (self.ny), 4) 

76 

77 # Released charge is the amount released after one decay. 

78 releasedCharge = trap.release_charge() 

79 self.assertEqual(releasedCharge.shape, (self.ny, self.nx + self.prescan)) 

80 self.assertAlmostEqual(np.sum(releasedCharge), 190.030934, 4) 

81 

82 

83class DeferredChargeTestCase(lsst.utils.tests.TestCase): 

84 def setUp(self): 

85 self.nx = 64 

86 self.ny = 128 

87 self.prescan = 8 

88 self.overscan = 16 

89 self.trapSize = 10.0 

90 self.trapDecay = 3.0 

91 self.trapPixel = self.nx//2 + self.prescan 

92 self.trapCoeffs = [5.0, 1e-3] 

93 self.calib = DeferredChargeCalib() 

94 

95 self.calib.driftScale['amp0'] = 1.8e-4 

96 self.calib.driftScale['amp1'] = 2.8e-4 

97 self.calib.decayTime['amp0'] = 3.1 

98 self.calib.decayTime['amp1'] = 3.2 

99 self.calib.globalCti['amp0'] = 1.4e-7 

100 self.calib.globalCti['amp1'] = 1.5e-7 

101 

102 self.calib.serialTraps['amp0'] = SerialTrap(self.trapSize, self.trapDecay, 

103 self.trapPixel, 'linear', self.trapCoeffs) 

104 self.calib.serialTraps['amp0'] = SerialTrap(self.trapSize, self.trapDecay, 

105 self.trapPixel, 'logistic', self.trapCoeffs) 

106 

107 def testFullyPopulated(self): 

108 # Do IO tests. 

109 outPath = tempfile.mktemp() + '.yaml' 

110 self.calib.writeText(outPath) 

111 newCalib = DeferredChargeCalib().readText(outPath) 

112 self.assertEqual(self.calib, newCalib) 

113 

114 outPath = tempfile.mktemp() + '.fits' 

115 self.calib.writeFits(outPath) 

116 newCalib = DeferredChargeCalib().readFits(outPath) 

117 self.assertEqual(self.calib, newCalib) 

118 

119 def testTaskMethods(self): 

120 task = DeferredChargeTask() 

121 

122 image = np.full((self.ny, self.nx + self.prescan + self.overscan), 100.0) 

123 image[:, 0:self.prescan] = 0.0 

124 image[:, -self.overscan:] = 1.0 

125 

126 corrected = task.local_offset_inverse(image, self.calib.driftScale['amp0'], 

127 self.calib.decayTime['amp0'], 

128 num_previous_pixels=15) 

129 # 64*128*100 + 16*64 * ~(1 - driftScale) 

130 self.assertAlmostEqual(np.sum(corrected), 821094.5118501, 5) 

131 

132 corrected = task.local_trap_inverse(corrected, self.calib.serialTraps['amp0'], 

133 self.calib.globalCti['amp0'], 

134 num_previous_pixels=6) 

135 # As above + ~320 deposited in prescan 

136 self.assertAlmostEqual(np.sum(corrected), 821733.2317048, 5) 

137 

138 

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

140 pass 

141 

142 

143def setup_module(module): 

144 lsst.utils.tests.init() 

145 

146 

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

148 import sys 

149 setup_module(sys.modules[__name__]) 

150 unittest.main()