22Photodiode storage class.
25__all__ = [
"PhotodiodeCalib"]
28from astropy.table
import Table
34 """Independent current measurements from photodiode for linearity
39 timeSamples : `list` or `numpy.ndarray`
40 List of samples the photodiode was measured at.
41 currentSamples : `list` or `numpy.ndarray`
42 List of current measurements at each time sample.
43 log : `lsst.log.Log`, optional
44 Log to write messages to.
46 Additional parameters. These will be passed to the parent
47 constructor with the exception of:
49 ``"integrationMethod"``
50 Name of the algorithm to use to integrate the current
51 samples. Allowed values are ``DIRECT_SUM``,
52 ``TRIMMED_SUM``, and ``CHARGE_SUM`` (`str`).
54 Scale factor to apply to the current samples for the
55 ``CHARGE_SUM`` integration method. A typical value
56 would be `-1`, to flip the sign of the integrated charge.
59 _OBSTYPE =
'PHOTODIODE'
60 _SCHEMA =
'Photodiode'
63 def __init__(self, timeSamples=None, currentSamples=None, **kwargs):
64 if timeSamples
is not None and currentSamples
is not None:
65 if len(timeSamples) != len(currentSamples):
66 raise RuntimeError(f
"Inconsitent vector lengths: {len(timeSamples)} vs {len(currentSamples)}")
76 if 'integrationMethod' in kwargs:
81 if 'currentScale' in kwargs:
86 if 'day_obs' in kwargs:
88 if 'seq_num' in kwargs:
95 """Construct a PhotodiodeCalib from a dictionary of properties.
100 Dictionary of properties.
104 calib : `lsst.ip.isr.PhotodiodeCalib`
105 Constructed photodiode data.
110 Raised if the supplied dictionary is for a different
115 if calib._OBSTYPE != dictionary[
'metadata'][
'OBSTYPE']:
116 raise RuntimeError(f
"Incorrect photodiode supplied. Expected {calib._OBSTYPE}, "
117 f
"found {dictionary['metadata']['OBSTYPE']}")
119 calib.setMetadata(dictionary[
'metadata'])
121 calib.timeSamples = np.array(dictionary[
'timeSamples']).ravel()
122 calib.currentSamples = np.array(dictionary[
'currentSamples']).ravel()
123 calib.integrationMethod = dictionary.get(
'integrationMethod',
"DIRECT_SUM")
125 calib.updateMetadata()
129 """Return a dictionary containing the photodiode properties.
131 The dictionary should be able to be round-tripped through.
137 Dictionary of properties.
153 """Construct calibration from a list of tables.
155 This method uses the `fromDict` method to create the
156 calibration after constructing an appropriate dictionary from
161 tableList : `list` [`astropy.table.Table`]
162 List of tables to use to construct the crosstalk
167 calib : `lsst.ip.isr.PhotodiodeCalib`
168 The calibration defined in the tables.
170 dataTable = tableList[0]
172 metadata = dataTable.meta
174 inDict[
'metadata'] = metadata
175 inDict[
'integrationMethod'] = metadata.pop(
'INTEGRATION_METHOD',
'DIRECT_SUM')
177 inDict[
'timeSamples'] = dataTable[
'TIME']
178 inDict[
'currentSamples'] = dataTable[
'CURRENT']
183 """Construct a list of tables containing the information in this
186 The list of tables should create an identical calibration
187 after being passed to this class's fromTable method.
191 tableList : `list` [`astropy.table.Table`]
192 List of tables containing the photodiode calibration
199 outMeta = {k: v
for k, v
in inMeta.items()
if v
is not None}
200 outMeta.update({k:
"" for k, v
in inMeta.items()
if v
is None})
202 catalog.meta = outMeta
208 """Construct a PhotodiodeCalib by reading the simple column format.
213 File to read samples from.
217 calib : `lsst.ip.isr.PhotodiodeCalib`
218 The calibration defined in the file.
222 rawData = np.loadtxt(filename, dtype=[(
'time',
'float'), (
'current',
'float')])
224 basename = os.path.basename(filename)
225 cleaned = os.path.splitext(basename)[0]
226 _, _, day_obs, seq_num = cleaned.split(
"_")
228 return cls(timeSamples=rawData[
'time'], currentSamples=rawData[
'current'],
229 day_obs=int(day_obs), seq_num=int(seq_num))
232 """Integrate the current.
237 Raised if the integration method is not known.
246 raise RuntimeError(f
"Unknown integration method {self.integrationMethod}")
251 This uses numpy's trapezoidal integrator.
256 Total charge measured.
261 """Integrate points with a baseline level subtracted.
263 This uses numpy's trapezoidal integrator.
268 Total charge measured.
272 lsst.eotask.gen3.eoPtc
276 lowValueIndices = np.where(self.
currentSamples < currentThreshold)
281 """For this method, the values in .currentSamples are actually the
282 integrated charge values as measured by the ammeter for each
283 sampling interval. We need to do a baseline subtraction,
284 based on the charge values when the LED is off, then sum up
285 the corrected signals.
290 Total charge measured.
306 dy = np.max(current) - np.min(current)
307 signal, = np.where(current > dy/20. + np.min(current))
309 imax = signal[-1] + 2
310 bg = np.concatenate([np.arange(0, imin), np.arange(imax, len(current))])
311 bg_current = np.sum(charge[bg])/np.sum(dt[bg])
313 return np.sum(charge - bg_current*dt)
requiredAttributes(self, value)
updateMetadata(self, camera=None, detector=None, filterName=None, setCalibId=False, setCalibInfo=False, setDate=False, **kwargs)
fromDict(cls, dictionary)
fromTable(cls, tableList)
readTwoColumnPhotodiodeData(cls, filename)
__init__(self, timeSamples=None, currentSamples=None, **kwargs)
integrateTrimmedSum(self)