03b63ba03a
Full implementation of Laguerre-Gauss modal reconstruction for gyrotron beam diagnostics, per the approved design spec, plus tests, docs, and a runnable end-to-end example. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
224 lines
10 KiB
Markdown
224 lines
10 KiB
Markdown
# he11lib API Reference
|
||
|
||
`he11lib` reconstructs the Laguerre-Gauss (LG) modal content ("mode purity")
|
||
of a free-space-propagating gyrotron RF beam from a set of thermal (flux)
|
||
images taken at different distances from the output window.
|
||
|
||
See `examples/full_pipeline_example.py` for a runnable end-to-end
|
||
demonstration, and
|
||
`docs/superpowers/specs/2026-07-02-gyrotron-mode-purity-design.md` for the
|
||
full design rationale.
|
||
|
||
Every class/function below is exported from the top-level `he11lib` package
|
||
(e.g. `from he11lib import BeamReconstructor`), except where noted.
|
||
|
||
## Quick start
|
||
|
||
```python
|
||
from he11lib import BeamReconstructor, MeasurementPlane
|
||
|
||
# planes: a list of >=3 MeasurementPlane objects built from your own
|
||
# flux arrays (see MeasurementPlane below).
|
||
reconstructor = BeamReconstructor(w0=5e-3, z0=0.5, wavelength=1.76e-3)
|
||
result = reconstructor.reconstruct(planes)
|
||
|
||
for mode, (power_fraction, phase_rad) in result.purity.items():
|
||
print(mode, power_fraction, phase_rad)
|
||
```
|
||
|
||
## `data` — `MeasurementPlane`, `ReconstructionResult`
|
||
|
||
### `MeasurementPlane(flux, z, pixel_scale=None, viewing_angle_deg=None, label=None)`
|
||
|
||
One measurement: a 2D flux array plus its acquisition metadata.
|
||
|
||
- `flux` — 2D `np.ndarray` of flux values. Dead-pixel correction, background
|
||
subtraction, and saturation clipping are assumed already handled upstream.
|
||
- `z` — nominal distance from the output window, in meters. Must be `> 0`.
|
||
- `pixel_scale` — known meters/pixel, or `None` if unknown (then jointly
|
||
fit by `ModalFitter`/`BeamReconstructor`).
|
||
- `viewing_angle_deg` — known camera viewing angle relative to the beam
|
||
axis, in degrees, or `None` if unknown (also jointly fit).
|
||
- `label` — optional human-readable identifier.
|
||
|
||
### `validate_planes(planes)`
|
||
|
||
Raises `ValueError` if there are fewer than 3 planes, planes have
|
||
mismatched flux shapes, or `z` values are not all distinct. Called
|
||
internally by `ModalFitter.fit`/`fit_auto`, `PhaseRetriever.retrieve`, and
|
||
`BeamReconstructor.reconstruct` — you generally don't need to call it
|
||
yourself. Not exported from the top-level package; import via
|
||
`from he11lib.data import validate_planes` if needed.
|
||
|
||
### `ReconstructionResult`
|
||
|
||
Output of a full reconstruction (returned by `ModalFitter.fit`/`fit_auto`
|
||
and `BeamReconstructor.reconstruct`):
|
||
|
||
- `purity: dict[(p, l), (power_fraction, phase_rad)]`
|
||
- `reconstructed_field: np.ndarray` — reconstructed complex field.
|
||
- `centers: list[(x, y)]` — fitted beam transverse center per plane, meters.
|
||
- `pointing_angle_deg: float` — fitted shared beam pointing angle (tilt).
|
||
- `geometry: dict[str, float]` — geometry parameters used or fitted (keys
|
||
`pixel_scale_{i}`, `viewing_angle_deg_{i}` per plane index `i`).
|
||
- `residuals: list[np.ndarray]` — per-plane (measured − modeled) flux maps.
|
||
Empty when `used_phase_retrieval` is `True`.
|
||
- `coefficient_uncertainty: dict[(p, l), float]` — 1-sigma uncertainty on
|
||
each mode's fitted power fraction. `NaN` per mode when
|
||
`used_phase_retrieval` is `True`.
|
||
- `used_phase_retrieval: bool` — whether the phase-retrieval fallback (not
|
||
the modal fit) produced this result.
|
||
|
||
## `modes` — `LGBasis`
|
||
|
||
`LGBasis(w0, z0, wavelength)` — the LG mode basis referenced to a known
|
||
waist radius `w0` (m), waist location `z0` (m), and radiation `wavelength`
|
||
(m).
|
||
|
||
- `beam_radius(z)` — `w(z)`.
|
||
- `inverse_radius_of_curvature(z)` — `1/R(z)` (well-defined, `0`, at the
|
||
waist).
|
||
- `gouy_phase(z, p, l)` — Gouy phase of mode `(p, l)` at `z`.
|
||
- `field(x, y, z, p, l)` — complex `LG_{p,l}` field sampled on the `(x, y)`
|
||
grid at distance `z`.
|
||
- `field_superposition(x, y, z, coefficients)` — complex field for
|
||
`coefficients: dict[(p, l), complex]`.
|
||
- `project(complex_field, x, y, dx, z, modes)` — projects `complex_field`
|
||
onto each `(p, l)` in `modes`, returning `dict[(p, l), complex]`
|
||
coefficients (Riemann-sum inner product; `dx` is the grid spacing).
|
||
|
||
## `geometry` — `GeometryCalibration`
|
||
|
||
`GeometryCalibration(plane)` wraps a single `MeasurementPlane` and resolves
|
||
its pixel-to-physical-coordinate mapping.
|
||
|
||
- `pixel_scale_known` / `viewing_angle_known` — `bool` properties.
|
||
- `physical_coordinates(pixel_scale=None, viewing_angle_deg=None)` —
|
||
returns `(x, y)` physical coordinate grids matching the plane's flux
|
||
shape. Values known on the `MeasurementPlane` take precedence over the
|
||
`override` arguments; raises `ValueError` if a value is neither known nor
|
||
overridden.
|
||
|
||
## `noise` — `NoiseEstimator`
|
||
|
||
`NoiseEstimator()` — automatic per-image noise estimation (no
|
||
user-supplied noise parameter needed).
|
||
|
||
- `estimate_std(image)` — fast Laplacian-based (Immerkær 1996) noise
|
||
standard-deviation estimate.
|
||
- `weights(image)` — per-pixel weights (`1/sigma**2`) for noise-weighted
|
||
least squares.
|
||
|
||
## `deconvolution` — `DiffusionDeconvolver`
|
||
|
||
`DiffusionDeconvolver(thermal_diffusivity, dwell_time)` — optional
|
||
correction for lateral thermal-diffusion blur in the absorbing target
|
||
(`thermal_diffusivity` in m²/s, `dwell_time` in s). Disabled unless you
|
||
pass a `deconvolver` to `BeamReconstructor`.
|
||
|
||
- `blur_sigma_m()` — Gaussian blur standard deviation, in meters.
|
||
- `blur(image, pixel_scale)` — forward blur (for synthetic testing).
|
||
- `deconvolve(image, pixel_scale, noise_to_signal_ratio=1e-3)` — regularized
|
||
(Wiener) removal of the blur.
|
||
|
||
Note: the blur/deconvolution kernel is isotropic in pixel space. If a
|
||
plane has a nonzero `viewing_angle_deg`, its `x` and `y` pixel axes have
|
||
different physical scales (see `SyntheticBeamGenerator` below), so
|
||
deconvolution is only exact for `viewing_angle_deg == 0`; at oblique
|
||
angles it is an approximation.
|
||
|
||
## `synthetic` — `SyntheticBeamGenerator`
|
||
|
||
`SyntheticBeamGenerator(basis, image_shape, pixel_scale)` — forward model
|
||
used to validate the pipeline against known ground truth, and to evaluate
|
||
experimental design (e.g. "would these distances separate my modes?").
|
||
`pixel_scale` is the physical pixel size, in meters, along the non-tilted
|
||
`y` axis; the `x` axis is compressed by `1/cos(viewing_angle_deg)` to model
|
||
an oblique camera view.
|
||
|
||
- `generate(coefficients, z_list, *, center=(0, 0), pointing_angle_deg=0.0, viewing_angle_deg=0.0, noise_std=0.0, seed=None)`
|
||
— returns one `MeasurementPlane` per `z` in `z_list`. The beam's
|
||
transverse center drifts linearly with `z` according to
|
||
`pointing_angle_deg`, starting from `center` at `z0`.
|
||
|
||
## `fitting` — `ModalFitter`, `generate_mode_shells`
|
||
|
||
### `generate_mode_shells(max_order)`
|
||
|
||
Groups candidate `LG_{p,l}` modes into shells of increasing order
|
||
`2p + |l|`, up to and including `max_order`. Returns
|
||
`list[list[(p, l)]]`, one list of modes per order.
|
||
|
||
### `ModalFitter(basis, noise_estimator=None)`
|
||
|
||
Core reconstruction path: a joint nonlinear least-squares fit of complex LG
|
||
coefficients, beam center/pointing, and (if unknown) geometry.
|
||
|
||
- `fit(planes, modes, initial_coefficients=None, initial_center=(0.0, 0.0), initial_tilt_deg=(0.0, 0.0), initial_pixel_scale=None, initial_viewing_angle_deg=0.0) -> ReconstructionResult`
|
||
— fits exactly the given candidate `modes`.
|
||
- `fit_auto(planes, max_order=4, bic_improvement_threshold=10.0) -> ReconstructionResult`
|
||
— starts from `LG_00` and grows the candidate mode set shell-by-shell
|
||
(via `generate_mode_shells`), stopping once BIC no longer improves by
|
||
more than `bic_improvement_threshold`, capped at `max_order`. Emits a
|
||
`UserWarning` (does not raise) if the cap is reached while the fit is
|
||
still improving.
|
||
|
||
## `phase_retrieval` — `PhaseRetriever`, `propagate_angular_spectrum`
|
||
|
||
Fallback reconstruction path for when the modal fit's residual stays high,
|
||
or when the mode content isn't well described by a small finite mode set.
|
||
|
||
### `propagate_angular_spectrum(field, dx, dz, wavelength)`
|
||
|
||
Free-space-propagates a complex `field` (pixel spacing `dx`) by distance
|
||
`dz` via the (paraxial) angular-spectrum method — the same propagation
|
||
model implicitly assumed by `LGBasis`'s closed-form paraxial modes.
|
||
|
||
### `PhaseRetriever(wavelength)`
|
||
|
||
- `retrieve(planes, pixel_scale=None, viewing_angle_deg=None, max_iterations=200) -> PhaseRetrievalResult`
|
||
— multi-plane Gerchberg-Saxton phase retrieval: propagates a trial
|
||
complex field back and forth between planes, enforcing the measured
|
||
amplitude (`sqrt(flux)`) at each plane, without assuming a finite mode
|
||
basis.
|
||
|
||
### `PhaseRetrievalResult`
|
||
|
||
`field, x, y, z, center, residual` — the recovered complex field (at the
|
||
smallest-`z` plane) on its `(x, y)` grid, the estimated beam center
|
||
(intensity centroid), and the final RMS amplitude-mismatch residual.
|
||
Project `field` onto `LGBasis` (via `LGBasis.project`) to get a purity
|
||
table, as `BeamReconstructor` does internally for its fallback path.
|
||
|
||
## `reconstruct` — `BeamReconstructor`
|
||
|
||
`BeamReconstructor(w0, z0, wavelength, max_order=4, noise_estimator=None, deconvolver=None, force_phase_retrieval=False, phase_retrieval_residual_threshold=None)`
|
||
|
||
High-level orchestrator wiring together the full pipeline: optional
|
||
diffusion deblurring → `ModalFitter.fit_auto` → optional
|
||
`PhaseRetriever` fallback.
|
||
|
||
- `reconstruct(planes) -> ReconstructionResult`
|
||
1. Validates `planes` (see `validate_planes`).
|
||
2. If `deconvolver` is set, deblurs each plane (raises `ValueError` if a
|
||
plane's `pixel_scale` isn't known).
|
||
3. Runs `ModalFitter(basis, noise_estimator).fit_auto(planes, max_order)`.
|
||
4. Runs the `PhaseRetriever` fallback instead, projecting its recovered
|
||
field onto all modes up to `max_order`, if `force_phase_retrieval` is
|
||
`True`, or if `phase_retrieval_residual_threshold` is set and the
|
||
modal fit's noise-weighted RMS residual exceeds it. In that case
|
||
`result.residuals` is empty and `coefficient_uncertainty` is `NaN`
|
||
per mode (phase retrieval doesn't produce a fit covariance).
|
||
|
||
## `plotting` — diagnostic visualizations
|
||
|
||
Each function returns a `matplotlib.figure.Figure` for the caller to
|
||
display (`fig.show()`) or save (`fig.savefig(...)`); none of them call
|
||
`plt.show()` themselves.
|
||
|
||
- `plot_mode_purity(result)` — bar chart of power fraction per mode.
|
||
- `plot_center_trace(planes, result)` — fitted beam center `(x, y)` vs. `z`.
|
||
- `plot_residuals(planes, result)` — per-plane residual maps. Raises
|
||
`ValueError` if `result.residuals` is empty (e.g. after the
|
||
phase-retrieval fallback).
|