Metadata-Version: 2.5
Name: solvephase
Version: 0.2.0
Summary: Fast, GPU-optional phase retrieval for adaptive optics, optical metrology and coherent imaging.
Project-URL: Homepage, https://github.com/jacotay7/solvephase
Project-URL: Documentation, https://jacotay7.github.io/solvephase/
Project-URL: Repository, https://github.com/jacotay7/solvephase
Project-URL: Issues, https://github.com/jacotay7/solvephase/issues
Project-URL: Changelog, https://github.com/jacotay7/solvephase/blob/main/CHANGELOG.md
Author-email: Jacob Taylor <jacobataylor7@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: adaptive-optics,coherent-diffraction-imaging,gerchberg-saxton,gpu,phase-diversity,phase-retrieval,wavefront-sensing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: aobasis>=2.0
Requires-Dist: aocore>=0.1
Requires-Dist: numpy>=1.23
Requires-Dist: scipy>=1.10
Requires-Dist: threadpoolctl>=3.0
Provides-Extra: cuda12
Requires-Dist: cupy-cuda12x[ctk]>=13.0; extra == 'cuda12'
Provides-Extra: cuda13
Requires-Dist: cupy-cuda13x[ctk]>=13.6; extra == 'cuda13'
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: matplotlib>=3.7; extra == 'dev'
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.5; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
Provides-Extra: fits
Requires-Dist: astropy>=5.0; extra == 'fits'
Provides-Extra: gpu
Requires-Dist: cupy-cuda12x[ctk]>=13.0; extra == 'gpu'
Provides-Extra: interop
Requires-Dist: getframes>=2.2; extra == 'interop'
Requires-Dist: pyturb>=1.2; extra == 'interop'
Provides-Extra: plot
Requires-Dist: matplotlib>=3.7; extra == 'plot'
Provides-Extra: test
Requires-Dist: pytest-cov>=4.0; extra == 'test'
Requires-Dist: pytest-timeout>=2.0; extra == 'test'
Requires-Dist: pytest>=7.0; extra == 'test'
Provides-Extra: validation
Requires-Dist: hcipy>=0.6; extra == 'validation'
Requires-Dist: matplotlib>=3.7; extra == 'validation'
Description-Content-Type: text/markdown

# solvephase

[![CI](https://github.com/jacotay7/solvephase/actions/workflows/ci.yml/badge.svg)](https://github.com/jacotay7/solvephase/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/solvephase.svg)](https://pypi.org/project/solvephase/)
[![Python](https://img.shields.io/pypi/pyversions/solvephase.svg)](https://pypi.org/project/solvephase/)
[![Docs](https://img.shields.io/badge/docs-jacotay7.github.io%2Fsolvephase-indigo.svg)](https://jacotay7.github.io/solvephase/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

**Documentation: [jacotay7.github.io/solvephase](https://jacotay7.github.io/solvephase/)**

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

<p align="center">
  <img src="examples/solvephase_showcase.webp" width="900" alt="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 &amp; Furious) on one clock, with a live error-versus-time chart and a gallery of CDI, coded-diffraction and TIE reconstructions.">
</p>

`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

```bash
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

```python
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:

```python
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](https://jacotay7.github.io/solvephase/choosing/)**
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](https://github.com/jacotay7/aobasis), realistic aberrations from
  [pyturb](https://github.com/jacotay7/pyturb), and detector frames from
  [getframes](https://github.com/jacotay7/getframes).

## Benchmarks

See the [benchmarks page](https://jacotay7.github.io/solvephase/benchmarks/)
and the versioned artifacts in [`benchmarks/artifacts`](benchmarks/artifacts).

Same problem, same data, on an Intel i7-10700 and an entry-level NVIDIA
Quadro P620 ([artifacts](benchmarks/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](https://jacotay7.github.io/solvephase/validation/).

## Development

```bash
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](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md).

## License

MIT; see [LICENSE](LICENSE).
