Skip to content

Allow for BPM to read only a single position - #459

Open
GamelinAl wants to merge 1 commit into
mainfrom
457-bpm-single-plane
Open

GamelinAl wants to merge 1 commit into
mainfrom
457-bpm-single-plane

Conversation

@GamelinAl

Copy link
Copy Markdown
Member

Solve #457

The idea is to add a new CSSparseScalarAggregator class (subclass of CSScalarAggregator) to allow for aggregator with missing values. The missing values are replaced by nan values.

ControlSystem.create_bpm_aggregators now uses this new CSSparseScalarAggregator to avoid the bug described in #457.

AI Summary

Description

A pyaml.bpm.bpm.BPM may define only one position plane, e.g. a vertical-only X-BPM (y_pos only). Such a BPM works in a simulator mode, but building the control-system mode failed as soon as it was part of a pyaml.arrays.bpm array (PyAMLException: All devices must be instances of Attribute), because a None position device was passed to the backend aggregator. Reading the BPM alone also failed (None.get()).

With this PR, a missing plane reads NaN, both for a single BPM and in BPM arrays. Grouped (parallel) reads are kept for all accessors, so mixing single-plane BPMs into an array costs nothing in performance.

Related Issue

Features/issues described there are:

  • bugfix: ControlSystem.create_bpm_aggregators now handles BPMs with a missing position device. It uses a new CSSparseScalarAggregator that only adds the existing devices to the backend aggregator and scatters the values back into a NaN-filled array. This keeps one grouped read per accessor (positions, h, v). Falling back to per-BPM reads would cost 2N sequential round trips: with a simulated 1 ms per Tango read, ~260 ms instead of ~1 ms for 120 BPMs + 4 XBPMs.
  • bugfix: RBpmArray (control system) returns NaN for a plane without device and takes unit() from whichever device is defined.

Changes to existing functionality

  • create_bpm_aggregators now returns CSSparseScalarAggregator instances instead of CSScalarAggregator. Behaviour is unchanged for BPMs with both planes; the only overhead is one array copy per read.
  • CSSparseScalarAggregator is a subclass rather than a change to CSScalarAggregator, on purpose:
    • CSStrengthScalarAggregator inherits from CSScalarAggregator, adds devices through self._devs directly and uses nb_device() as the number of power supplies, so slot tracking in the base class would be bypassed or ambiguous.
    • For magnets, a missing device is a configuration error and must keep raising, not turn into silent NaN reads or skipped writes.

Testing

The following tests (compatible with pytest) were added in tests/bpm/test_bpm_controlsystem.py, using the dummy tango-pyaml backend:

  • test_controlsystem_bpm_single_plane: a vertical-only BPM reads [nan, y] and reports the unit of its y device.
  • test_controlsystem_bpm_array_with_single_plane_bpm: an array of two full BPMs + one XBPM builds; positions, h and v return the right values with NaN at the missing plane; all three aggregators exist and read through the grouped path.
  • test_controlsystem_bpm_array_without_horizontal_plane: an array of XBPMs only returns all-NaN h and correct v.

Verify that your checklist complies with the project

  • New and existing unit tests pass locally (324 passed, 6 skipped)
  • Tests were added to prove that all features/changes are effective
  • The code is commented where appropriate
  • Any existing features are not broken (unless there is an explicit change to an existing functionality)

🤖 Generated with Claude Code

Solve #437

Add a new CSSparseScalarAggregator class to allow for aggregator with missing values.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ControlSystem fails on BPMs with a single position plane

1 participant