LSST Applications g0265f82a02+0e5473021a,g02d81e74bb+f5613e8b4f,g1470d8bcf6+190ad2ba91,g14a832a312+311607e4ab,g2079a07aa2+86d27d4dc4,g2305ad1205+a8e3196225,g295015adf3+b67ee847e5,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g3ddfee87b4+a761f810f3,g487adcacf7+17c8fdbcbd,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+65b5bd823e,g5a732f18d5+53520f316c,g64a986408d+f5613e8b4f,g6c1bc301e9+51106c2951,g858d7b2824+f5613e8b4f,g8a8a8dda67+585e252eca,g99cad8db69+6729933424,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,ga8c6da7877+ef4e3a5875,gb0e22166c9+60f28cb32d,gb6a65358fc+0e5473021a,gba4ed39666+c2a2e4ac27,gbb8dafda3b+e9bba80f27,gc120e1dc64+eee469a5e5,gc28159a63d+0e5473021a,gcf0d15dbbd+a761f810f3,gdaeeff99f8+f9a426f77a,ge6526c86ff+d4c1d4bfef,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gf1cff7945b+f5613e8b4f,w.2024.16
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Public Attributes | Protected Attributes | Static Protected 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

 __init__ (self, detector=None, nAmp=0, **kwargs)
 
 updateMetadata (self, setDate=False, **kwargs)
 
 fromDetector (self, detector, coeffVector=None)
 
 fromDict (cls, dictionary)
 
 toDict (self)
 
 fromTable (cls, tableList)
 
 toTable (self)
 
 subtractCrosstalk (self, thisExposure, sourceExposure=None, crosstalkCoeffs=None, badPixels=["BAD"], minPixelToMask=45000, crosstalkStr="CROSSTALK", isTrimmed=False, backgroundMethod="None")
 
 subtractCrosstalkParallelOverscanRegion (self, thisExposure, crosstalkCoeffs=None, badPixels=["BAD"], crosstalkStr="CROSSTALK", detectorConfig=None)
 

Static Public Member Functions

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

Public Attributes

 hasCrosstalk
 
 nAmp
 
 crosstalkShape
 
 coeffs
 
 coeffErr
 
 coeffNum
 
 coeffValid
 
 interChip
 

Protected Attributes

 _detectorId
 
 _detectorName
 
 _detectorSerial
 

Static Protected Attributes

str _OBSTYPE = 'CROSSTALK'
 
str _SCHEMA = 'Gen3 Crosstalk'
 
float _VERSION = 1.0
 

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 : `numpy.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 : `numpy.ndarray`, optional
    A matrix (as defined by ``coeffs``) containing the standard
    distribution of the crosstalk measurements.
coeffNum : `numpy.ndarray`, optional
    A matrix containing the number of pixel pairs used to measure
    the ``coeffs`` and ``coeffErr``.
coeffValid : `numpy.ndarray`, optional
    A matrix of Boolean values indicating if the coefficient is
    valid, defined as abs(coeff) > coeffErr / sqrt(coeffNum).
interChip : `dict` [`numpy.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__()

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

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

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

◆ calculateBackground()

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 435 of file crosstalk.py.

435 def calculateBackground(mi, badPixels=["BAD"]):
436 """Estimate median background in image.
437
438 Getting a great background model isn't important for crosstalk
439 correction, since the crosstalk is at a low level. The median should
440 be sufficient.
441
442 Parameters
443 ----------
444 mi : `lsst.afw.image.MaskedImage`
445 MaskedImage for which to measure background.
446 badPixels : `list` of `str`
447 Mask planes to ignore.
448 Returns
449 -------
450 bg : `float`
451 Median background level.
452 """
453 mask = mi.getMask()
455 stats.setAndMask(mask.getPlaneBitMask(badPixels))
456 return lsst.afw.math.makeStatistics(mi, lsst.afw.math.MEDIAN, stats).getValue()
457
Pass parameters to a Statistics object.
Definition Statistics.h:83
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:361

◆ extractAmp()

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 394 of file crosstalk.py.

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

◆ fromDetector()

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.

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

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()

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.

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

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

◆ fromTable()

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.

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

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

◆ subtractCrosstalk()

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 458 of file crosstalk.py.

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

◆ subtractCrosstalkParallelOverscanRegion()

lsst.ip.isr.crosstalk.CrosstalkCalib.subtractCrosstalkParallelOverscanRegion ( self,
thisExposure,
crosstalkCoeffs = None,
badPixels = ["BAD"],
crosstalkStr = "CROSSTALK",
detectorConfig = None )
Subtract crosstalk just from the parallel overscan region.

This assumes that serial overscan has been previously subtracted.

Parameters
----------
thisExposure : `lsst.afw.image.Exposure`
    Exposure for which to subtract crosstalk.
crosstalkCoeffs : `numpy.ndarray`, optional.
    Coefficients to use to correct crosstalk.
badPixels : `list` of `str`
    Mask planes to ignore.
crosstalkStr : `str`
    Mask plane name for pixels greatly modified by crosstalk
    (above minPixelToMask).
detectorConfig : `lsst.ip.isr.overscanDetectorConfig`, optional
    Per-amplifier configs to use.

Definition at line 570 of file crosstalk.py.

572 detectorConfig=None):
573 """Subtract crosstalk just from the parallel overscan region.
574
575 This assumes that serial overscan has been previously subtracted.
576
577 Parameters
578 ----------
579 thisExposure : `lsst.afw.image.Exposure`
580 Exposure for which to subtract crosstalk.
581 crosstalkCoeffs : `numpy.ndarray`, optional.
582 Coefficients to use to correct crosstalk.
583 badPixels : `list` of `str`
584 Mask planes to ignore.
585 crosstalkStr : `str`
586 Mask plane name for pixels greatly modified by crosstalk
587 (above minPixelToMask).
588 detectorConfig : `lsst.ip.isr.overscanDetectorConfig`, optional
589 Per-amplifier configs to use.
590 """
591 mi = thisExposure.getMaskedImage()
592 mask = mi.getMask()
593 detector = thisExposure.getDetector()
594 if self.hasCrosstalk is False:
595 self.fromDetector(detector, coeffVector=crosstalkCoeffs)
596
597 numAmps = len(detector)
598 if numAmps != self.nAmp:
599 raise RuntimeError(f"Crosstalk built for {self.nAmp} in {self._detectorName}, received "
600 f"{numAmps} in {detector.getName()}")
601
602 source = mi
603 sourceDetector = detector
604
605 if crosstalkCoeffs is not None:
606 coeffs = crosstalkCoeffs
607 else:
608 coeffs = self.coeffs
609
610 crosstalkPlane = mask.addMaskPlane(crosstalkStr)
611 crosstalk = mask.getPlaneBitMask(crosstalkStr)
612
613 subtrahend = source.Factory(source.getBBox())
614 subtrahend.set((0, 0, 0))
615
616 coeffs = coeffs.transpose()
617 for ss, sAmp in enumerate(sourceDetector):
618 if detectorConfig is not None:
619 ampConfig = detectorConfig.getOverscanAmpconfig(sAmp.getName())
620 if not ampConfig.doParallelOverscanCrosstalk:
621 # Skip crosstalk correction for this amplifier.
622 continue
623
624 sImage = subtrahend[sAmp.getRawParallelOverscanBBox()]
625 for tt, tAmp in enumerate(detector):
626 if coeffs[ss, tt] == 0.0:
627 continue
628 tImage = self.extractAmp(mi, tAmp, sAmp, False, parallelOverscan=True)
629 tImage.getMask().getArray()[:] &= crosstalk # Remove all other masks
630 sImage.scaledPlus(coeffs[ss, tt], tImage)
631
632 # Set crosstalkStr bit only for those pixels that have been
633 # significantly modified (i.e., those masked as such in 'subtrahend'),
634 # not necessarily those that are bright originally.
635 mask.clearMaskPlane(crosstalkPlane)
636 mi -= subtrahend # also sets crosstalkStr bit for bright pixels
637
638

◆ toDict()

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()

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

◆ updateMetadata()

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.

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

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

Member Data Documentation

◆ _detectorId

lsst.ip.isr.crosstalk.CrosstalkCalib._detectorId
protected

Definition at line 153 of file crosstalk.py.

◆ _detectorName

lsst.ip.isr.crosstalk.CrosstalkCalib._detectorName
protected

Definition at line 154 of file crosstalk.py.

◆ _detectorSerial

lsst.ip.isr.crosstalk.CrosstalkCalib._detectorSerial
protected

Definition at line 155 of file crosstalk.py.

◆ _OBSTYPE

str lsst.ip.isr.crosstalk.CrosstalkCalib._OBSTYPE = 'CROSSTALK'
staticprotected

Definition at line 86 of file crosstalk.py.

◆ _SCHEMA

str lsst.ip.isr.crosstalk.CrosstalkCalib._SCHEMA = 'Gen3 Crosstalk'
staticprotected

Definition at line 87 of file crosstalk.py.

◆ _VERSION

float lsst.ip.isr.crosstalk.CrosstalkCalib._VERSION = 1.0
staticprotected

Definition at line 88 of file crosstalk.py.

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

◆ nAmp

lsst.ip.isr.crosstalk.CrosstalkCalib.nAmp

Definition at line 92 of file crosstalk.py.


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