Source code for pyaml.magnet.linear_model
import numpy as np
from pydantic import BaseModel, ConfigDict
from ..common.element import __pyaml_repr__
from ..control.deviceaccess import DeviceAccess
from .curve import Curve
from .model import MagnetModel
# Define the main class name for this module
PYAMLCLASS = "LinearMagnetModel"
[docs]
class ConfigModel(BaseModel):
"""
Linear magnet model.
Parameters
----------
curve : Curve or None, optional
Curve object used for interpolation. By default,
identity curve is used.
powerconverter : DeviceAccess or None, optional
Power converter device to apply currrent
calibration_factor : float, optional
Correction factor applied to the curve. Default: 1.0
calibration_offset : float, optional
Correction offset applied to the curve. Default: 0.0
crosstalk : float, optional
Crosstalk factor. Default: 1.0
unit : str
Unit of the strength (i.e. 1/m or m-1)
"""
model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
curve: Curve | None = None
powerconverter: DeviceAccess | None
calibration_factor: float = 1.0
calibration_offset: float = 0.0
crosstalk: float = 1.0
unit: str
[docs]
class LinearMagnetModel(MagnetModel):
"""
Class that handle manget current/strength conversion using
linear interpolation for a single function magnet
"""
def __init__(self, cfg: ConfigModel):
self._cfg = cfg
if self._cfg.curve:
self.__curve = cfg.curve.get_curve()
self.__curve[:, 1] = self.__curve[:, 1] * cfg.calibration_factor * cfg.crosstalk + cfg.calibration_offset
self.__rcurve = Curve.inverse(self.__curve)
else:
self.__curve = None
self.__rcurve = None
self.__g = cfg.calibration_factor * cfg.crosstalk
self.__o = cfg.calibration_offset
self.__strength_unit = cfg.unit
self.__hardware_unit = cfg.powerconverter.unit()
self.__brho = np.nan
self.__ps = cfg.powerconverter
[docs]
def compute_hardware_values(self, strengths: np.array) -> np.array:
if self.__rcurve is not None:
_current = np.interp(strengths[0] * self.__brho, self.__rcurve[:, 0], self.__rcurve[:, 1])
else:
_current = (strengths[0] * self.__brho) / self.__g + self.__o
return np.array([_current])
[docs]
def compute_strengths(self, currents: np.array) -> np.array:
if self.__curve is not None:
_strength = np.interp(currents[0], self.__curve[:, 0], self.__curve[:, 1]) / self.__brho
else:
_strength = ((currents[0] - self.__o) * self.__g) / self.__brho
return np.array([_strength])
[docs]
def get_strength_units(self) -> list[str]:
return [self.__strength_unit] if self.__strength_unit is not None else [""]
[docs]
def get_hardware_units(self) -> list[str]:
return [self.__hardware_unit] if self.__hardware_unit is not None else [""]
[docs]
def get_devices(self) -> list[DeviceAccess]:
return [self.__ps]
[docs]
def set_magnet_rigidity(self, brho: np.double):
self.__brho = brho
def __repr__(self):
return __pyaml_repr__(self)