changes as of 260909
This commit is contained in:
1 parent
661e055479
commit
5f0d1fddeb
15 files changed
+602
-316
No files matched your search
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+44
-9
@@ -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
|
||||
|
||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -0,0 +1,3 @@
|
||||
energy,scan,reason
|
||||
25400,gap,User abort.
|
||||
25400,mono_pitch_exception,User abort.
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user