Source code for pyaml.tuning_tools.chromaticity

from pathlib import Path
from typing import TYPE_CHECKING

from .. import PyAMLException
from ..common.element import ElementConfigModel
from ..diagnostics.chromaticity_monitor import ChomaticityMonitor
from .response_matrix_data import ResponseMatrixData
from .tuning_tool import TuningTool

if TYPE_CHECKING:
    from ..arrays.magnet_array import MagnetArray

try:
    from typing import Self  # Python 3.11+
except ImportError:
    from typing_extensions import Self  # Python 3.10 and earlier
import logging
import time

import numpy as np

logger = logging.getLogger(__name__)

# Define the main class name for this module
PYAMLCLASS = "Chromaticity"


[docs] class ConfigModel(ElementConfigModel): """ Configuration model for Tune Parameters ---------- sextu_array_name : str Array name of sextu used to adjust the chromaticity chromaticty_monitor_name : str Name of the diagnostic pyaml device for measuring the chromaticity response_matrix : str | ResponseMatrixData filename or data of the chromaticity response matrix """ sextu_array_name: str chromaticty_monitor_name: str response_matrix: str | ResponseMatrixData
[docs] class Chromaticity(TuningTool): """ Class providing chromaticity adjustment tool """ def __init__(self, cfg: ConfigModel): """ Construct a chromaticity adjustment object. Parameters ---------- cfg : ConfigModel Configuration for the tune adjustment. """ super().__init__(cfg.name) self._cfg = cfg self._response_matrix = None self._correctionmat = None # If the configuration response matrix is a filename, load it if type(cfg.response_matrix) is str: try: cfg.response_matrix = ResponseMatrixData.load(cfg.response_matrix) except Exception as e: logger.warning(f"{str(e)}") cfg.response_matrix = None # Invert matrix if cfg.response_matrix: self._response_matrix = np.array(cfg.response_matrix._cfg.matrix) self._correctionmat = np.linalg.pinv(self._response_matrix) # TODO: Initialise first setpoint self._setpoint = np.array([np.nan, np.nan]) @property def response_matrix(self) -> ResponseMatrixData | None: """ Return the response matrix if it has been loaded None otherwise """ return self._cfg.response_matrix
[docs] def load(self, load_path: Path): """ Dynamically loads a response matrix. Parameters ---------- load_path : Path Filename of the :class:`~.ResponseMatrixData` to load """ self._cfg.response_matrix = ResponseMatrixData.load(load_path) self._response_matrix = np.array(self._cfg.response_matrix._cfg.matrix) self._correctionmat = np.linalg.pinv(self._response_matrix)
@property def _cm(self) -> "ChomaticityMonitor": self.check_peer() return self.peer.get_chromaticity_monitor(self._cfg.chromaticty_monitor_name) @property def _sextu(self) -> "MagnetArray": self.check_peer() return self.peer.get_magnets(self._cfg.sextu_array_name)
[docs] def get(self): """ Return the chromaticity setpoint """ return self._setpoint
[docs] def readback(self): """ Launch a chromaticty scan and returns the measured chromaticity. """ self._cm.measure() return self._cm.chromaticity.get()
[docs] def set(self, chroma: np.array, iter: int = 1, wait_time: float = 0.0): """ Sets the chromaticity Parameters ---------- chromaticity : np.array Chromaticity setpoint iter_nb : int Number of iteration wait_time : float Time to wait in second between 2 iterations """ for i in range(iter): diff_chroma = chroma - self.readback() if i == iter: wait_time = 0 # do not wait on last iteration self.add(diff_chroma, wait_time) self._setpoint = np.array(chroma)
[docs] def correct(self, dchroma: np.array) -> np.array: """ Return delta strengths for chromaticity correction Parameters ---------- dchroma : np.array Delta chroma """ if self._correctionmat is None: raise PyAMLException("Chromaticity.correct(): no matrix loaded or measured") return np.matmul(self._correctionmat, dchroma)
[docs] def add(self, dchroma: np.array, wait_time: float = 0.0): """ Add delta chromaticity to the actual chromaticity Parameters ---------- dchroma : np.array Delta tune iter_nb: int wait_time: float """ strengths = self._sextu.strengths.get() strengths += self.correct(dchroma) self._sextu.strengths.set(strengths) time.sleep(wait_time) self._setpoint += dchroma