Skip to content

Commit fcbb87f

Browse files
Merge pull request #359 from python-accelerator-middle-layer/schema-registry-bba
Remove ConfigModel from BBA
2 parents 45f7c87 + 13c834a commit fcbb87f

4 files changed

Lines changed: 204 additions & 145 deletions

File tree

pyaml/tuning_tools/bba.py

Lines changed: 83 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,66 +4,100 @@
44
import matplotlib.pyplot as plt
55
import numpy as np
66
import pySC
7-
from pydantic import ConfigDict
87
from pySC.apps import measure_bba
98
from pySC.apps.bba import BBAAnalysis
109
from pySC.apps.codes import BBACode
1110

1211
from ..common.constants import Action
1312
from ..common.exception import PyAMLException
1413
from ..external.pySC_interface import pySCInterface
15-
from .measurement_tool import MeasurementTool, MeasurementToolConfigModel
14+
from ..validation import DynamicValidation, register_schema
15+
from .measurement_tool import MeasurementTool
1616

1717
logger = logging.getLogger(__name__)
1818

1919
PYAMLCLASS = "BBA"
2020

2121

22-
class ConfigModel(MeasurementToolConfigModel):
22+
@register_schema
23+
class BBA(MeasurementTool, DynamicValidation):
2324
"""
24-
Configuration model for Beam Based Alignment.
25-
BBA finds the magnetic center of a quad (zero crossing).
25+
Beam-based alignment measurement tool.
26+
27+
This tool determines the magnetic center of a quadrupole by varying its
28+
strength while applying controlled horizontal and vertical orbit offsets.
29+
The quadrupole center is identified from the corresponding zero crossings
30+
in the BPM response.
2631
2732
Parameters
2833
----------
34+
name : str
35+
Name of the measurement tool.
2936
bpm_array_name : str
30-
BPM array name (orbit)
37+
Name of the BPM array used to measure the orbit.
3138
bpm_name : str
32-
BPM to be corrected (close to the quad)
39+
Name of the BPM located near the quadrupole whose center is measured.
3340
hcorr_name : str
34-
Horizontal corrector used to make a deviation in the quad
41+
Name of the horizontal corrector used to create horizontal orbit
42+
offsets at the quadrupole.
3543
vcorr_name : str
36-
Vertical corrector used to make a deviation in the quad
44+
Name of the vertical corrector used to create vertical orbit offsets
45+
at the quadrupole.
3746
quad_name : str
38-
Quadrupole used to find the center
47+
Name of the quadrupole to align.
3948
hcorr_delta : float
40-
Horizontal corrector delta strength
49+
Change in horizontal corrector strength used for each horizontal
50+
orbit-offset step.
4151
vcorr_delta : float
42-
Vertical corrector delta strength
52+
Change in vertical corrector strength used for each vertical
53+
orbit-offset step.
4354
hquad_delta : float
44-
Quadrupole delta strength (for h search)
55+
Change in quadrupole strength used during the horizontal alignment
56+
measurement.
4557
vquad_delta : float
46-
Quadrupole delta strength (for v search)
47-
58+
Change in quadrupole strength used during the vertical alignment
59+
measurement.
60+
n_step : int, default=1
61+
Number of orbit-offset steps to perform in each plane.
62+
sleep_between_step : float, default=0
63+
Time in seconds to wait after changing an orbit offset.
64+
n_avg_meas : int, default=1
65+
Number of BPM measurements to average at each step.
66+
sleep_between_meas : float, default=0
67+
Time in seconds to wait between individual BPM measurements.
4868
"""
4969

50-
model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
51-
52-
bpm_array_name: str
53-
bpm_name: str
54-
hcorr_name: str
55-
vcorr_name: str
56-
quad_name: str
57-
hcorr_delta: float
58-
vcorr_delta: float
59-
hquad_delta: float
60-
vquad_delta: float
61-
62-
63-
class BBA(MeasurementTool):
64-
def __init__(self, cfg: ConfigModel):
65-
super().__init__(cfg.name)
66-
self._cfg = cfg
70+
def __init__(
71+
self,
72+
name: str,
73+
bpm_array_name: str,
74+
bpm_name: str,
75+
hcorr_name: str,
76+
vcorr_name: str,
77+
quad_name: str,
78+
hcorr_delta: float,
79+
vcorr_delta: float,
80+
hquad_delta: float,
81+
vquad_delta: float,
82+
n_step: int = 1,
83+
sleep_between_step: float = 0,
84+
n_avg_meas: int = 1,
85+
sleep_between_meas: float = 0,
86+
):
87+
super().__init__(name)
88+
self.bpm_array_name = bpm_array_name
89+
self.bpm_name = bpm_name
90+
self.hcorr_name = hcorr_name
91+
self.vcorr_name = vcorr_name
92+
self.quad_name = quad_name
93+
self.hcorr_delta = hcorr_delta
94+
self.vcorr_delta = vcorr_delta
95+
self.hquad_delta = hquad_delta
96+
self.vquad_delta = vquad_delta
97+
self.n_step = n_step
98+
self.sleep_between_step = sleep_between_step
99+
self.n_avg_meas = n_avg_meas
100+
self.sleep_between_meas = sleep_between_meas
67101

68102
def measure(
69103
self,
@@ -111,29 +145,29 @@ def measure(
111145
plane: str, optional
112146
Plane to perform ("H" or "V", None => both plane)
113147
"""
114-
nb_meas = n_avg_meas if n_avg_meas is not None else self._cfg.n_avg_meas
115-
sleep_step = sleep_between_step if sleep_between_step is not None else self._cfg.sleep_between_step
116-
sleep_meas = sleep_between_meas if sleep_between_meas is not None else self._cfg.sleep_between_meas
148+
nb_meas = n_avg_meas if n_avg_meas is not None else self.n_avg_meas
149+
sleep_step = sleep_between_step if sleep_between_step is not None else self.sleep_between_step
150+
sleep_meas = sleep_between_meas if sleep_between_meas is not None else self.sleep_between_meas
117151

118152
element_holder = self._peer
119153
interface = pySCInterface(
120154
element_holder=element_holder,
121-
bpm_array_name=self._cfg.bpm_array_name,
155+
bpm_array_name=self.bpm_array_name,
122156
)
123157
interface.set_wait_time = sleep_step
124158
interface.read_wait_time = sleep_meas
125159

126-
bpms_names = element_holder.bpms.get(self._cfg.bpm_array_name).names()
160+
bpms_names = element_holder.bpms.get(self.bpm_array_name).names()
127161

128162
bba_pySC_config = {
129-
"number": bpms_names.index(self._cfg.bpm_name),
130-
"QUAD": self._cfg.quad_name,
131-
"HCORR": self._cfg.hcorr_name,
132-
"VCORR": self._cfg.vcorr_name,
133-
"HCORR_delta": self._cfg.hcorr_delta,
134-
"QUAD_dk_H": self._cfg.hquad_delta,
135-
"VCORR_delta": self._cfg.vcorr_delta,
136-
"QUAD_dk_V": self._cfg.vquad_delta,
163+
"number": bpms_names.index(self.bpm_name),
164+
"QUAD": self.quad_name,
165+
"HCORR": self.hcorr_name,
166+
"VCORR": self.vcorr_name,
167+
"HCORR_delta": self.hcorr_delta,
168+
"QUAD_dk_H": self.hquad_delta,
169+
"VCORR_delta": self.vcorr_delta,
170+
"QUAD_dk_V": self.vquad_delta,
137171
"magnet_type": "normal_quadrupole",
138172
}
139173

@@ -142,10 +176,10 @@ def measure(
142176

143177
generator = measure_bba(
144178
interface=interface,
145-
bpm_name=self._cfg.bpm_name,
179+
bpm_name=self.bpm_name,
146180
config=bba_pySC_config,
147181
shots_per_orbit=nb_meas,
148-
n_corr_steps=self._cfg.n_step,
182+
n_corr_steps=self.n_step,
149183
bipolar=False,
150184
skip_save=True,
151185
plane=plane,
@@ -266,7 +300,7 @@ def plot_data(self, plane: str):
266300
axes["A"].plot(xx[final_mask], yy[final_mask], ".", c="C0")
267301
axes["A"].plot(xx[~final_mask], yy[~final_mask], ".", c="C1")
268302

269-
axes["A"].set_xlabel(f"BPM position [μm]\n{self._cfg.bpm_name} offset = {offset * 1e6:.3f} [μm]")
303+
axes["A"].set_xlabel(f"BPM position [μm]\n{self.bpm_name} offset = {offset * 1e6:.3f} [μm]")
270304
axes["A"].set_ylabel("Modulation [μm]")
271305
axes["A"].grid()
272306

@@ -285,6 +319,6 @@ def plot_data(self, plane: str):
285319
axes["C"].grid()
286320

287321
fig.tight_layout()
288-
fig.canvas.manager.set_window_title(f"{plane} BBA {self._cfg.bpm_name}")
322+
fig.canvas.manager.set_window_title(f"{plane} BBA {self.bpm_name}")
289323

290324
plt.show()

0 commit comments

Comments
 (0)