From cdec557239486437bbe18b069cae0e133e97b422 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Wed, 16 Sep 2026 17:07:04 +0200 Subject: [PATCH 01/16] Complete magnet holder navigation (#373) --- pyaml/common/holders/generic_array_holder.py | 51 ++++++++++ pyaml/common/holders/sub_holders.py | 50 ++++++++++ tests/common/test_array_holder_navigation.py | 99 ++++++++++++++++++++ tests/test_load_conf_with_code.py | 2 + 4 files changed, 202 insertions(+) create mode 100644 tests/common/test_array_holder_navigation.py diff --git a/pyaml/common/holders/generic_array_holder.py b/pyaml/common/holders/generic_array_holder.py index 0ce62441..4004a52a 100644 --- a/pyaml/common/holders/generic_array_holder.py +++ b/pyaml/common/holders/generic_array_holder.py @@ -42,6 +42,13 @@ class GenericArrayHolder(Generic[T, A]): Return a named array or a transient array of all elements. add(arrayName, elementNames) Create and register a named array from element selectors. + + Notes + ----- + A configured array is also reachable as an attribute when its name is a + valid Python identifier, e.g. ``holder.QuadForTune`` is equivalent to + ``holder.get("QuadForTune")``. Array names appear in ``dir(holder)`` so + interactive completion (IPython, Jupyter) discovers them. """ def __init__( @@ -117,5 +124,49 @@ def __getitem__(self, key): """ return self.get().__getitem__(key) + def __getattr__(self, name: str) -> A: + """ + Return a configured array through attribute access. + + Only called when normal attribute lookup fails, so it never shadows + :meth:`get`, :meth:`add`, or any other existing attribute. + + Parameters + ---------- + name : str + Configured array name. Must be a valid Python identifier. + + Returns + ------- + A + The array registered under ``name``. + + Raises + ------ + AttributeError + If ``name`` starts with an underscore, is not a valid Python + identifier, or does not match a configured array. + + Examples + -------- + >>> quad_family = sr.live.magnets.get("QuadForTune") + >>> same_quad_family = sr.live.magnets.QuadForTune + """ + if name.startswith("_") or not name.isidentifier() or name not in self._array_store: + raise AttributeError(f"'{type(self).__name__}' object has no array named '{name}'") + return self._array_store[name] + + def __dir__(self) -> list[str]: + """ + List attributes, including configured array names. + + Returns + ------- + list of str + Default attributes plus configured array names that are valid + Python identifiers, for interactive completion (IPython, Jupyter). + """ + return sorted(set(super().__dir__()) | {name for name in self._array_store if name.isidentifier()}) + def __repr__(self): return __pyaml_repr__(self) diff --git a/pyaml/common/holders/sub_holders.py b/pyaml/common/holders/sub_holders.py index 399485eb..d61088ba 100644 --- a/pyaml/common/holders/sub_holders.py +++ b/pyaml/common/holders/sub_holders.py @@ -42,6 +42,19 @@ class MagnetsHolder(GenericArrayHolder[Magnet, MagnetArray]): ---------- peer : 'ElementHolder' Parent element holder that owns this specialized holder. + + Notes + ----- + A configured magnet family is also reachable as an attribute when its + name is a valid Python identifier, e.g. ``magnets.QuadForTune`` is + equivalent to ``magnets.get("QuadForTune")``. Family names appear in + ``dir(magnets)`` for interactive completion. + + Examples + -------- + >>> quad_family = sr.live.magnets.get("QuadForTune") + >>> same_quad_family = sr.live.magnets.QuadForTune + >>> combined_function_magnets = sr.live.magnets.get_cfm() """ def __init__(self, peer: "ElementHolder"): @@ -57,6 +70,22 @@ def __init__(self, peer: "ElementHolder"): "Magnet array", ) + def get_cfm(self) -> CombinedFunctionMagnetArray: + """ + Return all combined-function magnets. + + Returns + ------- + CombinedFunctionMagnetArray + New unnamed container with every registered combined-function + magnet. + + Examples + -------- + >>> combined_function_magnets = sr.live.magnets.get_cfm() + """ + return self._peer.combined_function_magnets.get() + class CombinedFunctionMagnetHolder(GenericElementHolder[CombinedFunctionMagnet]): """ @@ -83,6 +112,13 @@ class CombinedFunctionMagnetsHolder(GenericArrayHolder[CombinedFunctionMagnet, C ---------- peer : 'ElementHolder' Parent element holder that owns this specialized holder. + + Notes + ----- + A configured array is also reachable as an attribute when its name is a + valid Python identifier, e.g. ``combined_function_magnets.CFM`` is + equivalent to ``combined_function_magnets.get("CFM")``. Array names + appear in ``dir(combined_function_magnets)`` for interactive completion. """ def __init__(self, peer: "ElementHolder"): @@ -124,6 +160,13 @@ class SerializedMagnetsHolder(GenericArrayHolder[SerializedMagnets, SerializedMa ---------- peer : 'ElementHolder' Parent element holder that owns this specialized holder. + + Notes + ----- + A configured array is also reachable as an attribute when its name is a + valid Python identifier, e.g. ``serialized_magnets.QForTune`` is + equivalent to ``serialized_magnets.get("QForTune")``. Array names appear + in ``dir(serialized_magnets)`` for interactive completion. """ def __init__(self, peer: "ElementHolder"): @@ -165,6 +208,13 @@ class BPMsHolder(GenericArrayHolder[BPM, BPMArray]): ---------- peer : 'ElementHolder' Parent element holder that owns this specialized holder. + + Notes + ----- + A configured array is also reachable as an attribute when its name is a + valid Python identifier, e.g. ``bpms.BPMS`` is equivalent to + ``bpms.get("BPMS")``. Array names appear in ``dir(bpms)`` for interactive + completion. """ def __init__(self, peer: "ElementHolder"): diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py new file mode 100644 index 00000000..3fdcbe42 --- /dev/null +++ b/tests/common/test_array_holder_navigation.py @@ -0,0 +1,99 @@ +import pytest + +from pyaml.accelerator import Accelerator +from pyaml.arrays.cfm_magnet_array import CombinedFunctionMagnetArray + + +@pytest.fixture +def holder(accelerator_from_fragments, sr_configuration_fragments): + sr = accelerator_from_fragments(*sr_configuration_fragments) + sr.design.get_lattice().disable_6d() + return sr.design + + +@pytest.fixture +def serialized_holder(): + sr = Accelerator.load("tests/config/sr_serialized_magnets.yaml", include_locations=False, ignore_external=True) + return sr.design + + +def test_dynamic_attribute_returns_named_magnet_array(holder): + assert holder.magnets.HCORR is holder.magnets.get("HCORR") + assert holder.magnets.VCORR is holder.magnets.get("VCORR") + assert holder.magnets.HVCORR is holder.magnets.get("HVCORR") + + +def test_dynamic_attribute_returns_named_combined_function_magnet_array(holder): + assert holder.combined_function_magnets.CFM is holder.combined_function_magnets.get("CFM") + + +def test_dynamic_attribute_returns_named_bpm_array(holder): + assert holder.bpms.BPMS is holder.bpms.get("BPMS") + + +def test_dynamic_attribute_returns_named_serialized_magnet_array(serialized_holder): + assert serialized_holder.serialized_magnets.QForTune is serialized_holder.serialized_magnets.get("QForTune") + assert serialized_holder.serialized_magnets.series is serialized_holder.serialized_magnets.get("series") + + +def test_dynamic_attribute_unknown_name_raises_attribute_error(holder): + with pytest.raises(AttributeError): + _ = holder.magnets.UNKNOWN + + +def test_dynamic_attribute_does_not_shadow_existing_methods(holder): + holder.magnets._array_store["get"] = holder.magnets.get("HCORR") + holder.magnets._array_store["add"] = holder.magnets.get("HCORR") + + assert callable(holder.magnets.get) + assert callable(holder.magnets.add) + assert holder.magnets.get("HCORR").names() == ["SH1A-C01-H", "SH1A-C02-H"] + + +def test_dynamic_attribute_rejects_non_identifier_names(holder): + holder.magnets._array_store["not-an-id"] = holder.magnets.get("HCORR") + + with pytest.raises(AttributeError): + getattr(holder.magnets, "not-an-id") + + +def test_dir_includes_configured_array_names(holder): + assert {"HCORR", "VCORR", "HVCORR"} <= set(dir(holder.magnets)) + assert "CFM" in dir(holder.combined_function_magnets) + assert "BPMS" in dir(holder.bpms) + + +def test_dir_excludes_non_identifier_array_names(holder): + holder.magnets._array_store["not-an-id"] = holder.magnets.get("HCORR") + + assert "not-an-id" not in dir(holder.magnets) + + +def test_get_cfm_returns_all_combined_function_magnets(holder): + combined_function_magnets = holder.magnets.get_cfm() + + assert type(combined_function_magnets) is CombinedFunctionMagnetArray + assert combined_function_magnets.names() == holder.combined_function_magnets.get().names() + + +def test_issue_373_example(): + """Reproduce the #373 example verbatim, against real test lattice data.""" + sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True) + sr.design.get_lattice().disable_6d() + + all_magnets = sr.design.magnets[:] + quad_family = sr.design.magnets.get("QForTune") + same_quad_family = sr.design.magnets.QForTune + assert same_quad_family.names() == quad_family.names() + assert len(quad_family) == 124 + assert len(all_magnets) >= len(quad_family) + + combined_function_magnets = sr.design.magnets.get_cfm() + assert len(combined_function_magnets) == 0 + + matching_quadrupoles = sr.design.magnets["QF1*"] + assert matching_quadrupoles.names() == sr.design.magnets["QF1*"].names() + + one_magnet = sr.design.magnet.get("QF1E-C04") + one_magnet.strength.set(0.8) + assert one_magnet.strength.get() == pytest.approx(0.8) diff --git a/tests/test_load_conf_with_code.py b/tests/test_load_conf_with_code.py index de476102..e65f5be5 100644 --- a/tests/test_load_conf_with_code.py +++ b/tests/test_load_conf_with_code.py @@ -16,3 +16,5 @@ def test_load_conf_with_code(): assert sr.live["BPM*"].names() == bpms.names() assert sr.live[:].names() == [element.get_name() for element in sr.live.get_all_elements()] assert sr.design["BPM*"].names() == sr.design.bpms.get("BPM").names() + + assert sr.live.bpms.BPM is bpms From 3a8a897f8f9a82b6ac5e1a63a5421ad023dcfa0f Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Thu, 17 Sep 2026 14:58:34 +0200 Subject: [PATCH 02/16] Add a public diagnostic holder --- pyaml/common/holders/diagnostic_holder.py | 104 ++++++++++++++++++ pyaml/common/holders/element_holder.py | 9 ++ .../diagnostics/test_diagnostic_accessors.py | 60 ++++++++++ 3 files changed, 173 insertions(+) create mode 100644 pyaml/common/holders/diagnostic_holder.py create mode 100644 tests/diagnostics/test_diagnostic_accessors.py diff --git a/pyaml/common/holders/diagnostic_holder.py b/pyaml/common/holders/diagnostic_holder.py new file mode 100644 index 00000000..5fb99202 --- /dev/null +++ b/pyaml/common/holders/diagnostic_holder.py @@ -0,0 +1,104 @@ +"""Holder interface for diagnostics.""" + +from typing import TYPE_CHECKING + +from ...arrays.element_array import ElementArray +from ...diagnostics.tune_monitor import BetatronTuneMonitor +from ..element import Element, __pyaml_repr__ +from ..exception import PyAMLException + +if TYPE_CHECKING: + from .element_holder import ElementHolder + + +class DiagnosticHolder: + """ + Provide access to diagnostics. + + Parameters + ---------- + peer : 'ElementHolder' + Parent holder containing the diagnostic store. + + Attributes + ---------- + betatron_tune + Betatron tune monitor configured as ``BETATRON_TUNE``, the default, validated + against its expected class. + + Methods + ------- + get(name=None) + Return a named diagnostic, or all configured diagnostics when no name is given. + + Notes + ----- + :meth:`ElementHolder.get_betatron_tune_monitor + ` stays + available as the named, untyped lookup. This holder adds the default-name, + type-validated convenience property. + + Examples + -------- + >>> default_tune_monitor = sr.live.diagnostic.betatron_tune + >>> measured_tune = default_tune_monitor.tune.get() + >>> spare_tune_monitor = sr.live.diagnostic.get("SPARE_BETATRON_TUNE_MONITOR") + >>> all_diagnostics = sr.live.diagnostic.get() + """ + + def __init__(self, peer: "ElementHolder"): + """ + Initialize a diagnostic holder for an element holder. + """ + self._peer = peer + + def get(self, name: str = None) -> "Element | ElementArray": + """ + Return a named diagnostic, or all configured diagnostics when no name is given. + + Parameters + ---------- + name : str, optional + Name of the diagnostic to look up, as declared in the configuration. When + omitted, every configured diagnostic is returned instead. + + Returns + ------- + Element or ElementArray + The diagnostic registered under ``name``, or an + :class:`~pyaml.arrays.element_array.ElementArray` holding every configured + diagnostic, in insertion order, when ``name`` is omitted. + + Raises + ------ + PyAMLException + If ``name`` is given and no diagnostic is registered under it. + """ + if name is None: + return ElementArray("", list(self._peer._DIAG.values())) + return self._peer._get_diagnostic(name) + + @property + def betatron_tune(self) -> BetatronTuneMonitor: + """ + Return the betatron tune monitor configured as ``BETATRON_TUNE``. + + Returns + ------- + BetatronTuneMonitor + Betatron tune monitor registered under ``BETATRON_TUNE``. + + Raises + ------ + PyAMLException + If no diagnostic is registered under ``BETATRON_TUNE``, or if it is not a + :class:`~pyaml.diagnostics.tune_monitor.BetatronTuneMonitor`. + """ + name = "BETATRON_TUNE" + obj = self._peer.get_betatron_tune_monitor(name) + if not isinstance(obj, BetatronTuneMonitor): + raise PyAMLException(f"{name}: BetatronTuneMonitor expected but got {type(obj).__name__}") + return obj + + def __repr__(self): + return __pyaml_repr__(self) diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index aa2b16dc..cd7d5e0f 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -17,6 +17,7 @@ from ..abstract_aggregator import ScalarAggregator from ..element import Element from ..exception import PyAMLException +from .diagnostic_holder import DiagnosticHolder from .rf_holder import RFHolder from .sub_holders import ( BPMHolder, @@ -65,6 +66,8 @@ class ElementHolder(metaclass=ABCMeta): Single serialized magnet group by name, or a named array. rf RF plant and transmitters of this mode. + diagnostic + Diagnostics of this mode, with typed default-name access. tune, chromaticity, orbit, dispersion Tuning tools attached to this mode, looked up by name. trm, crm, orm @@ -159,6 +162,7 @@ def __init__(self): self._bpm_holder = BPMHolder(self) self._bpms_holder = BPMsHolder(self) self._rf_holder = RFHolder(self) + self._diagnostic_holder = DiagnosticHolder(self) @property def peer(self) -> "Accelerator": @@ -212,6 +216,11 @@ def rf(self) -> RFHolder: """Return the rf.""" return self._rf_holder + @property + def diagnostic(self) -> DiagnosticHolder: + """Return the diagnostic.""" + return self._diagnostic_holder + def post_init(self): """Run post-initialization hooks for every stored element.""" for e in self.get_all_elements(): diff --git a/tests/diagnostics/test_diagnostic_accessors.py b/tests/diagnostics/test_diagnostic_accessors.py new file mode 100644 index 00000000..7e878914 --- /dev/null +++ b/tests/diagnostics/test_diagnostic_accessors.py @@ -0,0 +1,60 @@ +import pytest + +from pyaml.accelerator import Accelerator +from pyaml.common.exception import PyAMLException +from pyaml.lattice.simulator import Simulator + + +def test_diagnostic_get_returns_named_monitor(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + assert design.diagnostic.get("BETATRON_TUNE") is design.get_betatron_tune_monitor("BETATRON_TUNE") + + +def test_diagnostic_get_with_no_name_returns_all_configured_diagnostics(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + all_diagnostics = design.diagnostic.get() + assert design.get_betatron_tune_monitor("BETATRON_TUNE") in all_diagnostics + + +def test_diagnostic_betatron_tune_returns_default_monitor(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + assert design.diagnostic.betatron_tune is design.get_betatron_tune_monitor("BETATRON_TUNE") + + +def test_diagnostic_raises_when_default_missing(ebs_lattice_file): + holder = Simulator(name="empty", lattice=str(ebs_lattice_file)) + + with pytest.raises(PyAMLException) as exc: + _ = holder.diagnostic.betatron_tune + assert "BETATRON_TUNE" in str(exc.value) + + +def test_diagnostic_raises_when_default_wrong_type(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + # Swap the registered default so it points to an object of the wrong type. + design._DIAG["BETATRON_TUNE"] = design.orbit + + with pytest.raises(PyAMLException) as exc: + _ = design.diagnostic.betatron_tune + assert "BETATRON_TUNE" in str(exc.value) + assert "BetatronTuneMonitor" in str(exc.value) From 5a7fea8060304a7f14eab3b40d482a6eec765147 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Thu, 17 Sep 2026 13:40:30 +0200 Subject: [PATCH 03/16] Add a public tuning and measurement tool holder --- pyaml/common/holders/element_holder.py | 42 +++--- pyaml/common/holders/tool_holder.py | 159 ++++++++++++++++++++++ tests/tuning_tools/test_tool_accessors.py | 72 ++++++++++ 3 files changed, 257 insertions(+), 16 deletions(-) create mode 100644 pyaml/common/holders/tool_holder.py diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index cd7d5e0f..934dfd41 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -29,6 +29,7 @@ SerializedMagnetHolder, SerializedMagnetsHolder, ) +from .tool_holder import ToolHolder if TYPE_CHECKING: from ...accelerator import Accelerator @@ -68,10 +69,13 @@ class ElementHolder(metaclass=ABCMeta): RF plant and transmitters of this mode. diagnostic Diagnostics of this mode, with typed default-name access. + tool + Tuning and measurement tools of this mode, with typed default-name access. tune, chromaticity, orbit, dispersion - Tuning tools attached to this mode, looked up by name. + Backward-compatible aliases for ``tool.tune``, ``tool.chromaticity``, ``tool.orbit`` + and ``tool.dispersion``. trm, crm, orm - Response-matrix measurement tools, looked up by name. + Backward-compatible aliases for ``tool.trm``, ``tool.crm`` and ``tool.orm``. Methods ------- @@ -163,6 +167,7 @@ def __init__(self): self._bpms_holder = BPMsHolder(self) self._rf_holder = RFHolder(self) self._diagnostic_holder = DiagnosticHolder(self) + self._tool_holder = ToolHolder(self) @property def peer(self) -> "Accelerator": @@ -221,6 +226,11 @@ def diagnostic(self) -> DiagnosticHolder: """Return the diagnostic.""" return self._diagnostic_holder + @property + def tool(self) -> ToolHolder: + """Return the tool.""" + return self._tool_holder + def post_init(self): """Run post-initialization hooks for every stored element.""" for e in self.get_all_elements(): @@ -678,13 +688,13 @@ def get_crm_tuning(self, name: str) -> "ChromaticityResponseMatrix": @property def chromaticity(self) -> "Chromaticity": - """Return the chromaticity.""" - return self.get_chromaticity_tuning("DEFAULT_CHROMATICITY_CORRECTION") + """Return the chromaticity. Alias for ``tool.chromaticity``.""" + return self.tool.chromaticity @property def crm(self) -> "ChromaticityResponseMatrix": - """Return the crm.""" - return self.get_crm_tuning("DEFAULT_CHROMATICITY_RESPONSE_MATRIX") + """Return the crm. Alias for ``tool.crm``.""" + return self.tool.crm # ---- Tune --------------------------------------------------------- @@ -706,8 +716,8 @@ def get_tune_tuning(self, name: str) -> "Tune": @property def tune(self) -> "Tune": - """Return the tune.""" - return self.get_tune_tuning("DEFAULT_TUNE_CORRECTION") + """Return the tune. Alias for ``tool.tune``.""" + return self.tool.tune def get_trm_tuning(self, name: str) -> "TuneResponseMatrix": """ @@ -727,8 +737,8 @@ def get_trm_tuning(self, name: str) -> "TuneResponseMatrix": @property def trm(self) -> "TuneResponseMatrix": - """Return the default tune response-matrix tool.""" - return self.get_trm_tuning("DEFAULT_TUNE_RESPONSE_MATRIX") + """Return the default tune response-matrix tool. Alias for ``tool.trm``.""" + return self.tool.trm # ---- Orbit -------------------------------------------------------- @@ -750,8 +760,8 @@ def get_orbit_tuning(self, name: str) -> "Orbit": @property def orbit(self) -> "Orbit": - """Return the orbit.""" - return self.get_orbit_tuning("DEFAULT_ORBIT_CORRECTION") + """Return the orbit. Alias for ``tool.orbit``.""" + return self.tool.orbit def get_orm_tuning(self, name: str) -> "OrbitResponseMatrix": """ @@ -771,8 +781,8 @@ def get_orm_tuning(self, name: str) -> "OrbitResponseMatrix": @property def orm(self) -> "OrbitResponseMatrix": - """Return the default orbit response-matrix tool.""" - return self.get_orm_tuning("DEFAULT_ORBIT_RESPONSE_MATRIX") + """Return the default orbit response-matrix tool. Alias for ``tool.orm``.""" + return self.tool.orm # ---- BBA -------------------------------------------------------- @@ -812,8 +822,8 @@ def get_dispersion_tuning(self, name: str) -> "Dispersion": @property def dispersion(self) -> "Dispersion": - """Return the dispersion.""" - return self.get_dispersion_tuning("DEFAULT_DISPERSION") + """Return the dispersion. Alias for ``tool.dispersion``.""" + return self.tool.dispersion def _get_array(self, name: str): """ diff --git a/pyaml/common/holders/tool_holder.py b/pyaml/common/holders/tool_holder.py new file mode 100644 index 00000000..be7d17a0 --- /dev/null +++ b/pyaml/common/holders/tool_holder.py @@ -0,0 +1,159 @@ +"""Holder interface for tuning and measurement tools.""" + +from typing import TYPE_CHECKING + +from ...arrays.element_array import ElementArray +from ..element import Element, __pyaml_repr__ +from ..exception import PyAMLException + +if TYPE_CHECKING: + from ...tuning_tools.chromaticity import Chromaticity + from ...tuning_tools.chromaticity_response_matrix import ChromaticityResponseMatrix + from ...tuning_tools.dispersion import Dispersion + from ...tuning_tools.orbit import Orbit + from ...tuning_tools.orbit_response_matrix import OrbitResponseMatrix + from ...tuning_tools.tune import Tune + from ...tuning_tools.tune_response_matrix import TuneResponseMatrix + from .element_holder import ElementHolder + + +class ToolHolder: + """ + Provide access to tuning and measurement tools. + + Parameters + ---------- + peer : 'ElementHolder' + Parent holder containing the tool store. + + Attributes + ---------- + tune, chromaticity, orbit, dispersion + Default tuning tool for each kind, resolved from its ``DEFAULT_...`` name and + validated against the expected class. + trm, crm, orm + Default response-matrix measurement tool for each kind, resolved the same way. + + Methods + ------- + get(name=None) + Return a named tool, or all configured tools when no name is given. + + Notes + ----- + :attr:`ElementHolder.tune `, + ``.trm``, ``.orbit``, ``.orm``, ``.chromaticity``, ``.crm`` and ``.dispersion`` are + backward-compatible aliases for the corresponding properties here. + + Examples + -------- + >>> tune_correction = sr.live.tool.tune + >>> tune_correction.set([0.31, 0.22]) + >>> tune_response = sr.live.tool.trm + >>> tune_response.measure() + >>> other_tool = sr.live.tool.get("OTHER_TUNE_CORRECTION") + >>> all_tools = sr.live.tool.get() + """ + + def __init__(self, peer: "ElementHolder"): + """ + Initialize a tool holder for an element holder. + """ + self._peer = peer + + def get(self, name: str = None) -> "Element | ElementArray": + """ + Return a named tool, or all configured tools when no name is given. + + Parameters + ---------- + name : str, optional + Name of the tuning or measurement tool to look up, as declared in the + configuration. When omitted, every configured tool is returned instead. + + Returns + ------- + Element or ElementArray + The tool registered under ``name``, or an :class:`~pyaml.arrays.element_array.ElementArray` + holding every configured tool, in insertion order, when ``name`` is omitted. + + Raises + ------ + PyAMLException + If ``name`` is given and no tool is registered under it. + """ + if name is None: + return ElementArray("", list(self._peer._TOOLS.values())) + return self._peer._get_tool(name) + + def _validate_type(self, name: str, obj: Element, expected_type: type) -> Element: + """ + Ensure a resolved default tool matches the type its accessor expects. + + Raises + ------ + PyAMLException + If ``obj`` is not an instance of ``expected_type``. + """ + if not isinstance(obj, expected_type): + raise PyAMLException(f"{name}: {expected_type.__name__} expected but got {type(obj).__name__}") + return obj + + @property + def chromaticity(self) -> "Chromaticity": + """Return the chromaticity tuning tool configured as ``DEFAULT_CHROMATICITY_CORRECTION``.""" + from ...tuning_tools.chromaticity import Chromaticity + + name = "DEFAULT_CHROMATICITY_CORRECTION" + return self._validate_type(name, self._peer.get_chromaticity_tuning(name), Chromaticity) + + @property + def crm(self) -> "ChromaticityResponseMatrix": + """Return the chromaticity response-matrix tool configured as ``DEFAULT_CHROMATICITY_RESPONSE_MATRIX``.""" + from ...tuning_tools.chromaticity_response_matrix import ChromaticityResponseMatrix + + name = "DEFAULT_CHROMATICITY_RESPONSE_MATRIX" + return self._validate_type(name, self._peer.get_crm_tuning(name), ChromaticityResponseMatrix) + + @property + def tune(self) -> "Tune": + """Return the tune correction tool configured as ``DEFAULT_TUNE_CORRECTION``.""" + from ...tuning_tools.tune import Tune + + name = "DEFAULT_TUNE_CORRECTION" + return self._validate_type(name, self._peer.get_tune_tuning(name), Tune) + + @property + def trm(self) -> "TuneResponseMatrix": + """Return the tune response-matrix tool configured as ``DEFAULT_TUNE_RESPONSE_MATRIX``.""" + from ...tuning_tools.tune_response_matrix import TuneResponseMatrix + + name = "DEFAULT_TUNE_RESPONSE_MATRIX" + return self._validate_type(name, self._peer.get_trm_tuning(name), TuneResponseMatrix) + + @property + def orbit(self) -> "Orbit": + """Return the orbit correction tool configured as ``DEFAULT_ORBIT_CORRECTION``.""" + from ...tuning_tools.orbit import Orbit + + name = "DEFAULT_ORBIT_CORRECTION" + return self._validate_type(name, self._peer.get_orbit_tuning(name), Orbit) + + @property + def orm(self) -> "OrbitResponseMatrix": + """Return the orbit response-matrix tool configured as ``DEFAULT_ORBIT_RESPONSE_MATRIX``.""" + from ...tuning_tools.orbit_response_matrix import OrbitResponseMatrix + + name = "DEFAULT_ORBIT_RESPONSE_MATRIX" + return self._validate_type(name, self._peer.get_orm_tuning(name), OrbitResponseMatrix) + + @property + def dispersion(self) -> "Dispersion": + """Return the dispersion tool configured as ``DEFAULT_DISPERSION``.""" + from ...tuning_tools.dispersion import Dispersion + + name = "DEFAULT_DISPERSION" + return self._validate_type(name, self._peer.get_dispersion_tuning(name), Dispersion) + + def __repr__(self): + return __pyaml_repr__(self) diff --git a/tests/tuning_tools/test_tool_accessors.py b/tests/tuning_tools/test_tool_accessors.py index 1ccbf5df..a3dcef13 100644 --- a/tests/tuning_tools/test_tool_accessors.py +++ b/tests/tuning_tools/test_tool_accessors.py @@ -1,4 +1,8 @@ +import pytest + from pyaml.accelerator import Accelerator +from pyaml.common.exception import PyAMLException +from pyaml.lattice.simulator import Simulator def test_tuning_tools_expose_configured_elements(): @@ -51,3 +55,71 @@ def test_tuning_tools_expose_configured_elements(): assert bba.quadrupole is design.magnet.get("QF6B-C04") assert design.get_bba("BBA2-BPM_C04-04").tune_correction is design.tune + + +def test_tool_get_returns_named_tool(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + assert design.tool.get("DEFAULT_TUNE_CORRECTION") is design.tune + assert design.tool.get("DEFAULT_ORBIT_RESPONSE_MATRIX") is design.orm + + +def test_tool_get_with_no_name_returns_all_configured_tools(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + all_tools = design.tool.get() + assert design.tune in all_tools + assert design.trm in all_tools + assert design.orbit in all_tools + assert design.orm in all_tools + assert design.chromaticity in all_tools + assert design.crm in all_tools + assert design.dispersion in all_tools + + +def test_tool_typed_properties_alias_existing_defaults(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + assert design.tool.tune is design.tune + assert design.tool.trm is design.trm + assert design.tool.orbit is design.orbit + assert design.tool.orm is design.orm + assert design.tool.chromaticity is design.chromaticity + assert design.tool.crm is design.crm + assert design.tool.dispersion is design.dispersion + + +def test_tool_raises_when_default_missing(ebs_lattice_file): + holder = Simulator(name="empty", lattice=str(ebs_lattice_file)) + + with pytest.raises(PyAMLException) as exc: + _ = holder.tool.tune + assert "DEFAULT_TUNE_CORRECTION" in str(exc.value) + + +def test_tool_raises_when_default_wrong_type(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + # Swap the registered default so it points to an object of the wrong type. + design._TOOLS["DEFAULT_TUNE_CORRECTION"] = design.orbit + + with pytest.raises(PyAMLException) as exc: + _ = design.tool.tune + assert "DEFAULT_TUNE_CORRECTION" in str(exc.value) + assert "Tune" in str(exc.value) From 86928b2d08f6c7381552cd7f3f2d9be513738f3b Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Fri, 18 Sep 2026 09:41:48 +0200 Subject: [PATCH 04/16] Move BPM holders under DiagnosticHolder --- .../ControlSystem/tango/main.py | 2 +- examples/use_cases/03-orbit_correction.ipynb | 19 +++------------ examples/use_cases/03-orbit_correction.py | 2 +- pyaml/arrays/bpm.py | 2 +- pyaml/common/holders/diagnostic_holder.py | 17 +++++++++++++ pyaml/common/holders/element_holder.py | 16 ------------- pyaml/common/holders/sub_holders.py | 5 ++-- pyaml/control/controlsystem.py | 2 +- pyaml/external/pySC_interface.py | 2 +- pyaml/lattice/simulator.py | 4 +++- pyaml/tuning_tools/bba.py | 4 ++-- pyaml/tuning_tools/bba2.py | 6 ++--- pyaml/tuning_tools/chromaticity_monitor.py | 2 +- pyaml/tuning_tools/dispersion.py | 2 +- pyaml/tuning_tools/orbit.py | 2 +- pyaml/tuning_tools/orbit_response_matrix.py | 2 +- tests/arrays/test_arrays.py | 24 +++++++++---------- tests/bpm/test_bpm.py | 14 +++++------ tests/bpm/test_bpm_controlsystem.py | 10 ++++---- tests/common/test_array_holder_navigation.py | 4 ++-- .../common/test_element_holder_collection.py | 6 ++--- tests/common/test_errors.py | 2 +- .../diagnostics/test_diagnostic_accessors.py | 21 ++++++++++++++++ tests/integration/test_dt4acc_twin_smoke.py | 2 +- tests/test_accelerator_load.py | 6 ++--- tests/test_catalogs.py | 4 ++-- tests/test_load_conf_with_code.py | 6 ++--- tests/tuning_tools/test_bba.py | 2 +- tests/tuning_tools/test_tool_accessors.py | 4 ++-- tests/tuning_tools/test_tuning_dispersion.py | 2 +- .../test_tuning_orbit_correction.py | 2 +- tests/tuning_tools/test_tuning_orm.py | 2 +- 32 files changed, 106 insertions(+), 94 deletions(-) diff --git a/examples/other_examples/ControlSystem/tango/main.py b/examples/other_examples/ControlSystem/tango/main.py index 8fe0782b..4a21dc35 100644 --- a/examples/other_examples/ControlSystem/tango/main.py +++ b/examples/other_examples/ControlSystem/tango/main.py @@ -3,7 +3,7 @@ sr = Accelerator.load("config.yaml") # print the BPM position -bpm = sr.live.bpm.get("BPM_C01-01") # bpm is a BPM +bpm = sr.live.diagnostic.bpm.get("BPM_C01-01") # bpm is a BPM print(bpm.positions.get()) # Direct access to control system diff --git a/examples/use_cases/03-orbit_correction.ipynb b/examples/use_cases/03-orbit_correction.ipynb index e476b7a0..58cad3cc 100644 --- a/examples/use_cases/03-orbit_correction.ipynb +++ b/examples/use_cases/03-orbit_correction.ipynb @@ -185,24 +185,11 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "6adb7436", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "BPMs: 320, H correctors: 288, V correctors: 288\n" - ] - } - ], - "source": [ - "bpms = SR.bpms.get(\"BPM\")\n", - "hcorr = SR.magnets.get(\"HCorr\")\n", - "vcorr = SR.magnets.get(\"VCorr\")\n", - "print(f\"BPMs: {len(bpms)}, H correctors: {len(hcorr)}, V correctors: {len(vcorr)}\")" - ] + "outputs": [], + "source": "bpms = SR.diagnostic.bpms.get(\"BPM\")\nhcorr = SR.magnets.get(\"HCorr\")\nvcorr = SR.magnets.get(\"VCorr\")\nprint(f\"BPMs: {len(bpms)}, H correctors: {len(hcorr)}, V correctors: {len(vcorr)}\")" }, { "cell_type": "markdown", diff --git a/examples/use_cases/03-orbit_correction.py b/examples/use_cases/03-orbit_correction.py index ceef8ec1..b7af039c 100644 --- a/examples/use_cases/03-orbit_correction.py +++ b/examples/use_cases/03-orbit_correction.py @@ -84,7 +84,7 @@ # In[4]: -bpms = SR.bpms.get("BPM") +bpms = SR.diagnostic.bpms.get("BPM") hcorr = SR.magnets.get("HCorr") vcorr = SR.magnets.get("VCorr") print(f"BPMs: {len(bpms)}, H correctors: {len(hcorr)}, V correctors: {len(vcorr)}") diff --git a/pyaml/arrays/bpm.py b/pyaml/arrays/bpm.py index 4ea84927..dd9d2996 100644 --- a/pyaml/arrays/bpm.py +++ b/pyaml/arrays/bpm.py @@ -88,4 +88,4 @@ def fill_array(self, holder: ElementHolder): holder : ElementHolder The element holder to populate the :py:class:`.BPMArray` with. """ - holder.bpms.add(self._name, self._elements) + holder.diagnostic.bpms.add(self._name, self._elements) diff --git a/pyaml/common/holders/diagnostic_holder.py b/pyaml/common/holders/diagnostic_holder.py index 5fb99202..361a06ed 100644 --- a/pyaml/common/holders/diagnostic_holder.py +++ b/pyaml/common/holders/diagnostic_holder.py @@ -6,6 +6,7 @@ from ...diagnostics.tune_monitor import BetatronTuneMonitor from ..element import Element, __pyaml_repr__ from ..exception import PyAMLException +from .sub_holders import BPMHolder, BPMsHolder if TYPE_CHECKING: from .element_holder import ElementHolder @@ -22,6 +23,8 @@ class DiagnosticHolder: Attributes ---------- + bpm, bpms + Single BPM by name, or a named BPM array. betatron_tune Betatron tune monitor configured as ``BETATRON_TUNE``, the default, validated against its expected class. @@ -44,6 +47,8 @@ class DiagnosticHolder: >>> measured_tune = default_tune_monitor.tune.get() >>> spare_tune_monitor = sr.live.diagnostic.get("SPARE_BETATRON_TUNE_MONITOR") >>> all_diagnostics = sr.live.diagnostic.get() + >>> bpm = sr.live.diagnostic.bpm.get("BPM01") + >>> bpms = sr.live.diagnostic.bpms.get("BPMS") """ def __init__(self, peer: "ElementHolder"): @@ -51,6 +56,18 @@ def __init__(self, peer: "ElementHolder"): Initialize a diagnostic holder for an element holder. """ self._peer = peer + self._bpm_holder = BPMHolder(peer) + self._bpms_holder = BPMsHolder(peer) + + @property + def bpm(self) -> BPMHolder: + """Return the bpm.""" + return self._bpm_holder + + @property + def bpms(self) -> BPMsHolder: + """Return the bpms.""" + return self._bpms_holder def get(self, name: str = None) -> "Element | ElementArray": """ diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 934dfd41..5b97734a 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -20,8 +20,6 @@ from .diagnostic_holder import DiagnosticHolder from .rf_holder import RFHolder from .sub_holders import ( - BPMHolder, - BPMsHolder, CombinedFunctionMagnetHolder, CombinedFunctionMagnetsHolder, MagnetHolder, @@ -59,8 +57,6 @@ class ElementHolder(metaclass=ABCMeta): ---------- magnet, magnets Single magnet by name, or a named magnet array. - bpm, bpms - Single BPM by name, or a named BPM array. combined_function_magnet, combined_function_magnets Single combined-function magnet by name, or a named array. serialized_magnet, serialized_magnets @@ -163,8 +159,6 @@ def __init__(self): self._serialized_magnets_holder = SerializedMagnetsHolder(self) self._combined_function_magnet_holder = CombinedFunctionMagnetHolder(self) self._combined_function_magnets_holder = CombinedFunctionMagnetsHolder(self) - self._bpm_holder = BPMHolder(self) - self._bpms_holder = BPMsHolder(self) self._rf_holder = RFHolder(self) self._diagnostic_holder = DiagnosticHolder(self) self._tool_holder = ToolHolder(self) @@ -206,16 +200,6 @@ def combined_function_magnets(self) -> CombinedFunctionMagnetsHolder: """Return the combined function magnets.""" return self._combined_function_magnets_holder - @property - def bpm(self) -> BPMHolder: - """Return the bpm.""" - return self._bpm_holder - - @property - def bpms(self) -> BPMsHolder: - """Return the bpms.""" - return self._bpms_holder - @property def rf(self) -> RFHolder: """Return the rf.""" diff --git a/pyaml/common/holders/sub_holders.py b/pyaml/common/holders/sub_holders.py index d61088ba..f5e36b92 100644 --- a/pyaml/common/holders/sub_holders.py +++ b/pyaml/common/holders/sub_holders.py @@ -221,11 +221,12 @@ def __init__(self, peer: "ElementHolder"): """ Initialize the BPMsHolder. """ + bpm_holder = BPMHolder(peer) super().__init__( peer, peer._BPM_ARRAYS, - peer.bpm.all, - peer.bpm.get, + bpm_holder.all, + bpm_holder.get, BPMArray, "BPM array", ) diff --git a/pyaml/control/controlsystem.py b/pyaml/control/controlsystem.py index 9199f98d..d2e25470 100644 --- a/pyaml/control/controlsystem.py +++ b/pyaml/control/controlsystem.py @@ -248,7 +248,7 @@ def _fill_bpm(self, bpm: BPM) -> None: positions = RBpmArray(position_devices[0], position_devices[1]) tilt = RWBpmTiltScalar(tilt_devices[0]) offsets = RWBpmOffsetArray(offset_devices[0], offset_devices[1]) - self.bpm.add(bpm.attach(self, positions, offsets, tilt)) + self.diagnostic.bpm.add(bpm.attach(self, positions, offsets, tilt)) def _fill_rf_plant(self, rf_plant: RFPlant) -> None: attached_transmitters: list[RFTransmitter] = [] diff --git a/pyaml/external/pySC_interface.py b/pyaml/external/pySC_interface.py index 3be5196e..b9e60493 100644 --- a/pyaml/external/pySC_interface.py +++ b/pyaml/external/pySC_interface.py @@ -56,7 +56,7 @@ def __init__( """ self.element_holder = element_holder - self.bpm_array = element_holder.bpms.get(bpm_array_name) + self.bpm_array = element_holder.diagnostic.bpms.get(bpm_array_name) self.rf_plant_name = rf_plant_name if rf_plant_name is not None: diff --git a/pyaml/lattice/simulator.py b/pyaml/lattice/simulator.py index 10bd537f..14903724 100644 --- a/pyaml/lattice/simulator.py +++ b/pyaml/lattice/simulator.py @@ -291,7 +291,9 @@ def _fill_bpm(self, bpm: BPM) -> None: if len(bpm_elt.Offset) != 2: raise PyAMLException(f"BPM {bpm.get_name()} offset must be a 2-element array.") update_bpm_transform_matrix(bpm_elt) - self.bpm.add(bpm.attach(self, RBpmArray(bpm_elt, self.ring), RWBpmOffsetArray(bpm_elt), RWBpmTiltScalar(bpm_elt))) + self.diagnostic.bpm.add( + bpm.attach(self, RBpmArray(bpm_elt, self.ring), RWBpmOffsetArray(bpm_elt), RWBpmTiltScalar(bpm_elt)) + ) def _fill_rf_plant(self, rf_plant: RFPlant) -> None: if rf_plant.transmitters: diff --git a/pyaml/tuning_tools/bba.py b/pyaml/tuning_tools/bba.py index 10dd6cdb..d5cc32df 100644 --- a/pyaml/tuning_tools/bba.py +++ b/pyaml/tuning_tools/bba.py @@ -163,13 +163,13 @@ def __init__( def bpms(self) -> "BPMArray": """Return the BPM array used for the measurement.""" self.check_peer() - return self.peer.bpms.get(self.bpm_array_name) + return self.peer.diagnostic.bpms.get(self.bpm_array_name) @property def bpm(self) -> "BPM": """Return the reference BPM used for the alignment.""" self.check_peer() - return self.peer.bpm.get(self.bpm_name) + return self.peer.diagnostic.bpm.get(self.bpm_name) @property def hcorrector(self) -> "Magnet": diff --git a/pyaml/tuning_tools/bba2.py b/pyaml/tuning_tools/bba2.py index 25424a0c..05544687 100644 --- a/pyaml/tuning_tools/bba2.py +++ b/pyaml/tuning_tools/bba2.py @@ -244,13 +244,13 @@ def __init__( def bpms(self) -> "BPMArray": """Return the BPM array used for the measurement.""" self.check_peer() - return self.peer.bpms.get(self.bpm_array_name) + return self.peer.diagnostic.bpms.get(self.bpm_array_name) @property def bpm(self) -> "BPM": """Return the reference BPM used for the alignment.""" self.check_peer() - return self.peer.bpm.get(self.bpm_name) + return self.peer.diagnostic.bpm.get(self.bpm_name) @property def hcorrector(self) -> "Magnet": @@ -359,7 +359,7 @@ def _init_responses( quad = design.magnet.get(quadname) sth = design.magnet.get(steererhname) stv = design.magnet.get(steerervname) - orbit = design.bpms.get(bpmname).positions + orbit = design.diagnostic.bpms.get(bpmname).positions tune_design = design.get_tune_tuning(tunename) tune_live = self._peer.get_tune_tuning(tunename) diff --git a/pyaml/tuning_tools/chromaticity_monitor.py b/pyaml/tuning_tools/chromaticity_monitor.py index 0f0ad6e6..f9bfa525 100644 --- a/pyaml/tuning_tools/chromaticity_monitor.py +++ b/pyaml/tuning_tools/chromaticity_monitor.py @@ -215,7 +215,7 @@ def bpms(self) -> "BPMArray | None": self.check_peer() if self.bpm_array_name is None: return None - return self.peer.bpms.get(self.bpm_array_name) + return self.peer.diagnostic.bpms.get(self.bpm_array_name) @property def chromaticity(self) -> ReadFloatArray: diff --git a/pyaml/tuning_tools/dispersion.py b/pyaml/tuning_tools/dispersion.py index e8f8f07d..81fccb11 100644 --- a/pyaml/tuning_tools/dispersion.py +++ b/pyaml/tuning_tools/dispersion.py @@ -91,7 +91,7 @@ def __init__(self, name: str, bpm_array_name: str, rf_plant_name: str, frequency def bpms(self) -> "BPMArray": """Return the BPM array used for orbit readback.""" self.check_peer() - return self.peer.bpms.get(self.bpm_array_name) + return self.peer.diagnostic.bpms.get(self.bpm_array_name) @property def rf_plant(self) -> "RFPlant": diff --git a/pyaml/tuning_tools/orbit.py b/pyaml/tuning_tools/orbit.py index feb9713c..61468323 100644 --- a/pyaml/tuning_tools/orbit.py +++ b/pyaml/tuning_tools/orbit.py @@ -212,7 +212,7 @@ def response_matrix(self) -> OrbitResponseMatrixData | None: def bpms(self) -> BPMArray: """Return the BPM array used for orbit readback.""" self.check_peer() - return self.peer.bpms.get(self.bpm_array_name) + return self.peer.diagnostic.bpms.get(self.bpm_array_name) @property def hcorrectors(self) -> MagnetArray: diff --git a/pyaml/tuning_tools/orbit_response_matrix.py b/pyaml/tuning_tools/orbit_response_matrix.py index 7d4964cc..101a7220 100644 --- a/pyaml/tuning_tools/orbit_response_matrix.py +++ b/pyaml/tuning_tools/orbit_response_matrix.py @@ -141,7 +141,7 @@ def __init__( def bpms(self) -> "BPMArray": """Return the BPM array used for orbit readback.""" self.check_peer() - return self.peer.bpms.get(self.bpm_array_name) + return self.peer.diagnostic.bpms.get(self.bpm_array_name) @property def hcorrectors(self) -> "MagnetArray": diff --git a/tests/arrays/test_arrays.py b/tests/arrays/test_arrays.py index 7ae9b871..62f9c202 100644 --- a/tests/arrays/test_arrays.py +++ b/tests/arrays/test_arrays.py @@ -128,32 +128,32 @@ def test_arrays(install_test_package): # Test BPMs array # Using aggregator - pos = sr.design.bpms.get("BPMS").positions.get() + pos = sr.design.diagnostic.bpms.get("BPMS").positions.get() assert np.abs(pos[0][0] - 7.22262850488348e-05) < 1e-10 assert np.abs(pos[0][1] - 3.4291613955705856e-05) < 1e-10 assert np.abs(pos[1][0] + 1.1696152238807462e-04) < 1e-10 assert np.abs(pos[1][1] - 7.4265634524358045e-06) < 1e-10 # Using aggregator (h and v) - pos_h = sr.design.bpms.get("BPMS").h.get() - pos_v = sr.design.bpms.get("BPMS").v.get() + pos_h = sr.design.diagnostic.bpms.get("BPMS").h.get() + pos_v = sr.design.diagnostic.bpms.get("BPMS").v.get() assert np.all(np.isclose(pos[:, 0], pos_h, rtol=1e-15, atol=1e-15)) assert np.all(np.isclose(pos[:, 1], pos_v, rtol=1e-15, atol=1e-15)) # Test BPM transformation matrices - sr.design.bpm.get("BPM_C04-01").offset.set([0.1, 0.2]) - sr.design.bpm.get("BPM_C04-02").offset.set([0.3, 0.4]) - pos = sr.design.bpms.get("BPMS").positions.get() + sr.design.diagnostic.bpm.get("BPM_C04-01").offset.set([0.1, 0.2]) + sr.design.diagnostic.bpm.get("BPM_C04-02").offset.set([0.3, 0.4]) + pos = sr.design.diagnostic.bpms.get("BPMS").positions.get() assert np.abs(pos[0][0] - 7.22262850488348e-05 - 0.1) < 1e-10 assert np.abs(pos[0][1] - 3.4291613955705856e-05 - 0.2) < 1e-10 assert np.abs(pos[1][0] + 1.1696152238807462e-04 - 0.3) < 1e-10 assert np.abs(pos[1][1] - 7.4265634524358045e-06 - 0.4) < 1e-10 - sr.design.bpm.get("BPM_C04-01").offset.set([0.0, 0.0]) - sr.design.bpm.get("BPM_C04-02").offset.set([0.0, 0.0]) + sr.design.diagnostic.bpm.get("BPM_C04-01").offset.set([0.0, 0.0]) + sr.design.diagnostic.bpm.get("BPM_C04-02").offset.set([0.0, 0.0]) # No aggregator bpms = [] - for b in sr.design.bpms.get("BPMS"): + for b in sr.design.diagnostic.bpms.get("BPMS"): bpms.append(b) bpms = BPMArray("BPM_noagg", bpms, use_aggregator=False) @@ -175,7 +175,7 @@ def test_arrays(install_test_package): assert len(allMags) == 7 # Create an array that contains all BPM - allBpms = BPMArray("AllBPMs", sr.design.bpm.all()) + allBpms = BPMArray("AllBPMs", sr.design.diagnostic.bpm.all()) assert len(allBpms) == 2 cfm = sr.design.combined_function_magnets.get("CFM") @@ -204,7 +204,7 @@ def test_arrays(install_test_package): assert np.abs(strHVSQ[4] + 0.000017) < 1e-10 # V assert np.abs(strHVSQ[5] - 1e-6) < 1e-10 # SQ - bpmsLive = BPMArray("", sr.live.bpm.all()) + bpmsLive = BPMArray("", sr.live.diagnostic.bpm.all()) bpmsLive.positions.get() # Test dynamic arrays @@ -232,7 +232,7 @@ def test_arrays(install_test_package): emptyBPM = BPM(name="emptyBPM", elements=[]) emptyBPM.fill_array(sr.design) # Attach the array - v = sr.design.bpms.get("emptyBPM").positions.get() # Ensure good attach + v = sr.design.diagnostic.bpms.get("emptyBPM").positions.get() # Ensure good attach assert np.shape(v) == (0,) emptyCFM = CombinedFunctionMagnet(name="emptyCFM", elements=[]) diff --git a/tests/bpm/test_bpm.py b/tests/bpm/test_bpm.py index 93ac68ec..3bf8ee71 100644 --- a/tests/bpm/test_bpm.py +++ b/tests/bpm/test_bpm.py @@ -9,7 +9,7 @@ def test_simulator_bpm_tilt(): sr.design.get_lattice().disable_6d() sr.design.magnet.get("SH1A-C01-H").strength.set(10e-6) # Add orbit sr.design.magnet.get("SH1A-C01-V").strength.set(10e-6) # Add orbit - bpm = sr.design.bpm.get("BPM_C01-01") + bpm = sr.design.diagnostic.bpm.get("BPM_C01-01") assert np.allclose(bpm.positions.get(), np.array([5.90809968e-05, 2.24832853e-05])) assert bpm.tilt.get() == 0 alpha = np.pi / 3 @@ -30,7 +30,7 @@ def test_simulator_bpm_tilt(): def test_simulator_bpm_offset(): sr: Accelerator = Accelerator.load("tests/config/bpms.yaml", ignore_external=True) sr.design.get_lattice().disable_6d() - bpm = sr.design.bpm.get("BPM_C01-01") + bpm = sr.design.diagnostic.bpm.get("BPM_C01-01") assert bpm.offset.get()[0] == 0 assert bpm.offset.get()[1] == 0 @@ -48,8 +48,8 @@ def test_simulator_bpm_offset(): def test_simulator_bpm_position(install_test_package): sr: Accelerator = Accelerator.load("tests/config/bpms.yaml") sr.design.get_lattice().disable_6d() - bpm = sr.design.bpm.get("BPM_C01-01") - bpm_simple = sr.live.bpm.get("BPM_C01-02") + bpm = sr.design.diagnostic.bpm.get("BPM_C01-01") + bpm_simple = sr.live.diagnostic.bpm.get("BPM_C01-02") assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0])) assert np.allclose(bpm_simple.positions.get(), np.array([0.0, 0.0])) @@ -58,9 +58,9 @@ def test_simulator_bpm_position(install_test_package): def test_simulator_bpm_position_with_bad_corrector_strength(): sr: Accelerator = Accelerator.load("tests/config/bpms.yaml", ignore_external=True) sr.design.get_lattice().disable_6d() - bpm1 = sr.design.bpm.get("BPM_C01-01") - bpm_simple = sr.design.bpm.get("BPM_C01-02") - bpm3 = sr.design.bpm.get("BPM_C01-03") + bpm1 = sr.design.diagnostic.bpm.get("BPM_C01-01") + bpm_simple = sr.design.diagnostic.bpm.get("BPM_C01-02") + bpm3 = sr.design.diagnostic.bpm.get("BPM_C01-03") sr.design.magnet.get("SH1A-C01-H").strength.set(-1e-6) sr.design.magnet.get("SH1A-C01-V").strength.set(-1e-6) diff --git a/tests/bpm/test_bpm_controlsystem.py b/tests/bpm/test_bpm_controlsystem.py index 13321ca1..8b534536 100644 --- a/tests/bpm/test_bpm_controlsystem.py +++ b/tests/bpm/test_bpm_controlsystem.py @@ -11,7 +11,7 @@ ) def test_controlsystem_bpm_tilt(install_test_package): sr: Accelerator = Accelerator.load("tests/config/bpms.yaml") - bpm = sr.live.bpm.get("BPM_C01-01") + bpm = sr.live.diagnostic.bpm.get("BPM_C01-01") print(bpm.tilt.get()) assert bpm.tilt.get() == 0 @@ -26,7 +26,7 @@ def test_controlsystem_bpm_tilt(install_test_package): ) def test_controlsystem_bpm_offset(install_test_package): sr: Accelerator = Accelerator.load("tests/config/bpms.yaml") - bpm = sr.live.bpm.get("BPM_C01-01") + bpm = sr.live.diagnostic.bpm.get("BPM_C01-01") assert bpm.offset.get()[0] == 0 assert bpm.offset.get()[1] == 0 @@ -43,8 +43,8 @@ def test_controlsystem_bpm_offset(install_test_package): ) def test_controlsystem_bpm_position(install_test_package): sr: Accelerator = Accelerator.load("tests/config/bpms.yaml") - bpm = sr.live.bpm.get("BPM_C01-01") - bpm_simple = sr.live.bpm.get("BPM_C01-02") + bpm = sr.live.diagnostic.bpm.get("BPM_C01-01") + bpm_simple = sr.live.diagnostic.bpm.get("BPM_C01-02") assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0])) assert np.allclose(bpm_simple.positions.get(), np.array([0.0, 0.0])) @@ -91,6 +91,6 @@ def test_controlsystem_bpm_position_indexed(install_test_package): set_attribute("srdiag/bpm/c01-04/Position", [0.0, 1.0], unit="mm") sr: Accelerator = Accelerator.load("tests/config/bpms.yaml") - bpm = sr.live.bpm.get("BPM_C01-04") + bpm = sr.live.diagnostic.bpm.get("BPM_C01-04") assert np.allclose(bpm.positions.get(), np.array([0.0, 1.0])) diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py index 3fdcbe42..7e630268 100644 --- a/tests/common/test_array_holder_navigation.py +++ b/tests/common/test_array_holder_navigation.py @@ -28,7 +28,7 @@ def test_dynamic_attribute_returns_named_combined_function_magnet_array(holder): def test_dynamic_attribute_returns_named_bpm_array(holder): - assert holder.bpms.BPMS is holder.bpms.get("BPMS") + assert holder.diagnostic.bpms.BPMS is holder.diagnostic.bpms.get("BPMS") def test_dynamic_attribute_returns_named_serialized_magnet_array(serialized_holder): @@ -60,7 +60,7 @@ def test_dynamic_attribute_rejects_non_identifier_names(holder): def test_dir_includes_configured_array_names(holder): assert {"HCORR", "VCORR", "HVCORR"} <= set(dir(holder.magnets)) assert "CFM" in dir(holder.combined_function_magnets) - assert "BPMS" in dir(holder.bpms) + assert "BPMS" in dir(holder.diagnostic.bpms) def test_dir_excludes_non_identifier_array_names(holder): diff --git a/tests/common/test_element_holder_collection.py b/tests/common/test_element_holder_collection.py index 937d2da7..4a55fadf 100644 --- a/tests/common/test_element_holder_collection.py +++ b/tests/common/test_element_holder_collection.py @@ -16,7 +16,7 @@ def holder(accelerator_from_fragments, sr_configuration_fragments): def test_exact_name_returns_the_element_or_none(holder): - assert holder["BPM_C04-01"] is holder.bpm.get("BPM_C04-01") + assert holder["BPM_C04-01"] is holder.diagnostic.bpm.get("BPM_C04-01") assert holder["UNKNOWN"] is None @@ -47,7 +47,7 @@ def test_new_calls_reflect_registry_additions(holder): assert "EXTRA_BPM" not in previous.names() assert holder.get().names() == previous.names() + ["EXTRA_BPM"] - assert holder["EXTRA_BPM"] is holder.bpm.get("EXTRA_BPM") + assert holder["EXTRA_BPM"] is holder.diagnostic.bpm.get("EXTRA_BPM") def test_patterns_always_return_arrays(holder): @@ -70,7 +70,7 @@ def test_character_classes_in_name_patterns(holder): def test_colons_are_part_of_names(holder): holder.fill_device([BPM("CELL04:BPM01", lattice_names="list(BPM_C04-01)")]) - assert holder["CELL04:BPM01"] is holder.bpm.get("CELL04:BPM01") + assert holder["CELL04:BPM01"] is holder.diagnostic.bpm.get("CELL04:BPM01") assert holder["CELL04:BPM*"].names() == ["CELL04:BPM01"] assert holder["model_name:*"].names() == [] diff --git a/tests/common/test_errors.py b/tests/common/test_errors.py index 38ce79f5..4265a20c 100644 --- a/tests/common/test_errors.py +++ b/tests/common/test_errors.py @@ -43,7 +43,7 @@ def test_tune(install_test_package): assert "Magnet QF1A-C05XX not defined" in str(exc.value) with pytest.raises(PyAMLException) as exc: - m2 = sr.design.bpm.get("QF1A-C05XX") + m2 = sr.design.diagnostic.bpm.get("QF1A-C05XX") assert "BPM QF1A-C05XX not defined" in str(exc.value) diff --git a/tests/diagnostics/test_diagnostic_accessors.py b/tests/diagnostics/test_diagnostic_accessors.py index 7e878914..2247db71 100644 --- a/tests/diagnostics/test_diagnostic_accessors.py +++ b/tests/diagnostics/test_diagnostic_accessors.py @@ -58,3 +58,24 @@ def test_diagnostic_raises_when_default_wrong_type(): _ = design.diagnostic.betatron_tune assert "BETATRON_TUNE" in str(exc.value) assert "BetatronTuneMonitor" in str(exc.value) + + +def test_diagnostic_bpm_returns_named_bpm(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + assert design.diagnostic.bpm.get("BPM_C04-04").get_name() == "BPM_C04-04" + + +def test_diagnostic_bpms_returns_named_array(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + bpms = design.diagnostic.bpms.get("BPM") + assert design.diagnostic.bpm.get("BPM_C04-04") in bpms diff --git a/tests/integration/test_dt4acc_twin_smoke.py b/tests/integration/test_dt4acc_twin_smoke.py index 549bdb4e..44220e09 100644 --- a/tests/integration/test_dt4acc_twin_smoke.py +++ b/tests/integration/test_dt4acc_twin_smoke.py @@ -134,7 +134,7 @@ def deactivated_test_orbit_correction(config_key: str): try: accelerator = _build_accelerator(config_key) control_mode = accelerator.live - bpms = control_mode.bpms.get("bpms") + bpms = control_mode.diagnostic.bpms.get("bpms") orbit_response_matrix = control_mode.get_orm_tuning("DEFAULT_ORBIT_RESPONSE_MATRIX") orbit_correction = control_mode.get_orbit_tuning("DEFAULT_ORBIT_CORRECTION") orbit_response_matrix.measure() diff --git a/tests/test_accelerator_load.py b/tests/test_accelerator_load.py index f30a68e3..0bc649ce 100644 --- a/tests/test_accelerator_load.py +++ b/tests/test_accelerator_load.py @@ -19,8 +19,8 @@ def test_peer(): def test_repr_is_informative_and_bounded(): sr = Accelerator.load("tests/config/EBSOrbit.yaml") - bpm = sr.design.bpm.get("BPM_C04-04") - bpms = sr.design.bpms.get("BPM") + bpm = sr.design.diagnostic.bpm.get("BPM_C04-04") + bpms = sr.design.diagnostic.bpms.get("BPM") assert repr(bpm) == ( "BPM(name='BPM_C04-04', lattice_names='BPM_C04-04', " @@ -46,7 +46,7 @@ def test_repr_options_limit_sequences(): set_repr_options(max_items=1) sr = Accelerator.load("tests/config/EBSOrbit.yaml") - bpms = sr.design.bpms.get("BPM") + bpms = sr.design.diagnostic.bpms.get("BPM") assert f"... +{len(bpms) - 1} more ..." in repr(bpms) finally: set_repr_options( diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py index 828627aa..43627e1d 100644 --- a/tests/test_catalogs.py +++ b/tests/test_catalogs.py @@ -59,7 +59,7 @@ def test_inline_catalog_is_supported(install_test_package): } ) - bpm = sr.live.bpm.get("BPM_C02-01") + bpm = sr.live.diagnostic.bpm.get("BPM_C02-01") assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0])) @@ -184,7 +184,7 @@ def test_indexed_catalog_entry_extracts_scalar_from_vector_attribute(install_tes } ) - bpm = sr.live.bpm.get("BPM_TEST") + bpm = sr.live.diagnostic.bpm.get("BPM_TEST") positions = bpm.positions.get() assert np.isclose(positions[0], 1.5) assert np.isclose(positions[1], -0.3) diff --git a/tests/test_load_conf_with_code.py b/tests/test_load_conf_with_code.py index e65f5be5..25a98a8d 100644 --- a/tests/test_load_conf_with_code.py +++ b/tests/test_load_conf_with_code.py @@ -8,13 +8,13 @@ def test_load_conf_with_code(): config_path = parent_folder.joinpath("config", "EBSOrbit.yaml").resolve() sr: Accelerator = Accelerator.load(config_path) - bpms = sr.live.bpms.get("BPM") + bpms = sr.live.diagnostic.bpms.get("BPM") assert bpms is not None assert len(bpms) == 320 assert sr.live[bpms[0].get_name()] is bpms[0] assert sr.live["BPM*"].names() == bpms.names() assert sr.live[:].names() == [element.get_name() for element in sr.live.get_all_elements()] - assert sr.design["BPM*"].names() == sr.design.bpms.get("BPM").names() + assert sr.design["BPM*"].names() == sr.design.diagnostic.bpms.get("BPM").names() - assert sr.live.bpms.BPM is bpms + assert sr.live.diagnostic.bpms.BPM is bpms diff --git a/tests/tuning_tools/test_bba.py b/tests/tuning_tools/test_bba.py index 330c8118..f4247103 100644 --- a/tests/tuning_tools/test_bba.py +++ b/tests/tuning_tools/test_bba.py @@ -9,7 +9,7 @@ def test_bba(): SR = sr.design # Add a misalignement - SR.bpm.get("BPM_C04-04").offset.set([20e-6, -15e-6]) + SR.diagnostic.bpm.get("BPM_C04-04").offset.set([20e-6, -15e-6]) # BBA (standard bow tie, model independant) bba = SR.get_bba("BBA-BPM_C04-04") diff --git a/tests/tuning_tools/test_tool_accessors.py b/tests/tuning_tools/test_tool_accessors.py index a3dcef13..d9a54e7b 100644 --- a/tests/tuning_tools/test_tool_accessors.py +++ b/tests/tuning_tools/test_tool_accessors.py @@ -27,7 +27,7 @@ def test_tuning_tools_expose_configured_elements(): assert design.crm.chromaticity_monitor is chromaticity_monitor assert design.crm.sextupoles is sextupoles - bpms = design.bpms.get("BPM") + bpms = design.diagnostic.bpms.get("BPM") rf_plant = design.rf.get("DEFAULT_RF_PLANT") assert chromaticity_monitor.tune_monitor is tune_monitor assert chromaticity_monitor.bpms is bpms @@ -49,7 +49,7 @@ def test_tuning_tools_expose_configured_elements(): for name in ("BBA-BPM_C04-04", "BBA2-BPM_C04-04"): bba = design.get_bba(name) assert bba.bpms is bpms - assert bba.bpm is design.bpm.get("BPM_C04-04") + assert bba.bpm is design.diagnostic.bpm.get("BPM_C04-04") assert bba.hcorrector is design.magnet.get("SF2E-C02-H") assert bba.vcorrector is design.magnet.get("SD1A-C26-V") assert bba.quadrupole is design.magnet.get("QF6B-C04") diff --git a/tests/tuning_tools/test_tuning_dispersion.py b/tests/tuning_tools/test_tuning_dispersion.py index 16d2cd39..9cd3e66b 100644 --- a/tests/tuning_tools/test_tuning_dispersion.py +++ b/tests/tuning_tools/test_tuning_dispersion.py @@ -17,7 +17,7 @@ def test_tuning_orm(): dispersion.measure() dispersion_data = dispersion.get() - bpms = element_holder.bpms.get("BPM") + bpms = element_holder.diagnostic.bpms.get("BPM") assert len(dispersion_data["frequency_response_x"]) == len(bpms) assert len(dispersion_data["frequency_response_y"]) == len(bpms) diff --git a/tests/tuning_tools/test_tuning_orbit_correction.py b/tests/tuning_tools/test_tuning_orbit_correction.py index 4bf3b6a6..7cf8fb56 100644 --- a/tests/tuning_tools/test_tuning_orbit_correction.py +++ b/tests/tuning_tools/test_tuning_orbit_correction.py @@ -22,7 +22,7 @@ def test_tuning_orbit_correction(): std_kick = 1e-6 hcorr = element_holder.magnets.get("HCorr") vcorr = element_holder.magnets.get("VCorr") - bpms = element_holder.bpms.get("BPM") + bpms = element_holder.diagnostic.bpms.get("BPM") x, y = bpms.positions.get().T # get reference orbit reference = np.concat((x, y)) diff --git a/tests/tuning_tools/test_tuning_orm.py b/tests/tuning_tools/test_tuning_orm.py index 553bce16..f3652f0c 100644 --- a/tests/tuning_tools/test_tuning_orm.py +++ b/tests/tuning_tools/test_tuning_orm.py @@ -17,7 +17,7 @@ def test_tuning_orm(): orm = element_holder.orm - bpms = element_holder.bpms.get("BPM") + bpms = element_holder.diagnostic.bpms.get("BPM") hcorr_names = element_holder.magnets.get("HCorr").names()[:4] vcorr_names = element_holder.magnets.get("VCorr").names()[:4] orm.measure(corrector_names=hcorr_names + vcorr_names) From 895d6517b934b17a5365e0f0dd4ed2e9572f447b Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Fri, 18 Sep 2026 17:09:57 +0200 Subject: [PATCH 05/16] Unify name/wildcard/regex lookup and miss-behavior across holders --- pyaml/arrays/element_array.py | 55 +++++---- pyaml/common/holders/diagnostic_holder.py | 32 +++++ pyaml/common/holders/element_holder.py | 84 ++++++++----- pyaml/common/holders/generic_array_holder.py | 30 ++++- .../common/holders/generic_element_holder.py | 33 ++++++ pyaml/common/holders/rf_holder.py | 64 ++++++++++ pyaml/common/holders/tool_holder.py | 32 +++++ tests/arrays/test_array_selection_types.py | 39 ++++++ tests/common/test_array_holder_navigation.py | 57 +++++++++ .../common/test_element_holder_collection.py | 112 +++++++++++++++++- tests/common/test_name_matching.py | 74 ++++++++++++ .../diagnostics/test_diagnostic_accessors.py | 68 +++++++++++ tests/rf/test_rf_holder.py | 48 ++++++++ tests/tuning_tools/test_tool_holder.py | 38 ++++++ 14 files changed, 702 insertions(+), 64 deletions(-) create mode 100644 tests/common/test_name_matching.py create mode 100644 tests/rf/test_rf_holder.py create mode 100644 tests/tuning_tools/test_tool_holder.py diff --git a/pyaml/arrays/element_array.py b/pyaml/arrays/element_array.py index 26b7ce26..ffa9e3d9 100644 --- a/pyaml/arrays/element_array.py +++ b/pyaml/arrays/element_array.py @@ -13,6 +13,7 @@ from ..bpm.bpm import BPM from ..common.element import Element, __pyaml_repr__ from ..common.exception import PyAMLException +from ..common.name_matching import resolve_names from ..magnet.cfm_magnet import CombinedFunctionMagnet from ..magnet.magnet import Magnet from ..magnet.serialized_magnet import SerializedMagnets @@ -240,22 +241,6 @@ def mro_as_list(cls: type) -> list[type]: return self.__create_array("", chosen, elements) - def _select_names(self, pattern: str) -> "ElementArray": - """Select names without interpreting field selectors. - - Parameters - ---------- - pattern : str - A fnmatch pattern applied to each element name. - - Returns - ------- - ElementArray - Typed selection in the original order, including an empty array - when no names match. - """ - return self._typed_array([element for element in self if fnmatch.fnmatch(element.get_name(), pattern)]) - def __is_bool_mask(self, other: object) -> bool: """Return True if 'other' looks like a boolean mask (list or numpy array).""" # --- numpy boolean array --- @@ -576,8 +561,13 @@ def __getitem__(self, key): Parameters ---------- - key : int, slice or str - Element index, slice, name pattern, or existing field selector. + key : int, slice, str, list[str] or tuple[str, ...] + Element index, slice, name pattern (or ``field:pattern`` field + selector), or a list/tuple of name patterns. A name pattern is a + literal name (must match an element in this array), an fnmatch + wildcard (``*``, ``?`` or ``[``), or a ``re:``-prefixed regular + expression. A list or tuple resolves each entry independently + and unions the results. Returns ------- @@ -585,33 +575,46 @@ def __getitem__(self, key): Indexed element or an array inferred from all selected elements. Different Magnet subclasses produce a MagnetArray; mixed element families produce an ElementArray. Empty selections return an - empty ElementArray. + empty ElementArray, except a literal name pattern (or literal + entry within a list/tuple) matching nothing, which raises. + + Raises + ------ + PyAMLException + If a literal name pattern, or a literal entry within a list or + tuple, matches no element in this array, or a ``re:`` pattern is + not a valid regular expression. Examples -------- >>> magnets = sr.design.magnets.get() >>> subset = magnets[:] # MagnetArray, including mixed magnet classes >>> correctors = magnets["SH*"] # MagnetArray + >>> correctors = magnets["re:^SH1A-C0[12]-H$"] # MagnetArray + >>> selection = magnets[["SH1A-C01-H", "SH*-V"]] # Union of patterns """ if isinstance(key, slice): # Slicing r = super().__getitem__(key) + elif isinstance(key, (list, tuple)): + # Selection by a list/tuple of name patterns + matched = set(resolve_names([e.get_name() for e in self], key)) + r = [e for e in self if e.get_name() in matched] + elif isinstance(key, str): - fields = key.split(":") + fields = [] if key.startswith("re:") else key.split(":") if len(fields) <= 1: - # Selection by name - r = [] - for e in self: - if fnmatch.fnmatch(e.get_name(), key): - r.append(e) + # Selection by name pattern + matched = set(resolve_names([e.get_name() for e in self], key)) + r = [e for e in self if e.get_name() in matched] else: # Selection by fields r = [] for e in self: txt = self.__eval_field(fields[0], e) - if fnmatch.fnmatch(txt, fields[1]): + if fnmatch.fnmatchcase(txt, fields[1]): r.append(e) else: diff --git a/pyaml/common/holders/diagnostic_holder.py b/pyaml/common/holders/diagnostic_holder.py index 361a06ed..66213bda 100644 --- a/pyaml/common/holders/diagnostic_holder.py +++ b/pyaml/common/holders/diagnostic_holder.py @@ -6,6 +6,7 @@ from ...diagnostics.tune_monitor import BetatronTuneMonitor from ..element import Element, __pyaml_repr__ from ..exception import PyAMLException +from ..name_matching import is_wildcard, resolve_names from .sub_holders import BPMHolder, BPMsHolder if TYPE_CHECKING: @@ -95,6 +96,37 @@ def get(self, name: str = None) -> "Element | ElementArray": return ElementArray("", list(self._peer._DIAG.values())) return self._peer._get_diagnostic(name) + def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | ElementArray": + """ + Return a diagnostic, or a selection typed as a generic ElementArray. + + Parameters + ---------- + key : str, list[str] or tuple[str, ...] + An exact literal name returns the stored diagnostic. An fnmatch + wildcard, a ``re:``-prefixed regular expression, or a list/tuple + of such patterns returns an ElementArray of matches (possibly + empty). + + Returns + ------- + Element or ElementArray + The stored diagnostic for an exact literal name, otherwise an + ElementArray of matches. + + Raises + ------ + PyAMLException + If an exact literal name, or a literal entry within a list or + tuple, does not match any diagnostic, or a ``re:`` pattern is + not a valid regular expression. + """ + store = self._peer._DIAG + if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + return self._peer._get_diagnostic(key) + names = resolve_names(store.keys(), key, what="Diagnostic") + return ElementArray("", [store[n] for n in names]) + @property def betatron_tune(self) -> BetatronTuneMonitor: """ diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 5b97734a..07751ee7 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -1,7 +1,5 @@ """Store, resolve, and group elements shared by runtime backends.""" -import fnmatch -import re from abc import ABCMeta, abstractmethod from typing import TYPE_CHECKING, overload @@ -17,6 +15,7 @@ from ..abstract_aggregator import ScalarAggregator from ..element import Element from ..exception import PyAMLException +from ..name_matching import is_wildcard, resolve_names from .diagnostic_holder import DiagnosticHolder from .rf_holder import RFHolder from .sub_holders import ( @@ -311,29 +310,31 @@ def create_bpm_aggregators(self, bpms: list[BPM]) -> list[ScalarAggregator | Non # Elements - def find_elements(self, filter: str) -> list[str]: + def find_elements(self, filter: str | list[str] | tuple[str, ...]) -> list[str]: """ - Find element names matching a literal, wildcard, or regular expression. + Find element names matching one or several literal, wildcard, or regex patterns. Parameters ---------- - filter : str - Pattern to match. Prefix with ``re:`` for a regular expression. + filter : str, list[str] or tuple[str, ...] + Pattern, or patterns, to match. A pattern is a literal name, an + fnmatch wildcard (``*``, ``?`` or ``[`` anywhere in the string), + or a regular expression prefixed with ``re:``. Several patterns + are resolved independently and unioned, de-duplicated, in + first-encounter order. Returns ------- list[str] Matching element names. - """ - if filter.startswith("re:"): - pattern = re.compile(rf"{filter[3:]}") - elements = [k for k in self._ALL.keys() if pattern.fullmatch(k)] - elif "*" in filter or "?" in filter: - elements = [k for k in self._ALL.keys() if fnmatch.fnmatch(k, filter)] - else: - elements = [filter] - return elements + Raises + ------ + PyAMLException + If a literal pattern matches no element, or a ``re:`` pattern is + not a valid regular expression. + """ + return resolve_names(self._ALL.keys(), filter, what="Element") def _fill_array( self, @@ -450,32 +451,43 @@ def __getitem__(self, key: int) -> Element: ... def __getitem__(self, key: slice) -> ElementArray: ... @overload - def __getitem__(self, key: str) -> Element | ElementArray | None: ... + def __getitem__(self, key: str) -> Element: ... + + @overload + def __getitem__(self, key: list[str] | tuple[str, ...]) -> ElementArray: ... - def __getitem__(self, key: int | slice | str) -> Element | ElementArray | None: + def __getitem__(self, key: int | slice | str | list[str] | tuple[str, ...]) -> Element | ElementArray: """Retrieve an element or select a collection. Parameters ---------- - key : int, slice or str - Index in registration order, slice, exact name, or name pattern. - Strings containing ``*``, ``?`` or ``[`` use fnmatch matching. - Other strings are exact registry keys. Colons are literal. + key : int, slice, str, list[str] or tuple[str, ...] + Index in registration order, slice, exact name, name pattern, or + a list/tuple of patterns. Strings containing ``*``, ``?`` or + ``[`` use fnmatch matching; a ``re:`` prefix uses a regular + expression instead. Any other string is an exact registry key. + Colons are literal. A list or tuple resolves each entry + independently and unions the results. Returns ------- - Element or ElementArray or None - An index returns an element. An exact name returns its element - or None. Patterns and slices return the most specific compatible - array, or an empty ElementArray when nothing matches. + Element or ElementArray + An index or an exact literal name returns its element. Patterns, + lists/tuples of patterns, and slices return the most specific + compatible array, or an empty ElementArray when nothing matches. The full slice ``[:]`` returns a generic ElementArray, like get(). Raises ------ + PyAMLException + If an exact literal name, or a literal entry within a list or + tuple, does not match any registered element, or if a ``re:`` + pattern is not a valid regular expression. IndexError If the index is out of bounds. TypeError - If the key is neither an integer, a slice, nor a string. + If the key is neither an integer, a slice, a string, nor a + list/tuple of strings. ValueError If a slice has a zero step. @@ -483,25 +495,33 @@ def __getitem__(self, key: int | slice | str) -> Element | ElementArray | None: ----- Indices follow insertion order, not necessarily lattice order. Collections share element references but do not modify the registry. - Field filters and regular expressions are not interpreted here. + Field filters are not interpreted here. Examples -------- >>> bpm = sr.live["BPM01"] - >>> missing = sr.live["UNKNOWN"] # None + >>> missing = sr.live["UNKNOWN"] # raises PyAMLException >>> bpms = sr.live["BPM*"] >>> bpms = sr.live["BPM0[123]"] # BPM01, BPM02 or BPM03 >>> bpms = sr.live["BPM0[1-3]"] # Same selection using a range >>> quads = sr.live["Q[FD]*"] # Names starting with QF or QD >>> bpms = sr.live["BPM0[!3]"] # One character after BPM0, except 3 + >>> bpms = sr.live["re:^BPM0[12]$"] # Regular expression + >>> mixed = sr.live[["BPM01", "QF1*"]] # Union of several patterns >>> first = sr.live[0] >>> subset = sr.live[1:10] >>> all_elements = sr.live[:] """ if isinstance(key, str): - if any(marker in key for marker in "*?["): - return self.get()._select_names(key) - return self._ALL.get(key) + if key.startswith("re:") or is_wildcard(key): + names = resolve_names(self._ALL.keys(), key) + return self.get()._typed_array([self._ALL[n] for n in names]) + if key not in self._ALL: + raise PyAMLException(f"Element {key} not defined") + return self._ALL[key] + if isinstance(key, (list, tuple)): + names = resolve_names(self._ALL.keys(), key) + return self.get()._typed_array([self._ALL[n] for n in names]) if isinstance(key, int): return list(self._ALL.values())[key] if isinstance(key, slice): @@ -509,7 +529,7 @@ def __getitem__(self, key: int | slice | str) -> Element | ElementArray | None: if key == slice(None): return elements return elements._typed_array(list(elements)[key]) - raise TypeError("ElementHolder keys must be integers, slices or strings") + raise TypeError("ElementHolder keys must be integers, slices, strings, or lists/tuples of strings") def fill_element_array(self, arrayName: str, elementNames: list[str]): """ diff --git a/pyaml/common/holders/generic_array_holder.py b/pyaml/common/holders/generic_array_holder.py index 4004a52a..50fec2c1 100644 --- a/pyaml/common/holders/generic_array_holder.py +++ b/pyaml/common/holders/generic_array_holder.py @@ -110,17 +110,41 @@ def add(self, arrayName: str, elementNames: list[str]): def __getitem__(self, key): """ - Return an element from the aggregate array by index. + Select from the aggregate array of every individual element. + + Delegates to :meth:`ElementArray.__getitem__ + ` on ``self.get()`` + (the array of every individual element of this type), so ``key`` + matches against **individual element names**, not against the + registered array/family names that :meth:`get` searches. These are + deliberately two different, non-overlapping namespaces: ``get(name)`` + looks up a configured family (e.g. ``"QForTune"``), while ``[key]`` + looks up the elements themselves (e.g. ``"QF1A-C01"`` or ``"QF1*"``). Parameters ---------- - key : int or slice - Index or slice passed to the aggregate array. + key : int, slice, str, list[str] or tuple[str, ...] + Index or slice into the aggregate array, an individual element's + exact name, an fnmatch wildcard or ``re:`` regular expression + over element names, or a list/tuple of such patterns. Returns ------- object Element or sub-array selected by ``key``. + + Raises + ------ + PyAMLException + If ``key`` is an exact literal element name (or a literal entry + within a list or tuple) that matches no individual element, or a + ``re:`` pattern is not a valid regular expression. + + Examples + -------- + >>> family = sr.live.magnets.get("QForTune") # array-name namespace + >>> one_magnet = sr.live.magnets["QF1A-C01"] # element-name namespace + >>> some_magnets = sr.live.magnets["QF1*"] # element-name namespace """ return self.get().__getitem__(key) diff --git a/pyaml/common/holders/generic_element_holder.py b/pyaml/common/holders/generic_element_holder.py index a23dec8b..ce5b85a4 100644 --- a/pyaml/common/holders/generic_element_holder.py +++ b/pyaml/common/holders/generic_element_holder.py @@ -2,7 +2,9 @@ from typing import TYPE_CHECKING, Generic, TypeVar +from ...arrays.element_array import ElementArray from ..element import Element, __pyaml_repr__ +from ..name_matching import is_wildcard, resolve_names if TYPE_CHECKING: from .element_holder import ElementHolder @@ -73,6 +75,37 @@ def get(self, name: str) -> T: """ return self._peer._get(self._what, name, self._store) + def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "T | ElementArray": + """ + Return an element, or a selection typed as a generic ElementArray. + + Parameters + ---------- + key : str, list[str] or tuple[str, ...] + An exact literal name returns the stored element. An fnmatch + wildcard (``*``, ``?`` or ``[``), a ``re:``-prefixed regular + expression, or a list/tuple of such patterns returns an + :class:`~pyaml.arrays.element_array.ElementArray` of matches + (possibly empty). + + Returns + ------- + T or ElementArray + The stored element for an exact literal name, otherwise an + ElementArray of matches. + + Raises + ------ + PyAMLException + If an exact literal name, or a literal entry within a list or + tuple, does not match any element in this holder, or a ``re:`` + pattern is not a valid regular expression. + """ + if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + return self._peer._get(self._what, key, self._store) + names = resolve_names(self._store.keys(), key, what=self._what) + return ElementArray("", [self._store[n] for n in names]) + def add(self, m: T): """ Add an element to the holder's name-indexed store. diff --git a/pyaml/common/holders/rf_holder.py b/pyaml/common/holders/rf_holder.py index 257c396a..0a2d1ed1 100644 --- a/pyaml/common/holders/rf_holder.py +++ b/pyaml/common/holders/rf_holder.py @@ -2,10 +2,12 @@ from typing import TYPE_CHECKING +from ...arrays.element_array import ElementArray from ...rf.rf_plant import RFPlant from ...rf.rf_transmitter import RFTransmitter from ..abstract import ReadWriteFloatScalar from ..element import __pyaml_repr__ +from ..name_matching import is_wildcard, resolve_names if TYPE_CHECKING: from .element_holder import ElementHolder @@ -50,6 +52,37 @@ def get(self, name: str) -> RFTransmitter: """ return self._peer._get("RFTransmitter", name, self._peer._RFTRANSMITTER) + def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFTransmitter | ElementArray": + """ + Return a transmitter, or a selection typed as a generic ElementArray. + + Parameters + ---------- + key : str, list[str] or tuple[str, ...] + An exact literal name returns the stored transmitter. An fnmatch + wildcard, a ``re:``-prefixed regular expression, or a list/tuple + of such patterns returns an ElementArray of matches (possibly + empty). + + Returns + ------- + RFTransmitter or ElementArray + The stored transmitter for an exact literal name, otherwise an + ElementArray of matches. + + Raises + ------ + PyAMLException + If an exact literal name, or a literal entry within a list or + tuple, does not match any transmitter, or a ``re:`` pattern is + not a valid regular expression. + """ + store = self._peer._RFTRANSMITTER + if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + return self._peer._get("RFTransmitter", key, store) + names = resolve_names(store.keys(), key, what="RFTransmitter") + return ElementArray("", [store[n] for n in names]) + def add(self, rf: RFTransmitter): """ Add an RF transmitter to the holder. @@ -134,6 +167,37 @@ def get(self, name: str) -> RFPlant: """ return self._peer._get("RFPlant", name, self._peer._RFPLANT) + def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFPlant | ElementArray": + """ + Return an RF plant, or a selection typed as a generic ElementArray. + + Parameters + ---------- + key : str, list[str] or tuple[str, ...] + An exact literal name returns the stored RF plant. An fnmatch + wildcard, a ``re:``-prefixed regular expression, or a list/tuple + of such patterns returns an ElementArray of matches (possibly + empty). + + Returns + ------- + RFPlant or ElementArray + The stored RF plant for an exact literal name, otherwise an + ElementArray of matches. + + Raises + ------ + PyAMLException + If an exact literal name, or a literal entry within a list or + tuple, does not match any RF plant, or a ``re:`` pattern is not + a valid regular expression. + """ + store = self._peer._RFPLANT + if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + return self._peer._get("RFPlant", key, store) + names = resolve_names(store.keys(), key, what="RFPlant") + return ElementArray("", [store[n] for n in names]) + def add(self, rf: RFPlant): """ Add an RF plant to the holder. diff --git a/pyaml/common/holders/tool_holder.py b/pyaml/common/holders/tool_holder.py index be7d17a0..4f8a8451 100644 --- a/pyaml/common/holders/tool_holder.py +++ b/pyaml/common/holders/tool_holder.py @@ -5,6 +5,7 @@ from ...arrays.element_array import ElementArray from ..element import Element, __pyaml_repr__ from ..exception import PyAMLException +from ..name_matching import is_wildcard, resolve_names if TYPE_CHECKING: from ...tuning_tools.chromaticity import Chromaticity @@ -86,6 +87,37 @@ def get(self, name: str = None) -> "Element | ElementArray": return ElementArray("", list(self._peer._TOOLS.values())) return self._peer._get_tool(name) + def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | ElementArray": + """ + Return a tool, or a selection typed as a generic ElementArray. + + Parameters + ---------- + key : str, list[str] or tuple[str, ...] + An exact literal name returns the stored tool. An fnmatch + wildcard, a ``re:``-prefixed regular expression, or a list/tuple + of such patterns returns an ElementArray of matches (possibly + empty). + + Returns + ------- + Element or ElementArray + The stored tool for an exact literal name, otherwise an + ElementArray of matches. + + Raises + ------ + PyAMLException + If an exact literal name, or a literal entry within a list or + tuple, does not match any tool, or a ``re:`` pattern is not a + valid regular expression. + """ + store = self._peer._TOOLS + if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + return self._peer._get_tool(key) + names = resolve_names(store.keys(), key, what="Tool") + return ElementArray("", [store[n] for n in names]) + def _validate_type(self, name: str, obj: Element, expected_type: type) -> Element: """ Ensure a resolved default tool matches the type its accessor expects. diff --git a/tests/arrays/test_array_selection_types.py b/tests/arrays/test_array_selection_types.py index d5cc782b..11e65181 100644 --- a/tests/arrays/test_array_selection_types.py +++ b/tests/arrays/test_array_selection_types.py @@ -2,6 +2,7 @@ from pyaml.arrays.element_array import ElementArray from pyaml.arrays.magnet_array import MagnetArray +from pyaml.common.exception import PyAMLException @pytest.fixture @@ -60,3 +61,41 @@ def test_empty_selections_and_integer_indexing_keep_their_behavior(design): assert magnets["UNKNOWN*"] == [] assert magnets[0] is design.magnet.get(magnets.names()[0]) assert type(magnets - magnets) is list + + +def test_literal_name_miss_raises(design): + magnets = design.magnets.get() + + with pytest.raises(PyAMLException): + magnets["UNKNOWN"] + with pytest.raises(PyAMLException): + design.magnets["UNKNOWN"] + + +def test_literal_name_hit_still_returns_a_single_element_array(design): + magnets = design.magnets.get() + + selected = magnets["SH1A-C01-H"] + assert type(selected) is MagnetArray + assert selected.names() == ["SH1A-C01-H"] + + +def test_bracket_only_pattern_is_a_wildcard(design): + magnets = design.magnets.get() + assert sorted(magnets["SH1A-C0[12]-H"].names()) == ["SH1A-C01-H", "SH1A-C02-H"] + + +def test_regex_pattern_is_supported(design): + magnets = design.magnets.get() + assert sorted(magnets["re:^SH1A-C0[12]-H$"].names()) == ["SH1A-C01-H", "SH1A-C02-H"] + + +def test_list_of_patterns_is_supported(design): + magnets = design.magnets.get() + selected = magnets[["SH1A-C01-H", "SH1A-C02-H"]] + assert selected.names() == ["SH1A-C01-H", "SH1A-C02-H"] + + +def test_wildcard_matching_is_case_sensitive(design): + magnets = design.magnets.get() + assert magnets["sh1a*"] == [] diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py index 7e630268..b1beea4e 100644 --- a/tests/common/test_array_holder_navigation.py +++ b/tests/common/test_array_holder_navigation.py @@ -2,6 +2,7 @@ from pyaml.accelerator import Accelerator from pyaml.arrays.cfm_magnet_array import CombinedFunctionMagnetArray +from pyaml.common.exception import PyAMLException @pytest.fixture @@ -97,3 +98,59 @@ def test_issue_373_example(): one_magnet = sr.design.magnet.get("QF1E-C04") one_magnet.strength.set(0.8) assert one_magnet.strength.get() == pytest.approx(0.8) + + +def test_configured_exclusion_family_reproduced_with_selection_and_difference(): + """QForTest is QForTune minus a `~name`/`~pattern` YAML exclusion; `[]` and `-` reproduce it.""" + sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True) + sr.design.get_lattice().disable_6d() + + q_for_tune = sr.design.magnets.get("QForTune") + q_for_test = sr.design.magnets.get("QForTest") # QForTune, minus ~QF1E-C05 and ~Q???-C06 + + reproduced = q_for_tune - sr.design.magnets["QF1E-C05"] - sr.design.magnets["Q???-C06"] + + assert reproduced == q_for_test + + +def test_magnet_holder_getitem_exact_name_matches_get(holder): + assert holder.magnet["SH1A-C01-H"] is holder.magnet.get("SH1A-C01-H") + + +def test_magnet_holder_getitem_exact_name_miss_raises(holder): + with pytest.raises(PyAMLException): + holder.magnet["UNKNOWN"] + + +def test_magnet_holder_getitem_wildcard_and_list_return_an_array(holder): + wildcard = holder.magnet["SH1A-C01-[HV]"] + assert sorted(wildcard.names()) == ["SH1A-C01-H", "SH1A-C01-V"] + assert holder.magnet["MISSING*"].names() == [] + + listed = holder.magnet[["SH1A-C01-H", "SH1A-C01-V"]] + assert listed.names() == ["SH1A-C01-H", "SH1A-C01-V"] + + +def test_magnet_holder_getitem_regex(holder): + matching = holder.magnet["re:^SH1A-C0[12]-H$"] + assert sorted(matching.names()) == ["SH1A-C01-H", "SH1A-C02-H"] + + +def test_combined_function_magnet_holder_getitem_exact_name_matches_get(holder): + assert holder.combined_function_magnet["SH1A-C01"] is holder.combined_function_magnet.get("SH1A-C01") + + +def test_combined_function_magnet_holder_getitem_exact_name_miss_raises(holder): + with pytest.raises(PyAMLException): + holder.combined_function_magnet["UNKNOWN"] + + +def test_serialized_magnet_holder_getitem_exact_name_matches_get(serialized_holder): + assert serialized_holder.serialized_magnet["mySeriesOfMagnets"] is serialized_holder.serialized_magnet.get( + "mySeriesOfMagnets" + ) + + +def test_serialized_magnet_holder_getitem_exact_name_miss_raises(serialized_holder): + with pytest.raises(PyAMLException): + serialized_holder.serialized_magnet["UNKNOWN"] diff --git a/tests/common/test_element_holder_collection.py b/tests/common/test_element_holder_collection.py index 4a55fadf..dd03865d 100644 --- a/tests/common/test_element_holder_collection.py +++ b/tests/common/test_element_holder_collection.py @@ -15,9 +15,10 @@ def holder(accelerator_from_fragments, sr_configuration_fragments): return sr.design -def test_exact_name_returns_the_element_or_none(holder): +def test_exact_name_returns_the_element_or_raises(holder): assert holder["BPM_C04-01"] is holder.diagnostic.bpm.get("BPM_C04-01") - assert holder["UNKNOWN"] is None + with pytest.raises(PyAMLException): + holder["UNKNOWN"] def test_get_and_full_slice_keep_registration_order(holder): @@ -113,7 +114,8 @@ def test_empty_holder_returns_empty_collections(ebs_lattice_file): assert type(holder.get()) is ElementArray assert holder[:].names() == [] assert holder["BPM*"].names() == [] - assert holder["BPM_C04-01"] is None + with pytest.raises(PyAMLException): + holder["BPM_C04-01"] def test_invalid_indices_and_keys_raise_clear_errors(holder): @@ -148,3 +150,107 @@ def test_existing_array_field_filters_still_work(holder): def test_existing_empty_intersection_stays_a_list(holder): assert type(holder["SH1A-C0?-H"] & holder["SH1A-C0?-V"]) is list + + +def test_intersecting_two_wildcard_selections(holder): + """Two overlapping wildcard selections combined with `&` narrow down to their overlap.""" + by_cell = holder["SH1A-C01*"] # SH1A-C01-H, SH1A-C01-V, SH1A-C01-SQ + by_plane = holder["SH1A-C0?-H"] # SH1A-C01-H, SH1A-C02-H + + selected = by_cell & by_plane + + assert isinstance(selected, MagnetArray) + assert selected.names() == ["SH1A-C01-H"] + + +def test_union_of_a_list_selection_and_a_wildcard_selection(holder): + """A list-of-patterns selection and a wildcard selection combine with `|` like any array.""" + cell_01 = holder[["SH1A-C01-H", "SH1A-C01-V"]] + cell_02 = holder["SH1A-C02*"] # the CFM magnet SH1A-C02, plus its -H, -V, -SQ sub-magnets + + combined = cell_01 | cell_02 + + # Mixes a CombinedFunctionMagnet (SH1A-C02) with plain Magnets, so the union + # stays a generic ElementArray rather than a MagnetArray. + assert type(combined) is ElementArray + assert sorted(combined.names()) == [ + "SH1A-C01-H", + "SH1A-C01-V", + "SH1A-C02", + "SH1A-C02-H", + "SH1A-C02-SQ", + "SH1A-C02-V", + ] + + +def test_difference_with_a_regex_selection(holder): + """`-` removes a `re:` selection's matches from a wildcard selection, like any array.""" + both_planes_h = holder["SH1A-C0?-H"] # SH1A-C01-H, SH1A-C02-H + cell_01_h = holder["re:^SH1A-C01-H$"] + + selected = both_planes_h - cell_01_h + + assert isinstance(selected, MagnetArray) + assert selected.names() == ["SH1A-C02-H"] + + +def test_disjoint_regex_and_list_selections_produce_a_plain_list(holder): + """The same empty-result-is-a-plain-list quirk applies to the new selection styles too.""" + cell_01_h = holder["re:^SH1A-C01-H$"] + cell_02_h_v = holder[["SH1A-C02-H", "SH1A-C02-V"]] + + assert type(cell_01_h & cell_02_h_v) is list + + +def test_selection_combined_with_a_configured_family_via_regex_and_list(holder): + """`re:` and list-of-patterns selections intersect with a configured family, same as wildcards.""" + el_array = holder.get_elements("ElArray") # BPM_C04-01, BPM_C04-02, SH1A-C01-V, SH1A-C02-H + + by_regex = holder["re:^SH1A-C0[12]-H$"] & el_array + assert isinstance(by_regex, MagnetArray) + assert by_regex.names() == ["SH1A-C02-H"] + + by_list = holder[["BPM_C04-01", "BPM_C04-02"]] & el_array + assert isinstance(by_list, BPMArray) + assert by_list.names() == ["BPM_C04-01", "BPM_C04-02"] + + +def test_regex_pattern_is_supported(holder): + assert holder["re:^BPM_C04-0[12]$"].names() == ["BPM_C04-01", "BPM_C04-02"] + assert holder["re:^NOTHING$"].names() == [] + + +def test_invalid_regex_raises_pyaml_exception(holder): + with pytest.raises(PyAMLException, match="Invalid regex"): + holder["re:("] + + +def test_list_of_patterns_unions_results(holder): + selected = holder[["BPM_C04-01", "SH1A-C0?-H"]] + assert selected.names() == ["BPM_C04-01", "SH1A-C01-H", "SH1A-C02-H"] + + +def test_list_of_patterns_with_missing_literal_raises(holder): + with pytest.raises(PyAMLException): + holder[["BPM_C04-01", "UNKNOWN"]] + + +def test_wildcard_matching_is_case_sensitive(holder): + assert holder["bpm_c04*"].names() == [] + + +def test_find_elements_literal_miss_raises(holder): + with pytest.raises(PyAMLException): + holder.find_elements("UNKNOWN") + + +def test_find_elements_bracket_only_pattern_is_a_wildcard(holder): + assert holder.find_elements("BPM_C04-0[12]") == ["BPM_C04-01", "BPM_C04-02"] + + +def test_find_elements_supports_regex(holder): + assert holder.find_elements("re:^BPM_C04-0[12]$") == ["BPM_C04-01", "BPM_C04-02"] + + +def test_find_elements_supports_a_list_of_patterns(holder): + assert holder.find_elements(["BPM_C04-01", "SH1A-C0?-H"]) == ["BPM_C04-01", "SH1A-C01-H", "SH1A-C02-H"] diff --git a/tests/common/test_name_matching.py b/tests/common/test_name_matching.py new file mode 100644 index 00000000..7e7319bf --- /dev/null +++ b/tests/common/test_name_matching.py @@ -0,0 +1,74 @@ +import pytest + +from pyaml.common.exception import PyAMLException +from pyaml.common.name_matching import is_wildcard, resolve_names + +NAMES = ["BPM_C04-01", "BPM_C04-02", "QF1A-C01", "QF1A-C02"] + + +def test_is_wildcard_triggers_on_star_question_and_bracket(): + assert is_wildcard("BPM*") + assert is_wildcard("BPM?") + assert is_wildcard("BPM[01]") + assert not is_wildcard("BPM_C04-01") + assert not is_wildcard("re:^BPM") + + +def test_literal_hit_returns_the_single_name(): + assert resolve_names(NAMES, "QF1A-C01") == ["QF1A-C01"] + + +def test_literal_miss_raises(): + with pytest.raises(PyAMLException, match="Element UNKNOWN not defined"): + resolve_names(NAMES, "UNKNOWN") + + +def test_literal_miss_uses_the_provided_what_label(): + with pytest.raises(PyAMLException, match="Magnet UNKNOWN not defined"): + resolve_names(NAMES, "UNKNOWN", what="Magnet") + + +def test_wildcard_hit_and_empty_are_not_errors(): + assert resolve_names(NAMES, "BPM*") == ["BPM_C04-01", "BPM_C04-02"] + assert resolve_names(NAMES, "MISSING*") == [] + + +def test_wildcard_is_case_sensitive(): + assert resolve_names(NAMES, "bpm*") == [] + + +def test_bracket_only_pattern_is_a_wildcard_not_a_literal(): + assert resolve_names(NAMES, "QF1A-C0[12]") == ["QF1A-C01", "QF1A-C02"] + + +def test_regex_hit_and_empty_are_not_errors(): + assert resolve_names(NAMES, "re:^BPM_C04-0[12]$") == ["BPM_C04-01", "BPM_C04-02"] + assert resolve_names(NAMES, "re:^NOTHING$") == [] + + +def test_regex_is_a_fullmatch(): + assert resolve_names(NAMES, "re:BPM_C04") == [] + + +def test_invalid_regex_raises_pyaml_exception_not_re_error(): + with pytest.raises(PyAMLException, match="Invalid regex"): + resolve_names(NAMES, "re:(") + + +def test_list_of_patterns_unions_and_deduplicates_in_order(): + result = resolve_names(NAMES, ["QF1A-C01", "BPM*", "QF1A-C01"]) + assert result == ["QF1A-C01", "BPM_C04-01", "BPM_C04-02"] + + +def test_tuple_of_patterns_is_also_accepted(): + assert resolve_names(NAMES, ("QF1A-C01", "QF1A-C02")) == ["QF1A-C01", "QF1A-C02"] + + +def test_list_with_one_missing_literal_raises(): + with pytest.raises(PyAMLException, match="Element UNKNOWN not defined"): + resolve_names(NAMES, ["QF1A-C01", "UNKNOWN"]) + + +def test_list_mixing_literal_wildcard_and_regex(): + result = resolve_names(NAMES, ["QF1A-C01", "BPM*", "re:^QF1A-C02$"]) + assert result == ["QF1A-C01", "BPM_C04-01", "BPM_C04-02", "QF1A-C02"] diff --git a/tests/diagnostics/test_diagnostic_accessors.py b/tests/diagnostics/test_diagnostic_accessors.py index 2247db71..342c04dd 100644 --- a/tests/diagnostics/test_diagnostic_accessors.py +++ b/tests/diagnostics/test_diagnostic_accessors.py @@ -79,3 +79,71 @@ def test_diagnostic_bpms_returns_named_array(): bpms = design.diagnostic.bpms.get("BPM") assert design.diagnostic.bpm.get("BPM_C04-04") in bpms + + +def test_diagnostic_getitem_exact_name_matches_get(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + assert design.diagnostic["BETATRON_TUNE"] is design.diagnostic.get("BETATRON_TUNE") + + +def test_diagnostic_getitem_exact_name_miss_raises(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + with pytest.raises(PyAMLException): + design.diagnostic["UNKNOWN"] + + +def test_diagnostic_getitem_wildcard_returns_an_array(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + matching = design.diagnostic["BETATRON*"] + assert matching.names() == ["BETATRON_TUNE"] + assert design.diagnostic["MISSING*"].names() == [] + + +def test_diagnostic_bpm_getitem_exact_name_matches_get(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + assert design.diagnostic.bpm["BPM_C04-04"] is design.diagnostic.bpm.get("BPM_C04-04") + + +def test_diagnostic_bpm_getitem_exact_name_miss_raises(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + with pytest.raises(PyAMLException): + design.diagnostic.bpm["UNKNOWN"] + + +def test_diagnostic_bpm_getitem_wildcard_and_list_return_an_array(): + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + wildcard = design.diagnostic.bpm["BPM_C04-0[14]"] + assert sorted(wildcard.names()) == ["BPM_C04-01", "BPM_C04-04"] + + listed = design.diagnostic.bpm[["BPM_C04-01", "BPM_C04-04"]] + assert listed.names() == ["BPM_C04-01", "BPM_C04-04"] diff --git a/tests/rf/test_rf_holder.py b/tests/rf/test_rf_holder.py new file mode 100644 index 00000000..784577a8 --- /dev/null +++ b/tests/rf/test_rf_holder.py @@ -0,0 +1,48 @@ +import pytest + +from pyaml.accelerator import Accelerator +from pyaml.common.exception import PyAMLException + + +@pytest.fixture +def design(): + return Accelerator.load("tests/config/EBS_rf_multi.yaml", ignore_external=True).design + + +def test_rf_holder_getitem_exact_name_matches_get(design): + assert design.rf["DEFAULT_RF_PLANT"] is design.rf.get("DEFAULT_RF_PLANT") + + +def test_rf_holder_getitem_exact_name_miss_raises(design): + with pytest.raises(PyAMLException): + design.rf["UNKNOWN"] + + +def test_rf_holder_getitem_wildcard_returns_an_array(design): + matching = design.rf["DEFAULT_*"] + assert matching.names() == ["DEFAULT_RF_PLANT"] + assert design.rf["MISSING*"].names() == [] + + +def test_rf_transmitter_holder_getitem_exact_name_matches_get(design): + assert design.rf.transmitter["RFTRA1"] is design.rf.transmitter.get("RFTRA1") + + +def test_rf_transmitter_holder_getitem_exact_name_miss_raises(design): + with pytest.raises(PyAMLException): + design.rf.transmitter["UNKNOWN"] + + +def test_rf_transmitter_holder_getitem_wildcard_returns_an_array(design): + matching = design.rf.transmitter["RFTRA*"] + assert sorted(matching.names()) == ["RFTRA1", "RFTRA2", "RFTRA_HARMONIC"] + + +def test_rf_transmitter_holder_getitem_list_of_patterns(design): + selected = design.rf.transmitter[["RFTRA1", "RFTRA2"]] + assert selected.names() == ["RFTRA1", "RFTRA2"] + + +def test_rf_transmitter_holder_getitem_regex(design): + matching = design.rf.transmitter["re:^RFTRA[12]$"] + assert sorted(matching.names()) == ["RFTRA1", "RFTRA2"] diff --git a/tests/tuning_tools/test_tool_holder.py b/tests/tuning_tools/test_tool_holder.py new file mode 100644 index 00000000..3821fcf3 --- /dev/null +++ b/tests/tuning_tools/test_tool_holder.py @@ -0,0 +1,38 @@ +import pytest + +from pyaml.accelerator import Accelerator +from pyaml.common.exception import PyAMLException + + +@pytest.fixture +def design(): + return Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + + +def test_tool_holder_getitem_exact_name_matches_get(design): + assert design.tool["DEFAULT_TUNE_CORRECTION"] is design.tool.get("DEFAULT_TUNE_CORRECTION") + + +def test_tool_holder_getitem_exact_name_miss_raises(design): + with pytest.raises(PyAMLException): + design.tool["UNKNOWN"] + + +def test_tool_holder_getitem_wildcard_returns_an_array(design): + matching = design.tool["DEFAULT_TUNE*"] + assert sorted(matching.names()) == ["DEFAULT_TUNE_CORRECTION", "DEFAULT_TUNE_RESPONSE_MATRIX"] + assert design.tool["MISSING*"].names() == [] + + +def test_tool_holder_getitem_list_of_patterns(design): + selected = design.tool[["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"]] + assert selected.names() == ["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"] + + +def test_tool_holder_getitem_regex(design): + matching = design.tool["re:^DEFAULT_(TUNE|ORBIT)_CORRECTION$"] + assert sorted(matching.names()) == ["DEFAULT_ORBIT_CORRECTION", "DEFAULT_TUNE_CORRECTION"] From b458038a847763c2791fef4e98d7510e9a56d9f9 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Fri, 18 Sep 2026 17:18:49 +0200 Subject: [PATCH 06/16] Unify name/wildcard/regex lookup and miss-behavior across holders --- pyaml/common/name_matching.py | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 pyaml/common/name_matching.py diff --git a/pyaml/common/name_matching.py b/pyaml/common/name_matching.py new file mode 100644 index 00000000..cc228346 --- /dev/null +++ b/pyaml/common/name_matching.py @@ -0,0 +1,67 @@ +"""Shared name and wildcard resolution convention used by every holder and array.""" + +import fnmatch +import re +from typing import Iterable + +from .exception import PyAMLException + +WILDCARD_CHARS = frozenset("*?[") + + +def is_wildcard(pattern: str) -> bool: + """Return True if `pattern` contains an fnmatch wildcard character.""" + return any(c in pattern for c in WILDCARD_CHARS) + + +def resolve_names(pool: Iterable[str], pattern: str | list[str] | tuple[str, ...], what: str = "Element") -> list[str]: + """ + Resolve one pattern, or several, against a pool of names. + + Parameters + ---------- + pool : Iterable[str] + Names to match against. + pattern : str, list[str] or tuple[str, ...] + A literal name, an fnmatch wildcard (triggered by ``*``, ``?`` or + ``[`` anywhere in the string), or a regular expression prefixed with + ``re:``. A sequence of patterns is resolved entry by entry and the + results are unioned, de-duplicated, in first-encounter order. + + Returns + ------- + list[str] + Matching names. + + Raises + ------ + PyAMLException + If a literal pattern does not match any name in `pool`, or if a + `re:`-prefixed pattern is not a valid regular expression. + """ + names = list(pool) + patterns = pattern if isinstance(pattern, (list, tuple)) else [pattern] + + resolved: list[str] = [] + seen: set[str] = set() + for p in patterns: + for name in _resolve_one(names, p, what): + if name not in seen: + seen.add(name) + resolved.append(name) + return resolved + + +def _resolve_one(names: list[str], pattern: str, what: str) -> list[str]: + if pattern.startswith("re:"): + source = pattern[3:] + try: + compiled = re.compile(source) + except re.error as exc: + raise PyAMLException(f"Invalid regex '{source}': {exc}") from exc + return [n for n in names if compiled.fullmatch(n)] + if is_wildcard(pattern): + return [n for n in names if fnmatch.fnmatchcase(n, pattern)] + if pattern not in names: + raise PyAMLException(f"{what} {pattern} not defined") + return [pattern] From b229b01caed726120a0ac6eecfec1b6c97504853 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Mon, 21 Sep 2026 10:43:07 +0200 Subject: [PATCH 07/16] Support ~ exclusion patterns in the public list-of-patterns resolver --- pyaml/arrays/element_array.py | 5 ++- pyaml/common/holders/diagnostic_holder.py | 2 +- pyaml/common/holders/element_holder.py | 21 ++++++---- .../common/holders/generic_element_holder.py | 2 +- pyaml/common/holders/rf_holder.py | 4 +- pyaml/common/holders/tool_holder.py | 2 +- pyaml/common/name_matching.py | 31 ++++++++++---- tests/common/test_array_holder_navigation.py | 17 ++++++++ .../common/test_element_holder_collection.py | 21 ++++++++++ tests/common/test_name_matching.py | 40 +++++++++++++++++++ 10 files changed, 125 insertions(+), 20 deletions(-) diff --git a/pyaml/arrays/element_array.py b/pyaml/arrays/element_array.py index ffa9e3d9..428b8e1d 100644 --- a/pyaml/arrays/element_array.py +++ b/pyaml/arrays/element_array.py @@ -567,7 +567,9 @@ def __getitem__(self, key): literal name (must match an element in this array), an fnmatch wildcard (``*``, ``?`` or ``[``), or a ``re:``-prefixed regular expression. A list or tuple resolves each entry independently - and unions the results. + and unions the results. Prefix a name pattern with ``~`` to + exclude its matches instead; a lone ``~pattern`` means every + element except those matches. Returns ------- @@ -592,6 +594,7 @@ def __getitem__(self, key): >>> correctors = magnets["SH*"] # MagnetArray >>> correctors = magnets["re:^SH1A-C0[12]-H$"] # MagnetArray >>> selection = magnets[["SH1A-C01-H", "SH*-V"]] # Union of patterns + >>> all_but_one = magnets["~SH1A-C01-H"] # Every magnet except one """ if isinstance(key, slice): # Slicing diff --git a/pyaml/common/holders/diagnostic_holder.py b/pyaml/common/holders/diagnostic_holder.py index 66213bda..588b74c7 100644 --- a/pyaml/common/holders/diagnostic_holder.py +++ b/pyaml/common/holders/diagnostic_holder.py @@ -122,7 +122,7 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | Elem not a valid regular expression. """ store = self._peer._DIAG - if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get_diagnostic(key) names = resolve_names(store.keys(), key, what="Diagnostic") return ElementArray("", [store[n] for n in names]) diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 07751ee7..9cf8be5d 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -319,9 +319,11 @@ def find_elements(self, filter: str | list[str] | tuple[str, ...]) -> list[str]: filter : str, list[str] or tuple[str, ...] Pattern, or patterns, to match. A pattern is a literal name, an fnmatch wildcard (``*``, ``?`` or ``[`` anywhere in the string), - or a regular expression prefixed with ``re:``. Several patterns - are resolved independently and unioned, de-duplicated, in - first-encounter order. + or a regular expression prefixed with ``re:``. Prefix any of + those with ``~`` to exclude its matches instead, as in the + ``elements:`` selector list of a YAML array declaration, e.g. + ``["QD2*", "QF1*", "~QF1E-C05"]``. A lone ``~pattern`` (or a list + made only of ``~`` entries) means "every element except those". Returns ------- @@ -331,8 +333,8 @@ def find_elements(self, filter: str | list[str] | tuple[str, ...]) -> list[str]: Raises ------ PyAMLException - If a literal pattern matches no element, or a ``re:`` pattern is - not a valid regular expression. + If a literal pattern (or a ``~``-prefixed literal) matches no + element, or a ``re:`` pattern is not a valid regular expression. """ return resolve_names(self._ALL.keys(), filter, what="Element") @@ -467,7 +469,10 @@ def __getitem__(self, key: int | slice | str | list[str] | tuple[str, ...]) -> E ``[`` use fnmatch matching; a ``re:`` prefix uses a regular expression instead. Any other string is an exact registry key. Colons are literal. A list or tuple resolves each entry - independently and unions the results. + independently and unions the results. Prefix any pattern with + ``~`` to exclude its matches instead, as in a YAML array's + ``elements:`` list; a lone ``~pattern`` means every element + except those matches. Returns ------- @@ -508,12 +513,14 @@ def __getitem__(self, key: int | slice | str | list[str] | tuple[str, ...]) -> E >>> bpms = sr.live["BPM0[!3]"] # One character after BPM0, except 3 >>> bpms = sr.live["re:^BPM0[12]$"] # Regular expression >>> mixed = sr.live[["BPM01", "QF1*"]] # Union of several patterns + >>> all_but_one = sr.live["~BPM01"] # Every element except BPM01 + >>> most_quads = sr.live[["QF1*", "~QF1A-C01"]] # QF1* minus one name >>> first = sr.live[0] >>> subset = sr.live[1:10] >>> all_elements = sr.live[:] """ if isinstance(key, str): - if key.startswith("re:") or is_wildcard(key): + if key.startswith("re:") or key.startswith("~") or is_wildcard(key): names = resolve_names(self._ALL.keys(), key) return self.get()._typed_array([self._ALL[n] for n in names]) if key not in self._ALL: diff --git a/pyaml/common/holders/generic_element_holder.py b/pyaml/common/holders/generic_element_holder.py index ce5b85a4..101796b9 100644 --- a/pyaml/common/holders/generic_element_holder.py +++ b/pyaml/common/holders/generic_element_holder.py @@ -101,7 +101,7 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "T | ElementArr tuple, does not match any element in this holder, or a ``re:`` pattern is not a valid regular expression. """ - if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get(self._what, key, self._store) names = resolve_names(self._store.keys(), key, what=self._what) return ElementArray("", [self._store[n] for n in names]) diff --git a/pyaml/common/holders/rf_holder.py b/pyaml/common/holders/rf_holder.py index 0a2d1ed1..8b81d7c9 100644 --- a/pyaml/common/holders/rf_holder.py +++ b/pyaml/common/holders/rf_holder.py @@ -78,7 +78,7 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFTransmitter not a valid regular expression. """ store = self._peer._RFTRANSMITTER - if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get("RFTransmitter", key, store) names = resolve_names(store.keys(), key, what="RFTransmitter") return ElementArray("", [store[n] for n in names]) @@ -193,7 +193,7 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFPlant | Elem a valid regular expression. """ store = self._peer._RFPLANT - if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get("RFPlant", key, store) names = resolve_names(store.keys(), key, what="RFPlant") return ElementArray("", [store[n] for n in names]) diff --git a/pyaml/common/holders/tool_holder.py b/pyaml/common/holders/tool_holder.py index 4f8a8451..d02c044b 100644 --- a/pyaml/common/holders/tool_holder.py +++ b/pyaml/common/holders/tool_holder.py @@ -113,7 +113,7 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | Elem valid regular expression. """ store = self._peer._TOOLS - if isinstance(key, str) and not key.startswith("re:") and not is_wildcard(key): + if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get_tool(key) names = resolve_names(store.keys(), key, what="Tool") return ElementArray("", [store[n] for n in names]) diff --git a/pyaml/common/name_matching.py b/pyaml/common/name_matching.py index cc228346..9125cd3a 100644 --- a/pyaml/common/name_matching.py +++ b/pyaml/common/name_matching.py @@ -25,8 +25,16 @@ def resolve_names(pool: Iterable[str], pattern: str | list[str] | tuple[str, ... pattern : str, list[str] or tuple[str, ...] A literal name, an fnmatch wildcard (triggered by ``*``, ``?`` or ``[`` anywhere in the string), or a regular expression prefixed with - ``re:``. A sequence of patterns is resolved entry by entry and the - results are unioned, de-duplicated, in first-encounter order. + ``re:``. Prefix any of those with ``~`` to exclude its matches + instead of including them, mirroring the ``elements:`` selector list + convention used in YAML configuration. A sequence of patterns is + resolved entry by entry: non-``~`` entries are unioned, + de-duplicated, in first-encounter order, then anything matched by a + ``~`` entry is removed from that union. If every entry is + ``~``-prefixed (including a single lone ``~pattern``, treated as a + one-entry sequence), there is no explicit inclusion, so the base set + defaults to the full pool: ``~pattern`` alone means "everything + except pattern". Returns ------- @@ -36,20 +44,29 @@ def resolve_names(pool: Iterable[str], pattern: str | list[str] | tuple[str, ... Raises ------ PyAMLException - If a literal pattern does not match any name in `pool`, or if a - `re:`-prefixed pattern is not a valid regular expression. + If a literal pattern (or the remainder of a ``~``-prefixed one) does + not match any name in `pool`, or if a `re:`-prefixed pattern is not + a valid regular expression. """ names = list(pool) patterns = pattern if isinstance(pattern, (list, tuple)) else [pattern] - resolved: list[str] = [] + included: list[str] = [] seen: set[str] = set() + excluded: set[str] = set() + has_inclusion = False for p in patterns: + if p.startswith("~"): + excluded.update(_resolve_one(names, p[1:], what)) + continue + has_inclusion = True for name in _resolve_one(names, p, what): if name not in seen: seen.add(name) - resolved.append(name) - return resolved + included.append(name) + + base = included if has_inclusion else names + return [n for n in base if n not in excluded] def _resolve_one(names: list[str], pattern: str, what: str) -> list[str]: diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py index b1beea4e..04cc2480 100644 --- a/tests/common/test_array_holder_navigation.py +++ b/tests/common/test_array_holder_navigation.py @@ -113,6 +113,23 @@ def test_configured_exclusion_family_reproduced_with_selection_and_difference(): assert reproduced == q_for_test +def test_configured_exclusion_family_reproduced_in_a_single_getitem_call(): + """The YAML `elements:` selector list (`[QD2*, QF1*, ~QF1E-C05, ~Q???-C06]`) works verbatim through `[]`. + + Selection goes through the top-level holder, not `.magnets`, so it resolves patterns + against the same global element pool `find_elements()`/`_fill_array` use to build + `QForTest` in the YAML, and so lands in the same order. + """ + sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True) + sr.design.get_lattice().disable_6d() + + q_for_test = sr.design.magnets.get("QForTest") + reproduced = sr.design[["QD2*", "QF1*", "~QF1E-C05", "~Q???-C06"]] + + assert type(reproduced) is type(q_for_test) + assert reproduced == q_for_test + + def test_magnet_holder_getitem_exact_name_matches_get(holder): assert holder.magnet["SH1A-C01-H"] is holder.magnet.get("SH1A-C01-H") diff --git a/tests/common/test_element_holder_collection.py b/tests/common/test_element_holder_collection.py index dd03865d..c6c889d5 100644 --- a/tests/common/test_element_holder_collection.py +++ b/tests/common/test_element_holder_collection.py @@ -254,3 +254,24 @@ def test_find_elements_supports_regex(holder): def test_find_elements_supports_a_list_of_patterns(holder): assert holder.find_elements(["BPM_C04-01", "SH1A-C0?-H"]) == ["BPM_C04-01", "SH1A-C01-H", "SH1A-C02-H"] + + +def test_find_elements_supports_an_exclusion_in_a_list(holder): + both_planes = holder.find_elements(["SH1A-C0?-H", "SH1A-C0?-V"]) + assert both_planes == ["SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V", "SH1A-C02-V"] + + minus_one = holder.find_elements(["SH1A-C0?-H", "SH1A-C0?-V", "~SH1A-C02-V"]) + assert minus_one == ["SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V"] + + +def test_getitem_supports_an_exclusion_in_a_list(holder): + selected = holder[["SH1A-C0?-H", "SH1A-C0?-V", "~SH1A-C02-V"]] + assert selected.names() == ["SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V"] + + +def test_getitem_lone_exclusion_pattern_means_everything_except(holder): + all_names = holder.get_all_elements() + selected = holder["~QF1A-C01"] + + assert "QF1A-C01" not in selected.names() + assert len(selected) == len(all_names) - 1 diff --git a/tests/common/test_name_matching.py b/tests/common/test_name_matching.py index 7e7319bf..c7365862 100644 --- a/tests/common/test_name_matching.py +++ b/tests/common/test_name_matching.py @@ -72,3 +72,43 @@ def test_list_with_one_missing_literal_raises(): def test_list_mixing_literal_wildcard_and_regex(): result = resolve_names(NAMES, ["QF1A-C01", "BPM*", "re:^QF1A-C02$"]) assert result == ["QF1A-C01", "BPM_C04-01", "BPM_C04-02", "QF1A-C02"] + + +def test_overlapping_wildcard_patterns_in_a_list_do_not_duplicate_a_match(): + names = ["BPM_01", "BPM_02", "BPM_03", "BPM_04", "BPM_05"] + result = resolve_names(names, ["BPM_0[1-3]", "BPM_0[3-5]"]) + assert result == ["BPM_01", "BPM_02", "BPM_03", "BPM_04", "BPM_05"] + + +def test_lone_exclusion_pattern_means_everything_except(): + assert resolve_names(NAMES, "~QF1A-C01") == ["BPM_C04-01", "BPM_C04-02", "QF1A-C02"] + + +def test_list_of_only_exclusion_patterns_means_everything_except(): + result = resolve_names(NAMES, ["~QF1A-C01", "~QF1A-C02"]) + assert result == ["BPM_C04-01", "BPM_C04-02"] + + +def test_exclusion_removes_matches_from_an_inclusion_pattern(): + assert resolve_names(NAMES, ["BPM*", "~BPM_C04-01"]) == ["BPM_C04-02"] + + +def test_exclusion_order_does_not_matter(): + forward = resolve_names(NAMES, ["BPM*", "~BPM_C04-01"]) + backward = resolve_names(NAMES, ["~BPM_C04-01", "BPM*"]) + assert forward == backward == ["BPM_C04-02"] + + +def test_exclusion_of_a_wildcard_pattern_removes_all_its_matches(): + result = resolve_names(NAMES, ["QF1A-C01", "QF1A-C02", "BPM_C04-01", "~QF1A-*"]) + assert result == ["BPM_C04-01"] + + +def test_exclusion_of_a_regex_pattern_removes_all_its_matches(): + result = resolve_names(NAMES, ["BPM*", "~re:^BPM_C04-01$"]) + assert result == ["BPM_C04-02"] + + +def test_exclusion_of_a_missing_literal_raises(): + with pytest.raises(PyAMLException, match="Element UNKNOWN not defined"): + resolve_names(NAMES, ["BPM*", "~UNKNOWN"]) From 4f4c0170879ce3f6fc76580d6481c6fe4fe72f2a Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Thu, 24 Sep 2026 11:09:20 +0200 Subject: [PATCH 08/16] Correction of pattern parsing --- pyaml/arrays/element_array.py | 2 +- pyaml/common/holders/element_holder.py | 13 +++----- tests/common/test_array_holder_navigation.py | 34 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/pyaml/arrays/element_array.py b/pyaml/arrays/element_array.py index 428b8e1d..f0522113 100644 --- a/pyaml/arrays/element_array.py +++ b/pyaml/arrays/element_array.py @@ -606,7 +606,7 @@ def __getitem__(self, key): r = [e for e in self if e.get_name() in matched] elif isinstance(key, str): - fields = [] if key.startswith("re:") else key.split(":") + fields = [] if key.lstrip("~").startswith("re:") else key.split(":") if len(fields) <= 1: # Selection by name pattern diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 9cf8be5d..046db388 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -346,7 +346,6 @@ def _fill_array( constructor, ARR: dict, ): - # Handle wildcard, regexp and exclusion pattern """ Resolve selectors and store a constructed element array. @@ -364,16 +363,14 @@ def _fill_array( Destination array store. """ all_names: list[str] = [] - excluded_names: list[str] = [] + excluded_names: set[str] = set() for name in element_names: if name.startswith("~"): - names = self.find_elements(name[1:]) - excluded_names.extend(names) + excluded_names.update(self.find_elements(name[1:])) else: - names = self.find_elements(name) - all_names.extend(names) + all_names.extend(self.find_elements(name)) - [all_names.remove(name) for name in excluded_names] + all_names = [n for n in all_names if n not in excluded_names] a = [] for n in all_names: @@ -382,7 +379,7 @@ def _fill_array( except Exception as err: raise PyAMLException(f"{constructor.__name__} {array_name} : {err} @index {len(a)}") from None if m in a: - raise PyAMLException(f"{constructor.__name__} {array_name} : duplicate name {name} @index {len(a)}") from None + raise PyAMLException(f"{constructor.__name__} {array_name} : duplicate name {n} @index {len(a)}") from None a.append(m) ARR[array_name] = constructor(array_name, a) diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py index 04cc2480..056df3b1 100644 --- a/tests/common/test_array_holder_navigation.py +++ b/tests/common/test_array_holder_navigation.py @@ -3,6 +3,7 @@ from pyaml.accelerator import Accelerator from pyaml.arrays.cfm_magnet_array import CombinedFunctionMagnetArray from pyaml.common.exception import PyAMLException +from pyaml.configuration.manager import ConfigurationManager @pytest.fixture @@ -130,6 +131,39 @@ def test_configured_exclusion_family_reproduced_in_a_single_getitem_call(): assert reproduced == q_for_test +def test_array_getitem_supports_a_negated_regex_pattern(): + """`~re:...` on an ElementArray excludes regex matches, same as `~wildcard`.""" + sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True) + sr.design.get_lattice().disable_6d() + + magnets = sr.design.magnets[:] + wildcard_exclusion = magnets["~QF1*"] + regex_exclusion = magnets["~re:^QF1.*$"] + + assert len(regex_exclusion) > 0 + assert len(regex_exclusion) < len(magnets) + assert regex_exclusion == wildcard_exclusion + + +def test_fill_array_supports_an_exclusion_outside_a_single_getitem_call_shape(): + """A YAML `elements:` list combining an inclusion and an exclusion builds an array, not a ValueError. + + `_fill_array` previously did its own include/exclude bookkeeping with `list.remove`, + which raised whenever the excluded name wasn't already gathered by an inclusion + pattern processed earlier in the same call. Delegating to `find_elements` (used here + with the same list, for comparison) avoids that ordering trap. + """ + manager = ConfigurationManager() + manager.add("tests/config/EBSTune-patterns.yaml") + manager.add({"arrays": [{"type": "pyaml.arrays.magnet", "name": "QD2Family", "elements": ["QD2*", "~QF1E-C05"]}]}) + sr = manager.build(ignore_external=True) + sr.design.get_lattice().disable_6d() + + qd2_family = sr.design.magnets.get("QD2Family") + + assert qd2_family.names() == sr.design.find_elements(["QD2*", "~QF1E-C05"]) + + def test_magnet_holder_getitem_exact_name_matches_get(holder): assert holder.magnet["SH1A-C01-H"] is holder.magnet.get("SH1A-C01-H") From ca492f72e864478b5e41e8a7e22a93970c97e85f Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Thu, 24 Sep 2026 15:29:05 +0200 Subject: [PATCH 09/16] Correction of pattern parsing for order and auto typing --- pyaml/common/holders/generic_element_holder.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pyaml/common/holders/generic_element_holder.py b/pyaml/common/holders/generic_element_holder.py index 101796b9..d5c404ff 100644 --- a/pyaml/common/holders/generic_element_holder.py +++ b/pyaml/common/holders/generic_element_holder.py @@ -77,22 +77,22 @@ def get(self, name: str) -> T: def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "T | ElementArray": """ - Return an element, or a selection typed as a generic ElementArray. + Return an element, or a selection typed as the most specific compatible array. Parameters ---------- key : str, list[str] or tuple[str, ...] An exact literal name returns the stored element. An fnmatch wildcard (``*``, ``?`` or ``[``), a ``re:``-prefixed regular - expression, or a list/tuple of such patterns returns an - :class:`~pyaml.arrays.element_array.ElementArray` of matches - (possibly empty). + expression, or a list/tuple of such patterns returns the most + specific compatible array of matches (possibly empty), like + :meth:`.ElementHolder.__getitem__`. Returns ------- T or ElementArray - The stored element for an exact literal name, otherwise an - ElementArray of matches. + The stored element for an exact literal name, otherwise a + typed array of matches. Raises ------ @@ -103,8 +103,9 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "T | ElementArr """ if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get(self._what, key, self._store) - names = resolve_names(self._store.keys(), key, what=self._what) - return ElementArray("", [self._store[n] for n in names]) + matched = set(resolve_names(self._store.keys(), key, what=self._what)) + elements = [v for n, v in self._store.items() if n in matched] + return ElementArray("", elements)._typed_array(elements) def add(self, m: T): """ From f576343a05d3cd594c4b247c6af47f40e0d00242 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Thu, 24 Sep 2026 15:47:59 +0200 Subject: [PATCH 10/16] Fix aggregator crash when a set operation auto-types to a CFM or serialized-magnet array --- pyaml/arrays/element_array.py | 8 +++-- tests/common/test_array_holder_navigation.py | 35 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/pyaml/arrays/element_array.py b/pyaml/arrays/element_array.py index f0522113..26c7b65b 100644 --- a/pyaml/arrays/element_array.py +++ b/pyaml/arrays/element_array.py @@ -137,13 +137,17 @@ def __create_array(self, array_name: str, element_type: type, elements: list): array_class = getattr(m, "BPMArray", None) return array_class(array_name, elements, self.__use_aggregator) elif issubclass(element_type, CombinedFunctionMagnet): + # CombinedFunctionMagnetArray has no aggregator support, unlike the + # array type this selection was derived from. m = importlib.import_module("pyaml.arrays.cfm_magnet_array") array_class = getattr(m, "CombinedFunctionMagnetArray", None) - return array_class(array_name, elements, self.__use_aggregator) + return array_class(array_name, elements, False) elif issubclass(element_type, SerializedMagnets): + # SerializedMagnetsArray has no aggregator support, unlike the + # array type this selection was derived from. m = importlib.import_module("pyaml.arrays.serialized_magnet_array") array_class = getattr(m, "SerializedMagnetsArray", None) - return array_class(array_name, elements, self.__use_aggregator) + return array_class(array_name, elements, False) elif issubclass(element_type, Element): return ElementArray(array_name, elements, self.__use_aggregator) else: diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py index 056df3b1..d76331bd 100644 --- a/tests/common/test_array_holder_navigation.py +++ b/tests/common/test_array_holder_navigation.py @@ -2,6 +2,7 @@ from pyaml.accelerator import Accelerator from pyaml.arrays.cfm_magnet_array import CombinedFunctionMagnetArray +from pyaml.arrays.magnet_array import MagnetArray from pyaml.common.exception import PyAMLException from pyaml.configuration.manager import ConfigurationManager @@ -182,6 +183,40 @@ def test_magnet_holder_getitem_wildcard_and_list_return_an_array(holder): assert listed.names() == ["SH1A-C01-H", "SH1A-C01-V"] +def test_magnet_holder_getitem_wildcard_returns_a_magnet_array(holder): + """A wildcard restricted to the .magnet store is auto-typed as MagnetArray, like the + top-level and .magnets holders, instead of falling back to a generic ElementArray.""" + wildcard = holder.magnet["SH1A-C0[12]-[HVQ]*"] + assert type(wildcard) is MagnetArray + + +def test_magnet_and_magnets_holder_getitem_agree_on_order(holder): + """.magnet (singular) and .magnets (plural) must return the same elements in the same + order for the same name list, regardless of the order the names were requested in. The + reference order is the configuration order, not the order of the requested names.""" + forward = holder.magnet[["SH1A-C01-H", "SH1A-C01-V"]] + backward = holder.magnet[["SH1A-C01-V", "SH1A-C01-H"]] + assert forward.names() == backward.names() == ["SH1A-C01-H", "SH1A-C01-V"] + + forward_plural = holder.magnets[["SH1A-C01-H", "SH1A-C01-V"]] + backward_plural = holder.magnets[["SH1A-C01-V", "SH1A-C01-H"]] + assert forward_plural.names() == backward_plural.names() == forward.names() + + +def test_subtracting_a_magnet_selection_from_a_mixed_selection_yields_a_cfm_array(holder): + """A top-level selection mixing CombinedFunctionMagnet and their virtual correctors, minus + the corrector-only .magnets selection, must yield the CFMs alone as a + CombinedFunctionMagnetArray. Regression test: this used to raise 'Aggregator not + implemented for CombinedFunctionMagnetArray' because the derived array blindly inherited + the use_aggregator flag of the ElementArray it was built from.""" + mixed = holder["SH*"] + only_magnets = holder.magnets["SH*"] + only_cfm = mixed - only_magnets + + assert type(only_cfm) is CombinedFunctionMagnetArray + assert only_cfm.names() == ["SH1A-C01", "SH1A-C02"] + + def test_magnet_holder_getitem_regex(holder): matching = holder.magnet["re:^SH1A-C0[12]-H$"] assert sorted(matching.names()) == ["SH1A-C01-H", "SH1A-C02-H"] From 279fea065db2ed2072eaf88c284513eb1778452a Mon Sep 17 00:00:00 2001 From: Alexis Gamelin Date: Thu, 24 Sep 2026 17:01:14 +0200 Subject: [PATCH 11/16] Add a test for array order --- tests/common/test_array_holder_navigation.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py index d76331bd..e28ca14d 100644 --- a/tests/common/test_array_holder_navigation.py +++ b/tests/common/test_array_holder_navigation.py @@ -203,6 +203,26 @@ def test_magnet_and_magnets_holder_getitem_agree_on_order(holder): assert forward_plural.names() == backward_plural.names() == forward.names() +@pytest.mark.parametrize( + "select", + [ + pytest.param(lambda h, k: h[k].names(), id="holder[]"), + pytest.param(lambda h, k: h.find_elements(k), id="holder.find_elements"), + pytest.param(lambda h, k: h.get()[k].names(), id="holder.get()[]"), + pytest.param(lambda h, k: h.magnet[k].names(), id="holder.magnet[]"), + pytest.param(lambda h, k: h.magnets[k].names(), id="holder.magnets[]"), + ], +) +@pytest.mark.parametrize("reverse", [False, True], ids=["forward", "reversed"]) +def test_every_accessor_returns_a_list_selection_in_configuration_order(holder, select, reverse): + """Every name-based accessor must return a list-of-patterns selection in configuration + order, whatever the order of the requested names, so that positional values line up the + same way whichever accessor built the array.""" + key = ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"] + expected = [n for n in holder.get().names() if n in key] + assert select(holder, key[::-1] if reverse else key) == expected + + def test_subtracting_a_magnet_selection_from_a_mixed_selection_yields_a_cfm_array(holder): """A top-level selection mixing CombinedFunctionMagnet and their virtual correctors, minus the corrector-only .magnets selection, must yield the CFMs alone as a From db35db7e2718161e09610f4afe9e500c2faa2a89 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Mon, 28 Sep 2026 11:42:19 +0200 Subject: [PATCH 12/16] Normalize list-selection order to configuration order across every holder --- pyaml/common/holders/diagnostic_holder.py | 4 +- pyaml/common/holders/element_holder.py | 11 +-- pyaml/common/holders/rf_holder.py | 8 +-- pyaml/common/holders/tool_holder.py | 4 +- tests/common/test_array_holder_navigation.py | 71 ++++++++++++++++--- .../common/test_element_holder_collection.py | 12 ++-- .../diagnostics/test_diagnostic_accessors.py | 23 ++++++ tests/rf/test_rf_holder.py | 27 +++++++ tests/tuning_tools/test_tool_holder.py | 9 +++ 9 files changed, 142 insertions(+), 27 deletions(-) diff --git a/pyaml/common/holders/diagnostic_holder.py b/pyaml/common/holders/diagnostic_holder.py index 588b74c7..b78eefbf 100644 --- a/pyaml/common/holders/diagnostic_holder.py +++ b/pyaml/common/holders/diagnostic_holder.py @@ -124,8 +124,8 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | Elem store = self._peer._DIAG if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get_diagnostic(key) - names = resolve_names(store.keys(), key, what="Diagnostic") - return ElementArray("", [store[n] for n in names]) + matched = set(resolve_names(store.keys(), key, what="Diagnostic")) + return ElementArray("", [v for n, v in store.items() if n in matched]) @property def betatron_tune(self) -> BetatronTuneMonitor: diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 046db388..5eed50c3 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -336,7 +336,8 @@ def find_elements(self, filter: str | list[str] | tuple[str, ...]) -> list[str]: If a literal pattern (or a ``~``-prefixed literal) matches no element, or a ``re:`` pattern is not a valid regular expression. """ - return resolve_names(self._ALL.keys(), filter, what="Element") + matched = set(resolve_names(self._ALL.keys(), filter, what="Element")) + return [n for n in self._ALL if n in matched] def _fill_array( self, @@ -518,14 +519,14 @@ def __getitem__(self, key: int | slice | str | list[str] | tuple[str, ...]) -> E """ if isinstance(key, str): if key.startswith("re:") or key.startswith("~") or is_wildcard(key): - names = resolve_names(self._ALL.keys(), key) - return self.get()._typed_array([self._ALL[n] for n in names]) + matched = set(resolve_names(self._ALL.keys(), key)) + return self.get()._typed_array([v for n, v in self._ALL.items() if n in matched]) if key not in self._ALL: raise PyAMLException(f"Element {key} not defined") return self._ALL[key] if isinstance(key, (list, tuple)): - names = resolve_names(self._ALL.keys(), key) - return self.get()._typed_array([self._ALL[n] for n in names]) + matched = set(resolve_names(self._ALL.keys(), key)) + return self.get()._typed_array([v for n, v in self._ALL.items() if n in matched]) if isinstance(key, int): return list(self._ALL.values())[key] if isinstance(key, slice): diff --git a/pyaml/common/holders/rf_holder.py b/pyaml/common/holders/rf_holder.py index 8b81d7c9..43c07028 100644 --- a/pyaml/common/holders/rf_holder.py +++ b/pyaml/common/holders/rf_holder.py @@ -80,8 +80,8 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFTransmitter store = self._peer._RFTRANSMITTER if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get("RFTransmitter", key, store) - names = resolve_names(store.keys(), key, what="RFTransmitter") - return ElementArray("", [store[n] for n in names]) + matched = set(resolve_names(store.keys(), key, what="RFTransmitter")) + return ElementArray("", [v for n, v in store.items() if n in matched]) def add(self, rf: RFTransmitter): """ @@ -195,8 +195,8 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFPlant | Elem store = self._peer._RFPLANT if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get("RFPlant", key, store) - names = resolve_names(store.keys(), key, what="RFPlant") - return ElementArray("", [store[n] for n in names]) + matched = set(resolve_names(store.keys(), key, what="RFPlant")) + return ElementArray("", [v for n, v in store.items() if n in matched]) def add(self, rf: RFPlant): """ diff --git a/pyaml/common/holders/tool_holder.py b/pyaml/common/holders/tool_holder.py index d02c044b..2ac49e86 100644 --- a/pyaml/common/holders/tool_holder.py +++ b/pyaml/common/holders/tool_holder.py @@ -115,8 +115,8 @@ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | Elem store = self._peer._TOOLS if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key): return self._peer._get_tool(key) - names = resolve_names(store.keys(), key, what="Tool") - return ElementArray("", [store[n] for n in names]) + matched = set(resolve_names(store.keys(), key, what="Tool")) + return ElementArray("", [v for n, v in store.items() if n in matched]) def _validate_type(self, name: str, obj: Element, expected_type: type) -> Element: """ diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py index e28ca14d..8bd0d2a9 100644 --- a/tests/common/test_array_holder_navigation.py +++ b/tests/common/test_array_holder_navigation.py @@ -116,11 +116,17 @@ def test_configured_exclusion_family_reproduced_with_selection_and_difference(): def test_configured_exclusion_family_reproduced_in_a_single_getitem_call(): - """The YAML `elements:` selector list (`[QD2*, QF1*, ~QF1E-C05, ~Q???-C06]`) works verbatim through `[]`. + """The YAML `elements:` selector list (`[QD2*, QF1*, ~QF1E-C05, ~Q???-C06]`) selects the + same *family* of elements through `[]` as declared for `QForTest`. Selection goes through the top-level holder, not `.magnets`, so it resolves patterns against the same global element pool `find_elements()`/`_fill_array` use to build - `QForTest` in the YAML, and so lands in the same order. + `QForTest` in the YAML. The two therefore agree on *which* elements are selected, but not + necessarily on their order: `_fill_array` concatenates matches pattern by pattern (all + `QD2*` matches, then all `QF1*` matches) to build the named array, while `[]` (like every + other list-selection accessor, see `test_every_accessor_returns_a_list_selection_in_configuration_order`) + normalizes its result to configuration order regardless of how many patterns were + involved or in what order they matched. """ sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True) sr.design.get_lattice().disable_6d() @@ -129,7 +135,8 @@ def test_configured_exclusion_family_reproduced_in_a_single_getitem_call(): reproduced = sr.design[["QD2*", "QF1*", "~QF1E-C05", "~Q???-C06"]] assert type(reproduced) is type(q_for_test) - assert reproduced == q_for_test + assert set(reproduced.names()) == set(q_for_test.names()) + assert reproduced.names() == [n for n in sr.design.get().names() if n in set(q_for_test.names())] def test_array_getitem_supports_a_negated_regex_pattern(): @@ -193,7 +200,9 @@ def test_magnet_holder_getitem_wildcard_returns_a_magnet_array(holder): def test_magnet_and_magnets_holder_getitem_agree_on_order(holder): """.magnet (singular) and .magnets (plural) must return the same elements in the same order for the same name list, regardless of the order the names were requested in. The - reference order is the configuration order, not the order of the requested names.""" + reference order is the configuration order, not the order of the requested names. This + must also hold for the top-level holder itself (`[]` and `find_elements`), not just its + typed sub-holders.""" forward = holder.magnet[["SH1A-C01-H", "SH1A-C01-V"]] backward = holder.magnet[["SH1A-C01-V", "SH1A-C01-H"]] assert forward.names() == backward.names() == ["SH1A-C01-H", "SH1A-C01-V"] @@ -202,6 +211,33 @@ def test_magnet_and_magnets_holder_getitem_agree_on_order(holder): backward_plural = holder.magnets[["SH1A-C01-V", "SH1A-C01-H"]] assert forward_plural.names() == backward_plural.names() == forward.names() + forward_top_level = holder[["SH1A-C01-H", "SH1A-C01-V"]] + backward_top_level = holder[["SH1A-C01-V", "SH1A-C01-H"]] + assert forward_top_level.names() == backward_top_level.names() == forward.names() + + assert holder.find_elements(["SH1A-C01-H", "SH1A-C01-V"]) == forward.names() + assert holder.find_elements(["SH1A-C01-V", "SH1A-C01-H"]) == forward.names() + + +def test_combined_function_magnet_and_bpm_holders_return_list_selections_in_configuration_order(holder): + """Every typed sub-holder must normalize list selections to configuration order, not just + .magnet/.magnets: this must also hold for .combined_function_magnet(s) and .bpm(s).""" + cfm_forward = holder.combined_function_magnet[["SH1A-C01", "SH1A-C02"]] + cfm_backward = holder.combined_function_magnet[["SH1A-C02", "SH1A-C01"]] + assert cfm_forward.names() == cfm_backward.names() == ["SH1A-C01", "SH1A-C02"] + + cfm_forward_plural = holder.combined_function_magnets[["SH1A-C01", "SH1A-C02"]] + cfm_backward_plural = holder.combined_function_magnets[["SH1A-C02", "SH1A-C01"]] + assert cfm_forward_plural.names() == cfm_backward_plural.names() == cfm_forward.names() + + bpm_forward = holder.diagnostic.bpm[["BPM_C04-01", "BPM_C04-02"]] + bpm_backward = holder.diagnostic.bpm[["BPM_C04-02", "BPM_C04-01"]] + assert bpm_forward.names() == bpm_backward.names() == ["BPM_C04-01", "BPM_C04-02"] + + bpm_forward_plural = holder.diagnostic.bpms[["BPM_C04-01", "BPM_C04-02"]] + bpm_backward_plural = holder.diagnostic.bpms[["BPM_C04-02", "BPM_C04-01"]] + assert bpm_forward_plural.names() == bpm_backward_plural.names() == bpm_forward.names() + @pytest.mark.parametrize( "select", @@ -214,12 +250,29 @@ def test_magnet_and_magnets_holder_getitem_agree_on_order(holder): ], ) @pytest.mark.parametrize("reverse", [False, True], ids=["forward", "reversed"]) -def test_every_accessor_returns_a_list_selection_in_configuration_order(holder, select, reverse): +@pytest.mark.parametrize( + "key, expected_members", + [ + pytest.param( + ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"], + {"SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"}, + id="literal-names", + ), + pytest.param( + ["SH1A-C0?-H", "SH1A-C01-V"], + {"SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V"}, + id="wildcard-and-literal", + ), + ], +) +def test_every_accessor_returns_a_list_selection_in_configuration_order(holder, select, reverse, key, expected_members): """Every name-based accessor must return a list-of-patterns selection in configuration - order, whatever the order of the requested names, so that positional values line up the - same way whichever accessor built the array.""" - key = ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"] - expected = [n for n in holder.get().names() if n in key] + order, whatever the order of the requested names/patterns, so that positional values line + up the same way whichever accessor built the array. This must hold both for a list of + literal names and for a list mixing a wildcard (matching several names) with a literal + name, since a wildcard entry is where a naive pattern-order passthrough diverges from + configuration order the most visibly.""" + expected = [n for n in holder.get().names() if n in expected_members] assert select(holder, key[::-1] if reverse else key) == expected diff --git a/tests/common/test_element_holder_collection.py b/tests/common/test_element_holder_collection.py index c6c889d5..3fdfc88d 100644 --- a/tests/common/test_element_holder_collection.py +++ b/tests/common/test_element_holder_collection.py @@ -226,8 +226,9 @@ def test_invalid_regex_raises_pyaml_exception(holder): def test_list_of_patterns_unions_results(holder): + """Order follows configuration (registration) order, not the order patterns were requested in.""" selected = holder[["BPM_C04-01", "SH1A-C0?-H"]] - assert selected.names() == ["BPM_C04-01", "SH1A-C01-H", "SH1A-C02-H"] + assert selected.names() == ["SH1A-C01-H", "SH1A-C02-H", "BPM_C04-01"] def test_list_of_patterns_with_missing_literal_raises(holder): @@ -253,20 +254,21 @@ def test_find_elements_supports_regex(holder): def test_find_elements_supports_a_list_of_patterns(holder): - assert holder.find_elements(["BPM_C04-01", "SH1A-C0?-H"]) == ["BPM_C04-01", "SH1A-C01-H", "SH1A-C02-H"] + """Order follows configuration (registration) order, not the order patterns were requested in.""" + assert holder.find_elements(["BPM_C04-01", "SH1A-C0?-H"]) == ["SH1A-C01-H", "SH1A-C02-H", "BPM_C04-01"] def test_find_elements_supports_an_exclusion_in_a_list(holder): both_planes = holder.find_elements(["SH1A-C0?-H", "SH1A-C0?-V"]) - assert both_planes == ["SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V", "SH1A-C02-V"] + assert both_planes == ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H", "SH1A-C02-V"] minus_one = holder.find_elements(["SH1A-C0?-H", "SH1A-C0?-V", "~SH1A-C02-V"]) - assert minus_one == ["SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V"] + assert minus_one == ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"] def test_getitem_supports_an_exclusion_in_a_list(holder): selected = holder[["SH1A-C0?-H", "SH1A-C0?-V", "~SH1A-C02-V"]] - assert selected.names() == ["SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V"] + assert selected.names() == ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"] def test_getitem_lone_exclusion_pattern_means_everything_except(holder): diff --git a/tests/diagnostics/test_diagnostic_accessors.py b/tests/diagnostics/test_diagnostic_accessors.py index 342c04dd..2acdb9c3 100644 --- a/tests/diagnostics/test_diagnostic_accessors.py +++ b/tests/diagnostics/test_diagnostic_accessors.py @@ -1,3 +1,5 @@ +import copy + import pytest from pyaml.accelerator import Accelerator @@ -114,6 +116,27 @@ def test_diagnostic_getitem_wildcard_returns_an_array(): assert design.diagnostic["MISSING*"].names() == [] +def test_diagnostic_getitem_list_selection_ignores_request_order(): + """A list-of-patterns selection lands in configuration order, whatever order the names + were requested in, same as every other holder (see + test_every_accessor_returns_a_list_selection_in_configuration_order). Only one diagnostic + is registered by any existing fixture, so a distinct second entry is poked directly into + the store (a renamed copy of the existing monitor) to make request order and + configuration order observably different.""" + design = Accelerator.load( + "tests/config/EBSOrbit.yaml", + ignore_external=True, + include_locations=False, + ).design + spare_monitor = copy.copy(design.get_betatron_tune_monitor("BETATRON_TUNE")) + spare_monitor._name = "SPARE_BETATRON_TUNE" + design._DIAG["SPARE_BETATRON_TUNE"] = spare_monitor + + forward = design.diagnostic[["BETATRON_TUNE", "SPARE_BETATRON_TUNE"]] + backward = design.diagnostic[["SPARE_BETATRON_TUNE", "BETATRON_TUNE"]] + assert forward.names() == backward.names() == ["BETATRON_TUNE", "SPARE_BETATRON_TUNE"] + + def test_diagnostic_bpm_getitem_exact_name_matches_get(): design = Accelerator.load( "tests/config/EBSOrbit.yaml", diff --git a/tests/rf/test_rf_holder.py b/tests/rf/test_rf_holder.py index 784577a8..b1839ea8 100644 --- a/tests/rf/test_rf_holder.py +++ b/tests/rf/test_rf_holder.py @@ -1,3 +1,5 @@ +import copy + import pytest from pyaml.accelerator import Accelerator @@ -43,6 +45,31 @@ def test_rf_transmitter_holder_getitem_list_of_patterns(design): assert selected.names() == ["RFTRA1", "RFTRA2"] +def test_rf_transmitter_holder_getitem_list_selection_ignores_request_order(design): + """A list-of-patterns selection lands in configuration order, whatever order the names + were requested in, same as every other holder (see + test_every_accessor_returns_a_list_selection_in_configuration_order).""" + forward = design.rf.transmitter[["RFTRA1", "RFTRA2"]] + backward = design.rf.transmitter[["RFTRA2", "RFTRA1"]] + assert forward.names() == backward.names() == ["RFTRA1", "RFTRA2"] + + +def test_rf_holder_getitem_list_selection_ignores_request_order(design): + """Same configuration-order guarantee as the RF transmitter holder, at the RF plant level. + + Only one RF plant is registered by this fixture, so a distinct second entry is poked + directly into the store (a renamed copy of the existing plant) to make request order and + configuration order observably different. + """ + spare_plant = copy.copy(design.rf.get("DEFAULT_RF_PLANT")) + spare_plant._name = "SPARE_RF_PLANT" + design._RFPLANT["SPARE_RF_PLANT"] = spare_plant + + forward = design.rf[["DEFAULT_RF_PLANT", "SPARE_RF_PLANT"]] + backward = design.rf[["SPARE_RF_PLANT", "DEFAULT_RF_PLANT"]] + assert forward.names() == backward.names() == ["DEFAULT_RF_PLANT", "SPARE_RF_PLANT"] + + def test_rf_transmitter_holder_getitem_regex(design): matching = design.rf.transmitter["re:^RFTRA[12]$"] assert sorted(matching.names()) == ["RFTRA1", "RFTRA2"] diff --git a/tests/tuning_tools/test_tool_holder.py b/tests/tuning_tools/test_tool_holder.py index 3821fcf3..cd921940 100644 --- a/tests/tuning_tools/test_tool_holder.py +++ b/tests/tuning_tools/test_tool_holder.py @@ -33,6 +33,15 @@ def test_tool_holder_getitem_list_of_patterns(design): assert selected.names() == ["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"] +def test_tool_holder_getitem_list_selection_ignores_request_order(design): + """A list-of-patterns selection lands in configuration order, whatever order the names + were requested in, same as every other holder (see + test_every_accessor_returns_a_list_selection_in_configuration_order).""" + forward = design.tool[["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"]] + backward = design.tool[["DEFAULT_ORBIT_CORRECTION", "DEFAULT_TUNE_CORRECTION"]] + assert forward.names() == backward.names() == ["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"] + + def test_tool_holder_getitem_regex(design): matching = design.tool["re:^DEFAULT_(TUNE|ORBIT)_CORRECTION$"] assert sorted(matching.names()) == ["DEFAULT_ORBIT_CORRECTION", "DEFAULT_TUNE_CORRECTION"] From e1fa68795f956ede7bbd52b369e466780d30ef62 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Mon, 28 Sep 2026 16:53:23 +0200 Subject: [PATCH 13/16] Remove ElementHolder backward-compatible tool aliases per review --- .../other_examples/ORM_Tango_server/ORM.py | 4 +- examples/use_cases/01-tune_correction.ipynb | 207 +----------------- examples/use_cases/01-tune_correction.py | 28 +-- examples/use_cases/03-orbit_correction.ipynb | 190 +--------------- examples/use_cases/03-orbit_correction.py | 32 +-- examples/use_cases/README.md | 10 +- pyaml/common/holders/element_holder.py | 40 ---- pyaml/common/holders/tool_holder.py | 20 +- .../chromaticity_response_matrix.py | 8 +- pyaml/tuning_tools/measurement_tool.py | 2 +- pyaml/tuning_tools/orbit_response_matrix.py | 8 +- pyaml/tuning_tools/tune_response_matrix.py | 8 +- .../diagnostics/test_diagnostic_accessors.py | 2 +- tests/tuning_tools/test_tool_accessors.py | 74 +++---- tests/tuning_tools/test_tuning_dispersion.py | 2 +- .../test_tuning_orbit_correction.py | 58 ++--- tests/tuning_tools/test_tuning_orm.py | 4 +- tests/tuning_tools/test_tuning_tools.py | 24 +- 18 files changed, 152 insertions(+), 569 deletions(-) diff --git a/examples/other_examples/ORM_Tango_server/ORM.py b/examples/other_examples/ORM_Tango_server/ORM.py index 186476af..fe686076 100644 --- a/examples/other_examples/ORM_Tango_server/ORM.py +++ b/examples/other_examples/ORM_Tango_server/ORM.py @@ -102,8 +102,8 @@ def orbit_callback(self, action: int, cdata): def orm_run(self): # On design sleep 10ms to allow thread schedule - self.SR.design.orm.measure(callback=orbit_callback, sleep_between_meas=0.01) - self.orm_data = self.SR.design.orm.get() + self.SR.design.tool.orm.measure(callback=orbit_callback, sleep_between_meas=0.01) + self.orm_data = self.SR.design.tool.orm.get() self.set_status(f"Ready to scan: {self.ConfigFileName}") self.set_state(DevState.ON) diff --git a/examples/use_cases/01-tune_correction.ipynb b/examples/use_cases/01-tune_correction.ipynb index dfba75bb..cf6e3471 100644 --- a/examples/use_cases/01-tune_correction.ipynb +++ b/examples/use_cases/01-tune_correction.ipynb @@ -282,83 +282,15 @@ "cell_type": "markdown", "id": "04431246", "metadata": {}, - "source": [ - "### Standard tune correction tool\n", - "\n", - "`SR.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool.\n", - "\n", - "Before correcting the tune you need a response matrix. It can be measured (below) or loaded from a previously saved file." - ] + "source": "### Standard tune correction tool\n\n`SR.tool.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.tool.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool.\n\nBefore correcting the tune you need a response matrix. It can be measured (below) or loaded from a previously saved file." }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "5c57ef30", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Tune(quad_array_name='QForTune', betatron_tune_name='BETATRON_TUNE', response_matrix=array([[ 0.17853128, 0.17890919, 0.17917984, 0.17843061, 0.17932054,\n", - " 0.17884878, 0.1786898 , 0.17950221, 0.17836418, 0.1790288 ,\n", - " 0.17907229, 0.17845344, 0.17936885, 0.1787317 , 0.17880339,\n", - " 0.1793422 , 0.17843576, 0.17914062, 0.17895506, 0.17850485,\n", - " 0.15843663, 0.1575313 , 0.15237977, 0.15250702, 0.17830408,\n", - " 0.17955648, 0.1784584 , 0.17880469, 0.17936621, 0.17824945,\n", - " 0.17941811, 0.17905372, 0.17841113, 0.17957284, 0.17835113,\n", - " 0.17897118, 0.17923226, 0.17825399, 0.17950825, 0.17876573,\n", - " 0.17866201, 0.17954684, 0.17827911, 0.17925585, 0.17897151,\n", - " 0.17830041, 0.17956082, 0.17873061, 0.17871689, 0.17948152,\n", - " 0.15577439, 0.15662709, 0.178933 , 0.17847488, 0.17937198,\n", - " 0.17881763, 0.17874021, 0.17931638, 0.17843723, 0.17929549,\n", - " 0.17880609, 0.17853484, 0.59082023, 0.59180433, 0.59274339,\n", - " 0.59079241, 0.59387998, 0.59265135, 0.59209988, 0.59391444,\n", - " 0.59072413, 0.59219559, 0.59234655, 0.59073497, 0.59391106,\n", - " 0.59225191, 0.59250056, 0.59390362, 0.59075881, 0.59259427,\n", - " 0.5919504 , 0.59077803, 0.52411485, 0.52163044, 0.50248335,\n", - " 0.50266086, 0.59115919, 0.59419444, 0.59038465, 0.59128648,\n", - " 0.59323464, 0.59032653, 0.59438116, 0.59313174, 0.59165988,\n", - " 0.5944257 , 0.59018699, 0.59180163, 0.59270748, 0.59015999,\n", - " 0.59451179, 0.5925782 , 0.59221837, 0.59452251, 0.59012406,\n", - " 0.59236712, 0.59213945, 0.59013148, 0.59450445, 0.59204248,\n", - " 0.59275305, 0.59448392, 0.51467256, 0.51681741, 0.59219055,\n", - " 0.59076114, 0.59387372, 0.59213029, 0.59261978, 0.59385979,\n", - " 0.59080955, 0.59274399, 0.59180476, 0.59083819],\n", - " [-1.26055967, -1.26031469, -1.2598023 , -1.26083158, -1.25981216,\n", - " -1.26160634, -1.26143231, -1.25920552, -1.26001143, -1.26105243,\n", - " -1.26026455, -1.26115601, -1.26145837, -1.25972946, -1.26035568,\n", - " -1.26035017, -1.25972691, -1.26145864, -1.2611518 , -1.26026992,\n", - " -1.28718859, -1.28580227, -1.29551207, -1.29591315, -1.26023455,\n", - " -1.26119118, -1.2611013 , -1.26019174, -1.26077014, -1.26007772,\n", - " -1.25987122, -1.260857 , -1.2609502 , -1.26075456, -1.26134921,\n", - " -1.25965397, -1.25996982, -1.26071455, -1.25976978, -1.26108183,\n", - " -1.26034272, -1.26107775, -1.26118967, -1.25922595, -1.25959951,\n", - " -1.26157551, -1.26072113, -1.26058879, -1.26193197, -1.25939288,\n", - " -1.28878699, -1.28913722, -1.26030408, -1.26116608, -1.26092241,\n", - " -1.25960761, -1.2599948 , -1.26128422, -1.26055622, -1.26012439,\n", - " -1.26052166, -1.2609009 , -0.49429912, -0.49420118, -0.49402884,\n", - " -0.49444032, -0.49392715, -0.49464442, -0.49464248, -0.49384803,\n", - " -0.4940031 , -0.49450349, -0.49410766, -0.49446404, -0.49461625,\n", - " -0.49392508, -0.49424032, -0.49423811, -0.49392437, -0.49461667,\n", - " -0.4944622 , -0.49410966, -0.49580432, -0.4952599 , -0.49584758,\n", - " -0.49606291, -0.49405329, -0.49450455, -0.4944593 , -0.49409569,\n", - " -0.49438685, -0.49411004, -0.49400608, -0.49449611, -0.4942921 ,\n", - " -0.49429813, -0.49459747, -0.49391976, -0.49407876, -0.49437648,\n", - " -0.49398646, -0.49451098, -0.49413892, -0.49443276, -0.49457543,\n", - " -0.49388618, -0.49382348, -0.49469773, -0.49426765, -0.49431067,\n", - " -0.49473566, -0.49380506, -0.49553592, -0.49574219, -0.49407224,\n", - " -0.4944902 , -0.4944531 , -0.49402325, -0.49396739, -0.49456722,\n", - " -0.49428634, -0.49420954, -0.49415863, -0.49439461]]), _tm=BetatronTuneMonitor(tune_h='srdiag/beam-tune/main/Qh', tune_v='srdiag/beam-tune/main/Qv', name='BETATRON_TUNE'), _quads=[Quadrupole(peer='Simulator:design', name='QD2E-C04', model_name='QD2E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C05', model_name='QD2A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C05', model_name='QD2E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C06', model_name='QD2A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C06', model_name='QD2E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C07', model_name='QD2A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C07', model_name='QD2E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C08', model_name='QD2A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C08', model_name='QD2E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C09', model_name='QD2A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C09', model_name='QD2E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C10', model_name='QD2A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C10', model_name='QD2E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C11', model_name='QD2A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C11', model_name='QD2E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C12', model_name='QD2A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C12', model_name='QD2E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C13', model_name='QD2A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C13', model_name='QD2E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C14', model_name='QD2A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C14', model_name='QD2E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C15', model_name='QD2A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C15', model_name='QD2E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C16', model_name='QD2A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C16', model_name='QD2E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C17', model_name='QD2A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C17', model_name='QD2E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C18', model_name='QD2A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C18', model_name='QD2E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C19', model_name='QD2A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C19', model_name='QD2E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C20', model_name='QD2A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C20', model_name='QD2E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C21', model_name='QD2A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C21', model_name='QD2E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C22', model_name='QD2A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C22', model_name='QD2E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C23', model_name='QD2A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C23', model_name='QD2E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C24', model_name='QD2A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C24', model_name='QD2E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C25', model_name='QD2A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C25', model_name='QD2E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C26', model_name='QD2A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C26', model_name='QD2E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C27', model_name='QD2A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C27', model_name='QD2E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C28', model_name='QD2A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C28', model_name='QD2E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C29', model_name='QD2A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C29', model_name='QD2E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C30', model_name='QD2A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C30', model_name='QD2E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C31', model_name='QD2A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C31', model_name='QD2E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C32', model_name='QD2A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C32', model_name='QD2E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C01', model_name='QD2A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C01', model_name='QD2E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C02', model_name='QD2A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C02', model_name='QD2E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C03', model_name='QD2A-C03', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C04', model_name='QF1E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C05', model_name='QF1A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C05', model_name='QF1E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C06', model_name='QF1A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C06', model_name='QF1E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C07', model_name='QF1A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C07', model_name='QF1E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C08', model_name='QF1A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C08', model_name='QF1E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C09', model_name='QF1A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C09', model_name='QF1E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C10', model_name='QF1A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C10', model_name='QF1E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C11', model_name='QF1A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C11', model_name='QF1E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C12', model_name='QF1A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C12', model_name='QF1E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C13', model_name='QF1A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C13', model_name='QF1E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C14', model_name='QF1A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C14', model_name='QF1E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C15', model_name='QF1A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C15', model_name='QF1E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C16', model_name='QF1A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C16', model_name='QF1E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C17', model_name='QF1A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C17', model_name='QF1E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C18', model_name='QF1A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C18', model_name='QF1E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C19', model_name='QF1A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C19', model_name='QF1E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C20', model_name='QF1A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C20', model_name='QF1E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C21', model_name='QF1A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C21', model_name='QF1E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C22', model_name='QF1A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C22', model_name='QF1E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C23', model_name='QF1A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C23', model_name='QF1E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C24', model_name='QF1A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C24', model_name='QF1E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C25', model_name='QF1A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C25', model_name='QF1E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C26', model_name='QF1A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C26', model_name='QF1E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C27', model_name='QF1A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C27', model_name='QF1E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C28', model_name='QF1A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C28', model_name='QF1E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C29', model_name='QF1A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C29', model_name='QF1E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C30', model_name='QF1A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C30', model_name='QF1E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C31', model_name='QF1A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C31', model_name='QF1E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C32', model_name='QF1A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C32', model_name='QF1E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C01', model_name='QF1A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C01', model_name='QF1E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C02', model_name='QF1A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C02', model_name='QF1E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C03', model_name='QF1A-C03', magnet_model=LinearMagnetModel)], name='DEFAULT_TUNE_CORRECTION')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "SR.tune # string representation" - ] + "outputs": [], + "source": "SR.tool.tune # string representation" }, { "cell_type": "markdown", @@ -391,142 +323,25 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "c81cdb05", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Response matrix loaded.\n" - ] - }, - { - "data": { - "text/plain": [ - "TuneResponseMatrix(quad_array_name='QForTune', betatron_tune_name='BETATRON_TUNE', quad_delta=0.0001, n_step=1, sleep_between_step=0.0, n_avg_meas=1, sleep_between_meas=0.0, name='DEFAULT_TUNE_RESPONSE_MATRIX')" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "if SR.tune.response_matrix is None:\n", - " SR.trm.measure(sleep_between_step=wait_time, callback=tune_callback)\n", - " SR.trm.save(CONFIG_DIR / \"trm.json\")\n", - "\n", - "SR.tune.load(CONFIG_DIR / \"trm.json\")\n", - "print(\"Response matrix loaded.\")\n", - "SR.trm # string representation" - ] + "outputs": [], + "source": "if SR.tool.tune.response_matrix is None:\n SR.tool.trm.measure(sleep_between_step=wait_time, callback=tune_callback)\n SR.tool.trm.save(CONFIG_DIR / \"trm.json\")\n\nSR.tool.tune.load(CONFIG_DIR / \"trm.json\")\nprint(\"Response matrix loaded.\")\nSR.tool.trm # string representation" }, { "cell_type": "markdown", "id": "ef7d7ce4", "metadata": {}, - "source": [ - "#### Correcting the tune\n", - "\n", - "`SR.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls the number of iterations and `wait_time` the settling time between each iteration." - ] + "source": "#### Correcting the tune\n\n`SR.tool.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls the number of iterations and `wait_time` the settling time between each iteration." }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "6b8bcf91", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tune before correction: [0.16000001 0.33999986]\n", - "\n", - "Setting tune to [0.19, 0.28]\n", - "Tune after correction: [0.19 0.28]\n", - "\n", - "Setting tune to [0.21, 0.3]\n", - "Tune after correction: [0.21 0.3 ]\n" - ] - }, - { - "data": { - "text/plain": [ - "Tune(quad_array_name='QForTune', betatron_tune_name='BETATRON_TUNE', response_matrix=array([[ 0.17853128, 0.17890919, 0.17917984, 0.17843061, 0.17932054,\n", - " 0.17884878, 0.1786898 , 0.17950221, 0.17836418, 0.1790288 ,\n", - " 0.17907229, 0.17845344, 0.17936885, 0.1787317 , 0.17880339,\n", - " 0.1793422 , 0.17843576, 0.17914062, 0.17895506, 0.17850485,\n", - " 0.15843663, 0.1575313 , 0.15237977, 0.15250702, 0.17830408,\n", - " 0.17955648, 0.1784584 , 0.17880469, 0.17936621, 0.17824945,\n", - " 0.17941811, 0.17905372, 0.17841113, 0.17957284, 0.17835113,\n", - " 0.17897118, 0.17923226, 0.17825399, 0.17950825, 0.17876573,\n", - " 0.17866201, 0.17954684, 0.17827911, 0.17925585, 0.17897151,\n", - " 0.17830041, 0.17956082, 0.17873061, 0.17871689, 0.17948152,\n", - " 0.15577439, 0.15662709, 0.178933 , 0.17847488, 0.17937198,\n", - " 0.17881763, 0.17874021, 0.17931638, 0.17843723, 0.17929549,\n", - " 0.17880609, 0.17853484, 0.59082023, 0.59180433, 0.59274339,\n", - " 0.59079241, 0.59387998, 0.59265135, 0.59209988, 0.59391444,\n", - " 0.59072413, 0.59219559, 0.59234655, 0.59073497, 0.59391106,\n", - " 0.59225191, 0.59250056, 0.59390362, 0.59075881, 0.59259427,\n", - " 0.5919504 , 0.59077803, 0.52411485, 0.52163044, 0.50248335,\n", - " 0.50266086, 0.59115919, 0.59419444, 0.59038465, 0.59128648,\n", - " 0.59323464, 0.59032653, 0.59438116, 0.59313174, 0.59165988,\n", - " 0.5944257 , 0.59018699, 0.59180163, 0.59270748, 0.59015999,\n", - " 0.59451179, 0.5925782 , 0.59221837, 0.59452251, 0.59012406,\n", - " 0.59236712, 0.59213945, 0.59013148, 0.59450445, 0.59204248,\n", - " 0.59275305, 0.59448392, 0.51467256, 0.51681741, 0.59219055,\n", - " 0.59076114, 0.59387372, 0.59213029, 0.59261978, 0.59385979,\n", - " 0.59080955, 0.59274399, 0.59180476, 0.59083819],\n", - " [-1.26055967, -1.26031469, -1.2598023 , -1.26083158, -1.25981216,\n", - " -1.26160634, -1.26143231, -1.25920552, -1.26001143, -1.26105243,\n", - " -1.26026455, -1.26115601, -1.26145837, -1.25972946, -1.26035568,\n", - " -1.26035017, -1.25972691, -1.26145864, -1.2611518 , -1.26026992,\n", - " -1.28718859, -1.28580227, -1.29551207, -1.29591315, -1.26023455,\n", - " -1.26119118, -1.2611013 , -1.26019174, -1.26077014, -1.26007772,\n", - " -1.25987122, -1.260857 , -1.2609502 , -1.26075456, -1.26134921,\n", - " -1.25965397, -1.25996982, -1.26071455, -1.25976978, -1.26108183,\n", - " -1.26034272, -1.26107775, -1.26118967, -1.25922595, -1.25959951,\n", - " -1.26157551, -1.26072113, -1.26058879, -1.26193197, -1.25939288,\n", - " -1.28878699, -1.28913722, -1.26030408, -1.26116608, -1.26092241,\n", - " -1.25960761, -1.2599948 , -1.26128422, -1.26055622, -1.26012439,\n", - " -1.26052166, -1.2609009 , -0.49429912, -0.49420118, -0.49402884,\n", - " -0.49444032, -0.49392715, -0.49464442, -0.49464248, -0.49384803,\n", - " -0.4940031 , -0.49450349, -0.49410766, -0.49446404, -0.49461625,\n", - " -0.49392508, -0.49424032, -0.49423811, -0.49392437, -0.49461667,\n", - " -0.4944622 , -0.49410966, -0.49580432, -0.4952599 , -0.49584758,\n", - " -0.49606291, -0.49405329, -0.49450455, -0.4944593 , -0.49409569,\n", - " -0.49438685, -0.49411004, -0.49400608, -0.49449611, -0.4942921 ,\n", - " -0.49429813, -0.49459747, -0.49391976, -0.49407876, -0.49437648,\n", - " -0.49398646, -0.49451098, -0.49413892, -0.49443276, -0.49457543,\n", - " -0.49388618, -0.49382348, -0.49469773, -0.49426765, -0.49431067,\n", - " -0.49473566, -0.49380506, -0.49553592, -0.49574219, -0.49407224,\n", - " -0.4944902 , -0.4944531 , -0.49402325, -0.49396739, -0.49456722,\n", - " -0.49428634, -0.49420954, -0.49415863, -0.49439461]]), _tm=BetatronTuneMonitor(tune_h='srdiag/beam-tune/main/Qh', tune_v='srdiag/beam-tune/main/Qv', name='BETATRON_TUNE'), _quads=[Quadrupole(peer='Simulator:design', name='QD2E-C04', model_name='QD2E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C05', model_name='QD2A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C05', model_name='QD2E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C06', model_name='QD2A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C06', model_name='QD2E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C07', model_name='QD2A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C07', model_name='QD2E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C08', model_name='QD2A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C08', model_name='QD2E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C09', model_name='QD2A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C09', model_name='QD2E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C10', model_name='QD2A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C10', model_name='QD2E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C11', model_name='QD2A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C11', model_name='QD2E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C12', model_name='QD2A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C12', model_name='QD2E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C13', model_name='QD2A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C13', model_name='QD2E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C14', model_name='QD2A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C14', model_name='QD2E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C15', model_name='QD2A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C15', model_name='QD2E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C16', model_name='QD2A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C16', model_name='QD2E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C17', model_name='QD2A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C17', model_name='QD2E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C18', model_name='QD2A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C18', model_name='QD2E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C19', model_name='QD2A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C19', model_name='QD2E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C20', model_name='QD2A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C20', model_name='QD2E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C21', model_name='QD2A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C21', model_name='QD2E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C22', model_name='QD2A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C22', model_name='QD2E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C23', model_name='QD2A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C23', model_name='QD2E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C24', model_name='QD2A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C24', model_name='QD2E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C25', model_name='QD2A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C25', model_name='QD2E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C26', model_name='QD2A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C26', model_name='QD2E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C27', model_name='QD2A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C27', model_name='QD2E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C28', model_name='QD2A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C28', model_name='QD2E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C29', model_name='QD2A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C29', model_name='QD2E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C30', model_name='QD2A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C30', model_name='QD2E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C31', model_name='QD2A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C31', model_name='QD2E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C32', model_name='QD2A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C32', model_name='QD2E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C01', model_name='QD2A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C01', model_name='QD2E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C02', model_name='QD2A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C02', model_name='QD2E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C03', model_name='QD2A-C03', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C04', model_name='QF1E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C05', model_name='QF1A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C05', model_name='QF1E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C06', model_name='QF1A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C06', model_name='QF1E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C07', model_name='QF1A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C07', model_name='QF1E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C08', model_name='QF1A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C08', model_name='QF1E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C09', model_name='QF1A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C09', model_name='QF1E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C10', model_name='QF1A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C10', model_name='QF1E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C11', model_name='QF1A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C11', model_name='QF1E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C12', model_name='QF1A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C12', model_name='QF1E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C13', model_name='QF1A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C13', model_name='QF1E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C14', model_name='QF1A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C14', model_name='QF1E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C15', model_name='QF1A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C15', model_name='QF1E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C16', model_name='QF1A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C16', model_name='QF1E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C17', model_name='QF1A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C17', model_name='QF1E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C18', model_name='QF1A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C18', model_name='QF1E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C19', model_name='QF1A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C19', model_name='QF1E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C20', model_name='QF1A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C20', model_name='QF1E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C21', model_name='QF1A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C21', model_name='QF1E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C22', model_name='QF1A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C22', model_name='QF1E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C23', model_name='QF1A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C23', model_name='QF1E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C24', model_name='QF1A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C24', model_name='QF1E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C25', model_name='QF1A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C25', model_name='QF1E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C26', model_name='QF1A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C26', model_name='QF1E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C27', model_name='QF1A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C27', model_name='QF1E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C28', model_name='QF1A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C28', model_name='QF1E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C29', model_name='QF1A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C29', model_name='QF1E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C30', model_name='QF1A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C30', model_name='QF1E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C31', model_name='QF1A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C31', model_name='QF1E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C32', model_name='QF1A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C32', model_name='QF1E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C01', model_name='QF1A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C01', model_name='QF1E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C02', model_name='QF1A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C02', model_name='QF1E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C03', model_name='QF1A-C03', magnet_model=LinearMagnetModel)], name='DEFAULT_TUNE_CORRECTION')" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "print(f\"Tune before correction: {SR.tune.readback()}\")\n", - "\n", - "qx, qy = 0.19, 0.28\n", - "print(f\"\\nSetting tune to [{qx}, {qy}]\")\n", - "SR.tune.set([qx, qy], iter=10, wait_time=wait_time)\n", - "print(f\"Tune after correction: {SR.tune.readback()}\")\n", - "\n", - "qx, qy = 0.21, 0.30\n", - "print(f\"\\nSetting tune to [{qx}, {qy}]\")\n", - "SR.tune.set([qx, qy], iter=10, wait_time=wait_time)\n", - "print(f\"Tune after correction: {SR.tune.readback()}\")\n", - "\n", - "SR.tune # string representation" - ] + "outputs": [], + "source": "print(f\"Tune before correction: {SR.tool.tune.readback()}\")\n\nqx, qy = 0.19, 0.28\nprint(f\"\\nSetting tune to [{qx}, {qy}]\")\nSR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time)\nprint(f\"Tune after correction: {SR.tool.tune.readback()}\")\n\nqx, qy = 0.21, 0.30\nprint(f\"\\nSetting tune to [{qx}, {qy}]\")\nSR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time)\nprint(f\"Tune after correction: {SR.tool.tune.readback()}\")\n\nSR.tool.tune # string representation" }, { "cell_type": "code", diff --git a/examples/use_cases/01-tune_correction.py b/examples/use_cases/01-tune_correction.py index d77cb367..fc84e929 100644 --- a/examples/use_cases/01-tune_correction.py +++ b/examples/use_cases/01-tune_correction.py @@ -112,14 +112,14 @@ # ### Standard tune correction tool # -# `SR.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool. +# `SR.tool.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.tool.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool. # # Before correcting the tune you need a response matrix. It can be measured (below) or loaded from a previously saved file. # In[7]: -print(SR.tune) # string representation +print(SR.tool.tune) # string representation # #### Measuring the tune response matrix @@ -145,36 +145,36 @@ def tune_callback(action: int, cb_data: dict): # In[9]: -if SR.tune.response_matrix is None: - SR.trm.measure(sleep_between_step=wait_time, callback=tune_callback) - SR.trm.save(CONFIG_DIR / "trm.json") +if SR.tool.tune.response_matrix is None: + SR.tool.trm.measure(sleep_between_step=wait_time, callback=tune_callback) + SR.tool.trm.save(CONFIG_DIR / "trm.json") -SR.tune.load(CONFIG_DIR / "trm.json") +SR.tool.tune.load(CONFIG_DIR / "trm.json") print("Response matrix loaded.") -print(SR.trm) # string representation +print(SR.tool.trm) # string representation # #### Correcting the tune # -# `SR.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls +# `SR.tool.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls # the number of iterations and `wait_time` the settling time between each iteration. # In[10]: -print(f"Tune before correction: {SR.tune.readback()}") +print(f"Tune before correction: {SR.tool.tune.readback()}") qx, qy = 0.19, 0.28 print(f"\nSetting tune to [{qx}, {qy}]") -SR.tune.set([qx, qy], iter=10, wait_time=wait_time) -print(f"Tune after correction: {SR.tune.readback()}") +SR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time) +print(f"Tune after correction: {SR.tool.tune.readback()}") qx, qy = 0.21, 0.30 print(f"\nSetting tune to [{qx}, {qy}]") -SR.tune.set([qx, qy], iter=10, wait_time=wait_time) -print(f"Tune after correction: {SR.tune.readback()}") +SR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time) +print(f"Tune after correction: {SR.tool.tune.readback()}") -print(SR.tune) # string representation +print(SR.tool.tune) # string representation # In[ ]: diff --git a/examples/use_cases/03-orbit_correction.ipynb b/examples/use_cases/03-orbit_correction.ipynb index 58cad3cc..9121fd64 100644 --- a/examples/use_cases/03-orbit_correction.ipynb +++ b/examples/use_cases/03-orbit_correction.ipynb @@ -195,140 +195,23 @@ "cell_type": "markdown", "id": "808334df", "metadata": {}, - "source": [ - "### Orbit response matrix\n", - "\n", - "The ORM can be saved in multiple formats. Load it into `SR.orbit` before correcting." - ] + "source": "### Orbit response matrix\n\nThe ORM can be saved in multiple formats. Load it into `SR.tool.orbit` before correcting." }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "33636af2", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "OrbitResponseMatrix(bpm_array_name='BPM', hcorr_array_name='HCorr', vcorr_array_name='VCorr', corrector_delta=1e-06, n_step=1, sleep_between_step=0.0, n_avg_meas=1, sleep_between_meas=0.0, name='DEFAULT_ORBIT_RESPONSE_MATRIX')" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "SR.orm # string representation" - ] + "outputs": [], + "source": "SR.tool.orm # string representation" }, { "cell_type": "code", "execution_count": null, "id": "3f9dcb18", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "14 Sep 2026, 15:10:12 | INFO | Measuring correctors from the default arrays: HCorr and VCorr.\n", - "14 Sep 2026, 15:10:14 | INFO | Measured response of SH1A-C04-H.\n", - "14 Sep 2026, 15:10:16 | INFO | Measured response of SJ1A-C04-H.\n", - "14 Sep 2026, 15:10:17 | INFO | Measured response of SJ2A-C04-H.\n", - "14 Sep 2026, 15:10:18 | INFO | Measured response of SJ1B-C04-H.\n", - "14 Sep 2026, 15:10:19 | INFO | Measured response of SH2B-C04-H.\n", - "14 Sep 2026, 15:10:21 | INFO | Measured response of SJ1D-C04-H.\n", - "14 Sep 2026, 15:10:22 | INFO | Measured response of SJ2E-C04-H.\n", - "14 Sep 2026, 15:10:23 | INFO | Measured response of SJ1E-C04-H.\n", - "14 Sep 2026, 15:10:24 | INFO | Measured response of SH3E-C04-H.\n", - "14 Sep 2026, 15:10:26 | INFO | Measured response of SH1A-C05-H.\n", - "14 Sep 2026, 15:10:27 | INFO | Measured response of SD1A-C05-H.\n", - "14 Sep 2026, 15:10:28 | INFO | Measured response of SF2A-C05-H.\n", - "14 Sep 2026, 15:10:29 | INFO | Measured response of SD1B-C05-H.\n", - "14 Sep 2026, 15:10:31 | INFO | Measured response of SH2B-C05-H.\n", - "14 Sep 2026, 15:10:32 | INFO | Measured response of SD1D-C05-H.\n", - "14 Sep 2026, 15:10:33 | INFO | Measured response of SF2E-C05-H.\n", - "14 Sep 2026, 15:10:34 | INFO | Measured response of SD1E-C05-H.\n", - "14 Sep 2026, 15:10:36 | INFO | Measured response of SH3E-C05-H.\n", - "14 Sep 2026, 15:10:37 | INFO | Measured response of SH1A-C06-H.\n", - "14 Sep 2026, 15:10:38 | INFO | Measured response of SD1A-C06-H.\n", - "14 Sep 2026, 15:10:39 | INFO | Measured response of SF2A-C06-H.\n", - "14 Sep 2026, 15:10:41 | INFO | Measured response of SD1B-C06-H.\n", - "14 Sep 2026, 15:10:42 | INFO | Measured response of SH2B-C06-H.\n", - "14 Sep 2026, 15:10:43 | INFO | Measured response of SD1D-C06-H.\n", - "14 Sep 2026, 15:10:44 | INFO | Measured response of SF2E-C06-H.\n", - "14 Sep 2026, 15:10:45 | INFO | Measured response of SD1E-C06-H.\n", - "14 Sep 2026, 15:10:47 | INFO | Measured response of SH3E-C06-H.\n", - "14 Sep 2026, 15:10:48 | INFO | Measured response of SH1A-C07-H.\n", - "14 Sep 2026, 15:10:49 | INFO | Measured response of SD1A-C07-H.\n", - "14 Sep 2026, 15:10:50 | INFO | Measured response of SF2A-C07-H.\n", - "14 Sep 2026, 15:10:52 | INFO | Measured response of SD1B-C07-H.\n", - "14 Sep 2026, 15:10:53 | INFO | Measured response of SH2B-C07-H.\n", - "14 Sep 2026, 15:10:54 | INFO | Measured response of SD1D-C07-H.\n", - "14 Sep 2026, 15:10:55 | INFO | Measured response of SF2E-C07-H.\n", - "14 Sep 2026, 15:10:56 | INFO | Measured response of SD1E-C07-H.\n", - "14 Sep 2026, 15:10:57 | INFO | Measured response of SH3E-C07-H.\n", - "14 Sep 2026, 15:10:59 | INFO | Measured response of SH1A-C08-H.\n", - "14 Sep 2026, 15:11:00 | INFO | Measured response of SD1A-C08-H.\n", - "14 Sep 2026, 15:11:01 | INFO | Measured response of SF2A-C08-H.\n", - "14 Sep 2026, 15:11:02 | INFO | Measured response of SD1B-C08-H.\n", - "14 Sep 2026, 15:11:04 | INFO | Measured response of SH2B-C08-H.\n", - "14 Sep 2026, 15:11:05 | INFO | Measured response of SD1D-C08-H.\n", - "14 Sep 2026, 15:11:06 | INFO | Measured response of SF2E-C08-H.\n", - "14 Sep 2026, 15:11:07 | INFO | Measured response of SD1E-C08-H.\n", - "14 Sep 2026, 15:11:08 | INFO | Measured response of SH3E-C08-H.\n", - "14 Sep 2026, 15:11:10 | INFO | Measured response of SH1A-C09-H.\n", - "14 Sep 2026, 15:11:11 | INFO | Measured response of SD1A-C09-H.\n", - "14 Sep 2026, 15:11:12 | INFO | Measured response of SF2A-C09-H.\n", - "14 Sep 2026, 15:11:13 | INFO | Measured response of SD1B-C09-H.\n", - "14 Sep 2026, 15:11:14 | INFO | Measured response of SH2B-C09-H.\n", - "14 Sep 2026, 15:11:16 | INFO | Measured response of SD1D-C09-H.\n", - "14 Sep 2026, 15:11:17 | INFO | Measured response of SF2E-C09-H.\n", - "14 Sep 2026, 15:11:18 | INFO | Measured response of SD1E-C09-H.\n", - "14 Sep 2026, 15:11:19 | INFO | Measured response of SH3E-C09-H.\n", - "14 Sep 2026, 15:11:21 | INFO | Measured response of SH1A-C10-H.\n", - "14 Sep 2026, 15:11:22 | INFO | Measured response of SD1A-C10-H.\n", - "14 Sep 2026, 15:11:23 | INFO | Measured response of SF2A-C10-H.\n", - "14 Sep 2026, 15:11:24 | INFO | Measured response of SD1B-C10-H.\n", - "14 Sep 2026, 15:11:26 | INFO | Measured response of SH2B-C10-H.\n", - "14 Sep 2026, 15:11:27 | INFO | Measured response of SD1D-C10-H.\n", - "14 Sep 2026, 15:11:28 | INFO | Measured response of SF2E-C10-H.\n", - "14 Sep 2026, 15:11:29 | INFO | Measured response of SD1E-C10-H.\n", - "14 Sep 2026, 15:11:31 | INFO | Measured response of SH3E-C10-H.\n", - "14 Sep 2026, 15:11:32 | INFO | Measured response of SH1A-C11-H.\n", - "14 Sep 2026, 15:11:33 | INFO | Measured response of SD1A-C11-H.\n", - "14 Sep 2026, 15:11:34 | INFO | Measured response of SF2A-C11-H.\n", - "14 Sep 2026, 15:11:35 | INFO | Measured response of SD1B-C11-H.\n", - "14 Sep 2026, 15:11:37 | INFO | Measured response of SH2B-C11-H.\n", - "14 Sep 2026, 15:11:38 | INFO | Measured response of SD1D-C11-H.\n", - "14 Sep 2026, 15:11:39 | INFO | Measured response of SF2E-C11-H.\n", - "14 Sep 2026, 15:11:40 | INFO | Measured response of SD1E-C11-H.\n", - "14 Sep 2026, 15:11:41 | INFO | Measured response of SH3E-C11-H.\n", - "14 Sep 2026, 15:11:43 | INFO | Measured response of SH1A-C12-H.\n", - "14 Sep 2026, 15:11:44 | INFO | Measured response of SD1A-C12-H.\n", - "14 Sep 2026, 15:11:45 | INFO | Measured response of SF2A-C12-H.\n", - "14 Sep 2026, 15:11:46 | INFO | Measured response of SD1B-C12-H.\n", - "14 Sep 2026, 15:11:47 | INFO | Measured response of SH2B-C12-H.\n", - "14 Sep 2026, 15:11:49 | INFO | Measured response of SD1D-C12-H.\n", - "14 Sep 2026, 15:11:50 | INFO | Measured response of SF2E-C12-H.\n", - "14 Sep 2026, 15:11:51 | INFO | Measured response of SD1E-C12-H.\n", - "14 Sep 2026, 15:11:52 | INFO | Measured response of SH3E-C12-H.\n", - "14 Sep 2026, 15:11:54 | INFO | Measured response of SH1A-C13-H.\n", - "14 Sep 2026, 15:11:55 | INFO | Measured response of SD1A-C13-H.\n", - "14 Sep 2026, 15:11:56 | INFO | Measured response of SF2A-C13-H.\n" - ] - } - ], - "source": [ - "SR.orm.measure(sleep_between_step=wait_time)\n", - "SR.orm.save(CONFIG_DIR / \"orm.json\")\n", - "SR.orm.save(CONFIG_DIR / \"orm.yaml\", with_type=\"yaml\")\n", - "SR.orm.save(CONFIG_DIR / \"orm.npz\", with_type=\"npz\")\n", - "\n", - "SR.orbit.load(CONFIG_DIR / \"orm.json\")\n", - "print(\"ORM measured, saved and loaded.\")" - ] + "outputs": [], + "source": "SR.tool.orm.measure(sleep_between_step=wait_time)\nSR.tool.orm.save(CONFIG_DIR / \"orm.json\")\nSR.tool.orm.save(CONFIG_DIR / \"orm.yaml\", with_type=\"yaml\")\nSR.tool.orm.save(CONFIG_DIR / \"orm.npz\", with_type=\"npz\")\n\nSR.tool.orbit.load(CONFIG_DIR / \"orm.json\")\nprint(\"ORM measured, saved and loaded.\")" }, { "cell_type": "markdown", @@ -344,15 +227,7 @@ "id": "942f8f3b", "metadata": {}, "outputs": [], - "source": [ - "orm_data = SR.orm.get()\n", - "plt.imshow(np.array(orm_data[\"matrix\"]))\n", - "plt.colorbar()\n", - "plt.title(\"Orbit response matrix\")\n", - "plt.xlabel(\"Corrector index\")\n", - "plt.ylabel(\"BPM index\")\n", - "plt.show()" - ] + "source": "orm_data = SR.tool.orm.get()\nplt.imshow(np.array(orm_data[\"matrix\"]))\nplt.colorbar()\nplt.title(\"Orbit response matrix\")\nplt.xlabel(\"Corrector index\")\nplt.ylabel(\"BPM index\")\nplt.show()" }, { "cell_type": "markdown", @@ -370,28 +245,7 @@ "id": "693fc409", "metadata": {}, "outputs": [], - "source": [ - "# Uncomment to measure and visualise dispersion\n", - "\n", - "# def disp_callback(action: int, cb_data) -> bool:\n", - "# from pyaml.common.constants import Action\n", - "# if action == Action.APPLY:\n", - "# print(\"Changing RF frequency\")\n", - "# elif action == Action.MEASURE:\n", - "# print(\"Reading orbit\")\n", - "# elif action == Action.RESTORE:\n", - "# print(\"Restoring RF frequency\")\n", - "# return True\n", - "\n", - "# SR.dispersion.measure(callback=disp_callback)\n", - "# disp_data = SR.dispersion.get()\n", - "# plt.plot(disp_data[\"frequency_response_x\"], label=\"H dispersion\")\n", - "# plt.plot(disp_data[\"frequency_response_y\"], label=\"V dispersion\")\n", - "# plt.xlabel(\"BPM index\")\n", - "# plt.ylabel(\"Orbit / Δf [m/Hz]\")\n", - "# plt.legend()\n", - "# plt.show()" - ] + "source": "# Uncomment to measure and visualise dispersion\n\n# def disp_callback(action: int, cb_data) -> bool:\n# from pyaml.common.constants import Action\n# if action == Action.APPLY:\n# print(\"Changing RF frequency\")\n# elif action == Action.MEASURE:\n# print(\"Reading orbit\")\n# elif action == Action.RESTORE:\n# print(\"Restoring RF frequency\")\n# return True\n\n# SR.tool.dispersion.measure(callback=disp_callback)\n# disp_data = SR.tool.dispersion.get()\n# plt.plot(disp_data[\"frequency_response_x\"], label=\"H dispersion\")\n# plt.plot(disp_data[\"frequency_response_y\"], label=\"V dispersion\")\n# plt.xlabel(\"BPM index\")\n# plt.ylabel(\"Orbit / Δf [m/Hz]\")\n# plt.legend()\n# plt.show()" }, { "cell_type": "markdown", @@ -464,16 +318,7 @@ "cell_type": "markdown", "id": "cf49c543", "metadata": {}, - "source": [ - "### Correct the orbit\n", - "\n", - "Standard correction: `SR.orbit.correct(reference=reference)`.\n", - "\n", - "Optional variants (uncomment to use):\n", - "- **Virtual corrector weight**: down-weights correctors that are already at large strengths.\n", - "- **RF correction**: also adjusts the RF frequency to minimise dispersion-driven orbit.\n", - "- **Live unit mismatch**: if BESSY2 BPMs read in nm, pass `gain=1e-9`." - ] + "source": "### Correct the orbit\n\nStandard correction: `SR.tool.orbit.correct(reference=reference)`.\n\nOptional variants (uncomment to use):\n- **Virtual corrector weight**: down-weights correctors that are already at large strengths.\n- **RF correction**: also adjusts the RF frequency to minimise dispersion-driven orbit.\n- **Live unit mismatch**: if BESSY2 BPMs read in nm, pass `gain=1e-9`." }, { "cell_type": "code", @@ -481,22 +326,7 @@ "id": "93135a4c", "metadata": {}, "outputs": [], - "source": [ - "# Standard correction\n", - "SR.orbit.correct(reference=reference)\n", - "\n", - "# With virtual corrector weight (ESRF style):\n", - "# SR.orbit.set_virtual_weight(1000)\n", - "# SR.orbit.correct(reference=reference)\n", - "\n", - "# With RF orbit correction (ESRF style, requires dispersion in ORM):\n", - "# SR.orbit.correct(reference=reference, rf=True)\n", - "\n", - "# BESSY2 live mode — BPMs in nm, use gain to compensate unit mismatch:\n", - "# SR.orbit.correct(reference=reference, gain=1e-9)\n", - "\n", - "sleep(wait_time)" - ] + "source": "# Standard correction\nSR.tool.orbit.correct(reference=reference)\n\n# With virtual corrector weight (ESRF style):\n# SR.tool.orbit.set_virtual_weight(1000)\n# SR.tool.orbit.correct(reference=reference)\n\n# With RF orbit correction (ESRF style, requires dispersion in ORM):\n# SR.tool.orbit.correct(reference=reference, rf=True)\n\n# BESSY2 live mode — BPMs in nm, use gain to compensate unit mismatch:\n# SR.tool.orbit.correct(reference=reference, gain=1e-9)\n\nsleep(wait_time)" }, { "cell_type": "code", diff --git a/examples/use_cases/03-orbit_correction.py b/examples/use_cases/03-orbit_correction.py index b7af039c..7271f26f 100644 --- a/examples/use_cases/03-orbit_correction.py +++ b/examples/use_cases/03-orbit_correction.py @@ -92,23 +92,23 @@ # ### Orbit response matrix # -# The ORM can be saved in multiple formats. Load it into `SR.orbit` before correcting. +# The ORM can be saved in multiple formats. Load it into `SR.tool.orbit` before correcting. # In[5]: -print(SR.orm) # string representation +print(SR.tool.orm) # string representation # In[6]: -SR.orm.measure(sleep_between_step=wait_time) -SR.orm.save(CONFIG_DIR / "orm.json") -SR.orm.save(CONFIG_DIR / "orm.yaml", with_type="yaml") -SR.orm.save(CONFIG_DIR / "orm.npz", with_type="npz") +SR.tool.orm.measure(sleep_between_step=wait_time) +SR.tool.orm.save(CONFIG_DIR / "orm.json") +SR.tool.orm.save(CONFIG_DIR / "orm.yaml", with_type="yaml") +SR.tool.orm.save(CONFIG_DIR / "orm.npz", with_type="npz") -SR.orbit.load(CONFIG_DIR / "orm.json") +SR.tool.orbit.load(CONFIG_DIR / "orm.json") print("ORM measured, saved and loaded.") @@ -117,7 +117,7 @@ # In[7]: -orm_data = SR.orm.get() +orm_data = SR.tool.orm.get() plt.imshow(np.array(orm_data["matrix"])) plt.colorbar() plt.title("Orbit response matrix") @@ -147,8 +147,8 @@ # print("Restoring RF frequency") # return True -# SR.dispersion.measure(callback=disp_callback) -# disp_data = SR.dispersion.get() +# SR.tool.dispersion.measure(callback=disp_callback) +# disp_data = SR.tool.dispersion.get() # plt.plot(disp_data["frequency_response_x"], label="H dispersion") # plt.plot(disp_data["frequency_response_y"], label="V dispersion") # plt.xlabel("BPM index") @@ -202,7 +202,7 @@ # ### Correct the orbit # -# Standard correction: `SR.orbit.correct(reference=reference)`. +# Standard correction: `SR.tool.orbit.correct(reference=reference)`. # # Optional variants (uncomment to use): # - **Virtual corrector weight**: down-weights correctors that are already at large strengths. @@ -213,17 +213,17 @@ # Standard correction -SR.orbit.correct(reference=reference) +SR.tool.orbit.correct(reference=reference) # With virtual corrector weight (ESRF style): -# SR.orbit.set_virtual_weight(1000) -# SR.orbit.correct(reference=reference) +# SR.tool.orbit.set_virtual_weight(1000) +# SR.tool.orbit.correct(reference=reference) # With RF orbit correction (ESRF style, requires dispersion in ORM): -# SR.orbit.correct(reference=reference, rf=True) +# SR.tool.orbit.correct(reference=reference, rf=True) # BESSY2 live mode — BPMs in nm, use gain to compensate unit mismatch: -# SR.orbit.correct(reference=reference, gain=1e-9) +# SR.tool.orbit.correct(reference=reference, gain=1e-9) sleep(wait_time) diff --git a/examples/use_cases/README.md b/examples/use_cases/README.md index ebcfe8c9..6bc3076e 100644 --- a/examples/use_cases/README.md +++ b/examples/use_cases/README.md @@ -89,8 +89,8 @@ In `design` mode all wait times can be set to `0.0`. In `live` mode use `wait_ti | `BPM` | Beam position monitors | | `BETATRON_TUNE` | Betatron tune monitor | | `CHROMATICITY_MONITOR` | Chromaticity monitor | -| `DEFAULT_TUNE_CORRECTION` | Tune correction tool → `SR.tune` | -| `DEFAULT_TUNE_RESPONSE_MATRIX` | Tune response matrix tool → `SR.trm` | -| `DEFAULT_ORBIT_CORRECTION` | Orbit correction tool → `SR.orbit` | -| `DEFAULT_ORBIT_RESPONSE_MATRIX` | Orbit response matrix tool → `SR.orm` | -| `DEFAULT_DISPERSION` | Dispersion measurement tool → `SR.dispersion` | +| `DEFAULT_TUNE_CORRECTION` | Tune correction tool → `SR.tool.tune` | +| `DEFAULT_TUNE_RESPONSE_MATRIX` | Tune response matrix tool → `SR.tool.trm` | +| `DEFAULT_ORBIT_CORRECTION` | Orbit correction tool → `SR.tool.orbit` | +| `DEFAULT_ORBIT_RESPONSE_MATRIX` | Orbit response matrix tool → `SR.tool.orm` | +| `DEFAULT_DISPERSION` | Dispersion measurement tool → `SR.tool.dispersion` | diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 5eed50c3..21d303ac 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -66,11 +66,6 @@ class ElementHolder(metaclass=ABCMeta): Diagnostics of this mode, with typed default-name access. tool Tuning and measurement tools of this mode, with typed default-name access. - tune, chromaticity, orbit, dispersion - Backward-compatible aliases for ``tool.tune``, ``tool.chromaticity``, ``tool.orbit`` - and ``tool.dispersion``. - trm, crm, orm - Backward-compatible aliases for ``tool.trm``, ``tool.crm`` and ``tool.orm``. Methods ------- @@ -695,16 +690,6 @@ def get_crm_tuning(self, name: str) -> "ChromaticityResponseMatrix": """ return self._get("ChromaticityResponseMatrix tool", name, self._TOOLS) - @property - def chromaticity(self) -> "Chromaticity": - """Return the chromaticity. Alias for ``tool.chromaticity``.""" - return self.tool.chromaticity - - @property - def crm(self) -> "ChromaticityResponseMatrix": - """Return the crm. Alias for ``tool.crm``.""" - return self.tool.crm - # ---- Tune --------------------------------------------------------- def get_tune_tuning(self, name: str) -> "Tune": @@ -723,11 +708,6 @@ def get_tune_tuning(self, name: str) -> "Tune": """ return self._get("Tune tuning tool", name, self._TOOLS) - @property - def tune(self) -> "Tune": - """Return the tune. Alias for ``tool.tune``.""" - return self.tool.tune - def get_trm_tuning(self, name: str) -> "TuneResponseMatrix": """ Return a named tune response-matrix tool. @@ -744,11 +724,6 @@ def get_trm_tuning(self, name: str) -> "TuneResponseMatrix": """ return self._get("TuneResponseMatrix tool", name, self._TOOLS) - @property - def trm(self) -> "TuneResponseMatrix": - """Return the default tune response-matrix tool. Alias for ``tool.trm``.""" - return self.tool.trm - # ---- Orbit -------------------------------------------------------- def get_orbit_tuning(self, name: str) -> "Orbit": @@ -767,11 +742,6 @@ def get_orbit_tuning(self, name: str) -> "Orbit": """ return self._get("Orbit tuning tool", name, self._TOOLS) - @property - def orbit(self) -> "Orbit": - """Return the orbit. Alias for ``tool.orbit``.""" - return self.tool.orbit - def get_orm_tuning(self, name: str) -> "OrbitResponseMatrix": """ Return a named orbit response-matrix tool. @@ -788,11 +758,6 @@ def get_orm_tuning(self, name: str) -> "OrbitResponseMatrix": """ return self._get("OrbitResponseMatrix tool", name, self._TOOLS) - @property - def orm(self) -> "OrbitResponseMatrix": - """Return the default orbit response-matrix tool. Alias for ``tool.orm``.""" - return self.tool.orm - # ---- BBA -------------------------------------------------------- def get_bba(self, name: str) -> "BBA": @@ -829,11 +794,6 @@ def get_dispersion_tuning(self, name: str) -> "Dispersion": """ return self._get("Dispersion tool", name, self._TOOLS) - @property - def dispersion(self) -> "Dispersion": - """Return the dispersion. Alias for ``tool.dispersion``.""" - return self.tool.dispersion - def _get_array(self, name: str): """ Generic array resolver used by YellowPages. diff --git a/pyaml/common/holders/tool_holder.py b/pyaml/common/holders/tool_holder.py index 2ac49e86..9f861959 100644 --- a/pyaml/common/holders/tool_holder.py +++ b/pyaml/common/holders/tool_holder.py @@ -40,12 +40,6 @@ class ToolHolder: get(name=None) Return a named tool, or all configured tools when no name is given. - Notes - ----- - :attr:`ElementHolder.tune `, - ``.trm``, ``.orbit``, ``.orm``, ``.chromaticity``, ``.crm`` and ``.dispersion`` are - backward-compatible aliases for the corresponding properties here. - Examples -------- >>> tune_correction = sr.live.tool.tune @@ -137,7 +131,7 @@ def chromaticity(self) -> "Chromaticity": from ...tuning_tools.chromaticity import Chromaticity name = "DEFAULT_CHROMATICITY_CORRECTION" - return self._validate_type(name, self._peer.get_chromaticity_tuning(name), Chromaticity) + return self._validate_type(name, self.get(name), Chromaticity) @property def crm(self) -> "ChromaticityResponseMatrix": @@ -145,7 +139,7 @@ def crm(self) -> "ChromaticityResponseMatrix": from ...tuning_tools.chromaticity_response_matrix import ChromaticityResponseMatrix name = "DEFAULT_CHROMATICITY_RESPONSE_MATRIX" - return self._validate_type(name, self._peer.get_crm_tuning(name), ChromaticityResponseMatrix) + return self._validate_type(name, self.get(name), ChromaticityResponseMatrix) @property def tune(self) -> "Tune": @@ -153,7 +147,7 @@ def tune(self) -> "Tune": from ...tuning_tools.tune import Tune name = "DEFAULT_TUNE_CORRECTION" - return self._validate_type(name, self._peer.get_tune_tuning(name), Tune) + return self._validate_type(name, self.get(name), Tune) @property def trm(self) -> "TuneResponseMatrix": @@ -161,7 +155,7 @@ def trm(self) -> "TuneResponseMatrix": from ...tuning_tools.tune_response_matrix import TuneResponseMatrix name = "DEFAULT_TUNE_RESPONSE_MATRIX" - return self._validate_type(name, self._peer.get_trm_tuning(name), TuneResponseMatrix) + return self._validate_type(name, self.get(name), TuneResponseMatrix) @property def orbit(self) -> "Orbit": @@ -169,7 +163,7 @@ def orbit(self) -> "Orbit": from ...tuning_tools.orbit import Orbit name = "DEFAULT_ORBIT_CORRECTION" - return self._validate_type(name, self._peer.get_orbit_tuning(name), Orbit) + return self._validate_type(name, self.get(name), Orbit) @property def orm(self) -> "OrbitResponseMatrix": @@ -177,7 +171,7 @@ def orm(self) -> "OrbitResponseMatrix": from ...tuning_tools.orbit_response_matrix import OrbitResponseMatrix name = "DEFAULT_ORBIT_RESPONSE_MATRIX" - return self._validate_type(name, self._peer.get_orm_tuning(name), OrbitResponseMatrix) + return self._validate_type(name, self.get(name), OrbitResponseMatrix) @property def dispersion(self) -> "Dispersion": @@ -185,7 +179,7 @@ def dispersion(self) -> "Dispersion": from ...tuning_tools.dispersion import Dispersion name = "DEFAULT_DISPERSION" - return self._validate_type(name, self._peer.get_dispersion_tuning(name), Dispersion) + return self._validate_type(name, self.get(name), Dispersion) def __repr__(self): return __pyaml_repr__(self) diff --git a/pyaml/tuning_tools/chromaticity_response_matrix.py b/pyaml/tuning_tools/chromaticity_response_matrix.py index c75ec53c..4d739e0e 100644 --- a/pyaml/tuning_tools/chromaticity_response_matrix.py +++ b/pyaml/tuning_tools/chromaticity_response_matrix.py @@ -151,10 +151,10 @@ def callback(action: Action, data:dict): sr = Accelerator.load("tests/config/EBSOrbit.yaml") acc = sr.design - if acc.crm.measure(callback=callback): - acc.crm.save("ideal_crm.json") - acc.crm.save("ideal_crm.yaml", with_type="yaml") - acc.crm.save("ideal_crm.npz", with_type="npz") + if acc.tool.crm.measure(callback=callback): + acc.tool.crm.save("ideal_crm.json") + acc.tool.crm.save("ideal_crm.yaml", with_type="yaml") + acc.tool.crm.save("ideal_crm.npz", with_type="npz") Parameters ---------- diff --git a/pyaml/tuning_tools/measurement_tool.py b/pyaml/tuning_tools/measurement_tool.py index 646d38ed..acdc5789 100644 --- a/pyaml/tuning_tools/measurement_tool.py +++ b/pyaml/tuning_tools/measurement_tool.py @@ -182,7 +182,7 @@ def callback(action: Action, data: dict): return True # Measure a tune response matrix using the above callback - sr.design.trm.measure(callback=callback) + sr.design.tool.trm.measure(callback=callback) Parameters ---------- diff --git a/pyaml/tuning_tools/orbit_response_matrix.py b/pyaml/tuning_tools/orbit_response_matrix.py index 101a7220..14bd96d2 100644 --- a/pyaml/tuning_tools/orbit_response_matrix.py +++ b/pyaml/tuning_tools/orbit_response_matrix.py @@ -173,10 +173,10 @@ def measure( sr = Accelerator.load("MyAccelerator.yaml") acc = sr.design - if acc.orm.measure(): - acc.orm.save("ideal_orm.json") - acc.orm.save("ideal_orm.yaml", with_type="yaml") - acc.orm.save("ideal_orm.npz", with_type="npz") + if acc.tool.orm.measure(): + acc.tool.orm.save("ideal_orm.json") + acc.tool.orm.save("ideal_orm.yaml", with_type="yaml") + acc.tool.orm.save("ideal_orm.npz", with_type="npz") Parameters ---------- diff --git a/pyaml/tuning_tools/tune_response_matrix.py b/pyaml/tuning_tools/tune_response_matrix.py index 0af72d6e..380a4105 100644 --- a/pyaml/tuning_tools/tune_response_matrix.py +++ b/pyaml/tuning_tools/tune_response_matrix.py @@ -190,10 +190,10 @@ def callback(action: Action, data:dict): sr = Accelerator.load("tests/config/EBSTune.yaml") acc = sr.design - if acc.trm.measure(n_avg_meas=3,sleep_between_meas=5,callback=callback): - acc.trm.save("ideal_trm.json") - acc.trm.save("ideal_trm.yaml", with_type="yaml") - acc.trm.save("ideal_trm.npz", with_type="npz") + if acc.tool.trm.measure(n_avg_meas=3,sleep_between_meas=5,callback=callback): + acc.tool.trm.save("ideal_trm.json") + acc.tool.trm.save("ideal_trm.yaml", with_type="yaml") + acc.tool.trm.save("ideal_trm.npz", with_type="npz") Parameters ---------- diff --git a/tests/diagnostics/test_diagnostic_accessors.py b/tests/diagnostics/test_diagnostic_accessors.py index 2acdb9c3..b4c6f58b 100644 --- a/tests/diagnostics/test_diagnostic_accessors.py +++ b/tests/diagnostics/test_diagnostic_accessors.py @@ -54,7 +54,7 @@ def test_diagnostic_raises_when_default_wrong_type(): ).design # Swap the registered default so it points to an object of the wrong type. - design._DIAG["BETATRON_TUNE"] = design.orbit + design._DIAG["BETATRON_TUNE"] = design.tool.orbit with pytest.raises(PyAMLException) as exc: _ = design.diagnostic.betatron_tune diff --git a/tests/tuning_tools/test_tool_accessors.py b/tests/tuning_tools/test_tool_accessors.py index d9a54e7b..a5dd2500 100644 --- a/tests/tuning_tools/test_tool_accessors.py +++ b/tests/tuning_tools/test_tool_accessors.py @@ -15,36 +15,36 @@ def test_tuning_tools_expose_configured_elements(): tune_monitor = design.get_betatron_tune_monitor("BETATRON_TUNE") quadrupoles = design.magnets.get("QForTune") - assert design.tune.tune_monitor is tune_monitor - assert design.tune.quadrupoles is quadrupoles - assert design.trm.tune_monitor is tune_monitor - assert design.trm.quadrupoles is quadrupoles + assert design.tool.tune.tune_monitor is tune_monitor + assert design.tool.tune.quadrupoles is quadrupoles + assert design.tool.trm.tune_monitor is tune_monitor + assert design.tool.trm.quadrupoles is quadrupoles chromaticity_monitor = design.get_chromaticity_monitor("CHROMATICITY_MONITOR") sextupoles = design.magnets.get("Sext") - assert design.chromaticity.chromaticity_monitor is chromaticity_monitor - assert design.chromaticity.sextupoles is sextupoles - assert design.crm.chromaticity_monitor is chromaticity_monitor - assert design.crm.sextupoles is sextupoles + assert design.tool.chromaticity.chromaticity_monitor is chromaticity_monitor + assert design.tool.chromaticity.sextupoles is sextupoles + assert design.tool.crm.chromaticity_monitor is chromaticity_monitor + assert design.tool.crm.sextupoles is sextupoles bpms = design.diagnostic.bpms.get("BPM") rf_plant = design.rf.get("DEFAULT_RF_PLANT") assert chromaticity_monitor.tune_monitor is tune_monitor assert chromaticity_monitor.bpms is bpms assert chromaticity_monitor.rf_plant is rf_plant - assert design.dispersion.bpms is bpms - assert design.dispersion.rf_plant is rf_plant + assert design.tool.dispersion.bpms is bpms + assert design.tool.dispersion.rf_plant is rf_plant hcorrectors = design.magnets.get("HCorr") vcorrectors = design.magnets.get("VCorr") - assert design.orbit.bpms is bpms - assert design.orbit.hcorrectors is hcorrectors - assert design.orbit.vcorrectors is vcorrectors - assert design.orbit.correctors.names() == hcorrectors.names() + vcorrectors.names() - assert design.orbit.rf_plant is rf_plant - assert design.orm.bpms is bpms - assert design.orm.hcorrectors is hcorrectors - assert design.orm.vcorrectors is vcorrectors + assert design.tool.orbit.bpms is bpms + assert design.tool.orbit.hcorrectors is hcorrectors + assert design.tool.orbit.vcorrectors is vcorrectors + assert design.tool.orbit.correctors.names() == hcorrectors.names() + vcorrectors.names() + assert design.tool.orbit.rf_plant is rf_plant + assert design.tool.orm.bpms is bpms + assert design.tool.orm.hcorrectors is hcorrectors + assert design.tool.orm.vcorrectors is vcorrectors for name in ("BBA-BPM_C04-04", "BBA2-BPM_C04-04"): bba = design.get_bba(name) @@ -54,7 +54,7 @@ def test_tuning_tools_expose_configured_elements(): assert bba.vcorrector is design.magnet.get("SD1A-C26-V") assert bba.quadrupole is design.magnet.get("QF6B-C04") - assert design.get_bba("BBA2-BPM_C04-04").tune_correction is design.tune + assert design.get_bba("BBA2-BPM_C04-04").tune_correction is design.tool.tune def test_tool_get_returns_named_tool(): @@ -64,8 +64,8 @@ def test_tool_get_returns_named_tool(): include_locations=False, ).design - assert design.tool.get("DEFAULT_TUNE_CORRECTION") is design.tune - assert design.tool.get("DEFAULT_ORBIT_RESPONSE_MATRIX") is design.orm + assert design.tool.get("DEFAULT_TUNE_CORRECTION") is design.tool.tune + assert design.tool.get("DEFAULT_ORBIT_RESPONSE_MATRIX") is design.tool.orm def test_tool_get_with_no_name_returns_all_configured_tools(): @@ -76,29 +76,13 @@ def test_tool_get_with_no_name_returns_all_configured_tools(): ).design all_tools = design.tool.get() - assert design.tune in all_tools - assert design.trm in all_tools - assert design.orbit in all_tools - assert design.orm in all_tools - assert design.chromaticity in all_tools - assert design.crm in all_tools - assert design.dispersion in all_tools - - -def test_tool_typed_properties_alias_existing_defaults(): - design = Accelerator.load( - "tests/config/EBSOrbit.yaml", - ignore_external=True, - include_locations=False, - ).design - - assert design.tool.tune is design.tune - assert design.tool.trm is design.trm - assert design.tool.orbit is design.orbit - assert design.tool.orm is design.orm - assert design.tool.chromaticity is design.chromaticity - assert design.tool.crm is design.crm - assert design.tool.dispersion is design.dispersion + assert design.tool.tune in all_tools + assert design.tool.trm in all_tools + assert design.tool.orbit in all_tools + assert design.tool.orm in all_tools + assert design.tool.chromaticity in all_tools + assert design.tool.crm in all_tools + assert design.tool.dispersion in all_tools def test_tool_raises_when_default_missing(ebs_lattice_file): @@ -117,7 +101,7 @@ def test_tool_raises_when_default_wrong_type(): ).design # Swap the registered default so it points to an object of the wrong type. - design._TOOLS["DEFAULT_TUNE_CORRECTION"] = design.orbit + design._TOOLS["DEFAULT_TUNE_CORRECTION"] = design.tool.orbit with pytest.raises(PyAMLException) as exc: _ = design.tool.tune diff --git a/tests/tuning_tools/test_tuning_dispersion.py b/tests/tuning_tools/test_tuning_dispersion.py index 9cd3e66b..a2abcc43 100644 --- a/tests/tuning_tools/test_tuning_dispersion.py +++ b/tests/tuning_tools/test_tuning_dispersion.py @@ -12,7 +12,7 @@ def test_tuning_orm(): sr = Accelerator.load(config_path) element_holder = sr.design - dispersion = element_holder.dispersion + dispersion = element_holder.tool.dispersion dispersion.measure() dispersion_data = dispersion.get() diff --git a/tests/tuning_tools/test_tuning_orbit_correction.py b/tests/tuning_tools/test_tuning_orbit_correction.py index 7cf8fb56..930d59e9 100644 --- a/tests/tuning_tools/test_tuning_orbit_correction.py +++ b/tests/tuning_tools/test_tuning_orbit_correction.py @@ -27,7 +27,7 @@ def test_tuning_orbit_correction(): x, y = bpms.positions.get().T # get reference orbit reference = np.concat((x, y)) # there should be nothing to correct, but still work - element_holder.orbit.correct(reference=reference) + element_holder.tool.orbit.correct(reference=reference) h_strengths = hcorr.strengths.get() + std_kick * np.random.normal(size=len(hcorr)) v_strengths = vcorr.strengths.get() + std_kick * np.random.normal(size=len(vcorr)) @@ -43,7 +43,7 @@ def test_tuning_orbit_correction(): assert np.isclose(std_bc[0], original_H, rtol=0, atol=1e-14) assert np.isclose(std_bc[1], original_V, rtol=0, atol=1e-14) - element_holder.orbit.correct(reference=None) + element_holder.tool.orbit.correct(reference=None) positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) @@ -53,7 +53,7 @@ def test_tuning_orbit_correction(): # mangle orbit again, test gain_h/gain_v hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.correct(gain_h=0.5, gain_v=0.1) + element_holder.tool.orbit.correct(gain_h=0.5, gain_v=0.1) positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) @@ -63,7 +63,7 @@ def test_tuning_orbit_correction(): # mangle orbit again, test gain/gain_v hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.correct(gain=1, gain_v=0.1) + element_holder.tool.orbit.correct(gain=1, gain_v=0.1) positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) @@ -73,7 +73,7 @@ def test_tuning_orbit_correction(): # mangle orbit again, test singular_values_h hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.correct(singular_values_h=100) + element_holder.tool.orbit.correct(singular_values_h=100) positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) @@ -83,7 +83,7 @@ def test_tuning_orbit_correction(): # mangle orbit again, test singular_values_v hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.correct(singular_values_v=50) + element_holder.tool.orbit.correct(singular_values_v=50) positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) @@ -93,7 +93,7 @@ def test_tuning_orbit_correction(): # mangle orbit again, test plane=H hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.correct(plane="H") + element_holder.tool.orbit.correct(plane="H") positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) @@ -104,7 +104,7 @@ def test_tuning_orbit_correction(): # mangle orbit again, test plane=V hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.correct(plane="V") + element_holder.tool.orbit.correct(plane="V") positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) @@ -116,65 +116,65 @@ def test_tuning_orbit_correction(): hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.set_weight("SJ2A-C04-H", 2) - element_holder.orbit.correct() + element_holder.tool.orbit.set_weight("SJ2A-C04-H", 2) + element_holder.tool.orbit.correct() positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) assert np.isclose(std_ac[0], 5.057265926153962e-07, rtol=0, atol=1e-14) assert np.isclose(std_ac[1], 4.78927471675123e-07, rtol=0, atol=1e-14) - element_holder.orbit.set_weight("SJ2A-C04-H", 1) + element_holder.tool.orbit.set_weight("SJ2A-C04-H", 1) # mangle orbit again, test bpm weight hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.set_weight("BPM_C04-05", 2) - element_holder.orbit.correct() + element_holder.tool.orbit.set_weight("BPM_C04-05", 2) + element_holder.tool.orbit.correct() positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) assert np.isclose(std_ac[0], 5.056719006414065e-07, rtol=0, atol=1e-14) assert np.isclose(std_ac[1], 4.790610352466602e-07, rtol=0, atol=1e-14) - element_holder.orbit.set_weight("BPM_C04-05", 1) + element_holder.tool.orbit.set_weight("BPM_C04-05", 1) # mangle orbit again, test virtual weight hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) - element_holder.orbit.set_virtual_weight(2) - element_holder.orbit.correct() + element_holder.tool.orbit.set_virtual_weight(2) + element_holder.tool.orbit.correct() positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) assert np.isclose(std_ac[0], 5.05398857685373e-07, rtol=0, atol=1e-14) assert np.isclose(std_ac[1], 4.789270969888965e-07, rtol=0, atol=1e-14) - element_holder.orbit.set_virtual_weight(1000) + element_holder.tool.orbit.set_virtual_weight(1000) # mangle orbit again, test virtual target hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) virtual_target = 1e-8 - element_holder.orbit.correct(virtual_target=virtual_target) + element_holder.tool.orbit.correct(virtual_target=virtual_target) delta_h_strengths = hcorr.strengths.get() - h_strengths delta_h_strengths_sum = -np.sum(delta_h_strengths) assert np.isclose(delta_h_strengths_sum - virtual_target, 0, rtol=0, atol=1e-13) - element_holder.orbit.set_virtual_weight(1) + element_holder.tool.orbit.set_virtual_weight(1) # mangle orbit again, test reference hcorr.strengths.set(h_strengths) vcorr.strengths.set(v_strengths) reference = np.concatenate((positions_bc[:, 0], positions_bc[:, 1])) - element_holder.orbit.correct(reference=reference) + element_holder.tool.orbit.correct(reference=reference) positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) assert np.isclose(std_ac[0], original_H, rtol=0, atol=1e-14) assert np.isclose(std_ac[1], original_V, rtol=0, atol=1e-14) # no need to mangle orbit again, test reference/plane=H - element_holder.orbit.correct(reference=reference / 2, plane="H") + element_holder.tool.orbit.correct(reference=reference / 2, plane="H") positions_ac = bpms.positions.get() std_ac = np.std(positions_ac, axis=0) assert np.isclose(std_ac[0], 3.360429728849497e-05, rtol=0, atol=1e-14) @@ -187,7 +187,7 @@ def test_tuning_orbit_correction(): frf = element_holder.rf.frequency.get() element_holder.rf.frequency.set(frf + 100) for _ in range(3): - element_holder.orbit.correct( + element_holder.tool.orbit.correct( reference=reference_before_rf, plane="H", rf=True, @@ -202,12 +202,12 @@ def test_tuning_orbit_correction(): x, y = bpms.positions.get().T # get reference orbit reference_before_rf = np.concat((x, y)) - rf_weight = element_holder.orbit.get_rf_weight() - element_holder.orbit.set_rf_weight(1.1 * rf_weight) + rf_weight = element_holder.tool.orbit.get_rf_weight() + element_holder.tool.orbit.set_rf_weight(1.1 * rf_weight) frf = element_holder.rf.frequency.get() element_holder.rf.frequency.set(frf + 100) for _ in range(8): - element_holder.orbit.correct( + element_holder.tool.orbit.correct( reference=reference_before_rf, plane="H", rf=True, @@ -217,12 +217,12 @@ def test_tuning_orbit_correction(): frf_after = element_holder.rf.frequency.get() assert np.isclose(frf, frf_after, rtol=0, atol=1e-16) - element_holder.orbit.set_rf_weight(rf_weight) + element_holder.tool.orbit.set_rf_weight(rf_weight) # test getters of weights - assert np.isclose(element_holder.orbit.get_weight("BPM_C04-05", plane="H"), 1, rtol=0, atol=1e-16) - assert np.isclose(element_holder.orbit.get_virtual_weight(), 1, rtol=0, atol=1e-16) - assert np.isclose(element_holder.orbit.get_rf_weight(), rf_weight, rtol=0, atol=1e-16) + assert np.isclose(element_holder.tool.orbit.get_weight("BPM_C04-05", plane="H"), 1, rtol=0, atol=1e-16) + assert np.isclose(element_holder.tool.orbit.get_virtual_weight(), 1, rtol=0, atol=1e-16) + assert np.isclose(element_holder.tool.orbit.get_rf_weight(), rf_weight, rtol=0, atol=1e-16) def test_tuning_orbit_correction_config(): diff --git a/tests/tuning_tools/test_tuning_orm.py b/tests/tuning_tools/test_tuning_orm.py index f3652f0c..3ea994f0 100644 --- a/tests/tuning_tools/test_tuning_orm.py +++ b/tests/tuning_tools/test_tuning_orm.py @@ -15,7 +15,7 @@ def test_tuning_orm(): sr = Accelerator.load(config_path) element_holder = sr.design - orm = element_holder.orm + orm = element_holder.tool.orm bpms = element_holder.diagnostic.bpms.get("BPM") hcorr_names = element_holder.magnets.get("HCorr").names()[:4] @@ -31,4 +31,4 @@ def test_tuning_orm(): orm.save(save_path=f.name) # load saved file - element_holder.orbit.load(f.name) + element_holder.tool.orbit.load(f.name) diff --git a/tests/tuning_tools/test_tuning_tools.py b/tests/tuning_tools/test_tuning_tools.py index 5c748b00..635142a2 100644 --- a/tests/tuning_tools/test_tuning_tools.py +++ b/tests/tuning_tools/test_tuning_tools.py @@ -12,11 +12,11 @@ def callback(action: Action, data: dict): def test_tune_tool(): sr = Accelerator.load("tests/config/EBSTune.yaml", include_locations=False) sr.design.get_lattice().disable_6d() - sr.design.trm.measure(callback=callback) - sr.design.trm.save("tunemat.json") - sr.design.tune.load("tunemat.json") - sr.design.tune.set([0.17, 0.32], iter=2) - tune = sr.design.tune.readback() + sr.design.tool.trm.measure(callback=callback) + sr.design.tool.trm.save("tunemat.json") + sr.design.tool.tune.load("tunemat.json") + sr.design.tool.tune.set([0.17, 0.32], iter=2) + tune = sr.design.tool.tune.readback() assert np.abs(tune[0] - 0.17) < 1e-5 assert np.abs(tune[1] - 0.32) < 1e-5 @@ -24,20 +24,20 @@ def test_tune_tool(): def test_tune_add(): sr = Accelerator.load("tests/config/EBSTune.yaml", include_locations=False) sr.design.get_lattice().disable_6d() - sr.design.tune.load("tunemat.json") - tune_initial = sr.design.tune.readback() + sr.design.tool.tune.load("tunemat.json") + tune_initial = sr.design.tool.tune.readback() dtune = np.array([0.01, -0.01]) - sr.design.tune.add(dtune) - tune = sr.design.tune.readback() + sr.design.tool.tune.add(dtune) + tune = sr.design.tool.tune.readback() np.testing.assert_allclose(tune - tune_initial, dtune, atol=1e-5) def test_chroma_tool(): sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", include_locations=False) sr.design.get_lattice().enable_6d() - sr.design.chromaticity.set([8.0, 5.0], iter=2) + sr.design.tool.chromaticity.set([8.0, 5.0], iter=2) QpAT = sr.design.get_lattice().get_chrom()[:-1] - Qp = sr.design.chromaticity.readback() + Qp = sr.design.tool.chromaticity.readback() assert np.abs(Qp[0] - 8.0) < 1e-3 assert np.abs(Qp[1] - 5.0) < 1e-3 assert np.abs(QpAT[0] - 8.0) < 1e-2 @@ -48,7 +48,7 @@ def test_chroma_add(): sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", include_locations=False) sr.design.get_lattice().enable_6d() chromaAT = sr.design.get_lattice().get_chrom()[:-1] - sr.design.chromaticity.add([0.5, 0.4]) + sr.design.tool.chromaticity.add([0.5, 0.4]) chromaAT2 = sr.design.get_lattice().get_chrom()[:-1] chromaDiff = chromaAT2 - chromaAT assert np.abs(chromaDiff[0] - 0.5) < 5e-2 From 18f8e62894df0aa1adf14f2f048f21ab0e7368ea Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Thu, 1 Oct 2026 14:12:26 +0200 Subject: [PATCH 14/16] ElementHolder.get() resolves named arrays of any type; drop superseded get_element/get_elements/get_all_elements/get_betatron_tune_monitor/get_*_tuning --- .../OphydDevice_examples/tune_ophyd_device.py | 2 +- examples/use_cases/01-tune_correction.ipynb | 2 +- examples/use_cases/01-tune_correction.py | 2 +- pyaml/arrays/element.py | 2 +- pyaml/arrays/element_array.py | 4 +- pyaml/common/holders/diagnostic_holder.py | 9 +- pyaml/common/holders/element_holder.py | 234 +++--------------- pyaml/tuning_tools/bba2.py | 6 +- pyaml/tuning_tools/chromaticity_monitor.py | 2 +- pyaml/tuning_tools/tune.py | 2 +- pyaml/tuning_tools/tune_response_matrix.py | 2 +- tests/arrays/test_array_selection_types.py | 2 +- tests/arrays/test_arrays.py | 6 +- tests/arrays/test_arrays_ops.py | 12 +- .../common/test_element_holder_collection.py | 27 +- .../diagnostics/test_diagnostic_accessors.py | 8 +- tests/integration/test_dt4acc_twin_smoke.py | 4 +- tests/magnet/test_serialized_magnets.py | 12 +- tests/test_accelerator_load.py | 8 +- tests/test_load_conf_with_code.py | 2 +- tests/tuning_tools/test_tool_accessors.py | 2 +- tests/tuning_tools/test_tune.py | 2 +- tests/tuning_tools/test_tune_hardware.py | 2 +- tests/tuning_tools/test_tune_monitor.py | 4 +- 24 files changed, 92 insertions(+), 266 deletions(-) diff --git a/examples/other_examples/OphydDevice_examples/tune_ophyd_device.py b/examples/other_examples/OphydDevice_examples/tune_ophyd_device.py index f98c1922..bb22a588 100644 --- a/examples/other_examples/OphydDevice_examples/tune_ophyd_device.py +++ b/examples/other_examples/OphydDevice_examples/tune_ophyd_device.py @@ -179,6 +179,6 @@ def unit(self) -> str: # Main code sr = Accelerator.from_dict(acc_config) -tm1 = sr.live.get_betatron_tune_monitor("MY_TUNE_MONITOR") +tm1 = sr.live.diagnostic.get("MY_TUNE_MONITOR") print(tm1.tune.get()) print(tm1.frequency.get()) diff --git a/examples/use_cases/01-tune_correction.ipynb b/examples/use_cases/01-tune_correction.ipynb index cf6e3471..4e20ff1f 100644 --- a/examples/use_cases/01-tune_correction.ipynb +++ b/examples/use_cases/01-tune_correction.ipynb @@ -207,7 +207,7 @@ } ], "source": [ - "tune_monitor = SR.get_betatron_tune_monitor(\"BETATRON_TUNE\")\n", + "tune_monitor = SR.diagnostic.get(\"BETATRON_TUNE\")\n", "print(f\"Current tune: {tune_monitor.tune.get()}\")\n", "tune_monitor # string representation" ] diff --git a/examples/use_cases/01-tune_correction.py b/examples/use_cases/01-tune_correction.py index fc84e929..1525b993 100644 --- a/examples/use_cases/01-tune_correction.py +++ b/examples/use_cases/01-tune_correction.py @@ -80,7 +80,7 @@ # In[4]: -tune_monitor = SR.get_betatron_tune_monitor("BETATRON_TUNE") +tune_monitor = SR.diagnostic.get("BETATRON_TUNE") print(f"Current tune: {tune_monitor.tune.get()}") print(tune_monitor) # string representation diff --git a/pyaml/arrays/element.py b/pyaml/arrays/element.py index 6483f03d..4b93276a 100644 --- a/pyaml/arrays/element.py +++ b/pyaml/arrays/element.py @@ -65,7 +65,7 @@ def fill_array(self, holder: ElementHolder): .. code-block:: python >>> elt_cfg.fill_array(sr.design) - >>> names = sr.design.get_elements("MyArray").names() + >>> names = sr.design.get("MyArray").names() >>> print(names) ['BPM_C04-01', 'SH1A-C04-H'] diff --git a/pyaml/arrays/element_array.py b/pyaml/arrays/element_array.py index 26c7b65b..797fc919 100644 --- a/pyaml/arrays/element_array.py +++ b/pyaml/arrays/element_array.py @@ -61,7 +61,7 @@ class ElementArray(list[Element]): .. code-block:: python >>> sr = Accelerator.load("acc.yaml") - >>> elements = sr.design.get_elements("QuadForTune") + >>> elements = sr.design.get("QuadForTune") """ def __init__(self, array_name: str, elements: list[Element], use_aggregator=True): @@ -282,7 +282,7 @@ def __and__(self, other: object): .. code-block:: python - >>> cell1 = sr.live.get_elements("C01") + >>> cell1 = sr.live.get("C01") >>> sexts = sr.live.get_magnets("SEXT") >>> cell1_sext = cell1 & sexts diff --git a/pyaml/common/holders/diagnostic_holder.py b/pyaml/common/holders/diagnostic_holder.py index b78eefbf..fa156c68 100644 --- a/pyaml/common/holders/diagnostic_holder.py +++ b/pyaml/common/holders/diagnostic_holder.py @@ -35,13 +35,6 @@ class DiagnosticHolder: get(name=None) Return a named diagnostic, or all configured diagnostics when no name is given. - Notes - ----- - :meth:`ElementHolder.get_betatron_tune_monitor - ` stays - available as the named, untyped lookup. This holder adds the default-name, - type-validated convenience property. - Examples -------- >>> default_tune_monitor = sr.live.diagnostic.betatron_tune @@ -144,7 +137,7 @@ def betatron_tune(self) -> BetatronTuneMonitor: :class:`~pyaml.diagnostics.tune_monitor.BetatronTuneMonitor`. """ name = "BETATRON_TUNE" - obj = self._peer.get_betatron_tune_monitor(name) + obj = self.get(name) if not isinstance(obj, BetatronTuneMonitor): raise PyAMLException(f"{name}: BetatronTuneMonitor expected but got {type(obj).__name__}") return obj diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 21d303ac..65291b2a 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -32,14 +32,7 @@ from ...accelerator import Accelerator from ...configuration.unbound_element import UnboundElement from ...tuning_tools.bba import BBA - from ...tuning_tools.chromaticity import Chromaticity - from ...tuning_tools.chromaticity_response_matrix import ChromaticityResponseMatrix - from ...tuning_tools.dispersion import Dispersion from ...tuning_tools.measurement_tool import MeasurementTool - from ...tuning_tools.orbit import Orbit - from ...tuning_tools.orbit_response_matrix import OrbitResponseMatrix - from ...tuning_tools.tune import Tune - from ...tuning_tools.tune_response_matrix import TuneResponseMatrix from ...tuning_tools.tuning_tool import TuningTool @@ -85,36 +78,16 @@ class ElementHolder(metaclass=ABCMeta): Create and register a generic element array. add_element(element) Add an element to the global element store. - get_element(name) - Return a named element from the global store. - get_elements(name) - Return a named generic element array. - get_all_elements() - Return all registered elements in insertion order. - get_betatron_tune_monitor(name) - Return a named betatron tune monitor. + get(name=None) + Return a named element array, or every registered element when no name is given. add_betatron_tune_monitor(tune_monitor) Add a betatron tune monitor to the diagnostics store. add_tool(tool) Add a tuning or measurement tool to the tool store. get_chromaticity_monitor(name) Return a named chromaticity monitor. - get_chromaticity_tuning(name) - Return a named chromaticity tuning tool. - get_crm_tuning(name) - Return a named chromaticity response-matrix tool. - get_tune_tuning(name) - Return a named tune correction tool. - get_trm_tuning(name) - Return a named tune response-matrix tool. - get_orbit_tuning(name) - Return a named orbit correction tool. - get_orm_tuning(name) - Return a named orbit response-matrix tool. get_bba(name) Return a named beam-based alignment tool. - get_dispersion_tuning(name) - Return a named dispersion tuning tool. """ def __init__(self): @@ -211,7 +184,7 @@ def tool(self) -> ToolHolder: def post_init(self): """Run post-initialization hooks for every stored element.""" - for e in self.get_all_elements(): + for e in self._ALL.values(): e.post_init() def fill_device(self, elements: list[Element]): @@ -418,13 +391,27 @@ def _get(self, what, name, array) -> Element: return array[name] # Generic elements - def get(self) -> ElementArray: - """Return all registered elements in insertion order. + def get(self, name: str | None = None) -> ElementArray: + """Return a named element array, or every registered element when no name is given. + + Parameters + ---------- + name : str, optional + Name of the element array to look up, as declared in the configuration. + When omitted, every registered element is returned instead. Returns ------- ElementArray - New unnamed container sharing the registered element references. + The element array registered under ``name``, regardless of its concrete + family (magnet, BPM, combined-function magnet, serialized-magnet, or + generic element array), or a new unnamed container of every registered + element, in insertion order, when ``name`` is omitted. + + Raises + ------ + PyAMLException + If ``name`` is given and no array is registered under it. Notes ----- @@ -436,8 +423,11 @@ def get(self) -> ElementArray: -------- >>> elements = sr.live.get() >>> names = elements.names() + >>> cell08 = sr.live.get("CELL08") """ - return ElementArray("", list(self._ALL.values())) + if name is None: + return ElementArray("", list(self._ALL.values())) + return self._get_array(name) @overload def __getitem__(self, key: int) -> Element: ... @@ -545,7 +535,7 @@ def fill_element_array(self, arrayName: str, elementNames: list[str]): self._fill_array( arrayName, elementNames, - self.get_element, + self._get_element, ElementArray, self._ELEMENT_ARRAYS, ) @@ -561,60 +551,14 @@ def add_element(self, element: Element): """ self._ALL[element.get_name()] = element - def get_element(self, name: str) -> Element: + def _get_element(self, name: str) -> Element: """ - Return a named element from the global store. - - Parameters - ---------- - name : str - Name of the element to look up, as declared in the configuration. - - Returns - ------- - Element - The element registered under ``name``. + Generic single-element resolver used internally to build element arrays. """ return self._get("Element", name, self._ALL) - def get_elements(self, name: str) -> ElementArray: - """ - Return a named generic element array. - - Parameters - ---------- - name : str - Name of the element array to look up, as declared in the configuration. - - Returns - ------- - ElementArray - The element array registered under ``name``. - """ - return self._get("Element array", name, self._ELEMENT_ARRAYS) - - def get_all_elements(self) -> list[Element]: - """Return all registered elements in insertion order.""" - return [value for key, value in self._ALL.items()] - # Tune monitor - def get_betatron_tune_monitor(self, name: str) -> BetatronTuneMonitor: - """ - Return a named betatron tune monitor. - - Parameters - ---------- - name : str - Name of the betatron tune monitor to look up, as declared in the configuration. - - Returns - ------- - BetatronTuneMonitor - The betatron tune monitor registered under ``name``. - """ - return self._get("Diagnostic", name, self._DIAG) - def add_betatron_tune_monitor(self, tune_monitor: Element): """ Add a betatron tune monitor to the diagnostics store. @@ -658,106 +602,6 @@ def get_chromaticity_monitor(self, name: str) -> ChromaticityMonitor: obj = self._get("Chromaticity monitor", name, self._TOOLS) return obj - def get_chromaticity_tuning(self, name: str) -> "Chromaticity": - """ - Return a named chromaticity tuning tool. - - Parameters - ---------- - name : str - Name of the chromaticity tuning tool to look up, as declared in the configuration. - - Returns - ------- - 'Chromaticity' - The chromaticity tuning tool registered under ``name``. - """ - return self._get("Chromaticity tool", name, self._TOOLS) - - def get_crm_tuning(self, name: str) -> "ChromaticityResponseMatrix": - """ - Return a named chromaticity response-matrix tool. - - Parameters - ---------- - name : str - Name of the chromaticity response-matrix tool to look up, as declared in the configuration. - - Returns - ------- - 'ChromaticityResponseMatrix' - The chromaticity response-matrix tool registered under ``name``. - """ - return self._get("ChromaticityResponseMatrix tool", name, self._TOOLS) - - # ---- Tune --------------------------------------------------------- - - def get_tune_tuning(self, name: str) -> "Tune": - """ - Return a named tune correction tool. - - Parameters - ---------- - name : str - Name of the tune correction tool to look up, as declared in the configuration. - - Returns - ------- - 'Tune' - The tune correction tool registered under ``name``. - """ - return self._get("Tune tuning tool", name, self._TOOLS) - - def get_trm_tuning(self, name: str) -> "TuneResponseMatrix": - """ - Return a named tune response-matrix tool. - - Parameters - ---------- - name : str - Name of the tune response-matrix tool to look up, as declared in the configuration. - - Returns - ------- - 'TuneResponseMatrix' - The tune response-matrix tool registered under ``name``. - """ - return self._get("TuneResponseMatrix tool", name, self._TOOLS) - - # ---- Orbit -------------------------------------------------------- - - def get_orbit_tuning(self, name: str) -> "Orbit": - """ - Return a named orbit correction tool. - - Parameters - ---------- - name : str - Name of the orbit correction tool to look up, as declared in the configuration. - - Returns - ------- - 'Orbit' - The orbit correction tool registered under ``name``. - """ - return self._get("Orbit tuning tool", name, self._TOOLS) - - def get_orm_tuning(self, name: str) -> "OrbitResponseMatrix": - """ - Return a named orbit response-matrix tool. - - Parameters - ---------- - name : str - Name of the orbit response-matrix tool to look up, as declared in the configuration. - - Returns - ------- - 'OrbitResponseMatrix' - The orbit response-matrix tool registered under ``name``. - """ - return self._get("OrbitResponseMatrix tool", name, self._TOOLS) - # ---- BBA -------------------------------------------------------- def get_bba(self, name: str) -> "BBA": @@ -776,24 +620,6 @@ def get_bba(self, name: str) -> "BBA": """ return self._get("BBA tool", name, self._TOOLS) - # ---- Dispersive orbit -------------------------------------------- - - def get_dispersion_tuning(self, name: str) -> "Dispersion": - """ - Return a named dispersion tuning tool. - - Parameters - ---------- - name : str - Name of the dispersion tuning tool to look up, as declared in the configuration. - - Returns - ------- - 'Dispersion' - The dispersion tuning tool registered under ``name``. - """ - return self._get("Dispersion tool", name, self._TOOLS) - def _get_array(self, name: str): """ Generic array resolver used by YellowPages. @@ -864,7 +690,7 @@ def _set_energy(self, E: float): Energy in eV """ # Needed by energy dependant element (i.e. magnet coil current calculation) - for m in self.get_all_elements(): + for m in self._ALL.values(): m.set_energy(E) def _set_mcf(self, alphac: float): @@ -877,7 +703,7 @@ def _set_mcf(self, alphac: float): Moment compaction factor """ # Needed by some off energy dependant element (i.e. chromaticty tools) - for m in self.get_all_elements(): + for m in self._ALL.values(): m.set_mcf(alphac) def _set_harmonic(self, h: int): @@ -889,5 +715,5 @@ def _set_harmonic(self, h: int): h : int Harmonic number """ - for m in self.get_all_elements(): + for m in self._ALL.values(): m.set_harmonic(h) diff --git a/pyaml/tuning_tools/bba2.py b/pyaml/tuning_tools/bba2.py index 05544687..5d6e5f2b 100644 --- a/pyaml/tuning_tools/bba2.py +++ b/pyaml/tuning_tools/bba2.py @@ -274,7 +274,7 @@ def quadrupole(self) -> "Magnet": def tune_correction(self) -> "Tune": """Return the tune-correction tool used during alignment.""" self.check_peer() - return self.peer.get_tune_tuning(self.tune_correction_name) + return self.peer.tool.get(self.tune_correction_name) @staticmethod def _x_intercept(x, k, n): @@ -360,8 +360,8 @@ def _init_responses( sth = design.magnet.get(steererhname) stv = design.magnet.get(steerervname) orbit = design.diagnostic.bpms.get(bpmname).positions - tune_design = design.get_tune_tuning(tunename) - tune_live = self._peer.get_tune_tuning(tunename) + tune_design = design.tool.get(tunename) + tune_live = self._peer.tool.get(tunename) # Get tune from live and adjust the model to improve quad response phase tune0 = tune_design.readback() diff --git a/pyaml/tuning_tools/chromaticity_monitor.py b/pyaml/tuning_tools/chromaticity_monitor.py index f9bfa525..c03e284f 100644 --- a/pyaml/tuning_tools/chromaticity_monitor.py +++ b/pyaml/tuning_tools/chromaticity_monitor.py @@ -201,7 +201,7 @@ def __init__( def tune_monitor(self) -> "BetatronTuneMonitor": """Return the betatron tune monitor used for measurements.""" self.check_peer() - return self.peer.get_betatron_tune_monitor(self.betatron_tune_name) + return self.peer.diagnostic.get(self.betatron_tune_name) @property def rf_plant(self) -> "RFPlant": diff --git a/pyaml/tuning_tools/tune.py b/pyaml/tuning_tools/tune.py index 3c336d31..18811bba 100644 --- a/pyaml/tuning_tools/tune.py +++ b/pyaml/tuning_tools/tune.py @@ -153,7 +153,7 @@ def response_matrix(self) -> ResponseMatrixData | None: def tune_monitor(self) -> "BetatronTuneMonitor": """Return the betatron tune monitor used by the correction.""" self.check_peer() - return self.peer.get_betatron_tune_monitor(self.betatron_tune_name) + return self.peer.diagnostic.get(self.betatron_tune_name) @property def quadrupoles(self) -> "MagnetArray": diff --git a/pyaml/tuning_tools/tune_response_matrix.py b/pyaml/tuning_tools/tune_response_matrix.py index 380a4105..fe65e0d1 100644 --- a/pyaml/tuning_tools/tune_response_matrix.py +++ b/pyaml/tuning_tools/tune_response_matrix.py @@ -154,7 +154,7 @@ def quadrupoles(self) -> "MagnetArray": def tune_monitor(self) -> "BetatronTuneMonitor": """Return the betatron tune monitor used for the measurement.""" self.check_peer() - return self.peer.get_betatron_tune_monitor(self.betatron_tune_name) + return self.peer.diagnostic.get(self.betatron_tune_name) def measure( self, diff --git a/tests/arrays/test_array_selection_types.py b/tests/arrays/test_array_selection_types.py index 11e65181..8dce804e 100644 --- a/tests/arrays/test_array_selection_types.py +++ b/tests/arrays/test_array_selection_types.py @@ -44,7 +44,7 @@ def test_magnet_holder_selection_uses_the_same_typing(design): def test_mixed_array_stays_generic_until_only_magnets_are_selected(design): - mixed = design.get_elements("ElArray") + mixed = design.get("ElArray") assert type(mixed[:]) is ElementArray assert mixed[:].names() == mixed.names() diff --git a/tests/arrays/test_arrays.py b/tests/arrays/test_arrays.py index 62f9c202..5bd02a3d 100644 --- a/tests/arrays/test_arrays.py +++ b/tests/arrays/test_arrays.py @@ -164,10 +164,10 @@ def test_arrays(install_test_package): assert np.abs(pos[1][1] - 7.4265634524358045e-06) < 1e-10 # Radom array - elts = sr.design.get_elements("ElArray") + elts = sr.design.get("ElArray") # Create an array that contains all elements - allElts = ElementArray("AllElements", sr.design.get_all_elements()) + allElts = ElementArray("AllElements", sr.design.get()) assert len(allElts) == 11 # Create an array that contains all elements @@ -210,7 +210,7 @@ def test_arrays(install_test_package): # Test dynamic arrays sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", include_locations=False) - ae = ElementArray("All", sr.design.get_all_elements()) + ae = ElementArray("All", sr.design.get()) acfm = ElementArray("AllCFM", sr.design.combined_function_magnet.all(), use_aggregator=False) bpmC5 = ae["BPM*"][10:20] # All BPM C5 diff --git a/tests/arrays/test_arrays_ops.py b/tests/arrays/test_arrays_ops.py index 5fd706e2..fd8c961f 100644 --- a/tests/arrays/test_arrays_ops.py +++ b/tests/arrays/test_arrays_ops.py @@ -43,7 +43,7 @@ def test_element_array_and_mask_filters_and_is_autotyped_list_mask( sr.design.get_lattice().disable_6d() # "ElArray" is a mixed ElementArray in the dummy config (see existing tests) - elts = sr.design.get_elements("ElArray") + elts = sr.design.get("ElArray") assert isinstance(elts, ElementArray) assert len(elts) > 0 @@ -71,7 +71,7 @@ def test_element_array_and_mask_filters_and_is_autotyped_numpy_mask( sr = accelerator_from_fragments(*sr_configuration_fragments) sr.design.get_lattice().disable_6d() - elts = sr.design.get_elements("ElArray") + elts = sr.design.get("ElArray") assert len(elts) > 0 mask_list = [isinstance(e, Magnet) for e in elts] @@ -97,7 +97,7 @@ def test_element_array_sub_mask_removes_true_inverse_of_and( sr = accelerator_from_fragments(*sr_configuration_fragments) sr.design.get_lattice().disable_6d() - elts = sr.design.get_elements("ElArray") + elts = sr.design.get("ElArray") assert len(elts) > 0 # Keep only magnets with '& mask' @@ -134,7 +134,7 @@ def test_element_array_mask_length_mismatch_raises_for_and_and_sub( sr = accelerator_from_fragments(*sr_configuration_fragments) sr.design.get_lattice().disable_6d() - elts = sr.design.get_elements("ElArray") + elts = sr.design.get("ElArray") assert len(elts) > 0 bad_mask = [True] * (len(elts) - 1) @@ -159,7 +159,7 @@ def test_mask_by_type_returns_correct_boolean_mask( sr = accelerator_from_fragments(*sr_configuration_fragments) sr.design.get_lattice().disable_6d() - elts = sr.design.get_elements("ElArray") + elts = sr.design.get("ElArray") mask = elts.mask_by_type(Magnet) assert isinstance(mask, list) @@ -182,7 +182,7 @@ def test_filter_by_type_returns_autotyped_array(install_test_package, accelerato sr = accelerator_from_fragments(*sr_configuration_fragments) sr.design.get_lattice().disable_6d() - elts = sr.design.get_elements("ElArray") + elts = sr.design.get("ElArray") filtered = elts.of_type(Magnet) if len(filtered) == 0: diff --git a/tests/common/test_element_holder_collection.py b/tests/common/test_element_holder_collection.py index 3fdfc88d..a90a1523 100644 --- a/tests/common/test_element_holder_collection.py +++ b/tests/common/test_element_holder_collection.py @@ -22,7 +22,7 @@ def test_exact_name_returns_the_element_or_raises(holder): def test_get_and_full_slice_keep_registration_order(holder): - names = [element.get_name() for element in holder.get_all_elements()] + names = [element.get_name() for element in holder.get()] assert type(holder.get()) is ElementArray assert type(holder[:]) is ElementArray @@ -79,7 +79,7 @@ def test_colons_are_part_of_names(holder): def test_magnet_subclasses_share_a_typed_array_in_either_order(holder): horizontal = holder.magnet.get("SH1A-C01-H") vertical = holder.magnet.get("SH1A-C01-V") - start = holder.get_all_elements().index(horizontal) + start = holder.get().index(horizontal) assert type(horizontal) is not type(vertical) assert isinstance(holder["SH1A-C01-[HV]"], MagnetArray) @@ -97,7 +97,7 @@ def test_mixed_selection_returns_a_generic_array(holder): def test_indices_and_slices_follow_insertion_order(holder): - registered = holder.get_all_elements() + registered = holder.get() assert holder[0] is registered[0] assert holder[-1] is registered[-1] @@ -119,7 +119,7 @@ def test_empty_holder_returns_empty_collections(ebs_lattice_file): def test_invalid_indices_and_keys_raise_clear_errors(holder): - size = len(holder.get_all_elements()) + size = len(holder.get()) with pytest.raises(IndexError): holder[size] @@ -132,14 +132,21 @@ def test_invalid_indices_and_keys_raise_clear_errors(holder): def test_selection_intersects_with_a_configured_family(holder): - selected = holder["SH1A-C0?-H"] & holder.get_elements("ElArray") + selected = holder["SH1A-C0?-H"] & holder.get("ElArray") assert isinstance(selected, MagnetArray) assert selected.names() == ["SH1A-C02-H"] - assert holder.get_element("SH1A-C02-H") is holder["SH1A-C02-H"] - assert holder.get_all_elements() == list(holder.get()) + + +def test_get_resolves_a_named_array_regardless_of_its_concrete_family(holder): + """`get(name)` must not be limited to generic element arrays, unlike the old `get_elements`.""" + assert isinstance(holder.get("HCORR"), MagnetArray) + assert holder.get("HCORR").names() == ["SH1A-C01-H", "SH1A-C02-H"] + assert isinstance(holder.get("BPMS"), BPMArray) + assert holder.get("BPMS").names() == ["BPM_C04-01", "BPM_C04-02"] + assert holder.get("ElArray").names() == ["BPM_C04-01", "BPM_C04-02", "SH1A-C01-V", "SH1A-C02-H"] with pytest.raises(PyAMLException): - holder.get_element("UNKNOWN") + holder.get("UNKNOWN") def test_existing_array_field_filters_still_work(holder): @@ -204,7 +211,7 @@ def test_disjoint_regex_and_list_selections_produce_a_plain_list(holder): def test_selection_combined_with_a_configured_family_via_regex_and_list(holder): """`re:` and list-of-patterns selections intersect with a configured family, same as wildcards.""" - el_array = holder.get_elements("ElArray") # BPM_C04-01, BPM_C04-02, SH1A-C01-V, SH1A-C02-H + el_array = holder.get("ElArray") # BPM_C04-01, BPM_C04-02, SH1A-C01-V, SH1A-C02-H by_regex = holder["re:^SH1A-C0[12]-H$"] & el_array assert isinstance(by_regex, MagnetArray) @@ -272,7 +279,7 @@ def test_getitem_supports_an_exclusion_in_a_list(holder): def test_getitem_lone_exclusion_pattern_means_everything_except(holder): - all_names = holder.get_all_elements() + all_names = holder.get() selected = holder["~QF1A-C01"] assert "QF1A-C01" not in selected.names() diff --git a/tests/diagnostics/test_diagnostic_accessors.py b/tests/diagnostics/test_diagnostic_accessors.py index b4c6f58b..0046d975 100644 --- a/tests/diagnostics/test_diagnostic_accessors.py +++ b/tests/diagnostics/test_diagnostic_accessors.py @@ -14,7 +14,7 @@ def test_diagnostic_get_returns_named_monitor(): include_locations=False, ).design - assert design.diagnostic.get("BETATRON_TUNE") is design.get_betatron_tune_monitor("BETATRON_TUNE") + assert design.diagnostic.get("BETATRON_TUNE") is design._DIAG["BETATRON_TUNE"] def test_diagnostic_get_with_no_name_returns_all_configured_diagnostics(): @@ -25,7 +25,7 @@ def test_diagnostic_get_with_no_name_returns_all_configured_diagnostics(): ).design all_diagnostics = design.diagnostic.get() - assert design.get_betatron_tune_monitor("BETATRON_TUNE") in all_diagnostics + assert design.diagnostic.get("BETATRON_TUNE") in all_diagnostics def test_diagnostic_betatron_tune_returns_default_monitor(): @@ -35,7 +35,7 @@ def test_diagnostic_betatron_tune_returns_default_monitor(): include_locations=False, ).design - assert design.diagnostic.betatron_tune is design.get_betatron_tune_monitor("BETATRON_TUNE") + assert design.diagnostic.betatron_tune is design.diagnostic.get("BETATRON_TUNE") def test_diagnostic_raises_when_default_missing(ebs_lattice_file): @@ -128,7 +128,7 @@ def test_diagnostic_getitem_list_selection_ignores_request_order(): ignore_external=True, include_locations=False, ).design - spare_monitor = copy.copy(design.get_betatron_tune_monitor("BETATRON_TUNE")) + spare_monitor = copy.copy(design.diagnostic.get("BETATRON_TUNE")) spare_monitor._name = "SPARE_BETATRON_TUNE" design._DIAG["SPARE_BETATRON_TUNE"] = spare_monitor diff --git a/tests/integration/test_dt4acc_twin_smoke.py b/tests/integration/test_dt4acc_twin_smoke.py index 44220e09..8bb2c634 100644 --- a/tests/integration/test_dt4acc_twin_smoke.py +++ b/tests/integration/test_dt4acc_twin_smoke.py @@ -135,8 +135,8 @@ def deactivated_test_orbit_correction(config_key: str): accelerator = _build_accelerator(config_key) control_mode = accelerator.live bpms = control_mode.diagnostic.bpms.get("bpms") - orbit_response_matrix = control_mode.get_orm_tuning("DEFAULT_ORBIT_RESPONSE_MATRIX") - orbit_correction = control_mode.get_orbit_tuning("DEFAULT_ORBIT_CORRECTION") + orbit_response_matrix = control_mode.tool.get("DEFAULT_ORBIT_RESPONSE_MATRIX") + orbit_correction = control_mode.tool.get("DEFAULT_ORBIT_CORRECTION") orbit_response_matrix.measure() ormdata = orbit_response_matrix.get() orbit_response_matrix.save("orm.json") diff --git a/tests/magnet/test_serialized_magnets.py b/tests/magnet/test_serialized_magnets.py index 1e95ca70..b362f7b7 100644 --- a/tests/magnet/test_serialized_magnets.py +++ b/tests/magnet/test_serialized_magnets.py @@ -27,11 +27,11 @@ def test_config_load(sr_file): sr: Accelerator = Accelerator.load(sr_file, include_locations=False, ignore_external=True) assert sr is not None magnets = [ - sr.design.get_element("QF8B-C04"), - sr.design.get_element("QF8B-C04"), - sr.design.get_element("QD5D-C04"), - sr.design.get_element("QF6D-C04"), - sr.design.get_element("QF4D-C04"), + sr.design["QF8B-C04"], + sr.design["QF8B-C04"], + sr.design["QD5D-C04"], + sr.design["QF6D-C04"], + sr.design["QF4D-C04"], ] assert None not in [magnets] @@ -115,7 +115,7 @@ def test_tune(sr_file): assert len(m.get_magnets()) == m.get_nb_magnets() quadForTuneDesign = sr.design.serialized_magnets.get("QForTune") - tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE") + tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE") # Build tune response matrix tunemat = np.zeros((len(quadForTuneDesign), 2)) diff --git a/tests/test_accelerator_load.py b/tests/test_accelerator_load.py index 0bc649ce..aa5df3ef 100644 --- a/tests/test_accelerator_load.py +++ b/tests/test_accelerator_load.py @@ -9,10 +9,10 @@ def test_peer(): sr = Accelerator.load("tests/config/tune_monitor.yaml") - tm = sr.design.get_betatron_tune_monitor("BETATRON_TUNE") + tm = sr.design.diagnostic.get("BETATRON_TUNE") assert isinstance(tm.peer.peer, Accelerator) assert isinstance(tm.peer, ElementHolder) - tm = sr.live.get_betatron_tune_monitor("BETATRON_TUNE") + tm = sr.live.diagnostic.get("BETATRON_TUNE") assert isinstance(tm.peer.peer, Accelerator) assert isinstance(tm.peer, ElementHolder) @@ -160,5 +160,5 @@ def test_config_dict(): assert sr.live.dconfig()["prefix"] == "VA:" assert sr.live.dconfig()["info"]["param1"] == "Param1 value" assert sr.live.dconfig()["info"]["param2"] == 12345.0 - assert isinstance(sr.live.get_element("MY_ELEMENT"), MyElement) - assert sr.live.get_element("MY_ELEMENT")._cfg.device_h == "TUNEZR:rdH" + assert isinstance(sr.live["MY_ELEMENT"], MyElement) + assert sr.live["MY_ELEMENT"]._cfg.device_h == "TUNEZR:rdH" diff --git a/tests/test_load_conf_with_code.py b/tests/test_load_conf_with_code.py index 25a98a8d..41771dbf 100644 --- a/tests/test_load_conf_with_code.py +++ b/tests/test_load_conf_with_code.py @@ -14,7 +14,7 @@ def test_load_conf_with_code(): assert sr.live[bpms[0].get_name()] is bpms[0] assert sr.live["BPM*"].names() == bpms.names() - assert sr.live[:].names() == [element.get_name() for element in sr.live.get_all_elements()] + assert sr.live[:].names() == [element.get_name() for element in sr.live.get()] assert sr.design["BPM*"].names() == sr.design.diagnostic.bpms.get("BPM").names() assert sr.live.diagnostic.bpms.BPM is bpms diff --git a/tests/tuning_tools/test_tool_accessors.py b/tests/tuning_tools/test_tool_accessors.py index a5dd2500..1b064490 100644 --- a/tests/tuning_tools/test_tool_accessors.py +++ b/tests/tuning_tools/test_tool_accessors.py @@ -13,7 +13,7 @@ def test_tuning_tools_expose_configured_elements(): ) design = sr.design - tune_monitor = design.get_betatron_tune_monitor("BETATRON_TUNE") + tune_monitor = design.diagnostic.get("BETATRON_TUNE") quadrupoles = design.magnets.get("QForTune") assert design.tool.tune.tune_monitor is tune_monitor assert design.tool.tune.quadrupoles is quadrupoles diff --git a/tests/tuning_tools/test_tune.py b/tests/tuning_tools/test_tune.py index a114230c..fe23a48e 100644 --- a/tests/tuning_tools/test_tune.py +++ b/tests/tuning_tools/test_tune.py @@ -14,7 +14,7 @@ def test_tune(): sr.design.get_lattice().disable_6d() quadForTuneDesign = sr.design.magnets.get("QForTune") - tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE") + tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE") # Build tune response matrix tune = tune_monitor.tune.get() print(tune) diff --git a/tests/tuning_tools/test_tune_hardware.py b/tests/tuning_tools/test_tune_hardware.py index 8e83197d..e48ce265 100644 --- a/tests/tuning_tools/test_tune_hardware.py +++ b/tests/tuning_tools/test_tune_hardware.py @@ -12,7 +12,7 @@ def test_tune(): # Build tune response matrix (hardware units) - tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE") + tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE") tune = tune_monitor.tune.get() print(tune) tunemat = np.zeros((len(quadForTuneDesign), 2)) diff --git a/tests/tuning_tools/test_tune_monitor.py b/tests/tuning_tools/test_tune_monitor.py index 893f096e..66694c37 100644 --- a/tests/tuning_tools/test_tune_monitor.py +++ b/tests/tuning_tools/test_tune_monitor.py @@ -11,7 +11,7 @@ def test_simulator_tune_monitor( ignore_external=True, ) sr.design.get_lattice().disable_6d() - tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE") + tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE") assert tune_monitor.tune.get()[0] == sr.design.get_lattice().get_tune()[0] assert tune_monitor.tune.get()[1] == sr.design.get_lattice().get_tune()[1] assert np.abs(tune_monitor.frequency.get()[0] - 56834.22592393) < 1e-6 @@ -31,6 +31,6 @@ def test_controlsystem_tune_monitor( sr = accelerator_from_fragments( *tune_monitor_configuration_fragments, ) - tune_monitor = sr.live.get_betatron_tune_monitor("BETATRON_TUNE") + tune_monitor = sr.live.diagnostic.get("BETATRON_TUNE") assert tune_monitor.tune.get()[0] == 0.0 assert tune_monitor.tune.get()[1] == 0.0 From 5ec15ea52d3f21b10e96839fb35577aea9380faa Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Thu, 1 Oct 2026 17:40:34 +0200 Subject: [PATCH 15/16] Remove ElementHolder.get_chromaticity_monitor/get_bba, superseded by tool.get(name) --- .../02-chromaticity_measurement.ipynb | 2 +- .../use_cases/02-chromaticity_measurement.py | 2 +- pyaml/common/holders/element_holder.py | 43 ------------------- pyaml/tuning_tools/bba.py | 2 +- pyaml/tuning_tools/bba2.py | 2 +- pyaml/tuning_tools/chromaticity.py | 2 +- .../chromaticity_response_matrix.py | 2 +- tests/integration/test_dt4acc_twin_smoke.py | 2 +- tests/tuning_tools/test_bba.py | 4 +- .../tuning_tools/test_chromaticity_monitor.py | 4 +- tests/tuning_tools/test_tool_accessors.py | 6 +-- 11 files changed, 14 insertions(+), 57 deletions(-) diff --git a/examples/use_cases/02-chromaticity_measurement.ipynb b/examples/use_cases/02-chromaticity_measurement.ipynb index 9ac1afca..05ea57a2 100644 --- a/examples/use_cases/02-chromaticity_measurement.ipynb +++ b/examples/use_cases/02-chromaticity_measurement.ipynb @@ -267,7 +267,7 @@ } ], "source": [ - "chroma_monitor = SR.get_chromaticity_monitor(\"CHROMATICITY_MONITOR\")\n", + "chroma_monitor = SR.tool.get(\"CHROMATICITY_MONITOR\")\n", "\n", "chroma_monitor.measure(\n", " callback=chroma_callback,\n", diff --git a/examples/use_cases/02-chromaticity_measurement.py b/examples/use_cases/02-chromaticity_measurement.py index 966b23ef..320aa0b9 100644 --- a/examples/use_cases/02-chromaticity_measurement.py +++ b/examples/use_cases/02-chromaticity_measurement.py @@ -109,7 +109,7 @@ def chroma_callback(action: int, cb_data: dict): # In[17]: -chroma_monitor = SR.get_chromaticity_monitor("CHROMATICITY_MONITOR") +chroma_monitor = SR.tool.get("CHROMATICITY_MONITOR") chroma_monitor.measure( callback=chroma_callback, diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index 65291b2a..f5880dd2 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -11,7 +11,6 @@ from ...magnet.serialized_magnet import SerializedMagnets from ...rf.rf_plant import RFPlant from ...rf.rf_transmitter import RFTransmitter -from ...tuning_tools.chromaticity_monitor import ChromaticityMonitor from ..abstract_aggregator import ScalarAggregator from ..element import Element from ..exception import PyAMLException @@ -31,7 +30,6 @@ if TYPE_CHECKING: from ...accelerator import Accelerator from ...configuration.unbound_element import UnboundElement - from ...tuning_tools.bba import BBA from ...tuning_tools.measurement_tool import MeasurementTool from ...tuning_tools.tuning_tool import TuningTool @@ -84,10 +82,6 @@ class ElementHolder(metaclass=ABCMeta): Add a betatron tune monitor to the diagnostics store. add_tool(tool) Add a tuning or measurement tool to the tool store. - get_chromaticity_monitor(name) - Return a named chromaticity monitor. - get_bba(name) - Return a named beam-based alignment tool. """ def __init__(self): @@ -583,43 +577,6 @@ def add_tool(self, tool: Element): """ self._add(self._TOOLS, tool) - # ---- Chromaticity ------------------------------------------------- - - def get_chromaticity_monitor(self, name: str) -> ChromaticityMonitor: - """ - Return a named chromaticity monitor. - - Parameters - ---------- - name : str - Name of the chromaticity monitor to look up, as declared in the configuration. - - Returns - ------- - ChromaticityMonitor - The chromaticity monitor registered under ``name``. - """ - obj = self._get("Chromaticity monitor", name, self._TOOLS) - return obj - - # ---- BBA -------------------------------------------------------- - - def get_bba(self, name: str) -> "BBA": - """ - Return a named beam-based alignment tool. - - Parameters - ---------- - name : str - Name of the beam-based alignment tool to look up, as declared in the configuration. - - Returns - ------- - 'BBA' - The beam-based alignment tool registered under ``name``. - """ - return self._get("BBA tool", name, self._TOOLS) - def _get_array(self, name: str): """ Generic array resolver used by YellowPages. diff --git a/pyaml/tuning_tools/bba.py b/pyaml/tuning_tools/bba.py index d5cc32df..05eb9b8e 100644 --- a/pyaml/tuning_tools/bba.py +++ b/pyaml/tuning_tools/bba.py @@ -206,7 +206,7 @@ def measure( sr = Accelerator.load("tests/config/EBSOrbit.yaml") SR = sr.design - bba = SR.get_bba("BBA-BPM_C04-04") + bba = SR.tool.get("BBA-BPM_C04-04") # Add a misalignement SR.get_bpm("BPM_C04-04").offset.set([20e-6,-15e-6]) diff --git a/pyaml/tuning_tools/bba2.py b/pyaml/tuning_tools/bba2.py index 5d6e5f2b..1e34d80d 100644 --- a/pyaml/tuning_tools/bba2.py +++ b/pyaml/tuning_tools/bba2.py @@ -585,7 +585,7 @@ def measure( sr = Accelerator.load("tests/config/EBSOrbit.yaml") SR = sr.live - bba = SR.get_bba("BBA2-BPM_C04-04") + bba = SR.tool.get("BBA2-BPM_C04-04") # Add a misalignement SR.get_bpm("BPM_C04-04").offset.set([200e-6,-150e-6]) diff --git a/pyaml/tuning_tools/chromaticity.py b/pyaml/tuning_tools/chromaticity.py index 94d475ee..d43c4672 100644 --- a/pyaml/tuning_tools/chromaticity.py +++ b/pyaml/tuning_tools/chromaticity.py @@ -135,7 +135,7 @@ def load(self, load_path: Path): def chromaticity_monitor(self) -> "ChromaticityMonitor": """Return the chromaticity monitor used for readback.""" self.check_peer() - return self.peer.get_chromaticity_monitor(self._chromaticity_monitor_name) + return self.peer.tool.get(self._chromaticity_monitor_name) @property def sextupoles(self) -> "MagnetArray": diff --git a/pyaml/tuning_tools/chromaticity_response_matrix.py b/pyaml/tuning_tools/chromaticity_response_matrix.py index 4d739e0e..23d712ed 100644 --- a/pyaml/tuning_tools/chromaticity_response_matrix.py +++ b/pyaml/tuning_tools/chromaticity_response_matrix.py @@ -115,7 +115,7 @@ def sextupoles(self) -> "MagnetArray": def chromaticity_monitor(self) -> "ChromaticityMonitor": """Return the chromaticity monitor used for the measurement.""" self.check_peer() - return self.peer.get_chromaticity_monitor(self.chromaticity_name) + return self.peer.tool.get(self.chromaticity_name) def measure( self, diff --git a/tests/integration/test_dt4acc_twin_smoke.py b/tests/integration/test_dt4acc_twin_smoke.py index 8bb2c634..1e891627 100644 --- a/tests/integration/test_dt4acc_twin_smoke.py +++ b/tests/integration/test_dt4acc_twin_smoke.py @@ -179,7 +179,7 @@ def deactivated_test_chromaticity_measurement(config_key: str): accelerator = _build_accelerator(config_key) control_mode = accelerator.live - chromaticity_measurement = control_mode.get_chromaticity_monitor("DEFAULT_CHROMATICITY_MEASUREMENT") + chromaticity_measurement = control_mode.tool.get("DEFAULT_CHROMATICITY_MEASUREMENT") def chroma_callback(action: int, cb_data: dict): if action == Action.MEASURE: diff --git a/tests/tuning_tools/test_bba.py b/tests/tuning_tools/test_bba.py index f4247103..22f60c14 100644 --- a/tests/tuning_tools/test_bba.py +++ b/tests/tuning_tools/test_bba.py @@ -12,13 +12,13 @@ def test_bba(): SR.diagnostic.bpm.get("BPM_C04-04").offset.set([20e-6, -15e-6]) # BBA (standard bow tie, model independant) - bba = SR.get_bba("BBA-BPM_C04-04") + bba = SR.tool.get("BBA-BPM_C04-04") bba.measure() assert np.abs(bba.h_offset() - 20e-6) < 1e-6 assert np.abs(bba.v_offset() + 15e-6) < 1e-6 # BBA (model dependant method) - bba = SR.get_bba("BBA2-BPM_C04-04") + bba = SR.tool.get("BBA2-BPM_C04-04") bba.minicycle_sleep_time = 0 bba.measure() assert np.abs(bba.h_offset() - 20e-6) < 1e-6 diff --git a/tests/tuning_tools/test_chromaticity_monitor.py b/tests/tuning_tools/test_chromaticity_monitor.py index 3f7671d9..4f9c7e11 100644 --- a/tests/tuning_tools/test_chromaticity_monitor.py +++ b/tests/tuning_tools/test_chromaticity_monitor.py @@ -13,7 +13,7 @@ def test_simulator_chromaticity_monitor(): sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", ignore_external=True) sr.design.get_lattice().enable_6d() chromaAT = sr.design.get_lattice().get_chrom()[:-1] - chromaticity_monitor = sr.design.get_chromaticity_monitor("CHROMATICITY_MONITOR") + chromaticity_monitor = sr.design.tool.get("CHROMATICITY_MONITOR") assert chromaticity_monitor.chromaticity.unit() == "1" assert chromaticity_monitor.dispersion.unit() == "m" chromaticity_monitor.measure(fit_dispersion=True, callback=callback) @@ -43,7 +43,7 @@ def test_simulator_chromaticity_monitor(): ) def test_controlsystem_chromaticity_monitor(install_test_package): sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml") - chromaticity_monitor = sr.live.get_chromaticity_monitor("CHROMATICITY_MONITOR") + chromaticity_monitor = sr.live.tool.get("CHROMATICITY_MONITOR") assert chromaticity_monitor.chromaticity.get() is None chromaticity_monitor.measure( do_plot=False, diff --git a/tests/tuning_tools/test_tool_accessors.py b/tests/tuning_tools/test_tool_accessors.py index 1b064490..f582040a 100644 --- a/tests/tuning_tools/test_tool_accessors.py +++ b/tests/tuning_tools/test_tool_accessors.py @@ -20,7 +20,7 @@ def test_tuning_tools_expose_configured_elements(): assert design.tool.trm.tune_monitor is tune_monitor assert design.tool.trm.quadrupoles is quadrupoles - chromaticity_monitor = design.get_chromaticity_monitor("CHROMATICITY_MONITOR") + chromaticity_monitor = design.tool.get("CHROMATICITY_MONITOR") sextupoles = design.magnets.get("Sext") assert design.tool.chromaticity.chromaticity_monitor is chromaticity_monitor assert design.tool.chromaticity.sextupoles is sextupoles @@ -47,14 +47,14 @@ def test_tuning_tools_expose_configured_elements(): assert design.tool.orm.vcorrectors is vcorrectors for name in ("BBA-BPM_C04-04", "BBA2-BPM_C04-04"): - bba = design.get_bba(name) + bba = design.tool.get(name) assert bba.bpms is bpms assert bba.bpm is design.diagnostic.bpm.get("BPM_C04-04") assert bba.hcorrector is design.magnet.get("SF2E-C02-H") assert bba.vcorrector is design.magnet.get("SD1A-C26-V") assert bba.quadrupole is design.magnet.get("QF6B-C04") - assert design.get_bba("BBA2-BPM_C04-04").tune_correction is design.tool.tune + assert design.tool.get("BBA2-BPM_C04-04").tune_correction is design.tool.tune def test_tool_get_returns_named_tool(): From b93d97d45fffd0ddfcb4d163ad371ab3a04f0663 Mon Sep 17 00:00:00 2001 From: guillaumepichon Date: Mon, 5 Oct 2026 09:51:41 +0200 Subject: [PATCH 16/16] Moving BPMs to diagnostics --- .../ControlSystem/tango/config.yaml | 2 +- examples/use_cases/config/bessy2/bessy2.yaml | 246 +++---- examples/use_cases/config/esrf/esrf.yaml | 640 +++++++++--------- .../use_cases/config/soleil_ii/devices.yaml | 360 +++++----- pyaml/apidoc/gen_api.py | 2 +- pyaml/arrays/bpm_array.py | 9 +- pyaml/arrays/element_array.py | 3 +- pyaml/bpm/__init__.py | 0 pyaml/common/holders/element_holder.py | 3 +- pyaml/common/holders/sub_holders.py | 3 +- pyaml/control/controlsystem.py | 3 +- pyaml/diagnostics/bpm/__init__.py | 3 + pyaml/{ => diagnostics}/bpm/bpm.py | 12 +- pyaml/lattice/simulator.py | 3 +- pyaml/tuning_tools/bba.py | 3 +- pyaml/tuning_tools/bba2.py | 3 +- .../common/test_element_holder_collection.py | 2 +- tests/common/test_errors.py | 14 +- tests/config/EBSOrbit.yaml | 640 +++++++++--------- tests/config/bad_conf_duplicate_2.yaml | 6 +- tests/config/bad_conf_duplicate_3.yaml | 8 +- tests/config/bpms.yaml | 8 +- tests/config/config_manager_sr_devices.yaml | 4 +- tests/config/sr.yaml | 4 +- .../test_configuration_manager.py | 4 +- tests/{ => diagnostics}/bpm/test_bpm.py | 0 .../bpm/test_bpm_controlsystem.py | 0 tests/test_catalogs.py | 6 +- 28 files changed, 1002 insertions(+), 989 deletions(-) delete mode 100644 pyaml/bpm/__init__.py create mode 100644 pyaml/diagnostics/bpm/__init__.py rename pyaml/{ => diagnostics}/bpm/bpm.py (94%) rename tests/{ => diagnostics}/bpm/test_bpm.py (100%) rename tests/{ => diagnostics}/bpm/test_bpm_controlsystem.py (100%) diff --git a/examples/other_examples/ControlSystem/tango/config.yaml b/examples/other_examples/ControlSystem/tango/config.yaml index 22881f75..1c87c843 100644 --- a/examples/other_examples/ControlSystem/tango/config.yaml +++ b/examples/other_examples/ControlSystem/tango/config.yaml @@ -8,7 +8,7 @@ controls: name: live data_folder: /data/store devices: -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-01 x_pos: srdiag/bpm/c01-01/SA_HPosition y_pos: srdiag/bpm/c01-01/SA_VPosition diff --git a/examples/use_cases/config/bessy2/bessy2.yaml b/examples/use_cases/config/bessy2/bessy2.yaml index eb493815..8d5d1f35 100644 --- a/examples/use_cases/config/bessy2/bessy2.yaml +++ b/examples/use_cases/config/bessy2/bessy2.yaml @@ -1356,495 +1356,495 @@ devices: unit: 1/m powerconverter: (VS3P1D1R:rdbk, VS3P1D1R:set)[A] hardware_unit: A -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5D1R x_pos: ORBITCC:rdPos@0 y_pos: ORBITCC:rdPos@1 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D1R x_pos: ORBITCC:rdPos@2 y_pos: ORBITCC:rdPos@3 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D1R x_pos: ORBITCC:rdPos@4 y_pos: ORBITCC:rdPos@5 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T1R x_pos: ORBITCC:rdPos@6 y_pos: ORBITCC:rdPos@7 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T1R x_pos: ORBITCC:rdPos@8 y_pos: ORBITCC:rdPos@9 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T1R x_pos: ORBITCC:rdPos@10 y_pos: ORBITCC:rdPos@11 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T1R x_pos: ORBITCC:rdPos@12 y_pos: ORBITCC:rdPos@13 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ41T1R x_pos: ORBITCC:rdPos@14 y_pos: ORBITCC:rdPos@15 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T1R x_pos: ORBITCC:rdPos@16 y_pos: ORBITCC:rdPos@17 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T1R x_pos: ORBITCC:rdPos@18 y_pos: ORBITCC:rdPos@19 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T1R x_pos: ORBITCC:rdPos@20 y_pos: ORBITCC:rdPos@21 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D2R x_pos: ORBITCC:rdPos@22 y_pos: ORBITCC:rdPos@23 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D2R x_pos: ORBITCC:rdPos@24 y_pos: ORBITCC:rdPos@25 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D2R x_pos: ORBITCC:rdPos@26 y_pos: ORBITCC:rdPos@27 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D2R x_pos: ORBITCC:rdPos@28 y_pos: ORBITCC:rdPos@29 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5D2R x_pos: ORBITCC:rdPos@30 y_pos: ORBITCC:rdPos@31 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D2R x_pos: ORBITCC:rdPos@32 y_pos: ORBITCC:rdPos@33 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D2R x_pos: ORBITCC:rdPos@34 y_pos: ORBITCC:rdPos@35 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T2R x_pos: ORBITCC:rdPos@36 y_pos: ORBITCC:rdPos@37 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T2R x_pos: ORBITCC:rdPos@38 y_pos: ORBITCC:rdPos@39 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T2R x_pos: ORBITCC:rdPos@40 y_pos: ORBITCC:rdPos@41 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T2R x_pos: ORBITCC:rdPos@42 y_pos: ORBITCC:rdPos@43 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ41T2R x_pos: ORBITCC:rdPos@44 y_pos: ORBITCC:rdPos@45 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ42T2R x_pos: ORBITCC:rdPos@46 y_pos: ORBITCC:rdPos@47 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ43T2R x_pos: ORBITCC:rdPos@48 y_pos: ORBITCC:rdPos@49 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T2R x_pos: ORBITCC:rdPos@50 y_pos: ORBITCC:rdPos@51 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T2R x_pos: ORBITCC:rdPos@52 y_pos: ORBITCC:rdPos@53 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T2R x_pos: ORBITCC:rdPos@54 y_pos: ORBITCC:rdPos@55 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D3R x_pos: ORBITCC:rdPos@56 y_pos: ORBITCC:rdPos@57 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D3R x_pos: ORBITCC:rdPos@58 y_pos: ORBITCC:rdPos@59 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D3R x_pos: ORBITCC:rdPos@60 y_pos: ORBITCC:rdPos@61 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D3R x_pos: ORBITCC:rdPos@62 y_pos: ORBITCC:rdPos@63 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5D3R x_pos: ORBITCC:rdPos@64 y_pos: ORBITCC:rdPos@65 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D3R x_pos: ORBITCC:rdPos@66 y_pos: ORBITCC:rdPos@67 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D3R x_pos: ORBITCC:rdPos@68 y_pos: ORBITCC:rdPos@69 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T3R x_pos: ORBITCC:rdPos@70 y_pos: ORBITCC:rdPos@71 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T3R x_pos: ORBITCC:rdPos@72 y_pos: ORBITCC:rdPos@73 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T3R x_pos: ORBITCC:rdPos@74 y_pos: ORBITCC:rdPos@75 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T3R x_pos: ORBITCC:rdPos@76 y_pos: ORBITCC:rdPos@77 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T3R x_pos: ORBITCC:rdPos@78 y_pos: ORBITCC:rdPos@79 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T3R x_pos: ORBITCC:rdPos@80 y_pos: ORBITCC:rdPos@81 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T3R x_pos: ORBITCC:rdPos@82 y_pos: ORBITCC:rdPos@83 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D4R x_pos: ORBITCC:rdPos@84 y_pos: ORBITCC:rdPos@85 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D4R x_pos: ORBITCC:rdPos@86 y_pos: ORBITCC:rdPos@87 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D4R x_pos: ORBITCC:rdPos@88 y_pos: ORBITCC:rdPos@89 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D4R x_pos: ORBITCC:rdPos@90 y_pos: ORBITCC:rdPos@91 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5D4R x_pos: ORBITCC:rdPos@92 y_pos: ORBITCC:rdPos@93 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D4R x_pos: ORBITCC:rdPos@94 y_pos: ORBITCC:rdPos@95 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D4R x_pos: ORBITCC:rdPos@96 y_pos: ORBITCC:rdPos@97 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T4R x_pos: ORBITCC:rdPos@98 y_pos: ORBITCC:rdPos@99 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T4R x_pos: ORBITCC:rdPos@100 y_pos: ORBITCC:rdPos@101 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T4R x_pos: ORBITCC:rdPos@102 y_pos: ORBITCC:rdPos@103 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T4R x_pos: ORBITCC:rdPos@104 y_pos: ORBITCC:rdPos@105 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T4R x_pos: ORBITCC:rdPos@106 y_pos: ORBITCC:rdPos@107 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T4R x_pos: ORBITCC:rdPos@108 y_pos: ORBITCC:rdPos@109 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T4R x_pos: ORBITCC:rdPos@110 y_pos: ORBITCC:rdPos@111 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D5R x_pos: ORBITCC:rdPos@112 y_pos: ORBITCC:rdPos@113 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D5R x_pos: ORBITCC:rdPos@114 y_pos: ORBITCC:rdPos@115 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D5R x_pos: ORBITCC:rdPos@116 y_pos: ORBITCC:rdPos@117 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D5R x_pos: ORBITCC:rdPos@118 y_pos: ORBITCC:rdPos@119 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5D5R x_pos: ORBITCC:rdPos@120 y_pos: ORBITCC:rdPos@121 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D5R x_pos: ORBITCC:rdPos@122 y_pos: ORBITCC:rdPos@123 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D5R x_pos: ORBITCC:rdPos@124 y_pos: ORBITCC:rdPos@125 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T5R x_pos: ORBITCC:rdPos@126 y_pos: ORBITCC:rdPos@127 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T5R x_pos: ORBITCC:rdPos@128 y_pos: ORBITCC:rdPos@129 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T5R x_pos: ORBITCC:rdPos@130 y_pos: ORBITCC:rdPos@131 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T5R x_pos: ORBITCC:rdPos@132 y_pos: ORBITCC:rdPos@133 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T5R x_pos: ORBITCC:rdPos@134 y_pos: ORBITCC:rdPos@135 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T5R x_pos: ORBITCC:rdPos@136 y_pos: ORBITCC:rdPos@137 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T5R x_pos: ORBITCC:rdPos@138 y_pos: ORBITCC:rdPos@139 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D6R x_pos: ORBITCC:rdPos@140 y_pos: ORBITCC:rdPos@141 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D6R x_pos: ORBITCC:rdPos@142 y_pos: ORBITCC:rdPos@143 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D6R x_pos: ORBITCC:rdPos@144 y_pos: ORBITCC:rdPos@145 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D6R x_pos: ORBITCC:rdPos@146 y_pos: ORBITCC:rdPos@147 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ41D6R x_pos: ORBITCC:rdPos@148 y_pos: ORBITCC:rdPos@149 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ42D6R x_pos: ORBITCC:rdPos@150 y_pos: ORBITCC:rdPos@151 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ43D6R x_pos: ORBITCC:rdPos@152 y_pos: ORBITCC:rdPos@153 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ44D6R x_pos: ORBITCC:rdPos@154 y_pos: ORBITCC:rdPos@155 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D6R x_pos: ORBITCC:rdPos@156 y_pos: ORBITCC:rdPos@157 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D6R x_pos: ORBITCC:rdPos@158 y_pos: ORBITCC:rdPos@159 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T6R x_pos: ORBITCC:rdPos@160 y_pos: ORBITCC:rdPos@161 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T6R x_pos: ORBITCC:rdPos@162 y_pos: ORBITCC:rdPos@163 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T6R x_pos: ORBITCC:rdPos@164 y_pos: ORBITCC:rdPos@165 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T6R x_pos: ORBITCC:rdPos@166 y_pos: ORBITCC:rdPos@167 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ41T6R x_pos: ORBITCC:rdPos@168 y_pos: ORBITCC:rdPos@169 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T6R x_pos: ORBITCC:rdPos@170 y_pos: ORBITCC:rdPos@171 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T6R x_pos: ORBITCC:rdPos@172 y_pos: ORBITCC:rdPos@173 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T6R x_pos: ORBITCC:rdPos@174 y_pos: ORBITCC:rdPos@175 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D7R x_pos: ORBITCC:rdPos@176 y_pos: ORBITCC:rdPos@177 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D7R x_pos: ORBITCC:rdPos@178 y_pos: ORBITCC:rdPos@179 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D7R x_pos: ORBITCC:rdPos@180 y_pos: ORBITCC:rdPos@181 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D7R x_pos: ORBITCC:rdPos@182 y_pos: ORBITCC:rdPos@183 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5D7R x_pos: ORBITCC:rdPos@184 y_pos: ORBITCC:rdPos@185 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D7R x_pos: ORBITCC:rdPos@186 y_pos: ORBITCC:rdPos@187 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D7R x_pos: ORBITCC:rdPos@188 y_pos: ORBITCC:rdPos@189 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T7R x_pos: ORBITCC:rdPos@190 y_pos: ORBITCC:rdPos@191 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T7R x_pos: ORBITCC:rdPos@192 y_pos: ORBITCC:rdPos@193 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T7R x_pos: ORBITCC:rdPos@194 y_pos: ORBITCC:rdPos@195 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T7R x_pos: ORBITCC:rdPos@196 y_pos: ORBITCC:rdPos@197 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ41T7R x_pos: ORBITCC:rdPos@198 y_pos: ORBITCC:rdPos@199 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T7R x_pos: ORBITCC:rdPos@200 y_pos: ORBITCC:rdPos@201 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T7R x_pos: ORBITCC:rdPos@202 y_pos: ORBITCC:rdPos@203 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T7R x_pos: ORBITCC:rdPos@204 y_pos: ORBITCC:rdPos@205 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D8R x_pos: ORBITCC:rdPos@206 y_pos: ORBITCC:rdPos@207 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D8R x_pos: ORBITCC:rdPos@208 y_pos: ORBITCC:rdPos@209 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D8R x_pos: ORBITCC:rdPos@210 y_pos: ORBITCC:rdPos@211 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D8R x_pos: ORBITCC:rdPos@212 y_pos: ORBITCC:rdPos@213 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5D8R x_pos: ORBITCC:rdPos@214 y_pos: ORBITCC:rdPos@215 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6D8R x_pos: ORBITCC:rdPos@216 y_pos: ORBITCC:rdPos@217 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7D8R x_pos: ORBITCC:rdPos@218 y_pos: ORBITCC:rdPos@219 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1T8R x_pos: ORBITCC:rdPos@220 y_pos: ORBITCC:rdPos@221 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2T8R x_pos: ORBITCC:rdPos@222 y_pos: ORBITCC:rdPos@223 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3T8R x_pos: ORBITCC:rdPos@224 y_pos: ORBITCC:rdPos@225 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4T8R x_pos: ORBITCC:rdPos@226 y_pos: ORBITCC:rdPos@227 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ5T8R x_pos: ORBITCC:rdPos@228 y_pos: ORBITCC:rdPos@229 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ6T8R x_pos: ORBITCC:rdPos@230 y_pos: ORBITCC:rdPos@231 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ7T8R x_pos: ORBITCC:rdPos@232 y_pos: ORBITCC:rdPos@233 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ1D1R x_pos: ORBITCC:rdPos@234 y_pos: ORBITCC:rdPos@235 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ2D1R x_pos: ORBITCC:rdPos@236 y_pos: ORBITCC:rdPos@237 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ3D1R x_pos: ORBITCC:rdPos@238 y_pos: ORBITCC:rdPos@239 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ4D1R x_pos: ORBITCC:rdPos@240 y_pos: ORBITCC:rdPos@241 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ41D1R x_pos: ORBITCC:rdPos@242 y_pos: ORBITCC:rdPos@243 -- class: pyaml.bpm.bpm.BPM +- class: pyaml.diagnostics.bpm.bpm.BPM name: BPMZ42D1R x_pos: ORBITCC:rdPos@244 y_pos: ORBITCC:rdPos@245 diff --git a/examples/use_cases/config/esrf/esrf.yaml b/examples/use_cases/config/esrf/esrf.yaml index a3bdba75..88899f73 100644 --- a/examples/use_cases/config/esrf/esrf.yaml +++ b/examples/use_cases/config/esrf/esrf.yaml @@ -5713,1285 +5713,1285 @@ devices: - srmag/ps-corr-sh3/c03-e-ch3/current - srmag/ps-corr-sh3/c03-e-ch5/current - srmag/ps-corr-sh3/c03-e-ch6/current -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-01 x_pos: srdiag/bpm/c04-01/SA_HPosition y_pos: srdiag/bpm/c04-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-02 x_pos: srdiag/bpm/c04-02/SA_HPosition y_pos: srdiag/bpm/c04-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-03 x_pos: srdiag/bpm/c04-03/SA_HPosition y_pos: srdiag/bpm/c04-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-04 x_pos: srdiag/bpm/c04-04/SA_HPosition y_pos: srdiag/bpm/c04-04/SA_VPosition x_offset: srdiag/bpm/c04-04/HOffset y_offset: srdiag/bpm/c04-04/VOffset -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-05 x_pos: srdiag/bpm/c04-05/SA_HPosition y_pos: srdiag/bpm/c04-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-06 x_pos: srdiag/bpm/c04-06/SA_HPosition y_pos: srdiag/bpm/c04-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-07 x_pos: srdiag/bpm/c04-07/SA_HPosition y_pos: srdiag/bpm/c04-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-08 x_pos: srdiag/bpm/c04-08/SA_HPosition y_pos: srdiag/bpm/c04-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-09 x_pos: srdiag/bpm/c04-09/SA_HPosition y_pos: srdiag/bpm/c04-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-10 x_pos: srdiag/bpm/c04-10/SA_HPosition y_pos: srdiag/bpm/c04-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-01 x_pos: srdiag/bpm/c05-01/SA_HPosition y_pos: srdiag/bpm/c05-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-02 x_pos: srdiag/bpm/c05-02/SA_HPosition y_pos: srdiag/bpm/c05-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-03 x_pos: srdiag/bpm/c05-03/SA_HPosition y_pos: srdiag/bpm/c05-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-04 x_pos: srdiag/bpm/c05-04/SA_HPosition y_pos: srdiag/bpm/c05-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-05 x_pos: srdiag/bpm/c05-05/SA_HPosition y_pos: srdiag/bpm/c05-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-06 x_pos: srdiag/bpm/c05-06/SA_HPosition y_pos: srdiag/bpm/c05-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-07 x_pos: srdiag/bpm/c05-07/SA_HPosition y_pos: srdiag/bpm/c05-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-08 x_pos: srdiag/bpm/c05-08/SA_HPosition y_pos: srdiag/bpm/c05-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-09 x_pos: srdiag/bpm/c05-09/SA_HPosition y_pos: srdiag/bpm/c05-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-10 x_pos: srdiag/bpm/c05-10/SA_HPosition y_pos: srdiag/bpm/c05-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-01 x_pos: srdiag/bpm/c06-01/SA_HPosition y_pos: srdiag/bpm/c06-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-02 x_pos: srdiag/bpm/c06-02/SA_HPosition y_pos: srdiag/bpm/c06-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-03 x_pos: srdiag/bpm/c06-03/SA_HPosition y_pos: srdiag/bpm/c06-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-04 x_pos: srdiag/bpm/c06-04/SA_HPosition y_pos: srdiag/bpm/c06-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-05 x_pos: srdiag/bpm/c06-05/SA_HPosition y_pos: srdiag/bpm/c06-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-06 x_pos: srdiag/bpm/c06-06/SA_HPosition y_pos: srdiag/bpm/c06-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-07 x_pos: srdiag/bpm/c06-07/SA_HPosition y_pos: srdiag/bpm/c06-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-08 x_pos: srdiag/bpm/c06-08/SA_HPosition y_pos: srdiag/bpm/c06-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-09 x_pos: srdiag/bpm/c06-09/SA_HPosition y_pos: srdiag/bpm/c06-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-10 x_pos: srdiag/bpm/c06-10/SA_HPosition y_pos: srdiag/bpm/c06-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-01 x_pos: srdiag/bpm/c07-01/SA_HPosition y_pos: srdiag/bpm/c07-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-02 x_pos: srdiag/bpm/c07-02/SA_HPosition y_pos: srdiag/bpm/c07-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-03 x_pos: srdiag/bpm/c07-03/SA_HPosition y_pos: srdiag/bpm/c07-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-04 x_pos: srdiag/bpm/c07-04/SA_HPosition y_pos: srdiag/bpm/c07-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-05 x_pos: srdiag/bpm/c07-05/SA_HPosition y_pos: srdiag/bpm/c07-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-06 x_pos: srdiag/bpm/c07-06/SA_HPosition y_pos: srdiag/bpm/c07-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-07 x_pos: srdiag/bpm/c07-07/SA_HPosition y_pos: srdiag/bpm/c07-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-08 x_pos: srdiag/bpm/c07-08/SA_HPosition y_pos: srdiag/bpm/c07-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-09 x_pos: srdiag/bpm/c07-09/SA_HPosition y_pos: srdiag/bpm/c07-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-10 x_pos: srdiag/bpm/c07-10/SA_HPosition y_pos: srdiag/bpm/c07-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-01 x_pos: srdiag/bpm/c08-01/SA_HPosition y_pos: srdiag/bpm/c08-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-02 x_pos: srdiag/bpm/c08-02/SA_HPosition y_pos: srdiag/bpm/c08-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-03 x_pos: srdiag/bpm/c08-03/SA_HPosition y_pos: srdiag/bpm/c08-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-04 x_pos: srdiag/bpm/c08-04/SA_HPosition y_pos: srdiag/bpm/c08-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-05 x_pos: srdiag/bpm/c08-05/SA_HPosition y_pos: srdiag/bpm/c08-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-06 x_pos: srdiag/bpm/c08-06/SA_HPosition y_pos: srdiag/bpm/c08-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-07 x_pos: srdiag/bpm/c08-07/SA_HPosition y_pos: srdiag/bpm/c08-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-08 x_pos: srdiag/bpm/c08-08/SA_HPosition y_pos: srdiag/bpm/c08-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-09 x_pos: srdiag/bpm/c08-09/SA_HPosition y_pos: srdiag/bpm/c08-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-10 x_pos: srdiag/bpm/c08-10/SA_HPosition y_pos: srdiag/bpm/c08-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-01 x_pos: srdiag/bpm/c09-01/SA_HPosition y_pos: srdiag/bpm/c09-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-02 x_pos: srdiag/bpm/c09-02/SA_HPosition y_pos: srdiag/bpm/c09-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-03 x_pos: srdiag/bpm/c09-03/SA_HPosition y_pos: srdiag/bpm/c09-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-04 x_pos: srdiag/bpm/c09-04/SA_HPosition y_pos: srdiag/bpm/c09-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-05 x_pos: srdiag/bpm/c09-05/SA_HPosition y_pos: srdiag/bpm/c09-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-06 x_pos: srdiag/bpm/c09-06/SA_HPosition y_pos: srdiag/bpm/c09-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-07 x_pos: srdiag/bpm/c09-07/SA_HPosition y_pos: srdiag/bpm/c09-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-08 x_pos: srdiag/bpm/c09-08/SA_HPosition y_pos: srdiag/bpm/c09-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-09 x_pos: srdiag/bpm/c09-09/SA_HPosition y_pos: srdiag/bpm/c09-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-10 x_pos: srdiag/bpm/c09-10/SA_HPosition y_pos: srdiag/bpm/c09-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-01 x_pos: srdiag/bpm/c10-01/SA_HPosition y_pos: srdiag/bpm/c10-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-02 x_pos: srdiag/bpm/c10-02/SA_HPosition y_pos: srdiag/bpm/c10-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-03 x_pos: srdiag/bpm/c10-03/SA_HPosition y_pos: srdiag/bpm/c10-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-04 x_pos: srdiag/bpm/c10-04/SA_HPosition y_pos: srdiag/bpm/c10-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-05 x_pos: srdiag/bpm/c10-05/SA_HPosition y_pos: srdiag/bpm/c10-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-06 x_pos: srdiag/bpm/c10-06/SA_HPosition y_pos: srdiag/bpm/c10-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-07 x_pos: srdiag/bpm/c10-07/SA_HPosition y_pos: srdiag/bpm/c10-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-08 x_pos: srdiag/bpm/c10-08/SA_HPosition y_pos: srdiag/bpm/c10-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-09 x_pos: srdiag/bpm/c10-09/SA_HPosition y_pos: srdiag/bpm/c10-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-10 x_pos: srdiag/bpm/c10-10/SA_HPosition y_pos: srdiag/bpm/c10-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-01 x_pos: srdiag/bpm/c11-01/SA_HPosition y_pos: srdiag/bpm/c11-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-02 x_pos: srdiag/bpm/c11-02/SA_HPosition y_pos: srdiag/bpm/c11-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-03 x_pos: srdiag/bpm/c11-03/SA_HPosition y_pos: srdiag/bpm/c11-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-04 x_pos: srdiag/bpm/c11-04/SA_HPosition y_pos: srdiag/bpm/c11-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-05 x_pos: srdiag/bpm/c11-05/SA_HPosition y_pos: srdiag/bpm/c11-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-06 x_pos: srdiag/bpm/c11-06/SA_HPosition y_pos: srdiag/bpm/c11-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-07 x_pos: srdiag/bpm/c11-07/SA_HPosition y_pos: srdiag/bpm/c11-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-08 x_pos: srdiag/bpm/c11-08/SA_HPosition y_pos: srdiag/bpm/c11-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-09 x_pos: srdiag/bpm/c11-09/SA_HPosition y_pos: srdiag/bpm/c11-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-10 x_pos: srdiag/bpm/c11-10/SA_HPosition y_pos: srdiag/bpm/c11-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-01 x_pos: srdiag/bpm/c12-01/SA_HPosition y_pos: srdiag/bpm/c12-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-02 x_pos: srdiag/bpm/c12-02/SA_HPosition y_pos: srdiag/bpm/c12-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-03 x_pos: srdiag/bpm/c12-03/SA_HPosition y_pos: srdiag/bpm/c12-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-04 x_pos: srdiag/bpm/c12-04/SA_HPosition y_pos: srdiag/bpm/c12-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-05 x_pos: srdiag/bpm/c12-05/SA_HPosition y_pos: srdiag/bpm/c12-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-06 x_pos: srdiag/bpm/c12-06/SA_HPosition y_pos: srdiag/bpm/c12-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-07 x_pos: srdiag/bpm/c12-07/SA_HPosition y_pos: srdiag/bpm/c12-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-08 x_pos: srdiag/bpm/c12-08/SA_HPosition y_pos: srdiag/bpm/c12-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-09 x_pos: srdiag/bpm/c12-09/SA_HPosition y_pos: srdiag/bpm/c12-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-10 x_pos: srdiag/bpm/c12-10/SA_HPosition y_pos: srdiag/bpm/c12-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-01 x_pos: srdiag/bpm/c13-01/SA_HPosition y_pos: srdiag/bpm/c13-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-02 x_pos: srdiag/bpm/c13-02/SA_HPosition y_pos: srdiag/bpm/c13-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-03 x_pos: srdiag/bpm/c13-03/SA_HPosition y_pos: srdiag/bpm/c13-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-04 x_pos: srdiag/bpm/c13-04/SA_HPosition y_pos: srdiag/bpm/c13-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-05 x_pos: srdiag/bpm/c13-05/SA_HPosition y_pos: srdiag/bpm/c13-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-06 x_pos: srdiag/bpm/c13-06/SA_HPosition y_pos: srdiag/bpm/c13-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-07 x_pos: srdiag/bpm/c13-07/SA_HPosition y_pos: srdiag/bpm/c13-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-08 x_pos: srdiag/bpm/c13-08/SA_HPosition y_pos: srdiag/bpm/c13-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-09 x_pos: srdiag/bpm/c13-09/SA_HPosition y_pos: srdiag/bpm/c13-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-10 x_pos: srdiag/bpm/c13-10/SA_HPosition y_pos: srdiag/bpm/c13-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-01 x_pos: srdiag/bpm/c14-01/SA_HPosition y_pos: srdiag/bpm/c14-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-02 x_pos: srdiag/bpm/c14-02/SA_HPosition y_pos: srdiag/bpm/c14-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-03 x_pos: srdiag/bpm/c14-03/SA_HPosition y_pos: srdiag/bpm/c14-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-04 x_pos: srdiag/bpm/c14-04/SA_HPosition y_pos: srdiag/bpm/c14-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-05 x_pos: srdiag/bpm/c14-05/SA_HPosition y_pos: srdiag/bpm/c14-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-06 x_pos: srdiag/bpm/c14-06/SA_HPosition y_pos: srdiag/bpm/c14-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-07 x_pos: srdiag/bpm/c14-07/SA_HPosition y_pos: srdiag/bpm/c14-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-08 x_pos: srdiag/bpm/c14-08/SA_HPosition y_pos: srdiag/bpm/c14-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-09 x_pos: srdiag/bpm/c14-09/SA_HPosition y_pos: srdiag/bpm/c14-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-10 x_pos: srdiag/bpm/c14-10/SA_HPosition y_pos: srdiag/bpm/c14-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-01 x_pos: srdiag/bpm/c15-01/SA_HPosition y_pos: srdiag/bpm/c15-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-02 x_pos: srdiag/bpm/c15-02/SA_HPosition y_pos: srdiag/bpm/c15-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-03 x_pos: srdiag/bpm/c15-03/SA_HPosition y_pos: srdiag/bpm/c15-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-04 x_pos: srdiag/bpm/c15-04/SA_HPosition y_pos: srdiag/bpm/c15-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-05 x_pos: srdiag/bpm/c15-05/SA_HPosition y_pos: srdiag/bpm/c15-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-06 x_pos: srdiag/bpm/c15-06/SA_HPosition y_pos: srdiag/bpm/c15-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-07 x_pos: srdiag/bpm/c15-07/SA_HPosition y_pos: srdiag/bpm/c15-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-08 x_pos: srdiag/bpm/c15-08/SA_HPosition y_pos: srdiag/bpm/c15-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-09 x_pos: srdiag/bpm/c15-09/SA_HPosition y_pos: srdiag/bpm/c15-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-10 x_pos: srdiag/bpm/c15-10/SA_HPosition y_pos: srdiag/bpm/c15-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-01 x_pos: srdiag/bpm/c16-01/SA_HPosition y_pos: srdiag/bpm/c16-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-02 x_pos: srdiag/bpm/c16-02/SA_HPosition y_pos: srdiag/bpm/c16-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-03 x_pos: srdiag/bpm/c16-03/SA_HPosition y_pos: srdiag/bpm/c16-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-04 x_pos: srdiag/bpm/c16-04/SA_HPosition y_pos: srdiag/bpm/c16-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-05 x_pos: srdiag/bpm/c16-05/SA_HPosition y_pos: srdiag/bpm/c16-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-06 x_pos: srdiag/bpm/c16-06/SA_HPosition y_pos: srdiag/bpm/c16-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-07 x_pos: srdiag/bpm/c16-07/SA_HPosition y_pos: srdiag/bpm/c16-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-08 x_pos: srdiag/bpm/c16-08/SA_HPosition y_pos: srdiag/bpm/c16-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-09 x_pos: srdiag/bpm/c16-09/SA_HPosition y_pos: srdiag/bpm/c16-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-10 x_pos: srdiag/bpm/c16-10/SA_HPosition y_pos: srdiag/bpm/c16-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-01 x_pos: srdiag/bpm/c17-01/SA_HPosition y_pos: srdiag/bpm/c17-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-02 x_pos: srdiag/bpm/c17-02/SA_HPosition y_pos: srdiag/bpm/c17-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-03 x_pos: srdiag/bpm/c17-03/SA_HPosition y_pos: srdiag/bpm/c17-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-04 x_pos: srdiag/bpm/c17-04/SA_HPosition y_pos: srdiag/bpm/c17-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-05 x_pos: srdiag/bpm/c17-05/SA_HPosition y_pos: srdiag/bpm/c17-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-06 x_pos: srdiag/bpm/c17-06/SA_HPosition y_pos: srdiag/bpm/c17-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-07 x_pos: srdiag/bpm/c17-07/SA_HPosition y_pos: srdiag/bpm/c17-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-08 x_pos: srdiag/bpm/c17-08/SA_HPosition y_pos: srdiag/bpm/c17-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-09 x_pos: srdiag/bpm/c17-09/SA_HPosition y_pos: srdiag/bpm/c17-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-10 x_pos: srdiag/bpm/c17-10/SA_HPosition y_pos: srdiag/bpm/c17-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-01 x_pos: srdiag/bpm/c18-01/SA_HPosition y_pos: srdiag/bpm/c18-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-02 x_pos: srdiag/bpm/c18-02/SA_HPosition y_pos: srdiag/bpm/c18-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-03 x_pos: srdiag/bpm/c18-03/SA_HPosition y_pos: srdiag/bpm/c18-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-04 x_pos: srdiag/bpm/c18-04/SA_HPosition y_pos: srdiag/bpm/c18-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-05 x_pos: srdiag/bpm/c18-05/SA_HPosition y_pos: srdiag/bpm/c18-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-06 x_pos: srdiag/bpm/c18-06/SA_HPosition y_pos: srdiag/bpm/c18-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-07 x_pos: srdiag/bpm/c18-07/SA_HPosition y_pos: srdiag/bpm/c18-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-08 x_pos: srdiag/bpm/c18-08/SA_HPosition y_pos: srdiag/bpm/c18-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-09 x_pos: srdiag/bpm/c18-09/SA_HPosition y_pos: srdiag/bpm/c18-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-10 x_pos: srdiag/bpm/c18-10/SA_HPosition y_pos: srdiag/bpm/c18-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-01 x_pos: srdiag/bpm/c19-01/SA_HPosition y_pos: srdiag/bpm/c19-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-02 x_pos: srdiag/bpm/c19-02/SA_HPosition y_pos: srdiag/bpm/c19-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-03 x_pos: srdiag/bpm/c19-03/SA_HPosition y_pos: srdiag/bpm/c19-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-04 x_pos: srdiag/bpm/c19-04/SA_HPosition y_pos: srdiag/bpm/c19-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-05 x_pos: srdiag/bpm/c19-05/SA_HPosition y_pos: srdiag/bpm/c19-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-06 x_pos: srdiag/bpm/c19-06/SA_HPosition y_pos: srdiag/bpm/c19-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-07 x_pos: srdiag/bpm/c19-07/SA_HPosition y_pos: srdiag/bpm/c19-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-08 x_pos: srdiag/bpm/c19-08/SA_HPosition y_pos: srdiag/bpm/c19-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-09 x_pos: srdiag/bpm/c19-09/SA_HPosition y_pos: srdiag/bpm/c19-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-10 x_pos: srdiag/bpm/c19-10/SA_HPosition y_pos: srdiag/bpm/c19-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-01 x_pos: srdiag/bpm/c20-01/SA_HPosition y_pos: srdiag/bpm/c20-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-02 x_pos: srdiag/bpm/c20-02/SA_HPosition y_pos: srdiag/bpm/c20-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-03 x_pos: srdiag/bpm/c20-03/SA_HPosition y_pos: srdiag/bpm/c20-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-04 x_pos: srdiag/bpm/c20-04/SA_HPosition y_pos: srdiag/bpm/c20-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-05 x_pos: srdiag/bpm/c20-05/SA_HPosition y_pos: srdiag/bpm/c20-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-06 x_pos: srdiag/bpm/c20-06/SA_HPosition y_pos: srdiag/bpm/c20-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-07 x_pos: srdiag/bpm/c20-07/SA_HPosition y_pos: srdiag/bpm/c20-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-08 x_pos: srdiag/bpm/c20-08/SA_HPosition y_pos: srdiag/bpm/c20-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-09 x_pos: srdiag/bpm/c20-09/SA_HPosition y_pos: srdiag/bpm/c20-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-10 x_pos: srdiag/bpm/c20-10/SA_HPosition y_pos: srdiag/bpm/c20-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-01 x_pos: srdiag/bpm/c21-01/SA_HPosition y_pos: srdiag/bpm/c21-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-02 x_pos: srdiag/bpm/c21-02/SA_HPosition y_pos: srdiag/bpm/c21-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-03 x_pos: srdiag/bpm/c21-03/SA_HPosition y_pos: srdiag/bpm/c21-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-04 x_pos: srdiag/bpm/c21-04/SA_HPosition y_pos: srdiag/bpm/c21-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-05 x_pos: srdiag/bpm/c21-05/SA_HPosition y_pos: srdiag/bpm/c21-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-06 x_pos: srdiag/bpm/c21-06/SA_HPosition y_pos: srdiag/bpm/c21-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-07 x_pos: srdiag/bpm/c21-07/SA_HPosition y_pos: srdiag/bpm/c21-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-08 x_pos: srdiag/bpm/c21-08/SA_HPosition y_pos: srdiag/bpm/c21-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-09 x_pos: srdiag/bpm/c21-09/SA_HPosition y_pos: srdiag/bpm/c21-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-10 x_pos: srdiag/bpm/c21-10/SA_HPosition y_pos: srdiag/bpm/c21-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-01 x_pos: srdiag/bpm/c22-01/SA_HPosition y_pos: srdiag/bpm/c22-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-02 x_pos: srdiag/bpm/c22-02/SA_HPosition y_pos: srdiag/bpm/c22-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-03 x_pos: srdiag/bpm/c22-03/SA_HPosition y_pos: srdiag/bpm/c22-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-04 x_pos: srdiag/bpm/c22-04/SA_HPosition y_pos: srdiag/bpm/c22-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-05 x_pos: srdiag/bpm/c22-05/SA_HPosition y_pos: srdiag/bpm/c22-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-06 x_pos: srdiag/bpm/c22-06/SA_HPosition y_pos: srdiag/bpm/c22-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-07 x_pos: srdiag/bpm/c22-07/SA_HPosition y_pos: srdiag/bpm/c22-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-08 x_pos: srdiag/bpm/c22-08/SA_HPosition y_pos: srdiag/bpm/c22-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-09 x_pos: srdiag/bpm/c22-09/SA_HPosition y_pos: srdiag/bpm/c22-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-10 x_pos: srdiag/bpm/c22-10/SA_HPosition y_pos: srdiag/bpm/c22-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-01 x_pos: srdiag/bpm/c23-01/SA_HPosition y_pos: srdiag/bpm/c23-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-02 x_pos: srdiag/bpm/c23-02/SA_HPosition y_pos: srdiag/bpm/c23-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-03 x_pos: srdiag/bpm/c23-03/SA_HPosition y_pos: srdiag/bpm/c23-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-04 x_pos: srdiag/bpm/c23-04/SA_HPosition y_pos: srdiag/bpm/c23-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-05 x_pos: srdiag/bpm/c23-05/SA_HPosition y_pos: srdiag/bpm/c23-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-06 x_pos: srdiag/bpm/c23-06/SA_HPosition y_pos: srdiag/bpm/c23-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-07 x_pos: srdiag/bpm/c23-07/SA_HPosition y_pos: srdiag/bpm/c23-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-08 x_pos: srdiag/bpm/c23-08/SA_HPosition y_pos: srdiag/bpm/c23-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-09 x_pos: srdiag/bpm/c23-09/SA_HPosition y_pos: srdiag/bpm/c23-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-10 x_pos: srdiag/bpm/c23-10/SA_HPosition y_pos: srdiag/bpm/c23-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-01 x_pos: srdiag/bpm/c24-01/SA_HPosition y_pos: srdiag/bpm/c24-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-02 x_pos: srdiag/bpm/c24-02/SA_HPosition y_pos: srdiag/bpm/c24-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-03 x_pos: srdiag/bpm/c24-03/SA_HPosition y_pos: srdiag/bpm/c24-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-04 x_pos: srdiag/bpm/c24-04/SA_HPosition y_pos: srdiag/bpm/c24-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-05 x_pos: srdiag/bpm/c24-05/SA_HPosition y_pos: srdiag/bpm/c24-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-06 x_pos: srdiag/bpm/c24-06/SA_HPosition y_pos: srdiag/bpm/c24-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-07 x_pos: srdiag/bpm/c24-07/SA_HPosition y_pos: srdiag/bpm/c24-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-08 x_pos: srdiag/bpm/c24-08/SA_HPosition y_pos: srdiag/bpm/c24-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-09 x_pos: srdiag/bpm/c24-09/SA_HPosition y_pos: srdiag/bpm/c24-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-10 x_pos: srdiag/bpm/c24-10/SA_HPosition y_pos: srdiag/bpm/c24-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-01 x_pos: srdiag/bpm/c25-01/SA_HPosition y_pos: srdiag/bpm/c25-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-02 x_pos: srdiag/bpm/c25-02/SA_HPosition y_pos: srdiag/bpm/c25-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-03 x_pos: srdiag/bpm/c25-03/SA_HPosition y_pos: srdiag/bpm/c25-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-04 x_pos: srdiag/bpm/c25-04/SA_HPosition y_pos: srdiag/bpm/c25-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-05 x_pos: srdiag/bpm/c25-05/SA_HPosition y_pos: srdiag/bpm/c25-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-06 x_pos: srdiag/bpm/c25-06/SA_HPosition y_pos: srdiag/bpm/c25-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-07 x_pos: srdiag/bpm/c25-07/SA_HPosition y_pos: srdiag/bpm/c25-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-08 x_pos: srdiag/bpm/c25-08/SA_HPosition y_pos: srdiag/bpm/c25-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-09 x_pos: srdiag/bpm/c25-09/SA_HPosition y_pos: srdiag/bpm/c25-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-10 x_pos: srdiag/bpm/c25-10/SA_HPosition y_pos: srdiag/bpm/c25-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-01 x_pos: srdiag/bpm/c26-01/SA_HPosition y_pos: srdiag/bpm/c26-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-02 x_pos: srdiag/bpm/c26-02/SA_HPosition y_pos: srdiag/bpm/c26-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-03 x_pos: srdiag/bpm/c26-03/SA_HPosition y_pos: srdiag/bpm/c26-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-04 x_pos: srdiag/bpm/c26-04/SA_HPosition y_pos: srdiag/bpm/c26-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-05 x_pos: srdiag/bpm/c26-05/SA_HPosition y_pos: srdiag/bpm/c26-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-06 x_pos: srdiag/bpm/c26-06/SA_HPosition y_pos: srdiag/bpm/c26-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-07 x_pos: srdiag/bpm/c26-07/SA_HPosition y_pos: srdiag/bpm/c26-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-08 x_pos: srdiag/bpm/c26-08/SA_HPosition y_pos: srdiag/bpm/c26-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-09 x_pos: srdiag/bpm/c26-09/SA_HPosition y_pos: srdiag/bpm/c26-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-10 x_pos: srdiag/bpm/c26-10/SA_HPosition y_pos: srdiag/bpm/c26-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-01 x_pos: srdiag/bpm/c27-01/SA_HPosition y_pos: srdiag/bpm/c27-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-02 x_pos: srdiag/bpm/c27-02/SA_HPosition y_pos: srdiag/bpm/c27-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-03 x_pos: srdiag/bpm/c27-03/SA_HPosition y_pos: srdiag/bpm/c27-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-04 x_pos: srdiag/bpm/c27-04/SA_HPosition y_pos: srdiag/bpm/c27-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-05 x_pos: srdiag/bpm/c27-05/SA_HPosition y_pos: srdiag/bpm/c27-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-06 x_pos: srdiag/bpm/c27-06/SA_HPosition y_pos: srdiag/bpm/c27-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-07 x_pos: srdiag/bpm/c27-07/SA_HPosition y_pos: srdiag/bpm/c27-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-08 x_pos: srdiag/bpm/c27-08/SA_HPosition y_pos: srdiag/bpm/c27-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-09 x_pos: srdiag/bpm/c27-09/SA_HPosition y_pos: srdiag/bpm/c27-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-10 x_pos: srdiag/bpm/c27-10/SA_HPosition y_pos: srdiag/bpm/c27-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-01 x_pos: srdiag/bpm/c28-01/SA_HPosition y_pos: srdiag/bpm/c28-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-02 x_pos: srdiag/bpm/c28-02/SA_HPosition y_pos: srdiag/bpm/c28-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-03 x_pos: srdiag/bpm/c28-03/SA_HPosition y_pos: srdiag/bpm/c28-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-04 x_pos: srdiag/bpm/c28-04/SA_HPosition y_pos: srdiag/bpm/c28-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-05 x_pos: srdiag/bpm/c28-05/SA_HPosition y_pos: srdiag/bpm/c28-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-06 x_pos: srdiag/bpm/c28-06/SA_HPosition y_pos: srdiag/bpm/c28-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-07 x_pos: srdiag/bpm/c28-07/SA_HPosition y_pos: srdiag/bpm/c28-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-08 x_pos: srdiag/bpm/c28-08/SA_HPosition y_pos: srdiag/bpm/c28-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-09 x_pos: srdiag/bpm/c28-09/SA_HPosition y_pos: srdiag/bpm/c28-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-10 x_pos: srdiag/bpm/c28-10/SA_HPosition y_pos: srdiag/bpm/c28-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-01 x_pos: srdiag/bpm/c29-01/SA_HPosition y_pos: srdiag/bpm/c29-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-02 x_pos: srdiag/bpm/c29-02/SA_HPosition y_pos: srdiag/bpm/c29-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-03 x_pos: srdiag/bpm/c29-03/SA_HPosition y_pos: srdiag/bpm/c29-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-04 x_pos: srdiag/bpm/c29-04/SA_HPosition y_pos: srdiag/bpm/c29-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-05 x_pos: srdiag/bpm/c29-05/SA_HPosition y_pos: srdiag/bpm/c29-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-06 x_pos: srdiag/bpm/c29-06/SA_HPosition y_pos: srdiag/bpm/c29-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-07 x_pos: srdiag/bpm/c29-07/SA_HPosition y_pos: srdiag/bpm/c29-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-08 x_pos: srdiag/bpm/c29-08/SA_HPosition y_pos: srdiag/bpm/c29-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-09 x_pos: srdiag/bpm/c29-09/SA_HPosition y_pos: srdiag/bpm/c29-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-10 x_pos: srdiag/bpm/c29-10/SA_HPosition y_pos: srdiag/bpm/c29-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-01 x_pos: srdiag/bpm/c30-01/SA_HPosition y_pos: srdiag/bpm/c30-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-02 x_pos: srdiag/bpm/c30-02/SA_HPosition y_pos: srdiag/bpm/c30-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-03 x_pos: srdiag/bpm/c30-03/SA_HPosition y_pos: srdiag/bpm/c30-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-04 x_pos: srdiag/bpm/c30-04/SA_HPosition y_pos: srdiag/bpm/c30-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-05 x_pos: srdiag/bpm/c30-05/SA_HPosition y_pos: srdiag/bpm/c30-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-06 x_pos: srdiag/bpm/c30-06/SA_HPosition y_pos: srdiag/bpm/c30-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-07 x_pos: srdiag/bpm/c30-07/SA_HPosition y_pos: srdiag/bpm/c30-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-08 x_pos: srdiag/bpm/c30-08/SA_HPosition y_pos: srdiag/bpm/c30-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-09 x_pos: srdiag/bpm/c30-09/SA_HPosition y_pos: srdiag/bpm/c30-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-10 x_pos: srdiag/bpm/c30-10/SA_HPosition y_pos: srdiag/bpm/c30-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-01 x_pos: srdiag/bpm/c31-01/SA_HPosition y_pos: srdiag/bpm/c31-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-02 x_pos: srdiag/bpm/c31-02/SA_HPosition y_pos: srdiag/bpm/c31-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-03 x_pos: srdiag/bpm/c31-03/SA_HPosition y_pos: srdiag/bpm/c31-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-04 x_pos: srdiag/bpm/c31-04/SA_HPosition y_pos: srdiag/bpm/c31-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-05 x_pos: srdiag/bpm/c31-05/SA_HPosition y_pos: srdiag/bpm/c31-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-06 x_pos: srdiag/bpm/c31-06/SA_HPosition y_pos: srdiag/bpm/c31-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-07 x_pos: srdiag/bpm/c31-07/SA_HPosition y_pos: srdiag/bpm/c31-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-08 x_pos: srdiag/bpm/c31-08/SA_HPosition y_pos: srdiag/bpm/c31-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-09 x_pos: srdiag/bpm/c31-09/SA_HPosition y_pos: srdiag/bpm/c31-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-10 x_pos: srdiag/bpm/c31-10/SA_HPosition y_pos: srdiag/bpm/c31-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-01 x_pos: srdiag/bpm/c32-01/SA_HPosition y_pos: srdiag/bpm/c32-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-02 x_pos: srdiag/bpm/c32-02/SA_HPosition y_pos: srdiag/bpm/c32-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-03 x_pos: srdiag/bpm/c32-03/SA_HPosition y_pos: srdiag/bpm/c32-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-04 x_pos: srdiag/bpm/c32-04/SA_HPosition y_pos: srdiag/bpm/c32-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-05 x_pos: srdiag/bpm/c32-05/SA_HPosition y_pos: srdiag/bpm/c32-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-06 x_pos: srdiag/bpm/c32-06/SA_HPosition y_pos: srdiag/bpm/c32-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-07 x_pos: srdiag/bpm/c32-07/SA_HPosition y_pos: srdiag/bpm/c32-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-08 x_pos: srdiag/bpm/c32-08/SA_HPosition y_pos: srdiag/bpm/c32-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-09 x_pos: srdiag/bpm/c32-09/SA_HPosition y_pos: srdiag/bpm/c32-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-10 x_pos: srdiag/bpm/c32-10/SA_HPosition y_pos: srdiag/bpm/c32-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-01 x_pos: srdiag/bpm/c01-01/SA_HPosition y_pos: srdiag/bpm/c01-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-02 x_pos: srdiag/bpm/c01-02/SA_HPosition y_pos: srdiag/bpm/c01-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-03 x_pos: srdiag/bpm/c01-03/SA_HPosition y_pos: srdiag/bpm/c01-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-04 x_pos: srdiag/bpm/c01-04/SA_HPosition y_pos: srdiag/bpm/c01-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-05 x_pos: srdiag/bpm/c01-05/SA_HPosition y_pos: srdiag/bpm/c01-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-06 x_pos: srdiag/bpm/c01-06/SA_HPosition y_pos: srdiag/bpm/c01-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-07 x_pos: srdiag/bpm/c01-07/SA_HPosition y_pos: srdiag/bpm/c01-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-08 x_pos: srdiag/bpm/c01-08/SA_HPosition y_pos: srdiag/bpm/c01-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-09 x_pos: srdiag/bpm/c01-09/SA_HPosition y_pos: srdiag/bpm/c01-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-10 x_pos: srdiag/bpm/c01-10/SA_HPosition y_pos: srdiag/bpm/c01-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-01 x_pos: srdiag/bpm/c02-01/SA_HPosition y_pos: srdiag/bpm/c02-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-02 x_pos: srdiag/bpm/c02-02/SA_HPosition y_pos: srdiag/bpm/c02-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-03 x_pos: srdiag/bpm/c02-03/SA_HPosition y_pos: srdiag/bpm/c02-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-04 x_pos: srdiag/bpm/c02-04/SA_HPosition y_pos: srdiag/bpm/c02-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-05 x_pos: srdiag/bpm/c02-05/SA_HPosition y_pos: srdiag/bpm/c02-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-06 x_pos: srdiag/bpm/c02-06/SA_HPosition y_pos: srdiag/bpm/c02-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-07 x_pos: srdiag/bpm/c02-07/SA_HPosition y_pos: srdiag/bpm/c02-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-08 x_pos: srdiag/bpm/c02-08/SA_HPosition y_pos: srdiag/bpm/c02-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-09 x_pos: srdiag/bpm/c02-09/SA_HPosition y_pos: srdiag/bpm/c02-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-10 x_pos: srdiag/bpm/c02-10/SA_HPosition y_pos: srdiag/bpm/c02-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-01 x_pos: srdiag/bpm/c03-01/SA_HPosition y_pos: srdiag/bpm/c03-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-02 x_pos: srdiag/bpm/c03-02/SA_HPosition y_pos: srdiag/bpm/c03-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-03 x_pos: srdiag/bpm/c03-03/SA_HPosition y_pos: srdiag/bpm/c03-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-04 x_pos: srdiag/bpm/c03-04/SA_HPosition y_pos: srdiag/bpm/c03-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-05 x_pos: srdiag/bpm/c03-05/SA_HPosition y_pos: srdiag/bpm/c03-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-06 x_pos: srdiag/bpm/c03-06/SA_HPosition y_pos: srdiag/bpm/c03-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-07 x_pos: srdiag/bpm/c03-07/SA_HPosition y_pos: srdiag/bpm/c03-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-08 x_pos: srdiag/bpm/c03-08/SA_HPosition y_pos: srdiag/bpm/c03-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-09 x_pos: srdiag/bpm/c03-09/SA_HPosition y_pos: srdiag/bpm/c03-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-10 x_pos: srdiag/bpm/c03-10/SA_HPosition y_pos: srdiag/bpm/c03-10/SA_VPosition diff --git a/examples/use_cases/config/soleil_ii/devices.yaml b/examples/use_cases/config/soleil_ii/devices.yaml index e75b0954..c19b50ad 100644 --- a/examples/use_cases/config/soleil_ii/devices.yaml +++ b/examples/use_cases/config/soleil_ii/devices.yaml @@ -1,4 +1,4 @@ -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_001 x_pos: AN01-SD/DG-EPOS/BPM.02/x_pos y_pos: AN01-SD/DG-EPOS/BPM.02/y_pos @@ -54,7 +54,7 @@ physics: - AN01-AR/EM-OCT/OH.02/strength - AN01-AR/EM-COR/OH.02-CQLN.02/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_002 x_pos: AN01-AR/DG-EPOS/BPM.03/x_pos y_pos: AN01-AR/DG-EPOS/BPM.03/y_pos @@ -108,7 +108,7 @@ physics: - AN01-AR/EM-SX/SCF.02/strength - AN01-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_003 x_pos: AN01-AR/DG-EPOS/BPM.04/x_pos y_pos: AN01-AR/DG-EPOS/BPM.04/y_pos @@ -168,7 +168,7 @@ physics: - AN01-AR/EM-SX/SCF.05/strength - AN01-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_004 x_pos: AN01-AR/DG-EPOS/BPM.05/x_pos y_pos: AN01-AR/DG-EPOS/BPM.05/y_pos @@ -228,7 +228,7 @@ physics: - AN01-AR/EM-SX/SCF.08/strength - AN01-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_005 x_pos: AN01-AR/DG-EPOS/BPM.06/x_pos y_pos: AN01-AR/DG-EPOS/BPM.06/y_pos @@ -288,7 +288,7 @@ - AN01-AR/EM-OCT/OC.04/strength - AN01-AR/EM-COR/OC.04-CQLN.13/strength - AN01-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_006 x_pos: AN01-AR/DG-EPOS/BPM.07/x_pos y_pos: AN01-AR/DG-EPOS/BPM.07/y_pos @@ -348,7 +348,7 @@ - AN01-AR/EM-OCT/OC.05/strength - AN01-AR/EM-COR/OC.05-CQLN.16/strength - AN01-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_007 x_pos: AN01-AR/DG-EPOS/BPM.08/x_pos y_pos: AN01-AR/DG-EPOS/BPM.08/y_pos @@ -420,7 +420,7 @@ physics: - AN01-AR/EM-SX/SCD.18/strength - AN01-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_008 x_pos: AN01-AR/DG-EPOS/BPM.09/x_pos y_pos: AN01-AR/DG-EPOS/BPM.09/y_pos @@ -462,7 +462,7 @@ physics: - AN01-AR/EM-OCT/OH.03/strength - AN01-AR/EM-COR/OH.03-CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_009 x_pos: AN01-AR/DG-EPOS/BPM.10/x_pos y_pos: AN01-AR/DG-EPOS/BPM.10/y_pos @@ -494,11 +494,11 @@ - AN01-AR/EM-OCT/OH.04/strength - AN01-AR/EM-COR/OH.04-CQLN.22/strength - AN01-AR/EM-COR/OH.04-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_010 x_pos: AN02-SD/DG-EPOS/BPM.01/x_pos y_pos: AN02-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_011 x_pos: AN02-SD/DG-EPOS/BPM.02/x_pos y_pos: AN02-SD/DG-EPOS/BPM.02/y_pos @@ -530,7 +530,7 @@ - AN02-AR/EM-SX/SHF.01/strength - AN02-AR/EM-COR/SHF.01-CDLH.01/strength - AN02-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_012 x_pos: AN02-AR/DG-EPOS/BPM.03/x_pos y_pos: AN02-AR/DG-EPOS/BPM.03/y_pos @@ -604,7 +604,7 @@ physics: - AN02-AR/EM-SX/SCF.02/strength - AN02-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_013 x_pos: AN02-AR/DG-EPOS/BPM.04/x_pos y_pos: AN02-AR/DG-EPOS/BPM.04/y_pos @@ -664,7 +664,7 @@ physics: - AN02-AR/EM-SX/SCF.05/strength - AN02-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_014 x_pos: AN02-AR/DG-EPOS/BPM.05/x_pos y_pos: AN02-AR/DG-EPOS/BPM.05/y_pos @@ -736,7 +736,7 @@ physics: - AN02-AR/EM-SX/SCD.09/strength - AN02-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_015 x_pos: AN02-AR/DG-EPOS/BPM.06/x_pos y_pos: AN02-AR/DG-EPOS/BPM.06/y_pos @@ -772,7 +772,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN02-AR/EM-COR/CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_016 x_pos: AN02-AR/DG-EPOS/BPM.07/x_pos y_pos: AN02-AR/DG-EPOS/BPM.07/y_pos @@ -804,11 +804,11 @@ - AN02-AR/EM-OCT/OH.03/strength - AN02-AR/EM-COR/OH.03-CQLN.13/strength - AN02-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_017 x_pos: AN03-SD/DG-EPOS/BPM.01/x_pos y_pos: AN03-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_018 x_pos: AN03-SD/DG-EPOS/BPM.02/x_pos y_pos: AN03-SD/DG-EPOS/BPM.02/y_pos @@ -840,7 +840,7 @@ - AN03-AR/EM-SX/SHF.01/strength - AN03-AR/EM-COR/SHF.01-CDLH.01/strength - AN03-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_019 x_pos: AN03-AR/DG-EPOS/BPM.03/x_pos y_pos: AN03-AR/DG-EPOS/BPM.03/y_pos @@ -908,7 +908,7 @@ physics: - AN03-AR/EM-SX/SCF.02/strength - AN03-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_020 x_pos: AN03-AR/DG-EPOS/BPM.04/x_pos y_pos: AN03-AR/DG-EPOS/BPM.04/y_pos @@ -968,7 +968,7 @@ physics: - AN03-AR/EM-SX/SCF.05/strength - AN03-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_021 x_pos: AN03-AR/DG-EPOS/BPM.05/x_pos y_pos: AN03-AR/DG-EPOS/BPM.05/y_pos @@ -1028,7 +1028,7 @@ physics: - AN03-AR/EM-SX/SCF.08/strength - AN03-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_022 x_pos: AN03-AR/DG-EPOS/BPM.06/x_pos y_pos: AN03-AR/DG-EPOS/BPM.06/y_pos @@ -1088,7 +1088,7 @@ - AN03-AR/EM-OCT/OC.04/strength - AN03-AR/EM-COR/OC.04-CQLN.13/strength - AN03-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_023 x_pos: AN03-AR/DG-EPOS/BPM.07/x_pos y_pos: AN03-AR/DG-EPOS/BPM.07/y_pos @@ -1148,7 +1148,7 @@ - AN03-AR/EM-OCT/OC.05/strength - AN03-AR/EM-COR/OC.05-CQLN.16/strength - AN03-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_024 x_pos: AN03-AR/DG-EPOS/BPM.08/x_pos y_pos: AN03-AR/DG-EPOS/BPM.08/y_pos @@ -1220,7 +1220,7 @@ physics: - AN03-AR/EM-SX/SCD.18/strength - AN03-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_025 x_pos: AN03-AR/DG-EPOS/BPM.09/x_pos y_pos: AN03-AR/DG-EPOS/BPM.09/y_pos @@ -1256,7 +1256,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN03-AR/EM-COR/CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_026 x_pos: AN03-AR/DG-EPOS/BPM.10/x_pos y_pos: AN03-AR/DG-EPOS/BPM.10/y_pos @@ -1288,11 +1288,11 @@ - AN03-AR/EM-OCT/OH.02/strength - AN03-AR/EM-COR/OH.02-CQLN.22/strength - AN03-AR/EM-COR/OH.02-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_027 x_pos: AN04-SD/DG-EPOS/BPM.01/x_pos y_pos: AN04-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_028 x_pos: AN04-SD/DG-EPOS/BPM.02/x_pos y_pos: AN04-SD/DG-EPOS/BPM.02/y_pos @@ -1324,7 +1324,7 @@ - AN04-AR/EM-SX/SHF.01/strength - AN04-AR/EM-COR/SHF.01-CDLH.01/strength - AN04-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_029 x_pos: AN04-AR/DG-EPOS/BPM.03/x_pos y_pos: AN04-AR/DG-EPOS/BPM.03/y_pos @@ -1392,7 +1392,7 @@ physics: - AN04-AR/EM-SX/SCF.02/strength - AN04-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_030 x_pos: AN04-AR/DG-EPOS/BPM.04/x_pos y_pos: AN04-AR/DG-EPOS/BPM.04/y_pos @@ -1452,7 +1452,7 @@ - AN04-AR/EM-OCT/OC.02/strength - AN04-AR/EM-COR/OC.02-CQLN.07/strength - AN04-AR/EM-COR/OC.02-CQLT.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_031 x_pos: AN04-AR/DG-EPOS/BPM.05/x_pos y_pos: AN04-AR/DG-EPOS/BPM.05/y_pos @@ -1524,7 +1524,7 @@ physics: - AN04-AR/EM-SX/SCD.09/strength - AN04-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_032 x_pos: AN04-AR/DG-EPOS/BPM.06/x_pos y_pos: AN04-AR/DG-EPOS/BPM.06/y_pos @@ -1566,7 +1566,7 @@ physics: - AN04-AR/EM-OCT/OH.02/strength - AN04-AR/EM-COR/OH.02-CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_033 x_pos: AN04-AR/DG-EPOS/BPM.07/x_pos y_pos: AN04-AR/DG-EPOS/BPM.07/y_pos @@ -1598,11 +1598,11 @@ - AN04-AR/EM-OCT/OH.03/strength - AN04-AR/EM-COR/OH.03-CQLN.13/strength - AN04-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_034 x_pos: AN05-SD/DG-EPOS/BPM.01/x_pos y_pos: AN05-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_035 x_pos: AN05-SD/DG-EPOS/BPM.02/x_pos y_pos: AN05-SD/DG-EPOS/BPM.02/y_pos @@ -1634,7 +1634,7 @@ - AN05-AR/EM-SX/SHF.01/strength - AN05-AR/EM-COR/SHF.01-CDLH.01/strength - AN05-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_036 x_pos: AN05-AR/DG-EPOS/BPM.03/x_pos y_pos: AN05-AR/DG-EPOS/BPM.03/y_pos @@ -1708,7 +1708,7 @@ physics: - AN05-AR/EM-SX/SCF.02/strength - AN05-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_037 x_pos: AN05-AR/DG-EPOS/BPM.04/x_pos y_pos: AN05-AR/DG-EPOS/BPM.04/y_pos @@ -1768,7 +1768,7 @@ physics: - AN05-AR/EM-SX/SCF.05/strength - AN05-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_038 x_pos: AN05-AR/DG-EPOS/BPM.05/x_pos y_pos: AN05-AR/DG-EPOS/BPM.05/y_pos @@ -1828,7 +1828,7 @@ physics: - AN05-AR/EM-SX/SCF.08/strength - AN05-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_039 x_pos: AN05-AR/DG-EPOS/BPM.06/x_pos y_pos: AN05-AR/DG-EPOS/BPM.06/y_pos @@ -1888,7 +1888,7 @@ - AN05-AR/EM-OCT/OC.04/strength - AN05-AR/EM-COR/OC.04-CQLN.13/strength - AN05-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_040 x_pos: AN05-AR/DG-EPOS/BPM.07/x_pos y_pos: AN05-AR/DG-EPOS/BPM.07/y_pos @@ -1948,7 +1948,7 @@ - AN05-AR/EM-OCT/OC.05/strength - AN05-AR/EM-COR/OC.05-CQLN.16/strength - AN05-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_041 x_pos: AN05-AR/DG-EPOS/BPM.08/x_pos y_pos: AN05-AR/DG-EPOS/BPM.08/y_pos @@ -2020,7 +2020,7 @@ physics: - AN05-AR/EM-SX/SCD.18/strength - AN05-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_042 x_pos: AN05-AR/DG-EPOS/BPM.09/x_pos y_pos: AN05-AR/DG-EPOS/BPM.09/y_pos @@ -2042,7 +2042,7 @@ physics: - AN05-AR/EM-SX/SHD.04/strength - AN05-AR/EM-COR/SHD.04-CDLV.09/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_043 x_pos: AN05-AR/DG-EPOS/BPM.10/x_pos y_pos: AN05-AR/DG-EPOS/BPM.10/y_pos @@ -2098,11 +2098,11 @@ - AN05-AR/EM-OCT/OH.04/strength - AN05-AR/EM-COR/OH.04-CQLN.22/strength - AN05-AR/EM-COR/OH.04-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_044 x_pos: AN06-SD/DG-EPOS/BPM.01/x_pos y_pos: AN06-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_045 x_pos: AN06-SD/DG-EPOS/BPM.02/x_pos y_pos: AN06-SD/DG-EPOS/BPM.02/y_pos @@ -2158,11 +2158,11 @@ physics: - AN06-SD/EM-OCT/OH.02/strength - AN06-SD/EM-COR/OH.02-CQLN.02/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_046 x_pos: AN06-SD/DG-EPOS/BPM.03/x_pos y_pos: AN06-SD/DG-EPOS/BPM.03/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_047 x_pos: AN06-SD/DG-EPOS/BPM.04/x_pos y_pos: AN06-SD/DG-EPOS/BPM.04/y_pos @@ -2218,7 +2218,7 @@ physics: - AN06-AR/EM-SX/SHD.02/strength - AN06-AR/EM-COR/SHD.02-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_048 x_pos: AN06-AR/DG-EPOS/BPM.05/x_pos y_pos: AN06-AR/DG-EPOS/BPM.05/y_pos @@ -2272,7 +2272,7 @@ physics: - AN06-AR/EM-SX/SCF.02/strength - AN06-AR/EM-COR/SCF.02-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_049 x_pos: AN06-AR/DG-EPOS/BPM.06/x_pos y_pos: AN06-AR/DG-EPOS/BPM.06/y_pos @@ -2332,7 +2332,7 @@ physics: - AN06-AR/EM-SX/SCF.05/strength - AN06-AR/EM-COR/SCF.05-CDLH.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_050 x_pos: AN06-AR/DG-EPOS/BPM.07/x_pos y_pos: AN06-AR/DG-EPOS/BPM.07/y_pos @@ -2392,7 +2392,7 @@ physics: - AN06-AR/EM-SX/SCF.08/strength - AN06-AR/EM-COR/SCF.08-CDLH.07/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_051 x_pos: AN06-AR/DG-EPOS/BPM.08/x_pos y_pos: AN06-AR/DG-EPOS/BPM.08/y_pos @@ -2452,7 +2452,7 @@ - AN06-AR/EM-OCT/OC.04/strength - AN06-AR/EM-COR/OC.04-CQLN.13/strength - AN06-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_052 x_pos: AN06-AR/DG-EPOS/BPM.09/x_pos y_pos: AN06-AR/DG-EPOS/BPM.09/y_pos @@ -2512,7 +2512,7 @@ - AN06-AR/EM-OCT/OC.05/strength - AN06-AR/EM-COR/OC.05-CQLN.16/strength - AN06-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_053 x_pos: AN06-AR/DG-EPOS/BPM.10/x_pos y_pos: AN06-AR/DG-EPOS/BPM.10/y_pos @@ -2584,7 +2584,7 @@ physics: - AN06-AR/EM-SX/SCD.18/strength - AN06-AR/EM-COR/SCD.18-CDLV.10/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_054 x_pos: AN06-AR/DG-EPOS/BPM.11/x_pos y_pos: AN06-AR/DG-EPOS/BPM.11/y_pos @@ -2626,7 +2626,7 @@ physics: - AN06-AR/EM-OCT/OH.03/strength - AN06-AR/EM-COR/OH.03-CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_055 x_pos: AN06-AR/DG-EPOS/BPM.12/x_pos y_pos: AN06-AR/DG-EPOS/BPM.12/y_pos @@ -2658,11 +2658,11 @@ - AN06-AR/EM-OCT/OH.04/strength - AN06-AR/EM-COR/OH.04-CQLN.22/strength - AN06-AR/EM-COR/OH.04-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_056 x_pos: AN07-SD/DG-EPOS/BPM.01/x_pos y_pos: AN07-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_057 x_pos: AN07-SD/DG-EPOS/BPM.02/x_pos y_pos: AN07-SD/DG-EPOS/BPM.02/y_pos @@ -2694,7 +2694,7 @@ - AN07-AR/EM-SX/SHF.01/strength - AN07-AR/EM-COR/SHF.01-CDLH.01/strength - AN07-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_058 x_pos: AN07-AR/DG-EPOS/BPM.03/x_pos y_pos: AN07-AR/DG-EPOS/BPM.03/y_pos @@ -2768,7 +2768,7 @@ physics: - AN07-AR/EM-SX/SCF.02/strength - AN07-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_059 x_pos: AN07-AR/DG-EPOS/BPM.04/x_pos y_pos: AN07-AR/DG-EPOS/BPM.04/y_pos @@ -2828,7 +2828,7 @@ physics: - AN07-AR/EM-SX/SCF.05/strength - AN07-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_060 x_pos: AN07-AR/DG-EPOS/BPM.05/x_pos y_pos: AN07-AR/DG-EPOS/BPM.05/y_pos @@ -2900,7 +2900,7 @@ physics: - AN07-AR/EM-SX/SCD.09/strength - AN07-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_061 x_pos: AN07-AR/DG-EPOS/BPM.06/x_pos y_pos: AN07-AR/DG-EPOS/BPM.06/y_pos @@ -2936,7 +2936,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN07-AR/EM-COR/CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_062 x_pos: AN07-AR/DG-EPOS/BPM.07/x_pos y_pos: AN07-AR/DG-EPOS/BPM.07/y_pos @@ -2968,11 +2968,11 @@ - AN07-AR/EM-OCT/OH.03/strength - AN07-AR/EM-COR/OH.03-CQLN.13/strength - AN07-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_063 x_pos: AN08-SD/DG-EPOS/BPM.01/x_pos y_pos: AN08-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_064 x_pos: AN08-SD/DG-EPOS/BPM.02/x_pos y_pos: AN08-SD/DG-EPOS/BPM.02/y_pos @@ -3004,7 +3004,7 @@ - AN08-AR/EM-SX/SHF.01/strength - AN08-AR/EM-COR/SHF.01-CDLH.01/strength - AN08-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_065 x_pos: AN08-AR/DG-EPOS/BPM.03/x_pos y_pos: AN08-AR/DG-EPOS/BPM.03/y_pos @@ -3072,7 +3072,7 @@ physics: - AN08-AR/EM-SX/SCF.02/strength - AN08-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_066 x_pos: AN08-AR/DG-EPOS/BPM.04/x_pos y_pos: AN08-AR/DG-EPOS/BPM.04/y_pos @@ -3132,7 +3132,7 @@ physics: - AN08-AR/EM-SX/SCF.05/strength - AN08-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_067 x_pos: AN08-AR/DG-EPOS/BPM.05/x_pos y_pos: AN08-AR/DG-EPOS/BPM.05/y_pos @@ -3192,7 +3192,7 @@ physics: - AN08-AR/EM-SX/SCF.08/strength - AN08-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_068 x_pos: AN08-AR/DG-EPOS/BPM.06/x_pos y_pos: AN08-AR/DG-EPOS/BPM.06/y_pos @@ -3252,7 +3252,7 @@ - AN08-AR/EM-OCT/OC.04/strength - AN08-AR/EM-COR/OC.04-CQLN.13/strength - AN08-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_069 x_pos: AN08-AR/DG-EPOS/BPM.07/x_pos y_pos: AN08-AR/DG-EPOS/BPM.07/y_pos @@ -3312,7 +3312,7 @@ - AN08-AR/EM-OCT/OC.05/strength - AN08-AR/EM-COR/OC.05-CQLN.16/strength - AN08-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_070 x_pos: AN08-AR/DG-EPOS/BPM.08/x_pos y_pos: AN08-AR/DG-EPOS/BPM.08/y_pos @@ -3384,7 +3384,7 @@ physics: - AN08-AR/EM-SX/SCD.18/strength - AN08-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_071 x_pos: AN08-AR/DG-EPOS/BPM.09/x_pos y_pos: AN08-AR/DG-EPOS/BPM.09/y_pos @@ -3420,7 +3420,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN08-AR/EM-COR/CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_072 x_pos: AN08-AR/DG-EPOS/BPM.10/x_pos y_pos: AN08-AR/DG-EPOS/BPM.10/y_pos @@ -3452,11 +3452,11 @@ - AN08-AR/EM-OCT/OH.02/strength - AN08-AR/EM-COR/OH.02-CQLN.22/strength - AN08-AR/EM-COR/OH.02-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_073 x_pos: AN09-SD/DG-EPOS/BPM.01/x_pos y_pos: AN09-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_074 x_pos: AN09-SD/DG-EPOS/BPM.02/x_pos y_pos: AN09-SD/DG-EPOS/BPM.02/y_pos @@ -3488,7 +3488,7 @@ - AN09-AR/EM-SX/SHF.01/strength - AN09-AR/EM-COR/SHF.01-CDLH.01/strength - AN09-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_075 x_pos: AN09-AR/DG-EPOS/BPM.03/x_pos y_pos: AN09-AR/DG-EPOS/BPM.03/y_pos @@ -3556,7 +3556,7 @@ physics: - AN09-AR/EM-SX/SCF.02/strength - AN09-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_076 x_pos: AN09-AR/DG-EPOS/BPM.04/x_pos y_pos: AN09-AR/DG-EPOS/BPM.04/y_pos @@ -3616,7 +3616,7 @@ - AN09-AR/EM-OCT/OC.02/strength - AN09-AR/EM-COR/OC.02-CQLN.07/strength - AN09-AR/EM-COR/OC.02-CQLT.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_077 x_pos: AN09-AR/DG-EPOS/BPM.05/x_pos y_pos: AN09-AR/DG-EPOS/BPM.05/y_pos @@ -3688,7 +3688,7 @@ physics: - AN09-AR/EM-SX/SCD.09/strength - AN09-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_078 x_pos: AN09-AR/DG-EPOS/BPM.06/x_pos y_pos: AN09-AR/DG-EPOS/BPM.06/y_pos @@ -3730,7 +3730,7 @@ physics: - AN09-AR/EM-OCT/OH.02/strength - AN09-AR/EM-COR/OH.02-CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_079 x_pos: AN09-AR/DG-EPOS/BPM.07/x_pos y_pos: AN09-AR/DG-EPOS/BPM.07/y_pos @@ -3762,11 +3762,11 @@ - AN09-AR/EM-OCT/OH.03/strength - AN09-AR/EM-COR/OH.03-CQLN.13/strength - AN09-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_080 x_pos: AN10-SD/DG-EPOS/BPM.01/x_pos y_pos: AN10-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_081 x_pos: AN10-SD/DG-EPOS/BPM.02/x_pos y_pos: AN10-SD/DG-EPOS/BPM.02/y_pos @@ -3798,7 +3798,7 @@ - AN10-AR/EM-SX/SHF.01/strength - AN10-AR/EM-COR/SHF.01-CDLH.01/strength - AN10-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_082 x_pos: AN10-AR/DG-EPOS/BPM.03/x_pos y_pos: AN10-AR/DG-EPOS/BPM.03/y_pos @@ -3872,7 +3872,7 @@ physics: - AN10-AR/EM-SX/SCF.02/strength - AN10-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_083 x_pos: AN10-AR/DG-EPOS/BPM.04/x_pos y_pos: AN10-AR/DG-EPOS/BPM.04/y_pos @@ -3932,7 +3932,7 @@ physics: - AN10-AR/EM-SX/SCF.05/strength - AN10-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_084 x_pos: AN10-AR/DG-EPOS/BPM.05/x_pos y_pos: AN10-AR/DG-EPOS/BPM.05/y_pos @@ -3992,7 +3992,7 @@ physics: - AN10-AR/EM-SX/SCF.08/strength - AN10-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_085 x_pos: AN10-AR/DG-EPOS/BPM.06/x_pos y_pos: AN10-AR/DG-EPOS/BPM.06/y_pos @@ -4052,7 +4052,7 @@ - AN10-AR/EM-OCT/OC.04/strength - AN10-AR/EM-COR/OC.04-CQLN.13/strength - AN10-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_086 x_pos: AN10-AR/DG-EPOS/BPM.07/x_pos y_pos: AN10-AR/DG-EPOS/BPM.07/y_pos @@ -4112,7 +4112,7 @@ - AN10-AR/EM-OCT/OC.05/strength - AN10-AR/EM-COR/OC.05-CQLN.16/strength - AN10-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_087 x_pos: AN10-AR/DG-EPOS/BPM.08/x_pos y_pos: AN10-AR/DG-EPOS/BPM.08/y_pos @@ -4184,7 +4184,7 @@ physics: - AN10-AR/EM-SX/SCD.18/strength - AN10-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_088 x_pos: AN10-AR/DG-EPOS/BPM.09/x_pos y_pos: AN10-AR/DG-EPOS/BPM.09/y_pos @@ -4206,7 +4206,7 @@ physics: - AN10-AR/EM-SX/SHD.04/strength - AN10-AR/EM-COR/SHD.04-CDLV.09/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_089 x_pos: AN10-AR/DG-EPOS/BPM.10/x_pos y_pos: AN10-AR/DG-EPOS/BPM.10/y_pos @@ -4262,11 +4262,11 @@ - AN10-AR/EM-SX/SHF.06/strength - AN10-AR/EM-COR/SHF.06-CDLH.10/strength - AN10-AR/EM-COR/SHF.06-CDLV.10/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_090 x_pos: AN11-SD/DG-EPOS/BPM.01/x_pos y_pos: AN11-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_091 x_pos: AN11-SD/DG-EPOS/BPM.02/x_pos y_pos: AN11-SD/DG-EPOS/BPM.02/y_pos @@ -4322,7 +4322,7 @@ physics: - AN11-AR/EM-OCT/OH.02/strength - AN11-AR/EM-COR/OH.02-CQLN.02/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_092 x_pos: AN11-AR/DG-EPOS/BPM.03/x_pos y_pos: AN11-AR/DG-EPOS/BPM.03/y_pos @@ -4376,7 +4376,7 @@ physics: - AN11-AR/EM-SX/SCF.02/strength - AN11-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_093 x_pos: AN11-AR/DG-EPOS/BPM.04/x_pos y_pos: AN11-AR/DG-EPOS/BPM.04/y_pos @@ -4436,7 +4436,7 @@ physics: - AN11-AR/EM-SX/SCF.05/strength - AN11-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_094 x_pos: AN11-AR/DG-EPOS/BPM.05/x_pos y_pos: AN11-AR/DG-EPOS/BPM.05/y_pos @@ -4496,7 +4496,7 @@ physics: - AN11-AR/EM-SX/SCF.08/strength - AN11-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_095 x_pos: AN11-AR/DG-EPOS/BPM.06/x_pos y_pos: AN11-AR/DG-EPOS/BPM.06/y_pos @@ -4556,7 +4556,7 @@ - AN11-AR/EM-OCT/OC.04/strength - AN11-AR/EM-COR/OC.04-CQLN.13/strength - AN11-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_096 x_pos: AN11-AR/DG-EPOS/BPM.07/x_pos y_pos: AN11-AR/DG-EPOS/BPM.07/y_pos @@ -4616,7 +4616,7 @@ - AN11-AR/EM-OCT/OC.05/strength - AN11-AR/EM-COR/OC.05-CQLN.16/strength - AN11-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_097 x_pos: AN11-AR/DG-EPOS/BPM.08/x_pos y_pos: AN11-AR/DG-EPOS/BPM.08/y_pos @@ -4688,7 +4688,7 @@ physics: - AN11-AR/EM-SX/SCD.18/strength - AN11-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_098 x_pos: AN11-AR/DG-EPOS/BPM.09/x_pos y_pos: AN11-AR/DG-EPOS/BPM.09/y_pos @@ -4730,7 +4730,7 @@ physics: - AN11-AR/EM-OCT/OH.03/strength - AN11-AR/EM-COR/OH.03-CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_099 x_pos: AN11-AR/DG-EPOS/BPM.10/x_pos y_pos: AN11-AR/DG-EPOS/BPM.10/y_pos @@ -4762,11 +4762,11 @@ - AN11-AR/EM-OCT/OH.04/strength - AN11-AR/EM-COR/OH.04-CQLN.22/strength - AN11-AR/EM-COR/OH.04-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_100 x_pos: AN12-SD/DG-EPOS/BPM.01/x_pos y_pos: AN12-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_101 x_pos: AN12-SD/DG-EPOS/BPM.02/x_pos y_pos: AN12-SD/DG-EPOS/BPM.02/y_pos @@ -4798,7 +4798,7 @@ - AN12-AR/EM-SX/SHF.01/strength - AN12-AR/EM-COR/SHF.01-CDLH.01/strength - AN12-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_102 x_pos: AN12-AR/DG-EPOS/BPM.03/x_pos y_pos: AN12-AR/DG-EPOS/BPM.03/y_pos @@ -4872,7 +4872,7 @@ physics: - AN12-AR/EM-SX/SCF.02/strength - AN12-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_103 x_pos: AN12-AR/DG-EPOS/BPM.04/x_pos y_pos: AN12-AR/DG-EPOS/BPM.04/y_pos @@ -4932,7 +4932,7 @@ physics: - AN12-AR/EM-SX/SCF.05/strength - AN12-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_104 x_pos: AN12-AR/DG-EPOS/BPM.05/x_pos y_pos: AN12-AR/DG-EPOS/BPM.05/y_pos @@ -5004,7 +5004,7 @@ physics: - AN12-AR/EM-SX/SCD.09/strength - AN12-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_105 x_pos: AN12-AR/DG-EPOS/BPM.06/x_pos y_pos: AN12-AR/DG-EPOS/BPM.06/y_pos @@ -5040,7 +5040,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN12-AR/EM-COR/CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_106 x_pos: AN12-AR/DG-EPOS/BPM.07/x_pos y_pos: AN12-AR/DG-EPOS/BPM.07/y_pos @@ -5072,11 +5072,11 @@ - AN12-AR/EM-OCT/OH.03/strength - AN12-AR/EM-COR/OH.03-CQLN.13/strength - AN12-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_107 x_pos: AN13-SD/DG-EPOS/BPM.01/x_pos y_pos: AN13-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_108 x_pos: AN13-SD/DG-EPOS/BPM.02/x_pos y_pos: AN13-SD/DG-EPOS/BPM.02/y_pos @@ -5108,7 +5108,7 @@ - AN13-AR/EM-SX/SHF.01/strength - AN13-AR/EM-COR/SHF.01-CDLH.01/strength - AN13-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_109 x_pos: AN13-AR/DG-EPOS/BPM.03/x_pos y_pos: AN13-AR/DG-EPOS/BPM.03/y_pos @@ -5176,7 +5176,7 @@ physics: - AN13-AR/EM-SX/SCF.02/strength - AN13-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_110 x_pos: AN13-AR/DG-EPOS/BPM.04/x_pos y_pos: AN13-AR/DG-EPOS/BPM.04/y_pos @@ -5236,7 +5236,7 @@ physics: - AN13-AR/EM-SX/SCF.05/strength - AN13-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_111 x_pos: AN13-AR/DG-EPOS/BPM.05/x_pos y_pos: AN13-AR/DG-EPOS/BPM.05/y_pos @@ -5296,7 +5296,7 @@ physics: - AN13-AR/EM-SX/SCF.08/strength - AN13-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_112 x_pos: AN13-AR/DG-EPOS/BPM.06/x_pos y_pos: AN13-AR/DG-EPOS/BPM.06/y_pos @@ -5356,7 +5356,7 @@ - AN13-AR/EM-OCT/OC.04/strength - AN13-AR/EM-COR/OC.04-CQLN.13/strength - AN13-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_113 x_pos: AN13-AR/DG-EPOS/BPM.07/x_pos y_pos: AN13-AR/DG-EPOS/BPM.07/y_pos @@ -5416,7 +5416,7 @@ - AN13-AR/EM-OCT/OC.05/strength - AN13-AR/EM-COR/OC.05-CQLN.16/strength - AN13-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_114 x_pos: AN13-AR/DG-EPOS/BPM.08/x_pos y_pos: AN13-AR/DG-EPOS/BPM.08/y_pos @@ -5488,7 +5488,7 @@ physics: - AN13-AR/EM-SX/SCD.18/strength - AN13-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_115 x_pos: AN13-AR/DG-EPOS/BPM.09/x_pos y_pos: AN13-AR/DG-EPOS/BPM.09/y_pos @@ -5524,7 +5524,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN13-AR/EM-COR/CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_116 x_pos: AN13-AR/DG-EPOS/BPM.10/x_pos y_pos: AN13-AR/DG-EPOS/BPM.10/y_pos @@ -5556,11 +5556,11 @@ - AN13-AR/EM-OCT/OH.02/strength - AN13-AR/EM-COR/OH.02-CQLN.22/strength - AN13-AR/EM-COR/OH.02-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_117 x_pos: AN14-SD/DG-EPOS/BPM.01/x_pos y_pos: AN14-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_118 x_pos: AN14-SD/DG-EPOS/BPM.02/x_pos y_pos: AN14-SD/DG-EPOS/BPM.02/y_pos @@ -5592,7 +5592,7 @@ - AN14-AR/EM-SX/SHF.01/strength - AN14-AR/EM-COR/SHF.01-CDLH.01/strength - AN14-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_119 x_pos: AN14-AR/DG-EPOS/BPM.03/x_pos y_pos: AN14-AR/DG-EPOS/BPM.03/y_pos @@ -5660,7 +5660,7 @@ physics: - AN14-AR/EM-SX/SCF.02/strength - AN14-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_120 x_pos: AN14-AR/DG-EPOS/BPM.04/x_pos y_pos: AN14-AR/DG-EPOS/BPM.04/y_pos @@ -5720,7 +5720,7 @@ - AN14-AR/EM-OCT/OC.02/strength - AN14-AR/EM-COR/OC.02-CQLN.07/strength - AN14-AR/EM-COR/OC.02-CQLT.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_121 x_pos: AN14-AR/DG-EPOS/BPM.05/x_pos y_pos: AN14-AR/DG-EPOS/BPM.05/y_pos @@ -5792,7 +5792,7 @@ physics: - AN14-AR/EM-SX/SCD.09/strength - AN14-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_122 x_pos: AN14-AR/DG-EPOS/BPM.06/x_pos y_pos: AN14-AR/DG-EPOS/BPM.06/y_pos @@ -5834,7 +5834,7 @@ physics: - AN14-AR/EM-OCT/OH.02/strength - AN14-AR/EM-COR/OH.02-CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_123 x_pos: AN14-AR/DG-EPOS/BPM.07/x_pos y_pos: AN14-AR/DG-EPOS/BPM.07/y_pos @@ -5866,11 +5866,11 @@ - AN14-AR/EM-OCT/OH.03/strength - AN14-AR/EM-COR/OH.03-CQLN.13/strength - AN14-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_124 x_pos: AN15-SD/DG-EPOS/BPM.01/x_pos y_pos: AN15-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_125 x_pos: AN15-SD/DG-EPOS/BPM.02/x_pos y_pos: AN15-SD/DG-EPOS/BPM.02/y_pos @@ -5902,7 +5902,7 @@ - AN15-AR/EM-SX/SHF.01/strength - AN15-AR/EM-COR/SHF.01-CDLH.01/strength - AN15-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_126 x_pos: AN15-AR/DG-EPOS/BPM.03/x_pos y_pos: AN15-AR/DG-EPOS/BPM.03/y_pos @@ -5976,7 +5976,7 @@ physics: - AN15-AR/EM-SX/SCF.02/strength - AN15-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_127 x_pos: AN15-AR/DG-EPOS/BPM.04/x_pos y_pos: AN15-AR/DG-EPOS/BPM.04/y_pos @@ -6036,7 +6036,7 @@ physics: - AN15-AR/EM-SX/SCF.05/strength - AN15-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_128 x_pos: AN15-AR/DG-EPOS/BPM.05/x_pos y_pos: AN15-AR/DG-EPOS/BPM.05/y_pos @@ -6096,7 +6096,7 @@ physics: - AN15-AR/EM-SX/SCF.08/strength - AN15-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_129 x_pos: AN15-AR/DG-EPOS/BPM.06/x_pos y_pos: AN15-AR/DG-EPOS/BPM.06/y_pos @@ -6156,7 +6156,7 @@ - AN15-AR/EM-OCT/OC.04/strength - AN15-AR/EM-COR/OC.04-CQLN.13/strength - AN15-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_130 x_pos: AN15-AR/DG-EPOS/BPM.07/x_pos y_pos: AN15-AR/DG-EPOS/BPM.07/y_pos @@ -6216,7 +6216,7 @@ - AN15-AR/EM-OCT/OC.05/strength - AN15-AR/EM-COR/OC.05-CQLN.16/strength - AN15-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_131 x_pos: AN15-AR/DG-EPOS/BPM.08/x_pos y_pos: AN15-AR/DG-EPOS/BPM.08/y_pos @@ -6288,7 +6288,7 @@ physics: - AN15-AR/EM-SX/SCD.18/strength - AN15-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_132 x_pos: AN15-AR/DG-EPOS/BPM.09/x_pos y_pos: AN15-AR/DG-EPOS/BPM.09/y_pos @@ -6310,7 +6310,7 @@ physics: - AN15-AR/EM-SX/SHD.04/strength - AN15-AR/EM-COR/SHD.04-CDLV.09/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_133 x_pos: AN15-AR/DG-EPOS/BPM.10/x_pos y_pos: AN15-AR/DG-EPOS/BPM.10/y_pos @@ -6364,11 +6364,11 @@ physics: - AN15-AR/EM-OCT/OH.04/strength - AN15-AR/EM-COR/OH.04-CQLN.22/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_134 x_pos: AN16-SD/DG-EPOS/BPM.01/x_pos y_pos: AN16-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_135 x_pos: AN16-SD/DG-EPOS/BPM.02/x_pos y_pos: AN16-SD/DG-EPOS/BPM.02/y_pos @@ -6424,11 +6424,11 @@ physics: - AN16-SD/EM-OCT/OH.02/strength - AN16-SD/EM-COR/OH.02-CQLN.02/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_136 x_pos: AN16-SD/DG-EPOS/BPM.03/x_pos y_pos: AN16-SD/DG-EPOS/BPM.03/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_137 x_pos: AN16-SD/DG-EPOS/BPM.04/x_pos y_pos: AN16-SD/DG-EPOS/BPM.04/y_pos @@ -6482,7 +6482,7 @@ physics: - AN16-AR/EM-SX/SHD.02/strength - AN16-AR/EM-COR/SHD.02-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_138 x_pos: AN16-AR/DG-EPOS/BPM.05/x_pos y_pos: AN16-AR/DG-EPOS/BPM.05/y_pos @@ -6536,7 +6536,7 @@ physics: - AN16-AR/EM-SX/SCF.02/strength - AN16-AR/EM-COR/SCF.02-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_139 x_pos: AN16-AR/DG-EPOS/BPM.06/x_pos y_pos: AN16-AR/DG-EPOS/BPM.06/y_pos @@ -6596,7 +6596,7 @@ physics: - AN16-AR/EM-SX/SCF.05/strength - AN16-AR/EM-COR/SCF.05-CDLH.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_140 x_pos: AN16-AR/DG-EPOS/BPM.07/x_pos y_pos: AN16-AR/DG-EPOS/BPM.07/y_pos @@ -6656,7 +6656,7 @@ physics: - AN16-AR/EM-SX/SCF.08/strength - AN16-AR/EM-COR/SCF.08-CDLH.07/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_141 x_pos: AN16-AR/DG-EPOS/BPM.08/x_pos y_pos: AN16-AR/DG-EPOS/BPM.08/y_pos @@ -6716,7 +6716,7 @@ - AN16-AR/EM-OCT/OC.04/strength - AN16-AR/EM-COR/OC.04-CQLN.13/strength - AN16-AR/EM-COR/OC.04-CQLT.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_142 x_pos: AN16-AR/DG-EPOS/BPM.09/x_pos y_pos: AN16-AR/DG-EPOS/BPM.09/y_pos @@ -6776,7 +6776,7 @@ - AN16-AR/EM-OCT/OC.05/strength - AN16-AR/EM-COR/OC.05-CQLN.16/strength - AN16-AR/EM-COR/OC.05-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_143 x_pos: AN16-AR/DG-EPOS/BPM.10/x_pos y_pos: AN16-AR/DG-EPOS/BPM.10/y_pos @@ -6848,7 +6848,7 @@ physics: - AN16-AR/EM-SX/SCD.18/strength - AN16-AR/EM-COR/SCD.18-CDLV.10/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_144 x_pos: AN16-AR/DG-EPOS/BPM.11/x_pos y_pos: AN16-AR/DG-EPOS/BPM.11/y_pos @@ -6890,7 +6890,7 @@ physics: - AN16-AR/EM-OCT/OH.03/strength - AN16-AR/EM-COR/OH.03-CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_145 x_pos: AN16-AR/DG-EPOS/BPM.12/x_pos y_pos: AN16-AR/DG-EPOS/BPM.12/y_pos @@ -6922,11 +6922,11 @@ - AN16-AR/EM-OCT/OH.04/strength - AN16-AR/EM-COR/OH.04-CQLN.22/strength - AN16-AR/EM-COR/OH.04-CQLT.07/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_146 x_pos: AN17-SD/DG-EPOS/BPM.01/x_pos y_pos: AN17-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_147 x_pos: AN17-SD/DG-EPOS/BPM.02/x_pos y_pos: AN17-SD/DG-EPOS/BPM.02/y_pos @@ -6958,7 +6958,7 @@ - AN17-AR/EM-SX/SHF.01/strength - AN17-AR/EM-COR/SHF.01-CDLH.01/strength - AN17-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_148 x_pos: AN17-AR/DG-EPOS/BPM.03/x_pos y_pos: AN17-AR/DG-EPOS/BPM.03/y_pos @@ -7032,7 +7032,7 @@ physics: - AN17-AR/EM-SX/SCF.02/strength - AN17-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_149 x_pos: AN17-AR/DG-EPOS/BPM.04/x_pos y_pos: AN17-AR/DG-EPOS/BPM.04/y_pos @@ -7092,7 +7092,7 @@ physics: - AN17-AR/EM-SX/SCF.05/strength - AN17-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_150 x_pos: AN17-AR/DG-EPOS/BPM.05/x_pos y_pos: AN17-AR/DG-EPOS/BPM.05/y_pos @@ -7164,7 +7164,7 @@ physics: - AN17-AR/EM-SX/SCD.09/strength - AN17-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_151 x_pos: AN17-AR/DG-EPOS/BPM.06/x_pos y_pos: AN17-AR/DG-EPOS/BPM.06/y_pos @@ -7200,7 +7200,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN17-AR/EM-COR/CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_152 x_pos: AN17-AR/DG-EPOS/BPM.07/x_pos y_pos: AN17-AR/DG-EPOS/BPM.07/y_pos @@ -7232,11 +7232,11 @@ - AN17-AR/EM-OCT/OH.03/strength - AN17-AR/EM-COR/OH.03-CQLN.13/strength - AN17-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_153 x_pos: AN18-SD/DG-EPOS/BPM.01/x_pos y_pos: AN18-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_154 x_pos: AN18-SD/DG-EPOS/BPM.02/x_pos y_pos: AN18-SD/DG-EPOS/BPM.02/y_pos @@ -7268,7 +7268,7 @@ - AN18-AR/EM-SX/SHF.01/strength - AN18-AR/EM-COR/SHF.01-CDLH.01/strength - AN18-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_155 x_pos: AN18-AR/DG-EPOS/BPM.03/x_pos y_pos: AN18-AR/DG-EPOS/BPM.03/y_pos @@ -7336,7 +7336,7 @@ physics: - AN18-AR/EM-SX/SCF.02/strength - AN18-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_156 x_pos: AN18-AR/DG-EPOS/BPM.04/x_pos y_pos: AN18-AR/DG-EPOS/BPM.04/y_pos @@ -7396,7 +7396,7 @@ physics: - AN18-AR/EM-SX/SCF.05/strength - AN18-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_157 x_pos: AN18-AR/DG-EPOS/BPM.05/x_pos y_pos: AN18-AR/DG-EPOS/BPM.05/y_pos @@ -7456,7 +7456,7 @@ physics: - AN18-AR/EM-SX/SCF.08/strength - AN18-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_158 x_pos: AN18-AR/DG-EPOS/BPM.06/x_pos y_pos: AN18-AR/DG-EPOS/BPM.06/y_pos @@ -7516,7 +7516,7 @@ - AN18-AR/EM-OCT/OC.04/strength - AN18-AR/EM-COR/OC.04-CQLN.13/strength - AN18-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_159 x_pos: AN18-AR/DG-EPOS/BPM.07/x_pos y_pos: AN18-AR/DG-EPOS/BPM.07/y_pos @@ -7576,7 +7576,7 @@ - AN18-AR/EM-OCT/OC.05/strength - AN18-AR/EM-COR/OC.05-CQLN.16/strength - AN18-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_160 x_pos: AN18-AR/DG-EPOS/BPM.08/x_pos y_pos: AN18-AR/DG-EPOS/BPM.08/y_pos @@ -7648,7 +7648,7 @@ physics: - AN18-AR/EM-SX/SCD.18/strength - AN18-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_161 x_pos: AN18-AR/DG-EPOS/BPM.09/x_pos y_pos: AN18-AR/DG-EPOS/BPM.09/y_pos @@ -7684,7 +7684,7 @@ type: pyaml.magnet.identity_model unit: 1/m physics: AN18-AR/EM-COR/CQLN.21/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_162 x_pos: AN18-AR/DG-EPOS/BPM.10/x_pos y_pos: AN18-AR/DG-EPOS/BPM.10/y_pos @@ -7716,11 +7716,11 @@ - AN18-AR/EM-OCT/OH.02/strength - AN18-AR/EM-COR/OH.02-CQLN.22/strength - AN18-AR/EM-COR/OH.02-CQLT.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_163 x_pos: AN19-SD/DG-EPOS/BPM.01/x_pos y_pos: AN19-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_164 x_pos: AN19-SD/DG-EPOS/BPM.02/x_pos y_pos: AN19-SD/DG-EPOS/BPM.02/y_pos @@ -7752,7 +7752,7 @@ - AN19-AR/EM-SX/SHF.01/strength - AN19-AR/EM-COR/SHF.01-CDLH.01/strength - AN19-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_165 x_pos: AN19-AR/DG-EPOS/BPM.03/x_pos y_pos: AN19-AR/DG-EPOS/BPM.03/y_pos @@ -7820,7 +7820,7 @@ physics: - AN19-AR/EM-SX/SCF.02/strength - AN19-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_166 x_pos: AN19-AR/DG-EPOS/BPM.04/x_pos y_pos: AN19-AR/DG-EPOS/BPM.04/y_pos @@ -7880,7 +7880,7 @@ - AN19-AR/EM-OCT/OC.02/strength - AN19-AR/EM-COR/OC.02-CQLN.07/strength - AN19-AR/EM-COR/OC.02-CQLT.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_167 x_pos: AN19-AR/DG-EPOS/BPM.05/x_pos y_pos: AN19-AR/DG-EPOS/BPM.05/y_pos @@ -7952,7 +7952,7 @@ physics: - AN19-AR/EM-SX/SCD.09/strength - AN19-AR/EM-COR/SCD.09-CDLV.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_168 x_pos: AN19-AR/DG-EPOS/BPM.06/x_pos y_pos: AN19-AR/DG-EPOS/BPM.06/y_pos @@ -7994,7 +7994,7 @@ physics: - AN19-AR/EM-OCT/OH.02/strength - AN19-AR/EM-COR/OH.02-CQLN.12/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_169 x_pos: AN19-AR/DG-EPOS/BPM.07/x_pos y_pos: AN19-AR/DG-EPOS/BPM.07/y_pos @@ -8026,11 +8026,11 @@ - AN19-AR/EM-OCT/OH.03/strength - AN19-AR/EM-COR/OH.03-CQLN.13/strength - AN19-AR/EM-COR/OH.03-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_170 x_pos: AN20-SD/DG-EPOS/BPM.01/x_pos y_pos: AN20-SD/DG-EPOS/BPM.01/y_pos -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_171 x_pos: AN20-SD/DG-EPOS/BPM.02/x_pos y_pos: AN20-SD/DG-EPOS/BPM.02/y_pos @@ -8062,7 +8062,7 @@ - AN20-AR/EM-SX/SHF.01/strength - AN20-AR/EM-COR/SHF.01-CDLH.01/strength - AN20-AR/EM-COR/SHF.01-CDLV.01/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_172 x_pos: AN20-AR/DG-EPOS/BPM.03/x_pos y_pos: AN20-AR/DG-EPOS/BPM.03/y_pos @@ -8136,7 +8136,7 @@ physics: - AN20-AR/EM-SX/SCF.02/strength - AN20-AR/EM-COR/SCF.02-CDLH.03/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_173 x_pos: AN20-AR/DG-EPOS/BPM.04/x_pos y_pos: AN20-AR/DG-EPOS/BPM.04/y_pos @@ -8196,7 +8196,7 @@ physics: - AN20-AR/EM-SX/SCF.05/strength - AN20-AR/EM-COR/SCF.05-CDLH.04/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_174 x_pos: AN20-AR/DG-EPOS/BPM.05/x_pos y_pos: AN20-AR/DG-EPOS/BPM.05/y_pos @@ -8256,7 +8256,7 @@ physics: - AN20-AR/EM-SX/SCF.08/strength - AN20-AR/EM-COR/SCF.08-CDLH.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_175 x_pos: AN20-AR/DG-EPOS/BPM.06/x_pos y_pos: AN20-AR/DG-EPOS/BPM.06/y_pos @@ -8316,7 +8316,7 @@ - AN20-AR/EM-OCT/OC.04/strength - AN20-AR/EM-COR/OC.04-CQLN.13/strength - AN20-AR/EM-COR/OC.04-CQLT.05/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_176 x_pos: AN20-AR/DG-EPOS/BPM.07/x_pos y_pos: AN20-AR/DG-EPOS/BPM.07/y_pos @@ -8376,7 +8376,7 @@ - AN20-AR/EM-OCT/OC.05/strength - AN20-AR/EM-COR/OC.05-CQLN.16/strength - AN20-AR/EM-COR/OC.05-CQLT.06/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_177 x_pos: AN20-AR/DG-EPOS/BPM.08/x_pos y_pos: AN20-AR/DG-EPOS/BPM.08/y_pos @@ -8448,7 +8448,7 @@ physics: - AN20-AR/EM-SX/SCD.18/strength - AN20-AR/EM-COR/SCD.18-CDLV.08/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_178 x_pos: AN20-AR/DG-EPOS/BPM.09/x_pos y_pos: AN20-AR/DG-EPOS/BPM.09/y_pos @@ -8470,7 +8470,7 @@ physics: - AN20-AR/EM-SX/SHD.04/strength - AN20-AR/EM-COR/SHD.04-CDLV.09/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_179 x_pos: AN20-AR/DG-EPOS/BPM.10/x_pos y_pos: AN20-AR/DG-EPOS/BPM.10/y_pos @@ -8526,7 +8526,7 @@ - AN20-AR/EM-SX/SHF.06/strength - AN20-AR/EM-COR/SHF.06-CDLH.10/strength - AN20-AR/EM-COR/SHF.06-CDLV.10/strength -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_180 x_pos: AN01-SD/DG-EPOS/BPM.01/x_pos y_pos: AN01-SD/DG-EPOS/BPM.01/y_pos diff --git a/pyaml/apidoc/gen_api.py b/pyaml/apidoc/gen_api.py index e2b05a8a..4439e85e 100644 --- a/pyaml/apidoc/gen_api.py +++ b/pyaml/apidoc/gen_api.py @@ -20,7 +20,6 @@ "pyaml.arrays.magnet_array", "pyaml.arrays.serialized_magnet", "pyaml.arrays.serialized_magnet_array", - "pyaml.bpm.bpm", "pyaml.common.abstract", "pyaml.common.abstract_aggregator", "pyaml.common.constants", @@ -40,6 +39,7 @@ "pyaml.control.deviceaccesslist", "pyaml.control.readback_value", "pyaml.diagnostics.atune_monitor", + "pyaml.diagnostics.bpm.bpm", "pyaml.diagnostics.tune_monitor", "pyaml.external.pySC_interface", "pyaml.lattice.abstract_impl", diff --git a/pyaml/arrays/bpm_array.py b/pyaml/arrays/bpm_array.py index 9006af38..f3751226 100644 --- a/pyaml/arrays/bpm_array.py +++ b/pyaml/arrays/bpm_array.py @@ -6,7 +6,8 @@ import numpy as np -from ..bpm.bpm import BPM +from pyaml.diagnostics.bpm import BPM + from ..common.abstract import ReadFloatArray from ..control.deviceaccesslist import DeviceAccessList from .element_array import ElementArray @@ -24,7 +25,7 @@ class RWBPMPosition(ReadFloatArray): ---------- name : str Name of the position accessor - bpms : list[pyaml.bpm.bpm.BPM] + bpms : list[pyaml.diagnostics.bpm.bpm.BPM] List of BPM objects to access Methods @@ -98,7 +99,7 @@ class RWBPMSinglePosition(ReadFloatArray): ---------- name : str Name of the position accessor - bpms : list[pyaml.bpm.bpm.BPM] + bpms : list[pyaml.diagnostics.bpm.bpm.BPM] List of BPM objects to access idx : int Index for the position axis (0 for horizontal, 1 for vertical) @@ -170,7 +171,7 @@ class BPMArray(ElementArray): ---------- arrayName : str Array name - bpms : list[pyaml.bpm.bpm.BPM] + bpms : list[pyaml.diagnostics.bpm.bpm.BPM] BPM list, all elements must be attached to the same instance of either a (:py:class:`~pyaml.lattice.simulator.Simulator` or a :py:class:`~pyaml.control.controlsystem.ControlSystem`). diff --git a/pyaml/arrays/element_array.py b/pyaml/arrays/element_array.py index 797fc919..d39d7cbb 100644 --- a/pyaml/arrays/element_array.py +++ b/pyaml/arrays/element_array.py @@ -10,7 +10,8 @@ import numpy as np -from ..bpm.bpm import BPM +from pyaml.diagnostics.bpm import BPM + from ..common.element import Element, __pyaml_repr__ from ..common.exception import PyAMLException from ..common.name_matching import resolve_names diff --git a/pyaml/bpm/__init__.py b/pyaml/bpm/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py index f5880dd2..1cf63dfb 100644 --- a/pyaml/common/holders/element_holder.py +++ b/pyaml/common/holders/element_holder.py @@ -3,8 +3,9 @@ from abc import ABCMeta, abstractmethod from typing import TYPE_CHECKING, overload +from pyaml.diagnostics.bpm import BPM + from ...arrays.element_array import ElementArray -from ...bpm.bpm import BPM from ...diagnostics.tune_monitor import BetatronTuneMonitor from ...magnet.cfm_magnet import CombinedFunctionMagnet from ...magnet.magnet import Magnet diff --git a/pyaml/common/holders/sub_holders.py b/pyaml/common/holders/sub_holders.py index f5e36b92..7d2bdc0a 100644 --- a/pyaml/common/holders/sub_holders.py +++ b/pyaml/common/holders/sub_holders.py @@ -2,11 +2,12 @@ from typing import TYPE_CHECKING +from pyaml.diagnostics.bpm import BPM + from ...arrays.bpm_array import BPMArray from ...arrays.cfm_magnet_array import CombinedFunctionMagnetArray from ...arrays.magnet_array import MagnetArray from ...arrays.serialized_magnet_array import SerializedMagnetsArray -from ...bpm.bpm import BPM from ...magnet.cfm_magnet import CombinedFunctionMagnet from ...magnet.magnet import Magnet from ...magnet.serialized_magnet import SerializedMagnets diff --git a/pyaml/control/controlsystem.py b/pyaml/control/controlsystem.py index d2e25470..d8a5ef80 100644 --- a/pyaml/control/controlsystem.py +++ b/pyaml/control/controlsystem.py @@ -10,7 +10,8 @@ from pydantic import BaseModel -from ..bpm.bpm import BPM +from pyaml.diagnostics.bpm import BPM + from ..common.abstract import RWMapper from ..common.abstract_aggregator import ScalarAggregator from ..common.exception import PyAMLException diff --git a/pyaml/diagnostics/bpm/__init__.py b/pyaml/diagnostics/bpm/__init__.py new file mode 100644 index 00000000..84915bda --- /dev/null +++ b/pyaml/diagnostics/bpm/__init__.py @@ -0,0 +1,3 @@ +from pyaml.diagnostics.bpm.bpm import BPM + +__all__ = ["BPM"] diff --git a/pyaml/bpm/bpm.py b/pyaml/diagnostics/bpm/bpm.py similarity index 94% rename from pyaml/bpm/bpm.py rename to pyaml/diagnostics/bpm/bpm.py index 364f3899..c63f662a 100644 --- a/pyaml/bpm/bpm.py +++ b/pyaml/diagnostics/bpm/bpm.py @@ -3,13 +3,13 @@ import copy from typing import TYPE_CHECKING, Self -from ..common.abstract import ReadFloatArray, ReadWriteFloatArray, ReadWriteFloatScalar -from ..common.element import Element, __pyaml_repr__ -from ..common.exception import PyAMLException -from ..validation import DynamicValidation, register_schema +from pyaml.common.abstract import ReadFloatArray, ReadWriteFloatArray, ReadWriteFloatScalar +from pyaml.common.element import Element, __pyaml_repr__ +from pyaml.common.exception import PyAMLException +from pyaml.validation import DynamicValidation, register_schema if TYPE_CHECKING: - from ..common.holders.element_holder import ElementHolder + from pyaml.common.holders.element_holder import ElementHolder PYAMLCLASS = "BPM" @@ -66,7 +66,7 @@ class BPM(Element, DynamicValidation): ------------- .. code-block:: yaml - - type: pyaml.bpm.bpm + - type: pyaml.diagnostics.bpm.bpm name: BPM_NAME lattice_names: LATTICE_BPM_NAME x_pos: DEVICE/X_POSITION diff --git a/pyaml/lattice/simulator.py b/pyaml/lattice/simulator.py index 14903724..738ddaf2 100644 --- a/pyaml/lattice/simulator.py +++ b/pyaml/lattice/simulator.py @@ -10,7 +10,8 @@ import at -from ..bpm.bpm import BPM +from pyaml.diagnostics.bpm import BPM + from ..common.abstract_aggregator import ScalarAggregator from ..common.element import Element, __pyaml_repr__ from ..common.exception import PyAMLException diff --git a/pyaml/tuning_tools/bba.py b/pyaml/tuning_tools/bba.py index 05eb9b8e..feb8bccd 100644 --- a/pyaml/tuning_tools/bba.py +++ b/pyaml/tuning_tools/bba.py @@ -23,8 +23,9 @@ from .measurement_tool import MeasurementTool if TYPE_CHECKING: + from pyaml.diagnostics.bpm import BPM + from ..arrays.bpm_array import BPMArray - from ..bpm.bpm import BPM from ..magnet.magnet import Magnet logger = logging.getLogger(__name__) diff --git a/pyaml/tuning_tools/bba2.py b/pyaml/tuning_tools/bba2.py index 1e34d80d..adaa9224 100644 --- a/pyaml/tuning_tools/bba2.py +++ b/pyaml/tuning_tools/bba2.py @@ -18,8 +18,9 @@ from .measurement_tool import MeasurementTool if TYPE_CHECKING: + from pyaml.diagnostics.bpm import BPM + from ..arrays.bpm_array import BPMArray - from ..bpm.bpm import BPM from ..magnet.magnet import Magnet from .tune import Tune diff --git a/tests/common/test_element_holder_collection.py b/tests/common/test_element_holder_collection.py index a90a1523..01585cf9 100644 --- a/tests/common/test_element_holder_collection.py +++ b/tests/common/test_element_holder_collection.py @@ -3,8 +3,8 @@ from pyaml.arrays.bpm_array import BPMArray from pyaml.arrays.element_array import ElementArray from pyaml.arrays.magnet_array import MagnetArray -from pyaml.bpm.bpm import BPM from pyaml.common.exception import PyAMLException +from pyaml.diagnostics.bpm.bpm import BPM from pyaml.lattice.simulator import Simulator diff --git a/tests/common/test_errors.py b/tests/common/test_errors.py index 4265a20c..8e970f58 100644 --- a/tests/common/test_errors.py +++ b/tests/common/test_errors.py @@ -50,12 +50,12 @@ def test_tune(install_test_package): def test_duplicate_error_reports_source_line_and_column_across_files(tmp_path): devices_a = tmp_path / "devices_a.yaml" devices_a.write_text( - "- type: pyaml.bpm.bpm\n name: BPM_DUPLICATE\n", + "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_DUPLICATE\n", encoding="utf-8", ) devices_b = tmp_path / "devices_b.yaml" devices_b.write_text( - "- type: pyaml.bpm.bpm\n name: BPM_UNIQUE\n- type: pyaml.bpm.bpm\n name: BPM_DUPLICATE\n", + "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_UNIQUE\n- type: pyaml.diagnostics.bpm.bpm\n name: BPM_DUPLICATE\n", encoding="utf-8", ) root = tmp_path / "root.yaml" @@ -76,7 +76,7 @@ def test_duplicate_error_reports_source_line_and_column_across_files(tmp_path): def test_malformed_local_included_yaml_reports_source_line_and_column(tmp_path): broken_devices = tmp_path / "broken_devices.yaml" broken_devices.write_text( - "- type: pyaml.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n", + "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n", encoding="utf-8", ) root = tmp_path / "root.yaml" @@ -101,7 +101,7 @@ def test_malformed_local_included_yaml_reports_source_line_and_column(tmp_path): def test_truncated_local_included_json_reports_source_and_position(tmp_path): broken_devices = tmp_path / "broken_devices.json" broken_devices.write_text( - '{"type": "pyaml.bpm.bpm", "name": "BPM_BROKEN", "model": ', + '{"type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_BROKEN", "model": ', encoding="utf-8", ) root = tmp_path / "root.yaml" @@ -133,7 +133,9 @@ def test_malformed_remote_included_yaml_reports_source_line_and_column(http_conf "data_folder: /data/store\n" "devices: fragments/broken_devices.yaml\n" ), - "/configs/fragments/broken_devices.yaml": ("- type: pyaml.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n"), + "/configs/fragments/broken_devices.yaml": ( + "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n" + ), } with http_config_server(routes) as base_url: @@ -156,7 +158,7 @@ def test_truncated_remote_included_json_reports_source_and_position(http_config_ "devices: fragments/broken_devices.json\n" ), "/configs/fragments/broken_devices.json": ( - '{"type": "pyaml.bpm.bpm", "name": "BPM_BROKEN", "model": ', + '{"type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_BROKEN", "model": ', "application/json", 200, ), diff --git a/tests/config/EBSOrbit.yaml b/tests/config/EBSOrbit.yaml index 5d6ea257..55ffe743 100644 --- a/tests/config/EBSOrbit.yaml +++ b/tests/config/EBSOrbit.yaml @@ -5713,1285 +5713,1285 @@ devices: - srmag/ps-corr-sh3/c03-e-ch3/current - srmag/ps-corr-sh3/c03-e-ch5/current - srmag/ps-corr-sh3/c03-e-ch6/current -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-01 x_pos: srdiag/bpm/c04-01/SA_HPosition y_pos: srdiag/bpm/c04-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-02 x_pos: srdiag/bpm/c04-02/SA_HPosition y_pos: srdiag/bpm/c04-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-03 x_pos: srdiag/bpm/c04-03/SA_HPosition y_pos: srdiag/bpm/c04-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-04 x_pos: srdiag/bpm/c04-04/SA_HPosition y_pos: srdiag/bpm/c04-04/SA_VPosition x_offset: srdiag/bpm/c04-04/HOffset y_offset: srdiag/bpm/c04-04/VOffset -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-05 x_pos: srdiag/bpm/c04-05/SA_HPosition y_pos: srdiag/bpm/c04-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-06 x_pos: srdiag/bpm/c04-06/SA_HPosition y_pos: srdiag/bpm/c04-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-07 x_pos: srdiag/bpm/c04-07/SA_HPosition y_pos: srdiag/bpm/c04-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-08 x_pos: srdiag/bpm/c04-08/SA_HPosition y_pos: srdiag/bpm/c04-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-09 x_pos: srdiag/bpm/c04-09/SA_HPosition y_pos: srdiag/bpm/c04-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-10 x_pos: srdiag/bpm/c04-10/SA_HPosition y_pos: srdiag/bpm/c04-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-01 x_pos: srdiag/bpm/c05-01/SA_HPosition y_pos: srdiag/bpm/c05-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-02 x_pos: srdiag/bpm/c05-02/SA_HPosition y_pos: srdiag/bpm/c05-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-03 x_pos: srdiag/bpm/c05-03/SA_HPosition y_pos: srdiag/bpm/c05-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-04 x_pos: srdiag/bpm/c05-04/SA_HPosition y_pos: srdiag/bpm/c05-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-05 x_pos: srdiag/bpm/c05-05/SA_HPosition y_pos: srdiag/bpm/c05-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-06 x_pos: srdiag/bpm/c05-06/SA_HPosition y_pos: srdiag/bpm/c05-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-07 x_pos: srdiag/bpm/c05-07/SA_HPosition y_pos: srdiag/bpm/c05-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-08 x_pos: srdiag/bpm/c05-08/SA_HPosition y_pos: srdiag/bpm/c05-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-09 x_pos: srdiag/bpm/c05-09/SA_HPosition y_pos: srdiag/bpm/c05-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C05-10 x_pos: srdiag/bpm/c05-10/SA_HPosition y_pos: srdiag/bpm/c05-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-01 x_pos: srdiag/bpm/c06-01/SA_HPosition y_pos: srdiag/bpm/c06-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-02 x_pos: srdiag/bpm/c06-02/SA_HPosition y_pos: srdiag/bpm/c06-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-03 x_pos: srdiag/bpm/c06-03/SA_HPosition y_pos: srdiag/bpm/c06-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-04 x_pos: srdiag/bpm/c06-04/SA_HPosition y_pos: srdiag/bpm/c06-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-05 x_pos: srdiag/bpm/c06-05/SA_HPosition y_pos: srdiag/bpm/c06-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-06 x_pos: srdiag/bpm/c06-06/SA_HPosition y_pos: srdiag/bpm/c06-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-07 x_pos: srdiag/bpm/c06-07/SA_HPosition y_pos: srdiag/bpm/c06-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-08 x_pos: srdiag/bpm/c06-08/SA_HPosition y_pos: srdiag/bpm/c06-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-09 x_pos: srdiag/bpm/c06-09/SA_HPosition y_pos: srdiag/bpm/c06-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C06-10 x_pos: srdiag/bpm/c06-10/SA_HPosition y_pos: srdiag/bpm/c06-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-01 x_pos: srdiag/bpm/c07-01/SA_HPosition y_pos: srdiag/bpm/c07-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-02 x_pos: srdiag/bpm/c07-02/SA_HPosition y_pos: srdiag/bpm/c07-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-03 x_pos: srdiag/bpm/c07-03/SA_HPosition y_pos: srdiag/bpm/c07-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-04 x_pos: srdiag/bpm/c07-04/SA_HPosition y_pos: srdiag/bpm/c07-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-05 x_pos: srdiag/bpm/c07-05/SA_HPosition y_pos: srdiag/bpm/c07-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-06 x_pos: srdiag/bpm/c07-06/SA_HPosition y_pos: srdiag/bpm/c07-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-07 x_pos: srdiag/bpm/c07-07/SA_HPosition y_pos: srdiag/bpm/c07-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-08 x_pos: srdiag/bpm/c07-08/SA_HPosition y_pos: srdiag/bpm/c07-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-09 x_pos: srdiag/bpm/c07-09/SA_HPosition y_pos: srdiag/bpm/c07-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C07-10 x_pos: srdiag/bpm/c07-10/SA_HPosition y_pos: srdiag/bpm/c07-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-01 x_pos: srdiag/bpm/c08-01/SA_HPosition y_pos: srdiag/bpm/c08-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-02 x_pos: srdiag/bpm/c08-02/SA_HPosition y_pos: srdiag/bpm/c08-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-03 x_pos: srdiag/bpm/c08-03/SA_HPosition y_pos: srdiag/bpm/c08-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-04 x_pos: srdiag/bpm/c08-04/SA_HPosition y_pos: srdiag/bpm/c08-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-05 x_pos: srdiag/bpm/c08-05/SA_HPosition y_pos: srdiag/bpm/c08-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-06 x_pos: srdiag/bpm/c08-06/SA_HPosition y_pos: srdiag/bpm/c08-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-07 x_pos: srdiag/bpm/c08-07/SA_HPosition y_pos: srdiag/bpm/c08-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-08 x_pos: srdiag/bpm/c08-08/SA_HPosition y_pos: srdiag/bpm/c08-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-09 x_pos: srdiag/bpm/c08-09/SA_HPosition y_pos: srdiag/bpm/c08-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C08-10 x_pos: srdiag/bpm/c08-10/SA_HPosition y_pos: srdiag/bpm/c08-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-01 x_pos: srdiag/bpm/c09-01/SA_HPosition y_pos: srdiag/bpm/c09-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-02 x_pos: srdiag/bpm/c09-02/SA_HPosition y_pos: srdiag/bpm/c09-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-03 x_pos: srdiag/bpm/c09-03/SA_HPosition y_pos: srdiag/bpm/c09-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-04 x_pos: srdiag/bpm/c09-04/SA_HPosition y_pos: srdiag/bpm/c09-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-05 x_pos: srdiag/bpm/c09-05/SA_HPosition y_pos: srdiag/bpm/c09-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-06 x_pos: srdiag/bpm/c09-06/SA_HPosition y_pos: srdiag/bpm/c09-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-07 x_pos: srdiag/bpm/c09-07/SA_HPosition y_pos: srdiag/bpm/c09-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-08 x_pos: srdiag/bpm/c09-08/SA_HPosition y_pos: srdiag/bpm/c09-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-09 x_pos: srdiag/bpm/c09-09/SA_HPosition y_pos: srdiag/bpm/c09-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C09-10 x_pos: srdiag/bpm/c09-10/SA_HPosition y_pos: srdiag/bpm/c09-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-01 x_pos: srdiag/bpm/c10-01/SA_HPosition y_pos: srdiag/bpm/c10-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-02 x_pos: srdiag/bpm/c10-02/SA_HPosition y_pos: srdiag/bpm/c10-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-03 x_pos: srdiag/bpm/c10-03/SA_HPosition y_pos: srdiag/bpm/c10-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-04 x_pos: srdiag/bpm/c10-04/SA_HPosition y_pos: srdiag/bpm/c10-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-05 x_pos: srdiag/bpm/c10-05/SA_HPosition y_pos: srdiag/bpm/c10-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-06 x_pos: srdiag/bpm/c10-06/SA_HPosition y_pos: srdiag/bpm/c10-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-07 x_pos: srdiag/bpm/c10-07/SA_HPosition y_pos: srdiag/bpm/c10-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-08 x_pos: srdiag/bpm/c10-08/SA_HPosition y_pos: srdiag/bpm/c10-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-09 x_pos: srdiag/bpm/c10-09/SA_HPosition y_pos: srdiag/bpm/c10-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C10-10 x_pos: srdiag/bpm/c10-10/SA_HPosition y_pos: srdiag/bpm/c10-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-01 x_pos: srdiag/bpm/c11-01/SA_HPosition y_pos: srdiag/bpm/c11-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-02 x_pos: srdiag/bpm/c11-02/SA_HPosition y_pos: srdiag/bpm/c11-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-03 x_pos: srdiag/bpm/c11-03/SA_HPosition y_pos: srdiag/bpm/c11-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-04 x_pos: srdiag/bpm/c11-04/SA_HPosition y_pos: srdiag/bpm/c11-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-05 x_pos: srdiag/bpm/c11-05/SA_HPosition y_pos: srdiag/bpm/c11-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-06 x_pos: srdiag/bpm/c11-06/SA_HPosition y_pos: srdiag/bpm/c11-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-07 x_pos: srdiag/bpm/c11-07/SA_HPosition y_pos: srdiag/bpm/c11-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-08 x_pos: srdiag/bpm/c11-08/SA_HPosition y_pos: srdiag/bpm/c11-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-09 x_pos: srdiag/bpm/c11-09/SA_HPosition y_pos: srdiag/bpm/c11-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C11-10 x_pos: srdiag/bpm/c11-10/SA_HPosition y_pos: srdiag/bpm/c11-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-01 x_pos: srdiag/bpm/c12-01/SA_HPosition y_pos: srdiag/bpm/c12-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-02 x_pos: srdiag/bpm/c12-02/SA_HPosition y_pos: srdiag/bpm/c12-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-03 x_pos: srdiag/bpm/c12-03/SA_HPosition y_pos: srdiag/bpm/c12-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-04 x_pos: srdiag/bpm/c12-04/SA_HPosition y_pos: srdiag/bpm/c12-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-05 x_pos: srdiag/bpm/c12-05/SA_HPosition y_pos: srdiag/bpm/c12-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-06 x_pos: srdiag/bpm/c12-06/SA_HPosition y_pos: srdiag/bpm/c12-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-07 x_pos: srdiag/bpm/c12-07/SA_HPosition y_pos: srdiag/bpm/c12-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-08 x_pos: srdiag/bpm/c12-08/SA_HPosition y_pos: srdiag/bpm/c12-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-09 x_pos: srdiag/bpm/c12-09/SA_HPosition y_pos: srdiag/bpm/c12-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C12-10 x_pos: srdiag/bpm/c12-10/SA_HPosition y_pos: srdiag/bpm/c12-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-01 x_pos: srdiag/bpm/c13-01/SA_HPosition y_pos: srdiag/bpm/c13-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-02 x_pos: srdiag/bpm/c13-02/SA_HPosition y_pos: srdiag/bpm/c13-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-03 x_pos: srdiag/bpm/c13-03/SA_HPosition y_pos: srdiag/bpm/c13-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-04 x_pos: srdiag/bpm/c13-04/SA_HPosition y_pos: srdiag/bpm/c13-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-05 x_pos: srdiag/bpm/c13-05/SA_HPosition y_pos: srdiag/bpm/c13-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-06 x_pos: srdiag/bpm/c13-06/SA_HPosition y_pos: srdiag/bpm/c13-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-07 x_pos: srdiag/bpm/c13-07/SA_HPosition y_pos: srdiag/bpm/c13-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-08 x_pos: srdiag/bpm/c13-08/SA_HPosition y_pos: srdiag/bpm/c13-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-09 x_pos: srdiag/bpm/c13-09/SA_HPosition y_pos: srdiag/bpm/c13-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C13-10 x_pos: srdiag/bpm/c13-10/SA_HPosition y_pos: srdiag/bpm/c13-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-01 x_pos: srdiag/bpm/c14-01/SA_HPosition y_pos: srdiag/bpm/c14-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-02 x_pos: srdiag/bpm/c14-02/SA_HPosition y_pos: srdiag/bpm/c14-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-03 x_pos: srdiag/bpm/c14-03/SA_HPosition y_pos: srdiag/bpm/c14-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-04 x_pos: srdiag/bpm/c14-04/SA_HPosition y_pos: srdiag/bpm/c14-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-05 x_pos: srdiag/bpm/c14-05/SA_HPosition y_pos: srdiag/bpm/c14-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-06 x_pos: srdiag/bpm/c14-06/SA_HPosition y_pos: srdiag/bpm/c14-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-07 x_pos: srdiag/bpm/c14-07/SA_HPosition y_pos: srdiag/bpm/c14-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-08 x_pos: srdiag/bpm/c14-08/SA_HPosition y_pos: srdiag/bpm/c14-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-09 x_pos: srdiag/bpm/c14-09/SA_HPosition y_pos: srdiag/bpm/c14-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C14-10 x_pos: srdiag/bpm/c14-10/SA_HPosition y_pos: srdiag/bpm/c14-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-01 x_pos: srdiag/bpm/c15-01/SA_HPosition y_pos: srdiag/bpm/c15-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-02 x_pos: srdiag/bpm/c15-02/SA_HPosition y_pos: srdiag/bpm/c15-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-03 x_pos: srdiag/bpm/c15-03/SA_HPosition y_pos: srdiag/bpm/c15-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-04 x_pos: srdiag/bpm/c15-04/SA_HPosition y_pos: srdiag/bpm/c15-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-05 x_pos: srdiag/bpm/c15-05/SA_HPosition y_pos: srdiag/bpm/c15-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-06 x_pos: srdiag/bpm/c15-06/SA_HPosition y_pos: srdiag/bpm/c15-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-07 x_pos: srdiag/bpm/c15-07/SA_HPosition y_pos: srdiag/bpm/c15-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-08 x_pos: srdiag/bpm/c15-08/SA_HPosition y_pos: srdiag/bpm/c15-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-09 x_pos: srdiag/bpm/c15-09/SA_HPosition y_pos: srdiag/bpm/c15-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C15-10 x_pos: srdiag/bpm/c15-10/SA_HPosition y_pos: srdiag/bpm/c15-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-01 x_pos: srdiag/bpm/c16-01/SA_HPosition y_pos: srdiag/bpm/c16-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-02 x_pos: srdiag/bpm/c16-02/SA_HPosition y_pos: srdiag/bpm/c16-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-03 x_pos: srdiag/bpm/c16-03/SA_HPosition y_pos: srdiag/bpm/c16-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-04 x_pos: srdiag/bpm/c16-04/SA_HPosition y_pos: srdiag/bpm/c16-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-05 x_pos: srdiag/bpm/c16-05/SA_HPosition y_pos: srdiag/bpm/c16-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-06 x_pos: srdiag/bpm/c16-06/SA_HPosition y_pos: srdiag/bpm/c16-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-07 x_pos: srdiag/bpm/c16-07/SA_HPosition y_pos: srdiag/bpm/c16-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-08 x_pos: srdiag/bpm/c16-08/SA_HPosition y_pos: srdiag/bpm/c16-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-09 x_pos: srdiag/bpm/c16-09/SA_HPosition y_pos: srdiag/bpm/c16-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C16-10 x_pos: srdiag/bpm/c16-10/SA_HPosition y_pos: srdiag/bpm/c16-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-01 x_pos: srdiag/bpm/c17-01/SA_HPosition y_pos: srdiag/bpm/c17-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-02 x_pos: srdiag/bpm/c17-02/SA_HPosition y_pos: srdiag/bpm/c17-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-03 x_pos: srdiag/bpm/c17-03/SA_HPosition y_pos: srdiag/bpm/c17-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-04 x_pos: srdiag/bpm/c17-04/SA_HPosition y_pos: srdiag/bpm/c17-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-05 x_pos: srdiag/bpm/c17-05/SA_HPosition y_pos: srdiag/bpm/c17-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-06 x_pos: srdiag/bpm/c17-06/SA_HPosition y_pos: srdiag/bpm/c17-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-07 x_pos: srdiag/bpm/c17-07/SA_HPosition y_pos: srdiag/bpm/c17-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-08 x_pos: srdiag/bpm/c17-08/SA_HPosition y_pos: srdiag/bpm/c17-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-09 x_pos: srdiag/bpm/c17-09/SA_HPosition y_pos: srdiag/bpm/c17-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C17-10 x_pos: srdiag/bpm/c17-10/SA_HPosition y_pos: srdiag/bpm/c17-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-01 x_pos: srdiag/bpm/c18-01/SA_HPosition y_pos: srdiag/bpm/c18-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-02 x_pos: srdiag/bpm/c18-02/SA_HPosition y_pos: srdiag/bpm/c18-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-03 x_pos: srdiag/bpm/c18-03/SA_HPosition y_pos: srdiag/bpm/c18-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-04 x_pos: srdiag/bpm/c18-04/SA_HPosition y_pos: srdiag/bpm/c18-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-05 x_pos: srdiag/bpm/c18-05/SA_HPosition y_pos: srdiag/bpm/c18-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-06 x_pos: srdiag/bpm/c18-06/SA_HPosition y_pos: srdiag/bpm/c18-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-07 x_pos: srdiag/bpm/c18-07/SA_HPosition y_pos: srdiag/bpm/c18-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-08 x_pos: srdiag/bpm/c18-08/SA_HPosition y_pos: srdiag/bpm/c18-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-09 x_pos: srdiag/bpm/c18-09/SA_HPosition y_pos: srdiag/bpm/c18-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C18-10 x_pos: srdiag/bpm/c18-10/SA_HPosition y_pos: srdiag/bpm/c18-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-01 x_pos: srdiag/bpm/c19-01/SA_HPosition y_pos: srdiag/bpm/c19-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-02 x_pos: srdiag/bpm/c19-02/SA_HPosition y_pos: srdiag/bpm/c19-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-03 x_pos: srdiag/bpm/c19-03/SA_HPosition y_pos: srdiag/bpm/c19-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-04 x_pos: srdiag/bpm/c19-04/SA_HPosition y_pos: srdiag/bpm/c19-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-05 x_pos: srdiag/bpm/c19-05/SA_HPosition y_pos: srdiag/bpm/c19-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-06 x_pos: srdiag/bpm/c19-06/SA_HPosition y_pos: srdiag/bpm/c19-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-07 x_pos: srdiag/bpm/c19-07/SA_HPosition y_pos: srdiag/bpm/c19-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-08 x_pos: srdiag/bpm/c19-08/SA_HPosition y_pos: srdiag/bpm/c19-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-09 x_pos: srdiag/bpm/c19-09/SA_HPosition y_pos: srdiag/bpm/c19-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C19-10 x_pos: srdiag/bpm/c19-10/SA_HPosition y_pos: srdiag/bpm/c19-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-01 x_pos: srdiag/bpm/c20-01/SA_HPosition y_pos: srdiag/bpm/c20-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-02 x_pos: srdiag/bpm/c20-02/SA_HPosition y_pos: srdiag/bpm/c20-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-03 x_pos: srdiag/bpm/c20-03/SA_HPosition y_pos: srdiag/bpm/c20-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-04 x_pos: srdiag/bpm/c20-04/SA_HPosition y_pos: srdiag/bpm/c20-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-05 x_pos: srdiag/bpm/c20-05/SA_HPosition y_pos: srdiag/bpm/c20-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-06 x_pos: srdiag/bpm/c20-06/SA_HPosition y_pos: srdiag/bpm/c20-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-07 x_pos: srdiag/bpm/c20-07/SA_HPosition y_pos: srdiag/bpm/c20-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-08 x_pos: srdiag/bpm/c20-08/SA_HPosition y_pos: srdiag/bpm/c20-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-09 x_pos: srdiag/bpm/c20-09/SA_HPosition y_pos: srdiag/bpm/c20-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C20-10 x_pos: srdiag/bpm/c20-10/SA_HPosition y_pos: srdiag/bpm/c20-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-01 x_pos: srdiag/bpm/c21-01/SA_HPosition y_pos: srdiag/bpm/c21-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-02 x_pos: srdiag/bpm/c21-02/SA_HPosition y_pos: srdiag/bpm/c21-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-03 x_pos: srdiag/bpm/c21-03/SA_HPosition y_pos: srdiag/bpm/c21-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-04 x_pos: srdiag/bpm/c21-04/SA_HPosition y_pos: srdiag/bpm/c21-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-05 x_pos: srdiag/bpm/c21-05/SA_HPosition y_pos: srdiag/bpm/c21-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-06 x_pos: srdiag/bpm/c21-06/SA_HPosition y_pos: srdiag/bpm/c21-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-07 x_pos: srdiag/bpm/c21-07/SA_HPosition y_pos: srdiag/bpm/c21-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-08 x_pos: srdiag/bpm/c21-08/SA_HPosition y_pos: srdiag/bpm/c21-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-09 x_pos: srdiag/bpm/c21-09/SA_HPosition y_pos: srdiag/bpm/c21-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C21-10 x_pos: srdiag/bpm/c21-10/SA_HPosition y_pos: srdiag/bpm/c21-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-01 x_pos: srdiag/bpm/c22-01/SA_HPosition y_pos: srdiag/bpm/c22-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-02 x_pos: srdiag/bpm/c22-02/SA_HPosition y_pos: srdiag/bpm/c22-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-03 x_pos: srdiag/bpm/c22-03/SA_HPosition y_pos: srdiag/bpm/c22-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-04 x_pos: srdiag/bpm/c22-04/SA_HPosition y_pos: srdiag/bpm/c22-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-05 x_pos: srdiag/bpm/c22-05/SA_HPosition y_pos: srdiag/bpm/c22-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-06 x_pos: srdiag/bpm/c22-06/SA_HPosition y_pos: srdiag/bpm/c22-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-07 x_pos: srdiag/bpm/c22-07/SA_HPosition y_pos: srdiag/bpm/c22-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-08 x_pos: srdiag/bpm/c22-08/SA_HPosition y_pos: srdiag/bpm/c22-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-09 x_pos: srdiag/bpm/c22-09/SA_HPosition y_pos: srdiag/bpm/c22-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C22-10 x_pos: srdiag/bpm/c22-10/SA_HPosition y_pos: srdiag/bpm/c22-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-01 x_pos: srdiag/bpm/c23-01/SA_HPosition y_pos: srdiag/bpm/c23-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-02 x_pos: srdiag/bpm/c23-02/SA_HPosition y_pos: srdiag/bpm/c23-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-03 x_pos: srdiag/bpm/c23-03/SA_HPosition y_pos: srdiag/bpm/c23-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-04 x_pos: srdiag/bpm/c23-04/SA_HPosition y_pos: srdiag/bpm/c23-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-05 x_pos: srdiag/bpm/c23-05/SA_HPosition y_pos: srdiag/bpm/c23-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-06 x_pos: srdiag/bpm/c23-06/SA_HPosition y_pos: srdiag/bpm/c23-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-07 x_pos: srdiag/bpm/c23-07/SA_HPosition y_pos: srdiag/bpm/c23-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-08 x_pos: srdiag/bpm/c23-08/SA_HPosition y_pos: srdiag/bpm/c23-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-09 x_pos: srdiag/bpm/c23-09/SA_HPosition y_pos: srdiag/bpm/c23-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C23-10 x_pos: srdiag/bpm/c23-10/SA_HPosition y_pos: srdiag/bpm/c23-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-01 x_pos: srdiag/bpm/c24-01/SA_HPosition y_pos: srdiag/bpm/c24-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-02 x_pos: srdiag/bpm/c24-02/SA_HPosition y_pos: srdiag/bpm/c24-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-03 x_pos: srdiag/bpm/c24-03/SA_HPosition y_pos: srdiag/bpm/c24-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-04 x_pos: srdiag/bpm/c24-04/SA_HPosition y_pos: srdiag/bpm/c24-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-05 x_pos: srdiag/bpm/c24-05/SA_HPosition y_pos: srdiag/bpm/c24-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-06 x_pos: srdiag/bpm/c24-06/SA_HPosition y_pos: srdiag/bpm/c24-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-07 x_pos: srdiag/bpm/c24-07/SA_HPosition y_pos: srdiag/bpm/c24-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-08 x_pos: srdiag/bpm/c24-08/SA_HPosition y_pos: srdiag/bpm/c24-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-09 x_pos: srdiag/bpm/c24-09/SA_HPosition y_pos: srdiag/bpm/c24-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C24-10 x_pos: srdiag/bpm/c24-10/SA_HPosition y_pos: srdiag/bpm/c24-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-01 x_pos: srdiag/bpm/c25-01/SA_HPosition y_pos: srdiag/bpm/c25-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-02 x_pos: srdiag/bpm/c25-02/SA_HPosition y_pos: srdiag/bpm/c25-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-03 x_pos: srdiag/bpm/c25-03/SA_HPosition y_pos: srdiag/bpm/c25-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-04 x_pos: srdiag/bpm/c25-04/SA_HPosition y_pos: srdiag/bpm/c25-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-05 x_pos: srdiag/bpm/c25-05/SA_HPosition y_pos: srdiag/bpm/c25-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-06 x_pos: srdiag/bpm/c25-06/SA_HPosition y_pos: srdiag/bpm/c25-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-07 x_pos: srdiag/bpm/c25-07/SA_HPosition y_pos: srdiag/bpm/c25-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-08 x_pos: srdiag/bpm/c25-08/SA_HPosition y_pos: srdiag/bpm/c25-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-09 x_pos: srdiag/bpm/c25-09/SA_HPosition y_pos: srdiag/bpm/c25-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C25-10 x_pos: srdiag/bpm/c25-10/SA_HPosition y_pos: srdiag/bpm/c25-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-01 x_pos: srdiag/bpm/c26-01/SA_HPosition y_pos: srdiag/bpm/c26-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-02 x_pos: srdiag/bpm/c26-02/SA_HPosition y_pos: srdiag/bpm/c26-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-03 x_pos: srdiag/bpm/c26-03/SA_HPosition y_pos: srdiag/bpm/c26-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-04 x_pos: srdiag/bpm/c26-04/SA_HPosition y_pos: srdiag/bpm/c26-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-05 x_pos: srdiag/bpm/c26-05/SA_HPosition y_pos: srdiag/bpm/c26-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-06 x_pos: srdiag/bpm/c26-06/SA_HPosition y_pos: srdiag/bpm/c26-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-07 x_pos: srdiag/bpm/c26-07/SA_HPosition y_pos: srdiag/bpm/c26-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-08 x_pos: srdiag/bpm/c26-08/SA_HPosition y_pos: srdiag/bpm/c26-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-09 x_pos: srdiag/bpm/c26-09/SA_HPosition y_pos: srdiag/bpm/c26-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C26-10 x_pos: srdiag/bpm/c26-10/SA_HPosition y_pos: srdiag/bpm/c26-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-01 x_pos: srdiag/bpm/c27-01/SA_HPosition y_pos: srdiag/bpm/c27-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-02 x_pos: srdiag/bpm/c27-02/SA_HPosition y_pos: srdiag/bpm/c27-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-03 x_pos: srdiag/bpm/c27-03/SA_HPosition y_pos: srdiag/bpm/c27-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-04 x_pos: srdiag/bpm/c27-04/SA_HPosition y_pos: srdiag/bpm/c27-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-05 x_pos: srdiag/bpm/c27-05/SA_HPosition y_pos: srdiag/bpm/c27-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-06 x_pos: srdiag/bpm/c27-06/SA_HPosition y_pos: srdiag/bpm/c27-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-07 x_pos: srdiag/bpm/c27-07/SA_HPosition y_pos: srdiag/bpm/c27-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-08 x_pos: srdiag/bpm/c27-08/SA_HPosition y_pos: srdiag/bpm/c27-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-09 x_pos: srdiag/bpm/c27-09/SA_HPosition y_pos: srdiag/bpm/c27-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C27-10 x_pos: srdiag/bpm/c27-10/SA_HPosition y_pos: srdiag/bpm/c27-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-01 x_pos: srdiag/bpm/c28-01/SA_HPosition y_pos: srdiag/bpm/c28-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-02 x_pos: srdiag/bpm/c28-02/SA_HPosition y_pos: srdiag/bpm/c28-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-03 x_pos: srdiag/bpm/c28-03/SA_HPosition y_pos: srdiag/bpm/c28-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-04 x_pos: srdiag/bpm/c28-04/SA_HPosition y_pos: srdiag/bpm/c28-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-05 x_pos: srdiag/bpm/c28-05/SA_HPosition y_pos: srdiag/bpm/c28-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-06 x_pos: srdiag/bpm/c28-06/SA_HPosition y_pos: srdiag/bpm/c28-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-07 x_pos: srdiag/bpm/c28-07/SA_HPosition y_pos: srdiag/bpm/c28-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-08 x_pos: srdiag/bpm/c28-08/SA_HPosition y_pos: srdiag/bpm/c28-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-09 x_pos: srdiag/bpm/c28-09/SA_HPosition y_pos: srdiag/bpm/c28-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C28-10 x_pos: srdiag/bpm/c28-10/SA_HPosition y_pos: srdiag/bpm/c28-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-01 x_pos: srdiag/bpm/c29-01/SA_HPosition y_pos: srdiag/bpm/c29-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-02 x_pos: srdiag/bpm/c29-02/SA_HPosition y_pos: srdiag/bpm/c29-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-03 x_pos: srdiag/bpm/c29-03/SA_HPosition y_pos: srdiag/bpm/c29-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-04 x_pos: srdiag/bpm/c29-04/SA_HPosition y_pos: srdiag/bpm/c29-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-05 x_pos: srdiag/bpm/c29-05/SA_HPosition y_pos: srdiag/bpm/c29-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-06 x_pos: srdiag/bpm/c29-06/SA_HPosition y_pos: srdiag/bpm/c29-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-07 x_pos: srdiag/bpm/c29-07/SA_HPosition y_pos: srdiag/bpm/c29-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-08 x_pos: srdiag/bpm/c29-08/SA_HPosition y_pos: srdiag/bpm/c29-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-09 x_pos: srdiag/bpm/c29-09/SA_HPosition y_pos: srdiag/bpm/c29-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C29-10 x_pos: srdiag/bpm/c29-10/SA_HPosition y_pos: srdiag/bpm/c29-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-01 x_pos: srdiag/bpm/c30-01/SA_HPosition y_pos: srdiag/bpm/c30-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-02 x_pos: srdiag/bpm/c30-02/SA_HPosition y_pos: srdiag/bpm/c30-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-03 x_pos: srdiag/bpm/c30-03/SA_HPosition y_pos: srdiag/bpm/c30-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-04 x_pos: srdiag/bpm/c30-04/SA_HPosition y_pos: srdiag/bpm/c30-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-05 x_pos: srdiag/bpm/c30-05/SA_HPosition y_pos: srdiag/bpm/c30-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-06 x_pos: srdiag/bpm/c30-06/SA_HPosition y_pos: srdiag/bpm/c30-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-07 x_pos: srdiag/bpm/c30-07/SA_HPosition y_pos: srdiag/bpm/c30-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-08 x_pos: srdiag/bpm/c30-08/SA_HPosition y_pos: srdiag/bpm/c30-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-09 x_pos: srdiag/bpm/c30-09/SA_HPosition y_pos: srdiag/bpm/c30-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C30-10 x_pos: srdiag/bpm/c30-10/SA_HPosition y_pos: srdiag/bpm/c30-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-01 x_pos: srdiag/bpm/c31-01/SA_HPosition y_pos: srdiag/bpm/c31-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-02 x_pos: srdiag/bpm/c31-02/SA_HPosition y_pos: srdiag/bpm/c31-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-03 x_pos: srdiag/bpm/c31-03/SA_HPosition y_pos: srdiag/bpm/c31-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-04 x_pos: srdiag/bpm/c31-04/SA_HPosition y_pos: srdiag/bpm/c31-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-05 x_pos: srdiag/bpm/c31-05/SA_HPosition y_pos: srdiag/bpm/c31-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-06 x_pos: srdiag/bpm/c31-06/SA_HPosition y_pos: srdiag/bpm/c31-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-07 x_pos: srdiag/bpm/c31-07/SA_HPosition y_pos: srdiag/bpm/c31-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-08 x_pos: srdiag/bpm/c31-08/SA_HPosition y_pos: srdiag/bpm/c31-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-09 x_pos: srdiag/bpm/c31-09/SA_HPosition y_pos: srdiag/bpm/c31-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C31-10 x_pos: srdiag/bpm/c31-10/SA_HPosition y_pos: srdiag/bpm/c31-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-01 x_pos: srdiag/bpm/c32-01/SA_HPosition y_pos: srdiag/bpm/c32-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-02 x_pos: srdiag/bpm/c32-02/SA_HPosition y_pos: srdiag/bpm/c32-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-03 x_pos: srdiag/bpm/c32-03/SA_HPosition y_pos: srdiag/bpm/c32-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-04 x_pos: srdiag/bpm/c32-04/SA_HPosition y_pos: srdiag/bpm/c32-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-05 x_pos: srdiag/bpm/c32-05/SA_HPosition y_pos: srdiag/bpm/c32-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-06 x_pos: srdiag/bpm/c32-06/SA_HPosition y_pos: srdiag/bpm/c32-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-07 x_pos: srdiag/bpm/c32-07/SA_HPosition y_pos: srdiag/bpm/c32-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-08 x_pos: srdiag/bpm/c32-08/SA_HPosition y_pos: srdiag/bpm/c32-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-09 x_pos: srdiag/bpm/c32-09/SA_HPosition y_pos: srdiag/bpm/c32-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C32-10 x_pos: srdiag/bpm/c32-10/SA_HPosition y_pos: srdiag/bpm/c32-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-01 x_pos: srdiag/bpm/c01-01/SA_HPosition y_pos: srdiag/bpm/c01-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-02 x_pos: srdiag/bpm/c01-02/SA_HPosition y_pos: srdiag/bpm/c01-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-03 x_pos: srdiag/bpm/c01-03/SA_HPosition y_pos: srdiag/bpm/c01-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-04 x_pos: srdiag/bpm/c01-04/SA_HPosition y_pos: srdiag/bpm/c01-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-05 x_pos: srdiag/bpm/c01-05/SA_HPosition y_pos: srdiag/bpm/c01-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-06 x_pos: srdiag/bpm/c01-06/SA_HPosition y_pos: srdiag/bpm/c01-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-07 x_pos: srdiag/bpm/c01-07/SA_HPosition y_pos: srdiag/bpm/c01-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-08 x_pos: srdiag/bpm/c01-08/SA_HPosition y_pos: srdiag/bpm/c01-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-09 x_pos: srdiag/bpm/c01-09/SA_HPosition y_pos: srdiag/bpm/c01-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-10 x_pos: srdiag/bpm/c01-10/SA_HPosition y_pos: srdiag/bpm/c01-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-01 x_pos: srdiag/bpm/c02-01/SA_HPosition y_pos: srdiag/bpm/c02-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-02 x_pos: srdiag/bpm/c02-02/SA_HPosition y_pos: srdiag/bpm/c02-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-03 x_pos: srdiag/bpm/c02-03/SA_HPosition y_pos: srdiag/bpm/c02-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-04 x_pos: srdiag/bpm/c02-04/SA_HPosition y_pos: srdiag/bpm/c02-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-05 x_pos: srdiag/bpm/c02-05/SA_HPosition y_pos: srdiag/bpm/c02-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-06 x_pos: srdiag/bpm/c02-06/SA_HPosition y_pos: srdiag/bpm/c02-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-07 x_pos: srdiag/bpm/c02-07/SA_HPosition y_pos: srdiag/bpm/c02-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-08 x_pos: srdiag/bpm/c02-08/SA_HPosition y_pos: srdiag/bpm/c02-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-09 x_pos: srdiag/bpm/c02-09/SA_HPosition y_pos: srdiag/bpm/c02-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C02-10 x_pos: srdiag/bpm/c02-10/SA_HPosition y_pos: srdiag/bpm/c02-10/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-01 x_pos: srdiag/bpm/c03-01/SA_HPosition y_pos: srdiag/bpm/c03-01/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-02 x_pos: srdiag/bpm/c03-02/SA_HPosition y_pos: srdiag/bpm/c03-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-03 x_pos: srdiag/bpm/c03-03/SA_HPosition y_pos: srdiag/bpm/c03-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-04 x_pos: srdiag/bpm/c03-04/SA_HPosition y_pos: srdiag/bpm/c03-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-05 x_pos: srdiag/bpm/c03-05/SA_HPosition y_pos: srdiag/bpm/c03-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-06 x_pos: srdiag/bpm/c03-06/SA_HPosition y_pos: srdiag/bpm/c03-06/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-07 x_pos: srdiag/bpm/c03-07/SA_HPosition y_pos: srdiag/bpm/c03-07/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-08 x_pos: srdiag/bpm/c03-08/SA_HPosition y_pos: srdiag/bpm/c03-08/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-09 x_pos: srdiag/bpm/c03-09/SA_HPosition y_pos: srdiag/bpm/c03-09/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C03-10 x_pos: srdiag/bpm/c03-10/SA_HPosition y_pos: srdiag/bpm/c03-10/SA_VPosition diff --git a/tests/config/bad_conf_duplicate_2.yaml b/tests/config/bad_conf_duplicate_2.yaml index 346957aa..4430fc2e 100644 --- a/tests/config/bad_conf_duplicate_2.yaml +++ b/tests/config/bad_conf_duplicate_2.yaml @@ -21,15 +21,15 @@ arrays: - BPM_C04-06 - BPM_C04-06 # duplicate name in array devices: -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-04 x_pos: srdiag/bpm/c04-04/SA_HPosition y_pos: srdiag/bpm/c04-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-05 x_pos: srdiag/bpm/c04-05/SA_HPosition y_pos: srdiag/bpm/c04-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-06 x_pos: srdiag/bpm/c04-06/SA_HPosition y_pos: srdiag/bpm/c04-06/SA_VPosition diff --git a/tests/config/bad_conf_duplicate_3.yaml b/tests/config/bad_conf_duplicate_3.yaml index 9149009f..8b5f376a 100644 --- a/tests/config/bad_conf_duplicate_3.yaml +++ b/tests/config/bad_conf_duplicate_3.yaml @@ -22,19 +22,19 @@ arrays: - BPM_C04-05 - BPM_C04-06 devices: -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-04 x_pos: srdiag/bpm/c04-04/SA_HPosition y_pos: srdiag/bpm/c04-04/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-05 x_pos: srdiag/bpm/c04-05/SA_HPosition y_pos: srdiag/bpm/c04-05/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C04-06 x_pos: srdiag/bpm/c04-06/SA_HPosition y_pos: srdiag/bpm/c04-06/SA_VPosition -- type: pyaml.bpm.bpm # duplicate device +- type: pyaml.diagnostics.bpm.bpm # duplicate device name: BPM_C04-06 x_pos: srdiag/bpm/c04-06/SA_HPosition y_pos: srdiag/bpm/c04-06/SA_VPosition diff --git a/tests/config/bpms.yaml b/tests/config/bpms.yaml index 07caf59a..cf2275c1 100644 --- a/tests/config/bpms.yaml +++ b/tests/config/bpms.yaml @@ -13,22 +13,22 @@ controls: catalog: catalogs/sr_catalogs.yaml data_folder: /data/store devices: -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-01 x_pos: srdiag/bpm/c01-01/SA_HPosition y_pos: srdiag/bpm/c01-01/SA_VPosition x_offset: srdiag/bpm/c01-01/HOffset y_offset: srdiag/bpm/c01-01/VOffset tilt: srdiag/bpm/c01-01/Tilt_Angle -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-02 x_pos: srdiag/bpm/c01-02/SA_HPosition y_pos: srdiag/bpm/c01-02/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-03 x_pos: srdiag/bpm/c01-03/SA_HPosition y_pos: srdiag/bpm/c01-03/SA_VPosition -- type: pyaml.bpm.bpm +- type: pyaml.diagnostics.bpm.bpm name: BPM_C01-04 x_pos: srdiag/bpm/c01-04/SA_HPosition y_pos: srdiag/bpm/c01-04/SA_VPosition diff --git a/tests/config/config_manager_sr_devices.yaml b/tests/config/config_manager_sr_devices.yaml index c6d3e212..46ffaad2 100644 --- a/tests/config/config_manager_sr_devices.yaml +++ b/tests/config/config_manager_sr_devices.yaml @@ -1,11 +1,11 @@ devices: - sr/quadrupoles/QF1AC01.yaml - sr/correctors/SH1AC01-C02.yaml - - type: pyaml.bpm.bpm + - type: pyaml.diagnostics.bpm.bpm name: BPM_C04-01 x_pos: srdiag/bpm/c04-01/SA_HPosition y_pos: srdiag/bpm/c04-01/SA_VPosition - - type: pyaml.bpm.bpm + - type: pyaml.diagnostics.bpm.bpm name: BPM_C04-02 x_pos: srdiag/bpm/c04-02/SA_HPosition y_pos: srdiag/bpm/c04-02/SA_VPosition diff --git a/tests/config/sr.yaml b/tests/config/sr.yaml index 3e9561e8..4fbcffd4 100644 --- a/tests/config/sr.yaml +++ b/tests/config/sr.yaml @@ -43,11 +43,11 @@ arrays: devices: - sr/quadrupoles/QF1AC01.yaml - sr/correctors/SH1AC01-C02.yaml - - type: pyaml.bpm.bpm + - type: pyaml.diagnostics.bpm.bpm name: BPM_C04-01 x_pos: srdiag/bpm/c04-01/SA_HPosition y_pos: srdiag/bpm/c04-01/SA_VPosition - - type: pyaml.bpm.bpm + - type: pyaml.diagnostics.bpm.bpm name: BPM_C04-02 x_pos: srdiag/bpm/c04-02/SA_HPosition y_pos: srdiag/bpm/c04-02/SA_VPosition diff --git a/tests/configuration/test_configuration_manager.py b/tests/configuration/test_configuration_manager.py index f36c37dd..4e1c4249 100644 --- a/tests/configuration/test_configuration_manager.py +++ b/tests/configuration/test_configuration_manager.py @@ -189,7 +189,7 @@ def test_configuration_manager_accumulates_multiple_device_fragments( assert manager.has("devices", "BETATRON_TUNE") assert manager.get("devices", "QF1A-C01")["class_path"] == "pyaml.magnet.quadrupole.Quadrupole" assert manager.get("devices", "SH1A-C01")["class_path"] == "pyaml.magnet.cfm_magnet.CombinedFunctionMagnet" - assert manager.get("devices", "BPM_C04-01")["class_path"] == "pyaml.bpm.bpm.BPM" + assert manager.get("devices", "BPM_C04-01")["class_path"] == "pyaml.diagnostics.bpm.bpm.BPM" assert manager.get("devices", "BETATRON_TUNE")["class_path"] == "pyaml.diagnostics.tune_monitor.BetatronTuneMonitor" @@ -273,7 +273,7 @@ def test_configuration_manager_repr_is_yellow_pages_like( assert "live (tango.pyaml.controlsystem.TangoControlSystem) source=config_manager_sr_base.yaml" in output assert "design (pyaml.lattice.simulator.Simulator) source=config_manager_sr_base.yaml" in output assert "HCORR (pyaml.arrays.magnet.Magnet) patterns=1 source=config_manager_sr_arrays.yaml" in output - assert "BPM_C04-01 (pyaml.bpm.bpm.BPM) source=config_manager_sr_devices.yaml" in output + assert "BPM_C04-01 (pyaml.diagnostics.bpm.bpm.BPM) source=config_manager_sr_devices.yaml" in output assert " ." in output diff --git a/tests/bpm/test_bpm.py b/tests/diagnostics/bpm/test_bpm.py similarity index 100% rename from tests/bpm/test_bpm.py rename to tests/diagnostics/bpm/test_bpm.py diff --git a/tests/bpm/test_bpm_controlsystem.py b/tests/diagnostics/bpm/test_bpm_controlsystem.py similarity index 100% rename from tests/bpm/test_bpm_controlsystem.py rename to tests/diagnostics/bpm/test_bpm_controlsystem.py diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py index 43627e1d..bbe42f46 100644 --- a/tests/test_catalogs.py +++ b/tests/test_catalogs.py @@ -50,7 +50,7 @@ def test_inline_catalog_is_supported(install_test_package): ], "devices": [ { - "type": "pyaml.bpm.bpm", + "type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_C02-01", "x_pos": "BPM_C02-01/x", "y_pos": "BPM_C02-01/y", @@ -103,7 +103,7 @@ def test_unresolved_catalog_key_raises_runtime_error(install_test_package): ], "devices": [ { - "type": "pyaml.bpm.bpm", + "type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_C03-01", "x_pos": "BPM_C03-01/x", "y_pos": "BPM_C03-01/y", @@ -175,7 +175,7 @@ def test_indexed_catalog_entry_extracts_scalar_from_vector_attribute(install_tes ], "devices": [ { - "type": "pyaml.bpm.bpm", + "type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_TEST", "x_pos": "bpm/SA_HPosition", "y_pos": "bpm/SA_VPosition",