Source code for pyaml.diagnostics.tune_monitor
from ..common.abstract import ReadFloatArray
from ..common.element import Element, ElementConfigModel
from ..control.deviceaccess import DeviceAccess
from .atune_monitor import ABetatronTuneMonitor
try:
from typing import Self # Python 3.11+
except ImportError:
from typing_extensions import Self # Python 3.10 and earlier
import numpy as np
from pydantic import ConfigDict
PYAMLCLASS = "BetatronTuneMonitor"
[docs]
class ConfigModel(ElementConfigModel):
"""
Configuration model for BetatronTuneMonitor
Parameters
----------
tune_h : DeviceAccess, optional
Horizontal betatron tune device
tune_v : DeviceAccess, optional
Vertical betatron tune device
"""
model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
tune_h: DeviceAccess | None
tune_v: DeviceAccess | None
rf_plant_name: str | None = None
[docs]
class BetatronTuneMonitor(Element, ABetatronTuneMonitor):
"""
Class providing access to a betatron tune monitor
of a physical or simulated lattice.
The monitor provides horizontal and vertical betatron tune measurements.
"""
def __init__(self, cfg: ConfigModel):
"""
Construct a BetatronTuneMonitor
Parameters
----------
cfg : ConfigModel
Configuration for the BetatronTuneMonitor, including
device access for horizontal and vertical tunes.
"""
super().__init__(cfg.name)
self._cfg = cfg
self.__tune = None
self._h = None
[docs]
def set_harmonic(self, h: int):
self._h = float(h)
@property
def tune(self) -> ReadFloatArray:
"""
Get the betatron tune values.
Returns
-------
ReadFloatArray
Array of tune values [horizontal, vertical]
"""
self.check_peer()
return self.__tune
@property
def frequency(self) -> ReadFloatArray:
"""
Get the betatron tune values in frequency
Returns
-------
ReadFloatArray
Array of tune values in frequency [horizontal, vertical]
"""
class TuneFreq(ReadFloatArray):
def __init__(self, parent: BetatronTuneMonitor):
self.parent = parent
def get(self) -> np.array:
h = self.parent._h
rf_name = self.parent._cfg.rf_plant_name
if h is not None and rf_name is not None:
tune = self.parent.tune.get()
rf = self.parent.peer.get_rf_plant(rf_name)
freq = rf.frequency.get()
return tune * freq / h
def unit(self) -> str:
return "Hz"
self.check_peer()
return TuneFreq(self)
[docs]
def attach(self, peer, betatron_tune: ReadFloatArray) -> Self:
"""
Attach the tune monitor to a peer with betatron tune data.
Parameters
----------
peer : object
The peer object (simulator or control system)
betatron_tune : ReadFloatArray
The betatron tune array to monitor
Returns
-------
Self
A new attached instance of TuneMonitor
"""
obj = self.__class__(self._cfg)
obj.__tune = betatron_tune
obj._peer = peer
return obj