Simulation
- wcc_etc.simulation.calculate_bg_normalization_magnitude(bg_surface_brightness, psf_area)[source]
Convert the Background Surface Brightness into the total magnitude given the PSF area.
The area needs to be in square arcseconds since the typical definition of Surface Brightness is in units of magnitudes per arcseconds^2.
- class wcc_etc.simulation.Simulation(telescope, sensor, scene=None, time=90, r_aper_mas=70, n_reads=1, meta={})[source]
Bases:
_MetaHolder_A class to manage and run image exposure simulations.
- Variables:
- classmethod from_config(config)[source]
Initialize a Simulation from a configuration dictionary.
- Parameters:
config (dict) – Configuration dictionary containing ‘telescope’, ‘sensor’, and ‘scene’ keys.
- Returns:
The initialized Simulation object.
- Return type:
- classmethod from_sensor(sensor, scene=None)[source]
Naming simplification of from_sensor_and_scene().
- classmethod from_sensor_and_scene(sensor, scene)[source]
Create a Simulation from a sensor specification and a scene.
- classmethod from_sensorfilter(sensorfilter, scene)[source]
Create a Simulation from a sensorfilter label, auto-selecting the PSF.
The label must be a key in sensor_info (e.g. ‘zwo:r’, ‘zwo:r+1’, ‘qcmos:bb’). The PSF matching the sensor’s focus_level is stored as _default_psf; get_image_snr uses it when no psf= argument is given.
- Parameters:
- Return type:
- update(**kwargs)[source]
Update simulation parameters.
The keyword should in principle have the following structure scene__source__mag = 21 to change the self.scene.source.mag parameter to 21.
To simplify the use, if the name has no ambiguity, you can skip the first structure elements. For instance, only scene__ has a source__mag. So source__mag=21 will automatically be associated with scene__source__mag=21. Same would work, for instance for dark_current: only detector__ has a dark_current mutable_parameter. However mag=21 is not clear enough, as scene__source__mag, scene__background__mag or scene__host__mag exist.
- Parameters:
**kwargs – Parameters to update. Can use double-underscore for sub-elements.
- update_telescope(**kwargs)[source]
Update telescope parameters.
- Parameters:
**kwargs – Telescope parameters.
- update_sensor(**kwargs)[source]
Update sensor parameters.
- Parameters:
**kwargs – Sensor parameters.
- get_countrates(scene=None, band=None, units='adu/s', as_dict=True)[source]
DEPRECATED (Airy, in-aperture). Use _count_rate_components for the 2D path or get_image_snr. Retained for the analytic Airy methods.
- get_signal_and_variance(time=None, units='e-', n_reads=None)[source]
Get the signal and total variance for a given exposure time.
- Parameters:
time (float or Quantity, optional) – Exposure time. Defaults to self.meta[‘time’].
units (str, optional) – Units of the signal (‘e-’, ‘adu’). Default is “e-“.
n_reads (int, optional) – Number of coadded frames; the read-noise variance is incurred n_reads times. Defaults to self.meta[‘n_reads’] (or 1).
- Returns:
(source_signal, total_variance)
- Return type:
- get_peak_pixel(time=None, units='adu', n_reads=None, *, psf=None, jitter_sigma_mas=None, npix=128, oversample=11)[source]
Brightest-pixel value for the actual (possibly defocused) PSF.
Peak = source_rate_total * peak_pixel_fraction + sky_per_pix + dark, where peak_pixel_fraction is the brightest pixel of the rendered PSF (psf_norm.max()), so defocused configs are handled correctly. psf defaults to _default_psf (set by from_sensorfilter), else AiryPSF. Saturation is per-frame (per-frame time = time / n_reads). Linear in time, so scalar or array time both work.
- is_saturated(time=None, n_reads=None, *, psf=None, jitter_sigma_mas=None, npix=128, oversample=11)[source]
Whether the brightest pixel (ADU) reaches sensor.adc_max, per frame, for the actual (possibly defocused) PSF. See get_peak_pixel.
Note: this tests the ADC clip (peak ADU incl. bias >= adc_max). The image-based saturation_mask_from_image_e additionally flags well-depth (electron) saturation and does not add bias; the two agree when the ADC limit binds and bias is small (the usual case). A full reconciliation of the two criteria (well-depth + bias handling) is a known follow-up.
- peak_pixel_fraction(psf=None, jitter_sigma_mas=None, npix=128, oversample=11)[source]
Fraction of total source flux in the brightest detector pixel for the actual (possibly defocused) PSF.
PSF-aware replacement for the retired psf_profile[‘peak_pixel_fraction’] (which was in-focus-Airy only). psf defaults to _default_psf if set, else AiryPSF().
- get_image_snr(time=None, mags=None, psf=None, r_aper_mas=None, ee_frac=None, optimize=False, jitter_sigma_mas=None, n_reads=None, npix=128, oversample=11, warn=True)[source]
PSF-aware aperture signal-to-noise ratio.
Unlike get_snr_airy (the analytic Airy-disk approximation), this renders the given PSF (default AiryPSF) on the detector grid and computes the SNR for a circular aperture. get_snr now delegates to this method; the in-focus default-aperture case reproduces get_snr_airy to within ~1%. Aperture precedence: optimize > r_aper_mas > ee_frac; if none is given, the Simulation’s r_aper_mas is used.
- Parameters:
time (float, array_like, or Quantity, optional) – Exposure time(s) in seconds (bare floats are interpreted as seconds). Defaults to meta[‘time’]. A scalar yields a dict of Python float/int; an array yields a dict of equal-length ndarrays.
mags (float, array_like, or None, optional) – Source magnitude(s) to evaluate at, sweeping the source brightness relative to its set magnitude (host/background/dark/read held fixed). None (default) leaves the source unchanged. A scalar yields a dict of floats; a 1-D array yields a dict of arrays over magnitude. time and mags may not both be arrays. Requires a scene with a source.
psf (PSFSource, optional) – PSF model. If None, uses _default_psf (set by from_sensorfilter) when available, otherwise falls back to AiryPSF().
r_aper_mas (float, optional) – Fixed aperture radius (mas).
ee_frac (float, optional) – Aperture enclosing this fraction of the PSF.
optimize (bool, optional) – If True, use the radius that maximizes SNR.
jitter_sigma_mas (float, optional) – Override the telescope jitter (mas).
npix (int, optional) – Render grid size and oversampling. npix must be large enough to contain the PSF; the default (128) contains the bundled defocus PSFs for the current sensors, but very small pixels or stronger defocus may need a larger value.
oversample (int, optional) – Render grid size and oversampling. npix must be large enough to contain the PSF; the default (128) contains the bundled defocus PSFs for the current sensors, but very small pixels or stronger defocus may need a larger value.
warn (bool, optional) – If True (default), emit a warning when any pixel in the rendered per-frame image saturates. The ‘n_saturated’/’saturated’ values are returned regardless of this flag.
- Returns:
‘snr’, ‘signal_e’, ‘noise_e’, ‘enclosed_fraction’, ‘r_aper_mas’, ‘n_pix’, plus saturation info ‘n_saturated’ (count of pixels in the rendered per-frame image at or above full well / ADC clip) and ‘saturated’ (bool). Values are Python float/int/bool for scalar time and mags, or ndarrays (n_pix/n_saturated as int, saturated as bool) when time or mags is an array.
- Return type:
- get_image_exptime_for_snr(snr, psf=None, r_aper_mas=None, ee_frac=None, optimize=False, jitter_sigma_mas=None, n_reads=None, npix=128, oversample=11, warn=True)[source]
Exposure time (s) to reach a target SNR on the PSF-aware path.
Inverse of get_image_snr. Aperture precedence: optimize > r_aper_mas > ee_frac; if none is given the Simulation’s r_aper_mas is used. Note optimize here picks the radius that reaches the target SNR fastest (minimum time), the inverse of get_image_snr’s max-SNR optimize. Returns a dict {‘time_s’, ‘snr’, ‘r_aper_mas’, ‘enclosed_fraction’, ‘n_pix’, ‘n_saturated’, ‘saturated’}.
- Parameters:
- get_snr(time=None, psf=None, r_aper_mas=None, ee_frac=None, optimize=False, jitter_sigma_mas=None, n_reads=None, npix=128, oversample=11, warn=True)[source]
Signal-to-noise ratio via the 2D image simulation (PSF-aware default).
Delegates to get_image_snr; see it for parameter details and the returned dict. time may be a scalar or an array (returns a dict of arrays). For the legacy analytic Airy approximation use get_snr_airy (deprecated).
- Returns:
Same as get_image_snr: ‘snr’, ‘signal_e’, ‘noise_e’, ‘enclosed_fraction’, ‘r_aper_mas’, ‘n_pix’, ‘n_saturated’, ‘saturated’ (scalar values for scalar time, ndarrays for array time). Pass warn=False to silence the saturation warning.
- Return type:
- get_snr_airy(time=None, n_reads=None, warn=True)[source]
DEPRECATED analytic Airy-disk SNR approximation.
Use get_snr, which computes the SNR via the 2D image simulation.
- get_exptime_for_snr(snr, n_reads=None, warn=True)[source]
Exposure time (seconds, Quantity) to reach a target SNR on the analytic (Airy) path. Inverse of get_snr_airy. Returns inf*u.s if the source rate is 0.
- compute_psf_profile()[source]
Compute the PSF profile and associated metrics.
DEPRECATED: use psf_profile (the cached property) or the PSF-aware 2D path (get_image_snr / get_image_exptime_for_snr / get_peak_pixel).
- Returns:
Dictionary containing ‘wavelength’, ‘r_psf_mas’, ‘psf1d’, ‘ee’, ‘ee_at_aper’, ‘num_psf_pixels’, and ‘psf_area’.
- Return type:
- property scene
The Scene object.
- property telescope
The Telescope object.
- property sensor
The Sensor object.
- property meta
Combined metadata from simulation and components.
- property mutable_parameters
List of all mutable parameters (including sub-elements).
- property psf_profile
The calculated PSF profile.