From 2e8966a7b6f08dac523fe7420a8cd3eff31363e6 Mon Sep 17 00:00:00 2001 From: ThorstenHellert Date: Sat, 10 Oct 2026 08:50:59 -0700 Subject: [PATCH 1/4] build: publish as accelerator-middle-layer-apg Rename the distribution, admit .postN tags in the PyPI workflow and run it in the pypi environment, and say in the README what this fork is. The import package stays pyaml. --- .github/workflows/deploy-pypi.yaml | 3 ++- README.md | 7 +++++++ pyproject.toml | 8 ++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-pypi.yaml b/.github/workflows/deploy-pypi.yaml index b1c116add..58292ea0e 100644 --- a/.github/workflows/deploy-pypi.yaml +++ b/.github/workflows/deploy-pypi.yaml @@ -4,6 +4,7 @@ on: push: tags: - '[0-9]+.[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+.post[0-9]+' workflow_dispatch: jobs: @@ -11,7 +12,7 @@ jobs: runs-on: ubuntu-latest - #environment: release + environment: pypi permissions: id-token: write diff --git a/README.md b/README.md index e9080dbb4..bd81ac917 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ # pyaml +> **This is the ALS-APG staging fork of [pyAML](https://github.com/python-accelerator-middle-layer/pyaml),** +> published on PyPI as `accelerator-middle-layer-apg` (import name unchanged: `pyaml`). +> It carries only upstream commits and exists so that OSPREY deployments can depend on +> fixes that are not yet in an upstream release. Unless you deploy OSPREY, install +> `accelerator-middle-layer` instead; do not install both, they ship the same `pyaml/` package. +> Please file issues and pull requests upstream. + **Package for the Python Accelerator Middle Layer core** [![Documentation Status](https://readthedocs.org/projects/pyaml/badge/?version=stable)](https://pyaml.readthedocs.io/en/stable/?badge=stable) diff --git a/pyproject.toml b/pyproject.toml index 51ebb354b..4b7055546 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,10 @@ [project] -name = "accelerator-middle-layer" -description = "Python Accelerator Middle Layer" +# ALS-APG staging distribution of pyAML (github.com/als-apg/pyaml): an upstream snapshot +# published so downstream packages can depend on fixes that are not yet in an upstream +# release. The import name is unchanged (`pyaml`), so do not install it beside +# `accelerator-middle-layer` -- both ship the same `pyaml/` package. +name = "accelerator-middle-layer-apg" +description = "ALS-APG staging snapshot of pyAML (Python Accelerator Middle Layer) for OSPREY deployments; everyone else should install accelerator-middle-layer" readme = "README.md" requires-python = ">=3.11" dynamic = ["version"] From 9eac244ed4cac1e0b1ed08162f52ed63e7bd953a Mon Sep 17 00:00:00 2001 From: ThorstenHellert Date: Fri, 16 Oct 2026 09:57:08 -0700 Subject: [PATCH 2/4] feat(tuning_tools): add first-turn trajectory correction tool pyAML had no tool for steering the beam through the first turn, when only the BPMs upstream of the loss point see a trajectory and an orbit correction cannot be applied. Trajectory is a tuning tool built from a trajectory response matrix (OrbitResponseMatrixData file, mapping or instance) plus default alpha, n_discard and gain. It validates the matrix once on load and publishes its facts as a read-only layout. pseudo_inverse() returns the Tikhonov- and truncation-regularised pseudo-inverse, and correct() returns one frozen corrector step that zeroes the correctors downstream of the last BPM with beam, plane by plane, together with a Reason saying why it did so. It reads no hardware. The test module checks the tool against goldens frozen from the ALS MATLAB sources (SCgetPinv.m and SCexp_ALS_calcCMstep.m) run in MATLAB 26.1.0.3276743 (R2026a) Update 3 on appsdev2.als.lbl.gov, over the 19 cases in trajectory_cases.json: trajectory_goldens.npz a00777fa45100b887c515ffee265dc641d128b7d1f01972cda42733aece62fef trajectory_cases.json 5c98dfb1e64e6d303aa38069d0b56fde2fd364573117813831e9cff72e0243be SCgetPinv.m e35239d6c5cafae8477adfdbccfba6d7c3d65d48d11c3a581de7fbc768575d1f calcCMstep.m 592b1a6cf05f7f5889f7b20aac26945ce80c3673e2d581563ac5a9e65a167f78 MATLAB driver df9cc13c5986a1922616619f6aefc4488fea4865da0567b6dd3f0d65c908341f Set PYAML_TRAJECTORY_GOLDENS to test against another goldens file; tests that need the goldens carry "golden" in their name. --- pyaml/tuning_tools/trajectory.py | 1196 ++++++++++ tests/tuning_tools/test_trajectory.py | 2580 +++++++++++++++++++++ tests/tuning_tools/trajectory_cases.json | 412 ++++ tests/tuning_tools/trajectory_goldens.npz | Bin 0 -> 480676 bytes 4 files changed, 4188 insertions(+) create mode 100644 pyaml/tuning_tools/trajectory.py create mode 100644 tests/tuning_tools/test_trajectory.py create mode 100644 tests/tuning_tools/trajectory_cases.json create mode 100644 tests/tuning_tools/trajectory_goldens.npz diff --git a/pyaml/tuning_tools/trajectory.py b/pyaml/tuning_tools/trajectory.py new file mode 100644 index 000000000..bccd1d2a9 --- /dev/null +++ b/pyaml/tuning_tools/trajectory.py @@ -0,0 +1,1196 @@ +""" +First-turn trajectory correction tool. + +This module holds the :class:`Trajectory` tool and the records it publishes and +returns: + +- :class:`Reason` and :class:`SpectrumKind`, two closed enums that serialise as + their member names; +- :class:`TrajectoryLayout`, the read-only, value-compared facts of a loaded + response matrix; +- :class:`PseudoInverse`, the result of :meth:`Trajectory.pseudo_inverse`; +- :class:`TrajectoryStep`, the result of :meth:`Trajectory.correct`. + +Every record is a frozen, slotted dataclass. Name fields are tuples of ``str``. +Every array a record stores is its own copy and is read-only, so a returned record +can never reach or change the tool's state. +""" + +import copy +import dataclasses +import logging +import math +import numbers +from collections.abc import Mapping +from dataclasses import dataclass +from enum import StrEnum +from pathlib import Path +from typing import Any, Optional, Union + +import numpy as np + +from ..common.exception import PyAMLException +from ..validation import DynamicValidation, register_schema +from .orbit_response_matrix_data import OrbitResponseMatrixData +from .tuning_tool import TuningTool + +__all__ = ["PseudoInverse", "Reason", "SpectrumKind", "Trajectory", "TrajectoryLayout", "TrajectoryStep"] + +logger = logging.getLogger(__name__) + +PYAMLCLASS = "Trajectory" + + +class Reason(StrEnum): + """ + Why a :class:`TrajectoryStep` has the step it has. + + The reason is the first match, in this order, of NO_BEAM, NO_INVERSE, + NO_UPSTREAM, NO_UPSTREAM_H / NO_UPSTREAM_V, ON_REFERENCE and OK. Each member's + value equals its name, so ``json.dumps`` writes the name. + + Attributes + ---------- + NO_BEAM + No BPM has beam (every entry of ``x`` is NaN). + NO_INVERSE + Every inverse weight is zero (``n_discard == L``). + NO_UPSTREAM + Neither plane has a live corrector at or before the last BPM with beam. + NO_UPSTREAM_H + The horizontal plane has no live corrector at or before the last BPM with beam. + NO_UPSTREAM_V + The vertical plane has no live corrector at or before the last BPM with beam. + ON_REFERENCE + The trajectory already equals the reference. + OK + A correction step was computed. + """ + + NO_BEAM = "NO_BEAM" + NO_INVERSE = "NO_INVERSE" + NO_UPSTREAM = "NO_UPSTREAM" + NO_UPSTREAM_H = "NO_UPSTREAM_H" + NO_UPSTREAM_V = "NO_UPSTREAM_V" + ON_REFERENCE = "ON_REFERENCE" + OK = "OK" + + +class SpectrumKind(StrEnum): + """ + Kind of one position of the singular spectrum of a :class:`PseudoInverse`. + + A position with two causes takes the first of STRUCTURAL > RANK_DISCARDED > + DISCARDED > LIVE. Each member's value equals its name, so ``json.dumps`` writes + the name. + + Attributes + ---------- + LIVE + A live singular value whose inverse weight is applied. + RANK_DISCARDED + A live singular value dropped by the rank guard (``alpha == 0`` only). + DISCARDED + A live singular value zeroed by ``n_discard``. + STRUCTURAL + A structural zero: a position past the live singular values, caused by + correctors with no response. + """ + + LIVE = "LIVE" + RANK_DISCARDED = "RANK_DISCARDED" + DISCARDED = "DISCARDED" + STRUCTURAL = "STRUCTURAL" + + +_STATUS: dict[Reason, str] = { + Reason.NO_BEAM: "no BPM with beam", + Reason.NO_INVERSE: "every singular value is discarded; no correction is possible", + Reason.NO_UPSTREAM: "no corrector upstream of the last BPM with beam", + Reason.NO_UPSTREAM_H: "no horizontal corrector upstream of the last BPM with beam", + Reason.NO_UPSTREAM_V: "no vertical corrector upstream of the last BPM with beam", + Reason.ON_REFERENCE: "already on reference", + Reason.OK: "", +} + + +def _names(value: Any, field: str) -> tuple[str, ...]: + """Return ``value`` as a tuple of str, raising TypeError on any other element.""" + names = tuple(value) + for name in names: + if not isinstance(name, str): + raise TypeError(f"{field} must hold str names, got {type(name).__name__} {name!r}") + return names + + +def _frozen_array(value: Any, field: str, ndim: int, dtype: Any = float) -> np.ndarray: + """Return a read-only copy of ``value`` with the given rank and dtype.""" + array = np.array(value, dtype=dtype, copy=True) + if array.ndim != ndim: + raise ValueError(f"{field} must be {ndim}-dimensional, got shape {array.shape}") + array.flags.writeable = False + return array + + +def _set(record: Any, field: str, value: Any) -> None: + object.__setattr__(record, field, value) + + +@dataclass(frozen=True, slots=True) +class TrajectoryLayout: + """ + Read-only facts of a loaded trajectory response matrix. + + Two layouts are equal when every name field is equal. All counts are derived + from the names. + + Parameters + ---------- + bpm_names_h : tuple[str, ...] + BPM names of the horizontal row half, in row order. + bpm_names_v : tuple[str, ...] + BPM names of the vertical row half, in row order. + hcorr_names : tuple[str, ...] + Horizontal corrector names, in column order. + vcorr_names : tuple[str, ...] + Vertical corrector names, in column order. + no_response_names : tuple[str, ...] + Names of the correctors whose response column is zero, in column order. + + Attributes + ---------- + n_bpm : int + Number of BPMs per plane. + n_h, n_v : int + Number of horizontal and vertical correctors. + n_cor : int + Number of correctors, ``n_h + n_v``. + n_live : int + Number of correctors with a response. + L : int + Length of the singular spectrum, ``min(2 * n_bpm, n_cor)``. + k_live : int + Number of live singular values, ``min(2 * n_bpm, n_live)``. + n_struct : int + Number of structural zeros, ``L - k_live``. + """ + + bpm_names_h: tuple[str, ...] + bpm_names_v: tuple[str, ...] + hcorr_names: tuple[str, ...] + vcorr_names: tuple[str, ...] + no_response_names: tuple[str, ...] + + def __post_init__(self) -> None: + for field in dataclasses.fields(self): + _set(self, field.name, _names(getattr(self, field.name), field.name)) + + @property + def n_bpm(self) -> int: + return len(self.bpm_names_h) + + @property + def n_h(self) -> int: + return len(self.hcorr_names) + + @property + def n_v(self) -> int: + return len(self.vcorr_names) + + @property + def n_cor(self) -> int: + return self.n_h + self.n_v + + @property + def n_live(self) -> int: + return self.n_cor - len(self.no_response_names) + + @property + def L(self) -> int: + return min(2 * self.n_bpm, self.n_cor) + + @property + def k_live(self) -> int: + return min(2 * self.n_bpm, self.n_live) + + @property + def n_struct(self) -> int: + return self.L - self.k_live + + +@dataclass(frozen=True, slots=True, eq=False) +class PseudoInverse: + """ + Guarded, damped pseudo-inverse of the trajectory response matrix. + + ``singular_values``, ``inverse_weights`` and ``spectrum_kind`` are index-aligned + and have length ``L``. Every array is a read-only copy. Records compare by + identity. + + Parameters + ---------- + matrix : numpy.ndarray + The ``n_cor x 2*n_bpm`` inverse. Rows of correctors with no response are + exactly zero. + singular_values : numpy.ndarray + The live singular values in descending order, then the structural zeros. + inverse_weights : numpy.ndarray + The diagonal applied to each singular direction, gain included; zero at + every structural, rank-discarded and discarded position. + spectrum_kind : tuple[SpectrumKind, ...] + The kind of each position. + rank_discarded : int + Number of live singular values the rank guard dropped (``alpha == 0`` only). + no_response_correctors : numpy.ndarray + Column indices of the correctors with no response. + no_response_names : tuple[str, ...] + Their names, as in the layout. + alpha : float + Tikhonov parameter used. + n_discard : int + Number of trailing spectrum positions zeroed. + gain : float + Gain applied. + """ + + matrix: np.ndarray + singular_values: np.ndarray + inverse_weights: np.ndarray + spectrum_kind: tuple[SpectrumKind, ...] + rank_discarded: int + no_response_correctors: np.ndarray + no_response_names: tuple[str, ...] + alpha: float + n_discard: int + gain: float + + def __post_init__(self) -> None: + _set(self, "matrix", _frozen_array(self.matrix, "matrix", 2)) + _set(self, "singular_values", _frozen_array(self.singular_values, "singular_values", 1)) + _set(self, "inverse_weights", _frozen_array(self.inverse_weights, "inverse_weights", 1)) + _set(self, "spectrum_kind", tuple(SpectrumKind(kind) for kind in self.spectrum_kind)) + _set( + self, + "no_response_correctors", + _frozen_array(self.no_response_correctors, "no_response_correctors", 1, np.intp), + ) + _set(self, "no_response_names", _names(self.no_response_names, "no_response_names")) + lengths = {len(self.singular_values), len(self.inverse_weights), len(self.spectrum_kind)} + if len(lengths) != 1: + raise ValueError( + "singular_values, inverse_weights and spectrum_kind must have one length, got " + f"{len(self.singular_values)}, {len(self.inverse_weights)}, {len(self.spectrum_kind)}" + ) + + +@dataclass(frozen=True, slots=True, eq=False) +class TrajectoryStep: + """ + Corrector step computed by :meth:`Trajectory.correct`. + + The increment to apply is ``-step``. Records compare by identity. + + Parameters + ---------- + step : numpy.ndarray + Read-only step in response-matrix column order: all horizontal correctors, + then all vertical ones. + names : tuple[str, ...] + Corrector names, aligned with ``step``. + n_h : int + Number of horizontal correctors; ``step[:n_h]`` is the horizontal plane. + last_bpm : int or None + Position of the last BPM with beam in the first half of ``bpm_index``, named + by ``layout.bpm_names_h``; None when no BPM has beam. + zeroed_h, zeroed_v : tuple[str, ...] + Correctors of each plane whose step was zeroed by threading, in column order. + pseudo_inverse : PseudoInverse + The inverse the step was solved with. + reason : Reason + Why the step is what it is. + + Attributes + ---------- + step_h, step_v : numpy.ndarray + Read-only horizontal and vertical parts of ``step``. + status : str + Sentence describing ``reason``; empty for OK. + all_zero : bool + True when every entry of ``step`` is zero. + """ + + step: np.ndarray + names: tuple[str, ...] + n_h: int + last_bpm: Optional[int] + zeroed_h: tuple[str, ...] + zeroed_v: tuple[str, ...] + pseudo_inverse: PseudoInverse + reason: Reason + + def __post_init__(self) -> None: + _set(self, "step", _frozen_array(self.step, "step", 1)) + _set(self, "names", _names(self.names, "names")) + _set(self, "zeroed_h", _names(self.zeroed_h, "zeroed_h")) + _set(self, "zeroed_v", _names(self.zeroed_v, "zeroed_v")) + _set(self, "reason", Reason(self.reason)) + if len(self.names) != len(self.step): + raise ValueError(f"names has {len(self.names)} entries, step has {len(self.step)}") + + @property + def step_h(self) -> np.ndarray: + return self.step[: self.n_h] + + @property + def step_v(self) -> np.ndarray: + return self.step[self.n_h :] + + @property + def status(self) -> str: + return _STATUS[self.reason] + + @property + def all_zero(self) -> bool: + return not np.any(self.step) + + +@dataclass(frozen=True, slots=True, eq=False) +class _RMState: + """ + Private, immutable state of a loaded response matrix. + + Built completely and assigned to the tool in one step by ``load()``, its only + writer; the solve reads ``matrix`` and ``live`` from it. + + Parameters + ---------- + response_matrix : OrbitResponseMatrixData + A private deep copy of the loaded data. + layout : TrajectoryLayout + The published facts. + matrix : numpy.ndarray + Read-only ``2*n_bpm x n_cor`` response matrix. + live : numpy.ndarray + Read-only boolean mask over columns, True where the corrector responds. + """ + + response_matrix: OrbitResponseMatrixData + layout: TrajectoryLayout + matrix: np.ndarray + live: np.ndarray + + def __post_init__(self) -> None: + _set(self, "matrix", _frozen_array(self.matrix, "matrix", 2)) + _set(self, "live", _frozen_array(self.live, "live", 1, bool)) + + +@dataclass(frozen=True, slots=True) +class _Settings: + """ + Resolved, checked solver settings. + + Only :func:`_resolve_settings` builds one, so every instance holds values that + passed its checks, as Python scalars. + + Parameters + ---------- + alpha : float + Tikhonov parameter, finite, ``>= 0``, with ``alpha * alpha`` finite. + n_discard : int + Number of trailing spectrum positions to zero, in ``[0, L]``. + gain : float + Gain, finite and ``> 0``. + """ + + alpha: float + n_discard: int + gain: float + + +def _unwrap(value: Any) -> Any: + """Return the scalar held by a 0-d ndarray (as ``np.load`` gives a stored scalar), else ``value``.""" + if isinstance(value, np.ndarray) and value.ndim == 0: + return value[()] + return value + + +def _is_bool(value: Any) -> bool: + return isinstance(value, (bool, np.bool_)) + + +def _real(value: Any, field: str) -> float: + """Return ``value`` as a finite float, raising PyAMLException on a non-real or non-finite value.""" + value = _unwrap(value) + if _is_bool(value) or not isinstance(value, numbers.Real): + raise PyAMLException(f"{field} must be a real number, got {type(value).__name__} {value!r}") + result = float(value) + if not math.isfinite(result): + raise PyAMLException(f"{field} must be finite, got {result!r}") + return result + + +def _resolve_settings( + alpha: Any, + n_discard: Any, + gain: Any, + L: Optional[int], + defaults: Optional[_Settings] = None, +) -> _Settings: + """ + Check and resolve the solver settings ``alpha``, ``n_discard`` and ``gain``. + + This is the one resolution routine of :class:`Trajectory`, used on every path: + at construction (where pyAML's validation layer may already have coerced the + values), at construction under ``validate=False``, at every ``load()`` (to + re-check the configured ``n_discard`` against the new ``L``) and at every call + that takes per-call overrides. It is a pure function of its arguments. + + Parameters + ---------- + alpha : real or None + Tikhonov parameter: a finite real ``>= 0`` whose square is finite. + n_discard : int or None + Number of trailing spectrum positions to zero: an integer in ``[0, L]``. + gain : real or None + Gain: a finite real ``> 0``. + L : int or None + Length of the singular spectrum of the loaded response matrix. None when no + response matrix is loaded; only ``n_discard >= 0`` is checked then, and + ``load()`` checks the upper bound. + defaults : _Settings, optional + The configured settings. A None argument takes its value from here; the + result is checked against ``L`` either way. Without ``defaults`` (at + construction) a None argument is an error. + + Returns + ------- + _Settings + The checked settings as Python ``float``, ``int`` and ``float``. + + Raises + ------ + PyAMLException + When a setting is None without a configured value, has the wrong type, or is + out of range. The message names the setting. + + Notes + ----- + ``bool`` and ``numpy.bool_`` are rejected for every setting. NumPy integer and + floating scalars, and 0-d arrays holding one (as ``np.load`` returns a stored + scalar), are accepted and converted to Python scalars. ``n_discard`` must be an + integer type: ``1.0`` is rejected, not truncated. + """ + if defaults is not None: + alpha = defaults.alpha if alpha is None else alpha + n_discard = defaults.n_discard if n_discard is None else n_discard + gain = defaults.gain if gain is None else gain + for field, value in (("alpha", alpha), ("n_discard", n_discard), ("gain", gain)): + if value is None: + raise PyAMLException(f"{field} must be given, got None") + + alpha_value = _real(alpha, "alpha") + if alpha_value < 0.0: + raise PyAMLException(f"alpha must be >= 0, got {alpha_value!r}") + if not math.isfinite(alpha_value * alpha_value): + raise PyAMLException(f"alpha is too large: alpha**2 is not finite for alpha={alpha_value!r}") + alpha_value += 0.0 # -0.0 -> 0.0 + + n_discard = _unwrap(n_discard) + if _is_bool(n_discard) or not isinstance(n_discard, numbers.Integral): + raise PyAMLException(f"n_discard must be an integer, got {type(n_discard).__name__} {n_discard!r}") + n_discard_value = int(n_discard) + if n_discard_value < 0 or (L is not None and n_discard_value > L): + bound = "[0, L]" if L is None else f"[0, {L}]" + raise PyAMLException(f"n_discard must be an integer in {bound}, got {n_discard_value}") + + gain_value = _real(gain, "gain") + if gain_value <= 0.0: + raise PyAMLException(f"gain must be > 0, got {gain_value!r}") + + return _Settings(alpha=alpha_value, n_discard=n_discard_value, gain=gain_value) + + +# --------------------------------------------------------------------------- +# Response-matrix entry point +# --------------------------------------------------------------------------- + +_RM_FIELDS = ("matrix", "observable_names", "variable_names", "rf_response", "variable_planes", "observable_planes") +_RM_REQUIRED = ("matrix", "observable_names") + + +def _rm_fields(response_matrix: Any, source: str) -> dict[str, Any]: + """ + Return the six ``OrbitResponseMatrixData`` fields of an instance or a mapping. + + A mapping must hold ``matrix`` and ``observable_names``; the other four fields + default to None. Any other key, a build key such as ``type`` included, is + rejected. + """ + if isinstance(response_matrix, OrbitResponseMatrixData): + return {field: getattr(response_matrix, field) for field in _RM_FIELDS} + if isinstance(response_matrix, Mapping): + unknown = sorted(str(key) for key in response_matrix if key not in _RM_FIELDS) + if unknown: + raise PyAMLException(f"{source}: unknown response-matrix keys {unknown}; expected only {list(_RM_FIELDS)}") + missing = [field for field in _RM_REQUIRED if field not in response_matrix] + if missing: + raise PyAMLException(f"{source}: missing response-matrix keys {missing}") + return {field: response_matrix.get(field) for field in _RM_FIELDS} + raise PyAMLException( + f"{source}: expected an OrbitResponseMatrixData file, mapping or instance, got {type(response_matrix).__name__}" + ) + + +def _str_list(value: Any, field: str, source: str) -> list[str]: + """Return ``value`` as a list of str, raising PyAMLException naming ``source`` otherwise.""" + if value is None: + raise PyAMLException(f"{source}: {field} is missing") + if not isinstance(value, (list, tuple)): + raise PyAMLException(f"{source}: {field} must be a list of str, got {type(value).__name__}") + for item in value: + if not isinstance(item, str): + raise PyAMLException(f"{source}: {field} must hold str, got {type(item).__name__} {item!r}") + return list(value) + + +def _plane_major(planes: list[str], field: str, source: str) -> int: + """Check that ``planes`` is every 'H' then every 'V'; return the number of 'H' entries.""" + bad = sorted({plane for plane in planes if plane not in ("H", "V")}) + if bad: + raise PyAMLException(f"{source}: {field} must hold only 'H' and 'V', got {bad}") + n_h = planes.count("H") + if planes != ["H"] * n_h + ["V"] * (len(planes) - n_h): + raise PyAMLException(f"{source}: {field} must be plane-major (every 'H' before every 'V')") + return n_h + + +def _duplicates(names: list[str]) -> list[str]: + seen: set[str] = set() + duplicated: set[str] = set() + for name in names: + (duplicated if name in seen else seen).add(name) + return sorted(duplicated) + + +def _matrix(rows: Any, source: str) -> np.ndarray: + """Return ``rows`` as a finite, rectangular, non-empty float matrix, raising PyAMLException otherwise.""" + if not isinstance(rows, (list, tuple)) or len(rows) == 0: + raise PyAMLException(f"{source}: matrix must be a non-empty list of rows") + for row in rows: + if not isinstance(row, (list, tuple)): + raise PyAMLException(f"{source}: every matrix row must be a list, got {type(row).__name__}") + for value in row: + if isinstance(value, (bool, np.bool_)) or not isinstance(value, numbers.Real): + raise PyAMLException(f"{source}: matrix entries must be real numbers, got {type(value).__name__}") + lengths = sorted({len(row) for row in rows}) + if len(lengths) != 1 or lengths[0] == 0: + raise PyAMLException(f"{source}: matrix must be rectangular and non-empty, got row lengths {lengths}") + matrix = np.array(rows, dtype=float) + if not np.all(np.isfinite(matrix)): + raise PyAMLException(f"{source}: matrix must be finite") + return matrix + + +def _build_state(fields: dict[str, Any], source: str, settings: _Settings) -> _RMState: + """ + Check every fact of a response matrix once and build the complete private state. + + Raises PyAMLException naming ``source`` on the first failed check, a configured + ``n_discard`` larger than the new ``L`` included. Nothing of ``fields`` is + aliased by the returned state. + """ + observable_names = _str_list(fields["observable_names"], "observable_names", source) + variable_names = _str_list(fields["variable_names"], "variable_names", source) + observable_planes = _str_list(fields["observable_planes"], "observable_planes", source) + variable_planes = _str_list(fields["variable_planes"], "variable_planes", source) + if fields["rf_response"] is not None: + raise PyAMLException(f"{source}: a trajectory response matrix must not carry an rf_response") + matrix = _matrix(fields["matrix"], source) + + n_rows, n_cols = matrix.shape + if not n_rows == len(observable_names) == len(observable_planes): + raise PyAMLException( + f"{source}: matrix has {n_rows} rows but {len(observable_names)} observable_names " + f"and {len(observable_planes)} observable_planes" + ) + if not n_cols == len(variable_names) == len(variable_planes): + raise PyAMLException( + f"{source}: matrix has {n_cols} columns but {len(variable_names)} variable_names " + f"and {len(variable_planes)} variable_planes" + ) + + n_bpm = _plane_major(observable_planes, "observable_planes", source) + if 2 * n_bpm != n_rows: + raise PyAMLException( + f"{source}: observable_planes must have equal row counts per plane, got {n_bpm} 'H' and {n_rows - n_bpm} 'V'" + ) + n_h = _plane_major(variable_planes, "variable_planes", source) + + bpm_names_h, bpm_names_v = observable_names[:n_bpm], observable_names[n_bpm:] + for part, names in (("H row half", bpm_names_h), ("V row half", bpm_names_v), ("variable_names", variable_names)): + duplicated = _duplicates(names) + if duplicated: + raise PyAMLException(f"{source}: names must be unique within the {part}, duplicated {duplicated}") + + live = np.any(matrix != 0.0, axis=0) + if not np.any(live): + raise PyAMLException(f"{source}: no corrector has a response (every matrix column is zero)") + + layout = TrajectoryLayout( + bpm_names_h=bpm_names_h, + bpm_names_v=bpm_names_v, + hcorr_names=variable_names[:n_h], + vcorr_names=variable_names[n_h:], + no_response_names=[name for name, responds in zip(variable_names, live, strict=True) if not responds], + ) + try: + _resolve_settings(None, None, None, L=layout.L, defaults=settings) + except PyAMLException as exc: + raise PyAMLException(f"{source}: {exc.message}") from exc + + data = OrbitResponseMatrixData( + matrix=matrix.tolist(), + observable_names=observable_names, + variable_names=variable_names, + rf_response=None, + variable_planes=variable_planes, + observable_planes=observable_planes, + validate=False, + ) + return _RMState(response_matrix=data, layout=layout, matrix=matrix, live=live) + + +# --------------------------------------------------------------------------- +# Pseudo-inverse +# --------------------------------------------------------------------------- + +_EPS = float(np.finfo(float).eps) + + +def _pseudo_inverse(state: _RMState, settings: _Settings) -> PseudoInverse: + """ + Compute the guarded, damped pseudo-inverse of a loaded response matrix. + + A pure function of ``state`` and ``settings``. The correctors with no response + (zero columns) are removed before the SVD and re-embedded as exact-zero rows, + so they are a structural fact at every ``alpha``. The spectrum has the + reference implementation's length ``L = min(2*n_bpm, n_cor)``: the ``k_live`` + live singular values in descending order, then ``n_struct = L - k_live`` + structural zeros. The weights are formed in the reference order: ``s / (s**2 + + alpha**2)`` for ``alpha > 0``, else ``1 / s`` under the rank guard ``s <= + max(2*n_bpm, n_cor) * eps * s_max``; then times ``gain``; then the structural + zeros are appended and the last ``n_discard`` positions of the full-length + vector are zeroed. + + Raises + ------ + PyAMLException + When, after the cut, a weight is not finite, or every weight is zero while + ``n_discard < L`` (``n_discard == L`` is the reference's own all-zero + diagonal and returns the all-zero inverse). + """ + layout = state.layout + alpha, n_discard, gain = settings.alpha, settings.n_discard, settings.gain + L, k_live, n_struct = layout.L, layout.k_live, layout.n_struct + + live_columns = np.flatnonzero(state.live) + u, s, vt = np.linalg.svd(state.matrix[:, live_columns], full_matrices=False) + s = s[:k_live] + u, vt = u[:, :k_live], vt[:k_live, :] + + rank_dropped = np.zeros(k_live, dtype=bool) + if alpha > 0.0: + weights = s / (s * s + alpha * alpha) + else: + if k_live: + rank_dropped = s <= max(2 * layout.n_bpm, layout.n_cor) * _EPS * s[0] + weights = np.zeros(k_live) + with np.errstate(divide="ignore", over="ignore"): + weights[~rank_dropped] = 1.0 / s[~rank_dropped] + rank_discarded = int(np.count_nonzero(rank_dropped)) + + with np.errstate(over="ignore", invalid="ignore"): + weights = weights * gain + weights = np.concatenate([weights, np.zeros(n_struct)]) + cut = np.zeros(L, dtype=bool) + if n_discard: + cut[L - n_discard :] = True + weights[cut] = 0.0 + + if not np.all(np.isfinite(weights)): + raise PyAMLException(f"the inverse weights are not finite for alpha={alpha!r}, n_discard={n_discard}, gain={gain!r}") + if n_discard < L and not np.any(weights): + raise PyAMLException( + f"every inverse weight is zero for alpha={alpha!r}, n_discard={n_discard}, gain={gain!r} " + f"(only n_discard == L = {L} discards the whole spectrum)" + ) + + kinds = [] + for i in range(L): + if i >= k_live: + kinds.append(SpectrumKind.STRUCTURAL) + elif rank_dropped[i]: + kinds.append(SpectrumKind.RANK_DISCARDED) + elif cut[i]: + kinds.append(SpectrumKind.DISCARDED) + else: + kinds.append(SpectrumKind.LIVE) + + matrix = np.zeros((layout.n_cor, 2 * layout.n_bpm)) + matrix[live_columns, :] = (vt.T * weights[:k_live]) @ u.T + singular_values = np.concatenate([s, np.zeros(n_struct)]) + + return PseudoInverse( + matrix=matrix, + singular_values=singular_values, + inverse_weights=weights, + spectrum_kind=kinds, + rank_discarded=rank_discarded, + no_response_correctors=np.flatnonzero(~state.live), + no_response_names=layout.no_response_names, + alpha=alpha, + n_discard=n_discard, + gain=gain, + ) + + +# --------------------------------------------------------------------------- +# Correction step +# --------------------------------------------------------------------------- + +# Reasons under which a plane's step is zeroed and listed whole, whatever the threading. +_WHOLE_PLANE_H = frozenset({Reason.NO_BEAM, Reason.NO_INVERSE, Reason.NO_UPSTREAM, Reason.NO_UPSTREAM_H}) +_WHOLE_PLANE_V = frozenset({Reason.NO_BEAM, Reason.NO_INVERSE, Reason.NO_UPSTREAM, Reason.NO_UPSTREAM_V}) + + +def _float_array(value: Any, field: str, shape: tuple[int, ...], source: str) -> np.ndarray: + """ + Return a float copy of ``value`` with exactly ``shape``. + + NaN is allowed (it carries meaning for readings, references and nothing else); + ±Inf anywhere, a non-numeric entry or any other shape raises PyAMLException + naming ``field``. + """ + try: + array = np.array(value, dtype=float, copy=True) + except (TypeError, ValueError) as exc: + raise PyAMLException(f"{source}: {field} must be an array of real numbers ({exc})") from exc + if array.shape != shape: + raise PyAMLException(f"{source}: {field} must have shape {shape} for the loaded response matrix, got {array.shape}") + if np.any(np.isinf(array)): + raise PyAMLException(f"{source}: {field} must not hold +Inf or -Inf") + return array + + +def _index_array(value: Any, field: str, length: int, source: str) -> np.ndarray: + """Return ``value`` as ``length`` finite, strictly increasing indices, raising PyAMLException otherwise.""" + array = _float_array(value, field, (length,), source) + if np.any(np.isnan(array)): + raise PyAMLException(f"{source}: {field} must not hold NaN") + if np.any(np.diff(array) <= 0.0): + raise PyAMLException(f"{source}: {field} must be strictly increasing") + return array + + +def _bpm_index(value: Any, n_bpm: int, source: str) -> np.ndarray: + """ + Return the first half of the sidecar's ``bpm_index``. + + The sidecar carries one entry per response-matrix row, ``2 * n_bpm`` in all; + both halves must be equal and strictly increasing. + """ + array = _float_array(value, "bpm_index", (2 * n_bpm,), source) + if np.any(np.isnan(array)): + raise PyAMLException(f"{source}: bpm_index must not hold NaN") + first, second = array[:n_bpm], array[n_bpm:] + if not np.array_equal(first, second): + raise PyAMLException(f"{source}: both halves of bpm_index (one entry per response-matrix row) must be equal") + if np.any(np.diff(first) <= 0.0): + raise PyAMLException(f"{source}: bpm_index must be strictly increasing within each half") + return first + + +def _correct( + state: _RMState, + pinv: PseudoInverse, + x: np.ndarray, + y: np.ndarray, + reference: np.ndarray, + bpm_index: np.ndarray, + hcorr_index: np.ndarray, + vcorr_index: np.ndarray, +) -> TrajectoryStep: + """ + Solve one checked set of inputs and thread the result; a pure function. + + ``step = pinv.matrix @ dR`` with ``dR = R - R0`` and NaN set to 0. The last + BPM with beam is the last non-NaN entry of ``x``; in each plane every + corrector whose index exceeds that BPM's index is zeroed (the reference + implementation's ``<=``). The reason is the first match of NO_BEAM, + NO_INVERSE, NO_UPSTREAM, NO_UPSTREAM_H / NO_UPSTREAM_V, ON_REFERENCE, OK; under + NO_BEAM, NO_INVERSE and NO_UPSTREAM both planes are zeroed whole, under + NO_UPSTREAM_H / NO_UPSTREAM_V that plane is. + """ + layout = state.layout + n_h, n_v = layout.n_h, layout.n_v + + d_r = np.concatenate([x, y]) - reference.reshape(-1) + d_r[np.isnan(d_r)] = 0.0 + step = pinv.matrix @ d_r + + with_beam = np.flatnonzero(~np.isnan(x)) + if with_beam.size: + last_bpm: Optional[int] = int(with_beam[-1]) + last_index = bpm_index[last_bpm] + past_h = hcorr_index > last_index + past_v = vcorr_index > last_index + else: + last_bpm = None + past_h = np.ones(n_h, dtype=bool) + past_v = np.ones(n_v, dtype=bool) + upstream_h = bool(np.any(state.live[:n_h] & ~past_h)) + upstream_v = bool(np.any(state.live[n_h:] & ~past_v)) + + if last_bpm is None: + reason = Reason.NO_BEAM + elif not np.any(pinv.inverse_weights): + reason = Reason.NO_INVERSE + elif not upstream_h and not upstream_v: + reason = Reason.NO_UPSTREAM + elif not upstream_h: + reason = Reason.NO_UPSTREAM_H + elif not upstream_v: + reason = Reason.NO_UPSTREAM_V + elif not np.any(d_r): + reason = Reason.ON_REFERENCE + else: + reason = Reason.OK + + zero_h = np.ones(n_h, dtype=bool) if reason in _WHOLE_PLANE_H else past_h + zero_v = np.ones(n_v, dtype=bool) if reason in _WHOLE_PLANE_V else past_v + step[np.concatenate([zero_h, zero_v])] = 0.0 + + return TrajectoryStep( + step=step, + names=layout.hcorr_names + layout.vcorr_names, + n_h=n_h, + last_bpm=last_bpm, + zeroed_h=tuple(name for name, zeroed in zip(layout.hcorr_names, zero_h, strict=True) if zeroed), + zeroed_v=tuple(name for name, zeroed in zip(layout.vcorr_names, zero_v, strict=True) if zeroed), + pseudo_inverse=pinv, + reason=reason, + ) + + +def _read_file(path: Union[str, Path], settings: _Settings) -> _RMState: + """Read and check the response-matrix file at ``path``; every failure is a PyAMLException naming it.""" + source = str(path) + try: + data = OrbitResponseMatrixData.load(source) + except Exception as exc: + message = getattr(exc, "message", None) or str(exc) + raise PyAMLException(f"{source}: cannot read the response matrix: {message}") from exc + if not isinstance(data, OrbitResponseMatrixData): + raise PyAMLException(f"{source}: the file holds a {type(data).__name__}, expected an OrbitResponseMatrixData") + return _build_state(_rm_fields(data, source), source, settings) + + +@register_schema +class Trajectory(TuningTool, DynamicValidation): + """ + First-turn trajectory correction from a trajectory response matrix. + + The tool is a response matrix plus default ``alpha``, ``n_discard`` and + ``gain``. It reads no hardware and needs no peer. Every fact of the response + matrix is checked once, when it is loaded, and published as :attr:`layout`. + :meth:`load` is the only method that changes the tool, and it replaces the + response matrix atomically; :meth:`pseudo_inverse` and :meth:`correct` are + pure functions of the tool and their arguments, each returning one frozen + record that carries the settings it used. + + Parameters + ---------- + name : str + Name of the tool. + response_matrix : str, Path, mapping or OrbitResponseMatrixData + Path to an :class:`~.OrbitResponseMatrixData` file, a mapping of its six + fields, or an instance. Rows are BPM readings, every horizontal one then + every vertical one, with equal counts; columns are correctors, every + horizontal one then every vertical one. It carries no RF response. + alpha : float + Tikhonov parameter, a finite real ``>= 0``. + n_discard : int + Number of trailing singular-spectrum positions to zero, in ``[0, L]``. + gain : float + Gain, a finite real ``> 0``. + + Attributes + ---------- + layout : TrajectoryLayout or None + Facts of the loaded response matrix; None when none is loaded. + response_matrix : OrbitResponseMatrixData or None + A copy of the loaded response matrix; None when none is loaded. + + Methods + ------- + load(load_path) + Replace the response matrix with the one in a file. + pseudo_inverse(alpha=None, n_discard=None, gain=None) + The guarded, damped pseudo-inverse of the response matrix. + correct(x, y, reference=None, *, bpm_index, hcorr_index, vcorr_index, ...) + The corrector step for one set of first-turn BPM readings. + + Configuration + ------------- + .. code-block:: yaml + + - type: pyaml.tuning_tools.trajectory + name: TRAJECTORY + response_matrix: ${path:trajectory_rm.json} + alpha: 0.0 + n_discard: 0 + gain: 1.0 + + Notes + ----- + **The x-row rule.** Threading follows the reference implementation (the ALS + ``calcCMstep`` routine): the last BPM with beam is the last non-NaN entry of + ``x``, and ``y`` never decides it. In each plane every corrector whose lattice + index exceeds that BPM's index is zeroed; a corrector at the BPM's own index + is kept. An *upstream corrector* is a live corrector (one with a response) at + or before that BPM. + + **The reason order.** A step's reason is the first match, in the fixed order + NO_BEAM, NO_INVERSE, NO_UPSTREAM, NO_UPSTREAM_H / NO_UPSTREAM_V, ON_REFERENCE, OK, + of: no BPM with beam (every entry of ``x`` NaN); every inverse weight zero + (``n_discard == L``); no upstream corrector in either plane; none in that + plane; the NaN-cleaned deviation identically zero; otherwise OK. Under NO_BEAM, + NO_INVERSE and NO_UPSTREAM both planes are zeroed whole, under NO_UPSTREAM_H / + NO_UPSTREAM_V that plane is, and otherwise exactly the correctors past the + last BPM with beam; ``zeroed_h`` and ``zeroed_v`` list them for every reason. + An all-zero step never carries OK; a non-OK reason does not imply an all-zero + step (NO_UPSTREAM_H / NO_UPSTREAM_V correct the other plane), so a caller + refuses to apply on ``all_zero``, never on the reason. + + **The four divergences.** The tool equals the reference implementation + (``SCgetPinv`` and ``calcCMstep``) on every parity case of the frozen goldens + and differs from it in exactly four frozen cases: + + (a) ``dead_last_plain``, rank-deficient at ``alpha == 0`` (an inverse + divergence, reason OK): the reference applies no rank guard, so its + inverse is not finite; the tool applies the guard, equals MATLAB + ``pinv``, and gives correctors with no response an exact-zero step at + every ``alpha``. + (b) ``first_bpm_only``, beam only at the first BPM, before any corrector + (verdict only): the tool answers NO_UPSTREAM with an all-zero step; the + reference zeroes nothing and its step is roundoff, because the deviation + lies outside the response matrix's range. + (c) ``one_plane_upstream``, one plane without a live corrector at or before + the last BPM with beam (verdict only in that plane): the tool zeroes that + plane under NO_UPSTREAM_H / NO_UPSTREAM_V; the other plane is parity. + (d) ``no_beam``, no BPM with beam (a step divergence): the tool answers + NO_BEAM and zeroes every corrector; the reference falls back to the last + BPM and zeroes no live corrector, so its vertical step is non-zero. + + ``n_discard == L`` (NO_INVERSE) is parity, not a divergence: the reference's + diagonal is all zero there too. + + **The error rule.** A bad constructor argument or bad response-matrix content + raises at construction, ``PyAMLConfigException`` from pyAML's validation layer + (and from ``Factory.build``) and ``PyAMLException`` otherwise. A path that is + not a file at construction logs a warning and leaves :attr:`layout` None, so + every call raises ``PyAMLException``. A missing or bad file at :meth:`load` + raises ``PyAMLException`` naming the path and leaves the tool unchanged. A + bad per-call argument of :meth:`pseudo_inverse` or :meth:`correct` (a setting + of the wrong type or out of range, a reading or index array whose shape does + not match :attr:`layout`, +Inf or -Inf anywhere, a non-increasing index array, + unequal ``bpm_index`` halves) raises ``PyAMLException`` naming the argument. A + mapping holding any key other than the six ``OrbitResponseMatrixData`` + fields, a build key such as ``type`` included, is rejected. + """ + + def __init__( + self, + name: str, + response_matrix: Union[str, Path, OrbitResponseMatrixData], + alpha: float = 0.0, + n_discard: int = 0, + gain: float = 1.0, + ): + super().__init__(name) + self._settings = _resolve_settings(alpha, n_discard, gain, L=None) + self._state: Optional[_RMState] = None + if isinstance(response_matrix, (str, Path)): + if not Path(response_matrix).is_file(): + logger.warning(f"{name}: response matrix {response_matrix} is not a file; no response matrix is loaded") + return + self._state = _read_file(response_matrix, self._settings) + else: + source = f"{name}: response_matrix" + self._state = _build_state(_rm_fields(response_matrix, source), source, self._settings) + + def load(self, load_path: Path) -> None: + """ + Replace the response matrix with the one in a file. + + The new matrix is checked completely before it replaces the old one, so a + failed load leaves the tool unchanged. + + Parameters + ---------- + load_path : Path + Path to an :class:`~.OrbitResponseMatrixData` file. + + Raises + ------ + PyAMLException + When the file is missing, cannot be read, or fails a check, a configured + ``n_discard`` larger than the new ``L`` included. The message names the + path. + """ + self._state = _read_file(load_path, self._settings) + + def pseudo_inverse( + self, + alpha: Optional[float] = None, + n_discard: Optional[int] = None, + gain: Optional[float] = None, + ) -> PseudoInverse: + """ + Compute the guarded, damped pseudo-inverse of the response matrix. + + A pure function of the loaded response matrix, the configured settings and + the overrides: nothing is stored on the tool, and the returned record is + immutable. Correctors with no response are exact-zero rows of the inverse + at every ``alpha``. + + Parameters + ---------- + alpha : float, optional + Tikhonov parameter, a finite real ``>= 0``; None means the configured + value. At ``alpha == 0`` the singular values below the rank guard + ``max(2*n_bpm, n_cor) * eps * s_max`` are dropped instead. + n_discard : int, optional + Number of trailing positions of the length-``L`` spectrum to zero, in + ``[0, L]``; None means the configured value. The structural zeros are + the last positions, so a discard consumes them before any live value. + gain : float, optional + Gain multiplying every weight, a finite real ``> 0``; None means the + configured value. + + Returns + ------- + PseudoInverse + The ``n_cor x 2*n_bpm`` inverse with its spectrum, the kind of each + position, the no-response correctors and the settings used. + + Raises + ------ + PyAMLException + When no response matrix is loaded; when a setting has the wrong type or + is out of range; when a weight is not finite after the cut; or when + every weight is zero while ``n_discard < L`` (``n_discard == L`` returns + the all-zero inverse). + """ + if self._state is None: + raise PyAMLException(f"{self.name}: no response matrix is loaded") + settings = _resolve_settings(alpha, n_discard, gain, L=self._state.layout.L, defaults=self._settings) + return _pseudo_inverse(self._state, settings) + + def correct( + self, + x: Any, + y: Any, + reference: Any = None, + *, + bpm_index: Any, + hcorr_index: Any, + vcorr_index: Any, + alpha: Optional[float] = None, + n_discard: Optional[int] = None, + gain: Optional[float] = None, + ) -> TrajectoryStep: + """ + Compute the corrector step for one set of first-turn BPM readings. + + A pure function of the loaded response matrix, the configured settings and + the arguments: nothing is stored on the tool, the arguments are not + modified, and the returned record is immutable. The solve is one joint + full-matrix product, ``step = pseudo_inverse.matrix @ dR`` with ``dR = R - + R0`` (all horizontal readings then all vertical ones) and NaN set to 0; + the caller applies ``-step``. + + Parameters + ---------- + x, y : array_like + Horizontal and vertical readings of the ``n_bpm`` BPMs, in the row + order of the response matrix; NaN means no beam at that BPM. + reference : array_like or None + ``(x_ref, y_ref)`` of shape ``(2, n_bpm)``; NaN means no reference at + that BPM. None means a zero reference. + bpm_index : array_like + The sidecar's ``bpm_index``, verbatim: one entry per response-matrix + row, ``2 * n_bpm`` in all, both halves equal and strictly increasing. + hcorr_index, vcorr_index : array_like + The lattice index of each horizontal and vertical corrector, in column + order, strictly increasing, of lengths ``n_h`` and ``n_v``. + alpha, n_discard, gain : optional + Per-call overrides, as for :meth:`pseudo_inverse`; None means the + configured value. + + Returns + ------- + TrajectoryStep + The step in column order with the corrector names, ``n_h``, the + position of the last BPM with beam, the correctors zeroed per plane, + the :class:`PseudoInverse` solved with and the reason. + + Raises + ------ + PyAMLException + When no response matrix is loaded; when a setting is rejected as in + :meth:`pseudo_inverse`; when a reading, the reference or an index + array has a shape that does not match :attr:`layout`, holds +Inf or + -Inf (or NaN in an index array), is not strictly increasing, or when + the two halves of ``bpm_index`` differ. The message names the + argument. + + Notes + ----- + Threading follows the reference implementation: the last BPM with beam is + the last non-NaN entry of ``x`` (``y`` never decides it), and in each + plane every corrector whose index exceeds that BPM's index is zeroed; a + corrector at the BPM's own index is kept. An upstream corrector is a live + corrector at or before that BPM. The reason is the first match of + NO_BEAM, NO_INVERSE, NO_UPSTREAM, NO_UPSTREAM_H / NO_UPSTREAM_V, + ON_REFERENCE, OK; see the class notes for the predicates and for where + the result deliberately differs from the reference implementation. + """ + if self._state is None: + raise PyAMLException(f"{self.name}: no response matrix is loaded") + state = self._state + layout = state.layout + settings = _resolve_settings(alpha, n_discard, gain, L=layout.L, defaults=self._settings) + source = f"{self.name}: correct" + n_bpm = layout.n_bpm + x_values = _float_array(x, "x", (n_bpm,), source) + y_values = _float_array(y, "y", (n_bpm,), source) + if reference is None: + reference_values = np.zeros((2, n_bpm)) + else: + reference_values = _float_array(reference, "reference", (2, n_bpm), source) + bpm = _bpm_index(bpm_index, n_bpm, source) + hcorr = _index_array(hcorr_index, "hcorr_index", layout.n_h, source) + vcorr = _index_array(vcorr_index, "vcorr_index", layout.n_v, source) + pinv = _pseudo_inverse(state, settings) + return _correct(state, pinv, x_values, y_values, reference_values, bpm, hcorr, vcorr) + + @property + def layout(self) -> Optional[TrajectoryLayout]: + """Facts of the loaded response matrix; None when none is loaded.""" + return None if self._state is None else self._state.layout + + @property + def response_matrix(self) -> Optional[OrbitResponseMatrixData]: + """A copy of the loaded response matrix; None when none is loaded.""" + return None if self._state is None else copy.deepcopy(self._state.response_matrix) diff --git a/tests/tuning_tools/test_trajectory.py b/tests/tuning_tools/test_trajectory.py new file mode 100644 index 000000000..c1391da76 --- /dev/null +++ b/tests/tuning_tools/test_trajectory.py @@ -0,0 +1,2580 @@ +"""Tests for :mod:`pyaml.tuning_tools.trajectory`. + +Every test that needs the frozen goldens file carries ``golden`` in its name, so +``pytest -k "not golden"`` runs the rest without it. The module clears pyAML's +element registry itself, because it must also run without the repository's +``conftest.py``. +""" + +import copy +import dataclasses +import hashlib +import json +import logging +import math +import os +from pathlib import Path + +import numpy as np +import pytest + +from pyaml.common.exception import PyAMLConfigException, PyAMLException +from pyaml.configuration.factory import Factory +from pyaml.tuning_tools.orbit_response_matrix_data import OrbitResponseMatrixData +from pyaml.tuning_tools.trajectory import ( + PseudoInverse, + Reason, + SpectrumKind, + Trajectory, + TrajectoryLayout, + TrajectoryStep, + _resolve_settings, + _Settings, +) + + +@pytest.fixture(autouse=True) +def _clear_element_registry(): + Factory.clear() + yield + Factory.clear() + + +# --------------------------------------------------------------------------- +# helpers +# --------------------------------------------------------------------------- + + +def _layout(n_bpm=4, n_h=3, n_v=3, dead=()): + return TrajectoryLayout( + bpm_names_h=[f"BPM{i}" for i in range(n_bpm)], + bpm_names_v=[f"BPM{i}" for i in range(n_bpm)], + hcorr_names=[f"HCM{i}" for i in range(n_h)], + vcorr_names=[f"VCM{i}" for i in range(n_v)], + no_response_names=list(dead), + ) + + +def _pinv(n_cor=6, n_obs=8, length=6, **overrides): + kwargs = dict( + matrix=np.arange(n_cor * n_obs, dtype=float).reshape(n_cor, n_obs), + singular_values=np.linspace(3.0, 1.0, length), + inverse_weights=1.0 / np.linspace(3.0, 1.0, length), + spectrum_kind=[SpectrumKind.LIVE] * length, + rank_discarded=0, + no_response_correctors=[], + no_response_names=[], + alpha=0.0, + n_discard=0, + gain=1.0, + ) + kwargs.update(overrides) + return PseudoInverse(**kwargs) + + +def _step(step=(1.0, 0.0, -2.0, 0.5, 0.0, 0.0), reason=Reason.OK, n_h=3, **overrides): + kwargs = dict( + step=np.asarray(step, dtype=float), + names=("HCM0", "HCM1", "HCM2", "VCM0", "VCM1", "VCM2"), + n_h=n_h, + last_bpm=3, + zeroed_h=(), + zeroed_v=(), + pseudo_inverse=_pinv(), + reason=reason, + ) + kwargs.update(overrides) + return TrajectoryStep(**kwargs) + + +# --------------------------------------------------------------------------- +# enums +# --------------------------------------------------------------------------- + + +def test_reason_members_are_the_closed_set(): + assert [m.name for m in Reason] == [ + "NO_BEAM", + "NO_INVERSE", + "NO_UPSTREAM", + "NO_UPSTREAM_H", + "NO_UPSTREAM_V", + "ON_REFERENCE", + "OK", + ] + + +def test_spectrum_kind_members_are_the_closed_set(): + assert [m.name for m in SpectrumKind] == ["LIVE", "RANK_DISCARDED", "DISCARDED", "STRUCTURAL"] + + +@pytest.mark.parametrize("enum_cls", [Reason, SpectrumKind]) +def test_enums_serialise_as_their_names(enum_cls): + for member in enum_cls: + assert member.name == member.value + text = json.dumps(member) + assert text == f'"{member.name}"' + assert json.loads(text) == member.name == member.value + assert enum_cls(json.loads(text)) is member + assert json.loads(json.dumps(list(enum_cls))) == [m.name for m in enum_cls] + + +# --------------------------------------------------------------------------- +# TrajectoryLayout +# --------------------------------------------------------------------------- + + +def test_layout_stores_name_fields_as_tuples_of_str(): + layout = _layout(dead=["HCM2"]) + for field in ("bpm_names_h", "bpm_names_v", "hcorr_names", "vcorr_names", "no_response_names"): + value = getattr(layout, field) + assert isinstance(value, tuple) + assert all(isinstance(name, str) for name in value) + assert layout.no_response_names == ("HCM2",) + + +def test_layout_rejects_non_str_names(): + with pytest.raises(TypeError): + TrajectoryLayout( + bpm_names_h=["B0"], + bpm_names_v=["B0"], + hcorr_names=[1], + vcorr_names=["V0"], + no_response_names=[], + ) + + +def test_layout_counts_are_derived_from_names(): + layout = _layout(n_bpm=4, n_h=3, n_v=2, dead=["HCM2"]) + assert layout.n_bpm == 4 + assert layout.n_h == 3 + assert layout.n_v == 2 + assert layout.n_cor == 5 + assert layout.n_live == 4 + assert layout.L == min(2 * 4, 5) == 5 + assert layout.k_live == min(2 * 4, 4) == 4 + assert layout.n_struct == 1 + + +@pytest.mark.parametrize( + "n_bpm, n_h, n_v, dead", + [ + (16, 12, 12, ()), + (16, 12, 12, ("HCM11", "VCM11")), + (2, 3, 3, ("HCM0",)), # n_cor > 2*n_bpm: one dead column leaves no structural zero + (2, 3, 3, ("HCM0", "HCM1", "VCM0")), + (72, 72, 72, ()), + (3, 1, 1, ("VCM0",)), + ], +) +def test_layout_identities(n_bpm, n_h, n_v, dead): + layout = _layout(n_bpm=n_bpm, n_h=n_h, n_v=n_v, dead=dead) + assert layout.n_cor == n_h + n_v + assert layout.n_live == layout.n_cor - len(dead) + assert layout.L == min(2 * layout.n_bpm, layout.n_cor) + assert layout.n_struct == layout.L - layout.k_live + assert layout.k_live == min(2 * layout.n_bpm, layout.n_live) + assert 0 <= layout.n_struct <= layout.L + + +def test_layout_n_cor_above_two_n_bpm_has_no_structural_zero(): + layout = _layout(n_bpm=2, n_h=3, n_v=3, dead=("HCM0",)) + assert layout.L == 4 + assert layout.k_live == 4 + assert layout.n_struct == 0 + + +def test_layout_is_value_compared_and_hashable(): + a = _layout(dead=["HCM2"]) + b = _layout(dead=("HCM2",)) + assert a == b + assert hash(a) == hash(b) + assert len({a, b}) == 1 + + +def test_layout_with_a_different_dead_column_is_unequal(): + a = _layout(dead=["HCM2"]) + b = _layout(dead=["VCM0", "HCM2"]) + assert a.bpm_names_h == b.bpm_names_h + assert a.hcorr_names == b.hcorr_names and a.vcorr_names == b.vcorr_names + assert a != b + assert a.n_live != b.n_live + + +def test_layout_with_different_names_is_unequal(): + assert _layout(n_bpm=4) != _layout(n_bpm=5) + + +def test_layout_is_frozen_and_slotted(): + layout = _layout() + with pytest.raises(dataclasses.FrozenInstanceError): + layout.hcorr_names = ("X",) + assert not hasattr(layout, "__dict__") + + +# --------------------------------------------------------------------------- +# PseudoInverse +# --------------------------------------------------------------------------- + + +def test_pseudo_inverse_arrays_are_read_only(): + pinv = _pinv(no_response_correctors=[5], no_response_names=["VCM2"]) + for field in ("matrix", "singular_values", "inverse_weights", "no_response_correctors"): + array = getattr(pinv, field) + assert isinstance(array, np.ndarray) + assert not array.flags.writeable + with pytest.raises(ValueError): + pinv.matrix[0, 0] = 1.0 + with pytest.raises(ValueError): + pinv.singular_values[0] = 1.0 + with pytest.raises(ValueError): + pinv.inverse_weights[:] = 0.0 + with pytest.raises(ValueError): + pinv.no_response_correctors[0] = 0 + + +def test_pseudo_inverse_does_not_alias_its_inputs(): + matrix = np.ones((6, 8)) + weights = np.ones(6) + pinv = _pinv(matrix=matrix, inverse_weights=weights) + matrix[0, 0] = 99.0 + weights[0] = 99.0 + assert pinv.matrix[0, 0] == 1.0 + assert pinv.inverse_weights[0] == 1.0 + assert matrix.flags.writeable and weights.flags.writeable + + +def test_pseudo_inverse_fields_and_types(): + pinv = _pinv( + spectrum_kind=["LIVE"] * 4 + [SpectrumKind.DISCARDED, "STRUCTURAL"], + no_response_correctors=[5], + no_response_names=["VCM2"], + rank_discarded=0, + alpha=0.5, + n_discard=2, + gain=0.7, + ) + assert [f.name for f in dataclasses.fields(PseudoInverse)] == [ + "matrix", + "singular_values", + "inverse_weights", + "spectrum_kind", + "rank_discarded", + "no_response_correctors", + "no_response_names", + "alpha", + "n_discard", + "gain", + ] + assert pinv.spectrum_kind == (SpectrumKind.LIVE,) * 4 + (SpectrumKind.DISCARDED, SpectrumKind.STRUCTURAL) + assert all(isinstance(kind, SpectrumKind) for kind in pinv.spectrum_kind) + assert json.loads(json.dumps(list(pinv.spectrum_kind)))[-1] == "STRUCTURAL" + assert pinv.no_response_names == ("VCM2",) + assert pinv.no_response_correctors.tolist() == [5] + assert (pinv.alpha, pinv.n_discard, pinv.gain) == (0.5, 2, 0.7) + + +def test_pseudo_inverse_spectrum_arrays_are_index_aligned(): + with pytest.raises(ValueError): + _pinv(inverse_weights=np.ones(5)) + with pytest.raises(ValueError): + _pinv(spectrum_kind=[SpectrumKind.LIVE] * 5) + + +def test_pseudo_inverse_rejects_wrong_array_ranks(): + with pytest.raises(ValueError): + _pinv(matrix=np.ones(6)) + with pytest.raises(ValueError): + _pinv(singular_values=np.ones((6, 1)), inverse_weights=np.ones((6, 1))) + + +def test_pseudo_inverse_is_frozen_slotted_and_identity_compared(): + a = _pinv() + b = _pinv() + assert a == a + assert a != b # eq=False: identity, and no ambiguous ndarray truth value + hash(a) + with pytest.raises(dataclasses.FrozenInstanceError): + a.gain = 2.0 + assert not hasattr(a, "__dict__") + + +# --------------------------------------------------------------------------- +# TrajectoryStep +# --------------------------------------------------------------------------- + + +def test_step_fields(): + assert [f.name for f in dataclasses.fields(TrajectoryStep)] == [ + "step", + "names", + "n_h", + "last_bpm", + "zeroed_h", + "zeroed_v", + "pseudo_inverse", + "reason", + ] + + +def test_step_array_is_read_only_and_not_aliased(): + raw = np.array([1.0, 0.0, -2.0, 0.5, 0.0, 0.0]) + step = _step(step=raw) + raw[0] = 42.0 + assert step.step[0] == 1.0 + assert not step.step.flags.writeable + with pytest.raises(ValueError): + step.step[0] = 3.0 + with pytest.raises(ValueError): + step.step_h[0] = 3.0 + with pytest.raises(ValueError): + step.step_v[0] = 3.0 + + +def test_step_plane_views(): + step = _step() + np.testing.assert_array_equal(step.step_h, [1.0, 0.0, -2.0]) + np.testing.assert_array_equal(step.step_v, [0.5, 0.0, 0.0]) + assert step.names[: step.n_h] == ("HCM0", "HCM1", "HCM2") + + +def test_step_plane_views_follow_n_h(): + step = _step(n_h=2) + np.testing.assert_array_equal(step.step_h, [1.0, 0.0]) + np.testing.assert_array_equal(step.step_v, [-2.0, 0.5, 0.0, 0.0]) + + +def test_step_all_zero(): + assert not _step().all_zero + assert _step(step=np.zeros(6), reason=Reason.NO_BEAM, last_bpm=None).all_zero + assert _step(step=-np.zeros(6), reason=Reason.ON_REFERENCE).all_zero + + +def test_step_name_fields_are_tuples(): + step = _step(names=["HCM0", "HCM1", "HCM2", "VCM0", "VCM1", "VCM2"], zeroed_h=["HCM2"], zeroed_v=["VCM2"]) + assert step.names == ("HCM0", "HCM1", "HCM2", "VCM0", "VCM1", "VCM2") + assert step.zeroed_h == ("HCM2",) + assert step.zeroed_v == ("VCM2",) + + +def test_step_reason_is_coerced_to_the_enum(): + step = _step(reason="ON_REFERENCE", step=np.zeros(6)) + assert step.reason is Reason.ON_REFERENCE + + +def test_step_rejects_names_of_the_wrong_length(): + with pytest.raises(ValueError): + _step(names=("HCM0", "HCM1")) + + +@pytest.mark.parametrize( + "reason, status", + [ + (Reason.NO_BEAM, "no BPM with beam"), + (Reason.NO_INVERSE, "every singular value is discarded; no correction is possible"), + (Reason.NO_UPSTREAM, "no corrector upstream of the last BPM with beam"), + (Reason.NO_UPSTREAM_H, "no horizontal corrector upstream of the last BPM with beam"), + (Reason.NO_UPSTREAM_V, "no vertical corrector upstream of the last BPM with beam"), + (Reason.ON_REFERENCE, "already on reference"), + (Reason.OK, ""), + ], +) +def test_step_status_is_derived_from_reason(reason, status): + assert _step(reason=reason).status == status + + +def test_step_is_frozen_slotted_and_identity_compared(): + a = _step() + b = _step() + assert a != b + hash(a) + with pytest.raises(dataclasses.FrozenInstanceError): + a.reason = Reason.NO_BEAM + assert not hasattr(a, "__dict__") + + +def test_step_serialises_reason_and_status(): + step = _step(reason=Reason.NO_UPSTREAM_V) + payload = json.loads(json.dumps({"reason": step.reason, "status": step.status, "all_zero": step.all_zero})) + assert payload == { + "reason": "NO_UPSTREAM_V", + "status": "no vertical corrector upstream of the last BPM with beam", + "all_zero": False, + } + + +# --------------------------------------------------------------------------- +# settings resolution +# --------------------------------------------------------------------------- +# +# ``_resolve_settings`` is the one routine every path goes through: construction, +# construction under ``validate=False``, and every per-call override. It is a pure +# function of its arguments and ``L``, so it is tested here before the class exists. + +_DEFAULTS = _Settings(alpha=0.5, n_discard=2, gain=0.8) + + +def test_resolve_returns_python_scalars_of_the_documented_types(): + settings = _resolve_settings(0.25, 3, 0.5, L=6) + assert settings == _Settings(alpha=0.25, n_discard=3, gain=0.5) + assert type(settings.alpha) is float + assert type(settings.n_discard) is int + assert type(settings.gain) is float + + +def test_resolve_settings_record_is_frozen(): + settings = _resolve_settings(0.0, 0, 1.0, L=6) + with pytest.raises(dataclasses.FrozenInstanceError): + settings.alpha = 1.0 + + +def test_resolve_accepts_ints_for_the_real_fields(): + settings = _resolve_settings(0, 0, 1, L=6) + assert settings == _Settings(alpha=0.0, n_discard=0, gain=1.0) + assert type(settings.alpha) is float and type(settings.gain) is float + + +def test_resolve_none_per_call_means_the_configured_value(): + assert _resolve_settings(None, None, None, L=6, defaults=_DEFAULTS) == _DEFAULTS + assert _resolve_settings(0.1, None, None, L=6, defaults=_DEFAULTS) == _Settings(0.1, 2, 0.8) + assert _resolve_settings(None, 5, None, L=6, defaults=_DEFAULTS) == _Settings(0.5, 5, 0.8) + assert _resolve_settings(None, None, 2.0, L=6, defaults=_DEFAULTS) == _Settings(0.5, 2, 2.0) + + +@pytest.mark.parametrize("field", ["alpha", "n_discard", "gain"]) +def test_resolve_none_without_defaults_raises_naming_the_field(field): + # Construction has no configured value to fall back on. + kwargs = {"alpha": 0.0, "n_discard": 0, "gain": 1.0, field: None} + with pytest.raises(PyAMLException, match=field): + _resolve_settings(**kwargs, L=6) + + +def test_resolve_rechecks_configured_defaults_against_l(): + # A configured n_discard that no longer fits L (load() shrank it) raises even + # when the call passes None. + with pytest.raises(PyAMLException, match="n_discard"): + _resolve_settings(None, None, None, L=1, defaults=_DEFAULTS) + + +@pytest.mark.parametrize("alpha", [0.0, -0.0, 1e-12, 3.5, 1e150]) +def test_resolve_alpha_in_range(alpha): + resolved = _resolve_settings(alpha, 0, 1.0, L=6).alpha + assert resolved == alpha + assert math.copysign(1.0, resolved) == 1.0 + + +@pytest.mark.parametrize("alpha", [-1e-300, -1.0, math.inf, -math.inf, math.nan, 1e200, 1e155], ids=lambda v: repr(v)) +def test_resolve_alpha_out_of_range_raises_naming_alpha(alpha): + with pytest.raises(PyAMLException, match="alpha"): + _resolve_settings(alpha, 0, 1.0, L=6) + + +def test_resolve_alpha_whose_square_overflows_raises(): + with pytest.raises(PyAMLException, match="alpha"): + _resolve_settings(1e200, 0, 1.0, L=6) + + +@pytest.mark.parametrize("n_discard", [0, 1, 5, 6]) +def test_resolve_n_discard_in_range(n_discard): + assert _resolve_settings(0.0, n_discard, 1.0, L=6).n_discard == n_discard + + +@pytest.mark.parametrize("n_discard", [-1, 7, 100]) +def test_resolve_n_discard_out_of_range_raises_naming_n_discard(n_discard): + with pytest.raises(PyAMLException, match="n_discard"): + _resolve_settings(0.0, n_discard, 1.0, L=6) + + +def test_resolve_n_discard_equal_to_l_is_allowed_and_l_plus_one_is_not(): + assert _resolve_settings(0.0, 4, 1.0, L=4).n_discard == 4 + with pytest.raises(PyAMLException, match="n_discard"): + _resolve_settings(0.0, 5, 1.0, L=4) + + +def test_resolve_without_l_checks_only_the_lower_bound(): + # L is None while no response matrix is loaded; load() re-checks the bound. + assert _resolve_settings(0.0, 1000, 1.0, L=None).n_discard == 1000 + with pytest.raises(PyAMLException, match="n_discard"): + _resolve_settings(0.0, -1, 1.0, L=None) + + +@pytest.mark.parametrize("gain", [1e-300, 0.5, 1.0, 10.0]) +def test_resolve_gain_in_range(gain): + assert _resolve_settings(0.0, 0, gain, L=6).gain == gain + + +@pytest.mark.parametrize("gain", [0.0, -0.0, -1.0, math.inf, -math.inf, math.nan], ids=lambda v: repr(v)) +def test_resolve_gain_out_of_range_raises_naming_gain(gain): + with pytest.raises(PyAMLException, match="gain"): + _resolve_settings(0.0, 0, gain, L=6) + + +@pytest.mark.parametrize( + "field, value", + [ + ("alpha", "0.1"), + ("alpha", True), + ("alpha", 1 + 0j), + ("alpha", [0.1]), + ("alpha", np.array([0.1])), + ("n_discard", 1.0), + ("n_discard", 1.5), + ("n_discard", "1"), + ("n_discard", True), + ("n_discard", np.bool_(True)), + ("n_discard", np.float64(1.0)), + ("gain", "1"), + ("gain", False), + ("gain", np.bool_(True)), + ("gain", object()), + ], + ids=lambda v: type(v).__name__ if not isinstance(v, str) else repr(v), +) +def test_resolve_wrong_type_raises_naming_the_field(field, value): + kwargs = {"alpha": 0.0, "n_discard": 0, "gain": 1.0, field: value} + with pytest.raises(PyAMLException, match=field): + _resolve_settings(**kwargs, L=6) + + +def test_resolve_wrong_type_is_also_rejected_as_a_per_call_override(): + with pytest.raises(PyAMLException, match="n_discard"): + _resolve_settings(None, 1.0, None, L=6, defaults=_DEFAULTS) + + +def test_resolve_accepts_numpy_scalars_and_returns_python_scalars(): + settings = _resolve_settings(np.float64(0.25), np.int64(3), np.float32(0.5), L=6) + assert settings == _Settings(alpha=0.25, n_discard=3, gain=0.5) + assert type(settings.alpha) is float + assert type(settings.n_discard) is int + assert type(settings.gain) is float + + +def test_resolve_accepts_zero_d_arrays_as_read_from_an_npz(): + # np.load(...)[key] of a stored scalar is a 0-d ndarray, not a numpy scalar. + settings = _resolve_settings(np.array(0.25), np.array(3, dtype=np.int64), np.array(2.0), L=6) + assert settings == _Settings(alpha=0.25, n_discard=3, gain=2.0) + assert type(settings.n_discard) is int + + +def test_resolve_numpy_scalars_are_range_checked(): + with pytest.raises(PyAMLException, match="n_discard"): + _resolve_settings(0.0, np.int64(7), 1.0, L=6) + with pytest.raises(PyAMLException, match="alpha"): + _resolve_settings(np.float64(np.nan), 0, 1.0, L=6) + with pytest.raises(PyAMLException, match="gain"): + _resolve_settings(0.0, 0, np.array(0.0), L=6) + + +def test_resolve_is_pure(): + defaults = _Settings(alpha=0.5, n_discard=2, gain=0.8) + alpha = np.array(0.25) + first = _resolve_settings(alpha, None, None, L=6, defaults=defaults) + second = _resolve_settings(alpha, None, None, L=6, defaults=defaults) + assert first == second + assert defaults == _Settings(alpha=0.5, n_discard=2, gain=0.8) + assert alpha == 0.25 + + +# --------------------------------------------------------------------------- +# construction, the RM entry point and load() +# +# The tool is pure: it reads no hardware and needs no holder or peer, so these +# tests construct it directly (and through Factory.build from a config dict). +# Every response-matrix file they read is written under tmp_path by _rm_fields +# and _write_rm below; the module reads no other file but the case table and the +# goldens npz. Every Factory.build call uses a fresh element name, and every +# Factory-route assertion matches a message naming the rejected field or the RM +# path, so a duplicate-name rejection can never satisfy it. +# --------------------------------------------------------------------------- + +_TOOL_TYPE = "pyaml.tuning_tools.trajectory" + + +def _rm_fields(n_bpm=4, n_h=3, n_v=3, dead=(), scale=1.0): + """The six OrbitResponseMatrixData fields of a small causal RM; ``dead`` names zero columns.""" + hcorr = [f"HCM{i}" for i in range(n_h)] + vcorr = [f"VCM{i}" for i in range(n_v)] + rng = np.random.default_rng(7) + matrix = scale * rng.uniform(0.5, 1.5, size=(2 * n_bpm, n_h + n_v)) + for j, name in enumerate(hcorr + vcorr): + if name in dead: + matrix[:, j] = 0.0 + return { + "matrix": matrix.tolist(), + "observable_names": [f"BPM{i}:x" for i in range(n_bpm)] + [f"BPM{i}:y" for i in range(n_bpm)], + "variable_names": hcorr + vcorr, + "rf_response": None, + "variable_planes": ["H"] * n_h + ["V"] * n_v, + "observable_planes": ["H"] * n_bpm + ["V"] * n_bpm, + } + + +def _write_rm(path, fields=None, type_key="pyaml.tuning_tools.orbit_response_matrix_data", **kwargs): + body = dict(_rm_fields(**kwargs) if fields is None else fields) + if body.get("rf_response") is None: + body.pop("rf_response", None) + if type_key is not None: + body["type"] = type_key + path.write_text(json.dumps(body)) + return path + + +def _expected_layout(n_bpm=4, n_h=3, n_v=3, dead=()): + return TrajectoryLayout( + bpm_names_h=[f"BPM{i}:x" for i in range(n_bpm)], + bpm_names_v=[f"BPM{i}:y" for i in range(n_bpm)], + hcorr_names=[f"HCM{i}" for i in range(n_h)], + vcorr_names=[f"VCM{i}" for i in range(n_v)], + no_response_names=list(dead), + ) + + +def _config(name, response_matrix, **settings): + return {"type": _TOOL_TYPE, "name": name, "response_matrix": response_matrix, **settings} + + +def _snapshot(tool): + rm = tool.response_matrix + return tool.layout, None if rm is None else json.dumps(dataclasses.asdict(rm)) + + +def test_trajectory_construction_forms_give_the_same_layout(tmp_path): + path = _write_rm(tmp_path / "rm.json", dead=("VCM2",)) + fields = _rm_fields(dead=("VCM2",)) + instance = OrbitResponseMatrixData(**fields) + tools = [ + Trajectory("from_str", str(path)), + Trajectory("from_path", path), + Trajectory("from_mapping", fields), + Trajectory("from_validated_instance", instance), + Trajectory("from_instance", instance, validate=False), + Factory.build(_config("from_factory", str(path))), + ] + expected = _expected_layout(dead=("VCM2",)) + for tool in tools: + assert isinstance(tool, Trajectory) + assert tool.layout == expected + assert tool.response_matrix.matrix == fields["matrix"] + assert tool.response_matrix.variable_names == fields["variable_names"] + assert tool.response_matrix.observable_names == fields["observable_names"] + assert expected.n_live == 5 and expected.L == 6 and expected.k_live == 5 and expected.n_struct == 1 + + +def test_trajectory_factory_build_registers_the_tool_under_its_name(tmp_path): + path = _write_rm(tmp_path / "rm.json") + tool = Factory.build(_config("registered_tool", str(path))) + assert tool.get_name() == "registered_tool" + with pytest.raises(PyAMLConfigException, match="registered_tool"): + Factory.build(_config("registered_tool", str(path))) + + +def test_trajectory_factory_build_passes_the_settings(tmp_path): + path = _write_rm(tmp_path / "rm.json") + tool = Factory.build(_config("factory_settings", str(path), alpha=0.5, n_discard=2, gain=0.7)) + assert tool._settings == _Settings(alpha=0.5, n_discard=2, gain=0.7) + + +def test_trajectory_defaults_are_alpha_zero_no_discard_unit_gain(tmp_path): + tool = Trajectory("defaults", _write_rm(tmp_path / "rm.json")) + assert tool._settings == _Settings(alpha=0.0, n_discard=0, gain=1.0) + + +def test_trajectory_mapping_with_a_build_key_is_rejected(): + # The implementer's choice, pinned here: a mapping may hold only the six + # OrbitResponseMatrixData fields. On the validated path pydantic rejects the + # extra key; under validate=False the tool's own check rejects it, naming it. + fields = dict(_rm_fields(), type="pyaml.tuning_tools.orbit_response_matrix_data") + with pytest.raises(PyAMLConfigException, match="response_matrix"): + Trajectory("build_key_validated", fields) + with pytest.raises(PyAMLException, match="type"): + Trajectory("build_key_unvalidated", fields, validate=False) + + +def test_trajectory_mapping_may_omit_the_optional_none_field(): + fields = _rm_fields() + del fields["rf_response"] + assert Trajectory("no_rf_key", fields, validate=False).layout == _expected_layout() + + +def test_trajectory_rejects_an_rm_argument_of_another_type(): + with pytest.raises(PyAMLException, match="response_matrix"): + Trajectory("bad_rm_type", 3, validate=False) + + +def _copy_fields(fields): + return json.loads(json.dumps(fields)) + + +def test_trajectory_does_not_alias_the_instance_or_mapping_it_was_built_from(): + fields = _rm_fields() + instance = OrbitResponseMatrixData(**_copy_fields(fields), validate=False) + from_instance = Trajectory("alias_instance", instance, validate=False) + mapping = _copy_fields(fields) + from_mapping = Trajectory("alias_mapping", mapping, validate=False) + before = [_snapshot(from_instance), _snapshot(from_mapping)] + + for target in (instance.matrix, mapping["matrix"]): + target[0][0] += 1.0 + target.append([0.0] * 6) + for names in (instance.variable_names, mapping["variable_names"]): + names[0] = "CHANGED" + + assert [_snapshot(from_instance), _snapshot(from_mapping)] == before + assert from_instance.layout == _expected_layout() + + +def test_trajectory_response_matrix_is_a_copy(tmp_path): + tool = Trajectory("rm_copy", _write_rm(tmp_path / "rm.json")) + first = tool.response_matrix + original = first.matrix[0][0] + first.matrix[0][0] += 1 + first.variable_names[0] = "CHANGED" + second = tool.response_matrix + assert second is not first + assert second.matrix[0][0] == original + assert second.variable_names[0] == "HCM0" + + +@pytest.mark.parametrize("key", ["bpm_array_name", "hcorr_array_name", "vcorr_array_name"]) +def test_trajectory_config_with_an_array_name_is_rejected(tmp_path, key): + path = _write_rm(tmp_path / "rm.json") + with pytest.raises(PyAMLConfigException, match=key): + Factory.build(_config(f"array_name_{key}", str(path), **{key: "BPM"})) + + +@pytest.mark.parametrize("field", ["alpha", "n_discard", "gain"]) +def test_trajectory_none_setting_at_construction_raises_config_exception(tmp_path, field): + path = _write_rm(tmp_path / "rm.json") + with pytest.raises(PyAMLConfigException, match=field): + Trajectory(f"none_{field}", str(path), **{field: None}) + + +_RANGE_REJECTIONS = [ + ("alpha", -1.0), + ("alpha", 1e200), + ("alpha", math.inf), + ("alpha", math.nan), + ("n_discard", -1), + ("n_discard", 7), + ("gain", 0.0), + ("gain", -1.0), + ("gain", math.inf), + ("gain", math.nan), +] + + +@pytest.mark.parametrize("field,value", _RANGE_REJECTIONS, ids=lambda v: repr(v)) +@pytest.mark.parametrize("validate", [True, False]) +def test_trajectory_range_rejection_at_direct_construction(tmp_path, field, value, validate): + path = _write_rm(tmp_path / "rm.json") # L = 6 + with pytest.raises(PyAMLException, match=field): + Trajectory(f"range_{field}", str(path), validate=validate, **{field: value}) + + +@pytest.mark.parametrize("field,value", _RANGE_REJECTIONS, ids=lambda v: repr(v)) +def test_trajectory_range_rejection_through_factory_build(tmp_path, field, value): + path = _write_rm(tmp_path / "rm.json") + with pytest.raises(PyAMLConfigException, match=field): + Factory.build(_config(f"factory_range_{field}_{value!r}", str(path), **{field: value})) + + +def test_trajectory_range_rejection_without_a_file_still_checks_the_lower_bounds(tmp_path): + missing = tmp_path / "missing.json" + with pytest.raises(PyAMLException, match="n_discard"): + Trajectory("lower_bound", missing, n_discard=-1) + # The upper bound needs L, which a missing file does not give. + assert Trajectory("upper_bound_unknown", missing, n_discard=100).layout is None + + +def test_trajectory_n_discard_up_to_l_is_accepted(tmp_path): + tool = Trajectory("n_discard_l", _write_rm(tmp_path / "rm.json"), n_discard=6) + assert tool.layout.L == 6 + + +def test_trajectory_n_discard_above_l_raises_at_a_load_that_shrinks_l(tmp_path): + tool = Trajectory("shrink", _write_rm(tmp_path / "big.json"), n_discard=6) + small = _write_rm(tmp_path / "small.json", n_bpm=2, n_h=1, n_v=1) # L = 2 + before = _snapshot(tool) + with pytest.raises(PyAMLException, match="n_discard") as info: + tool.load(small) + assert str(small) in info.value.message + assert _snapshot(tool) == before + + +def _interleaved(fields): + n = len(fields["observable_planes"]) // 2 + fields["observable_planes"] = ["H", "V"] * n + + +def _unequal_rows(fields): + n = len(fields["observable_planes"]) + fields["observable_planes"] = ["H"] * (n // 2 + 1) + ["V"] * (n // 2 - 1) + + +def _ragged(fields): + fields["matrix"][1] = fields["matrix"][1][:-1] + + +def _non_finite(fields): + fields["matrix"][2][3] = math.nan + + +def _shape_mismatch(fields): + fields["variable_names"] = fields["variable_names"] + ["HCM_extra"] + + +def _rf_response(fields): + fields["rf_response"] = [0.0] * len(fields["observable_names"]) + + +def _no_response(fields): + fields["matrix"] = [[0.0] * len(row) for row in fields["matrix"]] + + +def _duplicated_row_name(fields): + fields["observable_names"][1] = fields["observable_names"][0] + + +def _duplicated_column_name(fields): + fields["variable_names"][4] = fields["variable_names"][3] + + +def _missing_planes(fields): + del fields["variable_planes"] + + +def _write_malformed(path, case): + if case == "response_matrix_data_type": + fields = _rm_fields() + body = {k: fields[k] for k in ("matrix", "observable_names", "variable_names")} + return _write_rm(path, body, type_key="pyaml.tuning_tools.response_matrix_data") + if case == "type_3": + return _write_rm(path, type_key=3) + if case == "class_path_x": + body = dict(_rm_fields(), class_path="x") + return _write_rm(path, body, type_key=None) + fields = _rm_fields() + _MUTATIONS[case](fields) + return _write_rm(path, fields) + + +_MUTATIONS = { + "interleaved_planes": _interleaved, + "unequal_row_counts": _unequal_rows, + "ragged_matrix": _ragged, + "non_finite_matrix": _non_finite, + "shape_mismatched_to_names": _shape_mismatch, + "rf_response_present": _rf_response, + "no_responding_corrector": _no_response, + "duplicated_row_name": _duplicated_row_name, + "duplicated_column_name": _duplicated_column_name, + "planes_missing": _missing_planes, +} + +_MALFORMED = sorted(_MUTATIONS) + ["response_matrix_data_type", "type_3", "class_path_x"] + +# The check each malformed file must trip, so no case passes on another's failure. +_REJECTED_BY = { + "interleaved_planes": "plane-major", + "unequal_row_counts": "equal row counts", + "ragged_matrix": "rectangular", + "non_finite_matrix": "finite", + "shape_mismatched_to_names": "variable_names", + "rf_response_present": "rf_response", + "no_responding_corrector": "no corrector has a response", + "duplicated_row_name": "H row half", + "duplicated_column_name": "unique within the variable_names", + "planes_missing": "variable_planes is missing", + "response_matrix_data_type": "ResponseMatrixData", + "type_3": "cannot read", + "class_path_x": "cannot read", +} + + +@pytest.mark.parametrize("case", _MALFORMED) +def test_trajectory_malformed_rm_raises_at_construction_and_load(tmp_path, case): + bad = _write_malformed(tmp_path / f"{case}.json", case) + with pytest.raises(PyAMLException, match=_REJECTED_BY[case]) as info: + Trajectory(f"malformed_{case}", bad) + assert str(bad) in info.value.message + with pytest.raises(PyAMLException, match=_REJECTED_BY[case]): + Trajectory(f"malformed_{case}_unvalidated", str(bad), validate=False) + + tool = Trajectory(f"good_{case}", _write_rm(tmp_path / "good.json")) + before = _snapshot(tool) + with pytest.raises(PyAMLException, match=_REJECTED_BY[case]) as info: + tool.load(bad) + assert str(bad) in info.value.message + assert _snapshot(tool) == before + + +def test_trajectory_malformed_rm_through_factory_build_names_the_path(tmp_path): + bad = _write_malformed(tmp_path / "dup.json", "duplicated_column_name") + with pytest.raises(PyAMLConfigException, match="dup.json"): + Factory.build(_config("factory_malformed", str(bad))) + + +@pytest.mark.parametrize("case", sorted(_MUTATIONS)) +def test_trajectory_malformed_mapping_raises_at_construction(case): + fields = _rm_fields() + _MUTATIONS[case](fields) + with pytest.raises(PyAMLException, match=_REJECTED_BY[case]): + Trajectory(f"malformed_mapping_{case}", fields, validate=False) + + +def test_trajectory_duplicate_names_across_row_halves_are_allowed(): + fields = _rm_fields() + fields["observable_names"] = [f"BPM{i}" for i in range(4)] * 2 + tool = Trajectory("shared_bpm_names", fields) + assert tool.layout.bpm_names_h == tool.layout.bpm_names_v + + +def test_trajectory_missing_path_at_construction_warns_and_leaves_no_rm(tmp_path, caplog): + missing = tmp_path / "missing.json" + with caplog.at_level(logging.WARNING, logger="pyaml.tuning_tools.trajectory"): + tool = Trajectory("missing", str(missing)) + assert tool.layout is None + assert tool.response_matrix is None + assert any(str(missing) in record.getMessage() for record in caplog.records) + + +def test_trajectory_directory_path_at_construction_is_not_a_file(tmp_path, caplog): + with caplog.at_level(logging.WARNING, logger="pyaml.tuning_tools.trajectory"): + tool = Trajectory("directory", tmp_path) + assert tool.layout is None + assert any(str(tmp_path) in record.getMessage() for record in caplog.records) + + +def test_trajectory_missing_path_through_factory_build_warns(tmp_path, caplog): + missing = tmp_path / "missing.json" + with caplog.at_level(logging.WARNING, logger="pyaml.tuning_tools.trajectory"): + tool = Factory.build(_config("factory_missing", str(missing))) + assert tool.layout is None + assert any(str(missing) in record.getMessage() for record in caplog.records) + + +def test_trajectory_load_of_a_missing_path_raises_without_warning(tmp_path, caplog): + tool = Trajectory("load_missing", _write_rm(tmp_path / "rm.json")) + before = _snapshot(tool) + missing = tmp_path / "missing.json" + with caplog.at_level(logging.WARNING, logger="pyaml.tuning_tools.trajectory"): + with pytest.raises(PyAMLException) as info: + tool.load(missing) + assert str(missing) in info.value.message + assert not [record for record in caplog.records if record.levelno >= logging.WARNING] + assert _snapshot(tool) == before + + +def test_trajectory_load_of_a_missing_path_on_a_tool_without_rm_changes_nothing(tmp_path): + tool = Trajectory("load_missing_empty", tmp_path / "absent.json") + with pytest.raises(PyAMLException): + tool.load(tmp_path / "still_absent.json") + assert tool.layout is None and tool.response_matrix is None + + +def test_trajectory_second_load_changes_layout_and_rm_together(tmp_path): + tool = Trajectory("reload", _write_rm(tmp_path / "first.json")) + first_layout, first_rm = tool.layout, tool.response_matrix + second = _write_rm(tmp_path / "second.json", n_bpm=5, n_h=2, n_v=4, dead=("HCM1",), scale=2.0) + tool.load(second) + assert tool.layout == _expected_layout(n_bpm=5, n_h=2, n_v=4, dead=("HCM1",)) + assert tool.layout != first_layout + rm = tool.response_matrix + assert rm.matrix == _rm_fields(n_bpm=5, n_h=2, n_v=4, dead=("HCM1",), scale=2.0)["matrix"] + assert rm.matrix != first_rm.matrix + assert len(rm.matrix) == 2 * tool.layout.n_bpm + assert len(rm.variable_names) == tool.layout.n_cor + + +def test_trajectory_load_fills_a_tool_built_without_rm(tmp_path): + tool = Trajectory("late_load", tmp_path / "absent.json", n_discard=6) + tool.load(_write_rm(tmp_path / "rm.json")) + assert tool.layout == _expected_layout() + + +def test_trajectory_load_accepts_a_str_path(tmp_path): + tool = Trajectory("load_str", _write_rm(tmp_path / "rm.json")) + tool.load(str(_write_rm(tmp_path / "other.json", n_bpm=3))) + assert tool.layout.n_bpm == 3 + + +def test_trajectory_attached_copy_shares_no_writable_state(tmp_path): + tool = Trajectory("attach_src", _write_rm(tmp_path / "rm.json")) + clone = copy.copy(tool) + clone.load(_write_rm(tmp_path / "other.json", n_bpm=3)) + assert tool.layout == _expected_layout() + assert clone.layout.n_bpm == 3 + + +# --------------------------------------------------------------------------- +# pseudo_inverse() +# +# Designed matrices: _designed_fields gives column c one non-zero entry, at row c, +# so the singular values are the column magnitudes and the inverse is known by +# hand (a zero magnitude is a dead column). Random RMs from _rm_fields serve the +# count identities. Nothing here reads the goldens. +# --------------------------------------------------------------------------- + +_EPS = np.finfo(float).eps + + +def _designed_fields(h_values, v_values, n_bpm): + """Fields of a 2*n_bpm x (n_h + n_v) RM whose column c has one entry at row c.""" + values = list(h_values) + list(v_values) + assert len(values) <= 2 * n_bpm + matrix = np.zeros((2 * n_bpm, len(values))) + for c, value in enumerate(values): + matrix[c, c] = value + fields = _rm_fields(n_bpm=n_bpm, n_h=len(h_values), n_v=len(v_values)) + fields["matrix"] = matrix.tolist() + return fields + + +def _designed(name, h_values, v_values, n_bpm=2, **settings): + return Trajectory(name, _designed_fields(h_values, v_values, n_bpm), **settings) + + +def _counts(pinv): + return {kind: pinv.spectrum_kind.count(kind) for kind in SpectrumKind} + + +def _assert_count_identities(pinv, layout, n_discard): + counts = _counts(pinv) + assert len(pinv.singular_values) == len(pinv.inverse_weights) == len(pinv.spectrum_kind) == layout.L + assert counts[SpectrumKind.STRUCTURAL] == layout.n_struct + assert counts[SpectrumKind.RANK_DISCARDED] == pinv.rank_discarded + assert counts[SpectrumKind.DISCARDED] == max(n_discard - layout.n_struct - pinv.rank_discarded, 0) + assert counts[SpectrumKind.LIVE] == layout.L - sum(v for k, v in counts.items() if k is not SpectrumKind.LIVE) + # Structural zeros come last, then rank-discarded and discarded positions precede them. + assert pinv.spectrum_kind[layout.k_live :] == (SpectrumKind.STRUCTURAL,) * layout.n_struct + live = np.array([kind is SpectrumKind.LIVE for kind in pinv.spectrum_kind]) + assert np.all(pinv.inverse_weights[~live] == 0.0) + assert np.all(pinv.inverse_weights[live] != 0.0) + assert np.all(np.diff(pinv.singular_values) <= 0.0) + assert np.all(pinv.singular_values[layout.k_live :] == 0.0) + + +def _full_snapshot(tool): + state = tool._state + if state is None: + return None + return (state.layout, np.copy(state.matrix), np.copy(state.live), json.dumps(dataclasses.asdict(state.response_matrix))) + + +def _assert_same_snapshot(before, after): + assert (before is None) == (after is None) + if before is None: + return + assert before[0] == after[0] + assert np.array_equal(before[1], after[1]) and before[1].tobytes() == after[1].tobytes() + assert np.array_equal(before[2], after[2]) + assert before[3] == after[3] + + +def test_pseudo_inverse_without_rm_raises(tmp_path): + tool = Trajectory("pinv_no_rm", tmp_path / "absent.json") + with pytest.raises(PyAMLException, match="response matrix"): + tool.pseudo_inverse() + + +def test_pseudo_inverse_construction_forms_give_the_same_matrix(tmp_path): + path = _write_rm(tmp_path / "rm.json", dead=("VCM2",)) + fields = _rm_fields(dead=("VCM2",)) + tools = [ + Trajectory("pinv_form_str", str(path)), + Trajectory("pinv_form_path", path), + Trajectory("pinv_form_mapping", fields), + Trajectory("pinv_form_instance", OrbitResponseMatrixData(**fields, validate=False), validate=False), + Factory.build(_config("pinv_form_factory", str(path))), + ] + reference = tools[0].pseudo_inverse() + for tool in tools[1:]: + pinv = tool.pseudo_inverse() + assert np.array_equal(pinv.matrix, reference.matrix) + assert np.array_equal(pinv.singular_values, reference.singular_values) + assert np.array_equal(pinv.inverse_weights, reference.inverse_weights) + assert pinv.spectrum_kind == reference.spectrum_kind + + +def test_pseudo_inverse_returns_the_record_type_with_read_only_arrays(): + pinv = _designed("pinv_record", [4.0, 2.0], [1.0, 0.5]).pseudo_inverse() + assert isinstance(pinv, PseudoInverse) + for field in ("matrix", "singular_values", "inverse_weights", "no_response_correctors"): + array = getattr(pinv, field) + assert isinstance(array, np.ndarray) + assert not array.flags.writeable + with pytest.raises(ValueError): + array[...] = 0 + assert pinv.matrix.shape == (4, 4) + assert pinv.matrix.dtype == float + + +def test_pseudo_inverse_plain_inverse_of_a_designed_matrix(): + pinv = _designed("pinv_plain", [4.0, 2.0], [1.0, 0.5]).pseudo_inverse() + assert np.allclose(pinv.singular_values, [4.0, 2.0, 1.0, 0.5], rtol=1e-13, atol=0.0) + assert np.allclose(pinv.inverse_weights, [0.25, 0.5, 1.0, 2.0], rtol=1e-13, atol=0.0) + assert pinv.spectrum_kind == (SpectrumKind.LIVE,) * 4 + assert pinv.rank_discarded == 0 + assert np.allclose(pinv.matrix, np.diag([0.25, 0.5, 1.0, 2.0]), rtol=1e-13, atol=1e-15) + assert (pinv.alpha, pinv.n_discard, pinv.gain) == (0.0, 0, 1.0) + + +def test_pseudo_inverse_n_discard_zero_equals_the_plain_inverse(tmp_path): + tool = Trajectory("pinv_n0", _write_rm(tmp_path / "rm.json")) + matrix = np.array(tool.response_matrix.matrix) + pinv = tool.pseudo_inverse(n_discard=0) + expected = np.linalg.pinv(matrix, rcond=max(matrix.shape) * _EPS) + assert np.allclose(pinv.matrix, expected, rtol=1e-12, atol=1e-12 * np.abs(expected).max()) + assert np.allclose(pinv.matrix @ matrix, np.eye(6), atol=1e-10) + + +def test_pseudo_inverse_tikhonov_weights_in_matlab_order(): + alpha = 1.5 + pinv = _designed("pinv_tikhonov", [4.0, 2.0], [1.0, 0.5], alpha=alpha).pseudo_inverse() + s = np.array([4.0, 2.0, 1.0, 0.5]) + expected = s / (s * s + alpha * alpha) + assert np.allclose(pinv.inverse_weights, expected, rtol=1e-13, atol=0.0) + assert np.allclose(pinv.matrix, np.diag(expected), rtol=1e-13, atol=1e-15) + assert pinv.spectrum_kind == (SpectrumKind.LIVE,) * 4 + assert pinv.alpha == alpha + + +def test_pseudo_inverse_gain_scales_the_weights_and_the_matrix(): + plain = _designed("pinv_gain_1", [4.0, 2.0], [1.0, 0.5]).pseudo_inverse() + scaled = _designed("pinv_gain_2", [4.0, 2.0], [1.0, 0.5]).pseudo_inverse(gain=2.0) + assert np.allclose(scaled.inverse_weights, 2.0 * plain.inverse_weights, rtol=1e-15, atol=0.0) + assert np.allclose(scaled.matrix, 2.0 * plain.matrix, rtol=1e-15, atol=0.0) + assert np.array_equal(scaled.singular_values, plain.singular_values) + assert scaled.gain == 2.0 and plain.gain == 1.0 + + +def test_pseudo_inverse_gain_multiplies_after_tikhonov(): + alpha, gain = 0.7, 3.0 + pinv = _designed("pinv_alpha_gain", [4.0, 2.0], [1.0, 0.5]).pseudo_inverse(alpha=alpha, gain=gain) + s = np.array([4.0, 2.0, 1.0, 0.5]) + assert np.allclose(pinv.inverse_weights, gain * s / (s * s + alpha * alpha), rtol=1e-13, atol=0.0) + + +def test_pseudo_inverse_dead_column_is_a_structural_zero_and_an_exact_zero_row(): + # L = 4, n_live = 3: one structural zero at the end of the spectrum. + tool = _designed("pinv_dead", [4.0, 2.0], [1.0, 0.0]) + assert tool.layout.no_response_names == ("VCM1",) + for alpha in (0.0, 0.3): + pinv = tool.pseudo_inverse(alpha=alpha) + assert len(pinv.singular_values) == tool.layout.L == 4 + assert pinv.spectrum_kind == (SpectrumKind.LIVE,) * 3 + (SpectrumKind.STRUCTURAL,) + assert pinv.singular_values[3] == 0.0 and pinv.inverse_weights[3] == 0.0 + assert np.allclose(pinv.singular_values[:3], [4.0, 2.0, 1.0], rtol=1e-13, atol=0.0) + assert pinv.matrix[3].tobytes() == np.zeros(4).tobytes() # exact +0.0 + assert np.all(np.isfinite(pinv.matrix)) + assert pinv.rank_discarded == 0 + assert list(pinv.no_response_correctors) == [3] + assert pinv.no_response_correctors.dtype == np.intp + assert pinv.no_response_names == tool.layout.no_response_names + _assert_count_identities(pinv, tool.layout, 0) + + +def test_pseudo_inverse_dead_rows_are_exact_zero_on_a_random_rm_at_every_alpha(tmp_path): + dead = ("HCM1", "VCM2") + tool = Trajectory("pinv_dead_random", _write_rm(tmp_path / "rm.json", n_bpm=4, n_h=3, n_v=3, dead=dead)) + for alpha in (0.0, 1e-3, 2.5): + pinv = tool.pseudo_inverse(alpha=alpha) + assert list(pinv.no_response_correctors) == [1, 5] + assert pinv.no_response_names == dead + assert pinv.matrix[[1, 5]].tobytes() == np.zeros((2, 8)).tobytes() + assert np.all(pinv.matrix[[0, 2, 3, 4]] != 0.0) + _assert_count_identities(pinv, tool.layout, 0) + + +def test_pseudo_inverse_discard_cuts_structural_zeros_before_live_values(): + tool = _designed("pinv_cut_order", [4.0, 2.0], [1.0, 0.0]) # L = 4, k_live = 3, n_struct = 1 + one = tool.pseudo_inverse(n_discard=1) + assert one.spectrum_kind == (SpectrumKind.LIVE,) * 3 + (SpectrumKind.STRUCTURAL,) + assert np.allclose(one.inverse_weights, [0.25, 0.5, 1.0, 0.0], rtol=1e-13, atol=0.0) + assert np.allclose(one.matrix, tool.pseudo_inverse(n_discard=0).matrix, rtol=1e-15, atol=0.0) + two = tool.pseudo_inverse(n_discard=2) + assert two.spectrum_kind == (SpectrumKind.LIVE, SpectrumKind.LIVE, SpectrumKind.DISCARDED, SpectrumKind.STRUCTURAL) + assert np.allclose(two.inverse_weights, [0.25, 0.5, 0.0, 0.0], rtol=1e-13, atol=0.0) + assert np.allclose(two.matrix, np.diag([0.25, 0.5, 0.0, 0.0]), rtol=1e-13, atol=1e-15) + assert two.singular_values[2] != 0.0 # the value stays in the spectrum, only its weight is cut + for pinv, n_discard in ((one, 1), (two, 2)): + _assert_count_identities(pinv, tool.layout, n_discard) + assert pinv.n_discard == n_discard + + +def test_pseudo_inverse_discard_cuts_the_smallest_live_values_first(): + tool = _designed("pinv_cut_live", [4.0, 2.0], [1.0, 0.5]) + pinv = tool.pseudo_inverse(n_discard=3) + assert pinv.spectrum_kind == (SpectrumKind.LIVE,) + (SpectrumKind.DISCARDED,) * 3 + assert np.allclose(pinv.inverse_weights, [0.25, 0.0, 0.0, 0.0], rtol=1e-13, atol=0.0) + assert np.allclose(pinv.singular_values, [4.0, 2.0, 1.0, 0.5], rtol=1e-13, atol=0.0) + _assert_count_identities(pinv, tool.layout, 3) + + +def test_pseudo_inverse_n_discard_equal_to_l_gives_the_all_zero_inverse_without_raising(): + tool = _designed("pinv_all_cut", [4.0, 2.0], [1.0, 0.0]) + pinv = tool.pseudo_inverse(n_discard=tool.layout.L) + assert not np.any(pinv.matrix) + assert not np.any(pinv.inverse_weights) + assert pinv.spectrum_kind == (SpectrumKind.DISCARDED,) * 3 + (SpectrumKind.STRUCTURAL,) + assert np.allclose(pinv.singular_values[:3], [4.0, 2.0, 1.0], rtol=1e-13, atol=0.0) + _assert_count_identities(pinv, tool.layout, 4) + + +def test_pseudo_inverse_n_discard_equal_to_l_configured_at_construction(tmp_path): + tool = Trajectory("pinv_all_cut_cfg", _write_rm(tmp_path / "rm.json"), n_discard=6) + pinv = tool.pseudo_inverse() + assert not np.any(pinv.matrix) + assert pinv.n_discard == 6 + assert set(pinv.spectrum_kind) == {SpectrumKind.DISCARDED} + + +def test_pseudo_inverse_more_correctors_than_rows_has_no_structural_zero(tmp_path): + # 4 rows, 6 columns, one dead: L = 4 = k_live, so the dead column is no spectrum position. + tool = Trajectory("pinv_wide", _write_rm(tmp_path / "rm.json", n_bpm=2, n_h=3, n_v=3, dead=("HCM2",))) + assert tool.layout.L == 4 and tool.layout.n_struct == 0 + plain = tool.pseudo_inverse() + assert len(plain.singular_values) == 4 + assert SpectrumKind.STRUCTURAL not in plain.spectrum_kind + assert plain.spectrum_kind == (SpectrumKind.LIVE,) * 4 + assert plain.matrix[2].tobytes() == np.zeros(4).tobytes() + cut = tool.pseudo_inverse(n_discard=1) + assert cut.spectrum_kind == (SpectrumKind.LIVE,) * 3 + (SpectrumKind.DISCARDED,) + assert cut.inverse_weights[3] == 0.0 and cut.singular_values[3] != 0.0 + assert cut.matrix[2].tobytes() == np.zeros(4).tobytes() + for pinv, n_discard in ((plain, 0), (cut, 1)): + _assert_count_identities(pinv, tool.layout, n_discard) + + +def test_pseudo_inverse_rank_guard_drops_a_collinear_pair_at_alpha_zero(): + fields = _designed_fields([4.0, 2.0], [1.0, 1.0], n_bpm=2) + matrix = np.array(fields["matrix"]) + matrix[:, 3] = matrix[:, 2] # VCM1 duplicates VCM0: live, but rank-deficient + fields["matrix"] = matrix.tolist() + tool = Trajectory("pinv_collinear", fields) + assert tool.layout.no_response_names == () and tool.layout.n_struct == 0 + pinv = tool.pseudo_inverse() + assert pinv.rank_discarded == 1 + assert pinv.spectrum_kind == (SpectrumKind.LIVE,) * 3 + (SpectrumKind.RANK_DISCARDED,) + assert pinv.singular_values[3] <= 4 * _EPS * pinv.singular_values[0] + assert pinv.inverse_weights[3] == 0.0 + assert np.all(np.isfinite(pinv.matrix)) + expected = np.linalg.pinv(matrix, rcond=max(matrix.shape) * _EPS) + assert np.allclose(pinv.matrix, expected, rtol=1e-12, atol=1e-13) + _assert_count_identities(pinv, tool.layout, 0) + # The guard is applied only at alpha = 0: at alpha > 0 the pair is a tiny live weight. + damped = tool.pseudo_inverse(alpha=0.5) + assert damped.rank_discarded == 0 + assert damped.spectrum_kind[3] is SpectrumKind.LIVE + assert np.all(np.isfinite(damped.matrix)) + + +def test_pseudo_inverse_rank_discarded_counts_under_the_cut(): + fields = _designed_fields([4.0, 2.0], [1.0, 1.0], n_bpm=2) + matrix = np.array(fields["matrix"]) + matrix[:, 3] = matrix[:, 2] + fields["matrix"] = matrix.tolist() + tool = Trajectory("pinv_collinear_cut", fields) + pinv = tool.pseudo_inverse(n_discard=2) + assert pinv.rank_discarded == 1 + assert pinv.spectrum_kind == (SpectrumKind.LIVE, SpectrumKind.LIVE, SpectrumKind.DISCARDED, SpectrumKind.RANK_DISCARDED) + _assert_count_identities(pinv, tool.layout, 2) + assert np.allclose(pinv.inverse_weights, [0.25, 0.5, 0.0, 0.0], rtol=1e-13, atol=0.0) + + +def test_pseudo_inverse_underflowing_gain_raises_on_the_all_zero_vector(): + tool = _designed("pinv_underflow", [4.0, 2.0], [1.0, 0.5], alpha=1e150) + # s / (s^2 + alpha^2) ~ 1e-150, times 1e-200 underflows to exactly zero everywhere. + with pytest.raises(PyAMLException, match="zero"): + tool.pseudo_inverse(n_discard=0, gain=1e-200) + + +def test_pseudo_inverse_non_finite_weight_raises(): + tool = _designed("pinv_overflow", [4.0, 2.0], [1.0, 0.5]) + with pytest.raises(PyAMLException, match="finite"): + tool.pseudo_inverse(gain=1e308) # 1/0.5 * 1e308 overflows + # The same gain is fine once the overflowing position is discarded. + pinv = tool.pseudo_inverse(gain=1e308, n_discard=2) + assert np.all(np.isfinite(pinv.matrix)) + + +def test_pseudo_inverse_non_finite_check_happens_after_the_cut_not_before(): + tool = _designed("pinv_overflow_cut", [4.0, 2.0], [1.0, 0.5]) + # Before the cut the last weight is 1/0.5 * 1e308 = inf; after it, the vector is finite. + pinv = tool.pseudo_inverse(gain=1e308, n_discard=1) + assert pinv.inverse_weights[3] == 0.0 + assert np.all(np.isfinite(pinv.inverse_weights)) and np.all(np.isfinite(pinv.matrix)) + assert pinv.spectrum_kind[3] is SpectrumKind.DISCARDED + + +@pytest.mark.parametrize("field,value", _RANGE_REJECTIONS, ids=lambda v: repr(v)) +def test_pseudo_inverse_per_call_range_rejection_raises(tmp_path, field, value): + tool = Trajectory("pinv_range", _write_rm(tmp_path / "rm.json")) # L = 6 + before = _full_snapshot(tool) + with pytest.raises(PyAMLException, match=field): + tool.pseudo_inverse(**{field: value}) + _assert_same_snapshot(before, _full_snapshot(tool)) + + +@pytest.mark.parametrize("field,value", [("alpha", "0"), ("n_discard", 1.0), ("gain", True)], ids=lambda v: repr(v)) +def test_pseudo_inverse_per_call_wrong_type_raises(tmp_path, field, value): + tool = Trajectory("pinv_type", _write_rm(tmp_path / "rm.json")) + with pytest.raises(PyAMLException, match=field): + tool.pseudo_inverse(**{field: value}) + + +def test_pseudo_inverse_none_per_call_reproduces_the_configured_result(tmp_path): + tool = Trajectory("pinv_none", _write_rm(tmp_path / "rm.json", dead=("HCM0",)), alpha=0.4, n_discard=2, gain=1.5) + configured = tool.pseudo_inverse() + for pinv in (tool.pseudo_inverse(None, None, None), tool.pseudo_inverse(alpha=0.4, n_discard=2, gain=1.5)): + assert (pinv.alpha, pinv.n_discard, pinv.gain) == (0.4, 2, 1.5) + assert pinv.matrix.tobytes() == configured.matrix.tobytes() + assert pinv.singular_values.tobytes() == configured.singular_values.tobytes() + assert pinv.inverse_weights.tobytes() == configured.inverse_weights.tobytes() + assert pinv.spectrum_kind == configured.spectrum_kind + assert pinv.rank_discarded == configured.rank_discarded + + +def test_pseudo_inverse_per_call_override_does_not_change_the_configured_settings(tmp_path): + tool = Trajectory("pinv_override", _write_rm(tmp_path / "rm.json"), alpha=0.0, n_discard=0, gain=1.0) + configured = tool.pseudo_inverse() + override = tool.pseudo_inverse(alpha=2.0, n_discard=3, gain=0.5) + assert (override.alpha, override.n_discard, override.gain) == (2.0, 3, 0.5) + assert not np.array_equal(override.matrix, configured.matrix) + again = tool.pseudo_inverse() + assert (again.alpha, again.n_discard, again.gain) == (0.0, 0, 1.0) + assert again.matrix.tobytes() == configured.matrix.tobytes() + + +def test_pseudo_inverse_accepts_numpy_scalars_per_call(tmp_path): + tool = Trajectory("pinv_np_scalars", _write_rm(tmp_path / "rm.json")) + pinv = tool.pseudo_inverse(alpha=np.float64(0.25), n_discard=np.int64(1), gain=np.float32(2.0)) + assert (pinv.alpha, pinv.n_discard, pinv.gain) == (0.25, 1, 2.0) + assert type(pinv.alpha) is float and type(pinv.n_discard) is int and type(pinv.gain) is float + + +def test_pseudo_inverse_is_pure_and_deterministic(tmp_path): + tool = Trajectory("pinv_pure", _write_rm(tmp_path / "rm.json", dead=("VCM1",)), alpha=0.1, n_discard=1) + before = _full_snapshot(tool) + first = tool.pseudo_inverse() + second = tool.pseudo_inverse(alpha=3.0, n_discard=4, gain=0.1) + third = tool.pseudo_inverse() + _assert_same_snapshot(before, _full_snapshot(tool)) + assert first is not third + assert first.matrix.tobytes() == third.matrix.tobytes() + assert first.inverse_weights.tobytes() == third.inverse_weights.tobytes() + assert second.matrix.tobytes() != first.matrix.tobytes() + assert tool.layout == _expected_layout(dead=("VCM1",)) + # Returned arrays share no memory with the tool's state. + assert not np.shares_memory(first.matrix, tool._state.matrix) + + +def test_pseudo_inverse_echoes_the_layout_no_response_correctors(tmp_path): + dead = ("HCM2", "VCM0") + tool = Trajectory("pinv_echo", _write_rm(tmp_path / "rm.json", dead=dead)) + pinv = tool.pseudo_inverse(alpha=0.2) + assert pinv.no_response_names == tool.layout.no_response_names == dead + assert list(pinv.no_response_correctors) == [2, 3] + names = tool.layout.hcorr_names + tool.layout.vcorr_names + assert tuple(names[i] for i in pinv.no_response_correctors) == dead + + +@pytest.mark.parametrize( + "n_bpm,n_h,n_v,dead,alpha,n_discard", + [ + (4, 3, 3, (), 0.0, 0), + (4, 3, 3, (), 0.0, 6), + (4, 3, 3, ("HCM0",), 0.0, 0), + (4, 3, 3, ("HCM0", "VCM2"), 0.0, 1), + (4, 3, 3, ("HCM0", "VCM2"), 0.0, 3), + (4, 3, 3, ("HCM0", "VCM2"), 0.7, 3), + (2, 3, 3, ("HCM2",), 0.0, 0), + (2, 3, 3, ("HCM2",), 0.0, 1), + (2, 3, 3, ("HCM2", "VCM2", "VCM1"), 0.0, 2), + (2, 3, 3, ("HCM2", "VCM2", "VCM1"), 0.3, 4), + (3, 1, 2, ("HCM0",), 0.0, 1), + (3, 1, 2, ("HCM0",), 1e-3, 0), + (5, 2, 4, ("VCM3",), 0.0, 2), + (5, 2, 4, ("VCM3",), 0.0, 6), + ], +) +def test_pseudo_inverse_count_identities_on_constructed_cases(tmp_path, n_bpm, n_h, n_v, dead, alpha, n_discard): + tool = Trajectory( + f"pinv_counts_{n_bpm}_{n_h}_{n_v}_{len(dead)}_{alpha}_{n_discard}", + _write_rm(tmp_path / "rm.json", n_bpm=n_bpm, n_h=n_h, n_v=n_v, dead=dead), + ) + layout = tool.layout + pinv = tool.pseudo_inverse(alpha=alpha, n_discard=n_discard) + _assert_count_identities(pinv, layout, n_discard) + assert pinv.matrix.shape == (layout.n_cor, 2 * layout.n_bpm) + assert np.all(np.isfinite(pinv.matrix)) + dead_idx = [i for i, name in enumerate(layout.hcorr_names + layout.vcorr_names) if name in dead] + assert list(pinv.no_response_correctors) == dead_idx + for i in dead_idx: + assert pinv.matrix[i].tobytes() == np.zeros(2 * layout.n_bpm).tobytes() + assert (pinv.alpha, pinv.n_discard, pinv.gain) == (alpha, n_discard, 1.0) + if n_discard == layout.L: + assert not np.any(pinv.matrix) + else: + assert np.any(pinv.matrix) + + +# --------------------------------------------------------------------------- +# correct(): the correction step +# +# The index arrays below put BPM i at 10 * (i + 1) and corrector i of a plane at +# offset + 10 * i, so "beam to BPM j" keeps exactly the correctors whose index is +# at or before 10 * (j + 1); an offset above 10 puts every corrector after the +# first BPM. The RMs from _rm_fields are dense, so an upstream live corrector's +# step is non-zero whenever the deviation is. Nothing here reads the goldens. +# --------------------------------------------------------------------------- + + +def _indices(n_bpm=4, n_h=3, n_v=3, h_offset=5, v_offset=7): + bpm = [10 * (i + 1) for i in range(n_bpm)] + return { + "bpm_index": bpm + bpm, + "hcorr_index": [h_offset + 10 * i for i in range(n_h)], + "vcorr_index": [v_offset + 10 * i for i in range(n_v)], + } + + +def _readings(n_bpm=4, to_bpm=None, seed=3): + """Finite x, y with NaN past BPM ``to_bpm`` (None keeps beam at every BPM).""" + rng = np.random.default_rng(seed) + x = rng.uniform(0.2, 1.0, n_bpm) + y = rng.uniform(0.2, 1.0, n_bpm) + if to_bpm is not None: + x[to_bpm + 1 :] = np.nan + y[to_bpm + 1 :] = np.nan + return x, y + + +def _tool(tmp_path, name, **kwargs): + settings = {key: kwargs.pop(key) for key in ("alpha", "n_discard", "gain") if key in kwargs} + return Trajectory(name, _write_rm(tmp_path / f"{name}.json", **kwargs), **settings) + + +def _deviation(x, y, reference=None): + """The NaN-cleaned dR the tool solves with.""" + if reference is None: + reference = np.zeros((2, len(x))) + d_r = np.concatenate([x, y]) - np.asarray(reference, dtype=float).reshape(-1) + d_r[np.isnan(d_r)] = 0.0 + return d_r + + +def _positions(step, names): + all_names = step.names + return [all_names.index(name) for name in names] + + +def _matlab_positional_zeroing(indices, last_index): + """Positions the reference zeroes on a sorted array: everything after the last position with index <= last_index.""" + kept = [i for i, index in enumerate(indices) if index <= last_index] + assert kept, "the positional rule is only compared where a corrector is at or before the last BPM with beam" + return list(range(kept[-1] + 1, len(indices))) + + +def test_correct_without_rm_raises(tmp_path): + tool = Trajectory("correct_no_rm", str(tmp_path / "missing.json")) + x, y = _readings() + with pytest.raises(PyAMLException, match="no response matrix"): + tool.correct(x, y, **_indices()) + + +@pytest.mark.parametrize("field,value", _RANGE_REJECTIONS, ids=lambda v: repr(v)) +def test_correct_per_call_range_rejection_raises(tmp_path, field, value): + tool = _tool(tmp_path, "correct_range") + x, y = _readings() + before = _full_snapshot(tool) + with pytest.raises(PyAMLException, match=field): + tool.correct(x, y, **_indices(), **{field: value}) + _assert_same_snapshot(before, _full_snapshot(tool)) + + +@pytest.mark.parametrize("field,value", [("alpha", "0"), ("n_discard", 1.0), ("gain", True)], ids=lambda v: repr(v)) +def test_correct_per_call_wrong_type_raises(tmp_path, field, value): + tool = _tool(tmp_path, "correct_type") + x, y = _readings() + with pytest.raises(PyAMLException, match=field): + tool.correct(x, y, **_indices(), **{field: value}) + + +_BAD_INPUTS = [ + ("x_short", {"x": [0.0] * 3}), + ("x_long", {"x": [0.0] * 5}), + ("x_2d", {"x": [[0.0] * 4]}), + ("x_scalar", {"x": 0.0}), + ("x_text", {"x": ["a"] * 4}), + ("x_inf", {"x": [0.0, math.inf, 0.0, 0.0]}), + ("y_short", {"y": [0.0] * 3}), + ("y_2d", {"y": [[0.0] * 2] * 2}), + ("y_neg_inf", {"y": [0.0, 0.0, -math.inf, 0.0]}), + ("reference_1d", {"reference": [0.0] * 4}), + ("reference_three_rows", {"reference": [[0.0] * 4] * 3}), + ("reference_wrong_length", {"reference": ([0.0] * 5, [0.0] * 5)}), + ("reference_transposed", {"reference": [[0.0, 0.0]] * 4}), + ("reference_ragged", {"reference": ([0.0] * 4, [0.0] * 3)}), + ("reference_inf", {"reference": ([0.0, 0.0, 0.0, math.inf], [0.0] * 4)}), + ("reference_neg_inf", {"reference": ([0.0] * 4, [-math.inf, 0.0, 0.0, 0.0])}), + ("bpm_index_one_half", {"bpm_index": [10, 20, 30, 40]}), + ("bpm_index_too_long", {"bpm_index": [10, 20, 30, 40] * 2 + [50]}), + ("bpm_index_unequal_halves", {"bpm_index": [10, 20, 30, 40, 10, 20, 30, 41]}), + ("bpm_index_repeated", {"bpm_index": [10, 20, 20, 40] * 2}), + ("bpm_index_decreasing", {"bpm_index": [10, 30, 20, 40] * 2}), + ("bpm_index_nan", {"bpm_index": [10, 20, 30, math.nan] * 2}), + ("bpm_index_inf", {"bpm_index": [10, 20, 30, math.inf] * 2}), + ("bpm_index_2d", {"bpm_index": [[10, 20, 30, 40]] * 2}), + ("bpm_index_text", {"bpm_index": ["a"] * 8}), + ("hcorr_index_short", {"hcorr_index": [5, 15]}), + ("hcorr_index_long", {"hcorr_index": [5, 15, 25, 35]}), + ("hcorr_index_repeated", {"hcorr_index": [5, 5, 25]}), + ("hcorr_index_decreasing", {"hcorr_index": [25, 15, 5]}), + ("hcorr_index_nan", {"hcorr_index": [5, math.nan, 25]}), + ("hcorr_index_text", {"hcorr_index": ["a", "b", "c"]}), + ("vcorr_index_short", {"vcorr_index": [7]}), + ("vcorr_index_decreasing", {"vcorr_index": [7, 27, 17]}), + ("vcorr_index_neg_inf", {"vcorr_index": [-math.inf, 17, 27]}), + ("vcorr_index_2d", {"vcorr_index": [[7, 17, 27]]}), +] + + +@pytest.mark.parametrize("case,overrides", _BAD_INPUTS, ids=[case for case, _ in _BAD_INPUTS]) +def test_correct_rejects_bad_inputs_naming_the_argument(tmp_path, case, overrides): + tool = _tool(tmp_path, f"correct_bad_{case}") + x, y = _readings() + kwargs = {"x": x, "y": y, "reference": None, **_indices(), **overrides} + before = _full_snapshot(tool) + with pytest.raises(PyAMLException, match=next(iter(overrides))): + tool.correct(kwargs.pop("x"), kwargs.pop("y"), kwargs.pop("reference"), **kwargs) + _assert_same_snapshot(before, _full_snapshot(tool)) + + +def test_correct_layout_mismatch_names_the_argument(tmp_path): + tool = _tool(tmp_path, "correct_layout", n_bpm=3, n_h=2, n_v=4) + x, y = _readings(n_bpm=3) + good = _indices(n_bpm=3, n_h=2, n_v=4) + assert tool.correct(x, y, **good).reason is Reason.OK + with pytest.raises(PyAMLException, match="hcorr_index"): + tool.correct(x, y, **{**good, "hcorr_index": [5, 15, 25]}) + with pytest.raises(PyAMLException, match="vcorr_index"): + tool.correct(x, y, **{**good, "vcorr_index": [7, 17, 27]}) + with pytest.raises(PyAMLException, match="bpm_index"): + tool.correct(x, y, **{**good, "bpm_index": _indices()["bpm_index"]}) + with pytest.raises(PyAMLException, match="x"): + tool.correct(_readings()[0], y, **good) + # A load that changes the layout changes what is accepted. + tool.load(_write_rm(tmp_path / "other.json")) + x4, y4 = _readings() + with pytest.raises(PyAMLException, match="x"): + tool.correct(x, y, **_indices()) + assert tool.correct(x4, y4, **_indices()).reason is Reason.OK + + +def test_correct_solves_the_designed_matrix_exactly(): + tool = _designed("correct_designed", [2.0], [4.0], n_bpm=1) + step = tool.correct([0.5], [1.0], bpm_index=[3, 3], hcorr_index=[3], vcorr_index=[1]) + assert isinstance(step, TrajectoryStep) + assert step.reason is Reason.OK and step.status == "" + assert step.step.tolist() == [0.25, 0.25] + assert step.step_h.tolist() == [0.25] and step.step_v.tolist() == [0.25] + assert step.names == ("HCM0", "VCM0") and step.n_h == 1 + assert step.last_bpm == 0 and type(step.last_bpm) is int + assert step.zeroed_h == () and step.zeroed_v == () + assert not step.all_zero + # A reference is subtracted first; a gain scales the inverse. + step = tool.correct([0.5], [1.0], ([0.1], [0.2]), bpm_index=[3, 3], hcorr_index=[3], vcorr_index=[1]) + assert step.step.tolist() == pytest.approx([0.2, 0.2], rel=1e-15) + step = tool.correct([0.5], [1.0], bpm_index=[3, 3], hcorr_index=[3], vcorr_index=[1], gain=0.5) + assert step.step.tolist() == [0.125, 0.125] + assert step.pseudo_inverse.gain == 0.5 + + +def test_correct_step_is_the_joint_solve_with_nan_set_to_zero(tmp_path): + tool = _tool(tmp_path, "correct_solve", dead=("HCM1",)) + x, y = _readings() + reference = (np.array([0.1, math.nan, 0.3, 0.4]), np.array([math.nan, 0.2, 0.3, 0.4])) + step = tool.correct(x, y, reference, **_indices(), alpha=0.3) + pinv = tool.pseudo_inverse(alpha=0.3) + expected = pinv.matrix @ _deviation(x, y, reference) + assert step.step.tobytes() == expected.tobytes() + assert step.pseudo_inverse.matrix.tobytes() == pinv.matrix.tobytes() + assert step.reason is Reason.OK and step.zeroed_h == () and step.zeroed_v == () + assert step.step[1] == 0.0 # the dead corrector's row of the inverse is exactly zero + assert np.all(step.step[[0, 2, 3, 4, 5]] != 0.0) + + +def test_correct_nan_in_reference_means_no_reference_at_that_bpm(tmp_path): + tool = _tool(tmp_path, "correct_ref_nan") + x, y = _readings() + x_ref, y_ref = _readings(seed=11) + with_nan = (np.where(np.arange(4) == 1, np.nan, x_ref), np.where(np.arange(4) == 2, np.nan, y_ref)) + equal_there = (np.where(np.arange(4) == 1, x, x_ref), np.where(np.arange(4) == 2, y, y_ref)) + a = tool.correct(x, y, with_nan, **_indices()) + b = tool.correct(x, y, equal_there, **_indices()) + assert a.step.tobytes() == b.step.tobytes() + assert a.reason is b.reason is Reason.OK + assert a.last_bpm == b.last_bpm == 3 + + +def test_correct_reference_none_equals_an_explicit_zero_reference(tmp_path): + tool = _tool(tmp_path, "correct_ref_none") + x, y = _readings(to_bpm=2) + base = tool.correct(x, y, **_indices()) + for reference in ((np.zeros(4), np.zeros(4)), np.zeros((2, 4)), [[0.0] * 4, [0.0] * 4]): + other = tool.correct(x, y, reference, **_indices()) + assert other.step.tobytes() == base.step.tobytes() + assert other.reason is base.reason is Reason.OK + assert (other.last_bpm, other.zeroed_h, other.zeroed_v) == (base.last_bpm, base.zeroed_h, base.zeroed_v) + + +def test_correct_accepts_lists_tuples_and_arrays_alike(tmp_path): + tool = _tool(tmp_path, "correct_forms") + x, y = _readings(to_bpm=1) + idx = _indices() + base = tool.correct(x, y, **idx) + as_lists = tool.correct(x.tolist(), tuple(y.tolist()), **idx) + as_arrays = tool.correct(x, y, **{key: np.array(value) for key, value in idx.items()}) + as_floats = tool.correct(x, y, **{key: np.array(value, dtype=float) for key, value in idx.items()}) + for other in (as_lists, as_arrays, as_floats): + assert other.step.tobytes() == base.step.tobytes() + assert (other.reason, other.last_bpm, other.zeroed_h, other.zeroed_v) == ( + base.reason, + base.last_bpm, + base.zeroed_h, + base.zeroed_v, + ) + + +@pytest.mark.parametrize("to_bpm", [0, 1, 2, 3]) +def test_correct_threading_zeroes_exactly_the_correctors_past_the_last_bpm_with_beam(tmp_path, to_bpm): + tool = _tool(tmp_path, f"correct_thread_{to_bpm}") + idx = _indices() + x, y = _readings(to_bpm=to_bpm) + step = tool.correct(x, y, **idx) + last_index = idx["bpm_index"][to_bpm] + expected_h = tuple(f"HCM{i}" for i, index in enumerate(idx["hcorr_index"]) if index > last_index) + expected_v = tuple(f"VCM{i}" for i, index in enumerate(idx["vcorr_index"]) if index > last_index) + assert step.last_bpm == to_bpm + assert (step.zeroed_h, step.zeroed_v) == (expected_h, expected_v) + assert step.reason is Reason.OK and not step.all_zero + full = step.pseudo_inverse.matrix @ _deviation(x, y) + zeroed = _positions(step, step.zeroed_h + step.zeroed_v) + kept = [i for i in range(len(step.step)) if i not in zeroed] + assert np.all(step.step[zeroed] == 0.0) + assert step.step[kept].tobytes() == full[kept].tobytes() + assert np.all(step.step[kept] != 0.0) + # On sorted index arrays the reference's positional zeroing coincides with the index comparison. + assert _positions(step, step.zeroed_h) == _matlab_positional_zeroing(idx["hcorr_index"], last_index) + assert [i - step.n_h for i in _positions(step, step.zeroed_v)] == _matlab_positional_zeroing( + idx["vcorr_index"], last_index + ) + + +def test_correct_a_corrector_at_the_last_bpm_index_is_kept(tmp_path): + tool = _tool(tmp_path, "correct_tie") + idx = _indices(h_offset=10, v_offset=20) # HCM i at the index of BPM i; VCM i at the index of BPM i+1 + x, y = _readings(to_bpm=1) + step = tool.correct(x, y, **idx) + assert step.last_bpm == 1 + assert step.zeroed_h == ("HCM2",) + assert step.zeroed_v == ("VCM1", "VCM2") + assert step.step[1] != 0.0 and step.step[3] != 0.0 + + +def test_correct_last_bpm_follows_the_x_row_only(tmp_path): + tool = _tool(tmp_path, "correct_x_row") + idx = _indices() + x, y = _readings() + y_lost = y.copy() + y_lost[2:] = np.nan + step = tool.correct(x, y_lost, **idx) + assert step.last_bpm == 3 and step.zeroed_h == () and step.zeroed_v == () + assert step.reason is Reason.OK + assert step.step.tobytes() == (step.pseudo_inverse.matrix @ _deviation(x, y_lost)).tobytes() + x_lost = x.copy() + x_lost[2:] = np.nan + step = tool.correct(x_lost, y, **idx) + assert step.last_bpm == 1 and step.zeroed_h == ("HCM2",) and step.zeroed_v == ("VCM2",) + # Beam lost and regained: the last non-NaN entry of x decides. + x_gap = x.copy() + x_gap[1] = np.nan + step = tool.correct(x_gap, y, **idx) + assert step.last_bpm == 3 and step.zeroed_h == () and step.zeroed_v == () + assert step.step.tobytes() == (step.pseudo_inverse.matrix @ _deviation(x_gap, y)).tobytes() + + +def test_correct_no_beam(tmp_path): + tool = _tool(tmp_path, "correct_no_beam", dead=("VCM2",)) + x = np.full(4, np.nan) + _, y = _readings() + reference = (np.zeros(4), y + 0.5) + step = tool.correct(x, y, reference, **_indices(), alpha=0.1) + assert step.reason is Reason.NO_BEAM + assert step.status == "no BPM with beam" + assert step.last_bpm is None + assert step.all_zero + assert step.zeroed_h == tool.layout.hcorr_names and step.zeroed_v == tool.layout.vcorr_names + # The reference's fallback would keep every corrector: the unthreaded solve moves the V plane. + assert np.any(step.pseudo_inverse.matrix @ _deviation(x, y, reference)) + # All-NaN x and y, with and without a reference, read the same. + for reference in (None, (np.full(4, np.nan), np.full(4, np.nan))): + step = tool.correct(x, np.full(4, np.nan), reference, **_indices()) + assert step.reason is Reason.NO_BEAM and step.all_zero and step.last_bpm is None + + +def test_correct_no_inverse_at_n_discard_equal_to_l(tmp_path): + tool = _tool(tmp_path, "correct_no_inverse") + L = tool.layout.L + x, y = _readings() + step = tool.correct(x, y, **_indices(), n_discard=L) + assert step.reason is Reason.NO_INVERSE + assert step.status == "every singular value is discarded; no correction is possible" + assert step.all_zero + assert step.last_bpm == 3 + assert step.zeroed_h == tool.layout.hcorr_names and step.zeroed_v == tool.layout.vcorr_names + assert step.pseudo_inverse.n_discard == L and not np.any(step.pseudo_inverse.inverse_weights) + configured = _tool(tmp_path, "correct_no_inverse_configured", n_discard=L) + step = configured.correct(x, y, **_indices()) + assert step.reason is Reason.NO_INVERSE and step.all_zero + assert configured.correct(x, y, **_indices(), n_discard=L - 1).reason is Reason.OK + + +def test_correct_no_beam_precedes_no_inverse(tmp_path): + tool = _tool(tmp_path, "correct_no_beam_first") + _, y = _readings() + step = tool.correct(np.full(4, np.nan), y, **_indices(), n_discard=tool.layout.L) + assert step.reason is Reason.NO_BEAM and step.all_zero and step.last_bpm is None + + +def test_correct_beam_only_at_the_first_bpm_before_any_corrector_is_no_upstream(tmp_path): + tool = _tool(tmp_path, "correct_no_upstream") + idx = _indices(h_offset=15, v_offset=17) + x, y = _readings(to_bpm=0) + step = tool.correct(x, y, **idx) + assert step.reason is Reason.NO_UPSTREAM + assert step.status == "no corrector upstream of the last BPM with beam" + assert step.last_bpm == 0 + assert step.all_zero + assert step.zeroed_h == tool.layout.hcorr_names and step.zeroed_v == tool.layout.vcorr_names + # Zero deviation at that BPM reads NO_UPSTREAM, never ON_REFERENCE. + on_zero = tool.correct(np.where(np.isnan(x), np.nan, 0.0), np.where(np.isnan(y), np.nan, 0.0), **idx) + assert on_zero.reason is Reason.NO_UPSTREAM and on_zero.all_zero + on_ref = tool.correct(x, y, (x, y), **idx) + assert on_ref.reason is Reason.NO_UPSTREAM and on_ref.all_zero + # NO_INVERSE precedes NO_UPSTREAM. + assert tool.correct(x, y, **idx, n_discard=tool.layout.L).reason is Reason.NO_INVERSE + # One more BPM with beam reaches the first corrector of each plane. + x2, y2 = _readings(to_bpm=1) + reached = tool.correct(x2, y2, **idx) + assert reached.reason is Reason.OK and reached.zeroed_h == ("HCM1", "HCM2") and reached.zeroed_v == ("VCM1", "VCM2") + + +def test_correct_dead_corrector_at_or_before_the_beam_is_not_upstream(tmp_path): + tool = _tool(tmp_path, "correct_dead_upstream_h", dead=("HCM0",)) + idx = _indices() # HCM0 at 5 and VCM0 at 7 are both before BPM0 at 10 + x, y = _readings(to_bpm=0) + step = tool.correct(x, y, **idx) + assert step.reason is Reason.NO_UPSTREAM_H + assert step.status == "no horizontal corrector upstream of the last BPM with beam" + assert step.zeroed_h == tool.layout.hcorr_names + assert step.zeroed_v == ("VCM1", "VCM2") + assert not np.any(step.step_h) and step.step_v[0] != 0.0 and not np.any(step.step_v[1:]) + assert not step.all_zero + both = _tool(tmp_path, "correct_dead_upstream_both", dead=("HCM0", "VCM0")) + step = both.correct(x, y, **idx) + assert step.reason is Reason.NO_UPSTREAM and step.all_zero + assert step.zeroed_h == both.layout.hcorr_names and step.zeroed_v == both.layout.vcorr_names + + +def test_correct_no_upstream_v(tmp_path): + tool = _tool(tmp_path, "correct_no_upstream_v") + idx = _indices(h_offset=5, v_offset=17) + x, y = _readings(to_bpm=0) + # reference == (x, y) with no upstream VCM: NO_UPSTREAM_V and all_zero. + step = tool.correct(x, y, (x, y), **idx) + assert step.reason is Reason.NO_UPSTREAM_V + assert step.status == "no vertical corrector upstream of the last BPM with beam" + assert step.all_zero + assert step.last_bpm == 0 + assert step.zeroed_h == ("HCM1", "HCM2") and step.zeroed_v == tool.layout.vcorr_names + # With a deviation the H plane is corrected and the V plane is zeroed. + step = tool.correct(x, y, **idx) + assert step.reason is Reason.NO_UPSTREAM_V and not step.all_zero + assert step.step_h[0] != 0.0 and not np.any(step.step_h[1:]) and not np.any(step.step_v) + assert step.zeroed_h == ("HCM1", "HCM2") and step.zeroed_v == tool.layout.vcorr_names + + +def test_correct_plane_without_correctors_has_no_upstream_corrector(tmp_path): + tool = _tool(tmp_path, "correct_no_vcm", n_v=0) + x, y = _readings() + step = tool.correct(x, y, **_indices(n_v=0)) + assert step.reason is Reason.NO_UPSTREAM_V + assert step.zeroed_h == () and step.zeroed_v == () + assert step.step_v.shape == (0,) and step.n_h == 3 + assert not step.all_zero and np.all(step.step_h != 0.0) + + +def test_correct_on_reference(tmp_path): + tool = _tool(tmp_path, "correct_on_reference") + idx = _indices() + x, y = _readings() + step = tool.correct(x, y, (x, y), **idx) + assert step.reason is Reason.ON_REFERENCE + assert step.status == "already on reference" + assert step.all_zero and step.last_bpm == 3 and step.zeroed_h == () and step.zeroed_v == () + zeros = np.zeros(4) + assert tool.correct(zeros, zeros, **idx).reason is Reason.ON_REFERENCE + # Partial beam with an upstream corrector per plane: still ON_REFERENCE, with the tail zeroed. + x2, y2 = _readings(to_bpm=1) + step = tool.correct(x2, y2, (x2, y2), **idx) + assert step.reason is Reason.ON_REFERENCE and step.all_zero + assert step.last_bpm == 1 and step.zeroed_h == ("HCM2",) and step.zeroed_v == ("VCM2",) + # A deviation anywhere with beam is OK. + assert tool.correct(x2 + 0.1, y2, (x2, y2), **idx).reason is Reason.OK + + +def test_correct_ok_step(tmp_path): + tool = _tool(tmp_path, "correct_ok", dead=("HCM2",)) + x, y = _readings() + step = tool.correct(x, y, **_indices()) + assert step.reason is Reason.OK and step.status == "" + assert not step.all_zero + assert step.zeroed_h == () and step.zeroed_v == () + assert step.last_bpm == 3 + assert step.names == tool.layout.hcorr_names + tool.layout.vcorr_names + assert step.n_h == tool.layout.n_h + assert step.step[2] == 0.0 # dead corrector, exact-zero row + assert np.all(step.step[[0, 1, 3, 4, 5]] != 0.0) + + +_STATUS_TEXT = { + Reason.NO_BEAM: "no BPM with beam", + Reason.NO_INVERSE: "every singular value is discarded; no correction is possible", + Reason.NO_UPSTREAM: "no corrector upstream of the last BPM with beam", + Reason.NO_UPSTREAM_H: "no horizontal corrector upstream of the last BPM with beam", + Reason.NO_UPSTREAM_V: "no vertical corrector upstream of the last BPM with beam", + Reason.ON_REFERENCE: "already on reference", +} + + +def _expected_reason_and_zeroed(layout, live, x, d_r, weights, idx): + """The ruled predicates and the card's zeroed-list rule, written independently of the tool.""" + n_h = layout.n_h + h_index, v_index = np.array(idx["hcorr_index"]), np.array(idx["vcorr_index"]) + beam = np.flatnonzero(~np.isnan(x)) + if beam.size == 0: + past_h, past_v = np.ones(n_h, bool), np.ones(layout.n_v, bool) + else: + last_index = idx["bpm_index"][beam[-1]] + past_h, past_v = h_index > last_index, v_index > last_index + upstream_h = np.any(live[:n_h] & ~past_h) + upstream_v = np.any(live[n_h:] & ~past_v) + if beam.size == 0: + reason = Reason.NO_BEAM + elif not np.any(weights): + reason = Reason.NO_INVERSE + elif not upstream_h and not upstream_v: + reason = Reason.NO_UPSTREAM + elif not upstream_h: + reason = Reason.NO_UPSTREAM_H + elif not upstream_v: + reason = Reason.NO_UPSTREAM_V + elif not np.any(d_r): + reason = Reason.ON_REFERENCE + else: + reason = Reason.OK + whole_h = reason in (Reason.NO_BEAM, Reason.NO_INVERSE, Reason.NO_UPSTREAM, Reason.NO_UPSTREAM_H) + whole_v = reason in (Reason.NO_BEAM, Reason.NO_INVERSE, Reason.NO_UPSTREAM, Reason.NO_UPSTREAM_V) + zeroed_h = layout.hcorr_names if whole_h else tuple(n for n, p in zip(layout.hcorr_names, past_h, strict=True) if p) + zeroed_v = layout.vcorr_names if whole_v else tuple(n for n, p in zip(layout.vcorr_names, past_v, strict=True) if p) + return reason, zeroed_h, zeroed_v + + +@pytest.mark.parametrize("dead", [(), ("HCM0",), ("VCM0",), ("HCM0", "VCM0"), ("HCM2", "VCM1")]) +def test_correct_all_zero_implies_not_ok_and_zeroed_lists_follow_the_card_on_constructed_cases(tmp_path, dead): + tool = _tool(tmp_path, f"correct_sweep_{len(dead)}_{'_'.join(dead)}", dead=dead) + layout = tool.layout + live = np.array([name not in dead for name in layout.hcorr_names + layout.vcorr_names]) + seen = set() + for offsets in ((5, 7), (15, 17), (5, 17), (17, 5)): + idx = _indices(h_offset=offsets[0], v_offset=offsets[1]) + for to_bpm in (None, 0, 1, 3, "none"): + x, y = (np.full(4, np.nan), _readings()[1]) if to_bpm == "none" else _readings(to_bpm=to_bpm) + for n_discard in (0, 2, layout.L): + for reference in (None, (x, y), (np.zeros(4), y)): + step = tool.correct(x, y, reference, **idx, n_discard=n_discard) + has_ref = "set" if reference is not None else "None" + label = f"offsets={offsets} to_bpm={to_bpm} n_discard={n_discard} reference={has_ref}" + expected = _expected_reason_and_zeroed( + layout, live, x, _deviation(x, y, reference), step.pseudo_inverse.inverse_weights, idx + ) + assert (step.reason, step.zeroed_h, step.zeroed_v) == expected, label + assert not (step.all_zero and step.reason is Reason.OK), label + assert step.reason is not Reason.OK or not step.all_zero, label + assert step.status == ("" if step.reason is Reason.OK else _STATUS_TEXT[step.reason]), label + assert np.all(step.step[_positions(step, step.zeroed_h + step.zeroed_v)] == 0.0), label + assert all(isinstance(name, str) for name in step.zeroed_h + step.zeroed_v), label + assert step.last_bpm == (None if to_bpm == "none" else (3 if to_bpm is None else to_bpm)), label + seen.add(step.reason) + assert seen >= {Reason.NO_BEAM, Reason.NO_INVERSE, Reason.NO_UPSTREAM, Reason.ON_REFERENCE, Reason.OK} + if not dead: + assert seen == set(Reason), f"the live sweep must reach every reason, missing {set(Reason) - seen}" + + +def test_correct_the_three_overlapping_pairs_never_read_ok(tmp_path): + tool = _tool(tmp_path, "correct_overlaps") + x, y = _readings() + # All-NaN x and y. + step = tool.correct(np.full(4, np.nan), np.full(4, np.nan), **_indices()) + assert step.reason is Reason.NO_BEAM and step.all_zero + # Beam only at BPM 1 with zero deviation there. + x1, y1 = np.full(4, np.nan), np.full(4, np.nan) + x1[0], y1[0] = 0.0, 0.0 + step = tool.correct(x1, y1, **_indices(h_offset=15, v_offset=17)) + assert step.reason is Reason.NO_UPSTREAM and step.all_zero + # n_discard == L. + step = tool.correct(x, y, **_indices(), n_discard=tool.layout.L) + assert step.reason is Reason.NO_INVERSE and step.all_zero + + +def test_correct_returns_read_only_fresh_arrays(tmp_path): + tool = _tool(tmp_path, "correct_read_only") + x, y = _readings(to_bpm=2) + step = tool.correct(x, y, **_indices()) + assert step.step.flags.writeable is False + with pytest.raises(ValueError): + step.step[0] = 1.0 + assert step.step_h.flags.writeable is False and step.step_v.flags.writeable is False + assert step.pseudo_inverse.matrix.flags.writeable is False + assert step.pseudo_inverse.inverse_weights.flags.writeable is False + assert step.step.dtype == float and step.step.shape == (tool.layout.n_cor,) + assert not np.shares_memory(step.pseudo_inverse.matrix, tool._state.matrix) + assert isinstance(step.zeroed_h, tuple) and isinstance(step.zeroed_v, tuple) and isinstance(step.names, tuple) + other = tool.correct(x, y, **_indices()) + assert other is not step and other.step is not step.step and other.pseudo_inverse is not step.pseudo_inverse + + +def _settings_of(step): + return (step.pseudo_inverse.alpha, step.pseudo_inverse.n_discard, step.pseudo_inverse.gain) + + +def _input_bytes(x, y, reference, idx): + return (x.tobytes(), y.tobytes(), reference[0].tobytes(), reference[1].tobytes(), {k: v.tobytes() for k, v in idx.items()}) + + +def test_correct_per_call_overrides_reach_the_pseudo_inverse(tmp_path): + tool = _tool(tmp_path, "correct_overrides", alpha=0.2, n_discard=1, gain=2.0) + x, y = _readings() + idx = _indices() + configured = tool.correct(x, y, **idx) + assert _settings_of(configured) == (0.2, 1, 2.0) + override = tool.correct(x, y, **idx, alpha=0.3, n_discard=2, gain=0.5) + assert _settings_of(override) == (0.3, 2, 0.5) + assert override.step.tobytes() != configured.step.tobytes() + assert override.pseudo_inverse.matrix.tobytes() == tool.pseudo_inverse(alpha=0.3, n_discard=2, gain=0.5).matrix.tobytes() + unit = tool.correct(x, y, **idx, gain=1.0) + doubled = tool.correct(x, y, **idx, gain=2.0) + assert doubled.step.tolist() == pytest.approx((2.0 * unit.step).tolist(), rel=1e-14) + again = tool.correct(x, y, **idx) + assert again.step.tobytes() == configured.step.tobytes() + + +def test_correct_is_pure(tmp_path): + tool = _tool(tmp_path, "correct_pure", dead=("VCM1",), alpha=0.1) + before = _full_snapshot(tool) + x, y = _readings(to_bpm=2) + reference = (np.array([0.1, math.nan, 0.3, 0.4]), np.array([0.0, 0.2, math.nan, 0.4])) + idx = {key: np.array(value) for key, value in _indices().items()} + frozen = _input_bytes(x, y, reference, idx) + first = tool.correct(x, y, reference, **idx) + second = tool.correct(x, y, reference, **idx, alpha=3.0, n_discard=2, gain=0.5) + third = tool.correct(x, y, reference, **idx) + _assert_same_snapshot(before, _full_snapshot(tool)) + assert first is not third and first.step.tobytes() == third.step.tobytes() + assert second.step.tobytes() != first.step.tobytes() + assert first.pseudo_inverse.matrix.tobytes() == tool.pseudo_inverse().matrix.tobytes() + assert _input_bytes(x, y, reference, idx) == frozen + assert not np.shares_memory(first.step, tool._state.matrix) + with pytest.raises(PyAMLException): + tool.correct(x[:3], y, reference, **idx) + _assert_same_snapshot(before, _full_snapshot(tool)) + assert tool.correct(x, y, reference, **idx).step.tobytes() == first.step.tobytes() + + +def test_correct_repeat_after_rejected_load_second_load_and_copy_mutation_is_byte_identical(tmp_path): + path = _write_rm(tmp_path / "rm.json", dead=("VCM1",)) + tool = Trajectory("correct_repeat", path, alpha=0.2) + x, y = _readings(to_bpm=2) + idx = _indices() + base = tool.correct(x, y, **idx) + with pytest.raises(PyAMLException): + tool.load(tmp_path / "missing.json") + assert tool.correct(x, y, **idx).step.tobytes() == base.step.tobytes() + bad = _rm_fields() + bad["matrix"] = bad["matrix"][:-1] + with pytest.raises(PyAMLException): + tool.load(_write_rm(tmp_path / "bad.json", fields=bad)) + assert tool.correct(x, y, **idx).step.tobytes() == base.step.tobytes() + tool.load(path) + assert tool.correct(x, y, **idx).step.tobytes() == base.step.tobytes() + rm = tool.response_matrix + rm.matrix[0][0] += 1.0 + repeat = tool.correct(x, y, **idx) + assert repeat.step.tobytes() == base.step.tobytes() + assert repeat.reason is base.reason and repeat.zeroed_h == base.zeroed_h and repeat.zeroed_v == base.zeroed_v + + +def test_correct_from_a_file_shaped_as_the_phase_2_writer_emits_it(tmp_path): + n_bpm, n_h, n_v = 3, 2, 2 + rows = [f"SR{i}:BPM:x" for i in range(n_bpm)] + [f"SR{i}:BPM:y" for i in range(n_bpm)] + hcor, vcor = [f"SR{i}:HCM" for i in range(n_h)], [f"SR{i}:VCM" for i in range(n_v)] + rng = np.random.default_rng(5) + body = { + "type": "pyaml.tuning_tools.orbit_response_matrix_data", + "matrix": np.round(rng.uniform(0.5, 1.5, size=(2 * n_bpm, n_h + n_v)), 9).tolist(), + "observable_names": rows, + "variable_names": hcor + vcor, + "observable_planes": ["H"] * n_bpm + ["V"] * n_bpm, + "variable_planes": ["H"] * n_h + ["V"] * n_v, + } + bpm = [4, 9, 14] + sidecar = {"bpm_index": bpm + bpm, "hcor_index": [2, 7], "vcor_index": [3, 8]} + rm_path = tmp_path / "trajectory_rm.json" + rm_path.write_text(json.dumps(body, indent=2, ensure_ascii=False, allow_nan=False) + "\n") + index_path = tmp_path / "trajectory_rm.index.json" + index_path.write_text(json.dumps(sidecar, indent=2, ensure_ascii=False, allow_nan=False) + "\n") + tool = Factory.build(_config("correct_sidecar", str(rm_path))) + assert tool.layout.bpm_names_h == tuple(rows[:n_bpm]) and tool.layout.bpm_names_v == tuple(rows[n_bpm:]) + index = json.loads(index_path.read_text()) + x, y = _readings(n_bpm=n_bpm) + step = tool.correct(x, y, bpm_index=index["bpm_index"], hcorr_index=index["hcor_index"], vcorr_index=index["vcor_index"]) + assert step.reason is Reason.OK and not step.all_zero + assert step.names == tuple(hcor + vcor) and step.n_h == n_h + assert step.last_bpm == n_bpm - 1 and step.zeroed_h == () and step.zeroed_v == () + + +def test_trajectory_docstring_states_the_divergences_the_x_row_rule_the_reason_order_and_the_error_rule(): + doc = " ".join(Trajectory.__doc__.split()) # whitespace-insensitive: the docstring wraps its sentences + for case in ("dead_last_plain", "first_bpm_only", "one_plane_upstream", "no_beam"): + assert case in doc + assert "NO_BEAM, NO_INVERSE, NO_UPSTREAM, NO_UPSTREAM_H / NO_UPSTREAM_V, ON_REFERENCE, OK" in doc + assert "last non-NaN entry of ``x``" in doc + assert "PyAMLException" in doc and "PyAMLConfigException" in doc + assert "Configuration" in doc and "response_matrix: ${path:trajectory_rm.json}" in doc + assert "correct(" in doc + + +# --------------------------------------------------------------------------- +# the case table and the goldens +# +# ``trajectory_cases.json`` is the expected cases; ``trajectory_goldens.npz`` is +# what MATLAB returned for them. These tests are the goldens' one definition: the +# freeze script reads the case table by path and re-derives none of the +# assertions below. Every test that needs the npz carries ``golden`` in its name. +# --------------------------------------------------------------------------- + +_CASES_PATH = Path(__file__).with_name("trajectory_cases.json") +_CASE_TABLE = json.loads(_CASES_PATH.read_text()) +_CASES = {case["name"]: case for case in _CASE_TABLE["cases"]} + +_CASE_COLUMNS = frozenset( + { + "name", + "kind", + "divergence_planes", + "reason", + "alpha_rel", + "n_discard", + "gain", + "n_bpm", + "n_h", + "n_v", + "dead", + "dead_per_plane", + "structure", + "beam", + "beam_to_bpm", + "reference", + "cond_live", + "inputs", + } +) +_KINDS = ("parity", "inverse", "verdict-only", "step") +_DEAD_PATTERNS = ("none", "last", "mid", "real") +_BEAM_PATTERNS = ("all", "to_bpm", "x_none") +_REFERENCE_PATTERNS = ("none", "nan_entries", "equal_to_readings", "v_only") +_STRUCTURES = ("collinear_live_pair",) +_SUITE = {"n_bpm": 16, "n_h": 12, "n_v": 12} +_EXAMPLE_SR = "example_sr_tikhonov" + +PARITY_RTOL = 1e-10 # design rule 3: max|tool - MATLAB| <= PARITY_RTOL * max|MATLAB| per array +_STEP_FLOOR = 1e-6 # a real MATLAB step is ~1e-3 of max|Mplus| * max|dR|, roundoff ~1e-13 of it +_CALIBRATION = 1e9 +_CALIBRATION_CASES = ("full_plain", _EXAMPLE_SR) # alpha = 0, and the stored alpha on the real matrix +_THREADED_REASONS = frozenset({Reason.OK, Reason.ON_REFERENCE, Reason.NO_UPSTREAM, Reason.NO_UPSTREAM_H, Reason.NO_UPSTREAM_V}) +_SOLVED_REASONS = frozenset({Reason.OK, Reason.ON_REFERENCE}) + +_TOP_LEVEL_FIELDS = ( + "schema_version", + "case_names", + "n_cases", + "sha256_cases", + "matlab_version", + "blas", + "lapack", + "host", + "frozen_on", + "freeze_script_sha", + "freeze_script_commit", + "sha256_SCgetPinv", + "sha256_calcCMstep", + "sha256_driver", + "index_base", +) +_CASE_FIELDS = ( + "matrix", + "variable_names", + "observable_names", + "variable_planes", + "observable_planes", + "n_bpm", + "n_h", + "n_v", + "seed", + "cond_live", + "alpha_rel", + "alpha", + "n_discard", + "gain", + "x", + "y", + "reference", + "bpm_index", + "hcorr_index", + "vcorr_index", + "kind", + "reason", + "S", + "Mplus", + "dPhiHCM", + "dPhiVCM", + "n_kept_h", + "n_kept_v", +) +_EXAMPLE_SR_FIELDS = ("names_source", "names_source_sha256", "osprey_commit") + + +def _case_names(*kinds): + return [name for name, case in _CASES.items() if not kinds or case["kind"] in kinds] + + +def _suite_l(case): + return min(2 * case["n_bpm"], case["n_h"] + case["n_v"]) + + +# -- the case table itself (runs without the npz) ---------------------------- + + +def test_case_table_has_nineteen_distinct_cases(): + names = [case["name"] for case in _CASE_TABLE["cases"]] + assert len(names) == 19 + assert len(set(names)) == 19 + assert _CASE_TABLE["schema_version"] == 1 + + +@pytest.mark.parametrize("name", _case_names()) +def test_case_table_row_has_every_column_with_a_value_in_range(name): + case = _CASES[name] + assert set(case) == _CASE_COLUMNS + assert case["kind"] in _KINDS + assert case["reason"] in Reason.__members__ + assert isinstance(case["alpha_rel"], float) and math.isfinite(case["alpha_rel"]) and case["alpha_rel"] >= 0.0 + assert isinstance(case["n_discard"], int) and not isinstance(case["n_discard"], bool) + assert 0 <= case["n_discard"] <= _suite_l(case) + assert isinstance(case["gain"], float) and math.isfinite(case["gain"]) and case["gain"] > 0.0 + assert case["dead"] in _DEAD_PATTERNS + assert case["beam"] in _BEAM_PATTERNS + assert case["reference"] in _REFERENCE_PATTERNS + assert set(case["structure"]) <= set(_STRUCTURES) + assert set(case["divergence_planes"]) <= {"H", "V"} + assert bool(case["divergence_planes"]) == (case["kind"] in ("verdict-only", "step")) + assert isinstance(case["inputs"], str) and case["inputs"] + if case["beam"] == "to_bpm": + assert isinstance(case["beam_to_bpm"], int) and 1 <= case["beam_to_bpm"] < case["n_bpm"] + else: + assert case["beam_to_bpm"] is None + if case["dead"] == "real": + assert case["dead_per_plane"] is None + else: + assert case["dead_per_plane"] == (0 if case["dead"] == "none" else 1) + if name == _EXAMPLE_SR: + assert case["cond_live"] is None + assert (case["n_bpm"], case["n_h"], case["n_v"]) == (72, 72, 72) + assert case["dead"] == "real" + else: + assert isinstance(case["cond_live"], float) and math.isfinite(case["cond_live"]) and case["cond_live"] > 0.0 + assert {k: case[k] for k in _SUITE} == _SUITE + + +def test_case_table_states_the_divergence_cases_and_the_beam_cut(): + assert _CASES["dead_last_plain"]["kind"] == "inverse" + assert _CASES["dead_last_plain"]["structure"] == ["collinear_live_pair"] + assert _CASES["first_bpm_only"]["beam_to_bpm"] == 1 + assert _CASES["first_bpm_only"]["divergence_planes"] == ["H", "V"] + assert _CASES["one_plane_upstream"]["divergence_planes"] == ["V"] + assert _CASES["no_beam"]["divergence_planes"] == ["V"] and _CASES["no_beam"]["beam"] == "x_none" + # the beam cut keeps a causal V block with every VCM after BPM j at full column rank + one_plane = _CASES["one_plane_upstream"] + assert one_plane["beam_to_bpm"] <= one_plane["n_bpm"] - one_plane["n_v"] + assert _CASES["all_discarded"]["n_discard"] == _suite_l(_CASES["all_discarded"]) + # the only dead cases at alpha = 0 are the inverse divergence and a cut covering the structural zeros + for name, case in _CASES.items(): + if case["dead"] in ("last", "mid") and case["alpha_rel"] == 0.0: + assert name in ("dead_last_plain", "dead_last_discard_2") + assert _CASES["dead_last_discard_2"]["n_discard"] == 2 * _CASES["dead_last_discard_2"]["dead_per_plane"] + for name in _CALIBRATION_CASES: + assert name in _CASES + + +# -- reading the goldens ------------------------------------------------------ + + +@pytest.fixture(scope="module") +def goldens(): + """The frozen npz; a missing file is a ``FileNotFoundError``, never a skip.""" + path = os.environ.get("PYAML_TRAJECTORY_GOLDENS", str(Path(__file__).with_name("trajectory_goldens.npz"))) + with np.load(path, allow_pickle=False) as npz: + yield {key: npz[key] for key in npz.files} + + +def _field(goldens, name, field): + return goldens[f"{name}/{field}"] # a missing case or field is a KeyError on its own id + + +def _scalar(value): + return np.asarray(value).item() # stored npz values pass to the tool as Python scalars + + +def _text(value): + return str(np.asarray(value).item()) + + +def _texts(value): + return [str(item) for item in np.asarray(value).reshape(-1).tolist()] + + +def _golden_tool(goldens, name, scale=1.0, alpha=None): + """The tool built from the case's stored matrix and names (a mapping, so nothing is written to disk).""" + fields = { + "matrix": (scale * np.asarray(_field(goldens, name, "matrix"), dtype=float)).tolist(), + "variable_names": _texts(_field(goldens, name, "variable_names")), + "observable_names": _texts(_field(goldens, name, "observable_names")), + "variable_planes": _texts(_field(goldens, name, "variable_planes")), + "observable_planes": _texts(_field(goldens, name, "observable_planes")), + } + return Trajectory( + f"golden_{name}", + fields, + alpha=_scalar(_field(goldens, name, "alpha")) if alpha is None else alpha, + n_discard=_scalar(_field(goldens, name, "n_discard")), + gain=_scalar(_field(goldens, name, "gain")), + ) + + +def _golden_bpm_index(goldens, name): + """The tool's ``bpm_index``: the npz stores MATLAB's one-plane ``BPMindex``, both halves equal.""" + stored = np.asarray(_field(goldens, name, "bpm_index")) + n_bpm = _scalar(_field(goldens, name, "n_bpm")) + if stored.reshape(-1).size == n_bpm: + return np.concatenate([stored.reshape(-1), stored.reshape(-1)]) + return stored + + +def _golden_inputs(goldens, name, scale=1.0): + readings = { + "x": scale * np.asarray(_field(goldens, name, "x"), dtype=float), + "y": scale * np.asarray(_field(goldens, name, "y"), dtype=float), + "reference": scale * np.asarray(_field(goldens, name, "reference"), dtype=float), # verbatim + } + indices = { + "bpm_index": _golden_bpm_index(goldens, name), + "hcorr_index": np.asarray(_field(goldens, name, "hcorr_index")), + "vcorr_index": np.asarray(_field(goldens, name, "vcorr_index")), + } + return readings, indices + + +def _golden_step(goldens, name): + tool = _golden_tool(goldens, name) + readings, indices = _golden_inputs(goldens, name) + return tool, tool.correct(readings["x"], readings["y"], readings["reference"], **indices) + + +def _golden_d_r(goldens, name): + """MATLAB's ``dR = R - R0`` with NaN set to 0, in RM row order (all x rows, then all y rows).""" + readings, _ = _golden_inputs(goldens, name) + d_r = np.concatenate([readings["x"], readings["y"]]) - readings["reference"].reshape(-1) + d_r[np.isnan(d_r)] = 0.0 + return d_r + + +def _assert_parity(label, tool_array, matlab_array): + tool_array = np.asarray(tool_array, dtype=float) + matlab_array = np.asarray(matlab_array, dtype=float) + assert tool_array.shape == matlab_array.shape, label + assert np.all(np.isfinite(matlab_array)), label + error = np.max(np.abs(tool_array - matlab_array)) + assert error <= PARITY_RTOL * np.max(np.abs(matlab_array)), f"{label}: max|tool - MATLAB| = {error:.3e}" + + +def _plane(step, plane): + return step.step_h if plane == "H" else step.step_v + + +_DPHI = {"H": "dPhiHCM", "V": "dPhiVCM"} + + +def _parity_arrays(case): + """The arrays a case compares under the parity rule (design rule 3), by kind.""" + if case["kind"] == "inverse": + return () # raw Mplus and dPhi document the divergence; the inverse is compared to MATLAB pinv + if case["kind"] == "step": + return ("Mplus",) # the tool's whole step is zero under NO_BEAM; MATLAB's is the divergence + return ("Mplus",) + tuple(_DPHI[p] for p in ("H", "V") if p not in case["divergence_planes"]) + + +# -- the goldens -------------------------------------------------------------- + + +def test_golden_file_provenance(goldens): + for field in _TOP_LEVEL_FIELDS: + assert field in goldens, field + assert _scalar(goldens["schema_version"]) == 1 + assert _text(goldens["sha256_cases"]) == hashlib.sha256(_CASES_PATH.read_bytes()).hexdigest() + assert _text(goldens["sha256_driver"]) + assert _scalar(goldens["index_base"]) == 0 + assert sorted(_texts(goldens["case_names"])) == sorted(_CASES) + assert _scalar(goldens["n_cases"]) == len(_CASES) == 19 + for key, value in goldens.items(): + if value.dtype.kind in "US": + for text in _texts(value): + assert not text.startswith(("/", "~")), key + assert "/Users/" not in text and "/home/" not in text and ".claude/" not in text, key + + +@pytest.mark.parametrize("name", _case_names()) +def test_golden_case_fields_and_settings_match_the_table(goldens, name): + case = _CASES[name] + for field in _CASE_FIELDS: + assert f"{name}/{field}" in goldens, field + if case["kind"] == "inverse": + assert f"{name}/pinv" in goldens + if name == _EXAMPLE_SR: + for field in _EXAMPLE_SR_FIELDS: + assert f"{name}/{field}" in goldens, field + source = _text(_field(goldens, name, "names_source")) + assert source and not source.startswith(("/", "~")) and ".claude/" not in source + assert len(_text(_field(goldens, name, "names_source_sha256"))) == 64 + assert _text(_field(goldens, name, "osprey_commit")) + assert _text(_field(goldens, name, "kind")) == case["kind"] + assert _text(_field(goldens, name, "reason")) == case["reason"] + assert _scalar(_field(goldens, name, "alpha_rel")) == case["alpha_rel"] + assert _scalar(_field(goldens, name, "n_discard")) == case["n_discard"] + assert _scalar(_field(goldens, name, "gain")) == case["gain"] + for count in ("n_bpm", "n_h", "n_v"): + assert _scalar(_field(goldens, name, count)) == case[count], count + for kept in ("n_kept_h", "n_kept_v"): + assert np.asarray(_field(goldens, name, kept)).dtype == np.int64, kept + cond_live = _scalar(_field(goldens, name, "cond_live")) + assert math.isfinite(cond_live) and cond_live > 0.0 + if case["cond_live"] is not None: + assert abs(cond_live / case["cond_live"] - 1.0) <= 1e-2 + + +@pytest.mark.parametrize("name", _case_names()) +def test_golden_alpha_is_alpha_rel_times_the_matrix_norm(goldens, name): + case = _CASES[name] + alpha = _scalar(_field(goldens, name, "alpha")) + if case["alpha_rel"] == 0.0: + assert alpha == 0.0 + else: + norm = np.linalg.norm(np.asarray(_field(goldens, name, "matrix"), dtype=float), 2) + assert alpha == pytest.approx(case["alpha_rel"] * norm, rel=1e-12, abs=0.0) + tool, step = _golden_step(goldens, name) + assert step.pseudo_inverse.alpha == alpha + assert step.pseudo_inverse.n_discard == case["n_discard"] + assert step.pseudo_inverse.gain == case["gain"] + + +@pytest.mark.parametrize("name", _case_names()) +def test_golden_inputs_follow_the_case_table(goldens, name): + case = _CASES[name] + readings, indices = _golden_inputs(goldens, name) + x, y, reference = readings["x"], readings["y"], readings["reference"] + n_bpm = case["n_bpm"] + assert x.shape == (n_bpm,) and y.shape == (n_bpm,) and reference.shape == (2, n_bpm) + if case["beam"] == "all": + assert np.all(np.isfinite(x)) and np.all(np.isfinite(y)) + elif case["beam"] == "to_bpm": + j = case["beam_to_bpm"] + assert np.all(np.isfinite(x[:j])) and np.all(np.isfinite(y[:j])) + assert np.all(np.isnan(x[j:])) and np.all(np.isnan(y[j:])) + else: + assert np.all(np.isnan(x)) and np.all(np.isfinite(y)) + if case["reference"] == "none": + assert np.array_equal(reference, np.zeros((2, n_bpm))) + elif case["reference"] == "nan_entries": + assert np.any(np.isnan(reference)) + elif case["reference"] == "equal_to_readings": + assert np.array_equal(reference, np.vstack([x, y]), equal_nan=True) + else: + assert np.array_equal(reference[0], np.zeros(n_bpm)) + assert np.all(np.isfinite(reference[1])) and np.all(reference[1] != y) + assert indices["bpm_index"].shape == (2 * n_bpm,) + assert indices["hcorr_index"].shape == (case["n_h"],) and indices["vcorr_index"].shape == (case["n_v"],) + + +@pytest.mark.parametrize("name", _case_names()) +def test_golden_layout_identities(goldens, name): + case = _CASES[name] + tool, step = _golden_step(goldens, name) + layout = tool.layout + assert (layout.n_bpm, layout.n_h, layout.n_v) == (case["n_bpm"], case["n_h"], case["n_v"]) + assert layout.n_cor == layout.n_h + layout.n_v + assert layout.L == min(2 * layout.n_bpm, layout.n_cor) + assert layout.k_live == min(2 * layout.n_bpm, layout.n_live) + assert layout.n_struct == layout.L - layout.k_live + assert step.names == tuple(_texts(_field(goldens, name, "variable_names"))) + assert len(step.pseudo_inverse.singular_values) == layout.L + assert np.asarray(_field(goldens, name, "S")).reshape(-1).shape == (layout.L,) + assert step.pseudo_inverse.matrix.shape == np.asarray(_field(goldens, name, "Mplus")).shape + matrix = np.asarray(_field(goldens, name, "matrix"), dtype=float) + dead_names = tuple(n for n, column in zip(step.names, matrix.T, strict=True) if not np.any(column)) + assert layout.no_response_names == dead_names + if case["dead"] == "none": + assert dead_names == () + elif case["dead"] == "last": + assert dead_names == (layout.hcorr_names[-1], layout.vcorr_names[-1]) + elif case["dead"] == "mid": + assert len(dead_names) == 2 + assert dead_names[0] in layout.hcorr_names[1:-1] and dead_names[1] in layout.vcorr_names[1:-1] + + +@pytest.mark.parametrize("name", _case_names()) +def test_golden_reason_and_the_all_zero_invariant(goldens, name): + tool, step = _golden_step(goldens, name) + assert step.reason is Reason[_CASES[name]["reason"]] + if step.all_zero: + assert step.reason is not Reason.OK + + +@pytest.mark.parametrize("name", _case_names()) +def test_golden_zeroing_matches_matlab_kept_counts(goldens, name): + tool, step = _golden_step(goldens, name) + layout = tool.layout + if step.reason in _THREADED_REASONS: + for plane, names, zeroed in ( + ("h", layout.hcorr_names, step.zeroed_h), + ("v", layout.vcorr_names, step.zeroed_v), + ): + n_kept = _scalar(_field(goldens, name, f"n_kept_{plane}")) + if n_kept > 0: + assert zeroed == names[n_kept:], plane + else: + # the stated divergence: MATLAB zeroes nothing in a plane with no upstream corrector + assert zeroed == names, plane + assert step.reason in (Reason.NO_UPSTREAM, Reason.NO_UPSTREAM_H if plane == "h" else Reason.NO_UPSTREAM_V) + else: + # NO_BEAM and NO_INVERSE zero both planes whole; MATLAB's fallback keeps correctors, so the + # recorded counts are not compared + assert step.reason in (Reason.NO_BEAM, Reason.NO_INVERSE) + assert step.zeroed_h == layout.hcorr_names + assert step.zeroed_v == layout.vcorr_names + + +@pytest.mark.parametrize("name", [n for n in _case_names() if _parity_arrays(_CASES[n])]) +def test_golden_parity(goldens, name): + case = _CASES[name] + tool, step = _golden_step(goldens, name) + tool_arrays = {"Mplus": step.pseudo_inverse.matrix, "dPhiHCM": step.step_h, "dPhiVCM": step.step_v} + for array in _parity_arrays(case): + _assert_parity(f"{name}/{array}", tool_arrays[array], np.asarray(_field(goldens, name, array))) + + +@pytest.mark.parametrize("name", _case_names("verdict-only")) +def test_golden_verdict_only_divergence(goldens, name): + tool, step = _golden_step(goldens, name) + mplus = np.asarray(_field(goldens, name, "Mplus"), dtype=float) + bound = PARITY_RTOL * np.max(np.abs(mplus)) * np.max(np.abs(_golden_d_r(goldens, name))) + for plane in _CASES[name]["divergence_planes"]: + assert np.all(_plane(step, plane) == 0.0), plane + matlab = np.asarray(_field(goldens, name, _DPHI[plane]), dtype=float) + assert np.all(np.isfinite(matlab)) and np.max(np.abs(matlab)) <= bound, plane + + +@pytest.mark.parametrize("name", _case_names("step")) +def test_golden_step_divergence(goldens, name): + tool, step = _golden_step(goldens, name) + assert np.all(step.step == 0.0) + mplus = np.asarray(_field(goldens, name, "Mplus"), dtype=float) + n_bpm = _CASES[name]["n_bpm"] + for plane in _CASES[name]["divergence_planes"]: + rows = slice(0, n_bpm) if plane == "H" else slice(n_bpm, 2 * n_bpm) + d_r_plane = _golden_d_r(goldens, name)[rows] + assert np.all(_plane(step, plane) == 0.0), plane + matlab = np.asarray(_field(goldens, name, _DPHI[plane]), dtype=float) + assert np.max(np.abs(matlab)) > _STEP_FLOOR * np.max(np.abs(mplus)) * np.max(np.abs(d_r_plane)), plane + + +@pytest.mark.parametrize("name", _case_names("inverse")) +def test_golden_inverse_divergence(goldens, name): + tool, step = _golden_step(goldens, name) + layout = tool.layout + golden_pinv = np.asarray(_field(goldens, name, "pinv"), dtype=float) + _assert_parity(f"{name}/pinv", tool.pseudo_inverse().matrix, golden_pinv) + singular = np.asarray(_field(goldens, name, "S"), dtype=float).reshape(-1) + guard = max(2 * layout.n_bpm, layout.n_cor) * np.finfo(float).eps * singular[0] + assert np.count_nonzero(singular <= guard) == layout.n_struct + 1 + raw_mplus = np.asarray(_field(goldens, name, "Mplus"), dtype=float) + finite = np.all(np.isfinite(raw_mplus)) + assert not finite or np.max(np.abs(raw_mplus)) > 1e6 * np.max(np.abs(golden_pinv)) + non_finite_rows = ~np.all(np.isfinite(raw_mplus), axis=1) + raw_dphi = np.concatenate( + [np.asarray(_field(goldens, name, "dPhiHCM"), dtype=float), np.asarray(_field(goldens, name, "dPhiVCM"), dtype=float)] + ) + assert not np.any(np.isfinite(raw_dphi[non_finite_rows])) + assert step.pseudo_inverse.rank_discarded == 1 + + +@pytest.mark.parametrize("name", [n for n in _case_names() if Reason[_CASES[n]["reason"]] in _SOLVED_REASONS]) +def test_golden_observable_purity(goldens, name): + tool, step = _golden_step(goldens, name) + zeroed = set(step.zeroed_h) | set(step.zeroed_v) + mask = np.array([n in zeroed for n in step.names]) + solved = step.pseudo_inverse.matrix @ _golden_d_r(goldens, name) + assert np.all(step.step[mask] == 0.0) + assert np.array_equal(step.step[~mask], solved[~mask]) + + +def test_golden_full_plain_zeroes_nothing(goldens): + tool, step = _golden_step(goldens, "full_plain") + assert step.zeroed_h == () and step.zeroed_v == () + + +@pytest.mark.parametrize("name", _CALIBRATION_CASES) +def test_golden_calibration_invariance(goldens, name): + """A change of units scales the matrix, the readings and alpha by one factor; the step is unchanged.""" + tool, step = _golden_step(goldens, name) + scaled_tool = _golden_tool(goldens, name, scale=_CALIBRATION, alpha=_CALIBRATION * _scalar(_field(goldens, name, "alpha"))) + readings, indices = _golden_inputs(goldens, name, scale=_CALIBRATION) + scaled = scaled_tool.correct(readings["x"], readings["y"], readings["reference"], **indices) + assert scaled.reason is step.reason + assert np.max(np.abs(scaled.step - step.step)) <= PARITY_RTOL * np.max(np.abs(step.step)) + + +def test_golden_example_sr_cond_live_is_read_from_the_goldens(goldens): + cond_live = _scalar(_field(goldens, _EXAMPLE_SR, "cond_live")) + assert _CASES[_EXAMPLE_SR]["cond_live"] is None + assert math.isfinite(cond_live) and cond_live > 1.0 diff --git a/tests/tuning_tools/trajectory_cases.json b/tests/tuning_tools/trajectory_cases.json new file mode 100644 index 000000000..da3e8aaa4 --- /dev/null +++ b/tests/tuning_tools/trajectory_cases.json @@ -0,0 +1,412 @@ +{ + "schema_version": 1, + "description": "The frozen trajectory-correction cases. The fork test (test_trajectory.py) reads this file as its expected cases and is the one definition of the goldens; the freeze script reads it by path to build the cases and records its sha256 as sha256_cases in the npz. This file is written once; any change to it is a freeze-side change and requires a new freeze.", + "conventions": { + "suite": "Every synthetic case has n_bpm = 16, n_h = n_v = 12 and a causal, decoupled response matrix whose columns are all H correctors then all V correctors; example_sr_tikhonov is the phase-2 writer's real 72/72/72 matrix.", + "bpm_numbering": "beam_to_bpm counts BPMs from 1: j means BPMs 1..j carry beam and x and y are NaN at every BPM after BPM j. Index arrays stored in the npz are 0-based (index_base = 0).", + "alpha": "alpha = alpha_rel * ||matrix||_2; both are stored in the npz.", + "no_reference": "A case whose reference is 'none' stores reference = zeros((2, n_bpm)), which is what MATLAB receives as R0 and what the tool's reference=None means." + }, + "columns": { + "name": "case name; the npz key prefix", + "kind": "parity | inverse | verdict-only | step: which golden assertion checks the case", + "divergence_planes": "planes checked by the verdict-only or step assertion instead of the parity rule; empty for parity and inverse", + "reason": "expected Reason name of the tool's correct()", + "alpha_rel": "Tikhonov alpha relative to ||matrix||_2", + "n_discard": "number of trailing entries of the full-length spectrum zeroed (SCgetPinv's N); all_discarded uses L = min(2*n_bpm, n_cor) = 24", + "gain": "gain (SCgetPinv's damping)", + "n_bpm": "BPMs per plane", + "n_h": "horizontal correctors", + "n_v": "vertical correctors", + "dead": "none | last | mid | real: which corrector columns are exactly zero; last = the last corrector of each plane, mid = one corrector inside each plane, real = whatever the real matrix has", + "dead_per_plane": "number of zero columns per plane, null for the real matrix", + "structure": "extra structural features of the matrix; collinear_live_pair = one live column set to c times its neighbour in the same BPM gap (c from the seed), the matrix still causal", + "beam": "all | to_bpm | x_none: all = every BPM has beam; to_bpm = beam at BPMs 1..beam_to_bpm only (NaN in x and y after it); x_none = x is NaN everywhere, y is finite", + "beam_to_bpm": "the beam cut j for beam = to_bpm, else null", + "reference": "none | nan_entries | equal_to_readings | v_only: none = zero reference; nan_entries = readings finite, NaN only in some reference entries; equal_to_readings = reference == (x, y); v_only = the H reference row is zero and the V row is finite and differs from y at every BPM", + "cond_live": "condition number of the live block, 1e3 by construction (for dead_last_plain, of the live block before the collinear pair); null for example_sr_tikhonov, whose value is computed from the real matrix and lives in the npz only", + "inputs": "the proposal's beam-and-inputs description, verbatim" + }, + "cases": [ + { + "name": "full_plain", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all BPMs" + }, + { + "name": "full_tikhonov", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.01, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all" + }, + { + "name": "full_discard", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.0, + "n_discard": 2, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all" + }, + { + "name": "full_gain", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 0.7, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all" + }, + { + "name": "full_all", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.01, + "n_discard": 2, + "gain": 0.7, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all" + }, + { + "name": "nan_tail_plain", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "to_bpm", + "beam_to_bpm": 10, + "reference": "none", + "cond_live": 1000.0, + "inputs": "to BPM j; an upstream corrector per plane" + }, + { + "name": "nan_tail_tikhonov", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.01, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "to_bpm", + "beam_to_bpm": 10, + "reference": "none", + "cond_live": 1000.0, + "inputs": "same" + }, + { + "name": "ref_nan", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "nan_entries", + "cond_live": 1000.0, + "inputs": "all; NaN only in `reference`" + }, + { + "name": "dead_last_tikhonov", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.01, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "last", + "dead_per_plane": 1, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all" + }, + { + "name": "dead_last_discard_2", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.0, + "n_discard": 2, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "last", + "dead_per_plane": 1, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all; `N = n_struct`, nothing live cut" + }, + { + "name": "dead_last_discard_4", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.01, + "n_discard": 4, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "last", + "dead_per_plane": 1, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all; a live cut of 2 under the structural zeros" + }, + { + "name": "dead_mid_tikhonov", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.01, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "mid", + "dead_per_plane": 1, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all" + }, + { + "name": "example_sr_tikhonov", + "kind": "parity", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.01, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 72, + "n_h": 72, + "n_v": 72, + "dead": "real", + "dead_per_plane": null, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": null, + "inputs": "all; 72/72/72, the phase-2 writer's matrix and names" + }, + { + "name": "on_reference", + "kind": "parity", + "divergence_planes": [], + "reason": "ON_REFERENCE", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "equal_to_readings", + "cond_live": 1000.0, + "inputs": "all; `reference == (x, y)`" + }, + { + "name": "all_discarded", + "kind": "parity", + "divergence_planes": [], + "reason": "NO_INVERSE", + "alpha_rel": 0.0, + "n_discard": 24, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all; MATLAB's `D` is all zero" + }, + { + "name": "dead_last_plain", + "kind": "inverse", + "divergence_planes": [], + "reason": "OK", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "last", + "dead_per_plane": 1, + "structure": ["collinear_live_pair"], + "beam": "all", + "beam_to_bpm": null, + "reference": "none", + "cond_live": 1000.0, + "inputs": "all; plus one collinear live pair" + }, + { + "name": "first_bpm_only", + "kind": "verdict-only", + "divergence_planes": ["H", "V"], + "reason": "NO_UPSTREAM", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "to_bpm", + "beam_to_bpm": 1, + "reference": "none", + "cond_live": 1000.0, + "inputs": "beam at BPM 1 only" + }, + { + "name": "one_plane_upstream", + "kind": "verdict-only", + "divergence_planes": ["V"], + "reason": "NO_UPSTREAM_V", + "alpha_rel": 0.0, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "none", + "dead_per_plane": 0, + "structure": [], + "beam": "to_bpm", + "beam_to_bpm": 4, + "reference": "none", + "cond_live": 1000.0, + "inputs": "to BPM j; first HCM at or before j, first VCM after j" + }, + { + "name": "no_beam", + "kind": "step", + "divergence_planes": ["V"], + "reason": "NO_BEAM", + "alpha_rel": 0.01, + "n_discard": 0, + "gain": 1.0, + "n_bpm": 16, + "n_h": 12, + "n_v": 12, + "dead": "last", + "dead_per_plane": 1, + "structure": [], + "beam": "x_none", + "beam_to_bpm": null, + "reference": "v_only", + "cond_live": 1000.0, + "inputs": "all-NaN `x`; finite `y` and V reference, never equal" + } + ] +} diff --git a/tests/tuning_tools/trajectory_goldens.npz b/tests/tuning_tools/trajectory_goldens.npz new file mode 100644 index 0000000000000000000000000000000000000000..d54094c3f0c4b876353a4c090bdefd24cb7a56a2 GIT binary patch literal 480676 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 z
  • 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�pBtD@QaOAGrVF% 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%0A>qKG5O0d9j!%>DY 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 literal 0 HcmV?d00001 From cc8ab33b6bb368dbefbf6786b0408ce190861afd Mon Sep 17 00:00:00 2001 From: ThorstenHellert Date: Fri, 16 Oct 2026 12:15:35 -0700 Subject: [PATCH 3/4] test(tuning_tools): skip golden tests when the goldens file is absent A checkout without tests/tuning_tools/trajectory_goldens.npz now skips the 156 golden tests with a reason instead of erroring, so the module runs on a tree that does not ship the binary. A file named through PYAML_TRAJECTORY_GOLDENS stays required: a wrong path still errors. --- tests/tuning_tools/test_trajectory.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/tuning_tools/test_trajectory.py b/tests/tuning_tools/test_trajectory.py index c1391da76..bae74492b 100644 --- a/tests/tuning_tools/test_trajectory.py +++ b/tests/tuning_tools/test_trajectory.py @@ -1,7 +1,9 @@ """Tests for :mod:`pyaml.tuning_tools.trajectory`. Every test that needs the frozen goldens file carries ``golden`` in its name, so -``pytest -k "not golden"`` runs the rest without it. The module clears pyAML's +``pytest -k "not golden"`` runs the rest without it. When the in-repo goldens file is +absent the golden tests skip; a file named through ``PYAML_TRAJECTORY_GOLDENS`` is +required and a missing one errors. The module clears pyAML's element registry itself, because it must also run without the repository's ``conftest.py``. """ @@ -2243,8 +2245,16 @@ def test_case_table_states_the_divergence_cases_and_the_beam_cut(): @pytest.fixture(scope="module") def goldens(): - """The frozen npz; a missing file is a ``FileNotFoundError``, never a skip.""" - path = os.environ.get("PYAML_TRAJECTORY_GOLDENS", str(Path(__file__).with_name("trajectory_goldens.npz"))) + """The frozen npz. + + The in-repo file is optional: a checkout that does not ship it skips every golden + test. A path named through ``PYAML_TRAJECTORY_GOLDENS`` is required, so a wrong + path is a ``FileNotFoundError`` and never a silent skip. + """ + override = os.environ.get("PYAML_TRAJECTORY_GOLDENS") + path = Path(override) if override else Path(__file__).with_name("trajectory_goldens.npz") + if not override and not path.is_file(): + pytest.skip(f"{path.name} is not in this checkout; set PYAML_TRAJECTORY_GOLDENS to run the golden tests") with np.load(path, allow_pickle=False) as npz: yield {key: npz[key] for key in npz.files} From 35893ba978b678ae56d3e3b24c2526c8444d7cf2 Mon Sep 17 00:00:00 2001 From: ThorstenHellert Date: Sat, 17 Oct 2026 13:24:38 -0700 Subject: [PATCH 4/4] ci: publish only .postN tags from the fork A plain X.Y.Z tag is upstream's release. Pushing one to the fork must not publish it under the fork's distribution name. --- .github/workflows/deploy-pypi.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/deploy-pypi.yaml b/.github/workflows/deploy-pypi.yaml index 58292ea0e..153e23684 100644 --- a/.github/workflows/deploy-pypi.yaml +++ b/.github/workflows/deploy-pypi.yaml @@ -3,7 +3,6 @@ name: Publish Python Package on: push: tags: - - '[0-9]+.[0-9]+.[0-9]+' - '[0-9]+.[0-9]+.[0-9]+.post[0-9]+' workflow_dispatch: