This commit is contained in:
@@ -92,6 +92,7 @@ states:
|
||||
coll_y: park
|
||||
cryo_pos: in
|
||||
det_cov: 'close'
|
||||
det_z: 'mse'
|
||||
diag_y: park
|
||||
fl_bright: 'off'
|
||||
aerotech_x: in
|
||||
|
||||
@@ -433,8 +433,6 @@ coll_x:
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 0.0
|
||||
coll_y:
|
||||
description: Collimator Y
|
||||
deviceClass: ophyd_devices.EpicsMotor
|
||||
@@ -446,9 +444,9 @@ coll_y:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 40.834
|
||||
in: 39.393
|
||||
intermediate: 32
|
||||
out: 19.0
|
||||
out: 20.002
|
||||
park: 1
|
||||
tol: 0.05
|
||||
type: continuous
|
||||
@@ -614,6 +612,9 @@ det_z:
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
mse: 800
|
||||
vis: 1198
|
||||
diag_y:
|
||||
description: Scintillator/diode Y
|
||||
deviceClass: ophyd_devices.EpicsMotor
|
||||
@@ -625,10 +626,10 @@ diag_y:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
i1: 43.4
|
||||
i1: 41
|
||||
out: 20.0
|
||||
park: 1
|
||||
scint: 38.0
|
||||
scint: 36.004
|
||||
tol: 0.3
|
||||
type: continuous
|
||||
diag_z:
|
||||
@@ -1287,6 +1288,18 @@ samcam_ysig:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: monitored
|
||||
samcam_ecc:
|
||||
description: Sample Camera Eccentricity
|
||||
deviceClass: ophyd.EpicsSignalRO
|
||||
deviceConfig:
|
||||
auto_monitor: true
|
||||
read_pv: X10SA-ES-MS:Stats5:Eccentricity_RBV
|
||||
deviceTags:
|
||||
- scam
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: monitored
|
||||
scam_zoom:
|
||||
description: Sample Camera Zoom
|
||||
deviceClass: ophyd_devices.EpicsMotor
|
||||
@@ -1757,6 +1770,48 @@ vfm_yw:
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
xi_focus:
|
||||
description: Xeye Zoom
|
||||
deviceClass: ophyd_devices.EpicsMotor
|
||||
deviceConfig:
|
||||
prefix: X10SA-ES-XEYE:FOCUS
|
||||
deviceTags:
|
||||
- xeye
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
xi_x:
|
||||
description: Xeye X
|
||||
deviceClass: ophyd_devices.EpicsMotor
|
||||
deviceConfig:
|
||||
prefix: X10SA-ES-XEYE:TRX
|
||||
deviceTags:
|
||||
- xeye
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
xi_zoom:
|
||||
description: Xeye Zoom
|
||||
deviceClass: ophyd_devices.EpicsMotor
|
||||
deviceConfig:
|
||||
prefix: X10SA-ES-XEYE:ZOOM
|
||||
deviceTags:
|
||||
- xeye
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
xidiode:
|
||||
description: Xeye Diode
|
||||
deviceClass: ophyd.EpicsSignalRO
|
||||
deviceConfig:
|
||||
auto_monitor: true
|
||||
read_pv: X10SA-ES-XEYEDI:READOUT
|
||||
deviceTags:
|
||||
- xeye
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: monitored
|
||||
xrf_pos:
|
||||
description: XRF Positioner
|
||||
deviceClass: ophyd.EpicsSignal
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import numpy as np
|
||||
import math
|
||||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
|
||||
|
||||
################################
|
||||
@@ -312,9 +313,9 @@ def justfit(data_x, data_y, model="gauss", ibg=0):
|
||||
# diagnostics
|
||||
# print(f'Gfit: {g.params}')
|
||||
|
||||
print(f'Center of {model} fit: {g.params["center"].value:.5f}')
|
||||
print(f'Sigma: {g.params["sigma"].value:.5f}')
|
||||
print(f'FWHM: {g.params["fwhm"].value:.5f}')
|
||||
print(f'Center of {model} fit: {g.pars["center"].value:.5f}')
|
||||
print(f'Sigma: {g.pars["sigma"].value:.5f}')
|
||||
print(f'FWHM: {g.pars["fwhm"].value:.5f}')
|
||||
print(f"Position of maximum: {xm}")
|
||||
|
||||
return g, xm
|
||||
@@ -361,7 +362,7 @@ def fit_plothist(hindex: int, signal_name: str, model="gauss", ibg=0):
|
||||
plt.ylabel(signal_name)
|
||||
plt.show()
|
||||
|
||||
gcen = g.params["center"].value
|
||||
gcen = g.pars["center"].value
|
||||
|
||||
return gcen, xm, data_x, data_y
|
||||
|
||||
@@ -498,14 +499,14 @@ def fit_plot(data_x, data_y, model="gauss", ibg=1, fitrange=0, fitclick=0):
|
||||
|
||||
fit_id = pre+'_center'
|
||||
|
||||
center = g.params[fit_id].value
|
||||
center = g.pars[fit_id].value
|
||||
return center, xm
|
||||
|
||||
|
||||
####################################
|
||||
### just SAVE DATA
|
||||
####################################
|
||||
def save_data(hindex: int, device_name: str, signal_name: str):
|
||||
def save_data(hindex: int, device_name: str, signal_name: str, isave = 1):
|
||||
"""
|
||||
Get data for a completed scan from the BEC history,
|
||||
and plot all the results, store in a CSV file
|
||||
@@ -532,15 +533,16 @@ def save_data(hindex: int, device_name: str, signal_name: str):
|
||||
plt.ylabel(f"{signal_name} / AU")
|
||||
|
||||
plt.show()
|
||||
ans = "n"
|
||||
ans = input("Store data in csv file? y/n ")
|
||||
if ans == "y":
|
||||
dirname = "/sls/x10sa/config/commissioning/Data/"
|
||||
# writing output to simple data file for later analysis:
|
||||
combined = np.column_stack((data_x, data_y))
|
||||
filename = dirname + "Scan" + str(hindex) + device_name + ".txt"
|
||||
with open(filename, "w") as f:
|
||||
np.savetxt(f, combined, delimiter=",", fmt="%5f")
|
||||
if isave:
|
||||
ans = "n"
|
||||
ans = input("Store data in csv file? y/n ")
|
||||
if ans == "y":
|
||||
dirname = "/sls/x10sa/config/commissioning/Data/"
|
||||
# writing output to simple data file for later analysis:
|
||||
combined = np.column_stack((data_x, data_y))
|
||||
filename = dirname + "Scan" + str(hindex) + device_name + ".txt"
|
||||
with open(filename, "w") as f:
|
||||
np.savetxt(f, combined, delimiter=",", fmt="%5f")
|
||||
|
||||
return data_x, data_y
|
||||
|
||||
@@ -1319,7 +1321,8 @@ def detxeye_out():
|
||||
|
||||
|
||||
def measure_samcam(zoom=1000):
|
||||
scinti_inpos = 38.6 # mm
|
||||
import sys
|
||||
scinti_inpos = 36.4 # mm
|
||||
sc_rb = dev.diag_y.user_readback.get()
|
||||
if abs(scinti_inpos - sc_rb) > 0.3:
|
||||
print("Scinti not in, please move")
|
||||
|
||||
@@ -214,19 +214,22 @@ def gap_harm(e=12.4):
|
||||
|
||||
# test with estart = 6, end_en = 7.5 # should be 3 files , estimated time: 90 min
|
||||
|
||||
def long_gscan(estart=7, end_en=20.5, g_low=4.5, g_high=9.0, nsteps=1500):
|
||||
def long_gscan(estart=6, end_en=30.5, g_low=4.5, g_high=9.0, nsteps=1500):
|
||||
import time
|
||||
import numpy as np
|
||||
|
||||
dirname = "/sls/x10sa/config/commissioning/Data/"
|
||||
|
||||
enstep = 0.5
|
||||
enstep = 1.0
|
||||
|
||||
print(
|
||||
f"scanning the U19 gap from {estart} keV to {end_en} keV, for a gapsize from {g_low} to {g_high} in {enstep} keV energy intervals"
|
||||
)
|
||||
resol = (g_high - g_low) / nsteps
|
||||
print(f"nsteps = {nsteps}; resolution is {resol} mm")
|
||||
fe_h_size0 = dev.fe_sl_xsize.user_readback.get()
|
||||
fe_v_size0 = dev.fe_sl_ysize.user_readback.get()
|
||||
umv(dev.fe_sl_xsize, 0.5)
|
||||
umv(dev.fe_sl_ysize, 0.3)
|
||||
|
||||
dock_area = bec.gui.new("LongGapScan", geometry = [4000, 900, 1200, 700])
|
||||
wr = dock_area.new(bec.gui.available_widgets.Waveform)
|
||||
mot = dev.id_gap
|
||||
@@ -248,10 +251,16 @@ def long_gscan(estart=7, end_en=20.5, g_low=4.5, g_high=9.0, nsteps=1500):
|
||||
en = estart
|
||||
|
||||
while en < end_en:
|
||||
if en >= 17:
|
||||
nsteps = 1000
|
||||
g_high = 7.5
|
||||
#sete(en)
|
||||
#time.sleep(0.2)
|
||||
#rock()
|
||||
# maybe use
|
||||
resol = (g_high - g_low) / nsteps
|
||||
print(f"nsteps = {nsteps}; resolution is {resol} mm")
|
||||
|
||||
bl_energy(en, move_gap = False, plot = False)
|
||||
|
||||
print(f"setting energy to {en}")
|
||||
@@ -288,6 +297,12 @@ def long_gscan(estart=7, end_en=20.5, g_low=4.5, g_high=9.0, nsteps=1500):
|
||||
elapsed_time = time.perf_counter()-tstart
|
||||
print(f"Runtime: {elapsed_time: .6f} seconds, i.e., {elapsed_time: .6f}/60 min")
|
||||
|
||||
# moving slits back
|
||||
umv(dev.fe_sl_xsize, fe_h_size0)
|
||||
umv(dev.fe_sl_ysize, fe_v_size0)
|
||||
# move back to standard En
|
||||
bl_energy(12400)
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ class StateChangePlanner:
|
||||
after = self.get_positions()
|
||||
return {k: (before[k], after[k]) for k in before if before[k] != after[k]}
|
||||
|
||||
def get_closest_states(self):
|
||||
def __get_closest_states(self):
|
||||
"""
|
||||
Return states ordered by number of mismatches.
|
||||
"""
|
||||
@@ -161,7 +161,7 @@ class StateChangePlanner:
|
||||
|
||||
def closest_states(self, n=5):
|
||||
|
||||
for state, count, mismatches in self.get_closest_states()[:n]:
|
||||
for state, count, mismatches in self.__get_closest_states()[:n]:
|
||||
|
||||
print(f"\n{state}: {count} mismatch(es)")
|
||||
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
import numpy as np
|
||||
import math, time
|
||||
import matplotlib.pyplot as plt
|
||||
import scipy
|
||||
#########################################
|
||||
### just retrieve the saved data from csv
|
||||
########################################
|
||||
def read_data(filename: str):
|
||||
"""
|
||||
Get data stored in a CSV file
|
||||
|
||||
Args:
|
||||
filename (str): the csv file, eg, of a Scan
|
||||
e.g., dat = read_data("/home/e18747/SLS2/Data/gaps/gaps10.txt")
|
||||
"""
|
||||
|
||||
# dirname = '/home/gac-x10sa/Data/'
|
||||
# read output to simple data file for later analysis:
|
||||
|
||||
with open(filename, "r") as f:
|
||||
combined_data = np.loadtxt(f, delimiter=",") # no header and fmt for load
|
||||
|
||||
rows, cols = combined_data.shape
|
||||
|
||||
print("No of Rows =", rows)
|
||||
print("No of Colums =", cols)
|
||||
ind1 = 0
|
||||
ind2 = 1
|
||||
if cols > 2:
|
||||
print(
|
||||
"only first 2 colums (data[:, 0] and data[:, 1]) are plotted, please consider the other columns as well!"
|
||||
)
|
||||
index1 = 0
|
||||
index2 = 1
|
||||
index1, index2 = input(
|
||||
"please enter the columns to be plotted vs first one [eg: 1,2] : "
|
||||
).split(",")
|
||||
ind1 = int(index1)
|
||||
ind2 = int(index2)
|
||||
|
||||
if ind2 > cols - 1:
|
||||
print(" no valid index")
|
||||
|
||||
data_x = combined_data[:, ind1]
|
||||
data_y = combined_data[:, ind2]
|
||||
|
||||
plt.ion()
|
||||
plt.figure()
|
||||
plt.plot(data_x, data_y, ".")
|
||||
|
||||
plt.title(f"Scan from {filename}")
|
||||
plt.xlabel(f"data column {ind1}")
|
||||
plt.ylabel(f"data column {ind2}")
|
||||
|
||||
plt.show()
|
||||
|
||||
return combined_data
|
||||
|
||||
|
||||
def gaussfit(x,y,p):
|
||||
# define a gaussian fitting function where
|
||||
# p[0] = amplitude
|
||||
# p[1] = mean
|
||||
# p[2] = sigma
|
||||
# p[3] = const offset
|
||||
|
||||
fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2))+p[3]
|
||||
#fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2))
|
||||
errfct = lambda p, x0,y0: fitfct(p,x0)-y0
|
||||
|
||||
# guess fit parameters
|
||||
ind0 = np.where(y==max(y))[0]
|
||||
p0=np.c_[max(y), x[ind0], np.std(y), np.mean(y[0:5])]
|
||||
#p0=scipy.c_[max(y), np.where(y==max(y))[0], np.std(y)]
|
||||
# array generation [[]], and taking only one dimens
|
||||
# fit a gaussian to the correlation function
|
||||
|
||||
#print('p0 = ' , p0)
|
||||
p1, success = scipy.optimize.leastsq(errfct, p0.copy()[0],
|
||||
args=(x,y))
|
||||
|
||||
#plt.figure()
|
||||
bestfit=fitfct(p1,x)
|
||||
#print('************************', x,y)
|
||||
plt.plot(x,y,'r*')
|
||||
plt.plot(x,bestfit,'r-')
|
||||
|
||||
# different fit fct
|
||||
#popt, pcov = curve_fit(fitfct, x, y)
|
||||
#newfit=fitfct(popt,x)
|
||||
#plt.plot(x,newfit,'g+')
|
||||
|
||||
|
||||
plt.show()
|
||||
|
||||
return bestfit, p1
|
||||
|
||||
def scan_fe_sl():
|
||||
fe_v_size0 = dev.fe_sl_ysize.user_readback.get()
|
||||
umv(dev.fe_sl_xsize, 0.1)
|
||||
s = scans.line_scan(dev.fe_sl_ycen,-1,1, exp_time=02., steps=21, relative=True)
|
||||
time.sleep(0.1)
|
||||
umv(dev.fe_sl_xsize, fe_v_size0)
|
||||
|
||||
def mirrh():
|
||||
|
||||
#dat_ss = read_data("/home/anuschka/SS_pitch2p94.csv")
|
||||
#dat_bcu = read_data("/home/anuschka/BCU_pitch2p94.csv")
|
||||
|
||||
scan_fe_sl()
|
||||
ind = -1
|
||||
dat_ss = save_data(ind, 'fe_sl_ycen', 'ss_bpmsum', isave = 0)
|
||||
dat_bcu = save_data(ind, 'fe_sl_ycen', 'bcu_bpmsum', isave = 0)
|
||||
|
||||
|
||||
data_xs = dat_ss[0] # csv would be: dat_ss[:, 0]
|
||||
data_ys = dat_ss[1]
|
||||
|
||||
data_xb = dat_bcu[0]
|
||||
data_yb = dat_bcu[1]
|
||||
|
||||
#plt.figure()
|
||||
|
||||
#plt.plot(data_xs, data_ys, "*")
|
||||
#plt.plot(data_xb, data_yb, "+")
|
||||
|
||||
data_ys_norm = data_ys/max(data_ys)
|
||||
data_yb_norm = data_yb/max(data_yb)
|
||||
|
||||
plt.figure()
|
||||
|
||||
plt.plot(data_xs, data_ys_norm, "*")
|
||||
plt.plot(data_xb, data_yb_norm, "+")
|
||||
|
||||
|
||||
y= data_ys_norm
|
||||
xm = np.where(y==max(y))[0]
|
||||
xmi = data_xs[xm]
|
||||
#print('xm, xmi', xm, xmi)
|
||||
|
||||
pf1 = [1, xmi , np.std(data_ys_norm),0]
|
||||
fit_s, ps = gaussfit(data_xs,data_ys_norm, pf1)
|
||||
|
||||
y= data_yb_norm
|
||||
xm = np.where(y==max(y))[0]
|
||||
xmi = data_xb[xm]
|
||||
#print('xm, xmi', xm, xmi)
|
||||
|
||||
pf2 = [1, xmi, np.std(data_yb_norm),-11]
|
||||
fit_b, pb = gaussfit(data_xb,data_yb_norm, pf2)
|
||||
|
||||
|
||||
plt.figure()
|
||||
|
||||
plt.plot(data_xs, fit_s-ps[3], "*")
|
||||
plt.plot(data_xs, fit_s-ps[3])
|
||||
plt.plot(data_xb, fit_b-pb[3], "+")
|
||||
plt.plot(data_xb, fit_b-pb[3])
|
||||
|
||||
print('Fit Params of First BPM, SS, ps', ps)
|
||||
print('Fit Params of Second BPM, BCU, pb', pb)
|
||||
print()
|
||||
if abs(ps[1]-pb[1]) > 0.05:
|
||||
print('***** WARNING ******, mirror height not ok')
|
||||
if abs(ps[2]-pb[2]) > 0.05:
|
||||
print('***** WARNING ******, mirror not catching full beam')
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
import numpy as np
|
||||
import math
|
||||
import matplotlib.pyplot as plt
|
||||
import scipy
|
||||
#########################################
|
||||
### just retrieve the saved data from csv
|
||||
########################################
|
||||
def read_data(filename: str):
|
||||
"""
|
||||
Get data stored in a CSV file
|
||||
|
||||
Args:
|
||||
filename (str): the csv file, eg, of a Scan
|
||||
e.g., dat = read_data("/home/e18747/SLS2/Data/gaps/gaps10.txt")
|
||||
"""
|
||||
|
||||
# dirname = '/home/gac-x10sa/Data/'
|
||||
# read output to simple data file for later analysis:
|
||||
|
||||
with open(filename, "r") as f:
|
||||
combined_data = np.loadtxt(f, delimiter=",") # no header and fmt for load
|
||||
|
||||
rows, cols = combined_data.shape
|
||||
|
||||
print("No of Rows =", rows)
|
||||
print("No of Colums =", cols)
|
||||
ind1 = 0
|
||||
ind2 = 1
|
||||
if cols > 2:
|
||||
print(
|
||||
"only first 2 colums (data[:, 0] and data[:, 1]) are plotted, please consider the other columns as well!"
|
||||
)
|
||||
index1 = 0
|
||||
index2 = 1
|
||||
index1, index2 = input(
|
||||
"please enter the columns to be plotted vs first one [eg: 1,2] : "
|
||||
).split(",")
|
||||
ind1 = int(index1)
|
||||
ind2 = int(index2)
|
||||
|
||||
if ind2 > cols - 1:
|
||||
print(" no valid index")
|
||||
|
||||
data_x = combined_data[:, ind1]
|
||||
data_y = combined_data[:, ind2]
|
||||
|
||||
plt.ion()
|
||||
plt.figure()
|
||||
plt.plot(data_x, data_y, ".")
|
||||
|
||||
plt.title(f"Scan from {filename}")
|
||||
plt.xlabel(f"data column {ind1}")
|
||||
plt.ylabel(f"data column {ind2}")
|
||||
|
||||
plt.show()
|
||||
|
||||
return combined_data
|
||||
|
||||
|
||||
def gaussfit(x,y,p):
|
||||
# define a gaussian fitting function where
|
||||
# p[0] = amplitude
|
||||
# p[1] = mean
|
||||
# p[2] = sigma
|
||||
# p[3] = const offset
|
||||
|
||||
fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2))+p[3]
|
||||
#fitfct = lambda p, x0: p[0]*np.exp(-(x0-p[1])**2/(2.0*p[2]**2))
|
||||
errfct = lambda p, x0,y0: fitfct(p,x0)-y0
|
||||
|
||||
# guess fit parameters
|
||||
ind0 = np.where(y==max(y))[0]
|
||||
p0=scipy.c_[max(y), x[ind0], np.std(y), np.mean(y[0:5])]
|
||||
#p0=scipy.c_[max(y), np.where(y==max(y))[0], np.std(y)]
|
||||
# array generation [[]], and taking only one dimens
|
||||
# fit a gaussian to the correlation function
|
||||
|
||||
print('p0 = ' , p0)
|
||||
p1, success = scipy.optimize.leastsq(errfct, p0.copy()[0],
|
||||
args=(x,y))
|
||||
|
||||
plt.figure()
|
||||
bestfit=fitfct(p1,x)
|
||||
#print('************************', x,y)
|
||||
plt.plot(x,y,'r*')
|
||||
plt.plot(x,bestfit,'r-')
|
||||
|
||||
# different fit fct
|
||||
#popt, pcov = curve_fit(fitfct, x, y)
|
||||
#newfit=fitfct(popt,x)
|
||||
#plt.plot(x,newfit,'g+')
|
||||
|
||||
|
||||
plt.show()
|
||||
#time.sleep(1)
|
||||
#plt.close()
|
||||
return bestfit, p1
|
||||
|
||||
def mirh():
|
||||
|
||||
dat_ss = read_data("/home/anuschka/SS_pitch2p94.csv")
|
||||
dat_bcu = read_data("/home/anuschka/BCU_pitch2p94.csv")
|
||||
|
||||
data_xs = dat_ss[:, 0]
|
||||
data_ys = dat_ss[:, 1]
|
||||
|
||||
data_xb = dat_bcu[:, 0]
|
||||
data_yb = dat_bcu[:, 1]
|
||||
|
||||
plt.figure()
|
||||
|
||||
plt.plot(data_xs, data_ys, "*")
|
||||
plt.plot(data_xb, data_yb, "+")
|
||||
|
||||
data_ys_norm = data_ys/max(data_ys)
|
||||
data_yb_norm = data_yb/max(data_yb)
|
||||
|
||||
plt.figure()
|
||||
|
||||
plt.plot(data_xs, data_ys_norm, "*")
|
||||
plt.plot(data_xb, data_yb_norm, "+")
|
||||
|
||||
|
||||
pf1 = [1, 0.8 , np.std(data_ys_norm),0]
|
||||
|
||||
y= data_ys_norm
|
||||
xm = np.where(y==max(y))[0]
|
||||
xmi = data_xs[xm]
|
||||
print('xm, xmi', xm, xmi)
|
||||
|
||||
fit_s, ps = gaussfit(data_xs,data_ys_norm, pf1)
|
||||
|
||||
pf2 = [1, 0.8, np.std(data_yb_norm),-11]
|
||||
fit_b, pb = gaussfit(data_xb,data_yb_norm, pf2)
|
||||
|
||||
|
||||
plt.figure()
|
||||
|
||||
plt.plot(data_xs, fit_s-ps[3], "*")
|
||||
plt.plot(data_xb, fit_b-pb[3], "+")
|
||||
|
||||
|
||||
+383
-482
@@ -193,18 +193,24 @@ def beam_centre_from_bsc():
|
||||
return beampos
|
||||
|
||||
|
||||
def generate_dcm_lut(start_energy=26500, end_energy=30500, step=500):
|
||||
def generate_dcm_lut(start_energy=6000, end_energy=30000, step=300):
|
||||
"""Generate a lookup table for the dcm from start_energy to end_energy in steps of step"""
|
||||
now = datetime.now()
|
||||
fnow = now.strftime("%d%m%H%M")
|
||||
filename = f"luts/{fnow}_lut.csv"
|
||||
zoom = dev.scam_zoom.read()['scam_zoom']['value']
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
f.write("energy,harmonic,gap,pitch,roll,perp,ss_xicam_x,ss_xicam_y\n")
|
||||
f.write(f"energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom={zoom}\n")
|
||||
|
||||
for energy in range(start_energy, end_energy, step):
|
||||
print(f"Moving to {energy: .0f}eV")
|
||||
bl_energy(energy, mono_scan=False)
|
||||
scan_gap()
|
||||
try:
|
||||
scan_gap()
|
||||
except Exception as exc:
|
||||
print(f"Gap scan failed at {energy:.0f} eV: {exc}")
|
||||
set_gap(energy) # set fallback gap here
|
||||
|
||||
mono_pitch_scan()
|
||||
gap = dev.id_gap.read()["id_gap"]["value"]
|
||||
harm = Gap()
|
||||
@@ -212,13 +218,17 @@ def generate_dcm_lut(start_energy=26500, end_energy=30500, step=500):
|
||||
pitch = dev.dcm_pitch.read()["dcm_pitch"]["value"]
|
||||
roll = dev.dcm_froll.read()["dcm_froll"]["value"]
|
||||
perp = dev.dcm_perp.read()["dcm_perp"]["value"]
|
||||
auto_exposure(cam="ss_xicam", max_iter=25)
|
||||
x = dev.ss_xicam_x.read()["ss_xicam_x"]["value"]
|
||||
y = dev.ss_xicam_y.read()["ss_xicam_y"]["value"]
|
||||
# auto_exposure(cam="ss_xicam", max_iter=25)
|
||||
# x = dev.ss_xicam_x.read()["ss_xicam_x"]["value"]
|
||||
# y = dev.ss_xicam_y.read()["ss_xicam_y"]["value"]
|
||||
auto_exposure(cam="samcam", max_iter=20)
|
||||
x = dev.samcam_x.read()['samcam_x']['value']
|
||||
y = dev.samcam_y.read()['samcam_y']['value']
|
||||
with open(filename, "a", encoding="utf-8") as f:
|
||||
f.write(
|
||||
f"{energy:.0f},{h},{gap:.5g},{pitch:.5g},{roll:.4g},{perp:.5g},{x:.4g},{y:.4g}\n"
|
||||
)
|
||||
bl_energy(12400)
|
||||
umv(dev.id_gap, 20.0)
|
||||
|
||||
|
||||
@@ -1035,486 +1045,100 @@ def compute_norm():
|
||||
yn = ((readings["bpm1"] + readings["bpm3"]) - (readings["bpm2"] + readings["bpm4"])) / total
|
||||
return xn, yn
|
||||
|
||||
|
||||
# def vfm_pscan():
|
||||
# start_pitch = 3.0
|
||||
# scan_width = 0.03
|
||||
# start_vfm_y = -0.7
|
||||
# vfm_y = dev.vfm_y.read()['vfm_y']['value']
|
||||
# name = f"VFM-{vfm_y:.3g}"
|
||||
# bpmsum, y = [], []
|
||||
|
||||
# scanpoints = np.linspace((start_pitch-scan_width), (start_pitch+scan_width), 20)
|
||||
# umv(dev.vfm_y, start_vfm_y)
|
||||
# for repeat in range(0,8):
|
||||
# filename = f"./luts/pitch{name}.csv"
|
||||
# with open(filename, "w") as f:
|
||||
# f.write("BCUsum, BCU-Y\n")
|
||||
# for i in scanpoints:
|
||||
# umv(dev.vfm_pitch,i)
|
||||
# time.sleep(0.2)
|
||||
# bcu = dev.bcu_bpmsum.read()['bcu_bpmsum']['value']
|
||||
# xn, yn = compute_norm()
|
||||
# bpmsum.append(bcu)
|
||||
# ypos = y.append(yn)
|
||||
# with open(filename, "a") as f:
|
||||
# f.write(f"{i:.4g},{bcu:.4g},{yn:.4g}\n")
|
||||
# umv(dev.vfm_pitch,start_pitch)
|
||||
# sum_array = np.array(bpmsum)
|
||||
# y_array = np.array(y)
|
||||
# # --- Plot ---
|
||||
# plt.figure(figsize=(7,5))
|
||||
# plt.plot(scanpoints, sum_array, color='red', label=f'BCU bpmsum')
|
||||
# plt.xlabel('VFM pitch')
|
||||
# plt.ylabel('BCU')
|
||||
# plt.title(f"{name}")
|
||||
# plt.legend()
|
||||
# plt.grid(True)
|
||||
# plt.tight_layout()
|
||||
# plt.savefig(f"luts/{name}_sum.png")
|
||||
# # plt.show()
|
||||
# plt.figure(figsize=(7,5))
|
||||
# plt.plot(scanpoints, y_array, color='blue', label=f'BCU Y')
|
||||
# plt.xlabel('VFM pitch')
|
||||
# plt.ylabel('BCU')
|
||||
# plt.title(f"{name}")
|
||||
# plt.legend()
|
||||
# plt.grid(True)
|
||||
# plt.tight_layout()
|
||||
# plt.savefig(f"luts/{name}_y.png")
|
||||
# # plt.show()
|
||||
|
||||
|
||||
def hfm_pscan2():
|
||||
|
||||
# -----------------------
|
||||
# Settings
|
||||
# -----------------------
|
||||
start_pitch = 3.0
|
||||
pitch_width = 0.03
|
||||
n_pitch = 15
|
||||
|
||||
start_hfm_x = 1.5
|
||||
hfm_x_width = 0.2
|
||||
n_hfm_x = 7
|
||||
|
||||
settle = 0.2
|
||||
|
||||
output_dir = "./luts"
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# -----------------------
|
||||
# Save initial positions
|
||||
# -----------------------
|
||||
initial_pitch = dev.hfm_pitch.read()["hfm_pitch"]["value"]
|
||||
initial_hfmx = dev.hfm_x.read()["hfm_x"]["value"]
|
||||
|
||||
# -----------------------
|
||||
# Scan points
|
||||
# -----------------------
|
||||
pitch_points = np.linspace(start_pitch - pitch_width, start_pitch + pitch_width, n_pitch)
|
||||
|
||||
hfmx_points = np.linspace(start_hfm_x - hfm_x_width, start_hfm_x + hfm_x_width, n_hfm_x)
|
||||
|
||||
summary = []
|
||||
|
||||
# -----------------------
|
||||
# Loop over hFM X
|
||||
# -----------------------
|
||||
for hfmx in hfmx_points:
|
||||
|
||||
print(f"\nScanning HFM X = {hfmx:.4f}")
|
||||
|
||||
umv(dev.hfm_x, hfmx)
|
||||
time.sleep(settle)
|
||||
|
||||
bpmsum = []
|
||||
|
||||
name = f"HFMX_{hfmx:.4f}"
|
||||
|
||||
csvfile = os.path.join(output_dir, f"{name}.csv")
|
||||
|
||||
with open(csvfile, "w") as f:
|
||||
|
||||
f.write("pitch,bpmsum,bpmsum_std\n")
|
||||
|
||||
for pitch in pitch_points:
|
||||
|
||||
umv(dev.hfm_pitch, pitch)
|
||||
time.sleep(settle)
|
||||
|
||||
# Average several BPM readings
|
||||
vals = []
|
||||
for _ in range(5):
|
||||
vals.append(dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"])
|
||||
time.sleep(0.1)
|
||||
|
||||
bcu = np.mean(vals)
|
||||
bcu_std = np.std(vals)
|
||||
|
||||
bpmsum.append(bcu)
|
||||
|
||||
f.write(f"{pitch:.6f},{bcu:.6f}, {bcu_std:.6f}\n")
|
||||
|
||||
# Return pitch to nominal
|
||||
umv(dev.hfm_pitch, start_pitch)
|
||||
|
||||
bpmsum = np.array(bpmsum)
|
||||
|
||||
# Find maximum transmission
|
||||
imax = np.argmax(bpmsum)
|
||||
|
||||
pitch_peak = pitch_points[imax]
|
||||
sum_peak = bpmsum[imax]
|
||||
|
||||
summary.append([hfmx, pitch_peak, sum_peak])
|
||||
|
||||
print(f"Peak pitch = {pitch_peak:.5f}, " f"Max BPM sum = {sum_peak:.1f}")
|
||||
|
||||
# Plot this pitch scan
|
||||
plt.figure(figsize=(7, 5))
|
||||
|
||||
plt.plot(pitch_points, bpmsum, marker="o")
|
||||
|
||||
plt.axvline(pitch_peak, linestyle="--", label=f"Peak = {pitch_peak:.5f}")
|
||||
|
||||
plt.xlabel("HFM pitch")
|
||||
plt.ylabel("BPM sum")
|
||||
plt.title(name)
|
||||
|
||||
plt.grid(True)
|
||||
plt.legend()
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, f"{name}.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
# -----------------------
|
||||
# Summary analysis
|
||||
# -----------------------
|
||||
summary = np.array(summary)
|
||||
|
||||
hfmx = summary[:, 0]
|
||||
pitch_peak = summary[:, 1]
|
||||
sum_peak = summary[:, 2]
|
||||
|
||||
# Save summary CSV
|
||||
summary_file = os.path.join(output_dir, "hfm_summary.csv")
|
||||
|
||||
with open(summary_file, "w") as f:
|
||||
|
||||
f.write("hfmx,pitch_peak,sum_peak\n")
|
||||
|
||||
for row in summary:
|
||||
f.write(",".join(f"{x:.6f}" for x in row) + "\n")
|
||||
|
||||
# -----------------------
|
||||
# Summary plots
|
||||
# -----------------------
|
||||
|
||||
plt.figure(figsize=(7, 5))
|
||||
|
||||
plt.plot(hfmx, sum_peak, marker="o")
|
||||
|
||||
plt.xlabel("HFM X")
|
||||
plt.ylabel("Maximum BPM sum")
|
||||
plt.title("Transmission vs HFM X")
|
||||
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, "summary_sum_vs_hfmx.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
plt.figure(figsize=(7, 5))
|
||||
|
||||
plt.plot(hfmx, pitch_peak, marker="o")
|
||||
|
||||
plt.xlabel("HFM X")
|
||||
plt.ylabel("Pitch at maximum transmission")
|
||||
plt.title("Optimum pitch vs HFM X")
|
||||
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, "summary_pitch_vs_hfmx.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
# -----------------------
|
||||
# Find best HFM X
|
||||
# -----------------------
|
||||
ibest = np.argmax(sum_peak)
|
||||
|
||||
best_vfmy = hfmx[ibest]
|
||||
best_pitch = pitch_peak[ibest]
|
||||
|
||||
print("\nBest alignment:")
|
||||
print(f"HFM X = {best_hfmx:.5f}")
|
||||
print(f"HFM pitch = {best_pitch:.5f}")
|
||||
|
||||
# Move to optimum
|
||||
umv(dev.hfm_x, best_hfmx)
|
||||
umv(dev.hfm_pitch, best_pitch)
|
||||
|
||||
print("\nMoved mirrors to optimum values.")
|
||||
|
||||
return summary
|
||||
|
||||
|
||||
def vfm_pscan():
|
||||
|
||||
# -------------------------------
|
||||
# User settings
|
||||
# -------------------------------
|
||||
start_pitch = 3.0 # nominal pitch
|
||||
pitch_width = 0.03 # +/- pitch scan range
|
||||
n_pitch = 20
|
||||
|
||||
start_vfm_y = -0.900 # nominal VFM Y
|
||||
vfm_y_width = 0.05 # +/- VFM Y scan range
|
||||
n_vfm_y = 8
|
||||
|
||||
settle_time = 0.2
|
||||
|
||||
output_dir = "./luts"
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# -------------------------------
|
||||
# Save initial positions
|
||||
# -------------------------------
|
||||
initial_pitch = dev.vfm_pitch.read()["vfm_pitch"]["value"]
|
||||
initial_vfm_y = dev.vfm_y.read()["vfm_y"]["value"]
|
||||
|
||||
# -------------------------------
|
||||
# Generate scan points
|
||||
# -------------------------------
|
||||
pitch_points = np.linspace(start_pitch - pitch_width, start_pitch + pitch_width, n_pitch)
|
||||
|
||||
vfm_y_points = np.linspace(start_vfm_y - vfm_y_width, start_vfm_y + vfm_y_width, n_vfm_y)
|
||||
|
||||
summary = []
|
||||
|
||||
# -------------------------------
|
||||
# Loop over VFM Y
|
||||
# -------------------------------
|
||||
for vfm_y in vfm_y_points:
|
||||
|
||||
print(f"\nScanning VFM Y = {vfm_y:.4f}")
|
||||
|
||||
umv(dev.vfm_y, vfm_y)
|
||||
time.sleep(settle_time)
|
||||
|
||||
bpmsum = []
|
||||
bpm_y = []
|
||||
|
||||
name = f"VFMY_{vfm_y:.4f}"
|
||||
|
||||
csvfile = os.path.join(output_dir, f"{name}.csv")
|
||||
|
||||
with open(csvfile, "w") as f:
|
||||
|
||||
f.write("pitch,bpmsum,bpm_y\n")
|
||||
|
||||
# -------------------------------
|
||||
# Pitch scan
|
||||
# -------------------------------
|
||||
for pitch in pitch_points:
|
||||
|
||||
umv(dev.vfm_pitch, pitch)
|
||||
time.sleep(settle_time)
|
||||
|
||||
bcu = dev.bcu_bpmsum.read()["bcu_bpmsum"]["value"]
|
||||
|
||||
xn, yn = compute_norm()
|
||||
|
||||
bpmsum.append(bcu)
|
||||
bpm_y.append(yn)
|
||||
|
||||
f.write(f"{pitch:.6f},{bcu:.6f},{yn:.6f}\n")
|
||||
|
||||
# Return pitch to nominal
|
||||
umv(dev.vfm_pitch, start_pitch)
|
||||
|
||||
# Convert to arrays
|
||||
bpmsum = np.array(bpmsum)
|
||||
bpm_y = np.array(bpm_y)
|
||||
|
||||
# -------------------------------
|
||||
# Find optimum pitch
|
||||
# -------------------------------
|
||||
imax = np.argmax(bpmsum)
|
||||
|
||||
pitch_peak = pitch_points[imax]
|
||||
sum_peak = bpmsum[imax]
|
||||
y_peak = bpm_y[imax]
|
||||
|
||||
summary.append([vfm_y, pitch_peak, sum_peak, y_peak])
|
||||
|
||||
print(f"Peak at pitch={pitch_peak:.5f}, " f"BPM sum={sum_peak:.1f}, " f"BPM Y={y_peak:.4f}")
|
||||
|
||||
# -------------------------------
|
||||
# Plot BPM sum
|
||||
# -------------------------------
|
||||
plt.figure(figsize=(7, 5))
|
||||
|
||||
plt.plot(pitch_points, bpmsum, marker="o")
|
||||
|
||||
plt.axvline(pitch_peak, linestyle="--")
|
||||
|
||||
plt.xlabel("VFM pitch")
|
||||
plt.ylabel("BCU BPM sum")
|
||||
plt.title(name)
|
||||
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, f"{name}_sum.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
# -------------------------------
|
||||
# Plot BPM Y
|
||||
# -------------------------------
|
||||
plt.figure(figsize=(7, 5))
|
||||
|
||||
plt.plot(pitch_points, bpm_y, marker="o")
|
||||
|
||||
plt.axvline(pitch_peak, linestyle="--")
|
||||
|
||||
plt.xlabel("VFM pitch")
|
||||
plt.ylabel("BCU BPM Y")
|
||||
plt.title(name)
|
||||
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, f"{name}_y.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
# -------------------------------
|
||||
# Summary arrays
|
||||
# -------------------------------
|
||||
summary = np.array(summary)
|
||||
|
||||
vfm_y_vals = summary[:, 0]
|
||||
pitch_peaks = summary[:, 1]
|
||||
sum_peaks = summary[:, 2]
|
||||
y_peaks = summary[:, 3]
|
||||
|
||||
# Save summary CSV
|
||||
summary_file = os.path.join(output_dir, "vfm_summary.csv")
|
||||
|
||||
with open(summary_file, "w") as f:
|
||||
|
||||
f.write("vfm_y,pitch_peak,sum_peak,bpm_y_peak\n")
|
||||
|
||||
for row in summary:
|
||||
f.write(",".join(f"{x:.6f}" for x in row) + "\n")
|
||||
|
||||
# -------------------------------
|
||||
# Summary plots
|
||||
# -------------------------------
|
||||
|
||||
plt.figure(figsize=(7, 5))
|
||||
plt.plot(vfm_y_vals, pitch_peaks, marker="o")
|
||||
|
||||
plt.xlabel("VFM Y")
|
||||
plt.ylabel("Pitch at max BPM sum")
|
||||
plt.title("Optimum pitch vs VFM Y")
|
||||
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, "summary_pitch_vs_vfmy.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
plt.figure(figsize=(7, 5))
|
||||
plt.plot(vfm_y_vals, sum_peaks, marker="o")
|
||||
|
||||
plt.xlabel("VFM Y")
|
||||
plt.ylabel("Maximum BPM sum")
|
||||
plt.title("Maximum transmission vs VFM Y")
|
||||
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, "summary_sum_vs_vfmy.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
plt.figure(figsize=(7, 5))
|
||||
plt.plot(vfm_y_vals, y_peaks, marker="o")
|
||||
|
||||
plt.xlabel("VFM Y")
|
||||
plt.ylabel("BPM Y at optimum pitch")
|
||||
plt.title("Beam position vs VFM Y")
|
||||
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
|
||||
plt.savefig(os.path.join(output_dir, "summary_bpmy_vs_vfmy.png"))
|
||||
|
||||
plt.close()
|
||||
|
||||
# -------------------------------
|
||||
# Restore original positions
|
||||
# -------------------------------
|
||||
umv(dev.vfm_pitch, initial_pitch)
|
||||
umv(dev.vfm_y, initial_vfm_y)
|
||||
|
||||
print("\nScan complete.")
|
||||
print(f"Summary written to {summary_file}")
|
||||
|
||||
return summary
|
||||
|
||||
|
||||
def find_best_roll(low=6000, high=20000):
|
||||
low_scanpoints = np.linspace(0.5, 5.5, 11)
|
||||
high_scanpoints = np.linspace(1.0, 9.0, 9)
|
||||
def mirror_pitch(mirror = 'vfm'):
|
||||
|
||||
if mirror == 'vfm':
|
||||
pitch = dev.vfm_pitch.position
|
||||
mot = dev.vfm_pitch
|
||||
start = 2.94
|
||||
else:
|
||||
pitch = dev.hfm_pitch.position
|
||||
mot = dev.hfm_pitch
|
||||
start = 3.3
|
||||
print(f"Scanning {mirror}_pitch from 10-29 keV")
|
||||
pitch_range = [start - 0.25, start - 0.2, start -0.15, start - 0.1, start -0.05]
|
||||
|
||||
umv(mot,start)
|
||||
|
||||
results = []
|
||||
now = datetime.now()
|
||||
fnow = now.strftime("%d%m%H%M")
|
||||
csvfile = f"luts/{fnow}_{mirror}_pitch_energy.csv"
|
||||
|
||||
with open(csvfile, "w") as f:
|
||||
f.write("energy,pitch,diode\n")
|
||||
|
||||
# for p in pitch_range:
|
||||
for energy in range(17, 26):
|
||||
bl_energy(energy)
|
||||
time.sleep(1)
|
||||
|
||||
for p in pitch_range:
|
||||
umv(mot, p)
|
||||
print(f"{mirror}_pitch = {p}")
|
||||
time.sleep(0.2)
|
||||
vals_diode = []
|
||||
|
||||
for _ in range(5):
|
||||
vals_diode.append(dev.xidiode.read()['xidiode']['value'])
|
||||
time.sleep(0.1)
|
||||
|
||||
diode = np.mean(vals_diode)
|
||||
|
||||
results.append([
|
||||
energy,
|
||||
p,
|
||||
diode,
|
||||
])
|
||||
|
||||
with open(csvfile, "a") as f:
|
||||
f.write(
|
||||
f"{energy:.2f},{p:.5f},{diode:.5g}\n"
|
||||
)
|
||||
umv(mot,start)
|
||||
bl_energy(12400)
|
||||
results = np.array(results)
|
||||
|
||||
def find_best_roll(low = 6000, high = 20000):
|
||||
low_scanpoints = np.linspace(2.0, 7.0, 11)
|
||||
high_scanpoints = np.linspace(1.0, 9.0,9)
|
||||
highs_y, lows_y = [], []
|
||||
|
||||
# low energy
|
||||
bl_energy(low)
|
||||
energy = get_current_energy()
|
||||
filename = f"./luts/roll_{energy:.0f}.csv"
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
f.write("Roll, Y pos\n")
|
||||
auto_exposure("bsccam", max_iter=25)
|
||||
for i in low_scanpoints:
|
||||
umv(dev.dcm_froll, i)
|
||||
time.sleep(0.2)
|
||||
low_y = dev.bsccam_y.read()["bsccam_y"]["value"]
|
||||
print(f"Ypos at BSC cam is {low_y}")
|
||||
lows_y.append(low_y)
|
||||
with open(filename, "a", encoding="utf-8") as f:
|
||||
f.write(f"{i:.4g},{low_y:.4g} \n")
|
||||
|
||||
# high energy
|
||||
bl_energy(high)
|
||||
energy = get_current_energy()
|
||||
if 19999 < energy < 200001:
|
||||
umv(dev.id_gap, 4.718)
|
||||
filename = f"./luts/roll_{energy:.0f}.csv"
|
||||
filename = f"./luts/roll_{high:.0f}.csv"
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
f.write("Roll, Y pos\n")
|
||||
auto_exposure("bsccam", max_iter=25)
|
||||
f.write("Roll, Y pos\n")
|
||||
auto_exposure("samcam", max_iter=25)
|
||||
for i in high_scanpoints:
|
||||
umv(dev.dcm_froll, i)
|
||||
time.sleep(0.2)
|
||||
high_y = dev.bsccam_y.read()["bsccam_y"]["value"]
|
||||
print(f"Ypos at BSC cam is {high_y}")
|
||||
high_y = dev.samcam_y.read()['samcam_y']['value']
|
||||
print(f"Ypos at sample cam is {high_y}")
|
||||
highs_y.append(high_y)
|
||||
with open(filename, "a", encoding="utf-8") as f:
|
||||
f.write(f"{i:.4g},{low_y:4g.} \n")
|
||||
f.write(f"{i:.4g},{high_y:.4g} \n")
|
||||
|
||||
# low energy
|
||||
bl_energy(low)
|
||||
filename = f"./luts/roll_{low:.0f}.csv"
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
f.write("Roll, Y pos\n")
|
||||
auto_exposure("samcam", max_iter=25)
|
||||
for i in low_scanpoints:
|
||||
umv(dev.dcm_froll, i)
|
||||
time.sleep(0.2)
|
||||
low_y = dev.samcam_y.read()['samcam_y']['value']
|
||||
print(f"Ypos at sample cam is {low_y}")
|
||||
lows_y.append(low_y)
|
||||
with open(filename, "a", encoding="utf-8") as f:
|
||||
f.write(f"{i:.4g},{low_y:.4g} \n")
|
||||
|
||||
|
||||
y_high = np.array(highs_y)
|
||||
y_low = np.array(lows_y)
|
||||
|
||||
|
||||
# # Fit linear models: y = m*x + b
|
||||
m_high, b_high = np.polyfit(high_scanpoints, y_high, 1)
|
||||
m_low, b_low = np.polyfit(low_scanpoints, y_low, 1)
|
||||
@@ -1525,23 +1149,300 @@ def find_best_roll(low=6000, high=20000):
|
||||
|
||||
print(f"\nIntersection at:")
|
||||
print(f" DCM Roll = {x_intersect:.5f}")
|
||||
print(f" BSCcam Y = {y_intersect:.2f}")
|
||||
print(f" samcam Y = {y_intersect:.2f}")
|
||||
|
||||
# # --- Plot ---
|
||||
plt.figure(figsize=(7, 5))
|
||||
plt.scatter(high_scanpoints, y_high, color="red", label=f"High energy")
|
||||
plt.scatter(low_scanpoints, y_low, color="blue", label=f"Low energy")
|
||||
plt.figure(figsize=(7,5))
|
||||
plt.scatter(high_scanpoints, y_high, color='red', label=f'High energy')
|
||||
plt.scatter(low_scanpoints, y_low, color='blue', label=f'Low energy')
|
||||
|
||||
x_fit = np.linspace(min(high_scanpoints), max(high_scanpoints), 100)
|
||||
plt.plot(x_fit, m_high * x_fit + b_high, "r--", label=f"High energy")
|
||||
plt.plot(x_fit, m_low * x_fit + b_low, "b--", label=f"Low energy")
|
||||
plt.plot(x_fit, m_high*x_fit + b_high, 'r--', label=f'High energy')
|
||||
plt.plot(x_fit, m_low*x_fit + b_low, 'b--', label=f'Low energy')
|
||||
|
||||
plt.scatter(x_intersect, y_intersect, color="green", s=80, zorder=5, label="Intersection")
|
||||
plt.scatter(x_intersect, y_intersect, color='green', s=80, zorder=5, label='Intersection')
|
||||
|
||||
plt.xlabel("DCM fine roll")
|
||||
plt.ylabel("BSCcam Y pos")
|
||||
plt.title("Roll Calibration")
|
||||
plt.xlabel('DCM fine roll')
|
||||
plt.ylabel('samcam Y pos')
|
||||
plt.title('Roll Calibration')
|
||||
plt.legend()
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
|
||||
def vfm_yaw_check():
|
||||
slit_size = 0.02
|
||||
slit_point1 = -1.2
|
||||
slit_point2 = -0.12
|
||||
mirror_start = 0.5
|
||||
mirror_end = -5
|
||||
yaw_values = [-1.5, -0.5, 0, 0.5, 1]
|
||||
point1 = []
|
||||
point2 = []
|
||||
|
||||
umv(dev.ss_sl_ysize, slit_size)
|
||||
|
||||
for yaw in yaw_values:
|
||||
print(f"Moving VFM yaw to {yaw}")
|
||||
umv(dev.vfm_yaw, yaw)
|
||||
# Point 1
|
||||
print(f"Moving slits to position 1")
|
||||
umv(dev.ss_sl_ycen, slit_point1)
|
||||
scans.line_scan(dev.vfm_x, mirror_start, mirror_end, steps = 20, relative=False)
|
||||
fit_result = fit_history(-1, "xidiode", deriv=True)
|
||||
centre = fit_result['centre']
|
||||
print(f'Yaw = {yaw}, position = {slit_point1}, centre = {centre}')
|
||||
point1.append(centre)
|
||||
# Point 2
|
||||
print(f"Moving slits to position 2")
|
||||
umv(dev.ss_sl_ycen, slit_point2)
|
||||
scans.line_scan(dev.vfm_x, mirror_start, mirror_end, steps = 20, relative=False)
|
||||
fit_result = fit_history(-1, "xidiode", deriv=True)
|
||||
centre = fit_result['centre']
|
||||
print(f'Yaw = {yaw}, position = {slit_point2}, centre = {centre}')
|
||||
point2.append(centre)
|
||||
print(f"Point 1 values are {point1}")
|
||||
print(f"Point 2 values are {point2}")
|
||||
go_to_peak(dev.ss_sl_ycen, dev.xidiode, -2, 2, 100)
|
||||
umv(dev.ss_sl_ysize, 2)
|
||||
y_point1 = np.array(point1)
|
||||
y_point2 = np.array(point2)
|
||||
|
||||
|
||||
# # Fit linear models: y = m*x + b
|
||||
m_point1, b_point1 = np.polyfit(yaw_values, y_point1, 1)
|
||||
m_point2, b_point2 = np.polyfit(yaw_values, y_point2, 1)
|
||||
|
||||
# # Intersection point
|
||||
x_intersect = (b_point2 - b_point1) / (m_point1 - m_point1)
|
||||
y_intersect = m_point1 * x_intersect + b_point1
|
||||
|
||||
print(f"\nIntersection at:")
|
||||
print(f" Mirror yaw = {x_intersect:.5f}")
|
||||
print(f" Y = {y_intersect:.2f}")
|
||||
|
||||
# # --- Plot ---
|
||||
plt.figure(figsize=(7,5))
|
||||
plt.scatter(yaw_values, y_point1, color='red', label=f'point1')
|
||||
plt.scatter(yaw_values, y_point2, color='blue', label=f'point2')
|
||||
|
||||
x_fit = np.linspace(min(yaw_values), max(yaw_values), 100)
|
||||
plt.plot(x_fit, m_point1*x_fit + b_point1, 'r--', label=f'point1')
|
||||
plt.plot(x_fit, m_point2*x_fit + b_point2, 'b--', label=f'point2')
|
||||
|
||||
plt.scatter(x_intersect, y_intersect, color='green', s=80, zorder=5, label='Intersection')
|
||||
|
||||
plt.xlabel('VFM yaw')
|
||||
plt.ylabel('Edge')
|
||||
plt.title('VFM Yaw Calibration')
|
||||
plt.legend()
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
|
||||
from dataclasses import dataclass
|
||||
import time
|
||||
|
||||
|
||||
@dataclass
|
||||
class SlitAxis:
|
||||
name: str
|
||||
centre_motor: object # e.g. dev.slit1_x
|
||||
size_motor: object # e.g. dev.slit1_xsize
|
||||
scan_func: callable # your existing peak scan function
|
||||
scan_range: float = 2.0
|
||||
open_size: float = 2.0
|
||||
min_size: float = -0.4
|
||||
max_size: float = 5.0
|
||||
|
||||
|
||||
@dataclass
|
||||
class Slit:
|
||||
name: str
|
||||
x: SlitAxis
|
||||
y: SlitAxis
|
||||
|
||||
|
||||
def read_intensity(detector, n=5, delay=0.1):
|
||||
values = []
|
||||
for _ in range(n):
|
||||
values.append(detector.read()[detector.name]["value"])
|
||||
time.sleep(delay)
|
||||
return sum(values) / len(values)
|
||||
|
||||
|
||||
|
||||
def reduce_to_transmission(axis, detector, baseline, target=0.15, step=0.05):
|
||||
"""
|
||||
Close slit size until intensity is around target * baseline.
|
||||
"""
|
||||
size = axis.size_motor.position
|
||||
|
||||
while size > axis.min_size:
|
||||
intensity = read_intensity(detector)
|
||||
transmission = intensity / baseline
|
||||
|
||||
print(
|
||||
f"{axis.name}: size={size:.4f}, "
|
||||
f"I={intensity:.3g}, transmission={transmission:.3f}"
|
||||
)
|
||||
|
||||
if transmission <= target:
|
||||
return size, intensity
|
||||
|
||||
size -= step
|
||||
umv(axis.size_motor, size)
|
||||
|
||||
raise RuntimeError(f"{axis.name}: reached minimum slit size without reaching target")
|
||||
|
||||
|
||||
def open_to_transmission(axis, detector, baseline, target=0.99, step=0.05):
|
||||
"""
|
||||
Open slit until intensity is close to the original baseline.
|
||||
"""
|
||||
size = axis.size_motor.position
|
||||
|
||||
while size < axis.max_size:
|
||||
intensity = read_intensity(detector)
|
||||
transmission = intensity / baseline
|
||||
|
||||
print(
|
||||
f"{axis.name}: size={size:.4f}, "
|
||||
f"I={intensity:.3g}, transmission={transmission:.3f}"
|
||||
)
|
||||
|
||||
if transmission >= target:
|
||||
return size, intensity
|
||||
|
||||
size += step
|
||||
umv(axis.size_motor, size)
|
||||
# final_size = axis.size.motor.position
|
||||
# fudge = 0.5
|
||||
# umv(axis.size_motor,final_size + fudge)
|
||||
|
||||
raise RuntimeError(f"{axis.name}: reached maximum slit size without restoring intensity")
|
||||
|
||||
# def approx_centre_axis(axis, detector, slitsize=0.5):
|
||||
# umv(axis.size_motor, slitsize)
|
||||
# go_to_peak(axis.centre_motor, detector, -4, 4, 50, confirm=False)
|
||||
|
||||
|
||||
def centre_axis(axis, detector, close_fraction=0.10, open_fraction=0.95):
|
||||
print(f"\nAligning {axis.name}")
|
||||
|
||||
# approx_centre_axis(axis, detector, slitsize=0.5)
|
||||
|
||||
umv(axis.size_motor, axis.open_size)
|
||||
|
||||
baseline = read_intensity(detector)
|
||||
print(f"{axis.name}: baseline intensity = {baseline:.3g}")
|
||||
|
||||
# if baseline <= 0:
|
||||
# raise RuntimeError(f"{axis.name}: invalid baseline intensity")
|
||||
|
||||
reduce_to_transmission(
|
||||
axis,
|
||||
detector,
|
||||
baseline,
|
||||
target=close_fraction,
|
||||
)
|
||||
|
||||
go_to_peak(axis.centre_motor, detector, axis.centre_motor.position - axis.scan_range,
|
||||
axis.centre_motor.position + axis.scan_range,
|
||||
50,
|
||||
confirm=False)
|
||||
print(f"{axis.name}: moving centre to peak position")
|
||||
|
||||
open_to_transmission(
|
||||
axis,
|
||||
detector,
|
||||
baseline,
|
||||
target=open_fraction,
|
||||
)
|
||||
|
||||
final_intensity = read_intensity(detector)
|
||||
print(
|
||||
f"{axis.name}: final intensity = {final_intensity:.3g}, "
|
||||
f"transmission = {final_intensity / baseline:.3f}"
|
||||
)
|
||||
|
||||
def open_slits(size=3):
|
||||
slits = define_slits()
|
||||
for slit in slits:
|
||||
umv(slit.x.size_motor, size)
|
||||
umv(slit.y.size_motor, size)
|
||||
|
||||
|
||||
def centre_slit(slit, detector):
|
||||
print(f"\n=== Aligning {slit.name} ===")
|
||||
|
||||
centre_axis(slit.x, detector)
|
||||
centre_axis(slit.y, detector)
|
||||
|
||||
print(f"=== Finished {slit.name} ===")
|
||||
|
||||
|
||||
def centre_all_slits(slits, detector):
|
||||
for slit in slits:
|
||||
try:
|
||||
centre_slit(slit, detector)
|
||||
except Exception as exc:
|
||||
print(f"WARNING: failed to align {slit.name}: {exc}")
|
||||
print("Continuing with next slit.")
|
||||
|
||||
def centre_one(name, detector):
|
||||
slits = define_slits()
|
||||
for slit in slits:
|
||||
if slit.name == name:
|
||||
centre_slit(slit, detector)
|
||||
|
||||
def define_slits():
|
||||
slits = [
|
||||
Slit(
|
||||
name="bsf",
|
||||
x=SlitAxis(
|
||||
name="bsf_sl_x",
|
||||
centre_motor=dev.bsf_sl_xcen,
|
||||
size_motor=dev.bsf_sl_xsize,
|
||||
scan_func=go_to_peak,
|
||||
),
|
||||
y=SlitAxis(
|
||||
name="bsf_sl_y",
|
||||
centre_motor=dev.bsf_sl_ycen,
|
||||
size_motor=dev.bsf_sl_ysize,
|
||||
scan_func=go_to_peak,
|
||||
),
|
||||
),
|
||||
Slit(
|
||||
name="ss",
|
||||
x=SlitAxis(
|
||||
name="ss_sl_x",
|
||||
centre_motor=dev.ss_sl_xcen,
|
||||
size_motor=dev.ss_sl_xsize,
|
||||
scan_func=go_to_peak,
|
||||
),
|
||||
y=SlitAxis(
|
||||
name="ss_sl_y",
|
||||
centre_motor=dev.ss_sl_ycen,
|
||||
size_motor=dev.ss_sl_ysize,
|
||||
scan_func=go_to_peak,
|
||||
),
|
||||
),
|
||||
Slit(
|
||||
name="bcu",
|
||||
x=SlitAxis(
|
||||
name="bcu_sl_x",
|
||||
centre_motor=dev.bcu_sl_xcen,
|
||||
size_motor=dev.bcu_sl_xsize,
|
||||
scan_func=go_to_peak,
|
||||
),
|
||||
y=SlitAxis(
|
||||
name="ss_sl_y",
|
||||
centre_motor=dev.bcu_sl_ycen,
|
||||
size_motor=dev.bcu_sl_ysize,
|
||||
scan_func=go_to_peak,
|
||||
),
|
||||
),
|
||||
]
|
||||
return slits
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
energy,pitch,diode
|
||||
10.00,2.79003,2.5101e-05
|
||||
10.00,2.86503,2.7481e-05
|
||||
10.00,2.94003,2.7441e-05
|
||||
10.00,3.01503,2.7531e-05
|
||||
10.00,3.09003,2.7429e-05
|
||||
11.00,2.79003,6.7964e-05
|
||||
11.00,2.86503,7.9833e-05
|
||||
11.00,2.94003,7.9545e-05
|
||||
11.00,3.01503,7.9683e-05
|
||||
11.00,3.09003,7.9548e-05
|
||||
12.00,2.79003,6.4495e-05
|
||||
12.00,2.86503,7.3507e-05
|
||||
12.00,2.94003,7.3534e-05
|
||||
12.00,3.01503,7.3641e-05
|
||||
12.00,3.09003,7.292e-05
|
||||
13.00,2.79003,5.1657e-05
|
||||
13.00,2.86503,5.6129e-05
|
||||
13.00,2.94003,5.5938e-05
|
||||
13.00,3.01503,5.5935e-05
|
||||
13.00,3.09003,5.5824e-05
|
||||
14.00,2.79003,5.0019e-05
|
||||
14.00,2.86503,5.4959e-05
|
||||
14.00,2.94003,5.4717e-05
|
||||
14.00,3.01503,5.4711e-05
|
||||
14.00,3.09003,5.4572e-05
|
||||
15.00,2.79003,3.8514e-05
|
||||
15.00,2.86503,4.2182e-05
|
||||
15.00,2.94003,4.2072e-05
|
||||
15.00,3.01503,4.2056e-05
|
||||
15.00,3.09003,4.1897e-05
|
||||
16.00,2.79003,2.6391e-05
|
||||
16.00,2.86503,2.8237e-05
|
||||
16.00,2.94003,2.8187e-05
|
||||
16.00,3.01503,2.8078e-05
|
||||
16.00,3.09003,2.7934e-05
|
||||
17.00,2.79003,1.9654e-05
|
||||
17.00,2.86503,2.0669e-05
|
||||
17.00,2.94003,2.0592e-05
|
||||
17.00,3.01503,2.0495e-05
|
||||
17.00,3.09003,2.0409e-05
|
||||
18.00,2.79003,1.6418e-05
|
||||
18.00,2.86503,1.7321e-05
|
||||
18.00,2.94003,1.7276e-05
|
||||
18.00,3.01503,1.7201e-05
|
||||
18.00,3.09003,1.7058e-05
|
||||
19.00,2.79003,1.1114e-05
|
||||
19.00,2.86503,1.1688e-05
|
||||
19.00,2.94003,1.1616e-05
|
||||
19.00,3.01503,1.1486e-05
|
||||
19.00,3.09003,1.1229e-05
|
||||
20.00,2.79003,1.0067e-05
|
||||
20.00,2.86503,1.0474e-05
|
||||
20.00,2.94003,1.0233e-05
|
||||
20.00,3.01503,9.7442e-06
|
||||
20.00,3.09003,8.7702e-06
|
||||
21.00,2.79003,6.6035e-06
|
||||
21.00,2.86503,6.4392e-06
|
||||
21.00,2.94003,5.6891e-06
|
||||
21.00,3.01503,4.6277e-06
|
||||
21.00,3.09003,3.4547e-06
|
||||
22.00,2.79003,3.4235e-06
|
||||
22.00,2.86503,2.8148e-06
|
||||
22.00,2.94003,2.0854e-06
|
||||
22.00,3.01503,1.413e-06
|
||||
22.00,3.09003,1.0058e-06
|
||||
23.00,2.79003,1.3978e-06
|
||||
23.00,2.86503,9.5583e-07
|
||||
23.00,2.94003,6.9829e-07
|
||||
23.00,3.01503,5.3073e-07
|
||||
23.00,3.09003,4.8376e-07
|
||||
24.00,2.79003,5.5859e-07
|
||||
24.00,2.86503,4.3102e-07
|
||||
24.00,2.94003,3.3977e-07
|
||||
24.00,3.01503,2.7979e-07
|
||||
24.00,3.09003,2.2912e-07
|
||||
25.00,2.79003,2.3919e-07
|
||||
25.00,2.86503,1.9166e-07
|
||||
25.00,2.94003,1.5672e-07
|
||||
25.00,3.01503,1.2674e-07
|
||||
25.00,3.09003,9.9158e-08
|
||||
26.00,2.79003,1.7634e-07
|
||||
26.00,2.86503,1.4523e-07
|
||||
26.00,2.94003,1.1948e-07
|
||||
26.00,3.01503,9.6605e-08
|
||||
26.00,3.09003,8.3358e-08
|
||||
27.00,2.79003,7.4085e-08
|
||||
27.00,2.86503,6.2851e-08
|
||||
27.00,2.94003,5.1639e-08
|
||||
27.00,3.01503,4.5493e-08
|
||||
27.00,3.09003,4.1044e-08
|
||||
28.00,2.79003,4.757e-08
|
||||
28.00,2.86503,4.0306e-08
|
||||
28.00,2.94003,3.6045e-08
|
||||
28.00,3.01503,3.1936e-08
|
||||
28.00,3.09003,2.5395e-08
|
||||
|
@@ -0,0 +1,51 @@
|
||||
energy,pitch,diode
|
||||
17.00,2.49006,6.9998e-08
|
||||
17.00,2.54006,8.0892e-08
|
||||
17.00,2.59006,9.3759e-08
|
||||
17.00,2.64006,1.1324e-07
|
||||
17.00,2.69006,1.4562e-07
|
||||
18.00,2.49006,6.122e-08
|
||||
18.00,2.54006,7.1592e-08
|
||||
18.00,2.59006,8.4016e-08
|
||||
18.00,2.64006,1.0291e-07
|
||||
18.00,2.69006,1.3362e-07
|
||||
19.00,2.49006,3.8423e-08
|
||||
19.00,2.54006,4.5515e-08
|
||||
19.00,2.59006,5.3896e-08
|
||||
19.00,2.64006,6.6516e-08
|
||||
19.00,2.69006,8.8274e-08
|
||||
20.00,2.49006,2.9234e-08
|
||||
20.00,2.54006,3.5421e-08
|
||||
20.00,2.59006,4.3305e-08
|
||||
20.00,2.64006,5.5004e-08
|
||||
20.00,2.69006,7.3772e-08
|
||||
21.00,2.49006,1.7361e-08
|
||||
21.00,2.54006,2.0553e-08
|
||||
21.00,2.59006,2.5132e-08
|
||||
21.00,2.64006,3.2485e-08
|
||||
21.00,2.69006,4.5865e-08
|
||||
22.00,2.49006,1.0198e-08
|
||||
22.00,2.54006,1.1792e-08
|
||||
22.00,2.59006,1.4037e-08
|
||||
22.00,2.64006,1.7411e-08
|
||||
22.00,2.69006,2.4266e-08
|
||||
23.00,2.49006,7.7011e-09
|
||||
23.00,2.54006,8.4929e-09
|
||||
23.00,2.59006,9.5513e-09
|
||||
23.00,2.64006,1.1054e-08
|
||||
23.00,2.69006,1.4002e-08
|
||||
24.00,2.49006,5.3858e-09
|
||||
24.00,2.54006,5.698e-09
|
||||
24.00,2.59006,6.161e-09
|
||||
24.00,2.64006,6.804e-09
|
||||
24.00,2.69006,8.1435e-09
|
||||
25.00,2.49006,4.2137e-09
|
||||
25.00,2.54006,4.3605e-09
|
||||
25.00,2.59006,4.5837e-09
|
||||
25.00,2.64006,4.8794e-09
|
||||
25.00,2.69006,5.3341e-09
|
||||
26.00,2.49006,4.1207e-09
|
||||
26.00,2.54006,4.2034e-09
|
||||
26.00,2.59006,4.3481e-09
|
||||
26.00,2.64006,4.4824e-09
|
||||
26.00,2.69006,4.9786e-09
|
||||
|
@@ -0,0 +1,46 @@
|
||||
energy,pitch,diode
|
||||
17.00,2.69000,1.5377e-07
|
||||
17.00,2.74000,5.5058e-07
|
||||
17.00,2.79000,2.8742e-05
|
||||
17.00,2.84000,2.992e-05
|
||||
17.00,2.89000,2.9921e-05
|
||||
18.00,2.69000,1.3257e-07
|
||||
18.00,2.74000,6.2784e-07
|
||||
18.00,2.79000,2.3012e-05
|
||||
18.00,2.84000,2.4082e-05
|
||||
18.00,2.89000,2.3995e-05
|
||||
19.00,2.69000,8.7067e-08
|
||||
19.00,2.74000,5.28e-07
|
||||
19.00,2.79000,1.4786e-05
|
||||
19.00,2.84000,1.5433e-05
|
||||
19.00,2.89000,1.5369e-05
|
||||
20.00,2.69000,7.5571e-08
|
||||
20.00,2.74000,5.949e-07
|
||||
20.00,2.79000,1.3098e-05
|
||||
20.00,2.84000,1.3572e-05
|
||||
20.00,2.89000,1.3423e-05
|
||||
21.00,2.69000,4.5569e-08
|
||||
21.00,2.74000,4.6722e-07
|
||||
21.00,2.79000,8.2723e-06
|
||||
21.00,2.84000,8.1305e-06
|
||||
21.00,2.89000,7.7839e-06
|
||||
22.00,2.69000,2.4394e-08
|
||||
22.00,2.74000,3.137e-07
|
||||
22.00,2.79000,4.103e-06
|
||||
22.00,2.84000,3.6481e-06
|
||||
22.00,2.89000,3.0803e-06
|
||||
23.00,2.69000,1.4056e-08
|
||||
23.00,2.74000,2.2905e-07
|
||||
23.00,2.79000,1.6164e-06
|
||||
23.00,2.84000,1.2537e-06
|
||||
23.00,2.89000,9.8993e-07
|
||||
24.00,2.69000,8.1539e-09
|
||||
24.00,2.74000,8.9029e-08
|
||||
24.00,2.79000,6.3203e-07
|
||||
24.00,2.84000,5.3339e-07
|
||||
24.00,2.89000,4.4881e-07
|
||||
25.00,2.69000,5.483e-09
|
||||
25.00,2.74000,4.3057e-08
|
||||
25.00,2.79000,2.6918e-07
|
||||
25.00,2.84000,2.318e-07
|
||||
25.00,2.89000,2.0125e-07
|
||||
|
@@ -0,0 +1,5 @@
|
||||
energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0
|
||||
6000,H3,5.9369,-5.5214,4.651,0.178,1091,483.8
|
||||
6300,H3,6.2143,-5.5161,4.648,0.15925,1091,484.7
|
||||
6600,H3,6.5006,-5.513,4.651,0.14414,1089,482.2
|
||||
6900,H3,6.8005,-5.5102,4.65,0.1312,1089,482.3
|
||||
|
@@ -0,0 +1,78 @@
|
||||
energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0
|
||||
7000,H3,6.9059,-5.5096,4.651,0.12717,1089,480.7
|
||||
7300,H5,4.551,-5.5071,4.649,0.11594,1088,479.5
|
||||
7600,H5,4.697,-5.5057,4.647,0.10671,1087,478.8
|
||||
7900,H5,4.8454,-5.5028,4.65,0.09833,1084,478.9
|
||||
8200,H5,4.9952,-5.5026,4.649,0.09104,1085,481.3
|
||||
8500,H5,5.1461,-5.5018,4.648,0.084215,1086,481.8
|
||||
8800,H5,5.2989,-5.5,4.649,0.07845,1086,480.4
|
||||
9100,H5,5.4534,-5.5001,4.649,0.0732,1089,479.5
|
||||
9400,H5,5.6102,-5.4982,4.651,0.068385,1086,478.2
|
||||
9700,H5,5.7706,-5.497,4.651,0.064125,1086,477.8
|
||||
10000,H5,5.9309,-5.4964,4.651,0.06021,1085,475.8
|
||||
10300,H7,4.5766,-5.4954,4.651,0.056655,1086,474.8
|
||||
10600,H7,4.6797,-5.4945,4.651,0.0534,1085,474.5
|
||||
10900,H7,4.7853,-5.4938,4.651,0.050445,1085,473.1
|
||||
11200,H7,4.8916,-5.4933,4.651,0.04773,1084,472.4
|
||||
11500,H7,4.9984,-5.4927,4.651,0.04519,1084,471.9
|
||||
11800,H7,5.106,-5.4923,4.648,0.042885,1084,471.5
|
||||
12100,H7,5.2144,-5.4917,4.65,0.04069,1084,471.1
|
||||
12400,H7,5.3238,-5.491,4.65,0.03866,1083,469.9
|
||||
12700,H7,5.434,-5.4907,4.65,0.0369,1084,470
|
||||
13000,H7,5.5453,-5.4902,4.65,0.035145,1083,469
|
||||
13300,H9,4.5975,-5.4899,4.651,0.033575,1083,470.3
|
||||
13600,H9,4.6739,-5.4896,4.65,0.03209,1083,468.8
|
||||
13900,H9,4.7564,-5.4892,4.648,0.03027,1083,468.6
|
||||
14200,H9,4.8387,-5.4888,4.646,0.0302,1083,467.8
|
||||
14500,H9,4.9214,-5.4885,4.651,0.02818,1083,467.8
|
||||
14800,H9,5.0041,-5.4885,4.649,0.02704,1085,467.4
|
||||
15100,H9,5.0875,-5.488,4.651,0.02703,1084,466.9
|
||||
15400,H9,5.1711,-5.4876,4.649,0.024565,1083,466.7
|
||||
15700,H9,5.2554,-5.487,4.65,0.024555,1083,466.5
|
||||
16000,H9,5.3397,-5.4871,4.648,0.023035,1083,466.1
|
||||
16300,H11,4.6154,-5.4868,4.648,0.023025,1083,467.3
|
||||
16600,H11,4.6825,-5.4866,4.649,0.021305,1083,467.6
|
||||
16900,H11,4.7494,-5.4858,4.649,0.02127,1082,466.9
|
||||
17200,H11,4.8184,-5.4858,4.649,0.01983,1083,468.4
|
||||
17500,H11,4.8873,-5.4856,4.648,0.01976,1082,467.8
|
||||
17800,H11,4.9557,-5.4854,4.65,0.018535,1082,467.9
|
||||
18100,H11,5.0243,-5.4853,4.65,0.01849,1083,467.2
|
||||
18400,H11,5.0929,-5.4846,4.649,0.017295,1083,466.8
|
||||
18700,H11,5.1629,-5.4847,4.648,0.017285,1083,466.9
|
||||
19000,H11,5.2347,-5.4846,4.65,0.017285,1083,466.1
|
||||
19300,H13,4.6243,-5.4842,4.65,0.015695,1082,465.7
|
||||
19600,H13,4.6808,-5.484,4.651,0.01564,1082,465.4
|
||||
19900,H13,4.7387,-5.4838,4.649,0.015625,1082,465
|
||||
20200,H13,4.7961,-5.4836,4.648,0.0144,1083,464.9
|
||||
20500,H13,4.8537,-5.4833,4.649,0.01437,1083,464.2
|
||||
20800,H13,4.9126,-5.4829,4.648,0.01436,1083,463.6
|
||||
21100,H13,4.971,-5.4833,4.649,0.01317,1082,464.1
|
||||
21400,H13,5.0299,-5.4823,4.651,0.01313,1082,464.2
|
||||
21700,H13,5.0894,-5.4829,4.649,0.013145,1081,463.8
|
||||
22000,H13,5.1481,-5.4828,4.65,0.013135,1083,463.6
|
||||
22300,H15,4.6281,-5.4829,4.649,0.01175,1083,463.9
|
||||
22600,H15,4.6771,-5.4826,4.651,0.011735,1083,464.4
|
||||
22900,H15,4.7273,-5.4825,4.65,0.01174,1082,463.7
|
||||
23200,H15,4.7774,-5.4824,4.648,0.01174,1083,463.7
|
||||
23500,H15,4.8264,-5.4822,4.649,0.010605,1082,463.8
|
||||
23800,H15,4.8783,-5.4821,4.65,0.010585,1082,463.6
|
||||
24100,H15,4.9262,-5.482,4.649,0.01058,1082,463.8
|
||||
24400,H15,4.9759,-5.4818,4.649,0.010585,1082,463.4
|
||||
24700,H15,5.0255,-5.4818,4.649,0.010595,1082,463.4
|
||||
25000,H15,5.078,-5.4818,4.648,0.0094,1082,463
|
||||
25300,H17,4.6289,-5.482,4.649,0.00939,1082,462.7
|
||||
25600,H17,4.6718,-5.4819,4.648,0.009385,1082,462.9
|
||||
25900,H17,4.7168,-5.4819,4.649,0.00939,1080,463.4
|
||||
26200,H17,4.7603,-5.4819,4.649,0.009385,1082,463.2
|
||||
26500,H17,4.803,-5.4817,4.649,0.0094,1081,463.5
|
||||
26800,H17,4.8495,-5.4814,4.651,0.00814,1082,463.7
|
||||
27100,H17,4.8965,-5.4815,4.649,0.008145,1080,464.1
|
||||
27400,H17,4.9377,-5.4816,4.65,0.008145,1081,463.1
|
||||
27700,H19,4.5375,-5.4817,4.649,0.008155,1081,461.8
|
||||
28000,H19,4.5909,-5.4818,4.65,0.008135,1082,462
|
||||
28300,H19,4.6433,-5.4815,4.649,0.00815,1081,463.5
|
||||
28600,H19,4.677,-5.4813,4.649,0.008155,1081,462.6
|
||||
28900,H19,4.7062,-5.4813,4.651,0.007025,1081,461.5
|
||||
29200,H19,4.7429,-5.4812,4.649,0.00701,1081,461.8
|
||||
29500,H19,4.7828,-5.4811,4.65,0.00702,1080,461.9
|
||||
29800,H19,4.822,-5.4814,4.651,0.007015,1081,462.6
|
||||
|
@@ -0,0 +1,83 @@
|
||||
energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0
|
||||
6000,H3,5.9369,-5.5214,4.651,0.178,1091,483.8
|
||||
6300,H3,6.2143,-5.5161,4.648,0.15925,1091,484.7
|
||||
6600,H3,6.5006,-5.513,4.651,0.14414,1089,482.2
|
||||
6900,H3,6.8005,-5.5102,4.65,0.1312,1089,482.3
|
||||
energy,harmonic,gap,pitch,roll,perp,samcam_x,samcam_y,zoom=501.0
|
||||
7000,H3,6.9059,-5.5096,4.651,0.12717,1089,480.7
|
||||
7300,H5,4.551,-5.5071,4.649,0.11594,1088,479.5
|
||||
7600,H5,4.697,-5.5057,4.647,0.10671,1087,478.8
|
||||
7900,H5,4.8454,-5.5028,4.65,0.09833,1084,478.9
|
||||
8200,H5,4.9952,-5.5026,4.649,0.09104,1085,481.3
|
||||
8500,H5,5.1461,-5.5018,4.648,0.084215,1086,481.8
|
||||
8800,H5,5.2989,-5.5,4.649,0.07845,1086,480.4
|
||||
9100,H5,5.4534,-5.5001,4.649,0.0732,1089,479.5
|
||||
9400,H5,5.6102,-5.4982,4.651,0.068385,1086,478.2
|
||||
9700,H5,5.7706,-5.497,4.651,0.064125,1086,477.8
|
||||
10000,H5,5.9309,-5.4964,4.651,0.06021,1085,475.8
|
||||
10300,H7,4.5766,-5.4954,4.651,0.056655,1086,474.8
|
||||
10600,H7,4.6797,-5.4945,4.651,0.0534,1085,474.5
|
||||
10900,H7,4.7853,-5.4938,4.651,0.050445,1085,473.1
|
||||
11200,H7,4.8916,-5.4933,4.651,0.04773,1084,472.4
|
||||
11500,H7,4.9984,-5.4927,4.651,0.04519,1084,471.9
|
||||
11800,H7,5.106,-5.4923,4.648,0.042885,1084,471.5
|
||||
12100,H7,5.2144,-5.4917,4.65,0.04069,1084,471.1
|
||||
12400,H7,5.3238,-5.491,4.65,0.03866,1083,469.9
|
||||
12700,H7,5.434,-5.4907,4.65,0.0369,1084,470
|
||||
13000,H7,5.5453,-5.4902,4.65,0.035145,1083,469
|
||||
13300,H9,4.5975,-5.4899,4.651,0.033575,1083,470.3
|
||||
13600,H9,4.6739,-5.4896,4.65,0.03209,1083,468.8
|
||||
13900,H9,4.7564,-5.4892,4.648,0.03027,1083,468.6
|
||||
14200,H9,4.8387,-5.4888,4.646,0.0302,1083,467.8
|
||||
14500,H9,4.9214,-5.4885,4.651,0.02818,1083,467.8
|
||||
14800,H9,5.0041,-5.4885,4.649,0.02704,1085,467.4
|
||||
15100,H9,5.0875,-5.488,4.651,0.02703,1084,466.9
|
||||
15400,H9,5.1711,-5.4876,4.649,0.024565,1083,466.7
|
||||
15700,H9,5.2554,-5.487,4.65,0.024555,1083,466.5
|
||||
16000,H9,5.3397,-5.4871,4.648,0.023035,1083,466.1
|
||||
16300,H11,4.6154,-5.4868,4.648,0.023025,1083,467.3
|
||||
16600,H11,4.6825,-5.4866,4.649,0.021305,1083,467.6
|
||||
16900,H11,4.7494,-5.4858,4.649,0.02127,1082,466.9
|
||||
17200,H11,4.8184,-5.4858,4.649,0.01983,1083,468.4
|
||||
17500,H11,4.8873,-5.4856,4.648,0.01976,1082,467.8
|
||||
17800,H11,4.9557,-5.4854,4.65,0.018535,1082,467.9
|
||||
18100,H11,5.0243,-5.4853,4.65,0.01849,1083,467.2
|
||||
18400,H11,5.0929,-5.4846,4.649,0.017295,1083,466.8
|
||||
18700,H11,5.1629,-5.4847,4.648,0.017285,1083,466.9
|
||||
19000,H11,5.2347,-5.4846,4.65,0.017285,1083,466.1
|
||||
19300,H13,4.6243,-5.4842,4.65,0.015695,1082,465.7
|
||||
19600,H13,4.6808,-5.484,4.651,0.01564,1082,465.4
|
||||
19900,H13,4.7387,-5.4838,4.649,0.015625,1082,465
|
||||
20200,H13,4.7961,-5.4836,4.648,0.0144,1083,464.9
|
||||
20500,H13,4.8537,-5.4833,4.649,0.01437,1083,464.2
|
||||
20800,H13,4.9126,-5.4829,4.648,0.01436,1083,463.6
|
||||
21100,H13,4.971,-5.4833,4.649,0.01317,1082,464.1
|
||||
21400,H13,5.0299,-5.4823,4.651,0.01313,1082,464.2
|
||||
21700,H13,5.0894,-5.4829,4.649,0.013145,1081,463.8
|
||||
22000,H13,5.1481,-5.4828,4.65,0.013135,1083,463.6
|
||||
22300,H15,4.6281,-5.4829,4.649,0.01175,1083,463.9
|
||||
22600,H15,4.6771,-5.4826,4.651,0.011735,1083,464.4
|
||||
22900,H15,4.7273,-5.4825,4.65,0.01174,1082,463.7
|
||||
23200,H15,4.7774,-5.4824,4.648,0.01174,1083,463.7
|
||||
23500,H15,4.8264,-5.4822,4.649,0.010605,1082,463.8
|
||||
23800,H15,4.8783,-5.4821,4.65,0.010585,1082,463.6
|
||||
24100,H15,4.9262,-5.482,4.649,0.01058,1082,463.8
|
||||
24400,H15,4.9759,-5.4818,4.649,0.010585,1082,463.4
|
||||
24700,H15,5.0255,-5.4818,4.649,0.010595,1082,463.4
|
||||
25000,H15,5.078,-5.4818,4.648,0.0094,1082,463
|
||||
25300,H17,4.6289,-5.482,4.649,0.00939,1082,462.7
|
||||
25600,H17,4.6718,-5.4819,4.648,0.009385,1082,462.9
|
||||
25900,H17,4.7168,-5.4819,4.649,0.00939,1080,463.4
|
||||
26200,H17,4.7603,-5.4819,4.649,0.009385,1082,463.2
|
||||
26500,H17,4.803,-5.4817,4.649,0.0094,1081,463.5
|
||||
26800,H17,4.8495,-5.4814,4.651,0.00814,1082,463.7
|
||||
27100,H17,4.8965,-5.4815,4.649,0.008145,1080,464.1
|
||||
27400,H17,4.9377,-5.4816,4.65,0.008145,1081,463.1
|
||||
27700,H19,4.5375,-5.4817,4.649,0.008155,1081,461.8
|
||||
28000,H19,4.5909,-5.4818,4.65,0.008135,1082,462
|
||||
28300,H19,4.6433,-5.4815,4.649,0.00815,1081,463.5
|
||||
28600,H19,4.677,-5.4813,4.649,0.008155,1081,462.6
|
||||
28900,H19,4.7062,-5.4813,4.651,0.007025,1081,461.5
|
||||
29200,H19,4.7429,-5.4812,4.649,0.00701,1081,461.8
|
||||
29500,H19,4.7828,-5.4811,4.65,0.00702,1080,461.9
|
||||
29800,H19,4.822,-5.4814,4.651,0.007015,1081,462.6
|
||||
|
@@ -0,0 +1,10 @@
|
||||
Roll, Y pos
|
||||
1,313.4
|
||||
2,351.5
|
||||
3,388.1
|
||||
4,425
|
||||
5,460
|
||||
6,494.7
|
||||
7,526.9
|
||||
8,558.8
|
||||
9,590.4
|
||||
|
@@ -0,0 +1,12 @@
|
||||
Roll, Y pos
|
||||
2,125.4
|
||||
2.5,194.1
|
||||
3,260.1
|
||||
3.5,325.8
|
||||
4,387.4
|
||||
4.5,446.9
|
||||
5,504.4
|
||||
5.5,558.2
|
||||
6,609.9
|
||||
6.5,658.1
|
||||
7,705.2
|
||||
|
@@ -0,0 +1,96 @@
|
||||
energy,pitch,diode
|
||||
10.00,2.89010,2.778e-05
|
||||
10.00,2.91510,2.7708e-05
|
||||
10.00,2.94010,2.7698e-05
|
||||
10.00,2.96510,2.7769e-05
|
||||
10.00,2.99010,2.7757e-05
|
||||
11.00,2.89010,7.9613e-05
|
||||
11.00,2.91510,7.9352e-05
|
||||
11.00,2.94010,7.9336e-05
|
||||
11.00,2.96510,7.9483e-05
|
||||
11.00,2.99010,7.9565e-05
|
||||
12.00,2.89010,7.449e-05
|
||||
12.00,2.91510,7.4458e-05
|
||||
12.00,2.94010,7.4567e-05
|
||||
12.00,2.96510,7.4801e-05
|
||||
12.00,2.99010,7.4712e-05
|
||||
13.00,2.89010,5.6131e-05
|
||||
13.00,2.91510,5.6056e-05
|
||||
13.00,2.94010,5.5966e-05
|
||||
13.00,2.96510,5.5828e-05
|
||||
13.00,2.99010,5.5948e-05
|
||||
14.00,2.89010,5.5324e-05
|
||||
14.00,2.91510,5.5195e-05
|
||||
14.00,2.94010,5.5113e-05
|
||||
14.00,2.96510,5.5187e-05
|
||||
14.00,2.99010,5.508e-05
|
||||
15.00,2.89010,4.1622e-05
|
||||
15.00,2.91510,4.1965e-05
|
||||
15.00,2.94010,4.2153e-05
|
||||
15.00,2.96510,4.2094e-05
|
||||
15.00,2.99010,4.2148e-05
|
||||
16.00,2.89010,2.8267e-05
|
||||
16.00,2.91510,2.8252e-05
|
||||
16.00,2.94010,2.8214e-05
|
||||
16.00,2.96510,2.8193e-05
|
||||
16.00,2.99010,2.8145e-05
|
||||
17.00,2.89010,2.1235e-05
|
||||
17.00,2.91510,2.1204e-05
|
||||
17.00,2.94010,2.1172e-05
|
||||
17.00,2.96510,2.1117e-05
|
||||
17.00,2.99010,2.1088e-05
|
||||
18.00,2.89010,1.7443e-05
|
||||
18.00,2.91510,1.7463e-05
|
||||
18.00,2.94010,1.7414e-05
|
||||
18.00,2.96510,1.7132e-05
|
||||
18.00,2.99010,1.7091e-05
|
||||
19.00,2.89010,1.1583e-05
|
||||
19.00,2.91510,1.1553e-05
|
||||
19.00,2.94010,1.1521e-05
|
||||
19.00,2.96510,1.1486e-05
|
||||
19.00,2.99010,1.144e-05
|
||||
20.00,2.89010,1.0526e-05
|
||||
20.00,2.91510,1.0445e-05
|
||||
20.00,2.94010,1.036e-05
|
||||
20.00,2.96510,1.0243e-05
|
||||
20.00,2.99010,1.0096e-05
|
||||
21.00,2.89010,6.2969e-06
|
||||
21.00,2.91510,6.0377e-06
|
||||
21.00,2.94010,5.7381e-06
|
||||
21.00,2.96510,5.4072e-06
|
||||
21.00,2.99010,5.0424e-06
|
||||
22.00,2.89010,2.5998e-06
|
||||
22.00,2.91510,2.3461e-06
|
||||
22.00,2.94010,2.0986e-06
|
||||
22.00,2.96510,1.8549e-06
|
||||
22.00,2.99010,1.6269e-06
|
||||
23.00,2.89010,8.4958e-07
|
||||
23.00,2.91510,7.6319e-07
|
||||
23.00,2.94010,6.9276e-07
|
||||
23.00,2.96510,6.2826e-07
|
||||
23.00,2.99010,5.6922e-07
|
||||
24.00,2.89010,3.8721e-07
|
||||
24.00,2.91510,3.5652e-07
|
||||
24.00,2.94010,3.3073e-07
|
||||
24.00,2.96510,3.0885e-07
|
||||
24.00,2.99010,2.892e-07
|
||||
25.00,2.89010,1.7873e-07
|
||||
25.00,2.91510,1.6681e-07
|
||||
25.00,2.94010,1.5642e-07
|
||||
25.00,2.96510,1.4637e-07
|
||||
25.00,2.99010,1.3626e-07
|
||||
26.00,2.89010,1.3718e-07
|
||||
26.00,2.91510,1.2827e-07
|
||||
26.00,2.94010,1.1991e-07
|
||||
26.00,2.96510,1.1148e-07
|
||||
26.00,2.99010,1.0365e-07
|
||||
27.00,2.89010,5.8959e-08
|
||||
27.00,2.91510,5.5025e-08
|
||||
27.00,2.94010,5.1655e-08
|
||||
27.00,2.96510,4.9044e-08
|
||||
27.00,2.99010,4.715e-08
|
||||
28.00,2.89010,3.8685e-08
|
||||
28.00,2.91510,3.7246e-08
|
||||
28.00,2.94010,3.6209e-08
|
||||
28.00,2.96510,3.5094e-08
|
||||
28.00,2.99010,3.3689e-08
|
||||
|
@@ -61,7 +61,7 @@ def get_data_from_history(
|
||||
"""Read data from the BEC history and return the X and Y data as arrays."""
|
||||
scan = bec.history[history_index]
|
||||
md = scan.metadata["bec"]
|
||||
motor_name = md["scan_motors"][0].decode()
|
||||
motor_name = md["scan_report_devices"][0].decode()
|
||||
scan_number = md["scan_number"]
|
||||
x_data = scan.devices[motor_name][motor_name].read()["value"]
|
||||
y_data = scan.devices[signal_name][signal_name].read()["value"]
|
||||
|
||||
@@ -231,10 +231,12 @@ def fit_history(
|
||||
# Perform fit and plot the data
|
||||
fit_result = fit(data, fit_params)
|
||||
plot_fitted_data_bec(data, fit_result)
|
||||
|
||||
|
||||
# Optionally move the motor to the peak position
|
||||
if move_to_peak:
|
||||
move_to_position(data["motor_device"], data["motor_name"], fit_result["centre"], data)
|
||||
return fit_result
|
||||
|
||||
|
||||
def scan_bpm(bpmname):
|
||||
|
||||
@@ -165,8 +165,8 @@ def get_dcm_motors_positions(energy_ev):
|
||||
"""
|
||||
# dcm_motor_values = get_value_from_lut(energy_ev)
|
||||
dcm_motor_values = {}
|
||||
# pitch = float(np.poly1d(Calibration.pitch)(energy_ev))
|
||||
pitch = -5.5
|
||||
pitch = float(np.poly1d(Calibration.pitch_calib)(energy_ev))
|
||||
# pitch = -5.5
|
||||
fpitch = 5.0
|
||||
roll = EnergyDefaults.mono_roll_value
|
||||
perp = calc_perp_position(energy_ev, print_result=False)
|
||||
|
||||
@@ -18,7 +18,7 @@ class EnergyDefaults:
|
||||
mono_fpitch = dev.dcm_fpitch
|
||||
mono_perp = dev.dcm_perp
|
||||
mono_roll = dev.dcm_froll
|
||||
mono_roll_value = 4.65
|
||||
mono_roll_value = 4.56
|
||||
LUT_table = "luts/energy_lut.csv"
|
||||
stripe_thresholds = {"silicon": 9000, "rhodium": 20000, "platinum": 40000}
|
||||
pitch_scan = {"halfwidth": 0.075, "steps": 20}
|
||||
@@ -28,8 +28,13 @@ class EnergyDefaults:
|
||||
class Calibration:
|
||||
"""Calibration parameters for PXII optics"""
|
||||
|
||||
pitch = np.array([4.61823701e-14, -1.97330772e-09, 2.89694543e-05, -5.34468669e00])
|
||||
roll = np.array([2.28291039e-03, -2.41928101e01])
|
||||
# pitch = np.array([4.61823701e-14, -1.97330772e-09, 2.89694543e-05, -5.34468669e00])
|
||||
pitch_calib = [-5.89030403e-19,
|
||||
4.85665619e-14,
|
||||
-1.49364459e-09,
|
||||
2.08652765e-05,
|
||||
-5.59843072e+00]
|
||||
# roll = np.array([2.28291039e-03, -2.41928101e01])
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
||||
Reference in New Issue
Block a user