LSST Applications g0fba68d861+bb7a7cfa1f,g1ec0fe41b4+f536777771,g1fd858c14a+470a99fdf4,g216c3ac8a7+0d4d80193f,g35bb328faa+fcb1d3bbc8,g4d2262a081+23bd310d1b,g53246c7159+fcb1d3bbc8,g56a49b3a55+369644a549,g5a012ec0e7+3632fc3ff3,g60b5630c4e+3bfb9058a5,g67b6fd64d1+ed4b5058f4,g78460c75b0+2f9a1b4bcd,g786e29fd12+cf7ec2a62a,g8180f54f50+60bd39f3b6,g8352419a5c+fcb1d3bbc8,g87d29937c9+57a68d035f,g8852436030+4699110379,g89139ef638+ed4b5058f4,g9125e01d80+fcb1d3bbc8,g94187f82dc+3bfb9058a5,g989de1cb63+ed4b5058f4,g9ccd5d7f00+b7cae620c0,g9d31334357+3bfb9058a5,g9f33ca652e+00883ace41,gabe3b4be73+1e0a283bba,gabf8522325+fa80ff7197,gb1101e3267+27b24065a3,gb58c049af0+f03b321e39,gb89ab40317+ed4b5058f4,gc0af124501+708fe67c54,gcf25f946ba+4699110379,gd6cbbdb0b4+bb83cc51f8,gde0f65d7ad+acd5afb0eb,ge1ad929117+3bfb9058a5,ge278dab8ac+d65b3c2b70,ge410e46f29+ed4b5058f4,gf5e32f922b+fcb1d3bbc8,gf67bdafdda+ed4b5058f4,w.2025.17
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset Class Reference
Inheritance diagram for lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset:
lsst.ip.isr.calibType.IsrCalib

Public Member Functions

 __init__ (self, ampNames=[], ptcFitType=None, covMatrixSide=1, covMatrixSideFullCovFit=None, **kwargs)
 
 setAmpValuesPartialDataset (self, ampName, inputExpIdPair=(-1, -1), inputExpPairMjdStart=np.nan, rawExpTime=np.nan, rawMean=np.nan, rawVar=np.nan, rowMeanVariance=np.nan, photoCharge=np.nan, ampOffset=np.nan, expIdMask=False, covariance=None, covSqrtWeights=None, gain=np.nan, noise=np.nan, overscanMedianLevel=np.nan, histVar=np.nan, histChi2Dof=np.nan, kspValue=0.0)
 
 setAuxValuesPartialDataset (self, auxDict)
 
 updateMetadata (self, **kwargs)
 
 fromDict (cls, dictionary)
 
 toDict (self)
 
 fromTable (cls, tableList)
 
 toTable (self)
 
 fromDetector (self, detector)
 
 appendPartialPtc (self, partialPtc)
 
 sort (self, sortIndex)
 
 getExpIdsUsed (self, ampName)
 
 getGoodAmps (self)
 
 getGoodPoints (self, ampName)
 
 validateGainNoiseTurnoffValues (self, ampName, doWarn=False)
 
 evalPtcModel (self, mu)
 
 requiredAttributes (self)
 
 requiredAttributes (self, value)
 
 __str__ (self)
 
 __eq__ (self, other)
 
 metadata (self)
 
 getMetadata (self)
 
 setMetadata (self, metadata)
 
 updateMetadataFromExposures (self, exposures)
 
 calibInfoFromDict (self, dictionary)
 
 determineCalibClass (cls, metadata, message)
 
 readText (cls, filename, **kwargs)
 
 writeText (self, filename, format="auto")
 
 readFits (cls, filename, **kwargs)
 
 writeFits (self, filename)
 
 validate (self, other=None)
 
 apply (self, target)
 

Public Attributes

str ptcFitType = ptcFitType
 
 ampNames = ampNames
 
 covMatrixSide = covMatrixSide
 
 covMatrixSideFullCovFit = covMatrixSide
 
list badAmps = []
 
dict inputExpIdPairs = {ampName: [] for ampName in ampNames}
 
dict inputExpPairMjdStartList = {ampName: np.array([]) for ampName in ampNames}
 
dict expIdMask = {ampName: np.array([], dtype=bool) for ampName in ampNames}
 
dict rawExpTimes = {ampName: np.array([]) for ampName in ampNames}
 
dict rawMeans = {ampName: np.array([]) for ampName in ampNames}
 
dict rawVars = {ampName: np.array([]) for ampName in ampNames}
 
dict rowMeanVariance = {ampName: np.array([]) for ampName in ampNames}
 
dict photoCharges = {ampName: np.array([]) for ampName in ampNames}
 
dict ampOffsets = {ampName: np.array([]) for ampName in ampNames}
 
dict gain = {ampName: np.nan for ampName in ampNames}
 
dict gainUnadjusted = {ampName: np.nan for ampName in ampNames}
 
dict gainErr = {ampName: np.nan for ampName in ampNames}
 
dict gainList = {ampName: np.array([]) for ampName in ampNames}
 
dict overscanMedianLevelList = {ampName: np.array([]) for ampName in ampNames}
 
dict overscanMedian = {ampName: np.nan for ampName in ampNames}
 
dict overscanMedianSigma = {ampName: np.nan for ampName in ampNames}
 
dict noiseList = {ampName: np.array([]) for ampName in ampNames}
 
dict noise = {ampName: np.nan for ampName in ampNames}
 
dict noiseErr = {ampName: np.nan for ampName in ampNames}
 
dict histVars = {ampName: np.array([]) for ampName in ampNames}
 
dict histChi2Dofs = {ampName: np.array([]) for ampName in ampNames}
 
dict kspValues = {ampName: np.array([]) for ampName in ampNames}
 
dict ptcFitPars = {ampName: np.array([]) for ampName in ampNames}
 
dict ptcFitParsError = {ampName: np.array([]) for ampName in ampNames}
 
dict ptcFitChiSq = {ampName: np.nan for ampName in ampNames}
 
dict ptcTurnoff = {ampName: np.nan for ampName in ampNames}
 
dict ptcTurnoffSamplingError = {ampName: np.nan for ampName in ampNames}
 
dict covariances = {ampName: np.array([]) for ampName in ampNames}
 
dict covariancesModel = {ampName: np.array([]) for ampName in ampNames}
 
dict covariancesSqrtWeights = {ampName: np.array([]) for ampName in ampNames}
 
dict aMatrix = {ampName: np.array([]) for ampName in ampNames}
 
dict bMatrix = {ampName: np.array([]) for ampName in ampNames}
 
dict noiseMatrix = {ampName: np.array([]) for ampName in ampNames}
 
dict finalVars = {ampName: np.array([]) for ampName in ampNames}
 
dict finalModelVars = {ampName: np.array([]) for ampName in ampNames}
 
dict finalMeans = {ampName: np.array([]) for ampName in ampNames}
 
dict auxValues = {}
 
 requiredAttributes = set(["_OBSTYPE", "_SCHEMA", "_VERSION"])
 
 log = log if log else logging.getLogger(__name__)
 

Protected Member Functions

 _validateCovarianceMatrizSizes (self)
 

Protected Attributes

 _instrument = None
 
 _raftName = None
 
 _slotName = None
 
 _detectorName = None
 
 _detectorSerial = None
 
 _detectorId = None
 
 _filter = None
 
str _calibId = None
 
 _seqfile = None
 
 _seqname = None
 
 _seqcksum = None
 
 _metadata = PropertyList()
 
 _requiredAttributes
 

Static Protected Attributes

str _OBSTYPE = "generic"
 
str _SCHEMA = "NO SCHEMA"
 
int _VERSION = 0
 

Detailed Description

A simple class to hold the output data from the PTC task.

The dataset is made up of a dictionary for each item, keyed by the
amplifiers' names, which much be supplied at construction time.
New items cannot be added to the class to save accidentally saving to the
wrong property, and the class can be frozen if desired.
inputExpIdPairs records the exposures used to produce the data.
When fitPtc() or fitCovariancesAstier() is run, a mask is built up, which
is by definition always the same length as inputExpIdPairs, rawExpTimes,
rawMeans and rawVars, and is a list of bools, which are incrementally set
to False as points are discarded from the fits.
PTC fit parameters for polynomials are stored in a list in ascending order
of polynomial term, i.e. par[0]*x^0 + par[1]*x + par[2]*x^2 etc
with the length of the list corresponding to the order of the polynomial
plus one.

Parameters
----------
ampNames : `list`
    List with the names of the amplifiers of the detector at hand.
ptcFitType : `str`, optional
    Type of model fitted to the PTC: "POLYNOMIAL", "EXPAPPROXIMATION",
    or "FULLCOVARIANCE".
covMatrixSide : `int`, optional
    Maximum lag of measured covariances (size of square covariance
    matrices).
covMatrixSideFullCovFit : `int`, optional
    Maximum covariances lag for FULLCOVARIANCE fit. It should be less or
    equal than covMatrixSide.
kwargs : `dict`, optional
    Other keyword arguments to pass to the parent init.

Notes
-----
The stored attributes are:

badAmps : `list` [`str`]
    List with bad amplifiers names.
inputExpIdPairs : `dict`, [`str`, `list`]
    Dictionary keyed by amp names containing the input exposures IDs.
inputExpPairMjdStartList : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the start mjd from
    the first exposure in each flat pair.
expIdMask : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the mask produced after
    outlier rejection. The mask produced by the "FULLCOVARIANCE"
    option may differ from the one produced in the other two PTC
    fit types.
rawExpTimes : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the unmasked exposure times.
rawMeans : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the unmasked average of the
    means of the exposures in each flat pair (units: adu).
rawVars : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the variance of the
    difference image of the exposures in each flat pair (units: adu^2).
rowMeanVariance : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the variance of the
    means of the rows of the difference image of the exposures
    in each flat pair (units: adu^2).
histVars : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the variance of the
    difference image of the exposures in each flat pair estimated
    by fitting a Gaussian model.
histChi2Dofs : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the chi-squared per degree
    of freedom fitting the difference image to a Gaussian model.
kspValues : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the KS test p-value from
    fitting the difference image to a Gaussian model.
gain : `dict`, [`str`, `float`]
    Dictionary keyed by amp names containing the fitted gains. May be
    adjusted by amp-offset gain ratios if configured in PTC solver.
gainUnadjusted : `dict`, [`str`, `float`]
    Dictionary keyed by amp names containing unadjusted (raw) fit gain
    values. May be the same as gain values if amp-offset adjustment
    is not turned on.
gainErr : `dict`, [`str`, `float`]
    Dictionary keyed by amp names containing the errors on the
    fitted gains.
gainList : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the gain estimated from
    each flat pair.
overscanMedianLevelList : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the median overscan
    level from each input flat pair (units: adu).
overscanMedian : `dict `, [`str`, `float`]
    Dictionary keyed by amp names containing the median of
    overscanMedianLevelList[expIdMask] (units: adu).
overscanMedianSigma : `dict `, [`str`, `float`]
    Dictionary keyed by amp names containing the median absolute
    deviation of overscanMedianLevelList[expIdMask] (units: adu).
noiseList : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the mean overscan
    standard deviation from each flat pair (units: adu).
noise : `dict`, [`str`, `float`]
    Dictionary keyed by amp names containing the fitted noise
    (units: electron).
noiseErr : `dict`, [`str`, `float`]
    Dictionary keyed by amp names containing the errors on the fitted
    noise (units: electron).
ampOffsets : `dict`, [`str`, `float`]
    Dictionary keyed by amp names containing amp-to-amp offsets
    (units: adu).
ptcFitPars : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the fitted parameters of the
    PTC model for ptcFitType in ["POLYNOMIAL", "EXPAPPROXIMATION"].
ptcFitParsError : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the errors on the fitted
    parameters of the PTC model for ptcFitType in
    ["POLYNOMIAL", "EXPAPPROXIMATION"].
ptcFitChiSq : `dict`, [`str`, `float`]
    Dictionary keyed by amp names containing the reduced chi squared
    of the fit for ptcFitType in ["POLYNOMIAL", "EXPAPPROXIMATION"].
ptcTurnoff : `dict` [`str, `float`]
    Flux value (in adu) where the variance of the PTC curve starts
    decreasing consistently.
ptcTurnoffSamplingError : `dict` [`str`, `float`]
    ``Sampling`` error on the ptcTurnoff, based on the flux sampling
    of the input PTC (units: adu).
covariances : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing a list of measured
    covariances per mean flux (units: adu^2).
covariancesModel : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containinging covariances model
    (Eq. 20 of Astier+19) per mean flux (units: adu^2).
covariancesSqrtWeights : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containinging sqrt. of covariances
    weights (units: 1/adu).
aMatrix : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the "a" parameters from
    the model in Eq. 20 of Astier+19 (units: 1/electron).
bMatrix : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the "b" parameters from
    the model in Eq. 20 of Astier+19 (units: 1/electron).
noiseMatrix : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the "noise" parameters from
    the model in Eq. 20 of Astier+19 (units: electron^2).
covariancesModelNoB : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing covariances model
    (with 'b'=0 in Eq. 20 of Astier+19) per mean flux (units:
    adu^2). Will be removed after v29.
aMatrixNoB : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the "a" parameters from the
    model in Eq. 20 of Astier+19 (and 'b' = 0) (units: 1/electron).
    Will be removed after v29.
noiseMatrixNoB : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the "noise" parameters from
    the model in Eq. 20 of Astier+19, with 'b' = 0 (units: electron^2).
    Will be removed after v29.
finalVars : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the masked variance of the
    difference image of each flat
    pair. If needed, each array will be right-padded with
    np.nan to match the length of rawExpTimes.
finalModelVars : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the masked modeled
    variance of the difference image of each flat pair. If needed, each
    array will be right-padded with np.nan to match the length of
    rawExpTimes.
finalMeans : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the masked average of the
    means of the exposures in each flat pair. If needed, each array
    will be right-padded with np.nan to match the length of
    rawExpTimes.
photoCharges : `dict`, [`str`, `np.ndarray`]
    Dictionary keyed by amp names containing the integrated photocharge
    for linearity calibration.
auxValues : `dict`, [`str`, `np.ndarray`]
    Dictionary of per-detector auxiliary header values that can be used
    for PTC, linearity computation.

Version 1.1 adds the `ptcTurnoff` attribute.
Version 1.2 adds the `histVars`, `histChi2Dofs`, and `kspValues`
    attributes.
Version 1.3 adds the `noiseMatrix` and `noiseMatrixNoB` attributes.
Version 1.4 adds the `auxValues` attribute.
Version 1.5 adds the `covMatrixSideFullCovFit` attribute.
Version 1.6 adds the `rowMeanVariance` attribute.
Version 1.7 adds the `noiseList` attribute.
Version 1.8 adds the `ptcTurnoffSamplingError` attribute.
Version 1.9 standardizes PTC noise units to electron.
Version 2.0 adds the `ampOffsets`, `gainUnadjusted`, and
    `gainList` attributes.
Version 2.1 deprecates the `covariancesModelNoB`, `aMatrixNoB`, and
    `noiseMatrixNoB` attributes.
Version 2.2 adds the `overscanMedianLevelList` and
    `inputExpPairMjdStartList` attributes.
Version 2.3 adds the `overscanMedian` and
    `overscanMedianSigma` attrbutes.

Definition at line 65 of file ptcDataset.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.__init__ ( self,
ampNames = [],
ptcFitType = None,
covMatrixSide = 1,
covMatrixSideFullCovFit = None,
** kwargs )

Definition at line 276 of file ptcDataset.py.

277 covMatrixSideFullCovFit=None, **kwargs):
278 self.ptcFitType = ptcFitType
279 self.ampNames = ampNames
280 self.covMatrixSide = covMatrixSide
281 if covMatrixSideFullCovFit is None:
282 self.covMatrixSideFullCovFit = covMatrixSide
283 else:
284 self.covMatrixSideFullCovFit = covMatrixSideFullCovFit
285
286 self.badAmps = []
287
288 self.inputExpIdPairs = {ampName: [] for ampName in ampNames}
289 self.inputExpPairMjdStartList = {ampName: np.array([]) for ampName in ampNames}
290 self.expIdMask = {ampName: np.array([], dtype=bool) for ampName in ampNames}
291 self.rawExpTimes = {ampName: np.array([]) for ampName in ampNames}
292 self.rawMeans = {ampName: np.array([]) for ampName in ampNames}
293 self.rawVars = {ampName: np.array([]) for ampName in ampNames}
294 self.rowMeanVariance = {ampName: np.array([]) for ampName in ampNames}
295 self.photoCharges = {ampName: np.array([]) for ampName in ampNames}
296 self.ampOffsets = {ampName: np.array([]) for ampName in ampNames}
297
298 self.gain = {ampName: np.nan for ampName in ampNames}
299 self.gainUnadjusted = {ampName: np.nan for ampName in ampNames}
300 self.gainErr = {ampName: np.nan for ampName in ampNames}
301 self.gainList = {ampName: np.array([]) for ampName in ampNames}
302 self.overscanMedianLevelList = {ampName: np.array([]) for ampName in ampNames}
303 self.overscanMedian = {ampName: np.nan for ampName in ampNames}
304 self.overscanMedianSigma = {ampName: np.nan for ampName in ampNames}
305 self.noiseList = {ampName: np.array([]) for ampName in ampNames}
306 self.noise = {ampName: np.nan for ampName in ampNames}
307 self.noiseErr = {ampName: np.nan for ampName in ampNames}
308
309 self.histVars = {ampName: np.array([]) for ampName in ampNames}
310 self.histChi2Dofs = {ampName: np.array([]) for ampName in ampNames}
311 self.kspValues = {ampName: np.array([]) for ampName in ampNames}
312
313 self.ptcFitPars = {ampName: np.array([]) for ampName in ampNames}
314 self.ptcFitParsError = {ampName: np.array([]) for ampName in ampNames}
315 self.ptcFitChiSq = {ampName: np.nan for ampName in ampNames}
316 self.ptcTurnoff = {ampName: np.nan for ampName in ampNames}
317 self.ptcTurnoffSamplingError = {ampName: np.nan for ampName in ampNames}
318
319 self.covariances = {ampName: np.array([]) for ampName in ampNames}
320 self.covariancesModel = {ampName: np.array([]) for ampName in ampNames}
321 self.covariancesSqrtWeights = {ampName: np.array([]) for ampName in ampNames}
322 self.aMatrix = {ampName: np.array([]) for ampName in ampNames}
323 self.bMatrix = {ampName: np.array([]) for ampName in ampNames}
324 self.noiseMatrix = {ampName: np.array([]) for ampName in ampNames}
325
326 self.finalVars = {ampName: np.array([]) for ampName in ampNames}
327 self.finalModelVars = {ampName: np.array([]) for ampName in ampNames}
328 self.finalMeans = {ampName: np.array([]) for ampName in ampNames}
329
330 # Try this as a dict of arrays.
331 self.auxValues = {}
332
333 super().__init__(**kwargs)
334 self.requiredAttributes.update(['badAmps', 'inputExpIdPairs', 'inputExpPairMjdStartList',
335 'expIdMask', 'rawExpTimes', 'rawMeans', 'rawVars',
336 'rowMeanVariance', 'gain', 'gainErr', 'gainList', 'noise',
337 'noiseErr', 'noiseList', 'overscanMedianLevelList',
338 'overscanMedian', 'overscanMedianSigma', 'ptcFitPars',
339 'ptcFitParsError', 'ptcFitChiSq', 'ptcTurnoff', 'covariances',
340 'covariancesModel', 'covariancesSqrtWeights', 'aMatrix',
341 'bMatrix', 'noiseMatrix', 'finalVars', 'finalModelVars',
342 'finalMeans', 'photoCharges', 'histVars', 'histChi2Dofs',
343 'kspValues', 'auxValues', 'ptcTurnoffSamplingError',
344 'ampOffsets', 'gainUnadjusted'])
345
346 self.updateMetadata(setCalibInfo=True, setCalibId=True, **kwargs)
347 self._validateCovarianceMatrizSizes()
348

Member Function Documentation

◆ __eq__()

lsst.ip.isr.calibType.IsrCalib.__eq__ ( self,
other )
inherited
Calibration equivalence.

Running ``calib.log.setLevel(0)`` enables debug statements to
identify problematic fields.

Definition at line 103 of file calibType.py.

103 def __eq__(self, other):
104 """Calibration equivalence.
105
106 Running ``calib.log.setLevel(0)`` enables debug statements to
107 identify problematic fields.
108 """
109 if not isinstance(other, self.__class__):
110 self.log.debug("Incorrect class type: %s %s", self.__class__, other.__class__)
111 return False
112
113 for attr in self._requiredAttributes:
114 attrSelf = getattr(self, attr)
115 attrOther = getattr(other, attr)
116
117 if isinstance(attrSelf, dict):
118 # Dictionary of arrays.
119 if attrSelf.keys() != attrOther.keys():
120 self.log.debug("Dict Key Failure: %s %s %s", attr, attrSelf.keys(), attrOther.keys())
121 return False
122 for key in attrSelf:
123 try:
124 if not np.allclose(attrSelf[key], attrOther[key], equal_nan=True):
125 self.log.debug("Array Failure: %s %s %s", key, attrSelf[key], attrOther[key])
126 return False
127 except TypeError:
128 # If it is not something numpy can handle
129 # (it's not a number or array of numbers),
130 # then it needs to have its own equivalence
131 # operator.
132 if np.all(attrSelf[key] != attrOther[key]):
133 return False
134 elif isinstance(attrSelf, np.ndarray):
135 # Bare array.
136 if isinstance(attrSelf[0], (str, np.str_, np.bytes_)):
137 if not np.all(attrSelf == attrOther):
138 self.log.debug("Array Failure: %s %s %s", attr, attrSelf, attrOther)
139 return False
140 else:
141 if not np.allclose(attrSelf, attrOther, equal_nan=True):
142 self.log.debug("Array Failure: %s %s %s", attr, attrSelf, attrOther)
143 return False
144 elif type(attrSelf) is not type(attrOther):
145 if set([attrSelf, attrOther]) == set([None, ""]):
146 # Fits converts None to "", but None is not "".
147 continue
148 self.log.debug("Type Failure: %s %s %s %s %s", attr, type(attrSelf), type(attrOther),
149 attrSelf, attrOther)
150 return False
151 else:
152 if attrSelf != attrOther:
153 self.log.debug("Value Failure: %s %s %s", attr, attrSelf, attrOther)
154 return False
155
156 return True
157

◆ __str__()

lsst.ip.isr.calibType.IsrCalib.__str__ ( self)
inherited

Definition at line 100 of file calibType.py.

100 def __str__(self):
101 return f"{self.__class__.__name__}(obstype={self._OBSTYPE}, detector={self._detectorName}, )"
102

◆ _validateCovarianceMatrizSizes()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset._validateCovarianceMatrizSizes ( self)
protected
Ensure  covMatrixSideFullCovFit <= covMatrixSide.

Definition at line 1349 of file ptcDataset.py.

1349 def _validateCovarianceMatrizSizes(self):
1350 """Ensure covMatrixSideFullCovFit <= covMatrixSide."""
1351 if self.covMatrixSideFullCovFit > self.covMatrixSide:
1352 self.log.warning("covMatrixSideFullCovFit > covMatrixSide "
1353 f"({self.covMatrixSideFullCovFit} > {self.covMatrixSide})."
1354 "Setting the former to the latter.")
1355 self.covMatrixSideFullCovFit = self.covMatrixSide

◆ appendPartialPtc()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.appendPartialPtc ( self,
partialPtc )
Append a partial PTC dataset to this dataset.

Parameters
----------
partialPtc : `lsst.ip.isr.PhotonTransferCurveDataset`
    Partial PTC to append. Should only have one element.

Definition at line 990 of file ptcDataset.py.

990 def appendPartialPtc(self, partialPtc):
991 """Append a partial PTC dataset to this dataset.
992
993 Parameters
994 ----------
995 partialPtc : `lsst.ip.isr.PhotonTransferCurveDataset`
996 Partial PTC to append. Should only have one element.
997 """
998 if self.ampNames != partialPtc.ampNames:
999 raise ValueError("partialPtc has mis-matched amps.")
1000 if len(partialPtc.rawMeans[self.ampNames[0]]) != 1 or partialPtc.ptcFitType != "PARTIAL":
1001 raise ValueError("partialPtc does not appear to be the correct format.")
1002
1003 # Record the initial length of the PTC, for checking auxValues.
1004 initialLength = len(self.expIdMask[self.ampNames[0]])
1005
1006 for key, value in partialPtc.auxValues.items():
1007 if key in self.auxValues:
1008 self.auxValues[key] = np.append(self.auxValues[key], value)
1009 elif initialLength == 0:
1010 # This is the first partial, so we can set the dict key.
1011 self.auxValues[key] = value
1012 else:
1013 raise ValueError(f"partialPtc has mismatched auxValue key {key}.")
1014
1015 for ampName in self.ampNames:
1016 # The partial dataset consists of lists of values for each
1017 # quantity. In the case of the input exposure pairs and the
1018 # input exposure MJDs, this is a list of tuples. In all cases
1019 # we only want the first (and only) element of the list.
1020 self.inputExpIdPairs[ampName].append(partialPtc.inputExpIdPairs[ampName][0])
1021 self.inputExpPairMjdStartList[ampName] = np.append(
1022 self.inputExpPairMjdStartList[ampName],
1023 partialPtc.inputExpPairMjdStartList[ampName][0],
1024 )
1025 self.expIdMask[ampName] = np.append(self.expIdMask[ampName],
1026 partialPtc.expIdMask[ampName][0])
1027 self.rawExpTimes[ampName] = np.append(self.rawExpTimes[ampName],
1028 partialPtc.rawExpTimes[ampName][0])
1029 self.rawMeans[ampName] = np.append(self.rawMeans[ampName],
1030 partialPtc.rawMeans[ampName][0])
1031 self.rawVars[ampName] = np.append(self.rawVars[ampName],
1032 partialPtc.rawVars[ampName][0])
1033 self.rowMeanVariance[ampName] = np.append(self.rowMeanVariance[ampName],
1034 partialPtc.rowMeanVariance[ampName][0])
1035 self.photoCharges[ampName] = np.append(self.photoCharges[ampName],
1036 partialPtc.photoCharges[ampName][0])
1037 self.ampOffsets[ampName] = np.append(self.ampOffsets[ampName],
1038 partialPtc.ampOffsets[ampName][0])
1039 self.histVars[ampName] = np.append(self.histVars[ampName],
1040 partialPtc.histVars[ampName][0])
1041 self.histChi2Dofs[ampName] = np.append(self.histChi2Dofs[ampName],
1042 partialPtc.histChi2Dofs[ampName][0])
1043 self.kspValues[ampName] = np.append(self.kspValues[ampName],
1044 partialPtc.kspValues[ampName][0])
1045 self.gainList[ampName] = np.append(self.gainList[ampName],
1046 partialPtc.gain[ampName])
1047 self.overscanMedianLevelList[ampName] = np.append(
1048 self.overscanMedianLevelList[ampName],
1049 partialPtc.overscanMedianLevelList[ampName][0],
1050 )
1051 self.noiseList[ampName] = np.append(self.noiseList[ampName],
1052 partialPtc.noise[ampName])
1053 self.finalVars[ampName] = np.append(self.finalVars[ampName],
1054 partialPtc.finalVars[ampName][0])
1055 self.finalModelVars[ampName] = np.append(self.finalModelVars[ampName],
1056 partialPtc.finalModelVars[ampName][0])
1057 self.finalMeans[ampName] = np.append(self.finalMeans[ampName],
1058 partialPtc.finalMeans[ampName][0])
1059
1060 self.covariances[ampName] = np.append(
1061 self.covariances[ampName].ravel(),
1062 partialPtc.covariances[ampName].ravel()
1063 ).reshape(
1064 (
1065 len(self.rawExpTimes[ampName]),
1066 self.covMatrixSide,
1067 self.covMatrixSide,
1068 )
1069 )
1070 self.covariancesSqrtWeights[ampName] = np.append(
1071 self.covariancesSqrtWeights[ampName].ravel(),
1072 partialPtc.covariancesSqrtWeights[ampName].ravel()
1073 ).reshape(
1074 (
1075 len(self.rawExpTimes[ampName]),
1076 self.covMatrixSide,
1077 self.covMatrixSide,
1078 )
1079 )
1080 self.covariancesModel[ampName] = np.append(
1081 self.covariancesModel[ampName].ravel(),
1082 partialPtc.covariancesModel[ampName].ravel()
1083 ).reshape(
1084 (
1085 len(self.rawExpTimes[ampName]),
1086 self.covMatrixSide,
1087 self.covMatrixSide,
1088 )
1089 )
1090

◆ apply()

lsst.ip.isr.calibType.IsrCalib.apply ( self,
target )
inherited
Method to apply the calibration to the target object.

Parameters
----------
target : `object`
    Thing to validate against.

Returns
-------
valid : `bool`
    Returns true if the calibration was applied correctly.

Raises
------
NotImplementedError
    Raised if not implemented.

Definition at line 685 of file calibType.py.

685 def apply(self, target):
686 """Method to apply the calibration to the target object.
687
688 Parameters
689 ----------
690 target : `object`
691 Thing to validate against.
692
693 Returns
694 -------
695 valid : `bool`
696 Returns true if the calibration was applied correctly.
697
698 Raises
699 ------
700 NotImplementedError
701 Raised if not implemented.
702 """
703 raise NotImplementedError("Must be implemented by subclass.")
704
705

◆ calibInfoFromDict()

lsst.ip.isr.calibType.IsrCalib.calibInfoFromDict ( self,
dictionary )
inherited
Handle common keywords.

This isn't an ideal solution, but until all calibrations
expect to find everything in the metadata, they still need to
search through dictionaries.

Parameters
----------
dictionary : `dict` or `lsst.daf.base.PropertyList`
    Source for the common keywords.

Raises
------
RuntimeError
    Raised if the dictionary does not match the expected OBSTYPE.

Definition at line 322 of file calibType.py.

322 def calibInfoFromDict(self, dictionary):
323 """Handle common keywords.
324
325 This isn't an ideal solution, but until all calibrations
326 expect to find everything in the metadata, they still need to
327 search through dictionaries.
328
329 Parameters
330 ----------
331 dictionary : `dict` or `lsst.daf.base.PropertyList`
332 Source for the common keywords.
333
334 Raises
335 ------
336 RuntimeError
337 Raised if the dictionary does not match the expected OBSTYPE.
338 """
339
340 def search(haystack, needles):
341 """Search dictionary 'haystack' for an entry in 'needles'
342 """
343 test = [haystack.get(x) for x in needles]
344 test = set([x for x in test if x is not None])
345 if len(test) == 0:
346 if "metadata" in haystack:
347 return search(haystack["metadata"], needles)
348 else:
349 return None
350 elif len(test) == 1:
351 value = list(test)[0]
352 if value == "":
353 return None
354 else:
355 return value
356 else:
357 raise ValueError(f"Too many values found: {len(test)} {test} {needles}")
358
359 if "metadata" in dictionary:
360 metadata = dictionary["metadata"]
361
362 if self._OBSTYPE != metadata["OBSTYPE"]:
363 raise RuntimeError(f"Incorrect calibration supplied. Expected {self._OBSTYPE}, "
364 f"found {metadata['OBSTYPE']}")
365
366 if (value := search(dictionary, ["INSTRUME", "instrument"])) is not None:
367 self._instrument = value
368 if (value := search(dictionary, ["RAFTNAME"])) is not None:
369 self._slotName = value
370 if (value := search(dictionary, ["DETECTOR", "detectorId"])) is not None:
371 self._detectorId = value
372 if (value := search(dictionary, ["DET_NAME", "DETECTOR_NAME", "detectorName"])) is not None:
373 self._detectorName = value
374 if (value := search(dictionary, ["DET_SER", "DETECTOR_SERIAL", "detectorSerial"])) is not None:
375 self._detectorSerial = value
376 if (value := search(dictionary, ["FILTER", "filterName"])) is not None:
377 self._filter = value
378 if (value := search(dictionary, ["CALIB_ID"])) is not None:
379 self._calibId = value
380 if (value := search(dictionary, ["SEQFILE"])) is not None:
381 self._seqfile = value
382 if (value := search(dictionary, ["SEQNAME"])) is not None:
383 self._seqname = value
384 if (value := search(dictionary, ["SEQCKSUM"])) is not None:
385 self._seqcksum = value
386

◆ determineCalibClass()

lsst.ip.isr.calibType.IsrCalib.determineCalibClass ( cls,
metadata,
message )
inherited
Attempt to find calibration class in metadata.

Parameters
----------
metadata : `dict` or `lsst.daf.base.PropertyList`
    Metadata possibly containing a calibration class entry.
message : `str`
    Message to include in any errors.

Returns
-------
calibClass : `object`
    The class to use to read the file contents.  Should be an
    `lsst.ip.isr.IsrCalib` subclass.

Raises
------
ValueError
    Raised if the resulting calibClass is the base
    `lsst.ip.isr.IsrClass` (which does not implement the
    content methods).

Definition at line 388 of file calibType.py.

388 def determineCalibClass(cls, metadata, message):
389 """Attempt to find calibration class in metadata.
390
391 Parameters
392 ----------
393 metadata : `dict` or `lsst.daf.base.PropertyList`
394 Metadata possibly containing a calibration class entry.
395 message : `str`
396 Message to include in any errors.
397
398 Returns
399 -------
400 calibClass : `object`
401 The class to use to read the file contents. Should be an
402 `lsst.ip.isr.IsrCalib` subclass.
403
404 Raises
405 ------
406 ValueError
407 Raised if the resulting calibClass is the base
408 `lsst.ip.isr.IsrClass` (which does not implement the
409 content methods).
410 """
411 calibClassName = metadata.get("CALIBCLS")
412 calibClass = doImport(calibClassName) if calibClassName is not None else cls
413 if calibClass is IsrCalib:
414 raise ValueError(f"Cannot use base class to read calibration data: {message}")
415 return calibClass
416

◆ evalPtcModel()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.evalPtcModel ( self,
mu )
Computes the covariance model at specific signal levels.

Parameters
----------
mu : `numpy.array`, (N,)
    List of mean signals in ADU.

Raises
------
RuntimeError
    Raised if ptcFitType is invalid.

Returns
-------
covModel : `numpy.array`, (N, M, M)
    Covariances model at mu (in ADU^2).

Notes
-----
Computes the covModel for all mu, and it returns
cov[N, M, M], where the variance model is cov[:,0,0].
Both mu and cov are in ADUs and ADUs squared. This
routine evaulates the n-degree polynomial model (defined
by polynomialFitDegree) if self.ptcFitType == POLYNOMIAL,
the approximation in Eq. 16 of Astier+19 (1905.08677)
if self.ptcFitType == EXPAPPROXIMATION, and Eq. 20 of
Astier+19 if self.ptcFitType == FULLCOVARIANCE.

The POLYNOMIAL model and the EXPAPPROXIMATION model
(Eq. 16 of Astier+19) are only approximations for the
variance (cov[0,0]), so the function returns covModel
of shape (N,), representing an array of [C_{00}]
if self.ptcFitType == EXPAPPROXIMATION or
self.ptcFitType == POLYNOMAIL.

Definition at line 1243 of file ptcDataset.py.

1243 def evalPtcModel(self, mu):
1244 """Computes the covariance model at specific signal levels.
1245
1246 Parameters
1247 ----------
1248 mu : `numpy.array`, (N,)
1249 List of mean signals in ADU.
1250
1251 Raises
1252 ------
1253 RuntimeError
1254 Raised if ptcFitType is invalid.
1255
1256 Returns
1257 -------
1258 covModel : `numpy.array`, (N, M, M)
1259 Covariances model at mu (in ADU^2).
1260
1261 Notes
1262 -----
1263 Computes the covModel for all mu, and it returns
1264 cov[N, M, M], where the variance model is cov[:,0,0].
1265 Both mu and cov are in ADUs and ADUs squared. This
1266 routine evaulates the n-degree polynomial model (defined
1267 by polynomialFitDegree) if self.ptcFitType == POLYNOMIAL,
1268 the approximation in Eq. 16 of Astier+19 (1905.08677)
1269 if self.ptcFitType == EXPAPPROXIMATION, and Eq. 20 of
1270 Astier+19 if self.ptcFitType == FULLCOVARIANCE.
1271
1272 The POLYNOMIAL model and the EXPAPPROXIMATION model
1273 (Eq. 16 of Astier+19) are only approximations for the
1274 variance (cov[0,0]), so the function returns covModel
1275 of shape (N,), representing an array of [C_{00}]
1276 if self.ptcFitType == EXPAPPROXIMATION or
1277 self.ptcFitType == POLYNOMAIL.
1278 """
1279
1280 ampNames = self.ampNames
1281 covModel = {ampName: np.array([]) for ampName in ampNames}
1282
1283 if self.ptcFitType == "POLYNOMIAL":
1284 pars = self.ptcFitPars
1285
1286 for ampName in ampNames:
1287 c00 = poly.polyval(mu, [*pars[ampName]])
1288 covModel[ampName] = c00
1289
1290 elif self.ptcFitType == "EXPAPPROXIMATION":
1291 pars = self.ptcFitPars
1292
1293 for ampName in ampNames:
1294 a00, gain, noise = pars[ampName]
1295 f1 = 0.5/(a00*gain*gain)*(np.exp(2*a00*mu*gain)-1)
1296 f2 = noise/(gain*gain)
1297 c00 = f1 + f2
1298 covModel[ampName] = c00
1299
1300 elif self.ptcFitType in ["FULLCOVARIANCE", "FULLCOVARIANCE_NO_B"]:
1301 for ampName in ampNames:
1302 noiseMatrix = self.noiseMatrix[ampName]
1303 gain = self.gain[ampName]
1304 aMatrix = self.aMatrix[ampName]
1305 bMatrix = self.bMatrix[ampName]
1306 cMatrix = aMatrix*bMatrix
1307
1308 matrixSideFit = self.covMatrixSideFullCovFit
1309 sa = (matrixSideFit, matrixSideFit)
1310
1311 # pad a with zeros and symmetrize
1312 aEnlarged = np.zeros((int(sa[0]*1.5)+1, int(sa[1]*1.5)+1))
1313 aEnlarged[0:sa[0], 0:sa[1]] = aMatrix
1314 aSym = symmetrize(aEnlarged)
1315
1316 # pad c with zeros and symmetrize
1317 cEnlarged = np.zeros((int(sa[0]*1.5)+1, int(sa[1]*1.5)+1))
1318 cEnlarged[0:sa[0], 0:sa[1]] = cMatrix
1319
1320 cSym = symmetrize(cEnlarged)
1321 a2 = fftconvolve(aSym, aSym, mode='same')
1322 a3 = fftconvolve(a2, aSym, mode='same')
1323 ac = fftconvolve(aSym, cSym, mode='same')
1324 (xc, yc) = np.unravel_index(np.abs(aSym).argmax(), a2.shape)
1325
1326 a1 = aMatrix[np.newaxis, :, :]
1327 a2 = a2[np.newaxis, xc:xc + matrixSideFit, yc:yc + matrixSideFit]
1328 a3 = a3[np.newaxis, xc:xc + matrixSideFit, yc:yc + matrixSideFit]
1329 ac = ac[np.newaxis, xc:xc + matrixSideFit, yc:yc + matrixSideFit]
1330 c1 = cMatrix[np.newaxis, ::]
1331
1332 # assumes that mu is 1d
1333 bigMu = mu[:, np.newaxis, np.newaxis]*gain
1334 # c(=a*b in Astier+19) also has a contribution to the last
1335 # term, that is absent for now.
1336
1337 covModel[ampName] = (bigMu/(gain*gain)*(a1*bigMu+2./3.*(bigMu*bigMu)*(a2 + c1)
1338 + (1./3.*a3 + 5./6.*ac)*(bigMu*bigMu*bigMu))
1339 + noiseMatrix[np.newaxis, :, :]/gain**2)
1340
1341 # add the Poisson term, and the read out noise (variance)
1342 covModel[ampName][:, 0, 0] += mu/gain
1343 else:
1344 raise RuntimeError("Cannot compute PTC model for "
1345 "ptcFitType %s." % self.ptcFitType)
1346
1347 return covModel
1348

◆ fromDetector()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.fromDetector ( self,
detector )
Read metadata parameters from a detector.

Parameters
----------
detector : `lsst.afw.cameraGeom.detector`
    Input detector with parameters to use.

Returns
-------
calib : `lsst.ip.isr.PhotonTransferCurveDataset`
    The calibration constructed from the detector.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 974 of file ptcDataset.py.

974 def fromDetector(self, detector):
975 """Read metadata parameters from a detector.
976
977 Parameters
978 ----------
979 detector : `lsst.afw.cameraGeom.detector`
980 Input detector with parameters to use.
981
982 Returns
983 -------
984 calib : `lsst.ip.isr.PhotonTransferCurveDataset`
985 The calibration constructed from the detector.
986 """
987
988 pass
989

◆ fromDict()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.fromDict ( cls,
dictionary )
Construct a calibration from a dictionary of properties.
Must be implemented by the specific calibration subclasses.

Parameters
----------
dictionary : `dict`
    Dictionary of properties.

Returns
-------
calib : `lsst.ip.isr.PhotonTransferCurveDataset`
    Constructed calibration.

Raises
------
RuntimeError
    Raised if the supplied dictionary is for a different
    calibration.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 494 of file ptcDataset.py.

494 def fromDict(cls, dictionary):
495 """Construct a calibration from a dictionary of properties.
496 Must be implemented by the specific calibration subclasses.
497
498 Parameters
499 ----------
500 dictionary : `dict`
501 Dictionary of properties.
502
503 Returns
504 -------
505 calib : `lsst.ip.isr.PhotonTransferCurveDataset`
506 Constructed calibration.
507
508 Raises
509 ------
510 RuntimeError
511 Raised if the supplied dictionary is for a different
512 calibration.
513 """
514 calib = cls()
515 if calib._OBSTYPE != dictionary['metadata']['OBSTYPE']:
516 raise RuntimeError(f"Incorrect Photon Transfer Curve dataset supplied. "
517 f"Expected {calib._OBSTYPE}, found {dictionary['metadata']['OBSTYPE']}")
518 calib.setMetadata(dictionary['metadata'])
519 calib.ptcFitType = dictionary['ptcFitType']
520 calib.covMatrixSide = dictionary['covMatrixSide']
521 calib.covMatrixSideFullCovFit = dictionary['covMatrixSideFullCovFit']
522 calib.badAmps = np.array(dictionary['badAmps'], 'str').tolist()
523 calib.ampNames = []
524
525 # The cov matrices are square
526 covMatrixSide = calib.covMatrixSide
527 covMatrixSideFullCovFit = calib.covMatrixSideFullCovFit
528 # Number of final signal levels
529 covDimensionsProduct = len(np.array(list(dictionary['covariances'].values())[0]).ravel())
530 nSignalPoints = int(covDimensionsProduct/(covMatrixSide*covMatrixSide))
531
532 for ampName in dictionary['ampNames']:
533 calib.ampNames.append(ampName)
534 calib.inputExpIdPairs[ampName] = dictionary['inputExpIdPairs'][ampName]
535 calib.inputExpPairMjdStartList[ampName] = np.array(
536 dictionary['inputExpPairMjdStartList'][ampName],
537 )
538 calib.expIdMask[ampName] = np.array(dictionary['expIdMask'][ampName])
539 calib.rawExpTimes[ampName] = np.array(dictionary['rawExpTimes'][ampName], dtype=np.float64)
540 calib.rawMeans[ampName] = np.array(dictionary['rawMeans'][ampName], dtype=np.float64)
541 calib.rawVars[ampName] = np.array(dictionary['rawVars'][ampName], dtype=np.float64)
542 calib.rowMeanVariance[ampName] = np.array(dictionary['rowMeanVariance'][ampName],
543 dtype=np.float64)
544 calib.gain[ampName] = float(dictionary['gain'][ampName])
545 calib.gainErr[ampName] = float(dictionary['gainErr'][ampName])
546 calib.gainUnadjusted[ampName] = float(dictionary['gainUnadjusted'][ampName])
547 calib.gainList[ampName] = np.array(dictionary['gainList'][ampName], dtype=np.float64)
548 calib.noiseList[ampName] = np.array(dictionary['noiseList'][ampName], dtype=np.float64)
549 calib.overscanMedianLevelList[ampName] = np.array(
550 dictionary['overscanMedianLevelList'][ampName],
551 dtype=np.float64,
552 )
553 calib.overscanMedian[ampName] = float(dictionary['overscanMedian'][ampName])
554 calib.overscanMedianSigma[ampName] = float(dictionary['overscanMedianSigma'][ampName])
555 calib.noise[ampName] = float(dictionary['noise'][ampName])
556 calib.noiseErr[ampName] = float(dictionary['noiseErr'][ampName])
557 calib.histVars[ampName] = np.array(dictionary['histVars'][ampName], dtype=np.float64)
558 calib.histChi2Dofs[ampName] = np.array(dictionary['histChi2Dofs'][ampName], dtype=np.float64)
559 calib.kspValues[ampName] = np.array(dictionary['kspValues'][ampName], dtype=np.float64)
560 calib.ptcFitPars[ampName] = np.array(dictionary['ptcFitPars'][ampName], dtype=np.float64)
561 calib.ptcFitParsError[ampName] = np.array(dictionary['ptcFitParsError'][ampName],
562 dtype=np.float64)
563 calib.ptcFitChiSq[ampName] = float(dictionary['ptcFitChiSq'][ampName])
564 calib.ptcTurnoff[ampName] = float(dictionary['ptcTurnoff'][ampName])
565 calib.ptcTurnoffSamplingError[ampName] = float(dictionary['ptcTurnoffSamplingError'][ampName])
566 if nSignalPoints > 0:
567 # Regular dataset
568 calib.covariances[ampName] = np.array(dictionary['covariances'][ampName],
569 dtype=np.float64).reshape(
570 (nSignalPoints, covMatrixSide, covMatrixSide))
571 calib.covariancesModel[ampName] = np.array(
572 dictionary['covariancesModel'][ampName],
573 dtype=np.float64).reshape(
574 (nSignalPoints, covMatrixSideFullCovFit, covMatrixSideFullCovFit))
575 calib.covariancesSqrtWeights[ampName] = np.array(
576 dictionary['covariancesSqrtWeights'][ampName],
577 dtype=np.float64).reshape(
578 (nSignalPoints, covMatrixSide, covMatrixSide))
579 calib.aMatrix[ampName] = np.array(dictionary['aMatrix'][ampName],
580 dtype=np.float64).reshape(
581 (covMatrixSideFullCovFit, covMatrixSideFullCovFit))
582 calib.bMatrix[ampName] = np.array(dictionary['bMatrix'][ampName],
583 dtype=np.float64).reshape(
584 (covMatrixSideFullCovFit, covMatrixSideFullCovFit))
585 calib.noiseMatrix[ampName] = np.array(
586 dictionary['noiseMatrix'][ampName],
587 dtype=np.float64).reshape((covMatrixSideFullCovFit, covMatrixSideFullCovFit))
588 else:
589 # Empty dataset
590 calib.covariances[ampName] = np.array([], dtype=np.float64)
591 calib.covariancesModel[ampName] = np.array([], dtype=np.float64)
592 calib.covariancesSqrtWeights[ampName] = np.array([], dtype=np.float64)
593 calib.aMatrix[ampName] = np.array([], dtype=np.float64)
594 calib.bMatrix[ampName] = np.array([], dtype=np.float64)
595 calib.noiseMatrix[ampName] = np.array([], dtype=np.float64)
596
597 calib.finalVars[ampName] = np.array(dictionary['finalVars'][ampName], dtype=np.float64)
598 calib.finalModelVars[ampName] = np.array(dictionary['finalModelVars'][ampName], dtype=np.float64)
599 calib.finalMeans[ampName] = np.array(dictionary['finalMeans'][ampName], dtype=np.float64)
600 calib.photoCharges[ampName] = np.array(dictionary['photoCharges'][ampName], dtype=np.float64)
601 calib.ampOffsets[ampName] = np.array(dictionary['ampOffsets'][ampName], dtype=np.float64)
602
603 for key, value in dictionary['auxValues'].items():
604 if isinstance(value[0], numbers.Integral):
605 calib.auxValues[key] = np.atleast_1d(np.asarray(value).astype(np.int64))
606 elif isinstance(value[0], (str, np.str_, np.bytes_)):
607 calib.auxValues[key] = np.atleast_1d(np.asarray(value))
608 else:
609 calib.auxValues[key] = np.atleast_1d(np.array(value, dtype=np.float64))
610
611 calib.updateMetadata()
612 return calib
613

◆ fromTable()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.fromTable ( cls,
tableList )
Construct calibration from a list of tables.
This method uses the `fromDict` method to create the
calibration, after constructing an appropriate dictionary from
the input tables.

Parameters
----------
tableList : `list` [`lsst.afw.table.Table`]
    List of tables to use to construct the datasetPtc.

Returns
-------
calib : `lsst.ip.isr.PhotonTransferCurveDataset`
    The calibration defined in the tables.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 683 of file ptcDataset.py.

683 def fromTable(cls, tableList):
684 """Construct calibration from a list of tables.
685 This method uses the `fromDict` method to create the
686 calibration, after constructing an appropriate dictionary from
687 the input tables.
688
689 Parameters
690 ----------
691 tableList : `list` [`lsst.afw.table.Table`]
692 List of tables to use to construct the datasetPtc.
693
694 Returns
695 -------
696 calib : `lsst.ip.isr.PhotonTransferCurveDataset`
697 The calibration defined in the tables.
698 """
699 ptcTable = tableList[0]
700
701 metadata = ptcTable.meta
702 inDict = dict()
703 inDict['metadata'] = metadata
704 inDict['ampNames'] = []
705 inDict['ptcFitType'] = []
706 inDict['covMatrixSide'] = []
707 inDict['covMatrixSideFullCovFit'] = []
708 inDict['inputExpIdPairs'] = dict()
709 inDict['inputExpPairMjdStartList'] = dict()
710 inDict['expIdMask'] = dict()
711 inDict['rawExpTimes'] = dict()
712 inDict['rawMeans'] = dict()
713 inDict['rawVars'] = dict()
714 inDict['rowMeanVariance'] = dict()
715 inDict['gain'] = dict()
716 inDict['gainErr'] = dict()
717 inDict['gainUnadjusted'] = dict()
718 inDict['gainList'] = dict()
719 inDict['noiseList'] = dict()
720 inDict['overscanMedianLevelList'] = dict()
721 inDict['overscanMedian'] = dict()
722 inDict['overscanMedianSigma'] = dict()
723 inDict['noise'] = dict()
724 inDict['noiseErr'] = dict()
725 inDict['histVars'] = dict()
726 inDict['histChi2Dofs'] = dict()
727 inDict['kspValues'] = dict()
728 inDict['ptcFitPars'] = dict()
729 inDict['ptcFitParsError'] = dict()
730 inDict['ptcFitChiSq'] = dict()
731 inDict['ptcTurnoff'] = dict()
732 inDict['ptcTurnoffSamplingError'] = dict()
733 inDict['covariances'] = dict()
734 inDict['covariancesModel'] = dict()
735 inDict['covariancesSqrtWeights'] = dict()
736 inDict['aMatrix'] = dict()
737 inDict['bMatrix'] = dict()
738 inDict['noiseMatrix'] = dict()
739 inDict['finalVars'] = dict()
740 inDict['finalModelVars'] = dict()
741 inDict['finalMeans'] = dict()
742 inDict['badAmps'] = []
743 inDict['photoCharges'] = dict()
744 inDict['ampOffsets'] = dict()
745
746 # TODO: DM-47610, remove after v29
747 inDict['noiseMatrixNoB'] = dict()
748 inDict['covariancesModelNoB'] = dict()
749 inDict['aMatrixNoB'] = dict()
750
751 calibVersion = metadata['PTC_VERSION']
752 if calibVersion == 1.0:
753 cls().log.warning(f"Previous version found for PTC dataset: {calibVersion}. "
754 f"Setting 'ptcTurnoff' in all amps to last value in 'finalMeans'.")
755 for record in ptcTable:
756 ampName = record['AMPLIFIER_NAME']
757
758 inDict['ptcFitType'] = record['PTC_FIT_TYPE']
759 inDict['covMatrixSide'] = record['COV_MATRIX_SIDE']
760 inDict['ampNames'].append(ampName)
761 inDict['inputExpIdPairs'][ampName] = record['INPUT_EXP_ID_PAIRS'].tolist()
762 inDict['expIdMask'][ampName] = record['EXP_ID_MASK']
763 inDict['rawExpTimes'][ampName] = record['RAW_EXP_TIMES']
764 inDict['rawMeans'][ampName] = record['RAW_MEANS']
765 inDict['rawVars'][ampName] = record['RAW_VARS']
766 inDict['gain'][ampName] = record['GAIN']
767 inDict['gainErr'][ampName] = record['GAIN_ERR']
768 inDict['noise'][ampName] = record['NOISE']
769 inDict['noiseErr'][ampName] = record['NOISE_ERR']
770 inDict['ptcFitPars'][ampName] = record['PTC_FIT_PARS']
771 inDict['ptcFitParsError'][ampName] = record['PTC_FIT_PARS_ERROR']
772 inDict['ptcFitChiSq'][ampName] = record['PTC_FIT_CHI_SQ']
773 inDict['covariances'][ampName] = record['COVARIANCES']
774 inDict['covariancesModel'][ampName] = record['COVARIANCES_MODEL']
775 inDict['covariancesSqrtWeights'][ampName] = record['COVARIANCES_SQRT_WEIGHTS']
776 inDict['aMatrix'][ampName] = record['A_MATRIX']
777 inDict['bMatrix'][ampName] = record['B_MATRIX']
778 inDict['finalVars'][ampName] = record['FINAL_VARS']
779 inDict['finalModelVars'][ampName] = record['FINAL_MODEL_VARS']
780 inDict['finalMeans'][ampName] = record['FINAL_MEANS']
781 inDict['badAmps'] = record['BAD_AMPS'].tolist()
782 inDict['photoCharges'][ampName] = record['PHOTO_CHARGE']
783 if calibVersion == 1.0:
784 mask = record['FINAL_MEANS'].mask
785 array = record['FINAL_MEANS'][~mask]
786 if len(array) > 0:
787 inDict['ptcTurnoff'][ampName] = record['FINAL_MEANS'][~mask][-1]
788 else:
789 inDict['ptcTurnoff'][ampName] = np.nan
790 else:
791 inDict['ptcTurnoff'][ampName] = record['PTC_TURNOFF']
792 if calibVersion < 1.2:
793 inDict['histVars'][ampName] = np.array([np.nan])
794 inDict['histChi2Dofs'][ampName] = np.array([np.nan])
795 inDict['kspValues'][ampName] = np.array([0.0])
796 else:
797 inDict['histVars'][ampName] = record['HIST_VARS']
798 inDict['histChi2Dofs'][ampName] = record['HIST_CHI2_DOFS']
799 inDict['kspValues'][ampName] = record['KS_PVALUES']
800 if calibVersion < 1.3:
801 nanMatrix = np.full_like(inDict['aMatrix'][ampName], np.nan)
802 inDict['noiseMatrix'][ampName] = nanMatrix
803 inDict['noiseMatrixNoB'][ampName] = nanMatrix
804 elif calibVersion >= 1.3 and calibVersion < 2.1:
805 inDict['noiseMatrix'][ampName] = record['NOISE_MATRIX']
806 inDict['noiseMatrixNoB'][ampName] = record['NOISE_MATRIX_NO_B']
807 else:
808 inDict['noiseMatrix'][ampName] = record['NOISE_MATRIX']
809 nanMatrix = np.full_like(inDict['aMatrix'][ampName], np.nan)
810 inDict['noiseMatrixNoB'][ampName] = nanMatrix
811 if calibVersion < 1.5:
812 # Matched to `COV_MATRIX_SIDE`. Same for all amps.
813 inDict['covMatrixSideFullCovFit'] = inDict['covMatrixSide']
814 else:
815 inDict['covMatrixSideFullCovFit'] = record['COV_MATRIX_SIDE_FULL_COV_FIT']
816 if calibVersion < 1.6:
817 inDict['rowMeanVariance'][ampName] = np.full((len(inDict['expIdMask'][ampName]),), np.nan)
818 else:
819 inDict['rowMeanVariance'][ampName] = record['ROW_MEAN_VARIANCE']
820 if calibVersion < 1.7:
821 inDict['noiseList'][ampName] = np.full_like(inDict['rawMeans'][ampName], np.nan)
822 else:
823 inDict['noiseList'][ampName] = record['NOISE_LIST']
824 if calibVersion < 1.8:
825 inDict['ptcTurnoffSamplingError'][ampName] = np.nan
826 else:
827 inDict['ptcTurnoffSamplingError'][ampName] = record['PTC_TURNOFF_SAMPLING_ERROR']
828 if calibVersion < 1.9 and inDict['ptcFitType'] == "FULLCOVARIANCE":
829 # Before version 1.9, the noise stored in the PTC was in
830 # units of electron^2 only if ptcFitType == FULLCOVARIANCE.
831 # After version 1.9, we standardized the
832 # PhotonTransferCurveDataset noise units to electron to fix
833 # this bug. If a user tries to use an earlier version of
834 # PTC with this fit type, we must be sure to do the
835 # calculations properly. More information about this noise
836 # issue can be found in DM-45976.
837 if ampName == inDict['ampNames'][0]:
838 cls().log.info(f"Input PTC VERSION ({calibVersion}) < 1.9 and"
839 " ptcFitType == FULLCOVARIANCE. Applying fix for"
840 f" the DM-45976 noise issue.")
841 # The noiseErr calculation was accidentally correct in the
842 # previous version, so we only need to upday the noise
843 # attribute.
844 inDict['noise'][ampName] = np.sqrt(record['noise'][ampName])
845 if calibVersion < 2.0:
846 inDict['ampOffsets'][ampName] = np.full_like(inDict['rawMeans'][ampName], np.nan)
847 inDict['gainUnadjusted'][ampName] = record['GAIN']
848 inDict['gainList'][ampName] = np.full_like(inDict['rawMeans'][ampName], np.nan)
849 else:
850 inDict['ampOffsets'][ampName] = record['AMP_OFFSETS']
851 inDict['gainUnadjusted'][ampName] = record['GAIN_UNADJUSTED']
852 inDict['gainList'][ampName] = record['GAIN_LIST']
853 if calibVersion < 2.1:
854 inDict['covariancesModelNoB'][ampName] = record['COVARIANCES_MODEL_NO_B']
855 inDict['aMatrixNoB'][ampName] = record['A_MATRIX_NO_B']
856 else:
857 nanMatrixList = np.full_like(inDict['covariances'][ampName], np.nan)
858 inDict['covariancesModelNoB'][ampName] = nanMatrixList
859 nanMatrix = np.full_like(inDict['aMatrix'][ampName], np.nan)
860 inDict['aMatrixNoB'][ampName] = nanMatrix
861 if calibVersion < 2.2:
862 inDict['inputExpPairMjdStartList'][ampName] = np.full_like(
863 inDict['rawMeans'][ampName],
864 np.nan,
865 )
866 inDict['overscanMedianLevelList'][ampName] = np.full_like(
867 inDict['rawMeans'][ampName],
868 np.nan,
869 )
870 else:
871 inDict['inputExpPairMjdStartList'][ampName] = record['INPUT_EXP_PAIR_MJD_START']
872 inDict['overscanMedianLevelList'][ampName] = record['OVERSCAN_MEDIAN_LIST']
873 if calibVersion < 2.3:
874 inDict['overscanMedian'][ampName] = np.nan
875 inDict['overscanMedianSigma'][ampName] = np.nan
876 else:
877 inDict['overscanMedian'][ampName] = record['OVERSCAN_MEDIAN']
878 inDict['overscanMedianSigma'][ampName] = record['OVERSCAN_MEDIAN_SIGMA']
879
880 inDict['auxValues'] = {}
881 record = ptcTable[0]
882 for col in record.columns.keys():
883 if col.startswith('PTCAUX_'):
884 parts = col.split('PTCAUX_')
885 if isinstance(record[col][0], np.bytes_):
886 # Convert to a unicode string because astropy fits doesn't
887 # round-trip properly
888 inDict['auxValues'][parts[1]] = record[col].astype(np.str_)
889 else:
890 inDict['auxValues'][parts[1]] = record[col]
891
892 return cls().fromDict(inDict)
893

◆ getExpIdsUsed()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.getExpIdsUsed ( self,
ampName )
Get the exposures used, i.e. not discarded, for a given amp.
If no mask has been created yet, all exposures are returned.

Parameters
----------
ampName : `str`

Returns
-------
expIdsUsed : `list` [`tuple`]
    List of pairs of exposure ids used in PTC.

Definition at line 1151 of file ptcDataset.py.

1151 def getExpIdsUsed(self, ampName):
1152 """Get the exposures used, i.e. not discarded, for a given amp.
1153 If no mask has been created yet, all exposures are returned.
1154
1155 Parameters
1156 ----------
1157 ampName : `str`
1158
1159 Returns
1160 -------
1161 expIdsUsed : `list` [`tuple`]
1162 List of pairs of exposure ids used in PTC.
1163 """
1164 if len(self.expIdMask[ampName]) == 0:
1165 return self.inputExpIdPairs[ampName]
1166
1167 # if the mask exists it had better be the same length as the expIdPairs
1168 assert len(self.expIdMask[ampName]) == len(self.inputExpIdPairs[ampName])
1169
1170 pairs = self.inputExpIdPairs[ampName]
1171 mask = self.expIdMask[ampName]
1172 # cast to bool required because numpy
1173 try:
1174 expIdsUsed = [(exp1, exp2) for ((exp1, exp2), m) in zip(pairs, mask) if m]
1175 except ValueError:
1176 self.log.warning("The PTC file was written incorrectly; you should rerun the "
1177 "PTC solve task if possible.")
1178 expIdsUsed = []
1179 for pairList, m in zip(pairs, mask):
1180 if m:
1181 expIdsUsed.append(pairList[0])
1182
1183 return expIdsUsed
1184

◆ getGoodAmps()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.getGoodAmps ( self)
Get the good amps from this PTC.

Definition at line 1185 of file ptcDataset.py.

1185 def getGoodAmps(self):
1186 """Get the good amps from this PTC."""
1187 return [amp for amp in self.ampNames if amp not in self.badAmps]
1188

◆ getGoodPoints()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.getGoodPoints ( self,
ampName )
Get the good points used for a given amp in the PTC.

Parameters
----------
ampName : `str`
    Amplifier's name.

Returns
-------
goodPoints : `np.ndarray`
    Boolean array of good points used in PTC.

Definition at line 1189 of file ptcDataset.py.

1189 def getGoodPoints(self, ampName):
1190 """Get the good points used for a given amp in the PTC.
1191
1192 Parameters
1193 ----------
1194 ampName : `str`
1195 Amplifier's name.
1196
1197 Returns
1198 -------
1199 goodPoints : `np.ndarray`
1200 Boolean array of good points used in PTC.
1201 """
1202 return self.expIdMask[ampName]
1203

◆ getMetadata()

lsst.ip.isr.calibType.IsrCalib.getMetadata ( self)
inherited
Retrieve metadata associated with this calibration.

Returns
-------
meta : `lsst.daf.base.PropertyList`
    Metadata. The returned `~lsst.daf.base.PropertyList` can be
    modified by the caller and the changes will be written to
    external files.

Definition at line 171 of file calibType.py.

171 def getMetadata(self):
172 """Retrieve metadata associated with this calibration.
173
174 Returns
175 -------
176 meta : `lsst.daf.base.PropertyList`
177 Metadata. The returned `~lsst.daf.base.PropertyList` can be
178 modified by the caller and the changes will be written to
179 external files.
180 """
181 return self._metadata
182

◆ metadata()

lsst.ip.isr.calibType.IsrCalib.metadata ( self)
inherited

Definition at line 168 of file calibType.py.

168 def metadata(self):
169 return self._metadata
170

◆ readFits()

lsst.ip.isr.calibType.IsrCalib.readFits ( cls,
filename,
** kwargs )
inherited
Read calibration data from a FITS file.

Parameters
----------
filename : `str`
    Filename to read data from.
kwargs : `dict` or collections.abc.Mapping`, optional
    Set of key=value pairs to pass to the ``fromTable``
    method.

Returns
-------
calib : `lsst.ip.isr.IsrCalib`
    Calibration contained within the file.

Definition at line 505 of file calibType.py.

505 def readFits(cls, filename, **kwargs):
506 """Read calibration data from a FITS file.
507
508 Parameters
509 ----------
510 filename : `str`
511 Filename to read data from.
512 kwargs : `dict` or collections.abc.Mapping`, optional
513 Set of key=value pairs to pass to the ``fromTable``
514 method.
515
516 Returns
517 -------
518 calib : `lsst.ip.isr.IsrCalib`
519 Calibration contained within the file.
520 """
521 tableList = []
522 tableList.append(Table.read(filename, hdu=1, mask_invalid=False))
523 extNum = 2 # Fits indices start at 1, we've read one already.
524 keepTrying = True
525
526 while keepTrying:
527 with warnings.catch_warnings():
528 warnings.simplefilter("error")
529 try:
530 newTable = Table.read(filename, hdu=extNum, mask_invalid=False)
531 tableList.append(newTable)
532 extNum += 1
533 except Exception:
534 keepTrying = False
535
536 for table in tableList:
537 for k, v in table.meta.items():
538 if isinstance(v, fits.card.Undefined):
539 table.meta[k] = None
540
541 calibClass = cls.determineCalibClass(tableList[0].meta, "readFits")
542 return calibClass.fromTable(tableList, **kwargs)
543

◆ readText()

lsst.ip.isr.calibType.IsrCalib.readText ( cls,
filename,
** kwargs )
inherited
Read calibration representation from a yaml/ecsv file.

Parameters
----------
filename : `str`
    Name of the file containing the calibration definition.
kwargs : `dict` or collections.abc.Mapping`, optional
    Set of key=value pairs to pass to the ``fromDict`` or
    ``fromTable`` methods.

Returns
-------
calib : `~lsst.ip.isr.IsrCalibType`
    Calibration class.

Raises
------
RuntimeError
    Raised if the filename does not end in ".ecsv" or ".yaml".

Definition at line 418 of file calibType.py.

418 def readText(cls, filename, **kwargs):
419 """Read calibration representation from a yaml/ecsv file.
420
421 Parameters
422 ----------
423 filename : `str`
424 Name of the file containing the calibration definition.
425 kwargs : `dict` or collections.abc.Mapping`, optional
426 Set of key=value pairs to pass to the ``fromDict`` or
427 ``fromTable`` methods.
428
429 Returns
430 -------
431 calib : `~lsst.ip.isr.IsrCalibType`
432 Calibration class.
433
434 Raises
435 ------
436 RuntimeError
437 Raised if the filename does not end in ".ecsv" or ".yaml".
438 """
439 if filename.endswith((".ecsv", ".ECSV")):
440 data = Table.read(filename, format="ascii.ecsv")
441 calibClass = cls.determineCalibClass(data.meta, "readText/ECSV")
442 return calibClass.fromTable([data], **kwargs)
443 elif filename.endswith((".yaml", ".YAML")):
444 with open(filename, "r") as f:
445 data = yaml.load(f, Loader=yaml.CLoader)
446 calibClass = cls.determineCalibClass(data["metadata"], "readText/YAML")
447 return calibClass.fromDict(data, **kwargs)
448 else:
449 raise RuntimeError(f"Unknown filename extension: {filename}")
450

◆ requiredAttributes() [1/2]

lsst.ip.isr.calibType.IsrCalib.requiredAttributes ( self)
inherited

Definition at line 159 of file calibType.py.

159 def requiredAttributes(self):
160 return self._requiredAttributes
161

◆ requiredAttributes() [2/2]

lsst.ip.isr.calibType.IsrCalib.requiredAttributes ( self,
value )
inherited

Definition at line 163 of file calibType.py.

163 def requiredAttributes(self, value):
164 self._requiredAttributes = value
165

◆ setAmpValuesPartialDataset()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.setAmpValuesPartialDataset ( self,
ampName,
inputExpIdPair = (-1, -1),
inputExpPairMjdStart = np.nan,
rawExpTime = np.nan,
rawMean = np.nan,
rawVar = np.nan,
rowMeanVariance = np.nan,
photoCharge = np.nan,
ampOffset = np.nan,
expIdMask = False,
covariance = None,
covSqrtWeights = None,
gain = np.nan,
noise = np.nan,
overscanMedianLevel = np.nan,
histVar = np.nan,
histChi2Dof = np.nan,
kspValue = 0.0 )
Set the amp values for a partial PTC Dataset (from cpExtractPtcTask).

Parameters
----------
ampName : `str`
    Name of the amp to set the values.
inputExpIdPair : `tuple` [`int`]
    Exposure IDs of input pair.
inputExpPairMjdStart : `float`, optional
    The start MJD of first exposure in the flat pair.
rawExpTime : `float`, optional
    Exposure time for this exposure pair (units: sec).
rawMean : `float`, optional
    Average of the means of the exposures in this pair
    (units: adu).
rawVar : `float`, optional
    Variance of the difference of the exposures in this pair
    (units: adu^2).
rowMeanVariance : `float`, optional
    Variance of the means of the rows in the difference image
    of the exposures in this pair (units: adu^2).
photoCharge : `float`, optional
    Integrated photocharge for flat pair for linearity calibration
    (units: electron).
ampOffset : `float`, optional
    Amp offset for this amplifier.
expIdMask : `bool`, optional
    Flag setting if this exposure pair should be used (True)
    or not used (False).
covariance : `np.ndarray` or None, optional
    Measured covariance for this exposure pair (units: adu^2).
covSqrtWeights : `np.ndarray` or None, optional
    Measured sqrt of covariance weights in this exposure pair
    (units: 1/adu).
gain : `float`, optional
    Estimated gain for this exposure pair (units: electron/adu).
noise : `float`, optional
    Estimated read noise for this exposure pair (units: electron).
overscanMedianLevel : `float`, optional
    Average of the median overscan levels for this exposure pair.
    (units: adu)
histVar : `float`, optional
    Variance estimated from fitting a histogram with a Gaussian model
    (units: adu).
histChi2Dof : `float`, optional
    Chi-squared per degree of freedom from Gaussian histogram fit.
kspValue : `float`, optional
    KS test p-value from the Gaussian histogram fit.

Definition at line 349 of file ptcDataset.py.

369 ):
370 """
371 Set the amp values for a partial PTC Dataset (from cpExtractPtcTask).
372
373 Parameters
374 ----------
375 ampName : `str`
376 Name of the amp to set the values.
377 inputExpIdPair : `tuple` [`int`]
378 Exposure IDs of input pair.
379 inputExpPairMjdStart : `float`, optional
380 The start MJD of first exposure in the flat pair.
381 rawExpTime : `float`, optional
382 Exposure time for this exposure pair (units: sec).
383 rawMean : `float`, optional
384 Average of the means of the exposures in this pair
385 (units: adu).
386 rawVar : `float`, optional
387 Variance of the difference of the exposures in this pair
388 (units: adu^2).
389 rowMeanVariance : `float`, optional
390 Variance of the means of the rows in the difference image
391 of the exposures in this pair (units: adu^2).
392 photoCharge : `float`, optional
393 Integrated photocharge for flat pair for linearity calibration
394 (units: electron).
395 ampOffset : `float`, optional
396 Amp offset for this amplifier.
397 expIdMask : `bool`, optional
398 Flag setting if this exposure pair should be used (True)
399 or not used (False).
400 covariance : `np.ndarray` or None, optional
401 Measured covariance for this exposure pair (units: adu^2).
402 covSqrtWeights : `np.ndarray` or None, optional
403 Measured sqrt of covariance weights in this exposure pair
404 (units: 1/adu).
405 gain : `float`, optional
406 Estimated gain for this exposure pair (units: electron/adu).
407 noise : `float`, optional
408 Estimated read noise for this exposure pair (units: electron).
409 overscanMedianLevel : `float`, optional
410 Average of the median overscan levels for this exposure pair.
411 (units: adu)
412 histVar : `float`, optional
413 Variance estimated from fitting a histogram with a Gaussian model
414 (units: adu).
415 histChi2Dof : `float`, optional
416 Chi-squared per degree of freedom from Gaussian histogram fit.
417 kspValue : `float`, optional
418 KS test p-value from the Gaussian histogram fit.
419 """
420 nanMatrix = np.full((self.covMatrixSide, self.covMatrixSide), np.nan)
421 nanMatrixFit = np.full((self.covMatrixSideFullCovFit,
422 self.covMatrixSideFullCovFit), np.nan)
423 if covariance is None:
424 covariance = nanMatrix
425 if covSqrtWeights is None:
426 covSqrtWeights = nanMatrix
427
428 self.inputExpIdPairs[ampName] = [inputExpIdPair]
429 self.inputExpPairMjdStartList[ampName] = np.array([inputExpPairMjdStart])
430 self.rawExpTimes[ampName] = np.array([rawExpTime])
431 self.rawMeans[ampName] = np.array([rawMean])
432 self.rawVars[ampName] = np.array([rawVar])
433 self.rowMeanVariance[ampName] = np.array([rowMeanVariance])
434 self.photoCharges[ampName] = np.array([photoCharge])
435 self.ampOffsets[ampName] = np.array([ampOffset])
436 self.expIdMask[ampName] = np.array([expIdMask])
437 self.covariances[ampName] = np.array([covariance])
438 self.covariancesSqrtWeights[ampName] = np.array([covSqrtWeights])
439 self.gain[ampName] = gain
440 self.gainUnadjusted[ampName] = gain
441 self.gainList[ampName] = np.array([gain])
442 self.noise[ampName] = noise
443 self.noiseList[ampName] = np.array([noise])
444 self.overscanMedianLevelList[ampName] = np.array([overscanMedianLevel])
445 self.overscanMedian[ampName] = float(overscanMedianLevel)
446 self.overscanMedianSigma[ampName] = float(0.0)
447 self.histVars[ampName] = np.array([histVar])
448 self.histChi2Dofs[ampName] = np.array([histChi2Dof])
449 self.kspValues[ampName] = np.array([kspValue])
450
451 # From FULLCOVARIANCE model
452 self.covariancesModel[ampName] = np.array([nanMatrixFit])
453 self.aMatrix[ampName] = nanMatrixFit
454 self.bMatrix[ampName] = nanMatrixFit
455 self.noiseMatrix[ampName] = nanMatrixFit
456 # Filler values.
457 self.finalVars[ampName] = np.array([np.nan])
458 self.finalModelVars[ampName] = np.array([np.nan])
459 self.finalMeans[ampName] = np.array([np.nan])
460

◆ setAuxValuesPartialDataset()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.setAuxValuesPartialDataset ( self,
auxDict )
Set a dictionary of auxiliary values for a partial dataset.

Parameters
----------
auxDict : `dict` [`str`, `float`]
    Dictionary of float values.

Definition at line 461 of file ptcDataset.py.

461 def setAuxValuesPartialDataset(self, auxDict):
462 """
463 Set a dictionary of auxiliary values for a partial dataset.
464
465 Parameters
466 ----------
467 auxDict : `dict` [`str`, `float`]
468 Dictionary of float values.
469 """
470 for key, value in auxDict.items():
471 if isinstance(value, numbers.Integral):
472 self.auxValues[key] = np.atleast_1d(np.asarray(value).astype(np.int64))
473 elif isinstance(value, (str, np.str_, np.bytes_)):
474 self.auxValues[key] = np.atleast_1d(np.asarray(value))
475 else:
476 self.auxValues[key] = np.atleast_1d(np.array(value, dtype=np.float64))
477

◆ setMetadata()

lsst.ip.isr.calibType.IsrCalib.setMetadata ( self,
metadata )
inherited
Store a copy of the supplied metadata with this calibration.

Parameters
----------
metadata : `lsst.daf.base.PropertyList`
    Metadata to associate with the calibration.  Will be copied and
    overwrite existing metadata.

Reimplemented in lsst.ip.isr.transmissionCurve.IntermediateTransmissionCurve.

Definition at line 183 of file calibType.py.

183 def setMetadata(self, metadata):
184 """Store a copy of the supplied metadata with this calibration.
185
186 Parameters
187 ----------
188 metadata : `lsst.daf.base.PropertyList`
189 Metadata to associate with the calibration. Will be copied and
190 overwrite existing metadata.
191 """
192 if metadata is not None:
193 self._metadata.update(metadata)
194
195 # Ensure that we have the obs type required by calibration ingest
196 self._metadata["OBSTYPE"] = self._OBSTYPE
197 self._metadata[self._OBSTYPE + "_SCHEMA"] = self._SCHEMA
198 self._metadata[self._OBSTYPE + "_VERSION"] = self._VERSION
199
200 if isinstance(metadata, dict):
201 self.calibInfoFromDict(metadata)
202 elif isinstance(metadata, PropertyList):
203 self.calibInfoFromDict(metadata.toDict())
204

◆ sort()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.sort ( self,
sortIndex )
Sort the components of the PTC by a given sort index.

The PTC is sorted in-place.

Parameters
----------
sortIndex : `list` or `np.ndarray`
    The sorting index, which must be the same length as
    the number of elements of the PTC.

Definition at line 1091 of file ptcDataset.py.

1091 def sort(self, sortIndex):
1092 """Sort the components of the PTC by a given sort index.
1093
1094 The PTC is sorted in-place.
1095
1096 Parameters
1097 ----------
1098 sortIndex : `list` or `np.ndarray`
1099 The sorting index, which must be the same length as
1100 the number of elements of the PTC.
1101 """
1102 index = np.atleast_1d(sortIndex)
1103
1104 # First confirm everything matches.
1105 for ampName in self.ampNames:
1106 if len(index) != len(self.rawExpTimes[ampName]):
1107 raise ValueError(
1108 f"Length of sortIndex ({len(index)}) does not match number of PTC "
1109 f"elements ({len(self.rawExpTimes[ampName])})",
1110 )
1111
1112 # Note that gain, gainUnadjusted, gainErr, noise, noiseErr,
1113 # ptcTurnoff, ptcTurnoffSamplingError, and the full covariance fit
1114 # parameters are global and not sorted by input pair.
1115
1116 for ampName in self.ampNames:
1117 self.inputExpIdPairs[ampName] = np.array(
1118 self.inputExpIdPairs[ampName]
1119 )[index].tolist()
1120 self.inputExpPairMjdStartList[ampName] = self.inputExpPairMjdStartList[ampName][index]
1121
1122 self.expIdMask[ampName] = self.expIdMask[ampName][index]
1123 self.rawExpTimes[ampName] = self.rawExpTimes[ampName][index]
1124 self.rawMeans[ampName] = self.rawMeans[ampName][index]
1125 self.rawVars[ampName] = self.rawVars[ampName][index]
1126 self.rowMeanVariance[ampName] = self.rowMeanVariance[ampName][index]
1127 self.photoCharges[ampName] = self.photoCharges[ampName][index]
1128 self.ampOffsets[ampName] = self.ampOffsets[ampName][index]
1129
1130 self.gainList[ampName] = self.gainList[ampName][index]
1131 self.noiseList[ampName] = self.noiseList[ampName][index]
1132
1133 self.overscanMedianLevelList[ampName] = self.overscanMedianLevelList[ampName][index]
1134
1135 self.histVars[ampName] = self.histVars[ampName][index]
1136 self.histChi2Dofs[ampName] = self.histChi2Dofs[ampName][index]
1137 self.kspValues[ampName] = self.kspValues[ampName][index]
1138
1139 self.covariances[ampName] = self.covariances[ampName][index]
1140 self.covariancesSqrtWeights[ampName] = self.covariancesSqrtWeights[ampName][index]
1141 self.covariancesModel[ampName] = self.covariancesModel[ampName][index]
1142
1143 self.finalVars[ampName] = self.finalVars[ampName][index]
1144 self.finalModelVars[ampName] = self.finalModelVars[ampName][index]
1145 self.finalMeans[ampName] = self.finalMeans[ampName][index]
1146
1147 # Sort the auxiliary values which are not stored per-amp.
1148 for key, value in self.auxValues.items():
1149 self.auxValues[key] = value[index]
1150

◆ toDict()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.toDict ( self)
Return a dictionary containing the calibration properties.
The dictionary should be able to be round-tripped through
`fromDict`.

Returns
-------
dictionary : `dict`
    Dictionary of properties.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 614 of file ptcDataset.py.

614 def toDict(self):
615 """Return a dictionary containing the calibration properties.
616 The dictionary should be able to be round-tripped through
617 `fromDict`.
618
619 Returns
620 -------
621 dictionary : `dict`
622 Dictionary of properties.
623 """
624 self.updateMetadata()
625
626 outDict = dict()
627 metadata = self.getMetadata()
628 outDict['metadata'] = metadata
629
630 def _dictOfArraysToDictOfLists(dictOfArrays):
631 dictOfLists = {}
632 for key, value in dictOfArrays.items():
633 dictOfLists[key] = value.ravel().tolist()
634
635 return dictOfLists
636
637 outDict['ptcFitType'] = self.ptcFitType
638 outDict['covMatrixSide'] = self.covMatrixSide
639 outDict['covMatrixSideFullCovFit'] = self.covMatrixSideFullCovFit
640 outDict['ampNames'] = self.ampNames
641 outDict['badAmps'] = self.badAmps
642 outDict['inputExpIdPairs'] = self.inputExpIdPairs
643 outDict['inputExpPairMjdStartList'] = _dictOfArraysToDictOfLists(self.inputExpPairMjdStartList)
644 outDict['expIdMask'] = _dictOfArraysToDictOfLists(self.expIdMask)
645 outDict['rawExpTimes'] = _dictOfArraysToDictOfLists(self.rawExpTimes)
646 outDict['rawMeans'] = _dictOfArraysToDictOfLists(self.rawMeans)
647 outDict['rawVars'] = _dictOfArraysToDictOfLists(self.rawVars)
648 outDict['rowMeanVariance'] = _dictOfArraysToDictOfLists(self.rowMeanVariance)
649 outDict['gain'] = self.gain
650 outDict['gainErr'] = self.gainErr
651 outDict['gainUnadjusted'] = self.gainUnadjusted
652 outDict['gainList'] = _dictOfArraysToDictOfLists(self.gainList)
653 outDict['noiseList'] = _dictOfArraysToDictOfLists(self.noiseList)
654 outDict['overscanMedianLevelList'] = _dictOfArraysToDictOfLists(self.overscanMedianLevelList)
655 outDict['overscanMedian'] = self.overscanMedian
656 outDict['overscanMedianSigma'] = self.overscanMedianSigma
657 outDict['noise'] = self.noise
658 outDict['noiseErr'] = self.noiseErr
659 outDict['histVars'] = self.histVars
660 outDict['histChi2Dofs'] = self.histChi2Dofs
661 outDict['kspValues'] = self.kspValues
662 outDict['ptcFitPars'] = _dictOfArraysToDictOfLists(self.ptcFitPars)
663 outDict['ptcFitParsError'] = _dictOfArraysToDictOfLists(self.ptcFitParsError)
664 outDict['ptcFitChiSq'] = self.ptcFitChiSq
665 outDict['ptcTurnoff'] = self.ptcTurnoff
666 outDict['ptcTurnoffSamplingError'] = self.ptcTurnoffSamplingError
667 outDict['covariances'] = _dictOfArraysToDictOfLists(self.covariances)
668 outDict['covariancesModel'] = _dictOfArraysToDictOfLists(self.covariancesModel)
669 outDict['covariancesSqrtWeights'] = _dictOfArraysToDictOfLists(self.covariancesSqrtWeights)
670 outDict['aMatrix'] = _dictOfArraysToDictOfLists(self.aMatrix)
671 outDict['bMatrix'] = _dictOfArraysToDictOfLists(self.bMatrix)
672 outDict['noiseMatrix'] = _dictOfArraysToDictOfLists(self.noiseMatrix)
673 outDict['finalVars'] = _dictOfArraysToDictOfLists(self.finalVars)
674 outDict['finalModelVars'] = _dictOfArraysToDictOfLists(self.finalModelVars)
675 outDict['finalMeans'] = _dictOfArraysToDictOfLists(self.finalMeans)
676 outDict['photoCharges'] = _dictOfArraysToDictOfLists(self.photoCharges)
677 outDict['ampOffsets'] = _dictOfArraysToDictOfLists(self.ampOffsets)
678 outDict['auxValues'] = _dictOfArraysToDictOfLists(self.auxValues)
679
680 return outDict
681

◆ toTable()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.toTable ( self)
Construct a list of tables containing the information in this
calibration.

The list of tables should create an identical calibration
after being passed to this class's fromTable method.

Returns
-------
tableList : `list` [`astropy.table.Table`]
    List of tables containing the linearity calibration
    information.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 894 of file ptcDataset.py.

894 def toTable(self):
895 """Construct a list of tables containing the information in this
896 calibration.
897
898 The list of tables should create an identical calibration
899 after being passed to this class's fromTable method.
900
901 Returns
902 -------
903 tableList : `list` [`astropy.table.Table`]
904 List of tables containing the linearity calibration
905 information.
906 """
907 tableList = []
908 self.updateMetadata()
909
910 badAmps = np.array(self.badAmps) if len(self.badAmps) else np.array([], dtype="U3")
911
912 catalogList = []
913 for ampName in self.ampNames:
914 ampDict = {
915 'AMPLIFIER_NAME': ampName,
916 'PTC_FIT_TYPE': self.ptcFitType,
917 'COV_MATRIX_SIDE': self.covMatrixSide,
918 'COV_MATRIX_SIDE_FULL_COV_FIT': self.covMatrixSideFullCovFit,
919 'INPUT_EXP_ID_PAIRS': self.inputExpIdPairs[ampName],
920 'INPUT_EXP_PAIR_MJD_START': self.inputExpPairMjdStartList[ampName],
921 'EXP_ID_MASK': self.expIdMask[ampName],
922 'RAW_EXP_TIMES': self.rawExpTimes[ampName],
923 'RAW_MEANS': self.rawMeans[ampName],
924 'RAW_VARS': self.rawVars[ampName],
925 'ROW_MEAN_VARIANCE': self.rowMeanVariance[ampName],
926 'GAIN': self.gain[ampName],
927 'GAIN_ERR': self.gainErr[ampName],
928 'GAIN_UNADJUSTED': self.gainUnadjusted[ampName],
929 'GAIN_LIST': self.gainList[ampName],
930 'OVERSCAN_MEDIAN_LIST': self.overscanMedianLevelList[ampName],
931 'OVERSCAN_MEDIAN': self.overscanMedian[ampName],
932 'OVERSCAN_MEDIAN_SIGMA': self.overscanMedianSigma[ampName],
933 'NOISE_LIST': self.noiseList[ampName],
934 'NOISE': self.noise[ampName],
935 'NOISE_ERR': self.noiseErr[ampName],
936 'HIST_VARS': self.histVars[ampName],
937 'HIST_CHI2_DOFS': self.histChi2Dofs[ampName],
938 'KS_PVALUES': self.kspValues[ampName],
939 'PTC_FIT_PARS': np.array(self.ptcFitPars[ampName]),
940 'PTC_FIT_PARS_ERROR': np.array(self.ptcFitParsError[ampName]),
941 'PTC_FIT_CHI_SQ': self.ptcFitChiSq[ampName],
942 'PTC_TURNOFF': self.ptcTurnoff[ampName],
943 'PTC_TURNOFF_SAMPLING_ERROR': self.ptcTurnoffSamplingError[ampName],
944 'A_MATRIX': self.aMatrix[ampName].ravel(),
945 'B_MATRIX': self.bMatrix[ampName].ravel(),
946 'NOISE_MATRIX': self.noiseMatrix[ampName].ravel(),
947 'BAD_AMPS': badAmps,
948 'PHOTO_CHARGE': self.photoCharges[ampName],
949 'AMP_OFFSETS': self.ampOffsets[ampName],
950 'COVARIANCES': self.covariances[ampName].ravel(),
951 'COVARIANCES_MODEL': self.covariancesModel[ampName].ravel(),
952 'COVARIANCES_SQRT_WEIGHTS': self.covariancesSqrtWeights[ampName].ravel(),
953 'FINAL_VARS': self.finalVars[ampName],
954 'FINAL_MODEL_VARS': self.finalModelVars[ampName],
955 'FINAL_MEANS': self.finalMeans[ampName],
956 }
957
958 if self.auxValues:
959 for key, value in self.auxValues.items():
960 ampDict[f"PTCAUX_{key}"] = value
961
962 catalogList.append(ampDict)
963
964 catalog = Table(catalogList)
965
966 inMeta = self.getMetadata().toDict()
967 outMeta = {k: v for k, v in inMeta.items() if v is not None}
968 outMeta.update({k: "" for k, v in inMeta.items() if v is None})
969 catalog.meta = outMeta
970 tableList.append(catalog)
971
972 return tableList
973

◆ updateMetadata()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.updateMetadata ( self,
** kwargs )
Update calibration metadata.
This calls the base class's method after ensuring the required
calibration keywords will be saved.

Parameters
----------
setDate : `bool`, optional
    Update the CALIBDATE fields in the metadata to the current
    time. Defaults to False.
kwargs :
    Other keyword parameters to set in the metadata.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 478 of file ptcDataset.py.

478 def updateMetadata(self, **kwargs):
479 """Update calibration metadata.
480 This calls the base class's method after ensuring the required
481 calibration keywords will be saved.
482
483 Parameters
484 ----------
485 setDate : `bool`, optional
486 Update the CALIBDATE fields in the metadata to the current
487 time. Defaults to False.
488 kwargs :
489 Other keyword parameters to set in the metadata.
490 """
491 super().updateMetadata(PTC_FIT_TYPE=self.ptcFitType, **kwargs)
492

◆ updateMetadataFromExposures()

lsst.ip.isr.calibType.IsrCalib.updateMetadataFromExposures ( self,
exposures )
inherited
Extract and unify metadata information.

Parameters
----------
exposures : `list`
    Exposures or other calibrations to scan.

Definition at line 291 of file calibType.py.

291 def updateMetadataFromExposures(self, exposures):
292 """Extract and unify metadata information.
293
294 Parameters
295 ----------
296 exposures : `list`
297 Exposures or other calibrations to scan.
298 """
299 # This list of keywords is the set of header entries that
300 # should be checked and propagated. Not having an entry is
301 # not a failure, as they may not be defined for the exposures
302 # being used.
303 keywords = ["SEQNAME", "SEQFILE", "SEQCKSUM", "ODP", "AP0_RC"]
304 metadata = {}
305
306 for exp in exposures:
307 try:
308 expMeta = exp.getMetadata()
309 except AttributeError:
310 continue
311 for key in keywords:
312 if key in expMeta:
313 if key in metadata:
314 if metadata[key] != expMeta[key]:
315 self.log.warning("Metadata mismatch! Have: %s Found %s",
316 metadata[key], expMeta[key])
317 else:
318 metadata[key] = expMeta[key]
319
320 self.updateMetadata(**metadata, setCalibInfo=True)
321

◆ validate()

lsst.ip.isr.calibType.IsrCalib.validate ( self,
other = None )
inherited
Validate that this calibration is defined and can be used.

Parameters
----------
other : `object`, optional
    Thing to validate against.

Returns
-------
valid : `bool`
    Returns true if the calibration is valid and appropriate.

Reimplemented in lsst.ip.isr.linearize.Linearizer, and lsst.ip.isr.photodiodeCorrection.PhotodiodeCorrection.

Definition at line 670 of file calibType.py.

670 def validate(self, other=None):
671 """Validate that this calibration is defined and can be used.
672
673 Parameters
674 ----------
675 other : `object`, optional
676 Thing to validate against.
677
678 Returns
679 -------
680 valid : `bool`
681 Returns true if the calibration is valid and appropriate.
682 """
683 return False
684

◆ validateGainNoiseTurnoffValues()

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.validateGainNoiseTurnoffValues ( self,
ampName,
doWarn = False )
Ensure the gain, read noise, and PTC turnoff have
sensible values.

Parameters
----------
ampName : `str`
    Amplifier's name.

Definition at line 1204 of file ptcDataset.py.

1204 def validateGainNoiseTurnoffValues(self, ampName, doWarn=False):
1205 """Ensure the gain, read noise, and PTC turnoff have
1206 sensible values.
1207
1208 Parameters
1209 ----------
1210 ampName : `str`
1211 Amplifier's name.
1212 """
1213
1214 gain = self.gain[ampName]
1215 noise = self.noise[ampName]
1216 ptcTurnoff = self.ptcTurnoff[ampName]
1217
1218 # Check if gain is not positive or is np.nan
1219 if not (isinstance(gain, (int, float)) and gain > 0) or math.isnan(gain):
1220 if doWarn:
1221 self.log.warning(f"Invalid gain value {gain}"
1222 " Setting to default: Gain=1")
1223 gain = 1
1224
1225 # Check if noise is not positive or is np.nan
1226 if not (isinstance(noise, (int, float)) and noise > 0) or math.isnan(noise):
1227 if doWarn:
1228 self.log.warning(f"Invalid noise value: {noise}"
1229 " Setting to default: Noise=1")
1230 noise = 1
1231
1232 # Check if ptcTurnoff is not positive or is np.nan
1233 if not (isinstance(ptcTurnoff, (int, float)) and ptcTurnoff > 0) or math.isnan(ptcTurnoff):
1234 if doWarn:
1235 self.log.warning(f"Invalid PTC turnoff value: {ptcTurnoff}"
1236 " Setting to default: PTC Turnoff=2e19")
1237 ptcTurnoff = 2e19
1238
1239 self.gain[ampName] = gain
1240 self.noise[ampName] = noise
1241 self.ptcTurnoff[ampName] = ptcTurnoff
1242

◆ writeFits()

lsst.ip.isr.calibType.IsrCalib.writeFits ( self,
filename )
inherited
Write calibration data to a FITS file.

Parameters
----------
filename : `str`
    Filename to write data to.

Returns
-------
used : `str`
    The name of the file used to write the data.

Reimplemented in lsst.ip.isr.transmissionCurve.IntermediateTransmissionCurve.

Definition at line 544 of file calibType.py.

544 def writeFits(self, filename):
545 """Write calibration data to a FITS file.
546
547 Parameters
548 ----------
549 filename : `str`
550 Filename to write data to.
551
552 Returns
553 -------
554 used : `str`
555 The name of the file used to write the data.
556 """
557 tableList = self.toTable()
558 with warnings.catch_warnings():
559 warnings.filterwarnings("ignore", category=Warning, module="astropy.io")
560 astropyList = [fits.table_to_hdu(table) for table in tableList]
561 astropyList.insert(0, fits.PrimaryHDU())
562
563 writer = fits.HDUList(astropyList)
564 writer.writeto(filename, overwrite=True)
565 return filename
566

◆ writeText()

lsst.ip.isr.calibType.IsrCalib.writeText ( self,
filename,
format = "auto" )
inherited
Write the calibration data to a text file.

Parameters
----------
filename : `str`
    Name of the file to write.
format : `str`
    Format to write the file as.  Supported values are:
        ``"auto"`` : Determine filetype from filename.
        ``"yaml"`` : Write as yaml.
        ``"ecsv"`` : Write as ecsv.

Returns
-------
used : `str`
    The name of the file used to write the data.  This may
    differ from the input if the format is explicitly chosen.

Raises
------
RuntimeError
    Raised if filename does not end in a known extension, or
    if all information cannot be written.

Notes
-----
The file is written to YAML/ECSV format and will include any
associated metadata.

Definition at line 451 of file calibType.py.

451 def writeText(self, filename, format="auto"):
452 """Write the calibration data to a text file.
453
454 Parameters
455 ----------
456 filename : `str`
457 Name of the file to write.
458 format : `str`
459 Format to write the file as. Supported values are:
460 ``"auto"`` : Determine filetype from filename.
461 ``"yaml"`` : Write as yaml.
462 ``"ecsv"`` : Write as ecsv.
463
464 Returns
465 -------
466 used : `str`
467 The name of the file used to write the data. This may
468 differ from the input if the format is explicitly chosen.
469
470 Raises
471 ------
472 RuntimeError
473 Raised if filename does not end in a known extension, or
474 if all information cannot be written.
475
476 Notes
477 -----
478 The file is written to YAML/ECSV format and will include any
479 associated metadata.
480 """
481 if format == "yaml" or (format == "auto" and filename.lower().endswith((".yaml", ".YAML"))):
482 outDict = self.toDict()
483 path, ext = os.path.splitext(filename)
484 filename = path + ".yaml"
485 with open(filename, "w") as f:
486 yaml.dump(outDict, f)
487 elif format == "ecsv" or (format == "auto" and filename.lower().endswith((".ecsv", ".ECSV"))):
488 tableList = self.toTable()
489 if len(tableList) > 1:
490 # ECSV doesn't support multiple tables per file, so we
491 # can only write the first table.
492 raise RuntimeError(f"Unable to persist {len(tableList)}tables in ECSV format.")
493
494 table = tableList[0]
495 path, ext = os.path.splitext(filename)
496 filename = path + ".ecsv"
497 table.write(filename, format="ascii.ecsv")
498 else:
499 raise RuntimeError(f"Attempt to write to a file {filename} "
500 "that does not end in '.yaml' or '.ecsv'")
501
502 return filename
503

Member Data Documentation

◆ _calibId

str lsst.ip.isr.calibType.IsrCalib._calibId = None
protectedinherited

Definition at line 74 of file calibType.py.

◆ _detectorId

lsst.ip.isr.calibType.IsrCalib._detectorId = None
protectedinherited

Definition at line 72 of file calibType.py.

◆ _detectorName

lsst.ip.isr.calibType.IsrCalib._detectorName = None
protectedinherited

Definition at line 70 of file calibType.py.

◆ _detectorSerial

lsst.ip.isr.calibType.IsrCalib._detectorSerial = None
protectedinherited

Definition at line 71 of file calibType.py.

◆ _filter

lsst.ip.isr.calibType.IsrCalib._filter = None
protectedinherited

Definition at line 73 of file calibType.py.

◆ _instrument

lsst.ip.isr.calibType.IsrCalib._instrument = None
protectedinherited

Definition at line 67 of file calibType.py.

◆ _metadata

lsst.ip.isr.calibType.IsrCalib._metadata = PropertyList()
protectedinherited

Definition at line 78 of file calibType.py.

◆ _OBSTYPE

str lsst.ip.isr.calibType.IsrCalib._OBSTYPE = "generic"
staticprotectedinherited

Definition at line 62 of file calibType.py.

◆ _raftName

lsst.ip.isr.calibType.IsrCalib._raftName = None
protectedinherited

Definition at line 68 of file calibType.py.

◆ _requiredAttributes

lsst.ip.isr.calibType.IsrCalib._requiredAttributes
protectedinherited

Definition at line 113 of file calibType.py.

◆ _SCHEMA

str lsst.ip.isr.calibType.IsrCalib._SCHEMA = "NO SCHEMA"
staticprotectedinherited

Definition at line 63 of file calibType.py.

◆ _seqcksum

lsst.ip.isr.calibType.IsrCalib._seqcksum = None
protectedinherited

Definition at line 77 of file calibType.py.

◆ _seqfile

lsst.ip.isr.calibType.IsrCalib._seqfile = None
protectedinherited

Definition at line 75 of file calibType.py.

◆ _seqname

lsst.ip.isr.calibType.IsrCalib._seqname = None
protectedinherited

Definition at line 76 of file calibType.py.

◆ _slotName

lsst.ip.isr.calibType.IsrCalib._slotName = None
protectedinherited

Definition at line 69 of file calibType.py.

◆ _VERSION

int lsst.ip.isr.calibType.IsrCalib._VERSION = 0
staticprotectedinherited

Definition at line 64 of file calibType.py.

◆ aMatrix

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.aMatrix = {ampName: np.array([]) for ampName in ampNames}

Definition at line 322 of file ptcDataset.py.

◆ ampNames

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ampNames = ampNames

Definition at line 279 of file ptcDataset.py.

◆ ampOffsets

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ampOffsets = {ampName: np.array([]) for ampName in ampNames}

Definition at line 296 of file ptcDataset.py.

◆ auxValues

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.auxValues = {}

Definition at line 331 of file ptcDataset.py.

◆ badAmps

list lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.badAmps = []

Definition at line 286 of file ptcDataset.py.

◆ bMatrix

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.bMatrix = {ampName: np.array([]) for ampName in ampNames}

Definition at line 323 of file ptcDataset.py.

◆ covariances

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.covariances = {ampName: np.array([]) for ampName in ampNames}

Definition at line 319 of file ptcDataset.py.

◆ covariancesModel

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.covariancesModel = {ampName: np.array([]) for ampName in ampNames}

Definition at line 320 of file ptcDataset.py.

◆ covariancesSqrtWeights

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.covariancesSqrtWeights = {ampName: np.array([]) for ampName in ampNames}

Definition at line 321 of file ptcDataset.py.

◆ covMatrixSide

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.covMatrixSide = covMatrixSide

Definition at line 280 of file ptcDataset.py.

◆ covMatrixSideFullCovFit

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.covMatrixSideFullCovFit = covMatrixSide

Definition at line 282 of file ptcDataset.py.

◆ expIdMask

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.expIdMask = {ampName: np.array([], dtype=bool) for ampName in ampNames}

Definition at line 290 of file ptcDataset.py.

◆ finalMeans

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.finalMeans = {ampName: np.array([]) for ampName in ampNames}

Definition at line 328 of file ptcDataset.py.

◆ finalModelVars

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.finalModelVars = {ampName: np.array([]) for ampName in ampNames}

Definition at line 327 of file ptcDataset.py.

◆ finalVars

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.finalVars = {ampName: np.array([]) for ampName in ampNames}

Definition at line 326 of file ptcDataset.py.

◆ gain

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.gain = {ampName: np.nan for ampName in ampNames}

Definition at line 298 of file ptcDataset.py.

◆ gainErr

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.gainErr = {ampName: np.nan for ampName in ampNames}

Definition at line 300 of file ptcDataset.py.

◆ gainList

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.gainList = {ampName: np.array([]) for ampName in ampNames}

Definition at line 301 of file ptcDataset.py.

◆ gainUnadjusted

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.gainUnadjusted = {ampName: np.nan for ampName in ampNames}

Definition at line 299 of file ptcDataset.py.

◆ histChi2Dofs

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.histChi2Dofs = {ampName: np.array([]) for ampName in ampNames}

Definition at line 310 of file ptcDataset.py.

◆ histVars

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.histVars = {ampName: np.array([]) for ampName in ampNames}

Definition at line 309 of file ptcDataset.py.

◆ inputExpIdPairs

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.inputExpIdPairs = {ampName: [] for ampName in ampNames}

Definition at line 288 of file ptcDataset.py.

◆ inputExpPairMjdStartList

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.inputExpPairMjdStartList = {ampName: np.array([]) for ampName in ampNames}

Definition at line 289 of file ptcDataset.py.

◆ kspValues

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.kspValues = {ampName: np.array([]) for ampName in ampNames}

Definition at line 311 of file ptcDataset.py.

◆ log

lsst.ip.isr.calibType.IsrCalib.log = log if log else logging.getLogger(__name__)
inherited

Definition at line 94 of file calibType.py.

◆ noise

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.noise = {ampName: np.nan for ampName in ampNames}

Definition at line 306 of file ptcDataset.py.

◆ noiseErr

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.noiseErr = {ampName: np.nan for ampName in ampNames}

Definition at line 307 of file ptcDataset.py.

◆ noiseList

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.noiseList = {ampName: np.array([]) for ampName in ampNames}

Definition at line 305 of file ptcDataset.py.

◆ noiseMatrix

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.noiseMatrix = {ampName: np.array([]) for ampName in ampNames}

Definition at line 324 of file ptcDataset.py.

◆ overscanMedian

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.overscanMedian = {ampName: np.nan for ampName in ampNames}

Definition at line 303 of file ptcDataset.py.

◆ overscanMedianLevelList

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.overscanMedianLevelList = {ampName: np.array([]) for ampName in ampNames}

Definition at line 302 of file ptcDataset.py.

◆ overscanMedianSigma

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.overscanMedianSigma = {ampName: np.nan for ampName in ampNames}

Definition at line 304 of file ptcDataset.py.

◆ photoCharges

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.photoCharges = {ampName: np.array([]) for ampName in ampNames}

Definition at line 295 of file ptcDataset.py.

◆ ptcFitChiSq

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ptcFitChiSq = {ampName: np.nan for ampName in ampNames}

Definition at line 315 of file ptcDataset.py.

◆ ptcFitPars

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ptcFitPars = {ampName: np.array([]) for ampName in ampNames}

Definition at line 313 of file ptcDataset.py.

◆ ptcFitParsError

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ptcFitParsError = {ampName: np.array([]) for ampName in ampNames}

Definition at line 314 of file ptcDataset.py.

◆ ptcFitType

lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ptcFitType = ptcFitType

Definition at line 278 of file ptcDataset.py.

◆ ptcTurnoff

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ptcTurnoff = {ampName: np.nan for ampName in ampNames}

Definition at line 316 of file ptcDataset.py.

◆ ptcTurnoffSamplingError

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.ptcTurnoffSamplingError = {ampName: np.nan for ampName in ampNames}

Definition at line 317 of file ptcDataset.py.

◆ rawExpTimes

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.rawExpTimes = {ampName: np.array([]) for ampName in ampNames}

Definition at line 291 of file ptcDataset.py.

◆ rawMeans

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.rawMeans = {ampName: np.array([]) for ampName in ampNames}

Definition at line 292 of file ptcDataset.py.

◆ rawVars

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.rawVars = {ampName: np.array([]) for ampName in ampNames}

Definition at line 293 of file ptcDataset.py.

◆ requiredAttributes

lsst.ip.isr.calibType.IsrCalib.requiredAttributes = set(["_OBSTYPE", "_SCHEMA", "_VERSION"])
inherited

Definition at line 88 of file calibType.py.

◆ rowMeanVariance

dict lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.rowMeanVariance = {ampName: np.array([]) for ampName in ampNames}

Definition at line 294 of file ptcDataset.py.


The documentation for this class was generated from the following file: