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=None, 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, gain_mode=None)[source]
Create a Simulation from a sensor specification and a scene.
- classmethod from_sensorfilter(sensorfilter, scene, gain_mode=None)[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:
sensorfilter (str) – Label from sensor_info, format ‘kind:band’ (e.g. ‘zwo:r’, ‘zwo:r+1’, ‘qcmos:bb’). Only canonical labels are accepted; nicknames like ‘sony:r’ are not resolved here (use from_sensor_and_scene for those).
scene (Scene)
gain_mode (str, optional) – Gain mode for detectors that have several (qCMOS: ‘high’ or ‘low’).
- 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 = max over the per-frame clean image (_per_frame_clean_image_e): (source + unresolved contaminants) through the rendered PSF, plus extended profiles, sky, diffuse and dark, so defocused configs and an offset host are handled correctly. psf defaults to default_psf (diffraction-limited unless the simulation was built by from_sensorfilter). 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 of the clean per-frame image reaches sensor.saturation_e (min of full well and ADC clip after bias), for the actual (possibly defocused) PSF. See get_peak_pixel and Sensor.saturation_limit for which limit binds. Same threshold as psfsim.saturation_mask_from_image_e and ImageSimulator.simulate (#64).
- 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.
- extended_rate_image(psf_norm, ctx, comps=None)[source]
PSF-convolved e-/s/pix image of the profiled (extended) elements.
Each profile is rendered at the integer centre of a grid padded by
npix(rounded to even) and convolved withpsf_norminmode="same", whose kernel origin is that same integer centre (psfsim.grid_center). The host therefore lands wherever the PSF put the source –ctx.centeror the PSF class’s natural centre, odd or even grid – anddx/dyare offsets from the source. The padding lets light from just outside the detector grid convolve inward – no edge loss. Zeros when the scene has no extended element.
- 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, default_aperture decides (70 mas for the Airy PSF, optimized otherwise).
- Parameters:
time (float, array_like, or Quantity, optional) – Exposure time(s) in seconds (bare floats are interpreted as seconds). Defaults to meta[‘time’]. Must be finite and >= 0; zero time gives snr = 0. 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 (the focus-level PSF when built by from_sensorfilter, otherwise a diffraction-limited 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 default_aperture decides. 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:
psf (PSFSource, optional) – PSF model. If None, uses default_psf (the focus-level PSF when built by from_sensorfilter, otherwise a diffraction-limited AiryPSF).
warn (bool, optional) – If True (default), warn when the rendered image saturates at the solved time; ‘n_saturated’/’saturated’ are returned regardless.
- 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:
- plot(time, **kwargs)
SNR vs exposure time; see plotting.plot_snr.
- plot_peak_pixel(time, **kwargs)[source]
Peak pixel vs time with the saturation ceiling; see plotting.plot_peak_pixel.
- plot_exptime_for_snr(snr, **kwargs)[source]
Exposure time vs target SNR; see plotting.plot_exptime_for_snr.
- plot_snr_vs_aperture(radii, **kwargs)[source]
SNR vs aperture radius; see plotting.plot_snr_vs_aperture.
- 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.
- default_aperture(psf)[source]
Aperture mode used when a call gives no r_aper_mas/ee_frac/optimize.
Returns
(r_aper_mas, optimize): the Simulation’s ownr_aper_masif one was set; else 70 mas for anAiryPSF; elseoptimize=True, since the fixed Airy-core aperture holds only a few percent of a defocused PSF (#95).
- property default_psf
The PSF this simulation uses when no
psf=argument is given.from_sensorfiltersets this from the filter’s focus level (anAiryPSFfor0wave, aDefocusPSFfor1wave/2wave); every other construction path leaves it diffraction limited.
- property mutable_parameters
List of all mutable parameters (including sub-elements).
- property effective_wavelength
Photon-weighted effective wavelength of the bandpass times the source SED.
This is the wavelength the PSF is rendered at (see
wcc_etc.psfsim.AiryPSF). Unlikesensor.wavelength– the pivot wavelength, a property of the throughput curve alone – it moves with the colour of the source, which matters because the diffraction scale is linear in wavelength. Through the WCC broad band the pivot is 582 nm for every source, while the photons actually delivered average 541 nm for an O5V and 716 nm for an M5V; rendering the M5V PSF at the pivot overpredicts its central-pixel fraction by ~26% and so predicts premature saturation for red sources.Falls back to
sensor.wavelengthwhen the simulation carries no source spectrum. Cached, and invalidated byupdate/set_scene/set_sensor/set_telescope/resetlike the render caches.- Returns:
The effective wavelength, in nm.
- Return type:
Quantity
- polychromatic_psf(n_sub=7, base=None)[source]
A photon-weighted polychromatic PSF for this simulation’s band and source.
The monochromatic default (rendered at
effective_wavelength) already removes the colour bias in the PSF width; this goes further and coaddsn_subrenders across the band, so the wings and the diffraction ring structure are broadened the way a real broadband PSF is.- Parameters:
n_sub (int, optional) – Number of equal-photon-weight sub-bands. Default 7. Cost is linear in this; 5-9 is plenty for a broad optical band.
base (PSFSource, optional) – PSF rendered at each sub-band wavelength. Defaults to the simulation’s own default PSF (
AiryPSFunlessfrom_sensorfilterselected a defocused one).
- Returns:
Pass it as
psf=toget_image_snr/get_peak_pixel/peak_pixel_fraction/ImageSimulator.simulate.- Return type:
Examples
>>> sim.get_peak_pixel(10, psf=sim.polychromatic_psf())
- property psf_profile
The calculated PSF profile.