PSFs and image simulation

wcc-etc can render a realistic detector image of the scene, including the point-spread function, telescope jitter, sky background, Poisson and read noise, and per-pixel saturation.

PSF models

All PSF models subclass PSFSource and implement render(ctx) and cache_key():

Class

Description

AiryPSF

Diffraction-limited Airy disk computed for the sensor’s wavelength, plate scale, and aperture. The default when no PSF is given.

DefocusPSF

A resampled Zemax Huygens PSF loaded from disk. Two defocus files ship with the package (see below).

CustomPSF

An arbitrary PSF from a NumPy array or a file, with a given source pixel scale (src_um_per_pix).

Bundled defocus PSFs

Two Zemax Huygens PSFs (500 nm, 4 µm source pixels) ship with the package and are exposed as path constants:

from wcc_etc import DefocusPSF, DEFOCUS_1WAVE_PATH, DEFOCUS_2WAVE_PATH

psf1 = DefocusPSF(DEFOCUS_1WAVE_PATH)   # 1-wave defocus
psf2 = DefocusPSF(DEFOCUS_2WAVE_PATH)   # 2-wave defocus

Custom PSFs

import numpy as np
from wcc_etc import CustomPSF

array = np.load("my_psf.npy")
psf = CustomPSF(array, src_um_per_pix=4.0)

Automatic PSF selection by focus level

When you build a simulation with from_sensorfilter(), an appropriate default PSF (in-focus vs. defocused) is selected for that sensor:filter and used whenever you omit psf= in the SNR / image methods.

Simulating an image

Use ImageSimulator:

from wcc_etc import ImageSimulator, AiryPSF

imsim = ImageSimulator.from_sensor_and_scene("sony:r", scene, npix=300)
img = imsim.simulate(
    time=30,
    psf=AiryPSF(),
    jitter_sigma_mas=None,    # None → use the telescope's jitter
    add_noise=True,
    seed=0,                   # reproducible noise
)

simulate returns a SimulatedImage with:

Attribute / method

Description

image_e

Noisy image in electrons.

image_clean

Noiseless image (mean electrons).

saturation_mask

Boolean mask of saturated pixels.

to_adu()

Image converted to ADU using the sensor gain / bit depth.

to_fitsimg()

A FitsImg for aperture photometry and plotting.

plot_image()plot_encircled_energy()

Convenience plotting dispatchers (see Plotting).

Grid size and oversampling

npix sets the rendered grid and must be large enough to contain the PSF; oversample controls sub-pixel rendering before binning to detector pixels. The default npix used inside the SNR path (128) contains the bundled defocus PSFs for the current sensors, but very small pixels or stronger defocus may need a larger value.

Telescope jitter

Pointing jitter is applied as a Gaussian blur with standard deviation jitter_sigma_mas. Passing None uses the telescope’s configured jitter_sigma (10 mas for Lazuli by default); pass a value to override it for a single call.