Source code for gunagala.camera

"""
Cameras (stricly the image sensor subsystem, not including optics, optical filters, etc)
"""
import os

from astropy import units as u
from astropy.table import Table

from gunagala.utils import ensure_unit, get_table_data


[docs]class Camera: """ Class representing a camera. Here 'camera' refers to the image sensor, associated electronics, shutter, etc., but does not include any of the optical components of the system. Parameters ---------- bit_depth : int Bits per pixel used by the camera analogue to digital converters. full_well : astropy.units.Quantity Number of photo-electrons each pixel can receive before saturating. gain : astropy.units.Quantity Number of photo-electrons corresponding to one ADU in the digital data. bias : astropy.units.Quantity Bias level of image sensor, in ADU / pixel units. Used when determining saturation level. readout_time : astropy.units.Quantity Time required to read the data from the image sensor. pixel_size : astropy.units.Quantity Pixel pitch. Square pixels are assumed. Resolution : astropy.units.Quantity Two element Quantity containing the number of pixels across the image sensor in both horizontal & vertical directions. read_noise astropy.units.Quantity Intrinsic noise of image sensor and readout electronics, in electrons/pixel units. dark_current : astropy.units.Quantity Rate of accumlation of dark signal, in electrons/second/pixel units. QE : astropy.table.Table or str Quantum efficiency as a function of wavelength data, either as an astropy.table.Table object or the name of a file that can be read by `astropy.table.Table.read()`. The filename can be either the path to a user file or the name of one of gunagala's included files. The table must use column names `QE` andv`Throughput`. If the table does not specify units then nm and electron / photon are assumed. minimum_exposure : astropy.units.Quantity Length of the shortest exposure that the camera is able to take. Attributes ---------- bit_depth : int Same as parameters full_well : astropy.units.Quantity Same as parameters gain : astropy.units.Quantity Same as parameters bias : astropy.units.Quantity Same as parameters readout_time : astropy.units.Quantity Same as parameters pixel_size : astropy.units.Quantity Same as parameters resolution : astropy.units.Quantity Same as parameters read_noise : astropy.units.Quantity Same as parameters dark_current : astropy.units.Quantity Same as parameters minimum_exposure : astropy.units.Quantity Same as parameters saturation_level : astropy.units.Quantity Lowest of `full_well` and `2**bit_depth - 1 - bias` max_noise : astropy.units.Quantity Poisson + readout noise corresponding to `saturation_level` wavelenghts : astropy.units.Quantity Sequence of wavelengths from the QE data QE : astropy.units.Quantity Sequence of quantum efficiency values from the QE data. """ def __init__(self, bit_depth, full_well, gain, bias, readout_time, pixel_size, resolution, read_noise, dark_current, QE, minimum_exposure): self.bit_depth = int(bit_depth) self.full_well = ensure_unit(full_well, u.electron / u.pixel) self.gain = ensure_unit(gain, u.electron / u.adu) self.bias = ensure_unit(bias, u.adu / u.pixel) self.readout_time = ensure_unit(readout_time, u.second) self.pixel_size = ensure_unit(pixel_size, u.micron / u.pixel) self.resolution = ensure_unit(resolution, u.pixel) self.read_noise = ensure_unit(read_noise, u.electron / u.pixel) self.dark_current = ensure_unit(dark_current, u.electron / (u.second * u.pixel)) self.minimum_exposure = ensure_unit(minimum_exposure, u.second) # Calculate a saturation level corresponding to the lower of the 'analogue' (full well) # and 'digital' (ADC) limit, in electrons. self.saturation_level = min(self.full_well, ((2**self.bit_depth - 1) * u.adu / u.pixel - self.bias) * self.gain) # Calculate the noise at the saturation level self.max_noise = (self.saturation_level * u.electron / u.pixel + self.read_noise**2)**0.5 self.wavelengths, self.QE = get_table_data(QE, column_names=('Wavelength', 'QE'), column_units=(u.nm, u.electron / u.photon))