Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 29 additions & 32 deletions pyaml/tuning_tools/orbit.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
from ..arrays.magnet_array import MagnetArray
from ..common.element import Element, ElementConfigModel
from ..common.exception import PyAMLException
from ..configuration.factory import Factory
from ..configuration.fileloader import load
from ..external.pySC_interface import pySCInterface
from ..rf.rf_plant import RFPlant
from .response_matrix import ResponseMatrix
Expand Down Expand Up @@ -51,6 +49,7 @@ def __init__(self, cfg: ConfigModel):
self.bpm_array_name = cfg.bpm_array_name
self.hcorr_array_name = cfg.hcorr_array_name
self.vcorr_array_name = cfg.vcorr_array_name
self._pySC_response_matrix = None

self.virtual_target = cfg.virtual_target

Expand All @@ -71,16 +70,17 @@ def __init__(self, cfg: ConfigModel):
self.singular_values_H = cfg.singular_values
self.singular_values_V = cfg.singular_values

# If the configuration response matrix is a filename, load it
if type(cfg.response_matrix) is str:
response_matrix_filename = cfg.response_matrix
# assigns self.response_matrix
if Path(response_matrix_filename).exists():
self.load_response_matrix(response_matrix_filename)
else:
logger.warning(f"{response_matrix_filename} does not exist.")
self.response_matrix = None
else:
self.response_matrix = pySC_ResponseMatrix.model_validate(
try:
cfg.response_matrix = ResponseMatrix.load(cfg.response_matrix)
except Exception as e:
logger.warning(f"{str(e)}")
cfg.response_matrix = None

# assigns self._pySC_response_matrix
if cfg.response_matrix:
self._pySC_response_matrix = pySC_ResponseMatrix.model_validate(
cfg.response_matrix._cfg.model_dump()
)

Expand All @@ -89,6 +89,10 @@ def __init__(self, cfg: ConfigModel):
self._hvcorr: MagnetArray = None
self._rf_plant: RFPlant = None

@property
def reponse_matrix(self) -> ResponseMatrix | None:
return self._cfg.response_matrix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this property, because _pySC_response_matrix holds almost all of the information.

Is it in anticipation that a pyaml ResponseMatrix holds inside of it a _pySC_response_matrix, and then everything goes through the "pyaml" ResponseMatrix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is the idea

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pySC should not appear to the end user neither methods, neither internal structure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also currently thinking how to have a base class ResponseMatrix with basically only common field and having specific response matrices. For instance, i would like to not see the rf_respone in the base class.


def correct(
self,
plane: Optional[Literal["H", "V"]] = None,
Expand Down Expand Up @@ -137,7 +141,7 @@ def correct(
None or if plane = 'H'.
"""

if self.response_matrix is None:
if self._pySC_response_matrix is None:
raise PyAMLException(f"{self.get_name()} does not have a response_matrix.")

interface = pySCInterface(
Expand All @@ -161,7 +165,7 @@ def correct(
if plane is None or plane == "H":
trims_h = orbit_correction(
interface=interface,
response_matrix=self.response_matrix,
response_matrix=self._pySC_response_matrix,
method="svd_values",
parameter=svH,
virtual=True,
Expand All @@ -175,7 +179,7 @@ def correct(
if plane is None or plane == "V":
trims_v = orbit_correction(
interface=interface,
response_matrix=self.response_matrix,
response_matrix=self._pySC_response_matrix,
method="svd_values",
parameter=svV,
virtual=False,
Expand Down Expand Up @@ -241,35 +245,35 @@ def correct(
def set_weight(
self, name: str, weight: float, plane: Optional[Literal["H", "V"]] = None
) -> None:
self.response_matrix.set_weight(name, weight, plane=plane)
self._pySC_response_matrix.set_weight(name, weight, plane=plane)
return

def set_virtual_weight(self, weight: float) -> None:
self.response_matrix.virtual_weight = weight
self._pySC_response_matrix.virtual_weight = weight
return

def set_rf_weight(self, weight: float) -> None:
self.response_matrix.rf_weight = weight
self._pySC_response_matrix.rf_weight = weight
return

def get_weight(self, name: str, plane: Optional[Literal["H", "V"]] = None) -> float:
names = []
planes = []
weights = []

inames = self.response_matrix.input_names
iplanes = self.response_matrix.input_planes
iweights = self.response_matrix.input_weights
inames = self._pySC_response_matrix.input_names
iplanes = self._pySC_response_matrix.input_planes
iweights = self._pySC_response_matrix.input_weights
for iname, iplane, iw in zip(inames, iplanes, iweights, strict=True):
if name == iname:
if plane is None or plane == iplane:
names.append(iname)
planes.append(iplane)
weights.append(iw)

onames = self.response_matrix.output_names
oplanes = self.response_matrix.output_planes
oweights = self.response_matrix.output_weights
onames = self._pySC_response_matrix.output_names
oplanes = self._pySC_response_matrix.output_planes
oweights = self._pySC_response_matrix.output_weights
for oname, oplane, ow in zip(onames, oplanes, oweights, strict=True):
if name == oname:
if plane is None or plane == oplane:
Expand All @@ -286,10 +290,10 @@ def get_weight(self, name: str, plane: Optional[Literal["H", "V"]] = None) -> fl
)

def get_virtual_weight(self) -> float:
return self.response_matrix.virtual_weight
return self._pySC_response_matrix.virtual_weight

def get_rf_weight(self) -> float:
return self.response_matrix.rf_weight
return self._pySC_response_matrix.rf_weight

def post_init(self):
self._hcorr = self._peer.get_magnets(self._cfg.hcorr_array_name)
Expand All @@ -309,10 +313,3 @@ def attach(self, peer: "ElementHolder") -> Self:
obj = self.__class__(self._cfg)
obj._peer = peer
return obj

def load_response_matrix(self, filename: str) -> None:
path = Path(filename)
config_dict = load(str(path.resolve()))
rm = Factory.depth_first_build(config_dict, ignore_external=False)
self.response_matrix = pySC_ResponseMatrix.model_validate(rm._cfg.model_dump())
return None
30 changes: 28 additions & 2 deletions pyaml/tuning_tools/response_matrix.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from pathlib import Path
from typing import Optional

from pydantic import BaseModel, ConfigDict

from pyaml.common.element import __pyaml_repr__
from pyaml.configuration.factory import Factory

from .. import PyAMLException
from ..configuration.fileloader import load

PYAMLCLASS = "ResponseMatrix"


Expand All @@ -14,9 +21,9 @@ class ConfigModel(BaseModel):
matrix : list[list[float]]
Response matrix data
input_names : list[str], optional
Input names
Input names, basically the actuators
output_names : list[str]
Output names
Output names, basically the measurements
rf_response : list[float], optional
RF response data
"""
Expand All @@ -32,5 +39,24 @@ class ConfigModel(BaseModel):


class ResponseMatrix(object):
"""
Generic response matrix loader
"""

def __init__(self, cfg: ConfigModel):
self._cfg = cfg

@staticmethod
def load(filename: str) -> None:
"""
Load a reponse matrix from a configuration file
"""
path = Path(filename)
if path.exists():
config_dict = load(str(path.resolve()))
return Factory.depth_first_build(config_dict, ignore_external=False)
else:
raise PyAMLException(f"{filename}: file not found")

def __repr__(self):
return __pyaml_repr__(self)
Loading