Skip to main content

getframes

CI PyPI Python Docs License: MIT

Documentation: jacotay7.github.io/getframes

Realistic synthetic camera frames for scientific imaging pipelines.

Animated detector showcase: a CCD, EMCCD, sCMOS and C-RED One eAPD each simulated in the regime it is built for — deep-sky, AO wavefront sensing, wide-field, and near-infrared CDS — with live throughput.

getframes generates the frames a real detector would have produced: the full photon → electron → ADU signal path for CCD, CMOS, EMCCD, eAPD and sCMOS sensors, with auditable noise physics (read noise, dark current, shot noise, fixed-pattern non-uniformity, a unified stochastic gain stage, clock-induced charge, nonlinearity, cosmic rays). It produces dark, bias and flat frames, and renders star fields through a PSF and telescope into a realistic science frame — so you can build and validate image-processing pipelines against ground truth. It runs on NumPy by default and switches to CUDA (via CuPy) with a single argument.

Install

pip install getframes            # CPU (NumPy + SciPy + astropy)
pip install 'getframes[gpu]'     # + CuPy for CUDA 12.x
pip install -e '.[dev]'          # from a clone, for development

Quickstart

import getframes as gf

cam = gf.Camera.from_preset("andor_ikon_m934")  # 21 presets, or your own CameraConfig
frame = cam.dark_frame(exposure=60.0, temperature=-60.0, seed=0)

frame.data  # (1024, 1024) array of ADU
frame.stats()  # {'mean': ..., 'median': ..., 'std': ..., 'min': ..., 'max': ...}
frame.metadata  # camera/exposure/temperature provenance

scene = gf.Scene(  # render a sky, then expose it
    shape=(256, 256),
    optics=gf.Telescope(
        aperture_diameter_m=2.5,
        throughput=0.3,
        plate_scale_arcsec_per_pixel=0.4,
        band=gf.Bandpass.johnson("V"),
    ),
    psf=gf.MoffatPSF(fwhm_arcsec=1.1, beta=3.0),
    sources=[gf.PointSource(x=128, y=128, magnitude=20.0)],
    sky=gf.Sky(surface_brightness_mag_arcsec2=21.0),
)
frame = cam.with_config(resolution=(256, 256)).observe(scene, exposure=300.0, seed=0)

import cupy as cp  # and the same path on a GPU

cam = gf.Camera.from_preset("andor_ocam2k", device="gpu", precision="float32")
rate = cp.full(cam.resolution, 2.0e6, dtype=cp.float32)  # photons/s/pixel
frame = cam.expose(rate, exposure=1.0e-3, seed=0)  # CuPy ADU, no host copy

See Getting started for the full walkthrough, Observing scenes for sources, PSFs and telescopes, Camera presets for the preset library, and The noise model for the physics behind every stage.

Benchmarks

Warm bulk-frame throughput on an AMD Ryzen 9 9950X3D and an NVIDIA RTX 5090 (float32, truth enabled, persistent camera, device-resident input/output, no host transfers). The raw artifact and its invocation are versioned with the benchmarks:

Workflow Native shape CPU (frames/s) GPU (frames/s) Speedup
Pyramid WFS CMOS 80×80 5,240 11,514 2.20×
Shack-Hartmann WFS CMOS 160×160 1,386 11,471 8.27×
OCAM2K EMCCD 240×240 357 8,045 22.53×
SAPHIRA eAPD 256×320 280 7,497 26.74×
Large science CMOS 1024×1024 31 1,453 47.21×

Higher is better; CUDA was synchronized around every timed region and construction was excluded. Even the smallest case reaches about 2×, while larger arrays and gain-stage detectors expose much more parallel work. Reproduce the table with

python benchmarks/bench_devices.py --seconds 2 --warmup 10 --device both
python benchmarks/run.py                    # the CPU hot-path sweep

See the full snapshot and the GPU guide for the methodology.

Features

  • Five detector families — CCD, CMOS, EMCCD, eAPD and sCMOS, from a library of sourced presets (andor_ikon_m934, andor_ocam2k, leonardo_saphira, first_light_imaging_cred_one, andor_marana_4_2b_11, zwo_asi2600mm, …) or any CameraConfig you define.
  • Auditable noise physics — dark current vs. temperature, shot noise, a unified stochastic gain stage (EM and avalanche) with realistic excess noise, clock-induced charge, per-pixel sCMOS read noise, polynomial nonlinearity, saturation and quantisation, each a small documented pure function in the noise model.
  • Detector realism — CTI, blooming, IPC, kTC/reset noise, multi-amplifier readout, cosmic-ray tracks, defect and structured-bias maps, vignetting and radial distortion.
  • Fixed patterns that behave like silicon — PRNU, DSNU, hot pixels, defects and amplifier structure are keyed on fixed_pattern_seed, so they repeat in every frame and are genuinely removable by a master frame.
  • Scenes — point, extended and catalog sources, Gaussian/Moffat/Airy/array PSFs, a Telescope with Vega (Johnson) and AB (ugriz, Gaia, 2MASS) bandpasses, extinction, graybody thermal background, WCS pixel↔world, and light curves.
  • Calibration & ground truth — master bias/dark/flat builders and a calibrate reduction that closes the raw → reduced → truth loop.
  • Observations — Observation drives time series with jitter, drift, dither and persistence, carrying per-frame truth.
  • Spectral mode (opt-in) — QE curves, relative or absolute SEDs, transmission products and wavelength-resolved exposure; see Spectral mode and Radiometry & the infrared.
  • Analysis on real data too — aperture sums, centroids, photon-transfer curves, independent-stack characterization, and reset-aware nondestructive-ramp analysis run on measured detector frames as readily as on simulated ones.
  • Scale & datasets — a float32 fast path, vectorised multi-source rendering, a streaming raw+truth dataset generator and a getframes CLI; see Scale & datasets.
  • GPU-optional — every camera takes device="gpu" (CuPy) and keeps the detector path and truth arrays device-resident. CPU and GPU have independent RNG streams, so a seed repeats exactly on a fixed backend while parity across backends means matching statistics, not identical pixels.
  • Reproducible and typed — all randomness flows through a camera-owned seeded generator, never global state; mypy --strict passes; every public name is frozen under SemVer as of 2.0.
  • Validated — noise models are checked against published forms in CI; see Validation.

See the API reference for every public function and class, the runnable examples for PTC, exposure planning, AO limiting magnitude, transit photometry and detector realism, and the roadmap for what is next.

Contributing

Contributions — especially new camera presets — are welcome. See CONTRIBUTING.md. Run the checks locally with:

ruff check . && ruff format --check . && mypy && pytest

License

MIT — see LICENSE.

Metadata

Release files for getframes 2.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for getframes 2.2.0
File Size Uploaded
getframes-2.2.0.tar.gz 6.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for getframes 2.2.0
File Interpreter ABI Platform
getframes-2.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 7.1 MB

Release files / getframes-2.2.0.tar.gz

Download URL getframes-2.2.0.tar.gz
Size 6.9 MB
Tags Source
SHA-256 checksum
How to use checksums
d1017189222ce812ad3a95f7562155a9c04bbfa5011a1f1c440d8002adf9d845
BLAKE2b-256 checksum
How to use checksums
db5b88a9c73fd63078f3b94dfdb5340ff69e47a1dc64d79d56e3aee0bda9b8e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / getframes-2.2.0-py3-none-any.whl

Download URL getframes-2.2.0-py3-none-any.whl
Size 154.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
922a8369b45511e7d9e119ba69fccf79e8e15d579c4865314453cf1680553925
BLAKE2b-256 checksum
How to use checksums
3c34a8798bc9992c13663f7d60696406c02424548c30bdea2426ca5e01788719
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.2.0 This release

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page