Coverage for tests/test_brighterFatterKernel.py: 24%

68 statements  

« prev     ^ index     » next       coverage.py v7.3.0, created at 2023-08-25 11:15 +0000

1# 

2# LSST Data Management System 

3# 

4# Copyright 2008-2017 AURA/LSST. 

5# 

6# This product includes software developed by the 

7# LSST Project (http://www.lsst.org/). 

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 LSST License Statement and 

20# the GNU General Public License along with this program. If not, 

21# see <https://www.lsstcorp.org/LegalNotices/>. 

22# 

23"""Test cases for lsst.cp.pipe.BrighterFatterKernelSolveTask. 

24""" 

25 

26import unittest 

27import numpy as np 

28 

29import lsst.utils 

30import lsst.utils.tests 

31 

32import lsst.ip.isr as ipIsr 

33import lsst.cp.pipe as cpPipe 

34import lsst.afw.cameraGeom as cameraGeom 

35 

36 

37class BfkSolveTaskTestCase(lsst.utils.tests.TestCase): 

38 """A test case for the brighter fatter kernel solver. 

39 """ 

40 

41 def setUp(self): 

42 """Set up a plausible PTC dataset, with 1% of the expected variance 

43 shifted into covariance terms. 

44 """ 

45 cameraBuilder = cameraGeom.Camera.Builder('fake camera') 

46 detectorWrapper = cameraGeom.testUtils.DetectorWrapper(numAmps=1, cameraBuilder=cameraBuilder) 

47 self.detector = detectorWrapper.detector 

48 self.camera = cameraBuilder.finish() 

49 

50 self.defaultConfig = cpPipe.BrighterFatterKernelSolveConfig() 

51 self.ptc = ipIsr.PhotonTransferCurveDataset(ampNames=['amp 1'], ptcFitType='FULLCOVARIANCE', 

52 covMatrixSide=3) 

53 self.ptc.expIdMask['amp 1'] = np.array([False, True, True, True, True, True, True, True, True, True]) 

54 self.ptc.rawMeans['amp 1'] = np.array([1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000]) 

55 self.ptc.finalMeans['amp 1'] = self.ptc.rawMeans['amp 1'][self.ptc.expIdMask['amp 1']] 

56 self.ptc.rawVars['amp 1'] = 0.99 * np.array(self.ptc.rawMeans['amp 1'], dtype=float) 

57 self.ptc.finalVars['amp 1'] = self.ptc.rawVars['amp 1'][self.ptc.expIdMask['amp 1']] 

58 self.ptc.covariances['amp 1'] = [] 

59 for mean, variance in zip(self.ptc.rawMeans['amp 1'], self.ptc.rawVars['amp 1']): 

60 residual = mean - variance 

61 covariance = [[variance, 0.5 * residual, 0.1 * residual], 

62 [0.2 * residual, 0.1 * residual, 0.05 * residual], 

63 [0.025 * residual, 0.015 * residual, 0.01 * residual]] 

64 self.ptc.covariances['amp 1'].append(covariance) 

65 

66 self.ptc.gain['amp 1'] = 1.0 

67 self.ptc.noise['amp 1'] = 5.0 

68 

69 # This is empirically determined from the above parameters. 

70 self.ptc.aMatrix['amp 1'] = np.array([[2.14329806e-06, -4.28659612e-07, -5.35824515e-08], 

71 [-1.07164903e-06, -2.14329806e-07, -3.21494709e-08], 

72 [-2.14329806e-07, -1.07164903e-07, -2.14329806e-08]]) 

73 

74 # This is empirically determined from the above parameters. 

75 self.expectation = np.array([[4.88348887e-08, 1.01136877e-07, 1.51784114e-07, 

76 1.77570668e-07, 1.51784114e-07, 1.01136877e-07, 4.88348887e-08], 

77 [9.42026776e-08, 2.03928507e-07, 3.28428909e-07, 

78 4.06714446e-07, 3.28428909e-07, 2.03928507e-07, 9.42026776e-08], 

79 [1.24047315e-07, 2.70512582e-07, 4.44123665e-07, 

80 5.78099493e-07, 4.44123665e-07, 2.70512582e-07, 1.24047315e-07], 

81 [1.31474000e-07, 2.77801372e-07, 3.85123870e-07, 

82 -5.42128333e-08, 3.85123870e-07, 2.77801372e-07, 1.31474000e-07], 

83 [1.24047315e-07, 2.70512582e-07, 4.44123665e-07, 

84 5.78099493e-07, 4.44123665e-07, 2.70512582e-07, 1.24047315e-07], 

85 [9.42026776e-08, 2.03928507e-07, 3.28428909e-07, 

86 4.06714446e-07, 3.28428909e-07, 2.03928507e-07, 9.42026776e-08], 

87 [4.88348887e-08, 1.01136877e-07, 1.51784114e-07, 

88 1.77570668e-07, 1.51784114e-07, 1.01136877e-07, 4.88348887e-08]]) 

89 

90 def test_averaged(self): 

91 """Test "averaged" brighter-fatter kernel. 

92 """ 

93 task = cpPipe.BrighterFatterKernelSolveTask() 

94 

95 results = task.run(self.ptc, ['this is a dummy exposure'], self.camera, {'detector': 1}) 

96 self.assertFloatsAlmostEqual(results.outputBFK.ampKernels['amp 1'], self.expectation, atol=1e-5) 

97 

98 def test_aMatrix(self): 

99 """Test solution from Astier et al. 2019 "A" matrix 

100 """ 

101 config = cpPipe.BrighterFatterKernelSolveConfig() 

102 config.useAmatrix = True 

103 task = cpPipe.BrighterFatterKernelSolveTask(config=config) 

104 

105 results = task.run(self.ptc, ['this is a dummy exposure'], self.camera, {'detector': 1}) 

106 self.assertFloatsAlmostEqual(results.outputBFK.ampKernels['amp 1'], self.expectation, atol=1e-5) 

107 

108 def test_quadratic(self): 

109 """Test quadratic correlation solver. 

110 

111 This requires a different model for the variance, so cannot 

112 use the one generated by setUp. This model is not entirely 

113 physical, but will ensure that accidental code changes are 

114 detected. 

115 """ 

116 config = cpPipe.BrighterFatterKernelSolveConfig() 

117 config.correlationQuadraticFit = True 

118 config.forceZeroSum = True 

119 task = cpPipe.BrighterFatterKernelSolveTask(config=config) 

120 

121 ptc = ipIsr.PhotonTransferCurveDataset(ampNames=['amp 1'], ptcFitType='FULLCOVARIANCE', 

122 covMatrixSide=3) 

123 ptc.expIdMask['amp 1'] = np.array([False, True, True, True, True, True, True, True, True, True]) 

124 ptc.rawMeans['amp 1'] = np.array([1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000]) 

125 ptc.finalMeans['amp 1'] = ptc.rawMeans['amp 1'][ptc.expIdMask['amp 1']] 

126 ptc.rawVars['amp 1'] = 9e-5 * np.square(np.array(ptc.rawMeans['amp 1'], dtype=float)) 

127 ptc.finalVars['amp 1'] = ptc.rawVars['amp 1'][ptc.expIdMask['amp 1']] 

128 ptc.covariances['amp 1'] = [] 

129 for mean, variance in zip(ptc.rawMeans['amp 1'], ptc.rawVars['amp 1']): 

130 residual = variance 

131 covariance = [[variance, 0.5 * residual, 0.1 * residual], 

132 [0.2 * residual, 0.1 * residual, 0.05 * residual], 

133 [0.025 * residual, 0.015 * residual, 0.01 * residual]] 

134 ptc.covariances['amp 1'].append(covariance) 

135 

136 ptc.gain['amp 1'] = 1.0 

137 ptc.noise['amp 1'] = 5.0 

138 

139 results = task.run(ptc, ['this is a dummy exposure'], self.camera, {'detector': 1}) 

140 

141 expectation = np.array([[4.05330882e-08, 2.26654412e-07, 5.66636029e-07, 7.56066176e-07, 

142 5.66636029e-07, 2.26654412e-07, 4.05330882e-08], 

143 [-6.45220588e-08, 2.99448529e-07, 1.28382353e-06, 1.89099265e-06, 

144 1.28382353e-06, 2.99448529e-07, -6.45220588e-08], 

145 [-5.98069853e-07, -1.14816176e-06, -2.12178309e-06, -4.75974265e-06, 

146 -2.12178309e-06, -1.14816176e-06, -5.98069853e-07], 

147 [-1.17959559e-06, -3.52224265e-06, -1.28630515e-05, -6.16863971e-05, 

148 -1.28630515e-05, -3.52224265e-06, -1.17959559e-06], 

149 [-5.98069853e-07, -1.14816176e-06, -2.12178309e-06, -4.75974265e-06, 

150 -2.12178309e-06, -1.14816176e-06, -5.98069853e-07], 

151 [-6.45220588e-08, 2.99448529e-07, 1.28382353e-06, 1.89099265e-06, 

152 1.28382353e-06, 2.99448529e-07, -6.45220588e-08], 

153 [4.05330882e-08, 2.26654412e-07, 5.66636029e-07, 7.56066176e-07, 

154 5.66636029e-07, 2.26654412e-07, 4.05330882e-08]]) 

155 self.assertFloatsAlmostEqual(results.outputBFK.ampKernels['amp 1'], expectation, atol=1e-5) 

156 

157 

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

159 pass 

160 

161 

162def setup_module(module): 

163 lsst.utils.tests.init() 

164 

165 

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

167 lsst.utils.tests.init() 

168 unittest.main()