11import logging
2+ from dataclasses import asdict
23from pathlib import Path
3- from typing import TYPE_CHECKING , Literal , Optional , Union
4-
5- try :
6- from typing import Self # Python 3.11+
7- except ImportError :
8- from typing_extensions import Self # Python 3.10 and earlier
4+ from typing import Literal , Optional , Union
95
106import numpy as np
11- from pydantic import ConfigDict
12-
13- if TYPE_CHECKING :
14- from ..common .holders .element_holder import ElementHolder
157from pySC import ResponseMatrix as pySC_ResponseMatrix
168from pySC .apps import orbit_correction
179
1810from ..arrays .magnet_array import MagnetArray
19- from ..common .element import Element , ElementConfigModel
2011from ..common .exception import PyAMLException
2112from ..external .pySC_interface import pySCInterface
2213from ..rf .rf_plant import RFPlant
14+ from ..validation import DynamicValidation , register_schema
2315from .orbit_response_matrix_data import OrbitResponseMatrixData
2416from .tuning_tool import TuningTool
2517
2921PYAMLCLASS = "Orbit"
3022
3123
32- class ConfigModel (ElementConfigModel ):
33- model_config = ConfigDict (arbitrary_types_allowed = True , extra = "forbid" )
34-
35- bpm_array_name : str
36- hcorr_array_name : str
37- vcorr_array_name : str
38- rf_plant_name : Optional [str ] = None
39- singular_values : Optional [int ] = None
40- singular_values_H : Optional [int ] = None
41- singular_values_V : Optional [int ] = None
42- virtual_target : float = 0
43- response_matrix : Union [str , OrbitResponseMatrixData ]
44-
24+ @register_schema
25+ class Orbit (TuningTool , DynamicValidation ):
26+ def __init__ (
27+ self ,
28+ name : str ,
29+ bpm_array_name : str ,
30+ hcorr_array_name : str ,
31+ vcorr_array_name : str ,
32+ response_matrix : Union [str , OrbitResponseMatrixData ],
33+ rf_plant_name : Optional [str ] = None ,
34+ singular_values : Optional [int ] = None ,
35+ singular_values_H : Optional [int ] = None ,
36+ singular_values_V : Optional [int ] = None ,
37+ virtual_target : float = 0 ,
38+ ):
39+ super ().__init__ (name )
4540
46- class Orbit (TuningTool ):
47- def __init__ (self , cfg : ConfigModel ):
48- super ().__init__ (cfg .name )
49- self ._cfg = cfg
50- self .bpm_array_name = cfg .bpm_array_name
51- self .hcorr_array_name = cfg .hcorr_array_name
52- self .vcorr_array_name = cfg .vcorr_array_name
41+ self .bpm_array_name = bpm_array_name
42+ self .hcorr_array_name = hcorr_array_name
43+ self .vcorr_array_name = vcorr_array_name
5344 self ._pySC_response_matrix = None
45+ self .rf_plant_name = rf_plant_name
46+ self .virtual_target = virtual_target
5447
55- self .virtual_target = cfg .virtual_target
56-
57- if cfg .singular_values is None :
58- if cfg .singular_values_H is None or cfg .singular_values_V is None :
48+ if singular_values is None :
49+ if singular_values_H is None or singular_values_V is None :
5950 raise PyAMLException (
6051 "Either `singular_values` or `singular_values_H` and `singular_values_V` must be provided."
6152 )
62- self .singular_values_H = cfg . singular_values_H
63- self .singular_values_V = cfg . singular_values_V
53+ self .singular_values_H = singular_values_H
54+ self .singular_values_V = singular_values_V
6455 else :
65- if cfg . singular_values_H is not None or cfg . singular_values_V is not None :
56+ if singular_values_H is not None or singular_values_V is not None :
6657 raise PyAMLException (
6758 "Either `singular_values` or `singular_values_H` and `singular_values_V` must be provided, not both."
6859 )
69- self .singular_values_H = cfg . singular_values
70- self .singular_values_V = cfg . singular_values
60+ self .singular_values_H = singular_values
61+ self .singular_values_V = singular_values
7162
7263 # If the configuration response matrix is a filename, load it
73- if type (cfg . response_matrix ) is str :
64+ if type (response_matrix ) is str :
7465 try :
75- cfg . response_matrix = OrbitResponseMatrixData .load (cfg . response_matrix )
66+ self . _response_matrix = OrbitResponseMatrixData .load (response_matrix )
7667 except Exception as e :
77- logger .warning (f"Loading { cfg . response_matrix } failed { str (e )} " )
78- cfg . response_matrix = None
68+ logger .warning (f"Loading { response_matrix } failed { str (e )} " )
69+ self . _response_matrix = None
7970
8071 # Converts to self._pySC_response_matrix
81- if cfg . response_matrix :
82- self ._set_response_matrix (cfg . response_matrix )
72+ if self . _response_matrix :
73+ self ._set_response_matrix (self . _response_matrix )
8374
8475 self ._hcorr : MagnetArray = None
8576 self ._vcorr : MagnetArray = None
@@ -95,24 +86,25 @@ def load(self, load_path: Path):
9586 load_path : Path
9687 Filename of the :class:`~.OrbitResponseMatrixData` to load
9788 """
98- self ._cfg . response_matrix = OrbitResponseMatrixData .load (load_path )
99- self ._set_response_matrix (self ._cfg . response_matrix )
89+ self ._response_matrix = OrbitResponseMatrixData .load (load_path )
90+ self ._set_response_matrix (self .response_matrix )
10091
10192 def _set_response_matrix (self , mat ):
102- m = mat . _cfg . model_dump ( )
93+ m = asdict ( mat )
10394 m ["input_names" ] = m .pop ("variable_names" )
10495 m ["output_names" ] = m .pop ("observable_names" )
10596 m ["input_planes" ] = m .pop ("variable_planes" )
10697 m ["output_planes" ] = m .pop ("observable_planes" )
107- self ._cfg .response_matrix = mat
98+ m .pop ("type" , None )
99+ self ._response_matrix = mat
108100 self ._pySC_response_matrix = pySC_ResponseMatrix .model_validate (m )
109101
110102 @property
111103 def response_matrix (self ) -> OrbitResponseMatrixData | None :
112104 """
113105 Return the response matrix if it has been loaded None otherwise
114106 """
115- return self ._cfg . response_matrix
107+ return self ._response_matrix
116108
117109 def correct (
118110 self ,
@@ -312,11 +304,11 @@ def get_rf_weight(self) -> float:
312304 return self ._pySC_response_matrix .rf_weight
313305
314306 def post_init (self ):
315- self ._hcorr = self .peer .magnets .get (self ._cfg . hcorr_array_name )
316- self ._vcorr = self .peer .magnets .get (self ._cfg . vcorr_array_name )
307+ self ._hcorr = self .peer .magnets .get (self .hcorr_array_name )
308+ self ._vcorr = self .peer .magnets .get (self .vcorr_array_name )
317309 hvElts = []
318310 hvElts .extend (self ._hcorr )
319311 hvElts .extend (self ._vcorr )
320312 self ._hvcorr = MagnetArray ("" , hvElts )
321- if self ._cfg . rf_plant_name is not None :
322- self ._rf_plant = self .peer .rf .get (self ._cfg . rf_plant_name )
313+ if self .rf_plant_name is not None :
314+ self ._rf_plant = self .peer .rf .get (self .rf_plant_name )
0 commit comments