Skip to content

Commit fde6ae9

Browse files
committed
[TASK] plotting scripts drafted
1 parent d041ab8 commit fde6ae9

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

src/dt4acc/custom_epics/scripts/__init__.py

Whitespace-only changes.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from p4p.client.thread import Context
2+
import matplotlib.pyplot as plt
3+
import numpy as np
4+
import threading
5+
6+
# --- Configuration ---
7+
pv_base = "waheed:beam:twiss" # base name prefix
8+
update_interval = 0.2 # seconds
9+
10+
# PVs to monitor (relative to base)
11+
pv_names = [
12+
"x:alpha", "x:beta", "x:nu",
13+
"y:alpha", "y:beta", "y:nu",
14+
]
15+
16+
# --- Data structures ---
17+
ctx = Context("pva")
18+
latest = {pv: None for pv in pv_names}
19+
subs = {}
20+
lock = threading.Lock()
21+
22+
# --- Callback factory ---
23+
def make_callback(pv):
24+
def _cb(value):
25+
with lock:
26+
try:
27+
arr = np.array(value["value"], dtype=float)
28+
except Exception:
29+
arr = np.array(value, dtype=float)
30+
latest[pv] = arr
31+
return _cb
32+
33+
# --- Subscribe to all PVs ---
34+
for pv in pv_names:
35+
full = f"{pv_base}:{pv}"
36+
subs[pv] = ctx.monitor(full, make_callback(pv))
37+
print(f"Subscribed to {full}")
38+
39+
# --- Plot setup ---
40+
plt.ion()
41+
fig, axes = plt.subplots(len(pv_names), 1, figsize=(8, 12), sharex=False)
42+
lines = {}
43+
44+
for ax, pv in zip(axes, pv_names):
45+
(line,) = ax.plot([], [], lw=1.3)
46+
ax.set_title(pv)
47+
ax.set_ylabel("Value")
48+
ax.grid(True)
49+
lines[pv] = (ax, line)
50+
51+
axes[-1].set_xlabel("Index")
52+
fig.suptitle(f"{pv_base}:* (live monitor)", fontsize=14)
53+
fig.tight_layout(rect=[0, 0, 1, 0.97])
54+
55+
# --- Live update loop ---
56+
print("Monitoring all PVs... close the figure to stop.")
57+
try:
58+
while plt.fignum_exists(fig.number):
59+
updated = False
60+
with lock:
61+
for pv, arr in latest.items():
62+
if arr is not None and len(arr) > 0:
63+
ax, line = lines[pv]
64+
x = np.arange(len(arr))
65+
line.set_data(x, arr)
66+
ax.relim()
67+
ax.autoscale_view()
68+
updated = True
69+
if updated:
70+
plt.pause(update_interval)
71+
else:
72+
plt.pause(0.1)
73+
74+
except KeyboardInterrupt:
75+
pass
76+
finally:
77+
for s in subs.values():
78+
s.close()
79+
ctx.close()
80+
print("Stopped monitoring.")
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from p4p.client.thread import Context
2+
import matplotlib.pyplot as plt
3+
import numpy as np
4+
import threading
5+
6+
# --- Configuration ---
7+
pv_x = "waheed:beam:twiss:x:beta"
8+
pv_y = "waheed:beam:twiss:y:beta"
9+
update_interval = 0.1 # seconds
10+
11+
# --- Shared data ---
12+
latest_x = None
13+
latest_y = None
14+
lock = threading.Lock()
15+
16+
# --- P4P context ---
17+
ctx = Context("pva")
18+
19+
def on_update_x(value):
20+
global latest_x
21+
with lock:
22+
try:
23+
latest_x = np.array(value["value"], dtype=float)
24+
except Exception:
25+
latest_x = np.array(value, dtype=float)
26+
27+
def on_update_y(value):
28+
global latest_y
29+
with lock:
30+
try:
31+
latest_y = np.array(value["value"], dtype=float)
32+
except Exception:
33+
latest_y = np.array(value, dtype=float)
34+
35+
# Subscribe to both PVs
36+
sub_x = ctx.monitor(pv_x, on_update_x)
37+
sub_y = ctx.monitor(pv_y, on_update_y)
38+
39+
# --- Matplotlib setup ---
40+
plt.ion()
41+
fig, ax = plt.subplots()
42+
(line_x,) = ax.plot([], [], label="x plane", lw=1.5)
43+
(line_y,) = ax.plot([], [], label="y plane", lw=1.5)
44+
ax.set_title("waheed:beam:twiss:beta (x & y live)")
45+
ax.set_xlabel("Index")
46+
ax.set_ylabel(r"$\beta_{x, y}$")
47+
ax.legend()
48+
ax.grid(True)
49+
50+
print(f"Monitoring:\n {pv_x}\n {pv_y}\n(close the window to stop)")
51+
52+
try:
53+
while plt.fignum_exists(fig.number):
54+
with lock:
55+
updated = False
56+
if latest_x is not None:
57+
x_axis = np.arange(len(latest_x))
58+
line_x.set_data(x_axis, latest_x)
59+
updated = True
60+
if latest_y is not None:
61+
y_axis = np.arange(len(latest_y))
62+
line_y.set_data(y_axis, latest_y)
63+
updated = True
64+
65+
if updated:
66+
ax.relim()
67+
ax.autoscale_view()
68+
69+
plt.pause(update_interval)
70+
71+
except KeyboardInterrupt:
72+
pass
73+
finally:
74+
sub_x.close()
75+
sub_y.close()
76+
ctx.close()
77+
print("Stopped monitoring.")

0 commit comments

Comments
 (0)