Coverage for python/lsst/ip/isr/ptcDataset.py : 6%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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"""
23Define dataset class for MeasurePhotonTransferCurve task
24"""
25import numpy as np
26from astropy.table import Table
28from lsst.ip.isr import IsrCalib
30__all__ = ['PhotonTransferCurveDataset']
33class PhotonTransferCurveDataset(IsrCalib):
34 """A simple class to hold the output data from the PTC task.
35 The dataset is made up of a dictionary for each item, keyed by the
36 amplifiers' names, which much be supplied at construction time.
37 New items cannot be added to the class to save accidentally saving to the
38 wrong property, and the class can be frozen if desired.
39 inputExpIdPairs records the exposures used to produce the data.
40 When fitPtc() or fitCovariancesAstier() is run, a mask is built up, which
41 is by definition always the same length as inputExpIdPairs, rawExpTimes,
42 rawMeans and rawVars, and is a list of bools, which are incrementally set
43 to False as points are discarded from the fits.
44 PTC fit parameters for polynomials are stored in a list in ascending order
45 of polynomial term, i.e. par[0]*x^0 + par[1]*x + par[2]*x^2 etc
46 with the length of the list corresponding to the order of the polynomial
47 plus one.
48 Parameters
49 ----------
50 ampNames : `list`
51 List with the names of the amplifiers of the detector at hand.
52 ptcFitType : `str`
53 Type of model fitted to the PTC: "POLYNOMIAL", "EXPAPPROXIMATION",
54 or "FULLCOVARIANCE".
55 kwargs : `dict`, optional
56 Other keyword arguments to pass to the parent init.
57 Notes
58 -----
59 The stored attributes are:
60 badAmps : `list`
61 List with bad amplifiers names.
62 inputExpIdPairs : `dict`, [`str`, `list`]
63 Dictionary keyed by amp names containing the input exposures IDs.
64 expIdMask : `dict`, [`str`, `list`]
65 Dictionary keyed by amp names containing the mask produced after
66 outlier rejection. The mask produced by the "FULLCOVARIANCE"
67 option may differ from the one produced in the other two PTC
68 fit types.
69 rawExpTimes : `dict`, [`str`, `list`]
70 Dictionary keyed by amp names containing the unmasked exposure times.
71 rawMeans : `dict`, [`str`, `list`]
72 Dictionary keyed by amp namescontaining the unmasked average of the
73 means of the exposures in each flat pair.
74 rawVars : `dict`, [`str`, `list`]
75 Dictionary keyed by amp names containing the variance of the
76 difference image of the exposures in each flat pair.
77 gain : `dict`, [`str`, `list`]
78 Dictionary keyed by amp names containing the fitted gains.
79 gainErr : `dict`, [`str`, `list`]
80 Dictionary keyed by amp names containing the errors on the
81 fitted gains.
82 noise : `dict`, [`str`, `list`]
83 Dictionary keyed by amp names containing the fitted noise.
84 noiseErr : `dict`, [`str`, `list`]
85 Dictionary keyed by amp names containing the errors on the fitted noise.
86 ptcFitPars : `dict`, [`str`, `list`]
87 Dictionary keyed by amp names containing the fitted parameters of the
88 PTC model for ptcFitTye in ["POLYNOMIAL", "EXPAPPROXIMATION"].
89 ptcFitParsError : `dict`, [`str`, `list`]
90 Dictionary keyed by amp names containing the errors on the fitted
91 parameters of the PTC model for ptcFitTye in
92 ["POLYNOMIAL", "EXPAPPROXIMATION"].
93 ptcFitChiSq : `dict`, [`str`, `list`]
94 Dictionary keyed by amp names containing the reduced chi squared
95 of the fit for ptcFitTye in ["POLYNOMIAL", "EXPAPPROXIMATION"].
96 covariances : `dict`, [`str`, `list`]
97 Dictionary keyed by amp names containing a list of measured
98 covariances per mean flux.
99 covariancesModel : `dict`, [`str`, `list`]
100 Dictionary keyed by amp names containinging covariances model
101 (Eq. 20 of Astier+19) per mean flux.
102 covariancesSqrtWeights : `dict`, [`str`, `list`]
103 Dictionary keyed by amp names containinging sqrt. of covariances
104 weights.
105 aMatrix : `dict`, [`str`, `list`]
106 Dictionary keyed by amp names containing the "a" parameters from
107 the model in Eq. 20 of Astier+19.
108 bMatrix : `dict`, [`str`, `list`]
109 Dictionary keyed by amp names containing the "b" parameters from
110 the model in Eq. 20 of Astier+19.
111 covariancesNoB : `dict`, [`str`, `list`]
112 Dictionary keyed by amp names containing a list of measured
113 covariances per mean flux ('b'=0 in
114 Astier+19).
115 covariancesModelNoB : `dict`, [`str`, `list`]
116 Dictionary keyed by amp names containing covariances model
117 (with 'b'=0 in Eq. 20 of Astier+19)
118 per mean flux.
119 covariancesSqrtWeightsNoB : `dict`, [`str`, `list`]
120 Dictionary keyed by amp names containing sqrt. of covariances weights
121 ('b' = 0 in Eq. 20 of
122 Astier+19).
123 aMatrixNoB : `dict`, [`str`, `list`]
124 Dictionary keyed by amp names containing the "a" parameters from the
125 model in Eq. 20 of Astier+19
126 (and 'b' = 0).
127 finalVars : `dict`, [`str`, `list`]
128 Dictionary keyed by amp names containing the masked variance of the
129 difference image of each flat
130 pair. If needed, each array will be right-padded with
131 np.nan to match the length of rawExpTimes.
132 finalModelVars : `dict`, [`str`, `list`]
133 Dictionary keyed by amp names containing the masked modeled
134 variance of the difference image of each flat pair. If needed, each
135 array will be right-padded with np.nan to match the length of
136 rawExpTimes.
137 finalMeans : `dict`, [`str`, `list`]
138 Dictionary keyed by amp names containing the masked average of the
139 means of the exposures in each flat pair. If needed, each array
140 will be right-padded with np.nan to match the length of
141 rawExpTimes.
142 photoCharge : `dict`, [`str`, `list`]
143 Dictionary keyed by amp names containing the integrated photocharge
144 for linearity calibration.
146 Returns
147 -------
148 `lsst.cp.pipe.ptc.PhotonTransferCurveDataset`
149 Output dataset from MeasurePhotonTransferCurveTask.
150 """
152 _OBSTYPE = 'PTC'
153 _SCHEMA = 'Gen3 Photon Transfer Curve'
154 _VERSION = 1.0
156 def __init__(self, ampNames=[], ptcFitType=None, **kwargs):
158 self.ptcFitType = ptcFitType
159 self.ampNames = ampNames
160 self.badAmps = []
162 self.inputExpIdPairs = {ampName: [] for ampName in ampNames}
163 self.expIdMask = {ampName: [] for ampName in ampNames}
164 self.rawExpTimes = {ampName: [] for ampName in ampNames}
165 self.rawMeans = {ampName: [] for ampName in ampNames}
166 self.rawVars = {ampName: [] for ampName in ampNames}
167 self.photoCharge = {ampName: [] for ampName in ampNames}
169 self.gain = {ampName: -1. for ampName in ampNames}
170 self.gainErr = {ampName: -1. for ampName in ampNames}
171 self.noise = {ampName: -1. for ampName in ampNames}
172 self.noiseErr = {ampName: -1. for ampName in ampNames}
174 self.ptcFitPars = {ampName: [] for ampName in ampNames}
175 self.ptcFitParsError = {ampName: [] for ampName in ampNames}
176 self.ptcFitChiSq = {ampName: [] for ampName in ampNames}
178 self.covariances = {ampName: [] for ampName in ampNames}
179 self.covariancesModel = {ampName: [] for ampName in ampNames}
180 self.covariancesSqrtWeights = {ampName: [] for ampName in ampNames}
181 self.aMatrix = {ampName: [] for ampName in ampNames}
182 self.bMatrix = {ampName: [] for ampName in ampNames}
183 self.covariancesNoB = {ampName: [] for ampName in ampNames}
184 self.covariancesModelNoB = {ampName: [] for ampName in ampNames}
185 self.covariancesSqrtWeightsNoB = {ampName: [] for ampName in ampNames}
186 self.aMatrixNoB = {ampName: [] for ampName in ampNames}
188 self.finalVars = {ampName: [] for ampName in ampNames}
189 self.finalModelVars = {ampName: [] for ampName in ampNames}
190 self.finalMeans = {ampName: [] for ampName in ampNames}
192 super().__init__(**kwargs)
193 self.requiredAttributes.update(['badAmps', 'inputExpIdPairs', 'expIdMask', 'rawExpTimes',
194 'rawMeans', 'rawVars', 'gain', 'gainErr', 'noise', 'noiseErr',
195 'ptcFitPars', 'ptcFitParsError', 'ptcFitChiSq', 'aMatrixNoB',
196 'covariances', 'covariancesModel', 'covariancesSqrtWeights',
197 'covariancesNoB', 'covariancesModelNoB', 'covariancesSqrtWeightsNoB',
198 'aMatrix', 'bMatrix', 'finalVars', 'finalModelVars', 'finalMeans',
199 'photoCharge'])
201 def __eq__(self, other):
202 """Calibration equivalence
203 """
204 if not isinstance(other, self.__class__):
205 return False
207 for attr in self._requiredAttributes:
208 attrSelf = getattr(self, attr)
209 attrOther = getattr(other, attr)
210 if isinstance(attrSelf, dict) and isinstance(attrOther, dict):
211 for ampName in attrSelf:
212 if not np.allclose(attrSelf[ampName], attrOther[ampName], equal_nan=True):
213 return False
214 else:
215 if attrSelf != attrOther:
216 return False
217 return True
219 def updateMetadata(self, setDate=False, **kwargs):
220 """Update calibration metadata.
221 This calls the base class's method after ensuring the required
222 calibration keywords will be saved.
223 Parameters
224 ----------
225 setDate : `bool`, optional
226 Update the CALIBDATE fields in the metadata to the current
227 time. Defaults to False.
228 kwargs :
229 Other keyword parameters to set in the metadata.
230 """
231 kwargs['PTC_FIT_TYPE'] = self.ptcFitType
233 super().updateMetadata(setDate=setDate, **kwargs)
235 @classmethod
236 def fromDict(cls, dictionary):
237 """Construct a calibration from a dictionary of properties.
238 Must be implemented by the specific calibration subclasses.
239 Parameters
240 ----------
241 dictionary : `dict`
242 Dictionary of properties.
243 Returns
244 -------
245 calib : `lsst.ip.isr.CalibType`
246 Constructed calibration.
247 Raises
248 ------
249 RuntimeError :
250 Raised if the supplied dictionary is for a different
251 calibration.
252 """
253 calib = cls()
254 if calib._OBSTYPE != dictionary['metadata']['OBSTYPE']:
255 raise RuntimeError(f"Incorrect Photon Transfer Curve dataset supplied. "
256 f"Expected {calib._OBSTYPE}, found {dictionary['metadata']['OBSTYPE']}")
257 calib.setMetadata(dictionary['metadata'])
258 calib.ptcFitType = dictionary['ptcFitType']
259 calib.badAmps = np.array(dictionary['badAmps'], 'str').tolist()
260 # Number of final signal levels
261 nSignalPoints = len(list(dictionary['rawMeans'].values())[0])
262 # The cov matrices are square
263 covMatrixSide = int(np.sqrt(len(np.array(list(dictionary['aMatrix'].values())[0]).ravel())))
264 for ampName in dictionary['ampNames']:
265 calib.ampNames.append(ampName)
266 calib.inputExpIdPairs[ampName] = np.array(dictionary['inputExpIdPairs'][ampName]).tolist()
267 calib.expIdMask[ampName] = np.array(dictionary['expIdMask'][ampName]).tolist()
268 calib.rawExpTimes[ampName] = np.array(dictionary['rawExpTimes'][ampName]).tolist()
269 calib.rawMeans[ampName] = np.array(dictionary['rawMeans'][ampName]).tolist()
270 calib.rawVars[ampName] = np.array(dictionary['rawVars'][ampName]).tolist()
271 calib.gain[ampName] = np.array(dictionary['gain'][ampName]).tolist()
272 calib.gainErr[ampName] = np.array(dictionary['gainErr'][ampName]).tolist()
273 calib.noise[ampName] = np.array(dictionary['noise'][ampName]).tolist()
274 calib.noiseErr[ampName] = np.array(dictionary['noiseErr'][ampName]).tolist()
275 calib.ptcFitPars[ampName] = np.array(dictionary['ptcFitPars'][ampName]).tolist()
276 calib.ptcFitParsError[ampName] = np.array(dictionary['ptcFitParsError'][ampName]).tolist()
277 calib.ptcFitChiSq[ampName] = np.array(dictionary['ptcFitChiSq'][ampName]).tolist()
278 calib.covariances[ampName] = np.array(dictionary['covariances'][ampName]).reshape(
279 (nSignalPoints, covMatrixSide, covMatrixSide)).tolist()
280 calib.covariancesModel[ampName] = np.array(
281 dictionary['covariancesModel'][ampName]).reshape(
282 (nSignalPoints, covMatrixSide, covMatrixSide)).tolist()
283 calib.covariancesSqrtWeights[ampName] = np.array(
284 dictionary['covariancesSqrtWeights'][ampName]).reshape(
285 (nSignalPoints, covMatrixSide, covMatrixSide)).tolist()
286 calib.aMatrix[ampName] = np.array(dictionary['aMatrix'][ampName]).reshape(
287 (covMatrixSide, covMatrixSide)).tolist()
288 calib.bMatrix[ampName] = np.array(dictionary['bMatrix'][ampName]).reshape(
289 (covMatrixSide, covMatrixSide)).tolist()
290 calib.covariancesNoB[ampName] = np.array(
291 dictionary['covariancesNoB'][ampName]).reshape(
292 (nSignalPoints, covMatrixSide, covMatrixSide)).tolist()
293 calib.covariancesModelNoB[ampName] = np.array(
294 dictionary['covariancesModelNoB'][ampName]).reshape(
295 (nSignalPoints, covMatrixSide, covMatrixSide)).tolist()
296 calib.covariancesSqrtWeightsNoB[ampName] = np.array(
297 dictionary['covariancesSqrtWeightsNoB'][ampName]).reshape(
298 (nSignalPoints, covMatrixSide, covMatrixSide)).tolist()
299 calib.aMatrixNoB[ampName] = np.array(
300 dictionary['aMatrixNoB'][ampName]).reshape((covMatrixSide, covMatrixSide)).tolist()
301 calib.finalVars[ampName] = np.array(dictionary['finalVars'][ampName]).tolist()
302 calib.finalModelVars[ampName] = np.array(dictionary['finalModelVars'][ampName]).tolist()
303 calib.finalMeans[ampName] = np.array(dictionary['finalMeans'][ampName]).tolist()
304 calib.photoCharge[ampName] = np.array(dictionary['photoCharge'][ampName]).tolist()
305 calib.updateMetadata()
306 return calib
308 def toDict(self):
309 """Return a dictionary containing the calibration properties.
310 The dictionary should be able to be round-tripped through
311 `fromDict`.
312 Returns
313 -------
314 dictionary : `dict`
315 Dictionary of properties.
316 """
317 self.updateMetadata()
319 outDict = dict()
320 metadata = self.getMetadata()
321 outDict['metadata'] = metadata
323 outDict['ptcFitType'] = self.ptcFitType
324 outDict['ampNames'] = self.ampNames
325 outDict['badAmps'] = self.badAmps
326 outDict['inputExpIdPairs'] = self.inputExpIdPairs
327 outDict['expIdMask'] = self.expIdMask
328 outDict['rawExpTimes'] = self.rawExpTimes
329 outDict['rawMeans'] = self.rawMeans
330 outDict['rawVars'] = self.rawVars
331 outDict['gain'] = self.gain
332 outDict['gainErr'] = self.gainErr
333 outDict['noise'] = self.noise
334 outDict['noiseErr'] = self.noiseErr
335 outDict['ptcFitPars'] = self.ptcFitPars
336 outDict['ptcFitParsError'] = self.ptcFitParsError
337 outDict['ptcFitChiSq'] = self.ptcFitChiSq
338 outDict['covariances'] = self.covariances
339 outDict['covariancesModel'] = self.covariancesModel
340 outDict['covariancesSqrtWeights'] = self.covariancesSqrtWeights
341 outDict['aMatrix'] = self.aMatrix
342 outDict['bMatrix'] = self.bMatrix
343 outDict['covariancesNoB'] = self.covariancesNoB
344 outDict['covariancesModelNoB'] = self.covariancesModelNoB
345 outDict['covariancesSqrtWeightsNoB'] = self.covariancesSqrtWeightsNoB
346 outDict['aMatrixNoB'] = self.aMatrixNoB
347 outDict['finalVars'] = self.finalVars
348 outDict['finalModelVars'] = self.finalModelVars
349 outDict['finalMeans'] = self.finalMeans
350 outDict['photoCharge'] = self.photoCharge
352 return outDict
354 @classmethod
355 def fromTable(cls, tableList):
356 """Construct calibration from a list of tables.
357 This method uses the `fromDict` method to create the
358 calibration, after constructing an appropriate dictionary from
359 the input tables.
360 Parameters
361 ----------
362 tableList : `list` [`lsst.afw.table.Table`]
363 List of tables to use to construct the datasetPtc.
364 Returns
365 -------
366 calib : `lsst.cp.pipe.`
367 The calibration defined in the tables.
368 """
369 ptcTable = tableList[0]
371 metadata = ptcTable.meta
372 inDict = dict()
373 inDict['metadata'] = metadata
374 inDict['ampNames'] = []
375 inDict['ptcFitType'] = []
376 inDict['inputExpIdPairs'] = dict()
377 inDict['expIdMask'] = dict()
378 inDict['rawExpTimes'] = dict()
379 inDict['rawMeans'] = dict()
380 inDict['rawVars'] = dict()
381 inDict['gain'] = dict()
382 inDict['gainErr'] = dict()
383 inDict['noise'] = dict()
384 inDict['noiseErr'] = dict()
385 inDict['ptcFitPars'] = dict()
386 inDict['ptcFitParsError'] = dict()
387 inDict['ptcFitChiSq'] = dict()
388 inDict['covariances'] = dict()
389 inDict['covariancesModel'] = dict()
390 inDict['covariancesSqrtWeights'] = dict()
391 inDict['aMatrix'] = dict()
392 inDict['bMatrix'] = dict()
393 inDict['covariancesNoB'] = dict()
394 inDict['covariancesModelNoB'] = dict()
395 inDict['covariancesSqrtWeightsNoB'] = dict()
396 inDict['aMatrixNoB'] = dict()
397 inDict['finalVars'] = dict()
398 inDict['finalModelVars'] = dict()
399 inDict['finalMeans'] = dict()
400 inDict['badAmps'] = []
401 inDict['photoCharge'] = dict()
403 for record in ptcTable:
404 ampName = record['AMPLIFIER_NAME']
406 inDict['ptcFitType'] = record['PTC_FIT_TYPE']
407 inDict['ampNames'].append(ampName)
408 inDict['inputExpIdPairs'][ampName] = record['INPUT_EXP_ID_PAIRS']
409 inDict['expIdMask'][ampName] = record['EXP_ID_MASK']
410 inDict['rawExpTimes'][ampName] = record['RAW_EXP_TIMES']
411 inDict['rawMeans'][ampName] = record['RAW_MEANS']
412 inDict['rawVars'][ampName] = record['RAW_VARS']
413 inDict['gain'][ampName] = record['GAIN']
414 inDict['gainErr'][ampName] = record['GAIN_ERR']
415 inDict['noise'][ampName] = record['NOISE']
416 inDict['noiseErr'][ampName] = record['NOISE_ERR']
417 inDict['ptcFitPars'][ampName] = record['PTC_FIT_PARS']
418 inDict['ptcFitParsError'][ampName] = record['PTC_FIT_PARS_ERROR']
419 inDict['ptcFitChiSq'][ampName] = record['PTC_FIT_CHI_SQ']
420 inDict['covariances'][ampName] = record['COVARIANCES']
421 inDict['covariancesModel'][ampName] = record['COVARIANCES_MODEL']
422 inDict['covariancesSqrtWeights'][ampName] = record['COVARIANCES_SQRT_WEIGHTS']
423 inDict['aMatrix'][ampName] = record['A_MATRIX']
424 inDict['bMatrix'][ampName] = record['B_MATRIX']
425 inDict['covariancesNoB'][ampName] = record['COVARIANCES_NO_B']
426 inDict['covariancesModelNoB'][ampName] = record['COVARIANCES_MODEL_NO_B']
427 inDict['covariancesSqrtWeightsNoB'][ampName] = record['COVARIANCES_SQRT_WEIGHTS_NO_B']
428 inDict['aMatrixNoB'][ampName] = record['A_MATRIX_NO_B']
429 inDict['finalVars'][ampName] = record['FINAL_VARS']
430 inDict['finalModelVars'][ampName] = record['FINAL_MODEL_VARS']
431 inDict['finalMeans'][ampName] = record['FINAL_MEANS']
432 inDict['badAmps'] = record['BAD_AMPS']
433 inDict['photoCharge'][ampName] = record['PHOTO_CHARGE']
434 return cls().fromDict(inDict)
436 def toTable(self):
437 """Construct a list of tables containing the information in this
438 calibration.
440 The list of tables should create an identical calibration
441 after being passed to this class's fromTable method.
442 Returns
443 -------
444 tableList : `list` [`astropy.table.Table`]
445 List of tables containing the linearity calibration
446 information.
447 """
448 tableList = []
449 self.updateMetadata()
450 nSignalPoints = len(list(self.rawExpTimes.values())[0])
451 covMatrixSide = np.array(list(self.aMatrix.values())[0]).shape[0]
452 catalog = Table([{'AMPLIFIER_NAME': ampName,
453 'PTC_FIT_TYPE': self.ptcFitType,
454 'INPUT_EXP_ID_PAIRS': self.inputExpIdPairs[ampName],
455 'EXP_ID_MASK': self.expIdMask[ampName],
456 'RAW_EXP_TIMES': self.rawExpTimes[ampName],
457 'RAW_MEANS': self.rawMeans[ampName],
458 'RAW_VARS': self.rawVars[ampName],
459 'GAIN': self.gain[ampName],
460 'GAIN_ERR': self.gainErr[ampName],
461 'NOISE': self.noise[ampName],
462 'NOISE_ERR': self.noiseErr[ampName],
463 'PTC_FIT_PARS': np.array(self.ptcFitPars[ampName]).tolist(),
464 'PTC_FIT_PARS_ERROR': np.array(self.ptcFitParsError[ampName]).tolist(),
465 'PTC_FIT_CHI_SQ': self.ptcFitChiSq[ampName],
466 'COVARIANCES': np.array(self.covariances[ampName]).reshape(
467 nSignalPoints*covMatrixSide**2).tolist(),
468 'COVARIANCES_MODEL':
469 np.array(self.covariancesModel[ampName]).reshape(
470 nSignalPoints*covMatrixSide**2).tolist(),
471 'COVARIANCES_SQRT_WEIGHTS':
472 np.array(self.covariancesSqrtWeights[ampName]).reshape(
473 nSignalPoints*covMatrixSide**2).tolist(),
474 'A_MATRIX': np.array(self.aMatrix[ampName]).reshape(covMatrixSide**2).tolist(),
475 'B_MATRIX': np.array(self.bMatrix[ampName]).reshape(covMatrixSide**2).tolist(),
476 'COVARIANCES_NO_B':
477 np.array(self.covariancesNoB[ampName]).reshape(
478 nSignalPoints*covMatrixSide**2).tolist(),
479 'COVARIANCES_MODEL_NO_B':
480 np.array(self.covariancesModelNoB[ampName]).reshape(
481 nSignalPoints*covMatrixSide**2).tolist(),
482 'COVARIANCES_SQRT_WEIGHTS_NO_B':
483 np.array(self.covariancesSqrtWeightsNoB[ampName]).reshape(
484 nSignalPoints*covMatrixSide**2).tolist(),
485 'A_MATRIX_NO_B':
486 np.array(self.aMatrixNoB[ampName]).reshape(covMatrixSide**2).tolist(),
487 'FINAL_VARS': self.finalVars[ampName],
488 'FINAL_MODEL_VARS': self.finalModelVars[ampName],
489 'FINAL_MEANS': self.finalMeans[ampName],
490 'BAD_AMPS': np.array(self.badAmps).tolist() if len(self.badAmps) else np.nan,
491 'PHOTO_CHARGE': np.array(self.photoCharge[ampName]).tolist()
492 } for ampName in self.ampNames])
494 inMeta = self.getMetadata().toDict()
495 outMeta = {k: v for k, v in inMeta.items() if v is not None}
496 outMeta.update({k: "" for k, v in inMeta.items() if v is None})
497 catalog.meta = outMeta
498 tableList.append(catalog)
500 return(tableList)
502 def getExpIdsUsed(self, ampName):
503 """Get the exposures used, i.e. not discarded, for a given amp.
504 If no mask has been created yet, all exposures are returned.
505 """
506 if len(self.expIdMask[ampName]) == 0:
507 return self.inputExpIdPairs[ampName]
509 # if the mask exists it had better be the same length as the expIdPairs
510 assert len(self.expIdMask[ampName]) == len(self.inputExpIdPairs[ampName])
512 pairs = self.inputExpIdPairs[ampName]
513 mask = self.expIdMask[ampName]
514 # cast to bool required because numpy
515 return [(exp1, exp2) for ((exp1, exp2), m) in zip(pairs, mask) if bool(m) is True]
517 def getGoodAmps(self):
518 return [amp for amp in self.ampNames if amp not in self.badAmps]