solvephase
Documentation: jacotay7.github.io/solvephase
Fast, GPU-optional phase retrieval for adaptive optics, optical metrology and coherent imaging.
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)
| File | Size | Uploaded | |
|---|---|---|---|
| solvephase-0.2.0.tar.gz | 2.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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