Coverage for python/lsst/analysis/tools/atools/calibQuantityProfile.py: 29%

140 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-15 02:37 -0700

1# This file is part of analysis_tools. 

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

21from __future__ import annotations 

22 

23from lsst.analysis.tools.interfaces._interfaces import KeyedDataSchema 

24 

25__all__ = ( 

26 "CalibQuantityBaseTool", 

27 "CalibQuantityAmpProfileScatterTool", 

28 "CalibQuantityAmpProfileHistTool", 

29 "CalibAmpScatterTool", 

30 "CalibDivisaderoScatterTool", 

31 "CalibPtcCovarScatterTool", 

32) 

33 

34from typing import cast 

35 

36from lsst.pex.config import Field 

37from lsst.pex.config.configurableActions import ConfigurableActionField 

38 

39from ..actions.plot.elements import HistElement, ScatterElement 

40from ..actions.plot.gridPlot import GridPanelConfig, GridPlot 

41from ..interfaces import AnalysisTool, KeyedData, KeyedDataAction, PlotElement, Vector 

42 

43 

44class PrepRepacker(KeyedDataAction): 

45 """Prep action to repack data.""" 

46 

47 panelKey = Field[str]( 

48 doc="Panel selector. Data will be separated into multiple panels based on this key.", 

49 ) 

50 dataKey = Field[str]( 

51 doc="Data selector. Data will be separated into multiple groups in a single panel based on this key.", 

52 ) 

53 quantityKey = Field[str]( 

54 doc="Quantity selector. The actual data quantities to be plotted.", 

55 ) 

56 

57 def __call__(self, data: KeyedData, **kwargs) -> KeyedData: 

58 repackedData = {} 

59 # Loop over the length of the data vector and repack row by row 

60 for i in range(len(cast(Vector, data[self.panelKey]))): 

61 panelVec = cast(Vector, data[self.panelKey]) 

62 dataVec = cast(Vector, data[self.dataKey]) 

63 quantityVec = cast(Vector, data[self.quantityKey]) 

64 repackedData[f"{panelVec[i]}_{dataVec[i]}_{self.quantityKey}"] = quantityVec[i] 

65 return repackedData 

66 

67 def getInputSchema(self) -> KeyedDataSchema: 

68 return ( 

69 (self.panelKey, Vector), 

70 (self.dataKey, Vector), 

71 (self.quantityKey, Vector), 

72 ) 

73 

74 def addInputSchema(self, inputSchema: KeyedDataSchema) -> None: 

75 pass 

76 

77 

78class SingleValueRepacker(KeyedDataAction): 

79 """Prep action to repack data.""" 

80 

81 panelKey = Field[str]( 

82 doc="Panel selector. Data will be separated into multiple panels based on this key.", 

83 ) 

84 dataKey = Field[str]( 

85 doc="Data selector. Data will be separated into multiple groups in a single panel based on this key.", 

86 ) 

87 quantityKey = Field[str]( 

88 doc="Quantity selector. The actual data quantities to be plotted.", 

89 ) 

90 

91 def __call__(self, data: KeyedData, **kwargs) -> KeyedData: 

92 repackedData = {} 

93 uniquePanelKeys = list(set(data[self.panelKey])) 

94 

95 # Loop over data vector to repack information as it is expected. 

96 for i in range(len(uniquePanelKeys)): 

97 repackedData[f"{uniquePanelKeys[i]}_x"] = [] 

98 repackedData[f"{uniquePanelKeys[i]}"] = [] 

99 

100 panelVec = cast(Vector, data[self.panelKey]) 

101 dataVec = cast(Vector, data[self.dataKey]) 

102 quantityVec = cast(Vector, data[self.quantityKey]) 

103 

104 for i in range(len(panelVec)): 

105 repackedData[f"{panelVec[i]}_x"].append(dataVec[i]) 

106 repackedData[f"{panelVec[i]}"].append(quantityVec[i]) 

107 

108 return repackedData 

109 

110 def getInputSchema(self) -> KeyedDataSchema: 

111 return ( 

112 (self.panelKey, Vector), 

113 (self.dataKey, Vector), 

114 (self.quantityKey, Vector), 

115 ) 

116 

117 def addInputSchema(self, inputSchema: KeyedDataSchema) -> None: 

118 pass 

119 

120 

121class PassThrough(KeyedDataAction): 

122 def __call__(self, data: KeyedData, **kwargs) -> KeyedData: 

123 return data 

124 

125 def getInputSchema(self) -> KeyedDataSchema: 

126 # In general this method should be implemented, but here we are ALSO 

127 # implementing the prep step. We therefore know the method results are 

128 # not needed because it is doing something special with the inputs. 

129 return () 

130 

131 

132class CalibQuantityBaseTool(AnalysisTool): 

133 parameterizedBand: bool = False 

134 

135 plotElement = ConfigurableActionField[PlotElement]( 

136 doc="Plot element.", 

137 ) 

138 

139 def setDefaults(self): 

140 super().setDefaults() 

141 

142 # Repack the input data into a usable format 

143 self.prep = PrepRepacker() 

144 

145 # A simple pass-through process action to keep the data unchanged 

146 self.process = PassThrough() 

147 

148 # Plot the repacked data in a 4x4 grid 

149 self.produce.plot = GridPlot() 

150 self.produce.plot.panels = {} 

151 self.produce.plot.numRows = 4 

152 self.produce.plot.numCols = 4 

153 

154 # Values to group by to distinguish between data in differing panels 

155 self.produce.plot.valsGroupBy = { 

156 0: "C00", 

157 1: "C01", 

158 2: "C02", 

159 3: "C03", 

160 4: "C04", 

161 5: "C05", 

162 6: "C06", 

163 7: "C07", 

164 8: "C10", 

165 9: "C11", 

166 10: "C12", 

167 11: "C13", 

168 12: "C14", 

169 13: "C15", 

170 14: "C16", 

171 15: "C17", 

172 } 

173 

174 def finalize(self): 

175 super().finalize() 

176 

177 # Configure each panel 

178 for key, value in self.produce.plot.valsGroupBy.items(): 

179 gridPanelConfig = GridPanelConfig( 

180 plotElement=self.plotElement, 

181 title={"label": str(value), "fontsize": "10"}, 

182 titleY=0.85, 

183 ) 

184 self.produce.plot.panels[key] = gridPanelConfig 

185 

186 

187class CalibQuantityAmpProfileScatterTool(CalibQuantityBaseTool): 

188 def setDefaults(self): 

189 super().setDefaults() 

190 self.plotElement = ScatterElement() 

191 self.prep.panelKey = "amplifier" 

192 self.prep.dataKey = "mjd" 

193 

194 

195class CalibQuantityAmpProfileHistTool(CalibQuantityBaseTool): 

196 def setDefaults(self): 

197 super().setDefaults() 

198 self.plotElement = HistElement() 

199 self.prep.panelKey = "amplifier" 

200 self.prep.dataKey = "mjd" 

201 

202 

203class CalibAmpScatterTool(CalibQuantityBaseTool): 

204 def setDefaults(self): 

205 super().setDefaults() 

206 self.plotElement = ScatterElement() 

207 

208 # Repack the input data into a usable format 

209 self.prep = SingleValueRepacker() 

210 

211 self.produce.plot = GridPlot() 

212 self.produce.plot.panels = {} 

213 self.produce.plot.numRows = 4 

214 self.produce.plot.numCols = 4 

215 

216 # Values to use for x-axis data 

217 self.produce.plot.xDataKeys = { 

218 0: "C00_x", 

219 1: "C01_x", 

220 2: "C02_x", 

221 3: "C03_x", 

222 4: "C04_x", 

223 5: "C05_x", 

224 6: "C06_x", 

225 7: "C07_x", 

226 8: "C10_x", 

227 9: "C11_x", 

228 10: "C12_x", 

229 11: "C13_x", 

230 12: "C14_x", 

231 13: "C15_x", 

232 14: "C16_x", 

233 15: "C17_x", 

234 } 

235 

236 # Values to group by to distinguish between data in differing panels 

237 self.produce.plot.valsGroupBy = { 

238 0: "C00", 

239 1: "C01", 

240 2: "C02", 

241 3: "C03", 

242 4: "C04", 

243 5: "C05", 

244 6: "C06", 

245 7: "C07", 

246 8: "C10", 

247 9: "C11", 

248 10: "C12", 

249 11: "C13", 

250 12: "C14", 

251 13: "C15", 

252 14: "C16", 

253 15: "C17", 

254 } 

255 

256 self.prep.panelKey = "amplifier" 

257 self.prep.dataKey = "mjd" 

258 

259 def finalize(self): 

260 super().finalize() 

261 

262 # Configure each panel 

263 for key, value in self.produce.plot.valsGroupBy.items(): 

264 gridPanelConfig = GridPanelConfig( 

265 plotElement=self.plotElement, 

266 title={"label": str(value), "fontsize": "10"}, 

267 titleY=0.85, 

268 ) 

269 self.produce.plot.panels[key] = gridPanelConfig 

270 self.produce.plot.panels[key].plotElement.xKey = f"{value}_x" 

271 self.produce.plot.panels[key].plotElement.valsKey = value 

272 

273 

274class CalibDivisaderoScatterTool(CalibQuantityBaseTool): 

275 def setDefaults(self): 

276 super().setDefaults() 

277 self.plotElement = ScatterElement() 

278 

279 # Repack the input data into a usable format 

280 self.prep = SingleValueRepacker() 

281 

282 self.produce.plot = GridPlot() 

283 self.produce.plot.panels = {} 

284 self.produce.plot.numRows = 2 

285 self.produce.plot.numCols = 1 

286 

287 # Values to group by to distinguish between data in differing panels 

288 self.produce.plot.valsGroupBy = {0: "bank1", 1: "bank0"} 

289 

290 self.produce.plot.xDataKeys = { 

291 0: "bank1_x", 

292 1: "bank0_x", 

293 } 

294 self.prep.panelKey = "amplifier" 

295 self.prep.dataKey = "mjd" 

296 

297 def finalize(self): 

298 super().finalize() 

299 

300 # Configure each panel 

301 for key, value in self.produce.plot.valsGroupBy.items(): 

302 gridPanelConfig = GridPanelConfig( 

303 plotElement=self.plotElement, 

304 title={"label": str(value), "fontsize": "10"}, 

305 titleY=0.85, 

306 ) 

307 self.produce.plot.panels[key] = gridPanelConfig 

308 self.produce.plot.panels[key].plotElement.xKey = f"{value}_x" 

309 self.produce.plot.panels[key].plotElement.valsKey = value 

310 

311 

312class CalibPtcCovarScatterTool(CalibQuantityBaseTool): 

313 def setDefaults(self): 

314 super().setDefaults() 

315 self.plotElement = ScatterElement() 

316 

317 # Repack the input data into a usable format 

318 self.prep = PrepRepacker() 

319 

320 self.produce.plot = GridPlot() 

321 self.produce.plot.panels = {} 

322 self.produce.plot.numRows = 3 

323 self.produce.plot.numCols = 2 

324 

325 # Values to group by to distinguish between data in differing panels 

326 self.produce.plot.valsGroupBy = { 

327 0: "PTC_COV_10", 

328 1: "PTC_COV_20", 

329 2: "PTC_COV_01", 

330 3: "PTC_COV_02", 

331 4: "PTC_COV_11", 

332 5: None, 

333 } 

334 

335 self.produce.plot.xDataKeys = { 

336 0: "PTC_PTC_RAW_MEANS", 

337 1: "PTC_PTC_RAW_MEANS", 

338 2: "PTC_PTC_RAW_MEANS", 

339 3: "PTC_PTC_RAW_MEANS", 

340 4: "PTC_PTC_RAW_MEANS", 

341 5: None, 

342 } 

343 self.prep.panelKey = "amplifier" 

344 self.prep.dataKey = "mjd" 

345 

346 def finalize(self): 

347 super().finalize() 

348 

349 # Configure each panel 

350 for key, value in self.produce.plot.valsGroupBy.items(): 

351 gridPanelConfig = GridPanelConfig( 

352 plotElement=self.plotElement, 

353 title={"label": str(value), "fontsize": "10"}, 

354 titleY=0.85, 

355 ) 

356 self.produce.plot.panels[key] = gridPanelConfig 

357 self.produce.plot.panels[key].plotElement.xKey = "PTC_PTC_RAW_MEANS" 

358 self.produce.plot.panels[key].plotElement.valsKey = f"PTC_{value}"