Skip to content

Import generic optics helpers from aocore - #9

Merged
jacotay7 merged 1 commit into
mainfrom
refactor/use-aocore
Oct 7, 2026
Merged

jacotay7 merged 1 commit into
mainfrom
refactor/use-aocore

Conversation

@jacotay7

@jacotay7 jacotay7 commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Summary

aocore owns the AO stack's conventions and its generic optics primitives. CONVENTIONS.md §9 says consumers import them rather than re-implement them. This PR moves makewfs onto them and makes aocore>=0.1.2,<0.2 a core dependency. It was previously in the dev extra. makewfs already requires Python >= 3.10, which matches aocore.

Replaced

makewfs local code now uses
api._ARCSEC_PER_RADIAN = 206264.806… (plate scale) aocore.RAD_TO_ARCSEC (same value)
math.radians(x / 3600) in source.py (field angle, angular kernel, FWHM) x * aocore.ARCSEC_TO_RAD
(arange(n) - (n-1)/2) in wavefront._coordinates, the SH field-stop mask and the DFT detector grid aocore.centered_coordinates (scaled on the backend in the working dtype)
phase * λ / 2π for phase input aocore.phase_to_opd
2π · opd / λ in the SH and pyramid phasors aocore.opd_to_phase
general-factor branch of sampling.block_sum aocore.block_sum

makewfs.sampling.block_sum keeps its public signature, error messages and factor-two fast path. aocore has no such fast path, and factor 2 is the common SH oversampling.

Kept local, and why (each module docstring now says so)

  • pupil.make_pupil: aocore.Pupil cannot express the configured geometry. That geometry has angular-wedge spiders (width_fraction of π), square-grid segment gaps, pupil_rotation_deg and rectangular grids, and it is built on the selected CuPy/NumPy backend in the working dtype.
  • backend.ArrayBackend and its centred FFT helpers: the sensors choose a dtype per array, pass FFT workers and overwrite_x, and need ndimage helpers (map_coordinates, convolve, gaussian_filter). aocore.Backend has one precision per backend and its own worker policy. The centred FFTs use the fftshift convention internally, and the engines convert to CONVENTIONS 1.3 centring, which tests/test_conformance.py checks.
  • Quadrature offsets ((i + 0.5)/s - 0.5, used for pupil supersampling and the lenslet fill factor): these are sub-pixel sample offsets, not a coordinate grid.
  • Metadata wfs_input_opd_rms_m: this is a whole-input-grid quadratic mean with piston included, reduced on the device. aocore.rms is pupil-weighted, removes piston and runs on the host, so it is a different quantity. It is unchanged here (see below).
  • Validation and example centroids: validation/run.py and examples/keck_haka keep their batched, index-origin centroids so checked-in artifacts stay comparable.

Behaviour

No CONVENTIONS violation was found, so the physics is unchanged. I rendered every examples/configs/*.toml on main and on this branch with the same random OPD:

  • float32 (as shipped): bit-for-bit identical;
  • forced to float64: max relative difference ≤ 6e-16. This is rounding from the changed operation order in the angle and phase conversions and, for factors above two, in binning.

Public names are unchanged. tests/test_conformance.py now imports aocore directly instead of importorskip.

Docs

CHANGELOG (Unreleased), AGENTS.md (product boundary and code organisation), README and docs/units-and-coordinates.md are updated.

Test plan

Local 3_13 conda env:

  • ruff check . and ruff format --check .
  • python -m mypy
  • pytest --cov: 208 passed, coverage 92 %. The 2 failures in tests/test_oopao_validation.py are pre-existing; they fail identically on main (local OOPAO environment).
  • pytest -m gpu on a Quadro P620: 17 passed
  • python benchmarks/run.py --representative and check_regression.py: OK
  • validation/run.py, mkdocs build --strict and python -m build all succeed

🤖 Generated with Claude Code

aocore owns the stack's coordinates, angle constants, OPD/phase conversion
and pixel binning (CONVENTIONS.md section 9). makewfs now imports them:
centered_coordinates for the pupil, field-stop and DFT detector grids,
ARCSEC_TO_RAD/RAD_TO_ARCSEC for source angles and the plate scale,
opd_to_phase/phase_to_opd for phase input and the sensor phasors, and
block_sum behind makewfs.sampling.block_sum, which keeps its signature,
messages and factor-two fast path. aocore>=0.1.2,<0.2 becomes a core
dependency.

The pupil masks, ArrayBackend and its fftshift-convention centred FFTs stay
local because aocore has no equivalent; their docstrings say why. Float32
example renders are bit-identical and float64 renders differ only by
rounding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jacotay7
jacotay7 merged commit ba51a8e into main Oct 7, 2026
12 checks passed
@jacotay7
jacotay7 deleted the refactor/use-aocore branch October 7, 2026 02:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant