Coverage for tests / test_measureCrosstalk.py: 23%

69 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-24 08:52 +0000

1# 

2# LSST Data Management System 

3# Copyright 2008-2017 AURA/LSST. 

4# 

5# This product includes software developed by the 

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

7# 

8# This program is free software: you can redistribute it and/or modify 

9# it under the terms of the GNU General Public License as published by 

10# the Free Software Foundation, either version 3 of the License, or 

11# (at your option) any later version. 

12# 

13# This program is distributed in the hope that it will be useful, 

14# but WITHOUT ANY WARRANTY; without even the implied warranty of 

15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

16# GNU General Public License for more details. 

17# 

18# You should have received a copy of the LSST License Statement and 

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

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

21# 

22 

23import unittest 

24import numpy as np 

25 

26import lsst.utils.tests 

27from lsst.cp.pipe import CrosstalkExtractTask, CrosstalkExtractConfig 

28from lsst.cp.pipe import CrosstalkSolveTask, CrosstalkSolveConfig 

29import lsst.ip.isr.isrMock as isrMock 

30 

31 

32class PretendRef: 

33 "A class to act as a mock butler reference" 

34 

35 def __init__(self, exposure): 

36 self.exp = exposure 

37 

38 def get(self, component=None): 

39 if component: 

40 raise RuntimeError("Components not supported in CT PretendRef.") 

41 else: 

42 return self.exp 

43 

44 

45class MeasureCrosstalkTaskCases(lsst.utils.tests.TestCase): 

46 

47 def setup_measureCrosstalk(self, isTrimmed=False, nSources=8): 

48 """Generate a simulated set of exposures and test the measured 

49 crosstalk matrix. 

50 

51 Parameters 

52 ---------- 

53 isTrimmed : `bool`, optional 

54 Should the simulation use trimmed or untrimmed raw 

55 exposures? 

56 nSources : `int`, optional 

57 Number of random simulated sources to generate in the 

58 simulated exposures. 

59 

60 Returns 

61 ------- 

62 goodFitMask : `np.ndarray` 

63 Array of booleans indicating if the measured and expected 

64 crosstalk ratios are smaller than the measured uncertainty 

65 in the crosstalk ratio. 

66 """ 

67 mockTask = isrMock.CalibratedRawMock() 

68 mockTask.config.rngSeed = 12345 

69 mockTask.config.doGenerateImage = True 

70 mockTask.config.doAddSky = True 

71 mockTask.config.doAddSource = True 

72 mockTask.config.doAddCrosstalk = True 

73 mockTask.config.doAddBias = True 

74 mockTask.config.doAddFringe = False 

75 

76 mockTask.config.skyLevel = 0.0 

77 mockTask.config.biasLevel = 0.0 

78 mockTask.config.readNoise = 100.0 

79 

80 ctexConfig = CrosstalkExtractConfig() 

81 ctexConfig.threshold = 4000 

82 ctexConfig.isTrimmed = isTrimmed 

83 ctex = CrosstalkExtractTask(config=ctexConfig) 

84 measuredRatios = [] 

85 

86 mockTask.config.isTrimmed = isTrimmed 

87 # Generate simulated set of exposures. 

88 for idx in range(0, 12): 

89 mockTask.config.rngSeed = 12345 + idx * 1000 

90 

91 # Allow each simulated exposure to have nSources random 

92 # bright sources. 

93 mockTask.config.sourceAmp = (np.random.randint(8, size=nSources)).tolist() 

94 mockTask.config.sourceFlux = ((np.random.random(size=nSources) * 25000.0 + 20000.0).tolist()) 

95 mockTask.config.sourceX = ((np.random.random(size=nSources) * 100.0).tolist()) 

96 mockTask.config.sourceY = ((np.random.random(size=nSources) * 50.0).tolist()) 

97 

98 exposure = mockTask.run() 

99 result = ctex.run(exposure) 

100 measuredRatios.append(PretendRef(result.outputRatios)) 

101 camera = mockTask.getCamera() 

102 

103 # This test needs fixing: CZW: 

104 # return [True, True, True] 

105 # Generate the final measured CT ratios, uncertainties, pixel counts. 

106 outputDims = { 

107 'detector': list(measuredRatios[0].get().keys())[0], 

108 'instrument': camera.getName(), 

109 } 

110 

111 ctsConfig = CrosstalkSolveConfig() 

112 cts = CrosstalkSolveTask(config=ctsConfig) 

113 finalResult = cts.run(inputRatios=measuredRatios, camera=camera, outputDims=outputDims) 

114 calib = finalResult.outputCrosstalk 

115 

116 # Needed because measureCrosstalk cannot find coefficients equal to 0.0 

117 coeff = np.nan_to_num(calib.coeffs) 

118 coeffSig = np.nan_to_num(calib.coeffErr) 

119 

120 # Compare result against expectation used to create the simulation. 

121 expectation = isrMock.CrosstalkCoeffMock().run() 

122 goodFitMask = abs(coeff - expectation) <= coeffSig 

123 

124 if not np.all(goodFitMask): 

125 print("Coeff: ", coeff) 

126 print("Expectation: ", expectation) 

127 print("Good Fits: ", goodFitMask) 

128 return goodFitMask 

129 

130 def testMeasureCrosstalkTaskTrimmed(self): 

131 """Measure crosstalk from a sequence of trimmed mocked images. 

132 """ 

133 goodFitMask = self.setup_measureCrosstalk(isTrimmed=True, nSources=8) 

134 

135 self.assertTrue(np.all(goodFitMask)) 

136 

137 def testMeasureCrosstalkTaskUntrimmed(self): 

138 """Measure crosstalk from a sequence of untrimmed mocked images. 

139 """ 

140 goodFitMask = self.setup_measureCrosstalk(isTrimmed=False, nSources=8) 

141 

142 self.assertTrue(np.all(goodFitMask)) 

143 

144 

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

146 pass 

147 

148 

149def setup_module(module): 

150 lsst.utils.tests.init() 

151 

152 

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

154 lsst.utils.tests.init() 

155 unittest.main()