Simulation of CCD images#
With the goal of making it easier to generate simulated astronomical images, teareduce provides a class called SimulateCCDExposure that simplifies this task.
import astropy.units as u
import matplotlib.pyplot as plt
import numpy as np
import teareduce as tea
help(tea.SimulateCCDExposure)
Help on class SimulateCCDExposure in module teareduce.simulateccdexposure:
class SimulateCCDExposure(builtins.object)
| SimulateCCDExposure(naxis1=None, naxis2=None, bitpix=None, bias=<Quantity nan adu>, gain=<Quantity nan electron / adu>, readout_noise=<Quantity nan adu>, dark=<Quantity nan adu>, flatfield=nan, data_model=<Quantity nan adu>, seed=None)
|
| Simulated image generator from first principles.
|
| CCD exposures are simulated making use of basic CCD parameters,
| such as gain, readout noise, bias, dark and flat field.
| A data model can also be employed to simulate more realistic
| CCD exposures.
|
| The saturated pixels in 'data_model' are returned as 2**bitpix - 1
| in the simulated image (for instance, 65535 when bitpix=16).
|
| By initializing the seed of the random number generator
| when instantiating this class, there is in principle no need to
| use another seed for the run() method. This is useful for
| generating reproducible sets of consecutive exposures. In any case,
| it is also possible to provide a particular seed to the run()
| method in order to initialize the execution of single exposures.
|
| Attributes
| ----------
| naxis1 : int
| NAXIS1 value.
| naxis2 : int
| NAXIS2 value.
| bitpix : int
| BITPIX value.
| bias : Quantity
| Numpy array with the detector bias level (ADU).
| gain : Quantity
| Numpy array with the detector gain (electrons/ADU).
| readout_noise : Quantity
| Numpy array with the readout noise (ADU).
| dark : Quantity
| Numpy array with the total dark current (ADU) for each pixel.
| These numbers should not be the dark current rate (ADU/s).
| The provided numbers must correspond to the total dark current
| since the exposure time is not defined.
| flatfield : numpy.ndarray
| Numpy array with the pixel to pixel sensitivity (without units).
| data_model : Quantity
| Numpy array with the model of the source to be simulated (ADU).
| Note that this is the model before applying the flatfield.
| The values in this array must be the total ADU for each pixel.
| seed : int or None
| Random number generator seed.
| _rng : np.random.RandomState
| Random number generator.
|
| Methods
| -------
| set_constant(parameter, value, region)
| Set the value of a particular CCD parameter to a constant
| value. The parameter can be any of VALID_PARAMETERS. The
| constant value can be employed for all pixels or in a specific
| region.
| set_array2d(parameter, value, region)
| Set the value of a particular CCD parameter to a 2D array.
| The parameter can be any of VALID_PARAMETERS. The 2D array
| may correspond to the whole simulated array or to a specific
| region.
| run(imgtype, seed, method)
| Execute the generation of the simulated CCD exposure of
| type 'imgtype', where 'imgtype' is one of VALID_IMAGE_TYPES.
| The signal can be generated using either method: Poisson
| or Gaussian. It is possible to set the seed in order to
| initialize the random number generator.
|
| Methods defined here:
|
| __init__(self, naxis1=None, naxis2=None, bitpix=None, bias=<Quantity nan adu>, gain=<Quantity nan electron / adu>, readout_noise=<Quantity nan adu>, dark=<Quantity nan adu>, flatfield=nan, data_model=<Quantity nan adu>, seed=None)
| Initialize the class attributes.
|
| The simulated array dimensions are mandatory. If any additional
| parameter is not provided, all the pixel values are set to NaN.
| The values of each parameter can be subsequently modified using
| methods that allow these values to be changed in specific regions
| of the CCD.
|
| The input parameters must be a Quantity whose value is either
| a single number, which is expanded to fill the numpy.array,
| or a numpy.array with the expected shape (NAXIS2, NAXIS1).
|
| Parameters
| ----------
| naxis1 : int
| NAXIS1 value.
| naxis2 : int
| NAXIS2 value.
| bitpix : int
| BITPIX value.
| bias : Quantity
| Detector bias level (ADU).
| gain : Quantity
| Detector gain (electrons/ADU).
| readout_noise : Quantity
| Readout noise (ADU).
| dark : Quantity
| Total dark current (ADU). This number should not be the
| dark current rate (ADU/s). The provided number must
| be the total dark current since the exposure time is not
| defined.
| flatfield : float or numpy.ndarray
| Pixel to pixel sensitivity (without units).
| data_model : Quantity
| Model of the source to be simulated (ADU).
| seed : int or None
| Random number generator seed.
|
| __repr__(self)
| Return repr(self).
|
| run(self, imgtype, method='Poisson', seed=None)
| Execute the generation of the simulated CCD exposure.
|
| This function generates an image of type 'imgtype', which must
| be one of VALID_IMAGE_TYPES. The signal can be generated using
| either method: Poisson or Gaussian. It is possible to set the
| seed in order to initialize the random number generator.
|
| Parameters
| ----------
| imgtype : str
| Type of image to be generated. It must be one of
| VALID_IMAGE_TYPES.
| method : str
| Method to generate the simulated data. It must be one of
| VALID_METHODS.
| seed : int, optional
| Seed for the random number generator. The default is None.
|
| Returns
| -------
| result : SimulatedCCDResult
| Instance of SimulatedCCDResult to store the simulated image
| and the associated parameters employed to define how to
| generate the simulated CCD exposure.
|
| set_array2d(self, parameter, array2d, region=None)
| Set the value of a particular parameter to a 2D array.
|
| The parameter can be any of VALID_PARAMETERS. The 2D array
| may correspond to the whole simulated array or to a specific
| region.
|
| Parameters
| ----------
| parameter : str
| CCD parameter to set. It must be any of VALID_PARAMETERS.
| array2d : Quantity
| Array of values to be used to define 'parameter'.
| region : SliceRegion2D
| Region in which to define de parameter. When it is None, it
| indicates that 'quantity' has the same shape as the simulated
| image.
|
| set_constant(self, parameter, constant, region=None)
| Set the value of a particular parameter to a constant value.
|
| The parameter can be any of VALID_PARAMETERS. The constant
| value can be employed for all pixels or in a specific region.
|
| Parameters
| ----------
| parameter : str
| CCD parameter to set. It must be any of VALID_PARAMETERS.
| constant : Quantity or float
| Constant value for the parameter.
| region : SliceRegion2D or None
| Region in which to define de parameter. When it is None, it
| indicates that 'value' should be set for all pixels.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables
|
| __weakref__
| list of weak references to the object
Simple usage#
Define image basic parameters (dimensions, BITPIX)
naxis1, naxis2 = 5, 5
bitpix = 16
Each instance of the SimulateCCDExposure class becomes an image generator with the specified properties.
generator = tea.SimulateCCDExposure(
naxis1=naxis1,
naxis2=naxis2,
bitpix=bitpix
)
The generator we have just created contains information about the image dimensions and the BITPIX value, but there are still many attributes left undefined:
generator
SimulateCCDExposure(
naxis1=5,
naxis2=5,
bitpix=16,
bias=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
gain=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] electron / adu>,
readout_noise=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
dark=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
flatfield=array([[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]]),
data_model=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
seed=None,
)
If we try to use the generator as defined so far to create a bias image, we should encounter an error message.
exposure_bias = generator.run(imgtype='bias')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[6], line 1
----> 1 exposure_bias = generator.run(imgtype='bias')
File /opt/hostedtoolcache/Python/3.12.12/x64/lib/python3.12/site-packages/teareduce/simulateccdexposure.py:589, in SimulateCCDExposure.run(self, imgtype, method, seed)
587 # BIAS and Readout Noise
588 if np.isnan(self.bias.value).any():
--> 589 raise ValueError("The parameter 'bias' contains NaN")
590 if np.isnan(self.readout_noise.value).any():
591 raise ValueError("The parameter 'readout_noise' contains NaN")
ValueError: The parameter 'bias' contains NaN
We can see, then, that to generate a BIAS image we need to construct a generator that includes this information. For example, we can define the generator by specifying, in addition to the dimensions and BITPIX, the bias signal and the readout noise.
generator = tea.SimulateCCDExposure(
naxis1=naxis1, naxis2=naxis2, bitpix=bitpix,
bias=np.ones((naxis2, naxis1))*1000*u.adu,
readout_noise=5*u.adu
)
generator
SimulateCCDExposure(
naxis1=5,
naxis2=5,
bitpix=16,
bias=<Quantity [[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.]] adu>,
gain=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] electron / adu>,
readout_noise=<Quantity [[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.]] adu>,
dark=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
flatfield=array([[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]]),
data_model=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
seed=None,
)
We can then generate a simulated BIAS image using the method run(imgtype='bias'):
exposure_bias = generator.run(imgtype='bias')
The result is an object of type SimulatedCCDResult, which contains not only the simulated image but also all the information used to define the generator that was employed.
type(exposure_bias)
teareduce.simulateccdexposure.SimulatedCCDResult
exposure_bias
SimulatedCCDResult(
data=array([[1006.41310634, 999.89282835, 997.47739168, 1003.0014571 ,
1003.03928802],
[ 997.6205595 , 1005.68069342, 997.11808332, 989.94005427,
996.35279372],
[ 995.19625567, 1002.12071912, 1003.26954726, 999.41479604,
1013.95074569],
[ 999.91572402, 990.75529148, 996.14262845, 994.66398263,
1003.76820732],
[ 995.15649853, 993.78725863, 1000.87915961, 1000.36789148,
994.96179569]]),
unit=Unit("adu"),
imgtype='bias',
method='poisson',
origin=SimulateCCDExposure(
naxis1=5,
naxis2=5,
bitpix=16,
bias=<Quantity [[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.],
[1000., 1000., 1000., 1000., 1000.]] adu>,
gain=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] electron / adu>,
readout_noise=<Quantity [[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.],
[5., 5., 5., 5., 5.]] adu>,
dark=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
flatfield=array([[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]]),
data_model=<Quantity [[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan],
[nan, nan, nan, nan, nan]] adu>,
seed=None,
),
seed=None,
)
The .data attribute contains the NumPy array with the simulated image.
type(exposure_bias.data)
numpy.ndarray
tea.imshowme(exposure_bias.data, ds9mode=True)
plt.tight_layout()
Documentation pending update from this point