Skip to content

Commit a8b8b5d

Browse files
authored
Bad BPM presentation (#163)
* added
1 parent 402afd2 commit a8b8b5d

File tree

8 files changed

+134
-8
lines changed

8 files changed

+134
-8
lines changed
445 KB
Loading
571 KB
Loading
292 KB
Loading
550 KB
Loading

docs/css/custom_colors.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* docs/css/custom_colors.css */
2+
3+
/* Define the specific colors using CSS variables (optional but good practice) */
4+
:root {
5+
--color-cernniceblue: #0669b2;
6+
--color-atlasgreen: #27a572;
7+
--color-cernred: #e15e32;
8+
--color-atlasorange: #f09010;
9+
--color-cernlightblue: #15b3da;
10+
--color-cernpurple: #6e2466;
11+
}
12+
13+
/* General emphasis class */
14+
.omc-emph {
15+
color: var(--md-primary-fg-color);
16+
font-weight: bold;
17+
}
18+
19+
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<style>
2+
.tbt-related { color: var(--color-atlasgreen); font-weight: bold; }
3+
.svd-related { color: var(--color-cernred); font-weight: bold; }
4+
.spec-related { color: var(--color-atlasorange); font-weight: bold; }
5+
.manual-related { color: var(--color-cernlightblue); font-weight: bold; }
6+
.iforest-related { color: var(--color-cernpurple); font-weight: bold; }
7+
</style>
8+
9+
10+
The content of this page has been converted from the presentation given as ["OMC3 bad BPM detection" on the 31.03.2025](https://indico.cern.ch/event/1531923/) .
11+
12+
13+
## OMC-Analysis
14+
15+
![BPM vs Owl](../../assets/images/bpm_filtering/bpmvsowl.png)
16+
17+
* To get <span class="omc-emph">reliable</span> and <span class="omc-emph">reproducible</span> optics measurements, we cannot trust all BPM data that we are getting.
18+
* At <span class="omc-emph">different stages</span> of the code, we try to determine the "trustworthyness".
19+
* Some BPMs are fully <span class="omc-emph">excluded</span>, others are getting <span class="omc-emph">errorbars</span> based on their <span class="omc-emph">noise-level</span> (which are often used as *weights*, e.g. for correction calculations).
20+
21+
22+
## Automatic
23+
24+
* First the <span class="tbt-related">Turn-by-Turn Data</span> is checked for "obvious" signs.
25+
* <span class="tbt-related">EXACT_ZERO</span>: Any value has an <span class="tbt-related">exact zero</span> (might lead to false positives, but unlikely if happens in multiple datasets).
26+
* <span class="tbt-related">NANS</span>: Data contains <span class="tbt-related">NaN-values</span> (happens in SPS BPMs).
27+
* <span class="tbt-related">FLAT</span>: <span class="tbt-related">Peak-to-Peak</span> value was <span class="tbt-related">below</span> a given threshold (default: 10nm).
28+
* <span class="tbt-related">SPIKY</span>: A <span class="tbt-related">spike</span> in the data, <span class="tbt-related">above</span> a given threshold (default: 2cm).
29+
* To reduce <span class="svd-related">noise</span> we perform an SVD-decomposition and keep only the <span class="svd-related">strongest modes</span>.
30+
* <span class="svd-related">SVD_PEAK</span>: The BPM had a <span class="svd-related">mode</span> in the U-Matrix above a given threshold (default: 0.925).
31+
* Most information about the optics come from a <span class="spec-related">spectral analysis</span>.
32+
* <span class="spec-related">NO_TUNE</span>: Tune line could <span class="spec-related">not be found</span> in the spectrum.
33+
* <span class="spec-related">TUNE_CLEAN</span>: Tune line found was <span class="spec-related">too far from the average</span> of the other BPMs (default: > $10^{-5}$).
34+
35+
## Manual
36+
37+
38+
* <span class="manual-related">KNOWN</span>: Identified <span class="manual-related">manually</span>; sticking out spectrum/optics <span class="manual-related">regularly</span>.
39+
* <span class="manual-related">Large error bars</span>.
40+
* <span class="manual-related">Non-sensical</span> data points.
41+
* Cause <span class="manual-related">analysis issues</span> (e.g. phase-offsets, negative $\beta$, NaNs).
42+
* <span class="manual-related">Calibration</span> issues:
43+
* $\beta$-from-phase looks normal, peak in $\beta$-from-amplitude
44+
* $\beta$-ratios large.
45+
* Measure in <span class="manual-related">different optics</span> to <span class="manual-related">confirm BPM issue</span>.
46+
* **Good hint:** <span class="manual-related">Filtering them solves observed issues</span>.
47+
48+
49+
<figure>
50+
<img src="../../assets/images/bpm_filtering/BetaBeating.png">
51+
<figcaption>Observed Beta-Beating with some large errorbars (e.g. IP1 and IP5) and unrealistic beating (around 2200m in Y)</figcaption>
52+
</figure>
53+
54+
## Isolation Forest
55+
56+
* Using <span class="iforest-related">machine learning techniques</span> to identify Bad-BPMs.
57+
* <span class="iforest-related">IFOREST</span>: Identified BPM, due to being an <span class="iforest-related">outlier in Tune, Noise and/or Amplitude</span>
58+
59+
!!! warning "Under Re-evaluation"
60+
This functionality is currently under re-evaluation and has only been used on a small amount of data in 2021-2024!
61+
62+
![Isolation Forest Example](../../assets/images/bpm_filtering/iforest.png)
63+
64+
65+
[E. Fol - Machine Learning for BPM failure detection](https://indico.cern.ch/event/762124/contributions/3174751/attachments/1740028/2815322/hss_meeting_2410.pdf)<br>
66+
[E. Fol - Isolation Forest for bad BPMs: performance evaluation](https://indico.cern.ch/event/776442/contributions/3228674/attachments/1759222/2853627/omc_meeting_26nov.pdf)
67+
68+
## Bad BPMs Summary Script
69+
70+
* Bad-BPMs are written out in files <span class="omc-emph">per analysed TbT-Data</span>.
71+
* Script available to <span class="omc-emph">gather, summarize and make statistics</span>.
72+
73+
```bash
74+
usage: bad_bpms_summary.py [-h] --dates DATES [DATES ...] [--root ROOT] [--outfile OUTFILE]
75+
[--print_percentage PRINT_PERCENTAGE] [--accel_glob ACCEL_GLOB]
76+
77+
options:
78+
--dates DATES [DATES ...]
79+
Dates to include in analysis. This should be either subfolders in
80+
`root` or glob-patterns for those.
81+
--root ROOT Path to the root directory, containing the dates.
82+
Default: `/user/slops/data/LHC_DATA/OP_DATA/BetaBeat/`
83+
--outfile OUTFILE Path to the file to write out.
84+
--print_percentage PRINT_PERCENTAGE
85+
Print out BPMs that appear in more than this percentage of measurements.
86+
--accel_glob ACCEL_GLOB
87+
Accelerator name (glob for the sub-directories).
88+
```
89+
90+
Example: All bad BPMs from 2025, written into file and all &gt; 50% in terminal
91+
92+
```
93+
python -m omc3.scripts.bad_bpms_summary --dates 2025-* \
94+
--accel_glob LHCB* \
95+
--outfile bad_bpms_2025.txt \
96+
--print_percentage 50
97+
```
98+
99+
![A Bad BPM](../../assets/images/bpm_filtering/badbpm.png)
100+
101+
102+
103+
*[BPM]: Beam Position Monitor

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ extra:
9393
# Extras to load
9494
extra_css:
9595
- css/extra.css
96+
- css/custom_colors.css
9697
- css/hint.min.css
9798

9899
extra_javascript:
@@ -178,6 +179,7 @@ nav:
178179
- Introduction: measurements/physics/about.md
179180
- Error Propagation: measurements/physics/error_propagation.md
180181
- BPM-Calibration: measurements/physics/bpm_calibration.md
182+
- BPM-Filtering: measurements/physics/bpm_filtering.md
181183
- Coupling: measurements/physics/coupling.md
182184
- K-Mod: measurements/physics/kmod.md
183185
- Linear IR Optics: measurements/physics/ir_linear_optics.md

scripts/shift_calculations.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ def plot_all_machines_in_year(
326326
Returns:
327327
Figure: Figure of the plot.
328328
"""
329-
color_map = {name: f"C{ii}" for ii, name in enumerate(["lhc", "sps", "ps", "psb", "leir", "ad"])}
329+
color_map = {name: f"C{ii}" for ii, name in enumerate(["lhc", "sps", "ps", "psb", "leir", "ad", "superkekb"])}
330330

331331
data_map: dict[str, float] = {}
332332
for file_path in logbook_dir.glob(f"{year:4d}_*.md"):
@@ -387,8 +387,8 @@ def plot_all_machines_in_year(
387387

388388
# 2022 ---------------------------------------------------------------------
389389

390-
shift_m = manual_shifts(logbook_dir / "2022_lhc.md")
391-
plot_results(shift_m, title="OMC Shifts LHC 2022", output_path="lhc_2022_shifts.pdf")
390+
# shift_m = manual_shifts(logbook_dir / "2022_lhc.md")
391+
# plot_results(shift_m, title="OMC Shifts LHC 2022", output_path="lhc_2022_shifts.pdf")
392392

393393
# 2023 ---------------------------------------------------------------------
394394

@@ -398,8 +398,8 @@ def plot_all_machines_in_year(
398398
# shift_c = calculate_shifts(logbook_dir / "2023_ps.md")
399399
# plot_results(shift_c, title="OMC Shifts PS 2023 (from Start/End)")
400400

401-
shift_m = manual_shifts(logbook_dir / "2023_lhc.md")
402-
plot_results(shift_m, title="OMC Shifts LHC 2023", output_path="lhc_2023_shifts.pdf")
401+
# shift_m = manual_shifts(logbook_dir / "2023_lhc.md")
402+
# plot_results(shift_m, title="OMC Shifts LHC 2023", output_path="lhc_2023_shifts.pdf")
403403

404404
# shift_m = manual_shifts(logbook_dir / "2023_ps.md")
405405
# plot_results(shift_m, title="OMC Shifts PS 2023", output_path="ps_2023_shifts.pdf")
@@ -409,8 +409,8 @@ def plot_all_machines_in_year(
409409

410410
# 2024 ---------------------------------------------------------------------
411411

412-
shift_m = manual_shifts(logbook_dir / "2024_lhc.md")
413-
plot_results(shift_m, title="OMC Shifts LHC 2024", output_path="lhc_2024_shifts.pdf")
412+
# shift_m = manual_shifts(logbook_dir / "2024_lhc.md")
413+
# plot_results(shift_m, title="OMC Shifts LHC 2024", output_path="lhc_2024_shifts.pdf")
414414

415415
# shift_m = manual_shifts(logbook_dir / "2024_lhc.md", shift_type="Commissioning")
416416
# plot_results(shift_m, title="OMC Shifts LHC 2024 (Commissioning)", output_path="lhc_2024_shifts_commish.pdf")
@@ -426,8 +426,10 @@ def plot_all_machines_in_year(
426426

427427
# shift_m = manual_shifts(logbook_dir / "2024_sps.md")
428428
# plot_results(shift_m, title="OMC Shifts SPS 2024", output_path="sps_2024_shifts.pdf")
429+
430+
# plot_all_machines_in_year(2023, additional={}, output_path="machines_2023.pdf")
429431

430-
# plot_all_machines_in_year(2024, {"leir": 19}, output_path="machines_2024.pdf")
432+
plot_all_machines_in_year(2024, {"leir": 9, "superkekb": 4}, output_path="machines_2024.pdf")
431433

432434

433435
plt.show()

0 commit comments

Comments
 (0)