Skip to content

Commit adb19a4

Browse files
awegschefsoubelet
andauthored
add options to choose BPMs pairing for coupling calculation (#371)
Co-authored-by: Felix Soubelet <[email protected]>
1 parent cf22df6 commit adb19a4

File tree

4 files changed

+50
-14
lines changed

4 files changed

+50
-14
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
#### 2022-04-25
44

5+
- Added:
6+
- There is now an option, `coupling_pairing`, for the BPM pairing in coupling calculation, to let the user choose the number of BPMs instead of the usual "best candidate" method.
7+
8+
#### 2022-04-25
9+
510
- Fixed:
611
- Only perform index merging on the `NAME` column during coupling calculation. This solves an (at the moment) un-understood issue where some BPMs would have different `S` values in different files.
712

omc3/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
__title__ = "omc3"
1212
__description__ = "An accelerator physics tools package for the OMC team at CERN."
1313
__url__ = "https://github.com/pylhc/omc3"
14-
__version__ = "0.2.6"
14+
__version__ = "0.2.7"
1515
__author__ = "pylhc"
1616
__author_email__ = "[email protected]"
1717
__license__ = "MIT"

omc3/hole_in_one.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,13 @@ def hole_in_one_entrypoint(opt, rest):
232232
Flags: **--coupling_method**
233233
Choices: ``(0, 1, 2)``
234234
Default: ``2``
235+
- **coupling_pairing**: Pairing mode for 2 BPM coupling method. If 0 is given, omc3
236+
will try to determine the best candidate. If a number n>=1 is given, then some BPMs are
237+
skipped and the n-th following BPM downstream is used for the pairing.
238+
239+
Flags: **--coupling_pairing**
240+
Choices: ``(0, n>=1)``
241+
Default: ``0``.
235242
- **nonlinear**: Calculate higher order RDTs or CRDT
236243
237244
Flags: **--nonlinear**
@@ -508,6 +515,11 @@ def optics_params():
508515
params.add_parameter(name="coupling_method", type=int,
509516
choices=(0, 1, 2), default=OPTICS_DEFAULTS["coupling_method"],
510517
help="Analysis option for coupling: disabled, 1 BPM or 2 BPMs method")
518+
params.add_parameter(name="coupling_pairing", type=int,
519+
default=OPTICS_DEFAULTS["coupling_pairing"],
520+
help="Pairing mode for 2 BPM coupling method. If 0 is given, omc3 will try to "
521+
"determine the best candidate. If a number n>=1 is given, then some BPMs are skipped "
522+
"and the n-th following BPM downstream is used for the pairing.")
511523
params.add_parameter(name="range_of_bpms", type=int,
512524
choices=(5, 7, 9, 11, 13, 15), default=OPTICS_DEFAULTS["range_of_bpms"],
513525
help="Range of BPMs for beta from phase calculation")
@@ -553,6 +565,7 @@ def optics_params():
553565

554566
OPTICS_DEFAULTS = {
555567
"coupling_method": 2,
568+
"coupling_pairing": 0,
556569
"range_of_bpms": 11,
557570
"compensation": "model",
558571
}

omc3/optics_measurements/coupling.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ def calculate_coupling(
113113
)
114114

115115
LOGGER.debug("Finding BPM pairs for momentum reconstruction")
116-
bpm_pairs_x, deltas_x = _find_pair(phases_x)
117-
bpm_pairs_y, deltas_y = _find_pair(phases_y)
116+
bpm_pairs_x, deltas_x = _find_pair(phases_x, meas_input.coupling_pairing)
117+
bpm_pairs_y, deltas_y = _find_pair(phases_y, meas_input.coupling_pairing)
118118

119119
LOGGER.debug("Computing complex lines from spectra")
120120
A01: np.ndarray = 0.5 * _get_complex_line(
@@ -217,19 +217,37 @@ def compensate_rdts_ryoichi():
217217

218218
# ----- Helpers ----- #
219219

220-
# def _take_next(phases: tfs.TfsDataFrame, shift: int = 1):
221-
# """
222-
# Takes the following BPM for momentum reconstruction by a given shift.
223-
#
224-
# Args:
225-
# phases (tfs.TfsDataFrame): Dataframe matrix of phase advances, as calculated in phase.py.
226-
# shift (int): ???
227-
# """
228-
# indices = np.roll(np.arange(phases.to_numpy().shape[0]), shift)
229-
# return indices, phases.to_numpy()[np.arange(phases.to_numpy().shape[0]), indices] - 0.25
220+
def _find_pair(phases: tfs.TfsDataFrame, mode: int = 1):
221+
"""
222+
Does the BPM pairing for coupling calculation.
223+
224+
Args:
225+
mode (int): Value to determine the BPM pairing. If ``0`` is given,
226+
tries to find the best candidate. If a value ``n>=1`` is given,
227+
then takes the n-th following BPM downstream for the pairing.
228+
"""
229+
230+
if mode == 0:
231+
return _find_candidate(phases)
232+
else:
233+
return _take_next(phases, mode)
234+
235+
236+
def _take_next(phases: tfs.TfsDataFrame, shift: int = 1):
237+
"""
238+
Takes the following BPM for momentum reconstruction by a given shift.
239+
240+
Args:
241+
phases (tfs.TfsDataFrame): Dataframe matrix of phase advances, as calculated in phase.py.
242+
shift (int): Value to determine the BPM pairing. If ``0`` is given,
243+
tries to find the best candidate. If a value ``n>=1`` is given,
244+
then takes the n-th following BPM downstream for the pairing.
245+
"""
246+
indices = np.roll(np.arange(phases.to_numpy().shape[0]), shift)
247+
return indices, phases.to_numpy()[np.arange(phases.to_numpy().shape[0]), indices] - 0.25
230248

231249

232-
def _find_pair(phases: tfs.TfsDataFrame) -> Tuple[np.ndarray, np.ndarray]:
250+
def _find_candidate(phases: tfs.TfsDataFrame) -> Tuple[np.ndarray, np.ndarray]:
233251
"""
234252
Finds the best candidate for momentum reconstruction.
235253

0 commit comments

Comments
 (0)