LSST Applications 28.0.2,g0fba68d861+5b923b673a,g1fd858c14a+7a7b9dd5ed,g2c84ff76c0+5548bfee71,g30358e5240+f0e04ebe90,g35bb328faa+fcb1d3bbc8,g436fd98eb5+bdc6fcdd04,g4af146b050+742274f7cd,g4d2262a081+3efd3f8190,g4e0f332c67+cb09b8a5b6,g53246c7159+fcb1d3bbc8,g5a012ec0e7+477f9c599b,g5edb6fd927+826dfcb47f,g60b5630c4e+bdc6fcdd04,g67b6fd64d1+2218407a0c,g78460c75b0+2f9a1b4bcd,g786e29fd12+cf7ec2a62a,g7b71ed6315+fcb1d3bbc8,g87b7deb4dc+f9ac2ab1bd,g8852436030+ebf28f0d95,g89139ef638+2218407a0c,g9125e01d80+fcb1d3bbc8,g989de1cb63+2218407a0c,g9f33ca652e+42fb53f4c8,g9f7030ddb1+11b9b6f027,ga2b97cdc51+bdc6fcdd04,gab72ac2889+bdc6fcdd04,gabe3b4be73+1e0a283bba,gabf8522325+3210f02652,gb1101e3267+9c79701da9,gb58c049af0+f03b321e39,gb89ab40317+2218407a0c,gcf25f946ba+ebf28f0d95,gd6cbbdb0b4+e8f9c9c900,gd9a9a58781+fcb1d3bbc8,gde0f65d7ad+a08f294619,ge278dab8ac+3ef3db156b,ge410e46f29+2218407a0c,gf67bdafdda+2218407a0c
LSST Data Management Base Package
Loading...
Searching...
No Matches
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 1189 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 1283 of file deferredCharge.py.

1283 def flipData(ampData, amp):
1284 """Flip data array such that readout corner is at lower-left.
1285
1286 Parameters
1287 ----------
1288 ampData : `numpy.ndarray`, (nx, ny)
1289 Image data to flip.
1290 amp : `lsst.afw.cameraGeom.Amplifier`
1291 Amplifier to get readout corner information.
1292
1293 Returns
1294 -------
1295 ampData : `numpy.ndarray`, (nx, ny)
1296 Flipped image data.
1297 """
1298 X_FLIP = {ReadoutCorner.LL: False,
1299 ReadoutCorner.LR: True,
1300 ReadoutCorner.UL: False,
1301 ReadoutCorner.UR: True}
1302 Y_FLIP = {ReadoutCorner.LL: False,
1303 ReadoutCorner.LR: False,
1304 ReadoutCorner.UL: True,
1305 ReadoutCorner.UR: True}
1306
1307 if X_FLIP[amp.getReadoutCorner()]:
1308 ampData = np.fliplr(ampData)
1309 if Y_FLIP[amp.getReadoutCorner()]:
1310 ampData = np.flipud(ampData)
1311
1312 return ampData
1313

◆ 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 1315 of file deferredCharge.py.

1315 def local_offset_inverse(inputArr, drift_scale, decay_time, num_previous_pixels=15):
1316 r"""Remove CTI effects from local offsets.
1317
1318 This implements equation 10 of Snyder+21. For an image with
1319 CTI, s'(m, n), the correction factor is equal to the maximum
1320 value of the set of:
1321
1322 .. code-block::
1323
1324 {A_L s'(m, n - j) exp(-j t / \tau_L)}_j=0^jmax
1325
1326 Parameters
1327 ----------
1328 inputArr : `numpy.ndarray`, (nx, ny)
1329 Input image data to correct.
1330 drift_scale : `float`
1331 Drift scale (Snyder+21 A_L value) to use in correction.
1332 decay_time : `float`
1333 Decay time (Snyder+21 \tau_L) of the correction.
1334 num_previous_pixels : `int`, optional
1335 Number of previous pixels to use for correction. As the
1336 CTI has an exponential decay, this essentially truncates
1337 the correction where that decay scales the input charge to
1338 near zero.
1339
1340 Returns
1341 -------
1342 outputArr : `numpy.ndarray`, (nx, ny)
1343 Corrected image data.
1344 """
1345 r = np.exp(-1/decay_time)
1346 Ny, Nx = inputArr.shape
1347
1348 # j = 0 term:
1349 offset = np.zeros((num_previous_pixels, Ny, Nx))
1350 offset[0, :, :] = drift_scale*np.maximum(0, inputArr)
1351
1352 # j = 1..jmax terms:
1353 for n in range(1, num_previous_pixels):
1354 offset[n, :, n:] = drift_scale*np.maximum(0, inputArr[:, :-n])*(r**n)
1355
1356 Linv = np.amax(offset, axis=0)
1357 outputArr = inputArr - Linv
1358
1359 return outputArr
1360

◆ 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 1362 of file deferredCharge.py.

1362 def local_trap_inverse(inputArr, trap, global_cti=0.0, num_previous_pixels=6):
1363 r"""Apply localized trapping inverse operator to pixel signals.
1364
1365 This implements equation 13 of Snyder+21. For an image with
1366 CTI, s'(m, n), the correction factor is equal to the maximum
1367 value of the set of:
1368
1369 .. code-block::
1370
1371 {A_L s'(m, n - j) exp(-j t / \tau_L)}_j=0^jmax
1372
1373 Parameters
1374 ----------
1375 inputArr : `numpy.ndarray`, (nx, ny)
1376 Input image data to correct.
1377 trap : `lsst.ip.isr.SerialTrap`
1378 Serial trap describing the capture and release of charge.
1379 global_cti: `float`
1380 Mean charge transfer inefficiency, b from Snyder+21.
1381 num_previous_pixels : `int`, optional
1382 Number of previous pixels to use for correction.
1383
1384 Returns
1385 -------
1386 outputArr : `numpy.ndarray`, (nx, ny)
1387 Corrected image data.
1388
1389 """
1390 Ny, Nx = inputArr.shape
1391 a = 1 - global_cti
1392 r = np.exp(-1/trap.emission_time)
1393
1394 # Estimate trap occupancies during readout
1395 trap_occupancy = np.zeros((num_previous_pixels, Ny, Nx))
1396 for n in range(num_previous_pixels):
1397 trap_occupancy[n, :, n+1:] = trap.capture(np.maximum(0, inputArr))[:, :-(n+1)]*(r**n)
1398 trap_occupancy = np.amax(trap_occupancy, axis=0)
1399
1400 # Estimate captured charge
1401 C = trap.capture(np.maximum(0, inputArr)) - trap_occupancy*r
1402 C[C < 0] = 0.
1403
1404 # Estimate released charge
1405 R = np.zeros(inputArr.shape)
1406 R[:, 1:] = trap_occupancy[:, 1:]*(1-r)
1407 T = R - C
1408
1409 outputArr = inputArr - a*T
1410
1411 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.

Notes
-------
This task will read the exposure metadata and determine if
applying gains if necessary. The correction takes place in
units of electrons. If bootstrapping, the gains used
will just be 1.0. and the input/output units will stay in
adu. If the input image is in adu, the output image will be
in units of electrons. If the input image is in electron,
the output image will be in electron.

Definition at line 1199 of file deferredCharge.py.

1199 def run(self, exposure, ctiCalib, gains=None):
1200 """Correct deferred charge/CTI issues.
1201
1202 Parameters
1203 ----------
1204 exposure : `lsst.afw.image.Exposure`
1205 Exposure to correct the deferred charge on.
1206 ctiCalib : `lsst.ip.isr.DeferredChargeCalib`
1207 Calibration object containing the charge transfer
1208 inefficiency model.
1209 gains : `dict` [`str`, `float`]
1210 A dictionary, keyed by amplifier name, of the gains to
1211 use. If gains is None, the nominal gains in the amplifier
1212 object are used.
1213
1214 Returns
1215 -------
1216 exposure : `lsst.afw.image.Exposure`
1217 The corrected exposure.
1218
1219 Notes
1220 -------
1221 This task will read the exposure metadata and determine if
1222 applying gains if necessary. The correction takes place in
1223 units of electrons. If bootstrapping, the gains used
1224 will just be 1.0. and the input/output units will stay in
1225 adu. If the input image is in adu, the output image will be
1226 in units of electrons. If the input image is in electron,
1227 the output image will be in electron.
1228 """
1229 image = exposure.getMaskedImage().image
1230 detector = exposure.getDetector()
1231
1232 # Get the image and overscan units.
1233 imageUnits = exposure.getMetadata().get("LSST ISR UNITS")
1234
1235 # The deferred charge correction assumes that everything is in
1236 # electron units. Make it so:
1237 applyGains = False
1238 if imageUnits == "adu":
1239 applyGains = True
1240
1241 # If we need to convert the image to electrons, check that gains
1242 # were supplied. CTI should not be solved or corrected without
1243 # supplied gains.
1244 if applyGains and gains is None:
1245 raise RuntimeError("No gains supplied for deferred charge correction.")
1246
1247 with gainContext(exposure, image, apply=applyGains, gains=gains, isTrimmed=False):
1248 # Both the image and the overscan are in electron units.
1249 for amp in detector.getAmplifiers():
1250 ampName = amp.getName()
1251
1252 ampImage = image[amp.getRawBBox()]
1253 if self.config.zeroUnusedPixels:
1254 # We don't apply overscan subtraction, so zero these
1255 # out for now.
1256 ampImage[amp.getRawParallelOverscanBBox()].array[:, :] = 0.0
1257 ampImage[amp.getRawSerialPrescanBBox()].array[:, :] = 0.0
1258
1259 # The algorithm expects that the readout corner is in
1260 # the lower left corner. Flip it to be so:
1261 ampData = self.flipData(ampImage.array, amp)
1262
1263 if ctiCalib.driftScale[ampName] > 0.0:
1264 correctedAmpData = self.local_offset_inverse(ampData,
1265 ctiCalib.driftScale[ampName],
1266 ctiCalib.decayTime[ampName],
1267 self.config.nPixelOffsetCorrection)
1268 else:
1269 correctedAmpData = ampData.copy()
1270
1271 correctedAmpData = self.local_trap_inverse(correctedAmpData,
1272 ctiCalib.serialTraps[ampName],
1273 ctiCalib.globalCti[ampName],
1274 self.config.nPixelTrapCorrection)
1275
1276 # Undo flips here. The method is symmetric.
1277 correctedAmpData = self.flipData(correctedAmpData, amp)
1278 image[amp.getRawBBox()].array[:, :] = correctedAmpData[:, :]
1279
1280 return exposure
1281

Member Data Documentation

◆ _DefaultName

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

Definition at line 1197 of file deferredCharge.py.

◆ ConfigClass

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

Definition at line 1196 of file deferredCharge.py.


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