LSST Applications g0265f82a02+093ff98f47,g02d81e74bb+10352d6f39,g1f3e9fa97e+40b0fc677d,g2079a07aa2+14824f138e,g2bbee38e9b+093ff98f47,g337abbeb29+093ff98f47,g3ddfee87b4+064c02c7ee,g487adcacf7+7e842ebf4b,g50ff169b8f+5929b3527e,g52b1c1532d+a6fc98d2e7,g568d43a26c+1d7ac31cb0,g591dd9f2cf+fb1f69e2ea,g858d7b2824+10352d6f39,g8a8a8dda67+a6fc98d2e7,g8cdfe0ae6a+66d966b544,g99cad8db69+7ce8a7c20a,g9ddcbc5298+d4bad12328,ga1e77700b3+246acaaf9c,ga2e4dd1c03+064c02c7ee,ga8c6da7877+04f6ba86dc,gae46bcf261+093ff98f47,gb0e22166c9+3863383f4c,gba4ed39666+9664299f35,gbb8dafda3b+db40f59a7d,gbeb006f7da+e6a448e96d,gbf5cecdb8a+10352d6f39,gc0f3af6251+10a3fd39cd,gc120e1dc64+5839e50a77,gc28159a63d+093ff98f47,gcf0d15dbbd+064c02c7ee,gd2a12a3803+0c2c227a2b,gdaeeff99f8+a38ce5ea23,ge79ae78c31+093ff98f47,gee10cc3b42+a6fc98d2e7,gf1cff7945b+10352d6f39,w.2024.15
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Static Public Attributes | Static Protected Attributes | List of all members
lsst.ip.isr.deferredCharge.DeferredChargeTask Class Reference
Inheritance diagram for lsst.ip.isr.deferredCharge.DeferredChargeTask:

Public Member Functions

 run (self, exposure, ctiCalib, gains=None)
 

Static Public Member Functions

 flipData (ampData, amp)
 
 local_offset_inverse (inputArr, drift_scale, decay_time, num_previous_pixels=15)
 
 local_trap_inverse (inputArr, trap, global_cti=0.0, num_previous_pixels=6)
 

Static Public Attributes

 ConfigClass = DeferredChargeConfig
 

Static Protected Attributes

str _DefaultName = 'isrDeferredCharge'
 

Detailed Description

Task to correct an exposure for charge transfer inefficiency.

This uses the methods described by Snyder et al. 2021, Journal of
Astronimcal Telescopes, Instruments, and Systems, 7,
048002. doi:10.1117/1.JATIS.7.4.048002 (Snyder+21).

Definition at line 537 of file deferredCharge.py.

Member Function Documentation

◆ flipData()

lsst.ip.isr.deferredCharge.DeferredChargeTask.flipData ( ampData,
amp )
static
Flip data array such that readout corner is at lower-left.

Parameters
----------
ampData : `numpy.ndarray`, (nx, ny)
    Image data to flip.
amp : `lsst.afw.cameraGeom.Amplifier`
    Amplifier to get readout corner information.

Returns
-------
ampData : `numpy.ndarray`, (nx, ny)
    Flipped image data.

Definition at line 622 of file deferredCharge.py.

622 def flipData(ampData, amp):
623 """Flip data array such that readout corner is at lower-left.
624
625 Parameters
626 ----------
627 ampData : `numpy.ndarray`, (nx, ny)
628 Image data to flip.
629 amp : `lsst.afw.cameraGeom.Amplifier`
630 Amplifier to get readout corner information.
631
632 Returns
633 -------
634 ampData : `numpy.ndarray`, (nx, ny)
635 Flipped image data.
636 """
637 X_FLIP = {ReadoutCorner.LL: False,
638 ReadoutCorner.LR: True,
639 ReadoutCorner.UL: False,
640 ReadoutCorner.UR: True}
641 Y_FLIP = {ReadoutCorner.LL: False,
642 ReadoutCorner.LR: False,
643 ReadoutCorner.UL: True,
644 ReadoutCorner.UR: True}
645
646 if X_FLIP[amp.getReadoutCorner()]:
647 ampData = np.fliplr(ampData)
648 if Y_FLIP[amp.getReadoutCorner()]:
649 ampData = np.flipud(ampData)
650
651 return ampData
652

◆ local_offset_inverse()

lsst.ip.isr.deferredCharge.DeferredChargeTask.local_offset_inverse ( inputArr,
drift_scale,
decay_time,
num_previous_pixels = 15 )
static
Remove CTI effects from local offsets.

    This implements equation 10 of Snyder+21.  For an image with
    CTI, s'(m, n), the correction factor is equal to the maximum
    value of the set of:

    .. code-block::

        {A_L s'(m, n - j) exp(-j t / \tau_L)}_j=0^jmax

    Parameters
    ----------
    inputArr : `numpy.ndarray`, (nx, ny)
        Input image data to correct.
    drift_scale : `float`
        Drift scale (Snyder+21 A_L value) to use in correction.
    decay_time : `float`
        Decay time (Snyder+21 \tau_L) of the correction.
    num_previous_pixels : `int`, optional
        Number of previous pixels to use for correction.  As the
        CTI has an exponential decay, this essentially truncates
        the correction where that decay scales the input charge to
        near zero.

    Returns
    -------
    outputArr : `numpy.ndarray`, (nx, ny)
        Corrected image data.

Definition at line 654 of file deferredCharge.py.

654 def local_offset_inverse(inputArr, drift_scale, decay_time, num_previous_pixels=15):
655 r"""Remove CTI effects from local offsets.
656
657 This implements equation 10 of Snyder+21. For an image with
658 CTI, s'(m, n), the correction factor is equal to the maximum
659 value of the set of:
660
661 .. code-block::
662
663 {A_L s'(m, n - j) exp(-j t / \tau_L)}_j=0^jmax
664
665 Parameters
666 ----------
667 inputArr : `numpy.ndarray`, (nx, ny)
668 Input image data to correct.
669 drift_scale : `float`
670 Drift scale (Snyder+21 A_L value) to use in correction.
671 decay_time : `float`
672 Decay time (Snyder+21 \tau_L) of the correction.
673 num_previous_pixels : `int`, optional
674 Number of previous pixels to use for correction. As the
675 CTI has an exponential decay, this essentially truncates
676 the correction where that decay scales the input charge to
677 near zero.
678
679 Returns
680 -------
681 outputArr : `numpy.ndarray`, (nx, ny)
682 Corrected image data.
683 """
684 r = np.exp(-1/decay_time)
685 Ny, Nx = inputArr.shape
686
687 # j = 0 term:
688 offset = np.zeros((num_previous_pixels, Ny, Nx))
689 offset[0, :, :] = drift_scale*np.maximum(0, inputArr)
690
691 # j = 1..jmax terms:
692 for n in range(1, num_previous_pixels):
693 offset[n, :, n:] = drift_scale*np.maximum(0, inputArr[:, :-n])*(r**n)
694
695 Linv = np.amax(offset, axis=0)
696 outputArr = inputArr - Linv
697
698 return outputArr
699

◆ local_trap_inverse()

lsst.ip.isr.deferredCharge.DeferredChargeTask.local_trap_inverse ( inputArr,
trap,
global_cti = 0.0,
num_previous_pixels = 6 )
static
Apply localized trapping inverse operator to pixel signals.

    This implements equation 13 of Snyder+21.  For an image with
    CTI, s'(m, n), the correction factor is equal to the maximum
    value of the set of:

    .. code-block::

        {A_L s'(m, n - j) exp(-j t / \tau_L)}_j=0^jmax

    Parameters
    ----------
    inputArr : `numpy.ndarray`, (nx, ny)
        Input image data to correct.
    trap : `lsst.ip.isr.SerialTrap`
        Serial trap describing the capture and release of charge.
    global_cti: `float`
        Mean charge transfer inefficiency, b from Snyder+21.
    num_previous_pixels : `int`, optional
        Number of previous pixels to use for correction.

    Returns
    -------
    outputArr : `numpy.ndarray`, (nx, ny)
        Corrected image data.

Definition at line 701 of file deferredCharge.py.

701 def local_trap_inverse(inputArr, trap, global_cti=0.0, num_previous_pixels=6):
702 r"""Apply localized trapping inverse operator to pixel signals.
703
704 This implements equation 13 of Snyder+21. For an image with
705 CTI, s'(m, n), the correction factor is equal to the maximum
706 value of the set of:
707
708 .. code-block::
709
710 {A_L s'(m, n - j) exp(-j t / \tau_L)}_j=0^jmax
711
712 Parameters
713 ----------
714 inputArr : `numpy.ndarray`, (nx, ny)
715 Input image data to correct.
716 trap : `lsst.ip.isr.SerialTrap`
717 Serial trap describing the capture and release of charge.
718 global_cti: `float`
719 Mean charge transfer inefficiency, b from Snyder+21.
720 num_previous_pixels : `int`, optional
721 Number of previous pixels to use for correction.
722
723 Returns
724 -------
725 outputArr : `numpy.ndarray`, (nx, ny)
726 Corrected image data.
727
728 """
729 Ny, Nx = inputArr.shape
730 a = 1 - global_cti
731 r = np.exp(-1/trap.emission_time)
732
733 # Estimate trap occupancies during readout
734 trap_occupancy = np.zeros((num_previous_pixels, Ny, Nx))
735 for n in range(num_previous_pixels):
736 trap_occupancy[n, :, n+1:] = trap.capture(np.maximum(0, inputArr))[:, :-(n+1)]*(r**n)
737 trap_occupancy = np.amax(trap_occupancy, axis=0)
738
739 # Estimate captured charge
740 C = trap.capture(np.maximum(0, inputArr)) - trap_occupancy*r
741 C[C < 0] = 0.
742
743 # Estimate released charge
744 R = np.zeros(inputArr.shape)
745 R[:, 1:] = trap_occupancy[:, 1:]*(1-r)
746 T = R - C
747
748 outputArr = inputArr - a*T
749
750 return outputArr

◆ run()

lsst.ip.isr.deferredCharge.DeferredChargeTask.run ( self,
exposure,
ctiCalib,
gains = None )
Correct deferred charge/CTI issues.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to correct the deferred charge on.
ctiCalib : `lsst.ip.isr.DeferredChargeCalib`
    Calibration object containing the charge transfer
    inefficiency model.
gains : `dict` [`str`, `float`]
    A dictionary, keyed by amplifier name, of the gains to
    use.  If gains is None, the nominal gains in the amplifier
    object are used.

Returns
-------
exposure : `lsst.afw.image.Exposure`
    The corrected exposure.

Definition at line 547 of file deferredCharge.py.

547 def run(self, exposure, ctiCalib, gains=None):
548 """Correct deferred charge/CTI issues.
549
550 Parameters
551 ----------
552 exposure : `lsst.afw.image.Exposure`
553 Exposure to correct the deferred charge on.
554 ctiCalib : `lsst.ip.isr.DeferredChargeCalib`
555 Calibration object containing the charge transfer
556 inefficiency model.
557 gains : `dict` [`str`, `float`]
558 A dictionary, keyed by amplifier name, of the gains to
559 use. If gains is None, the nominal gains in the amplifier
560 object are used.
561
562 Returns
563 -------
564 exposure : `lsst.afw.image.Exposure`
565 The corrected exposure.
566 """
567 image = exposure.getMaskedImage().image
568 detector = exposure.getDetector()
569
570 # If gains were supplied, they should be used. If useGains is
571 # true, but no external gains were supplied, use the nominal
572 # gains listed in the detector. Finally, if useGains is
573 # false, fake a dictionary of unit gains for ``gainContext``.
574 useGains = True
575 if "USEGAINS" in ctiCalib.getMetadata().keys():
576 useGains = ctiCalib.getMetadata()["USEGAINS"]
577 self.log.info(f"useGains = {useGains} from calibration metadata.")
578 else:
579 useGains = self.config.useGains
580 self.log.info(f"USEGAINS not found in calibration metadata. Using {useGains} from config.")
581
582 if useGains:
583 if gains is None:
584 gains = {amp.getName(): amp.getGain() for amp in detector.getAmplifiers()}
585
586 with gainContext(exposure, image, useGains, gains):
587 for amp in detector.getAmplifiers():
588 ampName = amp.getName()
589
590 ampImage = image[amp.getRawBBox()]
591 if self.config.zeroUnusedPixels:
592 # We don't apply overscan subtraction, so zero these
593 # out for now.
594 ampImage[amp.getRawParallelOverscanBBox()].array[:, :] = 0.0
595 ampImage[amp.getRawSerialPrescanBBox()].array[:, :] = 0.0
596
597 # The algorithm expects that the readout corner is in
598 # the lower left corner. Flip it to be so:
599
600 ampData = self.flipData(ampImage.array, amp)
601
602 if ctiCalib.driftScale[ampName] > 0.0:
603 correctedAmpData = self.local_offset_inverse(ampData,
604 ctiCalib.driftScale[ampName],
605 ctiCalib.decayTime[ampName],
606 self.config.nPixelOffsetCorrection)
607 else:
608 correctedAmpData = ampData.copy()
609
610 correctedAmpData = self.local_trap_inverse(correctedAmpData,
611 ctiCalib.serialTraps[ampName],
612 ctiCalib.globalCti[ampName],
613 self.config.nPixelTrapCorrection)
614
615 # Undo flips here. The method is symmetric.
616 correctedAmpData = self.flipData(correctedAmpData, amp)
617 image[amp.getRawBBox()].array[:, :] = correctedAmpData[:, :]
618
619 return exposure
620

Member Data Documentation

◆ _DefaultName

str lsst.ip.isr.deferredCharge.DeferredChargeTask._DefaultName = 'isrDeferredCharge'
staticprotected

Definition at line 545 of file deferredCharge.py.

◆ ConfigClass

lsst.ip.isr.deferredCharge.DeferredChargeTask.ConfigClass = DeferredChargeConfig
static

Definition at line 544 of file deferredCharge.py.


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