current#

msfc_ccd.dark.current(images, axis, proportion=0.01, signal_max=<Quantity 100. DN>)[source]#

Estimate the dark current rate of each tap.

The images must be a sequence of darks gathered using a range of exposure lengths. The signal in each image is the trimmed mean of the bias-subtracted active pixels, and the rate is the slope of a linear fit of that signal against the measured exposure time of each image, msfc_ccd.ImageHeader.timedelta.

The masked rows at the start of each tap, where_masked(), are left out of the mean. They hold charge from the frame store rather than from the image area, and their dark current rate is about 80 times higher, so although they are less than two percent of the active pixels, including them would roughly double the result.

The intercept of the fit is discarded. The blank columns used to compute the bias are offset from the dark level of the active pixels by about 1 DN, and the fixed pattern of the sensor is not removed, so the intercept is not the dark current at zero exposure. Only the slope is independent of both.

The dark current accumulated during a single image is much smaller than the readout noise, about 0.05 DN in a two-second image, so it is only measurable after averaging over all the active pixels, and a long exposure is needed to separate it from the bias.

Images which all requested the same exposure length have no slope to fit, and raise an error. An image whose signal is above signal_max cannot be a dark, and raises an error too.

Parameters:
  • images (TapDataT) – A sequence of dark images from each tap, gathered using a range of exposure lengths, such as the taps of a sequence of images.

  • axis (str) – The logical axis along which the images are a sequence of darks.

  • proportion (float) –

    The fraction of the brightest and darkest active pixels to remove from each image before taking the mean, which protects the mean from cosmic rays.

    On the dark tests of 2017-07-12, cosmic rays are too rare to matter, and the result is the same to within one percent for any proportion from 0 to 0.05. Trimming much harder removes the hot pixels too, which are part of the dark current.

  • signal_max (Quantity) – The largest signal of an image which is accepted as a dark.

Returns:

  • A copy of images, of the same type, whose outputs are the dark current

  • rate of each tap.

Raises:
  • TypeError – If images is not the images from each tap.

  • ValueError – If the images did not request at least two different exposure lengths along axis, or one of them has a signal above signal_max.

Return type:

TapDataT

Examples

Estimate the dark current rate of the ESIS channel 1 camera using a pair of dark images with different exposure lengths.

import numpy as np
import named_arrays as na
import msfc_ccd

# Load a two-second dark image and a twelve-second dark image
path = na.ScalarArray(
    ndarray=np.array([
        msfc_ccd.samples.path_dark_2s_esis1,
        msfc_ccd.samples.path_dark_12s_esis1,
    ]),
    axes="time",
)
images = msfc_ccd.fits.open(path)

# Estimate the dark current rate of each tap
msfc_ccd.dark.current(images.taps, "time").outputs.to("DN / s").ndarray
\[[[0.024812228,~0.02456324],~ [0.012261405,~0.019747113]] \; \mathrm{\frac{DN}{s}}\]

Two images give only a rough estimate, since the uncertainty in the bias of each image is about a fifth of the signal accumulated between them. Averaging many images at each of five exposure lengths gives 0.020 to 0.025 DN / s across the four taps of this camera, within six percent of the independent analysis of the same test by MSFC.