Quick start
This page walks through the core workflow in a few minutes. Everything below
uses the single public entry point, simulate_field(), or the
equivalent command line.
The mental model
One call runs the whole pipeline:
(RA, Dec) ──► Gaia DR3 query (catalog.py)
──► counts/s per star (starflux.py, via wcc_etc)
──► oversampled PSF (psf.py: Airy or Zemax defocus)
──► scene rendering (render.py: sub-pixel placement)
──► noise + digitization (render.py: Poisson/sky/dark/read, ADU)
──► SimulatedField (image + satmask + catalog + WCS)
──► FITS (fitswriter.py: SCI/SATMASK/CAT/CLEAN)
1. Simulate a field
from wcc_sim import simulate_field
field = simulate_field(
291.0, 44.5, # pointing RA, Dec [deg, ICRS]
sensorfilter="zwo:r", # Sony IMX455 + r filter
focus=1, # +1 wave of defocus (0 = in focus, 2 = +2 waves)
exptime=90, # seconds
seed=42, # reproducible noise
output="field_1wave.fits" # write FITS (optional)
)
The first run performs a Gaia DR3 cone search sized to the detector footprint
(pass cache_dir="gaia_cache" to reuse it offline afterwards). The full
9568×6380 px array takes ~11 s; pass shape=(1024, 1024) for a quick look.
2. Inspect the result
simulate_field() returns a SimulatedField:
field.image_adu # digitized image [ADU], what a real frame looks like
field.image_e # same image in electrons, pre-ADC
field.image_clean # noiseless source-only image [e-]
field.saturation_mask # bool per pixel: full-well or ADC saturated
field.wcs # astropy TAN WCS
field.catalog # Gaia table + x, y, spt, rate_e_s, in_image, saturated
field.params # every input + derived quantity (gain, sky rate, ...)
import matplotlib.pyplot as plt
from astropy.visualization import simple_norm
plt.imshow(field.image_adu, origin="lower",
norm=simple_norm(field.image_adu, "asinh", percent=99.5),
cmap="gray")
3. Or use the command line
The same simulation from the shell:
wcc-sim --ra 291.0 --dec 44.5 --sensorfilter zwo:r --focus 1 \
--exptime 90 --seed 42 -o field_1wave.fits
See Command-line interface for every option and a cookbook of common invocations.
4. Read the FITS output back
from astropy.io import fits
from astropy.table import Table
with fits.open("field_1wave.fits") as hdul:
hdul.info() # SCI, SATMASK, CAT, CLEAN
sci = hdul["SCI"].data # ADU image with WCS in the header
sat = hdul["SATMASK"].data # uint8 saturation mask
cat = Table.read(hdul["CAT"]) # injected catalog
Where to go next
User guide — how each pipeline stage works and which knobs it exposes (PSF stamps, jitter, noise model, saturation, FITS layout).
Tutorials — runnable notebooks, from a first quick look to photometric closure and astrometric verification.
API reference — the full API reference.