Control System set up#

The control system interface is in a separated package from pyaml

pyaml itself:
pip install accelerator-middle-layer

tango interface to pyaml:
pip install tango-pyaml

ophyd-asynch interface to pyaml:
pip install pyaml-oa-cs

If the above packages are installed the examples below will work

from pyaml.accelerator import Accelerator

Assuming these lines are present in …/…/tests/config/EBSTune_TANGO.yaml

type: pyaml.accelerator
name: sr
energy: 6e9
controls:
  - type: tango.pyaml.controlsystem
      tango_host: ebs-simu-3:10000
      name: live
...
powerconverter:
      type: tango.pyaml.attribute
...
tune_h:
    type: tango.pyaml.attribute_read_only
...
# work with TANGO
SR_Tango: Accelerator = Accelerator.load("../../tests/config/EBSTune.yaml")
---------------------------------------------------------------------------
PyAMLConfigException                      Traceback (most recent call last)
Cell In[2], line 2
      1 # work with TANGO
----> 2 SR_Tango: Accelerator = Accelerator.load("../../tests/config/EBSTune.yaml")

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/accelerator.py:304, in Accelerator.load(filename, use_fast_loader, ignore_external)
    299 except UnsupportedConfigurationRootError as ex:
    300     raise PyAMLConfigException(
    301         "Accelerator.load() expects a 'pyaml.accelerator' root configuration. "
    302         "Use the factory APIs to build sub-elements directly."
    303     ) from ex
--> 304 return manager.build(ignore_external=ignore_external)

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/manager.py:496, in ConfigurationManager.build(self, ignore_external)
    494     set_root_folder(self._build_root)
    495 snapshot = ConfigurationManager.strip_runtime_internal_metadata(self._snapshot(include_internal_metadata=True))
--> 496 return Accelerator.from_dict(snapshot, ignore_external=ignore_external)

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/accelerator.py:275, in Accelerator.from_dict(config_dict, ignore_external)
    273 # Ensure factory is clean before building a new accelerator
    274 Factory.clear()
--> 275 return Factory.build(config_dict, ignore_external)

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/factory.py:548, in PyAMLFactory.build(self, data, ignore_external)
    545     return self._build_list(data, ignore_external)
    547 elif isinstance(data, dict):
--> 548     data = self._build_dict(data, ignore_external)
    549     return self.build_object(data, ignore_external)

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/factory.py:395, in PyAMLFactory._build_dict(self, data, ignore_external)
    392         # Do not recurse dict defined in ConfigModel
    393         # pydantic use TypedDict not usable with isinstance
    394         if not self._is_plain_dict_type(field_type):
--> 395             result[key] = self.build(value, ignore_external)
    397 return result

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/factory.py:545, in PyAMLFactory.build(self, data, ignore_external)
    542     raise PyAMLConfigException(f"Unexpected element found. 'dict' or 'list' expected but got '{type(data).__name__}'")
    544 if isinstance(data, list):
--> 545     return self._build_list(data, ignore_external)
    547 elif isinstance(data, dict):
    548     data = self._build_dict(data, ignore_external)

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/factory.py:360, in PyAMLFactory._build_list(self, items, ignore_external)
    355 def _build_list(self, items, ignore_external: bool):
    356     """
    357     Recursively build all nested objects contained in a list.
    358     """
--> 360     return [self.build(item, ignore_external) if isinstance(item, (dict, list)) else item for item in items]

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/factory.py:548, in PyAMLFactory.build(self, data, ignore_external)
    545     return self._build_list(data, ignore_external)
    547 elif isinstance(data, dict):
--> 548     data = self._build_dict(data, ignore_external)
    549     return self.build_object(data, ignore_external)

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/factory.py:380, in PyAMLFactory._build_dict(self, data, ignore_external)
    371 def _build_dict(self, data: dict, ignore_external: bool):
    372     """
    373     Recursively build nested objects referenced by a configuration
    374     dictionary.
   (...)    377     recursive build process and are left unchanged.
    378     """
--> 380     build_info = resolve_build_info(data, ignore_external)
    381     config_cls = build_info.config_cls
    383     result = dict(data)

File ~/checkouts/readthedocs.org/user_builds/pyaml/envs/latest/lib/python3.13/site-packages/pyaml/configuration/factory.py:238, in resolve_build_info(data, ignore_external)
    236     if ignore_external:
    237         return None
--> 238     raise PyAMLConfigException(f"Module referenced in type cannot be found: '{module_str}' {location_str}") from None
    240 # Get the object class name
    241 if class_str is None:

PyAMLConfigException: Module referenced in type cannot be found: 'tango.pyaml.controlsystem' /home/docs/checkouts/readthedocs.org/user_builds/pyaml/checkouts/latest/tests/config/EBSTune.yaml at line 12, column 5.

Assuming these lines are present in …/…/tests/config/EBSTuneOATango.yaml

type: pyaml.accelerator
name: sr
energy: 6e9
controls:
  - type: pyaml-cs-oa.pyaml.controlsystem
      name: live
...
 powerconverter:
      type: pyaml_cs_oa.tangoRW
...
 tune_h:
    type: pyaml_cs_oa.tangoR

this works with Ophyd-Asynch - tango:

SR_OphydAsynch_Tango: Accelerator = Accelerator.load(”…/…/tests/config/EBSTuneOATango.yaml”)

Assuming these lines are present in …/…/tests/config/EBSTuneOAEpics.yaml

type: pyaml.accelerator
name: sr
energy: 6e9
controls:
  - type: pyaml-cs-oa.pyaml.controlsystem
      name: live
...
 powerconverter:
      type: pyaml_cs_oa.epicsRW
...
 tune_h:
    type: pyaml_cs_oa.epicsR

This work with Ophyd-Asynch - epics :

SR_OphydAsynch_Epics: Accelerator = Accelerator.load(”…/…/examples/BESSY2_example/BESSY2Tune.yaml”)