189 lines
7.4 KiB
Python
189 lines
7.4 KiB
Python
import ch.psi.pshell.epics.Positioner as Positioner
|
|
import ch.psi.pshell.epics.ChannelDouble as ChannelDouble
|
|
import_py("CPython/hfitoff", "hfitoff")
|
|
import_py("CPython/extremum", "extremum")
|
|
|
|
dry_run = False
|
|
do_elog = True
|
|
#und = "SARUN15"
|
|
#scan = "AR_K"
|
|
if get_exec_pars().args: # args is set by callin process (Qt panel)
|
|
und = args[0]
|
|
scan = args[1]
|
|
if dry_run:
|
|
und = "STEST01"
|
|
scan = "AR_PHI"
|
|
|
|
gd_state_init = {}
|
|
if scan == "AR_K":
|
|
gd_state_init["SARFE10-PBPG050:ENERGY-SELECT"] = caget("SARFE10-PBPG050:ENERGY-SELECT")
|
|
gd_state_init["SARFE10-PBPG050:ENERGY"] = caget("SARFE10-PBPG050:ENERGY")
|
|
machine_ene = caget("SARUN:FELPHOTENE")
|
|
caput("SARFE10-PBPG050:ENERGY", machine_ene * 1000)
|
|
caput("SARFE10-PBPG050:ENERGY-SELECT", "USER")
|
|
x_channel = und + "-UIND030:K_SET" # use UPHS for pos ok -> UPHS slower (exception for SARUN15)
|
|
x_ok_channel = "SARUN15-UIND030:GAP-POS-OK" if und == "SARUN15" else und + "-UPHS060:GAP-POS-OK"
|
|
y_channel = "SARFE10-PBIG050-EVR0:CALCI"
|
|
elif scan == "AT_K":
|
|
gd_state_init["SATFE10-PEPG046:ENERGY-SELECT"] = caget("SATFE10-PEPG046:ENERGY-SELECT")
|
|
gd_state_init["SATFE10-PEPG046:ENERGY"] = caget("SATFE10-PEPG046:ENERGY")
|
|
machine_ene = caget("SATUN:FELPHOTENE")
|
|
caput("SATFE10-PEPG046:ENERGY", machine_ene * 1000)
|
|
caput("SATFE10-PEPG046:ENERGY-SELECT", "USER")
|
|
x_channel = und + "-UIND030:K_SET"
|
|
x_ok_channel = und + "-UIND030:RADIAL-POS-OK"
|
|
y_channel = "SATFE10-PEPG046-EVR0:CALCI"
|
|
elif scan == "AR_PHI":
|
|
x_channel = und + "-UPHS060:PHI_SET"
|
|
x_ok_channel = und + "-UPHS060:GAP-POS-OK"
|
|
y_channel = "SARFE10-PBIG050-EVR0:CALCI"
|
|
elif scan == "AT_PHI":
|
|
x_channel = und + "-UDLY060:PH-SHIFT-OP"
|
|
x_ok_channel = und + "-UDLY060:GAP-COMP-OP"
|
|
y_channel = "SATFE10-PEPG046-EVR0:CALCI"
|
|
if und == "STEST01" and scan == "AR_K":
|
|
y_channel = "STEST01:K-CALCI"
|
|
if und == "STEST01" and scan == "AR_PHI":
|
|
y_channel = "STEST01:PHI-CALCI"
|
|
if scan == "AR_K" or scan == "AT_K":
|
|
message_channel = und + ":K-SCAN-MESSAGE"
|
|
x0 = caget(x_channel)
|
|
start = x0 - 0.005
|
|
end = x0 + 0.005
|
|
step = 10
|
|
lat = 0.02
|
|
nb = 150
|
|
if scan == "AR_PHI" or scan == "AT_PHI":
|
|
message_channel = und + ":PHI-SCAN-MESSAGE"
|
|
start = -180
|
|
end = 180
|
|
step = 12
|
|
lat = 0.02
|
|
nb = 150
|
|
if scan == "AR_K" or scan == "AR_PHI":
|
|
gd_state_init["SARFE10-PBPG050:HAMP-X-HVS-STATUS"] = caget("SARFE10-PBPG050:HAMP-X-HVS-STATUS")
|
|
gd_state_init["SARFE10-PBPG050:HAMP-Y-HVS-STATUS"] = caget("SARFE10-PBPG050:HAMP-Y-HVS-STATUS")
|
|
caput("SARFE10-PBPG050:HAMP-X-HVS-STATUS", "OFF")
|
|
caput("SARFE10-PBPG050:HAMP-Y-HVS-STATUS", "OFF")
|
|
|
|
x_val = ChannelDouble(x_channel, x_channel)
|
|
x_val.initialize()
|
|
y_val = ChannelDouble(y_channel, y_channel)
|
|
y_val.initialize()
|
|
x_val0 = x_val.read()
|
|
y_averager = create_averager(y_val, nb, lat)
|
|
|
|
# pause scan when beam is down
|
|
def is_beam_ok():
|
|
mps_ma = int(caget("SIN-EMED-DTSA001:LEVEL1_MA.RVAL"))
|
|
mps_ar = int(caget("SIN-EMED-DTSA002:LEVEL1_AR.RVAL"))
|
|
mps_at = int(caget("SIN-EMED-DTSA003:LEVEL1_AT.RVAL"))
|
|
beam_ok = (mps_ma + mps_ar + mps_at == 3)
|
|
return beam_ok
|
|
|
|
def wait_beam():
|
|
if not is_beam_ok():
|
|
print("Waiting for beam...")
|
|
while not is_beam_ok():
|
|
time.sleep(0.5)
|
|
print("Beam ok")
|
|
|
|
# check mover position and wait for beam
|
|
def before():
|
|
time.sleep(1.0)
|
|
timeout = 15.0
|
|
start_time = time.time()
|
|
while (True):
|
|
mover_status = caget(x_ok_channel)
|
|
if mover_status=="OK" or mover_status=="True":
|
|
break
|
|
if time.time() - start_time > timeout:
|
|
raise Exception("mover timeout")
|
|
wait_beam()
|
|
|
|
# check for beam and update the plot dynamically
|
|
arr_x, arr_y = [],[]
|
|
def after(rec):
|
|
if not is_beam_ok():
|
|
print("Beam is down, invalidating record...")
|
|
rec.invalidate()
|
|
arr_x.append(rec.positions[0])
|
|
arr_y.append(rec.readables[0].mean)
|
|
caput("SF-SCAN-GLOBAL:X-ARRAY", to_array(arr_x, 'd'))
|
|
caput("SF-SCAN-GLOBAL:Y-ARRAY", to_array(arr_y, 'd'))
|
|
|
|
# scan and plot
|
|
try:
|
|
x_val.write(start)
|
|
time.sleep(5.0)
|
|
caput(message_channel, "scanning...")
|
|
caput("SF-SCAN-GLOBAL:FIT-X-ARRAY", to_array([0.0], 'd'))
|
|
caput("SF-SCAN-GLOBAL:FIT-Y-ARRAY", to_array([0.0], 'd'))
|
|
r = lscan(x_val, y_averager, start, end, step, latency=lat, before_read = before, after_read = after)
|
|
x_array = r.getPositions(0)
|
|
y_array = [val.mean for val in r.getReadable(0)]
|
|
y_array_error_mean = mean([val.stdev for val in r.getReadable(0)])
|
|
caput("SF-SCAN-GLOBAL:X-ARRAY", to_array(x_array, 'd'))
|
|
caput("SF-SCAN-GLOBAL:Y-ARRAY", to_array(y_array, 'd'))
|
|
try:
|
|
if scan == "AR_K" or scan == "AT_K":
|
|
x_max, y_max, fit_x, fit_y, R2 = extremum(x_array, y_array)
|
|
if scan == "AR_PHI" or scan == "AT_PHI":
|
|
fit_amplitude, fit_x_deg, fit_offset, x_max, fit_x, fit_y = hfitoff(y_array, x_array)
|
|
while x_max < -180:
|
|
x_max = x_max + 360
|
|
while x_max > 180:
|
|
x_max = x_max - 360
|
|
except:
|
|
raise Exception("Fit failure")
|
|
plt = plot(None, name="param scan")[0]
|
|
plt.getSeries(0).setData(to_array(x_array,'d'), to_array(y_array,'d'))
|
|
plt.getSeries(0).setPointSize(6)
|
|
plt.getSeries(0).setLinesVisible(False)
|
|
plt.addSeries(LinePlotSeries("fit"))
|
|
plt.getSeries(1).setData(fit_x, fit_y)
|
|
plt.getSeries(1).setPointsVisible(False)
|
|
plt.setLegendVisible(True)
|
|
caput(und + ":SCAN-CREST", x_max)
|
|
caput("SF-SCAN-GLOBAL:FIT-X-ARRAY", fit_x)
|
|
caput("SF-SCAN-GLOBAL:FIT-Y-ARRAY", fit_y)
|
|
signal_amplitude = max(fit_y) - min(fit_y)
|
|
signal_to_noise = signal_amplitude / y_array_error_mean if y_array_error_mean != 0 else 0
|
|
now = str(caget("SF-TIME:FULL-DATE"))
|
|
now = now[:16] if now[0].isdigit() else ""
|
|
message = now
|
|
if scan == "AR_K" or scan == "AT_K":
|
|
message = message + (" %.4f" % x_max)
|
|
if scan == "AR_PHI" or scan == "AT_PHI":
|
|
message = message + (" %.1f deg" % x_max)
|
|
message = message + " (snr: " + ("%.2f)" % signal_to_noise)
|
|
caput(message_channel, message)
|
|
finally:
|
|
if scan == "AR_K":
|
|
caput("SARFE10-PBPG050:ENERGY", gd_state_init["SARFE10-PBPG050:ENERGY"])
|
|
caput("SARFE10-PBPG050:ENERGY-SELECT", gd_state_init["SARFE10-PBPG050:ENERGY-SELECT"])
|
|
if scan == "AT_K":
|
|
caput("SATFE10-PEPG046:ENERGY", gd_state_init["SATFE10-PEPG046:ENERGY"])
|
|
caput("SATFE10-PEPG046:ENERGY-SELECT", gd_state_init["SATFE10-PEPG046:ENERGY-SELECT"])
|
|
if scan == "AR_K" or scan == "AR_PHI":
|
|
caput("SARFE10-PBPG050:HAMP-X-HVS-STATUS", gd_state_init["SARFE10-PBPG050:HAMP-X-HVS-STATUS"])
|
|
caput("SARFE10-PBPG050:HAMP-Y-HVS-STATUS", gd_state_init["SARFE10-PBPG050:HAMP-Y-HVS-STATUS"])
|
|
x_val.write(x_val0)
|
|
x_val.close()
|
|
y_val.close()
|
|
|
|
# Elog entry
|
|
if do_elog:
|
|
title = "Undulator scan " + und
|
|
log_msg = "Data file: " + get_exec_pars().path + "\n"
|
|
if scan == "AR_K" or scan == "AT_K":
|
|
log_msg = log_msg + "On-crest K: %0.4f" % x_max + "\n"
|
|
if scan == "AR_PHI" or scan == "AT_PHI":
|
|
log_msg = log_msg + "On-crest phase: %0.1f" % x_max + " deg\n"
|
|
log_msg = log_msg + "Scan quality: %0.2f" % signal_to_noise
|
|
attachments = get_plot_snapshots(size=(600,400))
|
|
elog(title, log_msg, attachments)
|
|
|
|
set_return([x_max, signal_to_noise])
|
|
|