Coverage for python/lsst/cp/verify/verifyCalib.py: 72%

29 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-10 14:23 +0000

1# This file is part of cp_verify. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://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 <http://www.gnu.org/licenses/>. 

21import lsst.pex.config as pexConfig 

22import lsst.pipe.base as pipeBase 

23import lsst.pipe.base.connectionTypes as cT 

24 

25__all__ = ['CpVerifyCalibConfig', 'CpVerifyCalibTask'] 

26 

27 

28class CpVerifyCalibConnections(pipeBase.PipelineTaskConnections, 

29 dimensions={"instrument", "detector"}, 

30 defaultTemplates={}): 

31 

32 exposure = cT.Input( 

33 name="raw", 

34 doc="Exposure to retreve calibration", 

35 storageClass='Exposure', 

36 dimensions=("instrument", "detector", "exposure"), 

37 multiple=True, 

38 deferLoad=True, 

39 ) 

40 

41 inputCalib = cT.Input( 

42 name="calib", 

43 doc="Input calib to calculate statistics for.", 

44 storageClass="IsrCalib", 

45 dimensions=["instrument", "detector"], 

46 isCalibration=True 

47 ) 

48 

49 camera = cT.PrerequisiteInput( 

50 name="camera", 

51 doc="Input camera to use for gain lookup.", 

52 storageClass="Camera", 

53 dimensions=("instrument",), 

54 isCalibration=True, 

55 ) 

56 

57 outputStats = cT.Output( 

58 name="calibStats", 

59 doc="Output statistics from cp_verify.", 

60 storageClass="StructuredDataDict", 

61 dimensions=["instrument", "detector"], 

62 ) 

63 

64 

65class CpVerifyCalibConfig(pipeBase.PipelineTaskConfig, 

66 pipelineConnections=CpVerifyCalibConnections): 

67 """Configuration parameters for CpVerifyCalibTask. 

68 """ 

69 # Statistics options. 

70 useReadNoise = pexConfig.Field( 

71 dtype=bool, 

72 doc="Compare sigma against read noise?", 

73 default=True, 

74 ) 

75 numSigmaClip = pexConfig.Field( 

76 dtype=float, 

77 doc="Rejection threshold (sigma) for statistics clipping.", 

78 default=5.0, 

79 ) 

80 clipMaxIter = pexConfig.Field( 

81 dtype=int, 

82 doc="Max number of clipping iterations to apply.", 

83 default=3, 

84 ) 

85 

86 # Keywords and statistics to measure from different sources. 

87 calibStatKeywords = pexConfig.DictField( 

88 keytype=str, 

89 itemtype=str, 

90 doc="Calib statistics to run.", 

91 default={}, 

92 ) 

93 

94 

95class CpVerifyCalibTask(pipeBase.PipelineTask): 

96 """Main statistic measurement and validation class. 

97 

98 This operates on a generic calibration, and is designed to be 

99 subclassed so specific calibrations can apply their own validation 

100 methods. 

101 """ 

102 

103 ConfigClass = CpVerifyCalibConfig 

104 _DefaultName = 'cpVerifyCalib' 

105 

106 def run(self, inputCalib, camera=None, exposure=None): 

107 """Calculate quality statistics and verify they meet the requirements 

108 for a calibration. 

109 

110 Parameters 

111 ---------- 

112 inputCalib : `lsst.ip.isr.IsrCalib` 

113 The calibration to be measured. 

114 camera : `lsst.afw.cameraGeom.Camera`, optional 

115 Input camera. 

116 exposure : `lsst.afw.image.Exposure`, optional 

117 Dummy exposure to identify a particular calibration 

118 dataset. 

119 

120 Returns 

121 ------- 

122 result : `lsst.pipe.base.Struct` 

123 Result struct with components: 

124 - ``outputStats`` : `dict` 

125 The output measured statistics. 

126 

127 Notes 

128 ----- 

129 The outputStats should have a yaml representation of the form 

130 (with STAT and TEST being the appropriate statistic and test 

131 names) 

132 

133 DET: 

134 STAT: value 

135 STAT2: value 

136 AMP: 

137 STAT: value 

138 STAT2: value 

139 VERIFY: 

140 TEST: boolean 

141 SUCCESS: boolean 

142 

143 """ 

144 outputStats = {} 

145 outputStats['AMP'] = self.amplifierStatistics(inputCalib, camera=camera) 

146 outputStats['DET'] = self.detectorStatistics(inputCalib, camera=camera) 

147 outputStats['VERIFY'], outputStats['SUCCESS'] = self.verify(inputCalib, outputStats, camera=camera) 

148 

149 return pipeBase.Struct( 

150 outputStats=outputStats, 

151 ) 

152 

153 # Methods that need to be implemented by the calibration-level subclasses. 

154 def detectorStatistics(self, inputCalib, camera=None, exposure=None): 

155 """Calculate detector level statistics from the calibration. 

156 

157 Parameters 

158 ---------- 

159 inputCalib : `lsst.ip.isr.IsrCalib` 

160 The calibration to verify. 

161 

162 Returns 

163 ------- 

164 outputStatistics : `dict` [`str`, scalar] 

165 A dictionary of the statistics measured and their values. 

166 camera : `lsst.afw.cameraGeom.Camera`, optional 

167 Input camera. 

168 exposure : `lsst.afw.image.Exposure`, optional 

169 Dummy exposure to identify a particular calibration 

170 dataset. 

171 

172 Raises 

173 ------ 

174 NotImplementedError : 

175 This method must be implemented by the calibration-type 

176 subclass. 

177 """ 

178 raise NotImplementedError("Subclasses must implement detector statistics method.") 

179 

180 def amplifierStatistics(self, inputCalib, camera=None, exposure=None): 

181 """Calculate amplifier level statistics from the calibration. 

182 

183 Parameters 

184 ---------- 

185 inputCalib : `lsst.ip.isr.IsrCalib` 

186 The calibration to verify. 

187 camera : `lsst.afw.cameraGeom.Camera`, optional 

188 Input camera. 

189 exposure : `lsst.afw.image.Exposure`, optional 

190 Dummy exposure to identify a particular calibration 

191 dataset. 

192 

193 Returns 

194 ------- 

195 outputStatistics : `dict` [`str`, scalar] 

196 A dictionary of the statistics measured and their values. 

197 

198 Raises 

199 ------ 

200 NotImplementedError : 

201 This method must be implemented by the calibration-type 

202 subclass. 

203 """ 

204 raise NotImplementedError("Subclasses must implement amplifier statistics method.") 

205 

206 def verify(self, inputCalib, statisticsDict, camera=None, exposure=None): 

207 """Verify that the measured calibration meet the verification criteria. 

208 

209 Parameters 

210 ---------- 

211 inputCalib : `lsst.ip.isr.IsrCalib` 

212 The calibration to verify. 

213 statisticsDictionary : `dict` [`str`, `dict` [`str`, scalar]], 

214 Dictionary of measured statistics. The inner dictionary 

215 should have keys that are statistic names (`str`) with 

216 values that are some sort of scalar (`int` or `float` are 

217 the mostly likely types). 

218 camera : `lsst.afw.cameraGeom.Camera`, optional 

219 Input camera. 

220 exposure : `lsst.afw.image.Exposure`, optional 

221 Dummy exposure to identify a particular calibration 

222 dataset. 

223 

224 Returns 

225 ------- 

226 outputStatistics : `dict` [`str`, `dict` [`str`, `bool`]] 

227 A dictionary indexed by the amplifier name, containing 

228 dictionaries of the verification criteria. 

229 success : `bool` 

230 A boolean indicating whether all tests have passed. 

231 

232 Raises 

233 ------ 

234 NotImplementedError : 

235 This method must be implemented by the calibration-type 

236 subclass. 

237 """ 

238 raise NotImplementedError("Subclasses must implement verification criteria.")