LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Public Member Functions | Static Public Member Functions | Public Attributes | List of all members
lsst.ip.isr.crosstalk.CrosstalkCalib Class Reference
Inheritance diagram for lsst.ip.isr.crosstalk.CrosstalkCalib:
lsst.ip.isr.calibType.IsrCalib

Public Member Functions

def __init__ (self, detector=None, nAmp=0, **kwargs)
 
def updateMetadata (self, setDate=False, **kwargs)
 
def fromDetector (self, detector, coeffVector=None)
 
def fromDict (cls, dictionary)
 
def toDict (self)
 
def fromTable (cls, tableList)
 
def toTable (self)
 
def subtractCrosstalk (self, thisExposure, sourceExposure=None, crosstalkCoeffs=None, badPixels=["BAD"], minPixelToMask=45000, crosstalkStr="CROSSTALK", isTrimmed=False, backgroundMethod="None")
 
def requiredAttributes (self)
 
def requiredAttributes (self, value)
 
def __str__ (self)
 
def __eq__ (self, other)
 
def getMetadata (self)
 
def setMetadata (self, metadata)
 
def updateMetadata (self, camera=None, detector=None, filterName=None, setCalibId=False, setCalibInfo=False, setDate=False, **kwargs)
 
def calibInfoFromDict (self, dictionary)
 
def determineCalibClass (cls, metadata, message)
 
def readText (cls, filename, **kwargs)
 
def writeText (self, filename, format="auto")
 
def readFits (cls, filename, **kwargs)
 
def writeFits (self, filename)
 
def fromDetector (self, detector)
 
def fromDict (cls, dictionary, **kwargs)
 
def fromTable (cls, tableList, **kwargs)
 
def validate (self, other=None)
 
def apply (self, target)
 

Static Public Member Functions

def extractAmp (image, amp, ampTarget, isTrimmed=False)
 
def calculateBackground (mi, badPixels=["BAD"])
 

Public Attributes

 hasCrosstalk
 
 nAmp
 
 crosstalkShape
 
 coeffs
 
 coeffErr
 
 coeffNum
 
 coeffValid
 
 interChip
 
 requiredAttributes
 
 log
 

Detailed Description

Calibration of amp-to-amp crosstalk coefficients.

Parameters
----------
detector : `lsst.afw.cameraGeom.Detector`, optional
    Detector to use to pull coefficients from.
nAmp : `int`, optional
    Number of amplifiers to initialize.
log : `logging.Logger`, optional
    Log to write messages to.
**kwargs :
    Parameters to pass to parent constructor.

Notes
-----
The crosstalk attributes stored are:

hasCrosstalk : `bool`
    Whether there is crosstalk defined for this detector.
nAmp : `int`
    Number of amplifiers in this detector.
crosstalkShape : `tuple` [`int`, `int`]
    A tuple containing the shape of the ``coeffs`` matrix.  This
    should be equivalent to (``nAmp``, ``nAmp``).
coeffs : `np.ndarray`
    A matrix containing the crosstalk coefficients.  coeff[i][j]
    contains the coefficients to calculate the contribution
    amplifier_j has on amplifier_i (each row[i] contains the
    corrections for detector_i).
coeffErr : `np.ndarray`, optional
    A matrix (as defined by ``coeffs``) containing the standard
    distribution of the crosstalk measurements.
coeffNum : `np.ndarray`, optional
    A matrix containing the number of pixel pairs used to measure
    the ``coeffs`` and ``coeffErr``.
coeffValid : `np.ndarray`, optional
    A matrix of Boolean values indicating if the coefficient is
    valid, defined as abs(coeff) > coeffErr / sqrt(coeffNum).
interChip : `dict` [`np.ndarray`]
    A dictionary keyed by detectorName containing ``coeffs``
    matrices used to correct for inter-chip crosstalk with a
    source on the detector indicated.

Definition at line 41 of file crosstalk.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.ip.isr.crosstalk.CrosstalkCalib.__init__ (   self,
  detector = None,
  nAmp = 0,
**  kwargs 
)

Definition at line 90 of file crosstalk.py.

90  def __init__(self, detector=None, nAmp=0, **kwargs):
91  self.hasCrosstalk = False
92  self.nAmp = nAmp if nAmp else 0
93  self.crosstalkShape = (self.nAmp, self.nAmp)
94 
95  self.coeffs = np.zeros(self.crosstalkShape) if self.nAmp else None
96  self.coeffErr = np.zeros(self.crosstalkShape) if self.nAmp else None
97  self.coeffNum = np.zeros(self.crosstalkShape,
98  dtype=int) if self.nAmp else None
99  self.coeffValid = np.zeros(self.crosstalkShape,
100  dtype=bool) if self.nAmp else None
101  self.interChip = {}
102 
103  super().__init__(**kwargs)
104  self.requiredAttributes.update(['hasCrosstalk', 'nAmp', 'coeffs',
105  'coeffErr', 'coeffNum', 'coeffValid',
106  'interChip'])
107  if detector:
108  self.fromDetector(detector)
109 

Member Function Documentation

◆ __eq__()

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

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

Reimplemented in lsst.ip.isr.defects.Defects, and lsst.ip.isr.calibType.IsrProvenance.

Definition at line 95 of file calibType.py.

95  def __eq__(self, other):
96  """Calibration equivalence.
97 
98  Running ``calib.log.setLevel(0)`` enables debug statements to
99  identify problematic fields.
100  """
101  if not isinstance(other, self.__class__):
102  self.log.debug("Incorrect class type: %s %s", self.__class__, other.__class__)
103  return False
104 
105  for attr in self._requiredAttributes:
106  attrSelf = getattr(self, attr)
107  attrOther = getattr(other, attr)
108 
109  if isinstance(attrSelf, dict):
110  # Dictionary of arrays.
111  if attrSelf.keys() != attrOther.keys():
112  self.log.debug("Dict Key Failure: %s %s %s", attr, attrSelf.keys(), attrOther.keys())
113  return False
114  for key in attrSelf:
115  if not np.allclose(attrSelf[key], attrOther[key], equal_nan=True):
116  self.log.debug("Array Failure: %s %s %s", key, attrSelf[key], attrOther[key])
117  return False
118  elif isinstance(attrSelf, np.ndarray):
119  # Bare array.
120  if not np.allclose(attrSelf, attrOther, equal_nan=True):
121  self.log.debug("Array Failure: %s %s %s", attr, attrSelf, attrOther)
122  return False
123  elif type(attrSelf) != type(attrOther):
124  if set([attrSelf, attrOther]) == set([None, ""]):
125  # Fits converts None to "", but None is not "".
126  continue
127  self.log.debug("Type Failure: %s %s %s %s %s", attr, type(attrSelf), type(attrOther),
128  attrSelf, attrOther)
129  return False
130  else:
131  if attrSelf != attrOther:
132  self.log.debug("Value Failure: %s %s %s", attr, attrSelf, attrOther)
133  return False
134 
135  return True
136 
table::Key< int > type
Definition: Detector.cc:163
daf::base::PropertySet * set
Definition: fits.cc:912

◆ __str__()

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

Reimplemented in lsst.ip.isr.defects.Defects, and lsst.ip.isr.calibType.IsrProvenance.

Definition at line 92 of file calibType.py.

92  def __str__(self):
93  return f"{self.__class__.__name__}(obstype={self._OBSTYPE}, detector={self._detectorName}, )"
94 

◆ apply()

def 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 612 of file calibType.py.

612  def apply(self, target):
613  """Method to apply the calibration to the target object.
614 
615  Parameters
616  ----------
617  target : `object`
618  Thing to validate against.
619 
620  Returns
621  -------
622  valid : `bool`
623  Returns true if the calibration was applied correctly.
624 
625  Raises
626  ------
627  NotImplementedError :
628  Raised if not implemented.
629  """
630  raise NotImplementedError("Must be implemented by subclass.")
631 
632 

◆ calculateBackground()

def lsst.ip.isr.crosstalk.CrosstalkCalib.calculateBackground (   mi,
  badPixels = ["BAD"] 
)
static
Estimate median background in image.

Getting a great background model isn't important for crosstalk correction,
since the crosstalk is at a low level. The median should be sufficient.

Parameters
----------
mi : `lsst.afw.image.MaskedImage`
    MaskedImage for which to measure background.
badPixels : `list` of `str`
    Mask planes to ignore.
Returns
-------
bg : `float`
    Median background level.

Definition at line 433 of file crosstalk.py.

433  def calculateBackground(mi, badPixels=["BAD"]):
434  """Estimate median background in image.
435 
436  Getting a great background model isn't important for crosstalk correction,
437  since the crosstalk is at a low level. The median should be sufficient.
438 
439  Parameters
440  ----------
441  mi : `lsst.afw.image.MaskedImage`
442  MaskedImage for which to measure background.
443  badPixels : `list` of `str`
444  Mask planes to ignore.
445  Returns
446  -------
447  bg : `float`
448  Median background level.
449  """
450  mask = mi.getMask()
452  stats.setAndMask(mask.getPlaneBitMask(badPixels))
453  return lsst.afw.math.makeStatistics(mi, lsst.afw.math.MEDIAN, stats).getValue()
454 
Pass parameters to a Statistics object.
Definition: Statistics.h:92
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
Definition: Statistics.h:359

◆ calibInfoFromDict()

def 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 261 of file calibType.py.

261  def calibInfoFromDict(self, dictionary):
262  """Handle common keywords.
263 
264  This isn't an ideal solution, but until all calibrations
265  expect to find everything in the metadata, they still need to
266  search through dictionaries.
267 
268  Parameters
269  ----------
270  dictionary : `dict` or `lsst.daf.base.PropertyList`
271  Source for the common keywords.
272 
273  Raises
274  ------
275  RuntimeError :
276  Raised if the dictionary does not match the expected OBSTYPE.
277 
278  """
279 
280  def search(haystack, needles):
281  """Search dictionary 'haystack' for an entry in 'needles'
282  """
283  test = [haystack.get(x) for x in needles]
284  test = set([x for x in test if x is not None])
285  if len(test) == 0:
286  if "metadata" in haystack:
287  return search(haystack["metadata"], needles)
288  else:
289  return None
290  elif len(test) == 1:
291  value = list(test)[0]
292  if value == "":
293  return None
294  else:
295  return value
296  else:
297  raise ValueError(f"Too many values found: {len(test)} {test} {needles}")
298 
299  if "metadata" in dictionary:
300  metadata = dictionary["metadata"]
301 
302  if self._OBSTYPE != metadata["OBSTYPE"]:
303  raise RuntimeError(f"Incorrect calibration supplied. Expected {self._OBSTYPE}, "
304  f"found {metadata['OBSTYPE']}")
305 
306  self._instrument = search(dictionary, ["INSTRUME", "instrument"])
307  self._raftName = search(dictionary, ["RAFTNAME"])
308  self._slotName = search(dictionary, ["SLOTNAME"])
309  self._detectorId = search(dictionary, ["DETECTOR", "detectorId"])
310  self._detectorName = search(dictionary, ["DET_NAME", "DETECTOR_NAME", "detectorName"])
311  self._detectorSerial = search(dictionary, ["DET_SER", "DETECTOR_SERIAL", "detectorSerial"])
312  self._filter = search(dictionary, ["FILTER", "filterName"])
313  self._calibId = search(dictionary, ["CALIB_ID"])
314 
daf::base::PropertyList * list
Definition: fits.cc:913

◆ determineCalibClass()

def 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 316 of file calibType.py.

316  def determineCalibClass(cls, metadata, message):
317  """Attempt to find calibration class in metadata.
318 
319  Parameters
320  ----------
321  metadata : `dict` or `lsst.daf.base.PropertyList`
322  Metadata possibly containing a calibration class entry.
323  message : `str`
324  Message to include in any errors.
325 
326  Returns
327  -------
328  calibClass : `object`
329  The class to use to read the file contents. Should be an
330  `lsst.ip.isr.IsrCalib` subclass.
331 
332  Raises
333  ------
334  ValueError :
335  Raised if the resulting calibClass is the base
336  `lsst.ip.isr.IsrClass` (which does not implement the
337  content methods).
338  """
339  calibClassName = metadata.get("CALIBCLS")
340  calibClass = doImport(calibClassName) if calibClassName is not None else cls
341  if calibClass is IsrCalib:
342  raise ValueError(f"Cannot use base class to read calibration data: {msg}")
343  return calibClass
344 

◆ extractAmp()

def lsst.ip.isr.crosstalk.CrosstalkCalib.extractAmp (   image,
  amp,
  ampTarget,
  isTrimmed = False 
)
static
Extract the image data from an amp, flipped to match ampTarget.

Parameters
----------
image : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage`
    Image containing the amplifier of interest.
amp : `lsst.afw.cameraGeom.Amplifier`
    Amplifier on image to extract.
ampTarget : `lsst.afw.cameraGeom.Amplifier`
    Target amplifier that the extracted image will be flipped
    to match.
isTrimmed : `bool`
    The image is already trimmed.
    TODO : DM-15409 will resolve this.

Returns
-------
output : `lsst.afw.image.Image`
    Image of the amplifier in the desired configuration.

Definition at line 393 of file crosstalk.py.

393  def extractAmp(image, amp, ampTarget, isTrimmed=False):
394  """Extract the image data from an amp, flipped to match ampTarget.
395 
396  Parameters
397  ----------
398  image : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage`
399  Image containing the amplifier of interest.
400  amp : `lsst.afw.cameraGeom.Amplifier`
401  Amplifier on image to extract.
402  ampTarget : `lsst.afw.cameraGeom.Amplifier`
403  Target amplifier that the extracted image will be flipped
404  to match.
405  isTrimmed : `bool`
406  The image is already trimmed.
407  TODO : DM-15409 will resolve this.
408 
409  Returns
410  -------
411  output : `lsst.afw.image.Image`
412  Image of the amplifier in the desired configuration.
413  """
414  X_FLIP = {lsst.afw.cameraGeom.ReadoutCorner.LL: False,
415  lsst.afw.cameraGeom.ReadoutCorner.LR: True,
416  lsst.afw.cameraGeom.ReadoutCorner.UL: False,
417  lsst.afw.cameraGeom.ReadoutCorner.UR: True}
418  Y_FLIP = {lsst.afw.cameraGeom.ReadoutCorner.LL: False,
419  lsst.afw.cameraGeom.ReadoutCorner.LR: False,
420  lsst.afw.cameraGeom.ReadoutCorner.UL: True,
421  lsst.afw.cameraGeom.ReadoutCorner.UR: True}
422 
423  output = image[amp.getBBox() if isTrimmed else amp.getRawDataBBox()]
424  thisAmpCorner = amp.getReadoutCorner()
425  targetAmpCorner = ampTarget.getReadoutCorner()
426 
427  # Flipping is necessary only if the desired configuration doesn't match what we currently have
428  xFlip = X_FLIP[targetAmpCorner] ^ X_FLIP[thisAmpCorner]
429  yFlip = Y_FLIP[targetAmpCorner] ^ Y_FLIP[thisAmpCorner]
430  return lsst.afw.math.flipImage(output, xFlip, yFlip)
431 
std::shared_ptr< ImageT > flipImage(ImageT const &inImage, bool flipLR, bool flipTB)
Flip an image left–right and/or top–bottom.
Definition: rotateImage.cc:92

◆ fromDetector() [1/2]

def lsst.ip.isr.calibType.IsrCalib.fromDetector (   self,
  detector 
)
inherited
Modify the calibration parameters to match the supplied detector.

Parameters
----------
detector : `lsst.afw.cameraGeom.Detector`
    Detector to use to set parameters from.

Raises
------
NotImplementedError
    This needs to be implemented by subclasses for each
    calibration type.

Reimplemented in lsst.ip.isr.linearize.Linearizer.

Definition at line 495 of file calibType.py.

495  def fromDetector(self, detector):
496  """Modify the calibration parameters to match the supplied detector.
497 
498  Parameters
499  ----------
500  detector : `lsst.afw.cameraGeom.Detector`
501  Detector to use to set parameters from.
502 
503  Raises
504  ------
505  NotImplementedError
506  This needs to be implemented by subclasses for each
507  calibration type.
508  """
509  raise NotImplementedError("Must be implemented by subclass.")
510 

◆ fromDetector() [2/2]

def lsst.ip.isr.crosstalk.CrosstalkCalib.fromDetector (   self,
  detector,
  coeffVector = None 
)
Set calibration parameters from the detector.

Parameters
----------
detector : `lsst.afw.cameraGeom.Detector`
    Detector to use to set parameters from.
coeffVector : `numpy.array`, optional
    Use the detector geometry (bounding boxes and flip
    information), but use ``coeffVector`` instead of the
    output of ``detector.getCrosstalk()``.

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

Definition at line 134 of file crosstalk.py.

134  def fromDetector(self, detector, coeffVector=None):
135  """Set calibration parameters from the detector.
136 
137  Parameters
138  ----------
139  detector : `lsst.afw.cameraGeom.Detector`
140  Detector to use to set parameters from.
141  coeffVector : `numpy.array`, optional
142  Use the detector geometry (bounding boxes and flip
143  information), but use ``coeffVector`` instead of the
144  output of ``detector.getCrosstalk()``.
145 
146  Returns
147  -------
148  calib : `lsst.ip.isr.CrosstalkCalib`
149  The calibration constructed from the detector.
150 
151  """
152  if detector.hasCrosstalk() or coeffVector:
153  self._detectorId = detector.getId()
154  self._detectorName = detector.getName()
155  self._detectorSerial = detector.getSerial()
156 
157  self.nAmp = len(detector)
158  self.crosstalkShape = (self.nAmp, self.nAmp)
159 
160  if coeffVector is not None:
161  crosstalkCoeffs = coeffVector
162  else:
163  crosstalkCoeffs = detector.getCrosstalk()
164  if len(crosstalkCoeffs) == 1 and crosstalkCoeffs[0] == 0.0:
165  return self
166  self.coeffs = np.array(crosstalkCoeffs).reshape(self.crosstalkShape)
167 
168  if self.coeffs.shape != self.crosstalkShape:
169  raise RuntimeError("Crosstalk coefficients do not match detector shape. "
170  f"{self.crosstalkShape} {self.nAmp}")
171 
172  self.coeffErr = np.zeros(self.crosstalkShape)
173  self.coeffNum = np.zeros(self.crosstalkShape, dtype=int)
174  self.coeffValid = np.ones(self.crosstalkShape, dtype=bool)
175  self.interChip = {}
176 
177  self.hasCrosstalk = True
178  self.updateMetadata()
179  return self
180 

◆ fromDict() [1/2]

def lsst.ip.isr.crosstalk.CrosstalkCalib.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.CalibType`
    Constructed calibration.

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

Definition at line 182 of file crosstalk.py.

182  def fromDict(cls, dictionary):
183  """Construct a calibration from a dictionary of properties.
184 
185  Must be implemented by the specific calibration subclasses.
186 
187  Parameters
188  ----------
189  dictionary : `dict`
190  Dictionary of properties.
191 
192  Returns
193  -------
194  calib : `lsst.ip.isr.CalibType`
195  Constructed calibration.
196 
197  Raises
198  ------
199  RuntimeError :
200  Raised if the supplied dictionary is for a different
201  calibration.
202  """
203  calib = cls()
204 
205  if calib._OBSTYPE != dictionary['metadata']['OBSTYPE']:
206  raise RuntimeError(f"Incorrect crosstalk supplied. Expected {calib._OBSTYPE}, "
207  f"found {dictionary['metadata']['OBSTYPE']}")
208 
209  calib.setMetadata(dictionary['metadata'])
210 
211  if 'detectorName' in dictionary:
212  calib._detectorName = dictionary.get('detectorName')
213  elif 'DETECTOR_NAME' in dictionary:
214  calib._detectorName = dictionary.get('DETECTOR_NAME')
215  elif 'DET_NAME' in dictionary['metadata']:
216  calib._detectorName = dictionary['metadata']['DET_NAME']
217  else:
218  calib._detectorName = None
219 
220  if 'detectorSerial' in dictionary:
221  calib._detectorSerial = dictionary.get('detectorSerial')
222  elif 'DETECTOR_SERIAL' in dictionary:
223  calib._detectorSerial = dictionary.get('DETECTOR_SERIAL')
224  elif 'DET_SER' in dictionary['metadata']:
225  calib._detectorSerial = dictionary['metadata']['DET_SER']
226  else:
227  calib._detectorSerial = None
228 
229  if 'detectorId' in dictionary:
230  calib._detectorId = dictionary.get('detectorId')
231  elif 'DETECTOR' in dictionary:
232  calib._detectorId = dictionary.get('DETECTOR')
233  elif 'DETECTOR' in dictionary['metadata']:
234  calib._detectorId = dictionary['metadata']['DETECTOR']
235  elif calib._detectorSerial:
236  calib._detectorId = calib._detectorSerial
237  else:
238  calib._detectorId = None
239 
240  if 'instrument' in dictionary:
241  calib._instrument = dictionary.get('instrument')
242  elif 'INSTRUME' in dictionary['metadata']:
243  calib._instrument = dictionary['metadata']['INSTRUME']
244  else:
245  calib._instrument = None
246 
247  calib.hasCrosstalk = dictionary.get('hasCrosstalk',
248  dictionary['metadata'].get('HAS_CROSSTALK', False))
249  if calib.hasCrosstalk:
250  calib.nAmp = dictionary.get('nAmp', dictionary['metadata'].get('NAMP', 0))
251  calib.crosstalkShape = (calib.nAmp, calib.nAmp)
252  calib.coeffs = np.array(dictionary['coeffs']).reshape(calib.crosstalkShape)
253  if 'coeffErr' in dictionary:
254  calib.coeffErr = np.array(dictionary['coeffErr']).reshape(calib.crosstalkShape)
255  else:
256  calib.coeffErr = np.zeros_like(calib.coeffs)
257  if 'coeffNum' in dictionary:
258  calib.coeffNum = np.array(dictionary['coeffNum']).reshape(calib.crosstalkShape)
259  else:
260  calib.coeffNum = np.zeros_like(calib.coeffs, dtype=int)
261  if 'coeffValid' in dictionary:
262  calib.coeffValid = np.array(dictionary['coeffValid']).reshape(calib.crosstalkShape)
263  else:
264  calib.coeffValid = np.ones_like(calib.coeffs, dtype=bool)
265 
266  calib.interChip = dictionary.get('interChip', None)
267  if calib.interChip:
268  for detector in calib.interChip:
269  coeffVector = calib.interChip[detector]
270  calib.interChip[detector] = np.array(coeffVector).reshape(calib.crosstalkShape)
271 
272  calib.updateMetadata()
273  return calib
274 

◆ fromDict() [2/2]

def lsst.ip.isr.calibType.IsrCalib.fromDict (   cls,
  dictionary,
**  kwargs 
)
inherited
Construct a calibration from a dictionary of properties.

Must be implemented by the specific calibration subclasses.

Parameters
----------
dictionary : `dict`
    Dictionary of properties.
kwargs : `dict` or collections.abc.Mapping`, optional
    Set of key=value options.

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

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

Definition at line 512 of file calibType.py.

512  def fromDict(cls, dictionary, **kwargs):
513  """Construct a calibration from a dictionary of properties.
514 
515  Must be implemented by the specific calibration subclasses.
516 
517  Parameters
518  ----------
519  dictionary : `dict`
520  Dictionary of properties.
521  kwargs : `dict` or collections.abc.Mapping`, optional
522  Set of key=value options.
523 
524  Returns
525  ------
526  calib : `lsst.ip.isr.CalibType`
527  Constructed calibration.
528 
529  Raises
530  ------
531  NotImplementedError :
532  Raised if not implemented.
533  """
534  raise NotImplementedError("Must be implemented by subclass.")
535 

◆ fromTable() [1/2]

def lsst.ip.isr.crosstalk.CrosstalkCalib.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 crosstalk
    calibration.

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

Definition at line 314 of file crosstalk.py.

314  def fromTable(cls, tableList):
315  """Construct calibration from a list of tables.
316 
317  This method uses the `fromDict` method to create the
318  calibration, after constructing an appropriate dictionary from
319  the input tables.
320 
321  Parameters
322  ----------
323  tableList : `list` [`lsst.afw.table.Table`]
324  List of tables to use to construct the crosstalk
325  calibration.
326 
327  Returns
328  -------
329  calib : `lsst.ip.isr.CrosstalkCalib`
330  The calibration defined in the tables.
331 
332  """
333  coeffTable = tableList[0]
334 
335  metadata = coeffTable.meta
336  inDict = dict()
337  inDict['metadata'] = metadata
338  inDict['hasCrosstalk'] = metadata['HAS_CROSSTALK']
339  inDict['nAmp'] = metadata['NAMP']
340 
341  inDict['coeffs'] = coeffTable['CT_COEFFS']
342  if 'CT_ERRORS' in coeffTable.columns:
343  inDict['coeffErr'] = coeffTable['CT_ERRORS']
344  if 'CT_COUNTS' in coeffTable.columns:
345  inDict['coeffNum'] = coeffTable['CT_COUNTS']
346  if 'CT_VALID' in coeffTable.columns:
347  inDict['coeffValid'] = coeffTable['CT_VALID']
348 
349  if len(tableList) > 1:
350  inDict['interChip'] = dict()
351  interChipTable = tableList[1]
352  for record in interChipTable:
353  inDict['interChip'][record['IC_SOURCE_DET']] = record['IC_COEFFS']
354 
355  return cls().fromDict(inDict)
356 

◆ fromTable() [2/2]

def lsst.ip.isr.calibType.IsrCalib.fromTable (   cls,
  tableList,
**  kwargs 
)
inherited
Construct a calibration from a dictionary of properties.

Must be implemented by the specific calibration subclasses.

Parameters
----------
tableList : `list` [`lsst.afw.table.Table`]
    List of tables of properties.
kwargs : `dict` or collections.abc.Mapping`, optional
    Set of key=value options.

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

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

Definition at line 555 of file calibType.py.

555  def fromTable(cls, tableList, **kwargs):
556  """Construct a calibration from a dictionary of properties.
557 
558  Must be implemented by the specific calibration subclasses.
559 
560  Parameters
561  ----------
562  tableList : `list` [`lsst.afw.table.Table`]
563  List of tables of properties.
564  kwargs : `dict` or collections.abc.Mapping`, optional
565  Set of key=value options.
566 
567  Returns
568  ------
569  calib : `lsst.ip.isr.CalibType`
570  Constructed calibration.
571 
572  Raises
573  ------
574  NotImplementedError :
575  Raised if not implemented.
576  """
577  raise NotImplementedError("Must be implemented by subclass.")
578 

◆ getMetadata()

def 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 145 of file calibType.py.

145  def getMetadata(self):
146  """Retrieve metadata associated with this calibration.
147 
148  Returns
149  -------
150  meta : `lsst.daf.base.PropertyList`
151  Metadata. The returned `~lsst.daf.base.PropertyList` can be
152  modified by the caller and the changes will be written to
153  external files.
154  """
155  return self._metadata
156 

◆ readFits()

def 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 432 of file calibType.py.

432  def readFits(cls, filename, **kwargs):
433  """Read calibration data from a FITS file.
434 
435  Parameters
436  ----------
437  filename : `str`
438  Filename to read data from.
439  kwargs : `dict` or collections.abc.Mapping`, optional
440  Set of key=value pairs to pass to the ``fromTable``
441  method.
442 
443  Returns
444  -------
445  calib : `lsst.ip.isr.IsrCalib`
446  Calibration contained within the file.
447  """
448  tableList = []
449  tableList.append(Table.read(filename, hdu=1))
450  extNum = 2 # Fits indices start at 1, we've read one already.
451  keepTrying = True
452 
453  while keepTrying:
454  with warnings.catch_warnings():
455  warnings.simplefilter("error")
456  try:
457  newTable = Table.read(filename, hdu=extNum)
458  tableList.append(newTable)
459  extNum += 1
460  except Exception:
461  keepTrying = False
462 
463  for table in tableList:
464  for k, v in table.meta.items():
465  if isinstance(v, fits.card.Undefined):
466  table.meta[k] = None
467 
468  calibClass = cls.determineCalibClass(tableList[0].meta, "readFits")
469  return calibClass.fromTable(tableList, **kwargs)
470 

◆ readText()

def 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 346 of file calibType.py.

346  def readText(cls, filename, **kwargs):
347  """Read calibration representation from a yaml/ecsv file.
348 
349  Parameters
350  ----------
351  filename : `str`
352  Name of the file containing the calibration definition.
353  kwargs : `dict` or collections.abc.Mapping`, optional
354  Set of key=value pairs to pass to the ``fromDict`` or
355  ``fromTable`` methods.
356 
357  Returns
358  -------
359  calib : `~lsst.ip.isr.IsrCalibType`
360  Calibration class.
361 
362  Raises
363  ------
364  RuntimeError :
365  Raised if the filename does not end in ".ecsv" or ".yaml".
366  """
367  if filename.endswith((".ecsv", ".ECSV")):
368  data = Table.read(filename, format="ascii.ecsv")
369  calibClass = cls.determineCalibClass(data.meta, "readText/ECSV")
370  return calibClass.fromTable([data], **kwargs)
371  elif filename.endswith((".yaml", ".YAML")):
372  with open(filename, "r") as f:
373  data = yaml.load(f, Loader=yaml.CLoader)
374  calibClass = cls.determineCalibClass(data["metadata"], "readText/YAML")
375  return calibClass.fromDict(data, **kwargs)
376  else:
377  raise RuntimeError(f"Unknown filename extension: {filename}")
378 

◆ requiredAttributes() [1/2]

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

Definition at line 138 of file calibType.py.

138  def requiredAttributes(self):
139  return self._requiredAttributes
140 

◆ requiredAttributes() [2/2]

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

Definition at line 142 of file calibType.py.

142  def requiredAttributes(self, value):
143  self._requiredAttributes = value
144 

◆ setMetadata()

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

Definition at line 157 of file calibType.py.

157  def setMetadata(self, metadata):
158  """Store a copy of the supplied metadata with this calibration.
159 
160  Parameters
161  ----------
162  metadata : `lsst.daf.base.PropertyList`
163  Metadata to associate with the calibration. Will be copied and
164  overwrite existing metadata.
165  """
166  if metadata is not None:
167  self._metadata.update(metadata)
168 
169  # Ensure that we have the obs type required by calibration ingest
170  self._metadata["OBSTYPE"] = self._OBSTYPE
171  self._metadata[self._OBSTYPE + "_SCHEMA"] = self._SCHEMA
172  self._metadata[self._OBSTYPE + "_VERSION"] = self._VERSION
173 
174  if isinstance(metadata, dict):
175  self.calibInfoFromDict(metadata)
176  elif isinstance(metadata, PropertyList):
177  self.calibInfoFromDict(metadata.toDict())
178 

◆ subtractCrosstalk()

def lsst.ip.isr.crosstalk.CrosstalkCalib.subtractCrosstalk (   self,
  thisExposure,
  sourceExposure = None,
  crosstalkCoeffs = None,
  badPixels = ["BAD"],
  minPixelToMask = 45000,
  crosstalkStr = "CROSSTALK",
  isTrimmed = False,
  backgroundMethod = "None" 
)
Subtract the crosstalk from thisExposure, optionally using a different source.

We set the mask plane indicated by ``crosstalkStr`` in a target amplifier
for pixels in a source amplifier that exceed ``minPixelToMask``. Note that
the correction is applied to all pixels in the amplifier, but only those
that have a substantial crosstalk are masked with ``crosstalkStr``.

The uncorrected image is used as a template for correction. This is good
enough if the crosstalk is small (e.g., coefficients < ~ 1e-3), but if it's
larger you may want to iterate.

Parameters
----------
thisExposure : `lsst.afw.image.Exposure`
    Exposure for which to subtract crosstalk.
sourceExposure : `lsst.afw.image.Exposure`, optional
    Exposure to use as the source of the crosstalk.  If not set,
    thisExposure is used as the source (intra-detector crosstalk).
crosstalkCoeffs : `numpy.ndarray`, optional.
    Coefficients to use to correct crosstalk.
badPixels : `list` of `str`
    Mask planes to ignore.
minPixelToMask : `float`
    Minimum pixel value (relative to the background level) in
    source amplifier for which to set ``crosstalkStr`` mask plane
    in target amplifier.
crosstalkStr : `str`
    Mask plane name for pixels greatly modified by crosstalk
    (above minPixelToMask).
isTrimmed : `bool`
    The image is already trimmed.
    This should no longer be needed once DM-15409 is resolved.
backgroundMethod : `str`
    Method used to subtract the background.  "AMP" uses
    amplifier-by-amplifier background levels, "DETECTOR" uses full
    exposure/maskedImage levels.  Any other value results in no
    background subtraction.

Definition at line 455 of file crosstalk.py.

458  backgroundMethod="None"):
459  """Subtract the crosstalk from thisExposure, optionally using a different source.
460 
461  We set the mask plane indicated by ``crosstalkStr`` in a target amplifier
462  for pixels in a source amplifier that exceed ``minPixelToMask``. Note that
463  the correction is applied to all pixels in the amplifier, but only those
464  that have a substantial crosstalk are masked with ``crosstalkStr``.
465 
466  The uncorrected image is used as a template for correction. This is good
467  enough if the crosstalk is small (e.g., coefficients < ~ 1e-3), but if it's
468  larger you may want to iterate.
469 
470  Parameters
471  ----------
472  thisExposure : `lsst.afw.image.Exposure`
473  Exposure for which to subtract crosstalk.
474  sourceExposure : `lsst.afw.image.Exposure`, optional
475  Exposure to use as the source of the crosstalk. If not set,
476  thisExposure is used as the source (intra-detector crosstalk).
477  crosstalkCoeffs : `numpy.ndarray`, optional.
478  Coefficients to use to correct crosstalk.
479  badPixels : `list` of `str`
480  Mask planes to ignore.
481  minPixelToMask : `float`
482  Minimum pixel value (relative to the background level) in
483  source amplifier for which to set ``crosstalkStr`` mask plane
484  in target amplifier.
485  crosstalkStr : `str`
486  Mask plane name for pixels greatly modified by crosstalk
487  (above minPixelToMask).
488  isTrimmed : `bool`
489  The image is already trimmed.
490  This should no longer be needed once DM-15409 is resolved.
491  backgroundMethod : `str`
492  Method used to subtract the background. "AMP" uses
493  amplifier-by-amplifier background levels, "DETECTOR" uses full
494  exposure/maskedImage levels. Any other value results in no
495  background subtraction.
496  """
497  mi = thisExposure.getMaskedImage()
498  mask = mi.getMask()
499  detector = thisExposure.getDetector()
500  if self.hasCrosstalk is False:
501  self.fromDetector(detector, coeffVector=crosstalkCoeffs)
502 
503  numAmps = len(detector)
504  if numAmps != self.nAmp:
505  raise RuntimeError(f"Crosstalk built for {self.nAmp} in {self._detectorName}, received "
506  f"{numAmps} in {detector.getName()}")
507 
508  if sourceExposure:
509  source = sourceExposure.getMaskedImage()
510  sourceDetector = sourceExposure.getDetector()
511  else:
512  source = mi
513  sourceDetector = detector
514 
515  if crosstalkCoeffs is not None:
516  coeffs = crosstalkCoeffs
517  else:
518  coeffs = self.coeffs
519  self.log.debug("CT COEFF: %s", coeffs)
520  # Set background level based on the requested method. The
521  # thresholdBackground holds the offset needed so that we only mask
522  # pixels high relative to the background, not in an absolute
523  # sense.
524  thresholdBackground = self.calculateBackground(source, badPixels)
525 
526  backgrounds = [0.0 for amp in sourceDetector]
527  if backgroundMethod is None:
528  pass
529  elif backgroundMethod == "AMP":
530  backgrounds = [self.calculateBackground(source[amp.getBBox()], badPixels)
531  for amp in sourceDetector]
532  elif backgroundMethod == "DETECTOR":
533  backgrounds = [self.calculateBackground(source, badPixels) for amp in sourceDetector]
534 
535  # Set the crosstalkStr bit for the bright pixels (those which will have
536  # significant crosstalk correction)
537  crosstalkPlane = mask.addMaskPlane(crosstalkStr)
538  footprints = lsst.afw.detection.FootprintSet(source,
539  lsst.afw.detection.Threshold(minPixelToMask
540  + thresholdBackground))
541  footprints.setMask(mask, crosstalkStr)
542  crosstalk = mask.getPlaneBitMask(crosstalkStr)
543 
544  # Define a subtrahend image to contain all the scaled crosstalk signals
545  subtrahend = source.Factory(source.getBBox())
546  subtrahend.set((0, 0, 0))
547 
548  coeffs = coeffs.transpose()
549  for ii, iAmp in enumerate(sourceDetector):
550  iImage = subtrahend[iAmp.getBBox() if isTrimmed else iAmp.getRawDataBBox()]
551  for jj, jAmp in enumerate(detector):
552  if coeffs[ii, jj] == 0.0:
553  continue
554  jImage = self.extractAmp(mi, jAmp, iAmp, isTrimmed)
555  jImage.getMask().getArray()[:] &= crosstalk # Remove all other masks
556  jImage -= backgrounds[jj]
557  iImage.scaledPlus(coeffs[ii, jj], jImage)
558 
559  # Set crosstalkStr bit only for those pixels that have been significantly modified (i.e., those
560  # masked as such in 'subtrahend'), not necessarily those that are bright originally.
561  mask.clearMaskPlane(crosstalkPlane)
562  mi -= subtrahend # also sets crosstalkStr bit for bright pixels
563 
564 
A set of Footprints, associated with a MaskedImage.
Definition: FootprintSet.h:53
A Threshold is used to pass a threshold value to detection algorithms.
Definition: Threshold.h:43

◆ toDict()

def lsst.ip.isr.crosstalk.CrosstalkCalib.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 275 of file crosstalk.py.

275  def toDict(self):
276  """Return a dictionary containing the calibration properties.
277 
278  The dictionary should be able to be round-tripped through
279  `fromDict`.
280 
281  Returns
282  -------
283  dictionary : `dict`
284  Dictionary of properties.
285  """
286  self.updateMetadata()
287 
288  outDict = {}
289  metadata = self.getMetadata()
290  outDict['metadata'] = metadata
291 
292  outDict['hasCrosstalk'] = self.hasCrosstalk
293  outDict['nAmp'] = self.nAmp
294  outDict['crosstalkShape'] = self.crosstalkShape
295 
296  ctLength = self.nAmp*self.nAmp
297  outDict['coeffs'] = self.coeffs.reshape(ctLength).tolist()
298 
299  if self.coeffErr is not None:
300  outDict['coeffErr'] = self.coeffErr.reshape(ctLength).tolist()
301  if self.coeffNum is not None:
302  outDict['coeffNum'] = self.coeffNum.reshape(ctLength).tolist()
303  if self.coeffValid is not None:
304  outDict['coeffValid'] = self.coeffValid.reshape(ctLength).tolist()
305 
306  if self.interChip:
307  outDict['interChip'] = dict()
308  for detector in self.interChip:
309  outDict['interChip'][detector] = self.interChip[detector].reshape(ctLength).tolist()
310 
311  return outDict
312 

◆ toTable()

def lsst.ip.isr.crosstalk.CrosstalkCalib.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` [`lsst.afw.table.Table`]
    List of tables containing the crosstalk calibration
    information.

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

Definition at line 357 of file crosstalk.py.

357  def toTable(self):
358  """Construct a list of tables containing the information in this calibration.
359 
360  The list of tables should create an identical calibration
361  after being passed to this class's fromTable method.
362 
363  Returns
364  -------
365  tableList : `list` [`lsst.afw.table.Table`]
366  List of tables containing the crosstalk calibration
367  information.
368 
369  """
370  tableList = []
371  self.updateMetadata()
372  catalog = Table([{'CT_COEFFS': self.coeffs.reshape(self.nAmp*self.nAmp),
373  'CT_ERRORS': self.coeffErr.reshape(self.nAmp*self.nAmp),
374  'CT_COUNTS': self.coeffNum.reshape(self.nAmp*self.nAmp),
375  'CT_VALID': self.coeffValid.reshape(self.nAmp*self.nAmp),
376  }])
377  # filter None, because astropy can't deal.
378  inMeta = self.getMetadata().toDict()
379  outMeta = {k: v for k, v in inMeta.items() if v is not None}
380  outMeta.update({k: "" for k, v in inMeta.items() if v is None})
381  catalog.meta = outMeta
382  tableList.append(catalog)
383 
384  if self.interChip:
385  interChipTable = Table([{'IC_SOURCE_DET': sourceDet,
386  'IC_COEFFS': self.interChip[sourceDet].reshape(self.nAmp*self.nAmp)}
387  for sourceDet in self.interChip.keys()])
388  tableList.append(interChipTable)
389  return tableList
390 

◆ updateMetadata() [1/2]

def lsst.ip.isr.calibType.IsrCalib.updateMetadata (   self,
  camera = None,
  detector = None,
  filterName = None,
  setCalibId = False,
  setCalibInfo = False,
  setDate = False,
**  kwargs 
)
inherited
Update metadata keywords with new values.

Parameters
----------
camera : `lsst.afw.cameraGeom.Camera`, optional
    Reference camera to use to set _instrument field.
detector : `lsst.afw.cameraGeom.Detector`, optional
    Reference detector to use to set _detector* fields.
filterName : `str`, optional
    Filter name to assign to this calibration.
setCalibId : `bool`, optional
    Construct the _calibId field from other fields.
setCalibInfo : `bool`, optional
    Set calibration parameters from metadata.
setDate : `bool`, optional
    Ensure the metadata CALIBDATE fields are set to the current datetime.
kwargs : `dict` or `collections.abc.Mapping`, optional
    Set of key=value pairs to assign to the metadata.

Definition at line 179 of file calibType.py.

181  **kwargs):
182  """Update metadata keywords with new values.
183 
184  Parameters
185  ----------
186  camera : `lsst.afw.cameraGeom.Camera`, optional
187  Reference camera to use to set _instrument field.
188  detector : `lsst.afw.cameraGeom.Detector`, optional
189  Reference detector to use to set _detector* fields.
190  filterName : `str`, optional
191  Filter name to assign to this calibration.
192  setCalibId : `bool`, optional
193  Construct the _calibId field from other fields.
194  setCalibInfo : `bool`, optional
195  Set calibration parameters from metadata.
196  setDate : `bool`, optional
197  Ensure the metadata CALIBDATE fields are set to the current datetime.
198  kwargs : `dict` or `collections.abc.Mapping`, optional
199  Set of key=value pairs to assign to the metadata.
200  """
201  mdOriginal = self.getMetadata()
202  mdSupplemental = dict()
203 
204  for k, v in kwargs.items():
205  if isinstance(v, fits.card.Undefined):
206  kwargs[k] = None
207 
208  if setCalibInfo:
209  self.calibInfoFromDict(kwargs)
210 
211  if camera:
212  self._instrument = camera.getName()
213 
214  if detector:
215  self._detectorName = detector.getName()
216  self._detectorSerial = detector.getSerial()
217  self._detectorId = detector.getId()
218  if "_" in self._detectorName:
219  (self._raftName, self._slotName) = self._detectorName.split("_")
220 
221  if filterName:
222  # TOD0 DM-28093: I think this whole comment can go away, if we
223  # always use physicalLabel everywhere in ip_isr.
224  # If set via:
225  # exposure.getInfo().getFilter().getName()
226  # then this will hold the abstract filter.
227  self._filter = filterName
228 
229  if setDate:
230  date = datetime.datetime.now()
231  mdSupplemental["CALIBDATE"] = date.isoformat()
232  mdSupplemental["CALIB_CREATION_DATE"] = date.date().isoformat()
233  mdSupplemental["CALIB_CREATION_TIME"] = date.time().isoformat()
234 
235  if setCalibId:
236  values = []
237  values.append(f"instrument={self._instrument}") if self._instrument else None
238  values.append(f"raftName={self._raftName}") if self._raftName else None
239  values.append(f"detectorName={self._detectorName}") if self._detectorName else None
240  values.append(f"detector={self._detectorId}") if self._detectorId else None
241  values.append(f"filter={self._filter}") if self._filter else None
242 
243  calibDate = mdOriginal.get("CALIBDATE", mdSupplemental.get("CALIBDATE", None))
244  values.append(f"calibDate={calibDate}") if calibDate else None
245 
246  self._calibId = " ".join(values)
247 
248  self._metadata["INSTRUME"] = self._instrument if self._instrument else None
249  self._metadata["RAFTNAME"] = self._raftName if self._raftName else None
250  self._metadata["SLOTNAME"] = self._slotName if self._slotName else None
251  self._metadata["DETECTOR"] = self._detectorId
252  self._metadata["DET_NAME"] = self._detectorName if self._detectorName else None
253  self._metadata["DET_SER"] = self._detectorSerial if self._detectorSerial else None
254  self._metadata["FILTER"] = self._filter if self._filter else None
255  self._metadata["CALIB_ID"] = self._calibId if self._calibId else None
256  self._metadata["CALIBCLS"] = get_full_type_name(self)
257 
258  mdSupplemental.update(kwargs)
259  mdOriginal.update(mdSupplemental)
260 

◆ updateMetadata() [2/2]

def lsst.ip.isr.crosstalk.CrosstalkCalib.updateMetadata (   self,
  setDate = False,
**  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.

Definition at line 110 of file crosstalk.py.

110  def updateMetadata(self, setDate=False, **kwargs):
111  """Update calibration metadata.
112 
113  This calls the base class's method after ensuring the required
114  calibration keywords will be saved.
115 
116  Parameters
117  ----------
118  setDate : `bool`, optional
119  Update the CALIBDATE fields in the metadata to the current
120  time. Defaults to False.
121  kwargs :
122  Other keyword parameters to set in the metadata.
123  """
124  kwargs['DETECTOR'] = self._detectorId
125  kwargs['DETECTOR_NAME'] = self._detectorName
126  kwargs['DETECTOR_SERIAL'] = self._detectorSerial
127  kwargs['HAS_CROSSTALK'] = self.hasCrosstalk
128  kwargs['NAMP'] = self.nAmp
129  self.crosstalkShape = (self.nAmp, self.nAmp)
130  kwargs['CROSSTALK_SHAPE'] = self.crosstalkShape
131 
132  super().updateMetadata(setDate=setDate, **kwargs)
133 

◆ validate()

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

Definition at line 597 of file calibType.py.

597  def validate(self, other=None):
598  """Validate that this calibration is defined and can be used.
599 
600  Parameters
601  ----------
602  other : `object`, optional
603  Thing to validate against.
604 
605  Returns
606  -------
607  valid : `bool`
608  Returns true if the calibration is valid and appropriate.
609  """
610  return False
611 

◆ writeFits()

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

Definition at line 471 of file calibType.py.

471  def writeFits(self, filename):
472  """Write calibration data to a FITS file.
473 
474  Parameters
475  ----------
476  filename : `str`
477  Filename to write data to.
478 
479  Returns
480  -------
481  used : `str`
482  The name of the file used to write the data.
483 
484  """
485  tableList = self.toTable()
486  with warnings.catch_warnings():
487  warnings.filterwarnings("ignore", category=Warning, module="astropy.io")
488  astropyList = [fits.table_to_hdu(table) for table in tableList]
489  astropyList.insert(0, fits.PrimaryHDU())
490 
491  writer = fits.HDUList(astropyList)
492  writer.writeto(filename, overwrite=True)
493  return filename
494 
def writeFits(filename, stamps, metadata, type_name, write_mask, write_variance, write_archive=False)
Definition: stamps.py:42

◆ writeText()

def 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 379 of file calibType.py.

379  def writeText(self, filename, format="auto"):
380  """Write the calibration data to a text file.
381 
382  Parameters
383  ----------
384  filename : `str`
385  Name of the file to write.
386  format : `str`
387  Format to write the file as. Supported values are:
388  ``"auto"`` : Determine filetype from filename.
389  ``"yaml"`` : Write as yaml.
390  ``"ecsv"`` : Write as ecsv.
391  Returns
392  -------
393  used : `str`
394  The name of the file used to write the data. This may
395  differ from the input if the format is explicitly chosen.
396 
397  Raises
398  ------
399  RuntimeError :
400  Raised if filename does not end in a known extension, or
401  if all information cannot be written.
402 
403  Notes
404  -----
405  The file is written to YAML/ECSV format and will include any
406  associated metadata.
407  """
408  if format == "yaml" or (format == "auto" and filename.lower().endswith((".yaml", ".YAML"))):
409  outDict = self.toDict()
410  path, ext = os.path.splitext(filename)
411  filename = path + ".yaml"
412  with open(filename, "w") as f:
413  yaml.dump(outDict, f)
414  elif format == "ecsv" or (format == "auto" and filename.lower().endswith((".ecsv", ".ECSV"))):
415  tableList = self.toTable()
416  if len(tableList) > 1:
417  # ECSV doesn't support multiple tables per file, so we
418  # can only write the first table.
419  raise RuntimeError(f"Unable to persist {len(tableList)}tables in ECSV format.")
420 
421  table = tableList[0]
422  path, ext = os.path.splitext(filename)
423  filename = path + ".ecsv"
424  table.write(filename, format="ascii.ecsv")
425  else:
426  raise RuntimeError(f"Attempt to write to a file {filename} "
427  "that does not end in '.yaml' or '.ecsv'")
428 
429  return filename
430 

Member Data Documentation

◆ coeffErr

lsst.ip.isr.crosstalk.CrosstalkCalib.coeffErr

Definition at line 96 of file crosstalk.py.

◆ coeffNum

lsst.ip.isr.crosstalk.CrosstalkCalib.coeffNum

Definition at line 97 of file crosstalk.py.

◆ coeffs

lsst.ip.isr.crosstalk.CrosstalkCalib.coeffs

Definition at line 95 of file crosstalk.py.

◆ coeffValid

lsst.ip.isr.crosstalk.CrosstalkCalib.coeffValid

Definition at line 99 of file crosstalk.py.

◆ crosstalkShape

lsst.ip.isr.crosstalk.CrosstalkCalib.crosstalkShape

Definition at line 93 of file crosstalk.py.

◆ hasCrosstalk

lsst.ip.isr.crosstalk.CrosstalkCalib.hasCrosstalk

Definition at line 91 of file crosstalk.py.

◆ interChip

lsst.ip.isr.crosstalk.CrosstalkCalib.interChip

Definition at line 101 of file crosstalk.py.

◆ log

lsst.ip.isr.calibType.IsrCalib.log
inherited

Definition at line 86 of file calibType.py.

◆ nAmp

lsst.ip.isr.crosstalk.CrosstalkCalib.nAmp

Definition at line 92 of file crosstalk.py.

◆ requiredAttributes

lsst.ip.isr.calibType.IsrCalib.requiredAttributes
inherited

Definition at line 81 of file calibType.py.


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