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

30 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-07 03:59 -0800

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 

25from lsst.cp.pipe._lookupStaticCalibration import lookupStaticCalibration 

26 

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

28 

29 

30class CpVerifyCalibConnections(pipeBase.PipelineTaskConnections, 

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

32 defaultTemplates={}): 

33 

34 exposure = cT.Input( 

35 name="raw", 

36 doc="Exposure to retreve calibration", 

37 storageClass='Exposure', 

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

39 multiple=True, 

40 deferLoad=True, 

41 ) 

42 

43 inputCalib = cT.Input( 

44 name="calib", 

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

46 storageClass="IsrCalib", 

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

48 isCalibration=True 

49 ) 

50 

51 camera = cT.PrerequisiteInput( 

52 name="camera", 

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

54 storageClass="Camera", 

55 dimensions=("instrument",), 

56 lookupFunction=lookupStaticCalibration, 

57 isCalibration=True, 

58 ) 

59 

60 outputStats = cT.Output( 

61 name="calibStats", 

62 doc="Output statistics from cp_verify.", 

63 storageClass="StructuredDataDict", 

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

65 ) 

66 

67 

68class CpVerifyCalibConfig(pipeBase.PipelineTaskConfig, 

69 pipelineConnections=CpVerifyCalibConnections): 

70 """Configuration parameters for CpVerifyCalibTask. 

71 """ 

72 # Statistics options. 

73 useReadNoise = pexConfig.Field( 

74 dtype=bool, 

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

76 default=True, 

77 ) 

78 numSigmaClip = pexConfig.Field( 

79 dtype=float, 

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

81 default=5.0, 

82 ) 

83 clipMaxIter = pexConfig.Field( 

84 dtype=int, 

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

86 default=3, 

87 ) 

88 

89 # Keywords and statistics to measure from different sources. 

90 calibStatKeywords = pexConfig.DictField( 

91 keytype=str, 

92 itemtype=str, 

93 doc="Calib statistics to run.", 

94 default={}, 

95 ) 

96 

97 

98class CpVerifyCalibTask(pipeBase.PipelineTask): 

99 """Main statistic measurement and validation class. 

100 

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

102 subclassed so specific calibrations can apply their own validation 

103 methods. 

104 """ 

105 

106 ConfigClass = CpVerifyCalibConfig 

107 _DefaultName = 'cpVerifyCalib' 

108 

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

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

111 for a calibration. 

112 

113 Parameters 

114 ---------- 

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

116 The calibration to be measured. 

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

118 Input camera. 

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

120 Dummy exposure to identify a particular calibration 

121 dataset. 

122 

123 Returns 

124 ------- 

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

126 Result struct with components: 

127 - ``outputStats`` : `dict` 

128 The output measured statistics. 

129 

130 Notes 

131 ----- 

132 The outputStats should have a yaml representation of the form 

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

134 names) 

135 

136 DET: 

137 STAT: value 

138 STAT2: value 

139 AMP: 

140 STAT: value 

141 STAT2: value 

142 VERIFY: 

143 TEST: boolean 

144 SUCCESS: boolean 

145 

146 """ 

147 outputStats = {} 

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

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

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

151 

152 return pipeBase.Struct( 

153 outputStats=outputStats, 

154 ) 

155 

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

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

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

159 

160 Parameters 

161 ---------- 

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

163 The calibration to verify. 

164 

165 Returns 

166 ------- 

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

168 A dictionary of the statistics measured and their values. 

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

170 Input camera. 

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

172 Dummy exposure to identify a particular calibration 

173 dataset. 

174 

175 Raises 

176 ------ 

177 NotImplementedError : 

178 This method must be implemented by the calibration-type 

179 subclass. 

180 """ 

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

182 

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

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

185 

186 Parameters 

187 ---------- 

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

189 The calibration to verify. 

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

191 Input camera. 

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

193 Dummy exposure to identify a particular calibration 

194 dataset. 

195 

196 Returns 

197 ------- 

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

199 A dictionary of the statistics measured and their values. 

200 

201 Raises 

202 ------ 

203 NotImplementedError : 

204 This method must be implemented by the calibration-type 

205 subclass. 

206 """ 

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

208 

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

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

211 

212 Parameters 

213 ---------- 

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

215 The calibration to verify. 

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

217 Dictionary of measured statistics. The inner dictionary 

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

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

220 the mostly likely types). 

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

222 Input camera. 

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

224 Dummy exposure to identify a particular calibration 

225 dataset. 

226 

227 Returns 

228 ------- 

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

230 A dictionary indexed by the amplifier name, containing 

231 dictionaries of the verification criteria. 

232 success : `bool` 

233 A boolean indicating whether all tests have passed. 

234 

235 Raises 

236 ------ 

237 NotImplementedError : 

238 This method must be implemented by the calibration-type 

239 subclass. 

240 """ 

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