Skip to main content

pyturb

CI PyPI Python Docs License: MIT

Documentation: jacotay7.github.io/pyturb

Fast, GPU-optional atmospheric turbulence for adaptive optics.

Animated Keck atmosphere showcase: frozen flow, boiling, and on/off-axis LGS turbulence.

pyturb generates the optical path differences (OPD) that an adaptive-optics system sees through the atmosphere: full layered turbulence for a representative sky, with per-layer wind, frozen-flow time evolution, off-axis directions, and standard site profiles. It runs on NumPy by default and switches to CUDA (via CuPy) with a single argument.

Install

pip install pyturb            # CPU (NumPy + SciPy, aocore, aobasis)
pip install pyturb[cuda13]    # + CuPy for CUDA 13.x (with CUDA headers)
pip install pyturb[cuda12]    # + CuPy for CUDA 12.x (with CUDA headers)
pip install pyturb[cuda11]    # + CuPy 13.x for CUDA 11.x
pip install pyturb[accel]     # + Numba, faster CPU frozen flow

Pick the extra matching your driver's CUDA version (nvidia-smi shows it). If you install CuPy yourself and the first GPU call fails with "Failed to find CUDA headers", install the headers too (pip install "cupy-cuda12x[ctk]", or cupy-cuda13x[ctk]) or point CUDA_PATH at a CUDA toolkit.

Quickstart

import pyturb

atm = pyturb.Atmosphere.from_profile(
    "paranal-median", seeing=0.8, zenith_angle=30, diameter=8.0, n=512, seed=1
)
print(atm.r0, atm.theta0, atm.tau0)      # Fried param, isoplanatic angle, tau0

for t, opd in atm.frames(dt=1e-3, steps=200):
    ...                                   # (512, 512) OPD [m], frozen flow
# The default spectral engine is periodic: keep runs under atm.time_to_wrap
# (0.25 s here) or pass engine="extrude" for unbounded, non-periodic flow.

ensemble = atm.sample(256)                # (256, 512, 512) Monte-Carlo OPDs

atm = pyturb.Atmosphere.from_profile("paranal-median", seeing=0.8, device="gpu")
for t, opd in atm.frames(dt=1e-3, steps=200):
    ...                                   # cupy arrays; ~4,600 fps at 512^2 on an RTX 4060

See Quickstart for off-axis/tomography, boiling, LGS, non-periodic frozen flow, and the lower-level PhaseScreen/InfinitePhaseScreen building blocks; and Concepts for r0, L0, Cn², θ0 and τ0 if you're new to AO.

Arrays are indexed (y, x) — x along axis 1 (columns), y along axis 0 (rows) — the convention of aobasis, makewfs, solvephase and HCIPy; wind directions, off-axis (thx, thy) and Zernike modes all follow it. Upgrading from 1.x, whose x was axis 0? See Migrating to 2.0.

Benchmarks

Full 9-layer Paranal atmosphere, frames/s (Monte-Carlo: screens/s).

pyturb 1.1 on an RTX 4060 with an Arm (Neoverse-N1) host (artifact):

screen GPU spectral GPU opd(t=times) GPU extrude GPU Monte-Carlo
256² 6,451 27,510 1,174 33,292
512² 4,591 6,653 482 6,993
1024² 1,304 1,166 120 1,715

Spectral frames replay a captured CUDA graph, so they no longer depend on the host CPU's speed; opd(t=times) evaluates an offline time series in one batched transform.

pyturb 1.0.0 on an RTX 5090 and a 32-core x86 CPU (pyturb[accel]; before the 1.1 CUDA-graph and batching work, artifact):

screen GPU spectral GPU extrude GPU Monte-Carlo screens/s CPU spectral CPU extrude
256² 3,219 4,489 104,981 1,014 2,571
512² 3,133 1,733 29,789 283 324
1024² 1,492 602 5,970 70 62

The Monte-Carlo column is Atmosphere.sample(), the full 9-layer atmosphere. Layers that share an outer scale are drawn as one aggregate screen (their PSDs add exactly), so a uniform-L0 profile costs one FFT, not nine. All Monte-Carlo figures are batched, device-resident throughput (a batch of up to 64 kept on the GPU); a single call, or one that copies its result to the host, is lower. Measure your own machine with python -c "import pyturb; pyturb.benchmark()", or python benchmarks/bench_suite.py for the full per-use-case sweep. More hardware and the head-to-head against aotools, soapy and HCIPy: benchmarks/RESULTS.md and Comparison.

Features

  • Layered Atmosphere — named site profiles (paranal-median, mauna-kea, keck, las-campanas, HV 5/7, ...) or a custom Cn²(h) model, summed to pupil OPD with per-layer wind and airmass/zenith scaling.
  • Two frozen-flow engines — engine="spectral" (default): exact sub-pixel shift-theorem translation, all layers in one FFT, periodic. engine="extrude": Assémat–Wilson row extrusion, unbounded and non-periodic, read out by a fused CUDA kernel (GPU) or Numba kernel (CPU, with [accel]). FFT screens default to the pupil's size (fastest); pass oversample=2–4 when statistics across the whole pupil matter (tilt, low-order modes), since a pupil-sized periodic screen underestimates them.
  • Off-axis / tomography — atm.opd(t, directions=[...]) batches several guide-star directions through one call.
  • Boiling — temporal decorrelation on top of frozen flow (tau_boil, the outer-scale lifetime; finer scales boil faster, or every scale at one rate with boil_scaling="uniform"), rough (boil_model="ar1") or smooth in time ("ar2"); pyturb.theory.travel_decorrelation_time gives on-sky per-layer time constants from wind speed.
  • Scintillation — atm.pupil_field(...) propagates a star's light through the layers to the pupil (paraxial angular spectrum, aocore's propagator) at one or several wavelengths: the complex field, the weighted intensity and the OPD. pyturb.theory.scintillation_index (Roddier 1981) and scintillation_transfer are the references; atm.advance(dt) jumps boiling exactly between sparse frames, and pyturb.theory.gems_boil_time gives GeMS-calibrated outer-scale lifetimes.
  • Estimator statistics — pyturb.theory.covariance / Atmosphere.covariance: the space-time covariance and structure function the simulator draws from (frozen flow + boiling), for MMSE/predictive/Kalman design.
  • LGS cone effect — finite-range sodium beacon focal anisoplanatism (lgs_altitude).
  • Chromatic OPD — achromatic by default; dispersion="edlen"/"ciddor" for the dry-air/water-vapour term.
  • Diagnostics (pyturb.analysis) — Zernike decomposition, Noll (1976) mode variances, temporal PSD + power-law fit, angular decorrelation.
  • I/O — pyturb.save/pyturb.load for FITS (optional astropy) and .npz, with provenance metadata.
  • GPU-optional — every class takes device="gpu" (CuPy); the GPU path is statistically identical to CPU (validated against the same theory to numerical precision). A seed reproduces the same atmosphere on any CUDA GPU (pyturb's GPU stream is a counter-based Philox generator, independent of the device). CPU (NumPy PCG64) and GPU use different generators, so a given seed draws a different realisation on each backend — the guarantee is matched statistics, not a bit-for-bit copy.
  • Validated against theory — structure function, Zernike spectrum, temporal PSD and angular decorrelation checked against analytic predictions in CI; see Validation.

See the API reference for every public function and class, and Interop for recipes with HCIPy, poppy, and DM-fitting loops.

License

MIT

Metadata

Release files for pyturb 2.5.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 pyturb 2.5.0
File Size Uploaded Provenance Actions
pyturb-2.5.0.tar.gz 6.9 MB With provenance Details for pyturb-2.5.0.tar.gz

Built distribution (wheel)

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

Total release size: 7.1 MB

Release files / pyturb-2.5.0.tar.gz

Download URL pyturb-2.5.0.tar.gz
Size 6.9 MB
Tags Source
SHA-256 checksum
How to use checksums
7dbde6f4db8dd5102dde14770b03251158fb71adb82b595ddecbc9069fe277e2
BLAKE2b-256 checksum
How to use checksums
b386813e61814e9aeb2c6f31a621cb0c8127c2bdf153dccee3cd1c1d0330bd1e
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 18, 2026.

Transparency log

Release files / pyturb-2.5.0-py3-none-any.whl

Download URL pyturb-2.5.0-py3-none-any.whl
Size 153.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ac570dd37d6d1d782941d60180c80b2198d08977c32c35c92f9174a7c1bd5d4d
BLAKE2b-256 checksum
How to use checksums
727c1e626b84bf980a957bb24d0d7fbfdf644540cf82f359f77304e807ddd25c
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 18, 2026.

Transparency log

Security for pyturb 2.5.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pyturb-2.5.0.tar.gz

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 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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