Source code for pyaml.tuning_tools.dispersion
import logging
from typing import Callable, Optional, Self
from pydantic import ConfigDict
from pySC.apps import measure_dispersion
from pySC.apps.codes import DispersionCode
from ..common.constants import Action
from ..common.element import ElementConfigModel
from ..common.element_holder import ElementHolder
from ..external.pySC_interface import pySCInterface
from .measurement_tool import MeasurementTool
logger = logging.getLogger(__name__)
PYAMLCLASS = "Dispersion"
[docs]
class ConfigModel(ElementConfigModel):
"""
Configuration model for dispersion measurement
Parameters
----------
bpm_array_name : str
BPM array name
rf_plant_name : str
RF plant name
frequency_delta : float
Frequency delta for measurement
"""
model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
bpm_array_name: str
rf_plant_name: str
frequency_delta: float
[docs]
class Dispersion(MeasurementTool):
def __init__(self, cfg: ConfigModel):
super().__init__(cfg.name)
self._cfg = cfg
self.bpm_array_name = cfg.bpm_array_name
self.rf_plant_name = cfg.rf_plant_name
self.frequency_delta = cfg.frequency_delta
[docs]
def measure(
self,
set_waiting_time: float = 0,
callback: Optional[Callable] = None,
):
element_holder = self._peer
interface = pySCInterface(
element_holder=element_holder,
bpm_array_name=self.bpm_array_name,
rf_plant_name=self.rf_plant_name,
)
interface.set_wait_time = set_waiting_time
generator = measure_dispersion(
interface=interface,
delta=self.frequency_delta,
skip_save=True,
)
aborted = False
idx = 0
err = None
try:
self._register_callback(callback)
self._init_measure()
for code, measurement in generator:
callback_data = {"idx": idx, "dispersion_data": measurement.dispersion_data}
if code is DispersionCode.AFTER_SET:
if not self.send_callback(Action.APPLY, callback_data):
if aborted:
break
elif code is DispersionCode.AFTER_GET:
if not self.send_callback(Action.MEASURE, callback_data):
aborted = True
break
elif code is DispersionCode.AFTER_RESTORE:
if not self.send_callback(Action.RESTORE, callback_data):
aborted = True
break
idx += 1
except Exception as ex:
err = ex
except KeyboardInterrupt as ex:
aborted = True
finally:
# Restore RF
# TODO
self.send_callback(
Action.RESTORE,
{"idx": idx},
raiseException=False,
)
if err is not None:
raise (err)
if aborted:
logger.warning(f"{self.get_name()} : measurement aborted (settings not restored)")
return False
dispersion_data = measurement.dispersion_data
# contains also pre-processed data
# dispersion_data.output_names = self.element_holder.get_bpms(
# self.bpm_array_name
# ).names()
self.latest_measurement.update(dispersion_data.model_dump())
return True
[docs]
def get(self):
return self.latest_measurement