Files
swissmx_tools/edge_scan/edge_scan_slic.py
2025-06-13 13:44:40 +02:00

156 lines
4.3 KiB
Python

#!/usr/bin/env python3
# authors M.Appleby + some code donated by J.Beale
"""
Martin needs to tidy this
# aim
Calculate FWHM of x-ray beam from an edge scan
# protocol
give run directory
To run and edge scan in Slic - may be a limit on how far and fast motor can move
# to execute directly in slic:
from devices.knife_edge import KnifeEdge
kn = KnifeEdge
scan = Scanner(default_acquisitions=[daq], condition=None)
scan.scan1D(kn.x, 4, 5, 0.1, 10, 'test_knife_edge_evr_only', detectors=[], channels=["SARES30-LSCP1-FNS:CH5:VAL_GET"], pvs=[])
"""
import os, glob
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
from scipy.optimize import curve_fit
from scipy.signal import peak_widths, find_peaks
from scipy import asarray as ar,exp
from math import sqrt, pi
from scipy.signal import savgol_filter
import argparse
from sfdata import SFDataFiles, SFScanInfo
def loadData(directory):
num_of_acqs=len([name for name in os.listdir(os.path.join(directory,'data'))])
print(num_of_acqs)
diode_data = []
for acquisition in range(1,num_of_acqs+1):
with SFDataFiles(os.path.join(directory,'data','acq{:04}.BSDATA.h5'.format(acquisition))) as data:
diode = data["SARES30-LSCP1-FNS:CH5:VAL_GET"].data
diode = diode.mean()
diode_data.append(diode)
scan = SFScanInfo(os.path.join(directory,'meta','scan.json'))
motor_positions = scan.readbacks
print(motor_positions)
print(len(diode_data), len(motor_positions))
return motor_positions, diode_data
def gauss(x, *p):
A, mu, sigma = p
return A * np.exp(-(x-mu)**2/(2.*sigma**2))
#def gauss(x, C, A, x0, sigma):
# return C + A*np.exp(-(x-x0)**2/(2.*sigma**2))
def getFWHM(motor_positions, diode_data):
#print(df.columns)
x_label='x motor'
y_label='diode'
x_vals = motor_positions*1000
y_vals = [i for i in diode_data]
y_vals = savgol_filter(y_vals, 15, 3)
fig, ax1 = plt.subplots()
ax1.scatter(x_vals, y_vals, label='edge_scan', color='blue')
plt.ylabel('Intensity (counts)')
plt.xlabel('Motor position (um)')
#plt.show()
dydx = np.gradient(y_vals, x_vals)
#dydx = dydx/max(dydx)
mean = sum((x_vals)*dydx)/sum(dydx)
sigma = sum(dydx*(mean)**2)/sum(dydx)
A= 1/(sigma*2*sqrt(pi))
dydx[np.isnan(dydx)] = 0
p0 = [100, mean, 5 ]
parameters, covariance = curve_fit( gauss, x_vals, dydx, p0=p0 )
x0_op = parameters[1]
# gaussian fit
gauss_y = gauss(x_vals, *parameters)
FWHM_x = np.abs(2*np.sqrt(2*np.log(2))*parameters[2])
# find peak centre
peaks = find_peaks( gauss_y )
# find fwhm peak width
fwhm_peak = peak_widths( gauss_y, peaks[0], rel_height=0.5 )
#fwhm_str = x_vals[int( round( fwhm_peak[2][0], 0 ))]
#fwhm_end = x_vals[int( round( fwhm_peak[3][0], 0 ))]
#fwhm = fwhm_str - fwhm_end
#fwhm_height = gauss_y[int( round( fwhm_peak[2][0], 0 ))]
# find 1/e2 peak width
#full_peak = peak_widths( gauss_y, peaks[0], rel_height=0.865 )
#full_str = x_vals[int( round( full_peak[2][0], 0 ))]
#full_end = x_vals[int( round( full_peak[3][0], 0 ))]
#full = full_str - full_end
#full_height = gauss_y[int( round( full_peak[2][0], 0 ))]
#print( "FWHM = {0}".format( fwhm ) )
print(FWHM_x)
#print( "1/e2 = {0}".format( full ) )
# plot
ax2 = ax1.twinx()
ax2.plot(x_vals, dydx,label ='derivative',color='red')
ax2.plot(x_vals,gauss_y,label='Gaussian fit',color ='orange')
plt.fill_between(x_vals,gauss_y,color='orange',alpha=0.5)
plt.axvspan(x0_op+FWHM_x/2,x0_op-FWHM_x/2, color='blue', alpha=0.75, lw=0, label='FWHM = {0}'.format(FWHM_x))
#plt.hlines(fwhm_height, fwhm_str, fwhm_end, color='green', label='FWHM (find_peaks) = {0}'.format(fwhm))
#plt.hlines(full_height, full_str, full_end, color='yellow', label='1/e2 = {0}'.format(full))
fig.legend(loc="upper left")
fig.tight_layout()
plt.show()
#plt.savefig(output_name+filename.split('/')[-1]+'FWHM_{0}.png'.format(sciFWHM_x))
return
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
"-i",
"--input",
help="location of input file",
type=str,
default="/sf/cristallina/data/p21736/raw/run0002/"
)
parser.add_argument(
"-t",
"--type",
help="laser or xray",
type=str,
#default="/sf/cristallina/data/p19150/raw/run0371/"
)
args = parser.parse_args()
x_data, y_data = loadData(args.input)
getFWHM(x_data, y_data)