Coverage for python/lsst/ip/isr/photodiodeCorrection.py: 20%

71 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-08-18 12:16 -0700

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/>. 

21""" 

22PhotodiodeCorrection storage class. 

23""" 

24import numpy as np 

25from astropy.table import Table 

26from .calibType import IsrCalib 

27 

28__all__ = ["PhotodiodeCorrection"] 

29 

30 

31class PhotodiodeCorrection(IsrCalib): 

32 """Parameter set for photodiode correction. 

33 

34 These parameters are included in cameraGeom.Amplifier, but 

35 should be accessible externally to allow for testing. 

36 

37 Parameters 

38 ---------- 

39 table : `numpy.array`, optional 

40 Lookup table; a 2-dimensional array of floats: 

41 - one row for each row index (value of coef[0] in the amplifier) 

42 - one column for each image value 

43 To avoid copying the table the last index should vary fastest 

44 (numpy default "C" order) 

45 log : `logging.Logger`, optional 

46 Logger to handle messages. 

47 kwargs : `dict`, optional 

48 Other keyword arguments to pass to the parent init. 

49 

50 Raises 

51 ------ 

52 RuntimeError : 

53 Raised if the supplied table is not 2D, or if the table has fewer 

54 columns than rows (indicating that the indices are swapped). 

55 

56 Notes 

57 ----- 

58 The photodiode correction attributes stored are: 

59 abscissaCorrections : `dict` : [`str`, `float`] 

60 Correction value indexed by exposure pair 

61 """ 

62 _OBSTYPE = "PHOTODIODE_CORRECTION" 

63 _SCHEMA = 'PhotodiodeCorrection' 

64 _VERSION = 1.1 

65 

66 def __init__(self, table=None, **kwargs): 

67 self.abscissaCorrections = dict() 

68 self.tableData = None 

69 if table is not None: 

70 if len(table.shape) != 2: 

71 raise RuntimeError("table shape = %s; must have two dimensions" % (table.shape,)) 

72 if table.shape[1] < table.shape[0]: 

73 raise RuntimeError("table shape = %s; indices are switched" % (table.shape,)) 

74 self.tableData = np.array(table, order="C") 

75 

76 super().__init__(**kwargs) 

77 self.requiredAttributes.update(['abscissaCorrections']) 

78 

79 def updateMetadata(self, setDate=False, **kwargs): 

80 """Update metadata keywords with new values. 

81 

82 This calls the base class's method after ensuring the required 

83 calibration keywords will be saved. 

84 

85 Parameters 

86 ---------- 

87 setDate : `bool`, optional 

88 Update the CALIBDATE fields in the metadata to the current 

89 time. Defaults to False. 

90 kwargs : 

91 Other keyword parameters to set in the metadata. 

92 """ 

93 

94 super().updateMetadata(setDate=setDate, **kwargs) 

95 

96 @classmethod 

97 def fromDict(cls, dictionary): 

98 """Construct a PhotodiodeCorrection from a dictionary of properties. 

99 

100 Parameters 

101 ---------- 

102 dictionary : `dict` 

103 Dictionary of properties. 

104 

105 Returns 

106 ------- 

107 calib : `lsst.ip.isr.PhotodiodeCorrection` 

108 Constructed photodiode data. 

109 

110 Raises 

111 ------ 

112 RuntimeError : 

113 Raised if the supplied dictionary is for a different 

114 calibration type. 

115 """ 

116 calib = cls() 

117 

118 if calib._OBSTYPE != dictionary['metadata']['OBSTYPE']: 

119 raise RuntimeError(f"Incorrect photodiode correction supplied. Expected {calib._OBSTYPE}, " 

120 f"found {dictionary['metadata']['OBSTYPE']}") 

121 

122 calib.setMetadata(dictionary['metadata']) 

123 for pair in dictionary['pairs']: 

124 correction = dictionary['pairs'][pair] 

125 calib.abscissaCorrections[pair] = correction 

126 

127 calib.tableData = dictionary.get('tableData', None) 

128 if calib.tableData: 

129 calib.tableData = np.array(calib.tableData) 

130 

131 return calib 

132 

133 def toDict(self): 

134 """Return a dictionary containing the photodiode correction properties. 

135 

136 The dictionary should be able to be round-tripped through. 

137 `fromDict`. 

138 

139 Returns 

140 ------- 

141 dictionary : `dict` 

142 Dictionary of properties. 

143 """ 

144 self.updateMetadata() 

145 

146 outDict = dict() 

147 outDict['pairs'] = dict() 

148 outDict['metadata'] = self.getMetadata() 

149 for pair in self.abscissaCorrections.keys(): 

150 outDict['pairs'][pair] = self.abscissaCorrections[pair] 

151 

152 if self.tableData is not None: 

153 outDict['tableData'] = self.tableData.tolist() 

154 

155 return outDict 

156 

157 @classmethod 

158 def fromTable(cls, tableList): 

159 """Construct calibration from a list of tables. 

160 

161 This method uses the `fromDict` method to create the 

162 calibration after constructing an appropriate dictionary from 

163 the input tables. 

164 

165 Parameters 

166 ---------- 

167 tableList : `list` [`astropy.table.Table`] 

168 List of tables to use to construct the crosstalk 

169 calibration. 

170 

171 Returns 

172 ------- 

173 calib : `lsst.ip.isr.PhotodiodeCorrection` 

174 The calibration defined in the tables. 

175 """ 

176 dataTable = tableList[0] 

177 

178 metadata = dataTable.meta 

179 inDict = dict() 

180 inDict['metadata'] = metadata 

181 inDict['pairs'] = dict() 

182 

183 for record in dataTable: 

184 pair = record['PAIR'] 

185 inDict['pairs'][pair] = record['PD_CORR'] 

186 

187 if len(tableList) > 1: 

188 tableData = tableList[1] 

189 inDict['tableData'] = [record['LOOKUP_VALUES'] for record in tableData] 

190 

191 return cls().fromDict(inDict) 

192 

193 def toTable(self): 

194 """Construct a list of tables containing the information in this 

195 calibration. 

196 

197 The list of tables should create an identical calibration 

198 after being passed to this class's fromTable method. 

199 

200 Returns 

201 ------- 

202 tableList : `list` [`astropy.table.Table`] 

203 List of tables containing the photodiode correction 

204 information. 

205 """ 

206 tableList = [] 

207 self.updateMetadata() 

208 catalog = Table([{'PAIR': key, 

209 'PD_CORR': self.abscissaCorrections[key]} 

210 for key in self.abscissaCorrections.keys()]) 

211 catalog.meta = self.getMetadata().toDict() 

212 tableList.append(catalog) 

213 

214 if self.tableData is not None: 

215 catalog = Table([{'LOOKUP_VALUES': value} for value in self.tableData]) 

216 tableList.append(catalog) 

217 

218 return(tableList) 

219 

220 def validate(self): 

221 """Validate photodiode correction""" 

222 return