changes as of 260909

This commit is contained in:
x10sa authored and perl_d committed 2026-10-20 16:07:54 +02:00
1 parent 661e055479
commit 5f0d1fddeb
15 files changed
+602 -316

No files matched your search

View File
File mode changed.
View File
File mode changed.
+44 -9
View File
@@ -55,8 +55,8 @@ aerotech:
deviceConfig:
prefix: http://mx-x10sa-queue-01:5234
deviceTags:
- motors
- aerotech
- motors
enabled: true
onFailure: buffer
readoutPriority: baseline
@@ -65,15 +65,15 @@ aerotech:
mount: 0
work: 0
x:
in: -8.1e-06
in: 0.05999397
out: -10
safe: -50
y:
mount: -0.0
work: -0.02600108
work: -0.02799609
z:
mount: 0
work: -0.00900383
work: -0.0090036
bcu_bpm1:
description: BCU BPM Channel 1
deviceClass: ophyd.EpicsSignalRO
@@ -302,7 +302,7 @@ bs_x:
onFailure: buffer
readoutPriority: baseline
userParameter:
in: 0.39119736
in: 0.2038985
bs_y:
description: Beamstop Y
deviceClass: ophyd_devices.EpicsMotor
@@ -314,7 +314,7 @@ bs_y:
onFailure: buffer
readoutPriority: baseline
userParameter:
in: 0.76699895
in: 0.9064885
bs_z:
description: Beamstop Z
deviceClass: ophyd_devices.EpicsMotor
@@ -330,7 +330,7 @@ bs_z:
max_blout: 70
min: 13
safe: 45.1
samp: 16.408
samp: 16.80557617
type: continuous
work_min: 20
bsf_f1_y:
@@ -444,7 +444,7 @@ coll_x:
onFailure: buffer
readoutPriority: baseline
userParameter:
in: 0.67471002
in: 0.68249115
coll_y:
description: Collimator Y
deviceClass: ophyd_devices.EpicsMotor
@@ -456,7 +456,7 @@ coll_y:
onFailure: buffer
readoutPriority: baseline
userParameter:
in: 39.02
in: 39.01884961
intermediate: 32
out: 20.002
park: 1
@@ -1322,6 +1322,29 @@ samcam_x:
onFailure: buffer
readOnly: true
readoutPriority: monitored
samcam_xcurs:
description: Sample Camera X Cursor
deviceClass: ophyd.EpicsSignal
deviceConfig:
auto_monitor: true
read_pv: X10SA-ES-MS:Stats5:CursorX
deviceTags:
- scam
enabled: true
onFailure: buffer
readoutPriority: baseline
samcam_xcursprof:
description: Sample Camera X Cursor Profile
deviceClass: ophyd.EpicsSignalRO
deviceConfig:
auto_monitor: true
read_pv: X10SA-ES-MS:Stats5:ProfileCursorX_RBV
deviceTags:
- scam
enabled: true
onFailure: buffer
readOnly: true
readoutPriority: monitored
samcam_xsig:
description: Sample Camera X Sigma
deviceClass: ophyd.EpicsSignalRO
@@ -1346,6 +1369,18 @@ samcam_y:
onFailure: buffer
readOnly: true
readoutPriority: monitored
samcam_ycursprof:
description: Sample Camera Y Cursor Profile
deviceClass: ophyd.EpicsSignalRO
deviceConfig:
auto_monitor: true
read_pv: X10SA-ES-MS:Stats5:ProfileCursorY_RBV
deviceTags:
- scam
enabled: true
onFailure: buffer
readOnly: true
readoutPriority: monitored
samcam_ysig:
description: Sample Camera Y Sigma
deviceClass: ophyd.EpicsSignalRO
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
+14 -14
View File
@@ -428,7 +428,7 @@ def fit_plothist(hindex: int, signal_name: str, model="gauss", ibg=0):
#########################
def fit_plot(data_x, data_y, model="gauss", ibg=1, silent=0,fitrange=0, fitclick=0):
def fit_plot(data_x, data_y, model="gauss", ibg=1, silent=0, iplot=1, fitrange=0, fitclick=0):
"""
Get data for a completed scan, gaussian, voigt or lorentzian fit,
default = gauss, plus linear background
@@ -507,16 +507,16 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, silent=0,fitrange=0, fitclic
g = model.fit(data_y, pars, x=data_x)
#####
if (iplot):
plt.ion()
plt.figure()
plt.plot(data_x, data_y, "*")
plt.plot(data_x, g.best_fit)
plt.xlabel("x-axis")
plt.ylabel("signal")
plt.show()
plt.ion()
plt.figure()
plt.plot(data_x, data_y, "*")
plt.plot(data_x, g.best_fit)
plt.xlabel("x-axis")
plt.ylabel("signal")
plt.show()
if fitclick:
if (fitclick*iplot):
print("Please define the x-range of the fit via click of graph")
print("First click for start: ")
x1 = plt.ginput(1)
@@ -1013,7 +1013,7 @@ def colliscan(direction: str, range=0.3, nsteps=30, stime=0.5, centre=1):
#####################
### SLITSCANS
#####################
def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0):
def slitscan(device_location: str, direction: str, range= 1, nsteps=50, centre=0):
"""
Slit scan, and possible centre
and plot all the results.
@@ -1024,7 +1024,7 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0
nsteps: default = 50
move to centre or not [0/1]
Example: slitscan("fe","h", 30, centre=1)
Example: slitscan("fe","h",1, 30, centre=1)
"""
@@ -1142,9 +1142,9 @@ def slitscan(device_location: str, direction: str, range: 1, nsteps=50, centre=0
data_y = s.scan.live_data.lu_bpmsum.lu_bpmsum.val
if mot.name == "fe_sl_xcen":
data_x = s.scan.live_data.fe_sxcen.fe_sxcen.val
data_x = s.scan.live_data.fe_sl_xcen.fe_sl_xcen.val
if mot.name == "fe_sl_ycen":
data_x = s.scan.live_data.fe_sycen.fe_sycen.val
data_x = s.scan.live_data.fe_sl_ycen.fe_sl_ycen.val
# BSF slits ================================
if mot.name == "bsf_sl_xcen":
data_x = s.scan.live_data.bsf_sl_xcen.bsf_sl_xcen.val
+86 -34
View File
@@ -97,7 +97,7 @@ def plot_harmon(e_start, e_end, h_no, pr_out=False):
plt.show()
def setu19(en, *harm_no, detune=0):
def setu19(en, *harm_no, detune=0, simul = 0):
"""
set the U19 to the gaps defined in Jul2025, or the "theoretical" ones for higher
harmonics
@@ -128,10 +128,10 @@ def setu19(en, *harm_no, detune=0):
harm = 9
elif 16 < en <= 19:
harm = 11
elif 19 < en <= 22:
elif 19 < en <= 22: ## 22
harm = 13
if en <= 22:
if (en <= 22 and harm <=13):
h = h_all[harm]
print(f"harmonics is {harm}.")
@@ -146,32 +146,41 @@ def setu19(en, *harm_no, detune=0):
# 29: 15, 17, 19
# 30: 19
##
if 23 < en <= 25:
n = 15
enorm = en / n
g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2])
elif 25 < en <= 29:
n = 17
enorm = en / n
g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2])
elif 29 < en:
n = 19
if (en > 22 and harm_no):
harm = int(harm_no[0])
print("Selected harmonics is:", harm)
n= harm
enorm = en / n
g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2])
else:
if 22 < en <= 25:
n = 15
enorm = en / n
g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2])
elif 25 < en <= 29:
n = 17
enorm = en / n
g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2])
elif 29 < en:
n = 19
enorm = en / n
g = exponential_func0(enorm, fitpar_u19[0], fitpar_u19[1], fitpar_u19[2])
print("Undulator has been ", g0, " mm")
if 4.5 <= g <= 20:
print("Moving Undulator gap to ", g, " mm")
else:
print("not a valid gap, do nothing")
if not simul:
print("Undulator has been ", g0, " mm")
if 4.5 <= g <= 20:
print("Moving Undulator gap to ", g, " mm")
else:
print("not a valid gap, do nothing")
if detune:
g = g * 0.996
print("moving to detuned gap value, slightly below max, about 0.15 % ")
if detune:
g = g * 0.996
print("moving to detuned gap value, slightly below max, about 0.15 % ")
# print("move disabled!!")
res = scans.umv(dev.id_gap, g, relative=False)
scans.umv(dev.id_gap, g, relative=False)
return
return g
##################################
@@ -305,9 +314,26 @@ def long_gscan(estart=6, end_en=30.5, g_low=4.5, g_high=9.0, nsteps=1000, sett =
return
def plottest(wname):
#wname="GapScan"
existing_docks = bec.gui.windows
if existing_docks.get(wname) is None:
dock_area = bec.gui.new(name=wname, geometry = [4000, 900, 700, 700])
wr = dock_area.new(bec.gui.available_widgets.Waveform, object_name="Plot")
mot = dev.id_gap
det = dev.lu_bpmsum
else:
dock_area = open_docks[wname]
wr= dock_area.Plot
wr.plot(device_x=mot, device_y=det) ## names first !
# wr.plot(x=mot.name,y=det.name) ### this comes later
wr.x_label = mot.name
wr.y_label = det.name
##################################
def gscan(centre=0, gomax=0, detune=0,sett=1):
def gscan(deltag = 0.05,centre=0, gomax=0, detune=0,sett=1, silent=0, iplot=1, isave=0):
"""
Scan the ID GAP and go
to the max of lu_bpm intensity
@@ -319,34 +345,58 @@ def gscan(centre=0, gomax=0, detune=0,sett=1):
"""
import time
dock_area = bec.gui.new(name="GapScan", geometry = [4000, 900, 700, 700])
wr = dock_area.new(bec.gui.available_widgets.Waveform)
wname="GapScan"
mot = dev.id_gap
det = dev.lu_bpmsum
det = dev.lu_bpmsum
existing_docks = bec.gui.windows
if existing_docks.get(wname) is None:
dock_area = bec.gui.new(name=wname, geometry = [4000, 900, 700, 700])
wr = dock_area.new(bec.gui.available_widgets.Waveform, object_name="Plot")
else:
dock_area = existing_docks[wname]
wr= dock_area.Plot
wr.clear_all()
wr.plot(device_x=mot, device_y=det) ## names first !
# wr.plot(x=mot.name,y=det.name) ### this comes later
wr.x_label = mot.name
wr.y_label = det.name
g0 = dev.id_gap.readback.get()
deltag = 0.05
#deltag = 0.05
steps = 30
resol = 2*deltag/steps
if resol < 0.002:
resol = 0.003
steps = round(2*deltag/resol)
start=-deltag
stop = deltag
print(f"Gap resol is {resol} mm ")
ds = scans.line_scan(dev.id_gap, -deltag, deltag, steps=steps, settling_time=sett,exp_time=0.5, relative=True)
if (g0-deltag < 4.5):
start=g0-4.5
ds = scans.line_scan(dev.id_gap, start, stop, steps=steps, settling_time=sett,exp_time=0.1, relative=True)
gap_data = ds.scan.live_data.id_gap.id_gap.val
bpm_data = ds.scan.live_data.lu_bpmsum.lu_bpmsum.val
gap_data=np.array(gap_data)
bpm_data = np.array(bpm_data)
if isave:
en = round(getenergy())
dirname = "/sls/x10sa/config/commissioning/Data/GapsFE_0p3/"
combined = np.column_stack((gap_data, bpm_data))
filename = dirname + "gap" + str(en)+"_"+str(g0*100)[0:3]+ ".txt"
with open(filename, "w") as f:
np.savetxt(f, combined, delimiter=",", fmt="%5f")
maxy = max(bpm_data)
indmax = np.argmax(bpm_data)
gm = gap_data[indmax]
gmax = gap_data[indmax]
gcen, xm = fit_plot(gap_data, bpm_data, model="voigt")
gcen, xm = fit_plot(gap_data, bpm_data, model="voigt", silent=silent, iplot=iplot)
if gomax:
gm = xm
@@ -354,6 +404,8 @@ def gscan(centre=0, gomax=0, detune=0,sett=1):
gm = gcen
print("gap off by ", g0 - gm, " mm")
print(f"gcen = {gcen}, gmax = {xm} or {gmax}")
if detune:
gm = gm * 0.996
print("moving to detuned gap value, slightly (0.15 %) below max")
@@ -366,4 +418,4 @@ def gscan(centre=0, gomax=0, detune=0,sett=1):
else:
print("Fit too far off, try using option gomax=1")
return
return gm, xm
+3
View File
@@ -454,6 +454,9 @@ def filter_results(results, statuses=None):
def run_check(show_all=False, scilog=False):
"""Check the status of beamline motors (must exist as devices in BEC).
For a full list of checked devices, use run_check(show_all=True).
Results will be logged in scilog if scilog=True"""
results = check2()
+376 -257
View File
@@ -1,4 +1,4 @@
""" Files needed for the daily setup routine for local contacts """
"""Files needed for the daily setup routine for local contacts"""
import time
from dataclasses import dataclass
@@ -19,6 +19,7 @@ class DailySetupContext:
messages: list
progress_state: dict
def daily_setup(
energy=12400,
*,
@@ -42,6 +43,8 @@ def daily_setup(
"Save new positions to BEC": save_positions,
}
results = {}
ctx = get_daily_setup_context(selected)
for task, enabled in selected.items():
@@ -52,29 +55,34 @@ def daily_setup(
try:
if set_energy:
run_daily_energy(energy,ctx)
results["Beamline energy"] = run_daily_energy(energy, ctx)
if move_beam:
run_daily_movebeam(ctx)
results["Move beam"] = run_daily_movebeam(ctx)
if align_beamstop:
run_daily_beamstop(ctx)
results["Align beamstop"] = run_daily_beamstop(ctx)
if measure_beampos:
run_daily_beampos(ctx)
results["Measure beam position"] = run_daily_beampos(ctx)
if align_collimator:
run_daily_collimator(ctx)
results["Align collimator"] = run_daily_collimator(ctx)
if measure_flux:
run_daily_flux(ctx)
results["Flux"] = run_daily_flux(ctx)
if save_positions:
run_save_positions(ctx)
log_daily_setup_to_scilog(bec,results)
return(results)
finally:
print("done")
# bl.planner.move_to(BeamlineState.SAMPLE_ALIGNMENT)
bl.planner.move_to(BeamlineState.ROBOT_SAMPLE_EXCHANGE)
def sanity_checks():
pass
def get_daily_setup_context(tasks=None):
"""Get widgets and state used by daily setup tasks."""
@@ -89,8 +97,8 @@ def get_daily_setup_context(tasks=None):
"Measure beam position",
"Align collimator",
"Measure flux",
"Save new positions to BEC"
]
"Save new positions to BEC",
]
return DailySetupContext(
plot1=plot1,
@@ -100,16 +108,11 @@ def get_daily_setup_context(tasks=None):
log=log,
progress=progress,
messages=[],
progress_state={
task: "todo"
for task in tasks
},
progress_state={task: "todo" for task in tasks},
)
def run_daily_energy(
energy,
ctx,
):
def run_daily_energy(energy, ctx):
"""Set and optimise beamline energy."""
task = "Set energy"
@@ -117,18 +120,27 @@ def run_daily_energy(
clear_daily_plots()
set_progress(ctx.progress, ctx.progress_state, task, "running")
daily_energy(energy, plot_widget=ctx.plot1)
en = daily_energy(energy, plot_widget=ctx.plot1)
result = {
"energy": en
}
update_log(
ctx.log,
ctx.messages,
f"Beamline energy is {get_current_energy():.5g} eV",
)
ctx.log,
ctx.messages,
format_energy_for_gui(result),
)
set_progress(ctx.progress, ctx.progress_state, task, "done")
return result
def format_energy_for_gui(result):
return f"Beamline energy {result['energy']:.0f} eV\n"
def run_daily_movebeam(ctx):
"""Move beam to the scintillator crosshair"""
task = "Move beam"
@@ -136,61 +148,24 @@ def run_daily_movebeam(ctx):
clear_daily_plots()
set_progress(ctx.progress, ctx.progress_state, task, "running")
move_result = daily_movebeam()
if move_result["success"]:
update_log(
ctx.log,
ctx.messages,
f"Beam position relative to crosshair: "
f"x = {move_result["BeamX"]:.2g} microns, "
f"y = {move_result["BeamY"]:.2g} microns."
)
result = daily_movebeam()
update_log(
ctx.log,
ctx.messages,
format_movebeam_for_gui(result),
)
set_progress(ctx.progress, ctx.progress_state, task, "done")
return result
def format_movebeam_for_gui(result):
if result["success"]:
return (f"Beam position relative to crosshair:\n"
f"Beam_X: {result["BeamX"]:.2g} microns, "
f"Beam_Y: {result["BeamY"]:.2g} microns.\n")
else:
update_log(
ctx.log,
ctx.messages,
"Moving beam to the crosshair failed"
)
set_progress(ctx.progress, ctx.progress_state, task, "done")
def run_daily_beampos(ctx):
"""Measure the beam position at the scintillator at Aare zoom levels"""
task = "Measure beam position"
set_progress(ctx.progress, ctx.progress_state, task, "running")
beampos_result = daily_beampos()
update_log(
ctx.log,
ctx.messages,
format_beam_positions(beampos_result),
)
def run_daily_collimator(ctx):
"""Align the collimator and save positions"""
task = "Align collimator"
set_progress(ctx.progress, ctx.progress_state, task, "running")
coll_result = daily_coll()
update_log(
ctx.log,
ctx.messages,
(
f"I1 intensity with collimator out: {coll_result['intensity_coll_out']:.2e}. "
f"Starting intensity with collimator in: {coll_result['start_intensity_coll_in']:.2e}. "
f"Intensity with collimator in after scans: {coll_result['final_intensity_coll_in']:.2e}. "
f"Collimator X: {coll_result['x_position']:.3f}, "
f"Collimator Y: {coll_result['y_position']:.3f}"
),
)
set_progress(ctx.progress, ctx.progress_state, task, "done")
return f"Moving beam to crosshaor failed"
def run_daily_beamstop(ctx):
@@ -201,41 +176,121 @@ def run_daily_beamstop(ctx):
# clear_daily_plots()
set_progress(ctx.progress, ctx.progress_state, task, "running")
bs_result = daily_beamstop()
# bs_result = {'x_position':20, 'y_position':3}
result = daily_beamstop()
update_log(
ctx.log,
ctx.messages,
(
"Beamstop centred: "
f"X={bs_result['x_position']:.4g}, "
f"Y={bs_result['y_position']:.4g}"
),
)
ctx.log,
ctx.messages,
format_beamstop_for_gui(result),
)
# save_current_position(dev.bs_x, "in")
# save_current_position(dev.bs_y, "in")
set_progress(ctx.progress, ctx.progress_state, task, "done")
return result
def run_daily_flux(ctx):
"""Measure the beam intensity using BCU BPM"""
def format_beamstop_for_gui(result):
return (
f"BS_X: {result['bs_x_pos']:.3g} mm, "
f"BS_Y: {result['bs_y_pos']:.3g} mm\n"
)
task = "Measure flux"
def run_daily_beampos(ctx):
"""Measure the beam position at the scintillator at Aare zoom levels"""
task = "Measure beam position"
set_progress(ctx.progress, ctx.progress_state, task, "running")
flux_result = bpm2flux()
beampos_result = daily_beampos()
update_log(
ctx.log,
ctx.messages,
(f"Intensity at current trasmission: {flux_result[0]:.2e}. "
f"Intensity at 100% transmission: {flux_result[1]:.2e}.")
format_beam_positions(beampos_result),
)
set_progress(ctx.progress, ctx.progress_state, task, "done")
return beampos_result
def format_beam_positions(pos_result):
"""Format camera beam positions for display."""
lines = [f"{'Zoom':<8} {'X / px':>10} {'Y / px':>10}", "-" * 30]
for zoom, pos in pos_result.items():
lines.append(f"{zoom:<8} {pos['x']:>10.1f} {pos['y']:>10.1f}")
return "\n".join(lines)
def run_daily_collimator(ctx):
"""Align the collimator and save positions"""
task = "Align collimator"
set_progress(ctx.progress, ctx.progress_state, task, "running")
result = daily_coll()
update_log(
ctx.log,
ctx.messages,
format_collimator_for_gui(result),
)
set_progress(ctx.progress, ctx.progress_state, task, "done")
return result
def format_collimator_for_gui(result):
"""Format collimator result for the Daily Setup GUI."""
return (
f"\nI1 intensity with collimator out: "
f"{result['intensity_coll_out']:.2e}\n"
f"Starting intensity with collimator in: "
f"{result['start_intensity_coll_in']:.2e}\n"
f"Intensity with collimator in after scans: "
f"{result['final_intensity_coll_in']:.2e}\n"
f"Scan Width X: {result['coll_x_width']:.3f} mm, "
f"Scan Width Y: {result['coll_y_width']:.3f} mm\n"
f"Coll_X: {result['coll_x_pos']:.3f} mm, "
f"Coll_Y: {result['coll_y_pos']:.3f} mm\n"
)
def run_daily_flux(ctx):
"""Measure the beam intensity using BCU BPM."""
task = "Measure flux"
set_progress(ctx.progress, ctx.progress_state, task, "running")
flux = bpm2flux()
result = {
"current_flux": flux[0],
"full_flux": flux[1],
}
update_log(
ctx.log,
ctx.messages,
format_flux_for_gui(result),
)
set_progress(ctx.progress, ctx.progress_state, task, "done")
return result
def format_flux_for_gui(result):
return (
f"Intensity at current transmission: "
f"{result['current_flux']:.2e} ph/s\n"
f"Intensity at 100% transmission: "
f"{result['full_flux']:.2e} ph/s"
)
def select_daily_setup_gui():
"""Return widgets belonging to the Daily Setup GUI."""
@@ -246,60 +301,38 @@ def select_daily_setup_gui():
gui = bec.gui.new(window_name)
# Row 1
log = gui.new(
widget="TextBox",
object_name="Info",
)
log = gui.new(widget="TextBox", object_name="Info")
progress = gui.new(
widget="TextBox",
object_name="Progress",
relative_to="Info",
where="right",
widget="TextBox", object_name="Progress", relative_to="Info", where="right"
)
# Row 2 - start a new full-width row
plot1 = gui.new(
widget="Waveform",
object_name="Beamstop_X",
where="bottom",
)
plot1 = gui.new(widget="Waveform", object_name="Plot_1", where="bottom")
plot2 = gui.new(
widget="Waveform",
object_name="Beamstop_Y",
relative_to="Beamstop_X",
where="right",
widget="Waveform", object_name="Plot_2", relative_to="Plot_1", where="right"
)
# Row 3 - start another full-width row
plot3 = gui.new(
widget="Waveform",
object_name="Collimator_X",
where="bottom",
)
plot3 = gui.new(widget="Waveform", object_name="Plot_3", where="bottom")
plot4 = gui.new(
widget="Waveform",
object_name="Collimator_Y",
relative_to="Collimator_X",
where="right",
widget="Waveform", object_name="Plot_4", relative_to="Plot_3", where="right"
)
gui.set_layout_ratios(
horizontal=[1, 1],
vertical=[1, 1, 1],
)
gui.set_layout_ratios(horizontal=[1, 1], vertical=[1, 1, 1])
else:
gui = open_windows[window_name]
plot1 = gui.Beamstop_X
plot2 = gui.Beamstop_Y
plot3 = gui.Collimator_X
plot4 = gui.Collimator_Y
plot1 = gui.Plot_1
plot2 = gui.Plot_2
plot3 = gui.Plot_3
plot4 = gui.Plot_4
log = gui.Info
progress = gui.Progress
return plot1, plot2, plot3, plot4, log, progress
def clear_daily_plots():
plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui()
plot1.clear_all()
@@ -308,52 +341,45 @@ def clear_daily_plots():
plot4.clear_all()
def update_log(log_box, messages, message):
"""Add new message to the daily setup log """
"""Add new message to the daily setup log"""
messages.append(message)
log_box.set_plain_text("\n".join(messages))
def update_progress(progress_box, progress_state):
""" Sets up the status icons for the progress tracker"""
"""Sets up the status icons for the progress tracker"""
status = {
"todo": "\u25CB",
"running": "\u25B6",
"todo": "\u25cb",
"running": "\u25b6",
"done": "\u2713",
"warning": "\u26A0",
"warning": "\u26a0",
"skipped": "–",
"failed": "\u2717",
}
text = "\n".join(
f"{status[state]} {label}"
for label, state in progress_state.items()
)
text = "\n".join(f"{status[state]} {label}" for label, state in progress_state.items())
progress_box.set_plain_text(text)
def set_progress(progress_box, progress_state, step, status):
"""Change the status of one step and update the display."""
progress_state[step] = status
update_progress(progress_box, progress_state)
def plot_daily_setup_scan(
motor_name,
signal_name,
plot="x",
title=None,
):
def plot_daily_setup_scan(motor_name, signal_name, plot="x", title=None):
"""Plot live scan data in one of the Daily Setup waveform widgets."""
plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui()
if plot.lower() == "beamstop_x":
if plot.lower() == "plot_1":
wf = plot1
elif plot.lower() == "beamstop_y":
wf = plot2
elif plot.lower() == "collimator_x":
elif plot.lower() == "plot_2":
wf = plot2
elif plot.lower() == "plot_3":
wf = plot3
elif plot.lower() == "collimator_y":
elif plot.lower() == "plot_4":
wf = plot4
else:
raise ValueError("plot must be 'x' or 'y'")
@@ -367,22 +393,23 @@ def plot_daily_setup_scan(
wf.x_label = motor_name
wf.y_label = signal_name
wf.plot(
device_x=motor_name,
device_y=signal_name,
)
wf.plot(device_x=motor_name, device_y=signal_name)
def daily_energy(energy, plot_widget=None):
""" Set the beamline to the required energy """
"""Set the beamline to the required energy"""
current_energy = get_current_energy()
if abs(energy - current_energy) > 1:
bl_energy(energy, window_name="DailySetup", plot_widget=plot_widget)
else:
gap_actual = dev.id_gap.position
gap_req = calc_gap(energy)
if abs(gap_actual-gap_req) > 0.05:
if abs(gap_actual - gap_req) > 0.05:
umv(dev.id_gap, gap_req)
mono_pitch_scan(window_name="DailySetup", plot_widget=plot_widget)
new_energy = get_current_energy()
return new_energy
def set_zoom(zoom):
"""Set sample camera zoom level."""
@@ -391,7 +418,8 @@ def set_zoom(zoom):
zoom = CameraZoom.from_label(zoom)
umv(dev.scam_zoom, zoom.position)
else:
umv(dev.scam_zoom, zoom)
umv(dev.scam_zoom, zoom)
def daily_beampos():
"""Measure beam positions at different zoom levels"""
@@ -409,7 +437,7 @@ def daily_beampos():
dev.bcu_shutter.put(1)
for zoom in CameraZoom:
print(F"Moving to {zoom.label}")
print(f"Moving to {zoom.label}")
umv(dev.scam_zoom, zoom.position)
# set autoexposure
@@ -417,31 +445,25 @@ def daily_beampos():
time.sleep(0.2)
# take readings
x = dev.samcam_x.read()['samcam_x']['value']
y = dev.samcam_y.read()['samcam_y']['value']
x = dev.samcam_x.read()["samcam_x"]["value"]
y = dev.samcam_y.read()["samcam_y"]["value"]
# append results
results[zoom.label] = {'x': x, 'y': y}
results[zoom.label] = {"x": x, "y": y}
print(f" {zoom.label}: x = {x:.4g}, y = {y:.4g}")
finally:
dev.bcu_shutter.put(0)
dev.bcu_shutter.put(0)
return results
def daily_coll():
"""Centre the collimator in X and Y using the I1 diode."""
plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui()
result = {
"success": False,
"intensity_coll_out": None,
"start_intensity_coll_in": None,
"final_intensity_coll_in": None,
"y_position": None,
"x_position": None,
}
result = {}
try:
if not bl.planner.is_state(BeamlineState.FLUX_MEASUREMENT):
@@ -452,6 +474,8 @@ def daily_coll():
time.sleep(0.2)
get_value(dev.i1)
result["intensity_coll_out"] = get_value(dev.i1)
print(f"Starting intensity is {result["intensity_coll_out"]:.3e}")
@@ -460,8 +484,7 @@ def daily_coll():
# Centre Y
result["start_intensity_coll_in"] = get_value(dev.i1)
print(
"Intensity with collimator in before scans: "
f"{result['start_intensity_coll_in']:.3e}"
"Intensity with collimator in before scans: " f"{result['start_intensity_coll_in']:.3e}"
)
y_result = find_feature(
@@ -476,8 +499,8 @@ def daily_coll():
plot_widget=plot4,
)
result["y_position"] = y_result["centre"]
result["y_width"] = y_result["width"]
result["coll_y_pos"] = y_result["centre"]
result["coll_y_width"] = y_result["width"]
# Centre X
@@ -493,13 +516,12 @@ def daily_coll():
plot_widget=plot3,
)
result["x_position"] = x_result["centre"]
result["coll_x_pos"] = x_result["centre"]
result["final_intensity_coll_in"] = get_value(dev.i1)
result["x_width"] = x_result["width"]
result["coll_x_width"] = x_result["width"]
print(
"Intensity with collimator in after scans: "
f"{result['final_intensity_coll_in']:.3e}"
"Intensity with collimator in after scans: " f"{result['final_intensity_coll_in']:.3e}"
)
result["success"] = True
@@ -509,41 +531,23 @@ def daily_coll():
finally:
dev.bcu_shutter.put(0)
def daily_beamstop():
"""Centre the beamstop against the detector
cover, i2"""
"""Centre the beamstop against the detector cover, i2"""
plot1, plot2, plot3, plot4, log, progress = select_daily_setup_gui()
result = {
# "success": False,
# "x_position": None,
"y_position": None,
"intensity after alignment": None
}
result = {}
dev.transm.put(EnergyDefaults.default_trans)
try:
# if not bl.planner.is_state(BeamlineState.BEAMSTOP_ALIGNMENT):
# bl.planner.move_to(BeamlineState.BEAMSTOP_ALIGNMENT)
# set_zoom('2x')
# auto_exposure('samcam', max_iter=20)
# bl.d['bl_pos'].move('out')
# bl.d['det_cov'].move('close')
# dev.bcu_shutter.put(1)
if not bl.planner.is_state(BeamlineState.DET_DIODE):
bl.planner.move_to(BeamlineState.DET_DIODE)
# set_zoom('2x')
# auto_exposure('samcam', max_iter=20)
# bl.d['bl_pos'].move('out')
bl.d['det_cov'].move('close')
bl.d["det_cov"].move("close")
dev.bcu_shutter.put(1)
time.sleep(0.2)
# Centre Y
@@ -570,21 +574,21 @@ def daily_beamstop():
1.2,
30,
feature="edge_offset",
offset = Beamstop.x_offset,
offset=Beamstop.x_offset,
relative=True,
confirm=False,
window_name="DailySetup",
plot_widget=plot1,
)
result["x_position"] = x_result["centre"]
result["y_position"] = y_result["centre"]
result["bs_x_pos"] = x_result["centre"]
result["bs_y_pos"] = y_result["centre"]
result["intensity after alignment"] = read_i2()
print(
"Intensity after Y scan: "
f"{result['intensity after alignment']:.4g}\n"
f"Centred position is {result["x_position"]:.5g}, {result["y_position"]:.5g}"
f"Centred position is {result["bs_x_pos"]:.5g}, {result["bs_y_pos"]:.5g}"
)
return result
@@ -592,12 +596,12 @@ def daily_beamstop():
finally:
dev.bcu_shutter.put(0)
def test_daily_movebeam(meas="scint", iterations=3):
vfm_start = get_value(dev.vfm_ydr)
hfm_start = get_value(dev.hfm_xd)
dev.transm.put(EnergyDefaults.default_trans)
if meas == "scint":
@@ -635,10 +639,7 @@ def test_daily_movebeam(meas="scint", iterations=3):
vfm_change = diff_y / BeamMove.scint_y_slope
new_vfm = current_vfm + vfm_change
print(
f"VFM: {current_vfm:.6f} -> {new_vfm:.6f} "
f"(change {vfm_change:+.6f})"
)
print(f"VFM: {current_vfm:.6f} -> {new_vfm:.6f} " f"(change {vfm_change:+.6f})")
beam_y_before = y
vfm_before = current_vfm
@@ -664,10 +665,7 @@ def test_daily_movebeam(meas="scint", iterations=3):
)
else:
print(
f"Y within tolerance ({diff_y:+.2f} px) "
"- no VFM move"
)
print(f"Y within tolerance ({diff_y:+.2f} px) " "- no VFM move")
# ----------------------------------------------------------
# HFM correction
@@ -685,18 +683,12 @@ def test_daily_movebeam(meas="scint", iterations=3):
hfm_change = diff_x / BeamMove.scint_x_slope
new_hfm = current_hfm + hfm_change
print(
f"HFM: {current_hfm:.6f} -> {new_hfm:.6f} "
f"(change {hfm_change:+.6f})"
)
print(f"HFM: {current_hfm:.6f} -> {new_hfm:.6f} " f"(change {hfm_change:+.6f})")
umv(dev.hfm_xd, new_hfm)
else:
print(
f"X within tolerance ({diff_x:+.2f} px) "
"- no HFM move"
)
print(f"X within tolerance ({diff_x:+.2f} px) " "- no HFM move")
# Final check
x, y = read_scintXY(CameraZoom.X12_5.position)
@@ -715,10 +707,10 @@ def test_daily_movebeam(meas="scint", iterations=3):
final_hfm = get_value(dev.hfm_xd)
print(
f"VFM: {vfm_start:.6f} -> {final_vfm:.6f}\n"
f"HFM: {hfm_start:.6f} -> {final_hfm:.6f}"
f"VFM: {vfm_start:.6f} -> {final_vfm:.6f}\n" f"HFM: {hfm_start:.6f} -> {final_hfm:.6f}"
)
def daily_movebeam(meas="scint", iterations=3):
"""
Move the beam onto the sample-camera crosshair using the VFM and HFM.
@@ -734,9 +726,7 @@ def daily_movebeam(meas="scint", iterations=3):
if meas != "scint":
raise ValueError(f"Unknown beam position measurement: {meas}")
result = {"success": None,
"BeamX": None,
"BeamY": None}
result = {"success": None, "BeamX": None, "BeamY": None}
# Starting mirror positions
vfm_start = get_value(dev.vfm_ydr)
@@ -752,8 +742,7 @@ def daily_movebeam(meas="scint", iterations=3):
max_move = 0.02 # mm
print(
f"Moving beam to scintillator crosshair\n"
f"Target: X={x_target:.1f}, Y={y_target:.1f} px"
f"Moving beam to scintillator crosshair\n" f"Target: X={x_target:.1f}, Y={y_target:.1f} px"
)
for i in range(iterations):
@@ -792,10 +781,7 @@ def daily_movebeam(meas="scint", iterations=3):
print("Beam alignment stopped.")
return False
umv(
dev.vfm_ydr,
current_vfm + vfm_change
)
umv(dev.vfm_ydr, current_vfm + vfm_change)
# Remeasure after VFM move since VFM may also affect X
x, y = read_scintXY(CameraZoom.X12_5.position)
@@ -819,10 +805,7 @@ def daily_movebeam(meas="scint", iterations=3):
print("Beam alignment stopped.")
return False
umv(
dev.hfm_xd,
current_hfm + hfm_change
)
umv(dev.hfm_xd, current_hfm + hfm_change)
# --------------------------------------------------------------
# Final verification
@@ -836,10 +819,7 @@ def daily_movebeam(meas="scint", iterations=3):
final_vfm = get_value(dev.vfm_ydr)
final_hfm = get_value(dev.hfm_xd)
success = (
abs(diff_x) <= tolerance
and abs(diff_y) <= tolerance
)
success = abs(diff_x) <= tolerance and abs(diff_y) <= tolerance
print(
f"\nFinal beam position: X={x:.2f}, Y={y:.2f} px\n"
@@ -851,10 +831,7 @@ def daily_movebeam(meas="scint", iterations=3):
if success:
print("Beam alignment successful.")
else:
print(
f"Beam is not within ±{tolerance:.1f} px after "
f"{iterations} corrections."
)
print(f"Beam is not within ±{tolerance:.1f} px after " f"{iterations} corrections.")
beamx = calc_scam_microns(diff_x, zoom=CameraZoom.X12_5.position)
beamy = calc_scam_microns(diff_y, zoom=CameraZoom.X12_5.position)
@@ -865,19 +842,161 @@ def daily_movebeam(meas="scint", iterations=3):
return result
def format_beam_positions(pos_result):
"""Format camera beam positions for display."""
lines = [
"Beam position",
"",
f"{'Zoom':<8} {'X / px':>10} {'Y / px':>10}",
"-" * 30,
]
for zoom, pos in pos_result.items():
lines.append(
f"{zoom:<8} {pos['x']:>10.1f} {pos['y']:>10.1f}"
# def format_daily_setup_result(result):
# """Create readable text for a daily setup result."""
# if result is None:
# return "completed"
# # Beam position dictionary
# if isinstance(result, dict):
# lines = []
# for key, value in result.items():
# if (
# isinstance(value, dict)
# and "x" in value
# and "y" in value
# ):
# lines.append(
# f"{key}: X={value['x']:.1f}, Y={value['y']:.1f}"
# )
# else:
# lines.append(f"{key}: {value}")
# return "\n".join(lines)
# return str(result)
# def build_daily_setup_log(results):
# """Build the text for a daily setup SciLog entry."""
# lines = ["PXII Daily Setup", ""]
# for step, result in results.items():
# lines.append(step)
# lines.append(format_daily_setup_result(result))
# lines.append("")
# return "\n".join(lines)
# def test_scilog():
# test_results = {
# "Set energy": "12.40 keV",
# "Align collimator": {
# "x": 39.042,
# "y": 12.376,
# },
# "Align beamstop": "completed",
# "Beam position": {
# "1x": {"x": 996.8, "y": 971.5},
# "2x": {"x": 999.9, "y": 971.3},
# "3x": {"x": 998.6, "y": 971.2},
# "5.8x": {"x": 998.4, "y": 972.5},
# "7.5x": {"x": 999.4, "y": 977.0},
# "12.5x": {"x": 995.2, "y": 976.0},
# },
# "Measure flux": "1.24e12 ph/s",
# }
# return test_results
def add_energy_to_scilog(msg, result):
msg.add_text("Energy: ", bold=True)
msg.add_text(f"{result['energy']:.0f} eV\n")
def add_flux_to_scilog(msg, result):
msg.add_text("Current transmission: ", bold=True)
msg.add_text(f"{result['current_flux']:.2e} ph/s\n")
msg.add_text("100% transmission: ", bold=True)
msg.add_text(f"{result['full_flux']:.2e} ph/s\n")
def add_movebeam_to_scilog(msg, result):
msg.add_text("Beam position relative to crosshair: \n", bold=True)
msg.add_text(f"Beam_X: {result['BeamX']:.3f} microns\n")
msg.add_text(f"Beam_Y: {result['BeamY']:.3f} microns\n")
def add_beamstop_to_scilog(msg, result):
msg.add_text("Beamstop X: ", bold=True)
msg.add_text(f"{result['bs_x_pos']:.3f} mm\n")
msg.add_text("Beamstop Y: ", bold=True)
msg.add_text(f"{result['bs_y_pos']:.3f} mm\n")
def add_collimator_to_scilog(msg, result):
msg.add_text("Collimator X: ", bold=True)
msg.add_text(f"{result['coll_x_pos']:.3f} mm\n")
msg.add_text("Collimator Y: ", bold=True)
msg.add_text(f"{result['coll_y_pos']:.3f} mm\n")
msg.add_text("X width: ", bold=True)
msg.add_text(f"{result['coll_x_width']:.3f} mm\n")
msg.add_text("Y width: ", bold=True)
msg.add_text(f"{result['coll_y_width']:.3f} mm\n")
def add_beampos_to_scilog(msg, result):
for zoom, pos in result.items():
msg.add_text(f"{zoom}: ", bold=True)
msg.add_text(
f"X={pos['x']:.1f} px, "
f"Y={pos['y']:.1f} px\n"
)
return "\n".join(lines)
def log_daily_setup_to_scilog(bec, results):
"""Send daily setup results to SciLog."""
scilog_formatters = {
"Beamline energy": add_energy_to_scilog,
"Move beam": add_movebeam_to_scilog,
"Align beamstop": add_beamstop_to_scilog,
"Measure beam position": add_beampos_to_scilog,
"Align collimator": add_collimator_to_scilog,
"Flux": add_flux_to_scilog,
}
msg = bec.messaging.scilog.new()
msg.add_text("PXII Daily Setup", bold=True)
msg.add_text("\n")
for step, result in results.items():
msg.add_text(f"\n{step}\n", bold=True)
formatter = scilog_formatters.get(step)
if formatter:
formatter(msg, result)
else:
msg.add_text(str(result))
msg.add_tags(["daily-setup", "pxii"])
msg.send()
def preview_daily_setup_scilog(results):
"""Preview the daily setup SciLog content without sending."""
print("\nPXII Daily Setup\n")
for step, result in results.items():
print(step)
if isinstance(result, dict):
for key, value in result.items():
if isinstance(value, dict) and "x" in value and "y" in value:
print(
f" {key}: "
f"X={value['x']:.1f}, "
f"Y={value['y']:.1f}"
)
else:
print(f" {key}: {value}")
else:
print(f" {result}")
print()
@@ -0,0 +1,65 @@
energy,harmonic,gap,pitch,samcam_x,samcam_y,zoom=800.0
6000,H3,5.9135,-5.5184,1011,987.4
6300,H3,6.1926,-5.5135,1006,988.6
6600,H3,6.4796,-5.5098,1014,991.3
6900,H3,6.7745,-5.5083,1006,988.3
7200,H3,7.0913,-5.506,1002,989.1
7500,H5,4.6331,-5.5042,1004,982.8
7800,H5,4.783,-5.502,1009,982.2
8100,H5,4.9292,-5.5005,1011,981.7
8400,H5,5.0802,-5.498,1019,978
8700,H5,5.2312,-5.4978,1011,979.4
9000,H5,5.3823,-5.4967,1011,979.2
9300,H5,5.5381,-5.4952,1013,977.1
9600,H5,5.697,-5.4944,1015,973.8
9900,H5,5.8558,-5.4934,1015,972.4
10200,H7,4.529,-5.4935,1010,968.3
10500,H7,4.6331,-5.4921,1010,970
10800,H7,4.7365,-5.4911,1010,969.1
11100,H7,4.8437,-5.4913,1006,969.5
11400,H7,4.9509,-5.4889,1019,968.7
11700,H7,5.0581,-5.4889,1012,967.4
12000,H7,5.1654,-5.489,1015,965.4
12300,H7,5.2726,-5.489,1011,968.2
12600,H7,5.3847,-5.488,1008,965.8
12900,H7,5.495,-5.4882,1005,967.8
13200,H9,4.5498,-5.4873,1013,964.4
13500,H9,4.6331,-5.4873,1010,965.8
13800,H9,4.7121,-5.4864,1014,963.7
14100,H9,4.7949,-5.4864,1008,963.5
14400,H9,4.8826,-5.4864,1008,964.7
14700,H9,4.9605,-5.4853,1013,963.3
15000,H9,5.0433,-5.4852,1011,963.9
15300,H9,5.1261,-5.4844,1013,964.9
15600,H9,5.2089,-5.4844,1012,964.2
15900,H9,5.2949,-5.4836,1012,965.6
16200,H11,4.565,-5.4838,1006,962.4
16500,H11,4.6331,-5.483,1012,964
16800,H11,4.6955,-5.483,1009,963
17100,H11,4.7631,-5.4821,1014,963.6
17400,H11,4.8308,-5.4819,1010,961.8
17700,H11,4.8984,-5.4822,1007,962
18000,H11,4.9661,-5.4824,1003,960.8
18300,H11,5.0337,-5.4811,1010,961.9
18600,H11,5.1014,-5.4811,1010,962
18900,H13,4.5186,-5.481,1006,960.6
19200,H13,4.5804,-5.4804,1007,960.3
19500,H13,4.6282,-5.4803,1012,960.7
19800,H13,4.6857,-5.48,1013,959.8
20100,H13,4.7407,-5.4803,1013,960
20400,H13,4.7993,-5.4802,1012,958.4
20700,H13,4.856,-5.4801,1013,958.4
21000,H13,4.9129,-5.48,1012,956.8
21300,H13,4.9746,-5.4798,1013,953.9
21600,H13,5.0313,-5.4795,1015,949.9
21900,H15,4.5338,-5.4796,1010,943.4
22200,H15,4.5812,-5.4795,1009,940
22500,H15,4.6331,-5.4773,1026,933.5
22800,H15,4.6764,-5.4796,1010,943
23100,H15,4.7355,-5.4795,1000,934.7
23400,H15,4.6169,-5.5042,990.5,936.9
23700,H15,4.8339,-5.4789,1001,933.7
24000,H15,4.7202,-5.4796,996.7,936.3
24300,H15,4.7823,-5.4789,996.7,936.3
24600,H15,4.809,-5.479,996.7,936.3
24900,H17,4.5417,-5.4789,999,944.1
1 energy,harmonic,gap,pitch,samcam_x,samcam_y,zoom=800.0
2 6000,H3,5.9135,-5.5184,1011,987.4
3 6300,H3,6.1926,-5.5135,1006,988.6
4 6600,H3,6.4796,-5.5098,1014,991.3
5 6900,H3,6.7745,-5.5083,1006,988.3
6 7200,H3,7.0913,-5.506,1002,989.1
7 7500,H5,4.6331,-5.5042,1004,982.8
8 7800,H5,4.783,-5.502,1009,982.2
9 8100,H5,4.9292,-5.5005,1011,981.7
10 8400,H5,5.0802,-5.498,1019,978
11 8700,H5,5.2312,-5.4978,1011,979.4
12 9000,H5,5.3823,-5.4967,1011,979.2
13 9300,H5,5.5381,-5.4952,1013,977.1
14 9600,H5,5.697,-5.4944,1015,973.8
15 9900,H5,5.8558,-5.4934,1015,972.4
16 10200,H7,4.529,-5.4935,1010,968.3
17 10500,H7,4.6331,-5.4921,1010,970
18 10800,H7,4.7365,-5.4911,1010,969.1
19 11100,H7,4.8437,-5.4913,1006,969.5
20 11400,H7,4.9509,-5.4889,1019,968.7
21 11700,H7,5.0581,-5.4889,1012,967.4
22 12000,H7,5.1654,-5.489,1015,965.4
23 12300,H7,5.2726,-5.489,1011,968.2
24 12600,H7,5.3847,-5.488,1008,965.8
25 12900,H7,5.495,-5.4882,1005,967.8
26 13200,H9,4.5498,-5.4873,1013,964.4
27 13500,H9,4.6331,-5.4873,1010,965.8
28 13800,H9,4.7121,-5.4864,1014,963.7
29 14100,H9,4.7949,-5.4864,1008,963.5
30 14400,H9,4.8826,-5.4864,1008,964.7
31 14700,H9,4.9605,-5.4853,1013,963.3
32 15000,H9,5.0433,-5.4852,1011,963.9
33 15300,H9,5.1261,-5.4844,1013,964.9
34 15600,H9,5.2089,-5.4844,1012,964.2
35 15900,H9,5.2949,-5.4836,1012,965.6
36 16200,H11,4.565,-5.4838,1006,962.4
37 16500,H11,4.6331,-5.483,1012,964
38 16800,H11,4.6955,-5.483,1009,963
39 17100,H11,4.7631,-5.4821,1014,963.6
40 17400,H11,4.8308,-5.4819,1010,961.8
41 17700,H11,4.8984,-5.4822,1007,962
42 18000,H11,4.9661,-5.4824,1003,960.8
43 18300,H11,5.0337,-5.4811,1010,961.9
44 18600,H11,5.1014,-5.4811,1010,962
45 18900,H13,4.5186,-5.481,1006,960.6
46 19200,H13,4.5804,-5.4804,1007,960.3
47 19500,H13,4.6282,-5.4803,1012,960.7
48 19800,H13,4.6857,-5.48,1013,959.8
49 20100,H13,4.7407,-5.4803,1013,960
50 20400,H13,4.7993,-5.4802,1012,958.4
51 20700,H13,4.856,-5.4801,1013,958.4
52 21000,H13,4.9129,-5.48,1012,956.8
53 21300,H13,4.9746,-5.4798,1013,953.9
54 21600,H13,5.0313,-5.4795,1015,949.9
55 21900,H15,4.5338,-5.4796,1010,943.4
56 22200,H15,4.5812,-5.4795,1009,940
57 22500,H15,4.6331,-5.4773,1026,933.5
58 22800,H15,4.6764,-5.4796,1010,943
59 23100,H15,4.7355,-5.4795,1000,934.7
60 23400,H15,4.6169,-5.5042,990.5,936.9
61 23700,H15,4.8339,-5.4789,1001,933.7
62 24000,H15,4.7202,-5.4796,996.7,936.3
63 24300,H15,4.7823,-5.4789,996.7,936.3
64 24600,H15,4.809,-5.479,996.7,936.3
65 24900,H17,4.5417,-5.4789,999,944.1
@@ -0,0 +1,2 @@
energy,harmonic,gap,pitch,samcam_x,samcam_y,zoom=800.0
25000,H17,4.5812,-5.4766,956.3,919.7
1 energy,harmonic,gap,pitch,samcam_x,samcam_y,zoom=800.0
2 25000,H17,4.5812,-5.4766,956.3,919.7
@@ -0,0 +1,7 @@
energy,scan,reason
23400,mono_pitch,Peak FWHM spans only 0.00 scan steps (minimum 1.5); centre uncertainty is large (0.000267)
24900,gap,An alarm has occurred. Severity: MAJOR.
ValueError.
An error occurred during 'set' on device 'id_gap'.
ValueError: 4.4999 outside of user-specified limits
1 energy,scan,reason
2 23400,mono_pitch,Peak FWHM spans only 0.00 scan steps (minimum 1.5); centre uncertainty is large (0.000267)
3 24900,gap,An alarm has occurred. Severity: MAJOR.
4 ValueError.
5 An error occurred during 'set' on device 'id_gap'.
6 ValueError: 4.4999 outside of user-specified limits
@@ -0,0 +1,3 @@
energy,scan,reason
25400,gap,User abort.
25400,mono_pitch_exception,User abort.
1 energy scan reason
2 25400 gap User abort.
3 25400 mono_pitch_exception User abort.
+2 -2
View File
@@ -201,7 +201,7 @@ class BPM_Y_Calibration:
# @dataclass(frozen=True)
class Beamstop:
x_offset = -0.65
x_offset = -0.55
class CameraZoom(Enum):
@@ -246,7 +246,7 @@ class BeamMove:
scint_target_y = 969
scint_x_slope = -19450
scint_y_slope = -37800
scint_tolerance = 10
scint_tolerance = 15