Skip to main content

solvephase

CI PyPI Python Docs License: MIT

Documentation: jacotay7.github.io/solvephase

Fast, GPU-optional phase retrieval for adaptive optics, optical metrology and coherent imaging.

A race between every solvephase focal-plane method on the same aberrated VLT-like wavefront (Gerchberg-Saxton/Misell, modal and zonal maximum likelihood, retrieve(), extended-scene phase diversity, LIFT and Fast & Furious) on one clock, with a live error-versus-time chart and a gallery of CDI, coded-diffraction and TIE reconstructions.

solvephase recovers phase from intensity. It covers focal-plane wavefront sensing (Gerchberg–Saxton/Misell, maximum-likelihood modal and zonal retrieval, phase diversity with unknown extended objects, LIFT, Fast & Furious), coherent diffraction imaging (ER, HIO, DM, RAAR, RRR, ASR, HPR, OSS, shrinkwrap), generic measurement models (Wirtinger, truncated, amplitude and reweighted flows) and the transport-of-intensity equation, all behind one API. It runs on NumPy by default and on CUDA (CuPy) with one argument.

Install

pip install solvephase                 # CPU
pip install "solvephase[cuda12]"       # + CuPy for CUDA 12.x
pip install "solvephase[cuda13]"       # + CuPy for CUDA 13.x
pip install "solvephase[interop]"      # + pyturb atmospheres and getframes detectors

Quickstart

import solvephase as sp

pupil = sp.Pupil.vlt(128)  # 8 m, obscured, four vanes
model = sp.FocalPlaneModel(
    pupil, 1.65e-6, 64, sampling=2.0, diversity=sp.zernike_diversity(pupil, 4, [0.0, 0.4e-6])
)
truth = sp.random_aberration(pupil, 100e-9, n_modes=40, start=4, seed=1)
images = sp.simulate_images(model, truth, photons=1e6, background=10, read_noise=3, seed=2)

result = sp.retrieve(
    images, pupil, 1.65e-6, sampling=2.0, diversity=[0.0, 0.4e-6], read_noise=3.0, device="auto"
)
print(result.summary())  # converged in a handful of LM steps
result.opd, result.coefficients  # wavefront [m], Zernike [m RMS]

retrieve is robust by default. It explores with Levenberg–Marquardt on the amplitude metric from a flat start and from Gerchberg–Saxton, keeps the better fit, and polishes with the Poisson likelihood. For full control, use FocalPlaneProblem and solve (choose the basis, likelihood, nuisance parameters and optimizer). The other families are one call each:

sp.phase_diversity(model, images_of_extended_scene)  # unknown object
sp.LIFT(pupil, wavelength, 32, sampling=2.0).estimate(img)  # one astigmatic image
sp.FastAndFurious(pupil, wavelength, 64, sampling=2.0).step(img, dm_change)
sp.cdi(magnitudes, support, schedule="hio:500,er:100", starts=16, device="gpu")
sp.tie(stack, [-dz, 0, dz], pitch=pitch, wavelength=wavelength)

See Choosing an algorithm for a side-by-side comparison: images needed, requirements, measured speed, accuracy and capture range of every method.

Highlights

  • Exact derivatives everywhere. Every propagator (FFT, matrix Fourier transform, angular spectrum, coded diffraction) has an exact adjoint. Gradients and Gauss–Newton Jacobians are analytic, with no autodiff tape. Levenberg–Marquardt typically converges in 5–10 iterations.
  • Statistically efficient. Poisson + read-noise likelihoods, fitted flux, background and registration, masks for bad and saturated pixels. The estimator reaches the Cramér–Rao bound in the validation suite.
  • Physically complete. Broadband light, any sampling (including undersampled detectors), pixel integration, segmented apertures, KL priors, and DM influence-function bases.
  • Fast on CPU and GPU. Batched FFTs, matrix Fourier transforms on BLAS, batched multi-start CDI, and device-resident optimizers. Single precision reaches the same noise floor as double.
  • Validated. It matches HCIPy to machine precision and the analytic Airy normalization, and the validation suite checks its Cramér–Rao efficiency and capture range on every CI run.
  • Part of an AO toolchain. Modal bases come from aobasis, realistic aberrations from pyturb, and detector frames from getframes.

Benchmarks

See the benchmarks page and the versioned artifacts in benchmarks/artifacts.

Same problem, same data, on an Intel i7-10700 and an entry-level NVIDIA Quadro P620 (artifacts):

Task Baseline solvephase CPU solvephase GPU
Focal-plane retrieval, 128², 36 modes, 2 images (time to solution) HCIPy + SciPy L-BFGS-B: 8.5 s; least_squares: 5.3 s 0.46 s 0.14 s
Misell/GS, 128², iterations/s textbook NumPy: 156 268 1,493
CDI HIO, 256², iterations/s textbook NumPy: 252 794 2,957 (3,492 per start with 16 batched starts)
Broadband (5 λ) gradient, 256² — 67 ms 9 ms
TIE, 2048², 3 planes — 253 ms 33 ms

On the focal-plane problem every method reaches 0.12–0.19 nm RMS; solvephase gets there 11–18x faster on the CPU and 38–61x faster on the GPU.

Validation

python validation/validate.py checks solvephase against theory and an independent code and writes a report; see the validation page.

Development

pip install -e ".[dev,docs,interop,validation]"
python -m pytest -q                       # fast suite
python -m pytest -q --run-slow --run-gpu  # everything

See CONTRIBUTING.md and AGENTS.md.

License

MIT; see LICENSE.

Metadata

Release files for solvephase 0.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 solvephase 0.2.0
File Size Uploaded
solvephase-0.2.0.tar.gz 2.2 MB Details

Built distribution (wheel)

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

Total release size: 2.3 MB

Release files / solvephase-0.2.0.tar.gz

Download URL solvephase-0.2.0.tar.gz
Size 2.2 MB
Tags Source
SHA-256 checksum
How to use checksums
068385b0d2c3b8e691b7363079baa68dea27dbac250f8b1d1c5f84fca5ab60b6
BLAKE2b-256 checksum
How to use checksums
3055503fae2422a5730af6c4da098949724188071d3b3fb476e27c9559a246ed
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 7, 2026.

Transparency log

Release files / solvephase-0.2.0-py3-none-any.whl

Download URL solvephase-0.2.0-py3-none-any.whl
Size 118.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2319c43245d3c166541bd727a694e30e282c7fa071f3860fcdebae0ad2c29229
BLAKE2b-256 checksum
How to use checksums
24dde0c00371acfac4db4a4bb3fccd84e93f948be5b5b2ffa6c70ab673dfbcde
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 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.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