diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa96c50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.class +*.pyc +*/__pycache__/* +nb/PSSS/nbproject/private +nb/PSSS/build +nb/PSSS/dist diff --git a/nb/PSSS/nbproject/private/config.properties b/nb/PSSS/nbproject/private/config.properties deleted file mode 100644 index e69de29..0000000 diff --git a/nb/PSSS/nbproject/private/private.properties b/nb/PSSS/nbproject/private/private.properties deleted file mode 100644 index ecf6f54..0000000 --- a/nb/PSSS/nbproject/private/private.properties +++ /dev/null @@ -1,8 +0,0 @@ -compile.on.save=true -do.depend=false -do.jar=true -do.jlink=false -javac.debug=true -javadoc.preview=true -jlink.strip=false -user.properties.file=/afs/psi.ch/user/g/gobbo_a/.netbeans/12.2/build.properties diff --git a/nb/PSSS/nbproject/private/private.xml b/nb/PSSS/nbproject/private/private.xml deleted file mode 100644 index 4750962..0000000 --- a/nb/PSSS/nbproject/private/private.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/plugins/PSSS$1.class b/plugins/PSSS$1.class deleted file mode 100644 index 71bd3a3..0000000 Binary files a/plugins/PSSS$1.class and /dev/null differ diff --git a/plugins/PSSS$2.class b/plugins/PSSS$2.class deleted file mode 100644 index 8b40abc..0000000 Binary files a/plugins/PSSS$2.class and /dev/null differ diff --git a/plugins/PSSS$3.class b/plugins/PSSS$3.class deleted file mode 100644 index 5d27748..0000000 Binary files a/plugins/PSSS$3.class and /dev/null differ diff --git a/plugins/PSSS$4.class b/plugins/PSSS$4.class deleted file mode 100644 index e19db9c..0000000 Binary files a/plugins/PSSS$4.class and /dev/null differ diff --git a/plugins/PSSS$5.class b/plugins/PSSS$5.class deleted file mode 100644 index bf4a464..0000000 Binary files a/plugins/PSSS$5.class and /dev/null differ diff --git a/plugins/PSSS$6.class b/plugins/PSSS$6.class deleted file mode 100644 index 50706c2..0000000 Binary files a/plugins/PSSS$6.class and /dev/null differ diff --git a/plugins/PSSS$7.class b/plugins/PSSS$7.class deleted file mode 100644 index 6735e76..0000000 Binary files a/plugins/PSSS$7.class and /dev/null differ diff --git a/plugins/PSSS$8.class b/plugins/PSSS$8.class deleted file mode 100644 index 682d694..0000000 Binary files a/plugins/PSSS$8.class and /dev/null differ diff --git a/plugins/PSSS$9.class b/plugins/PSSS$9.class deleted file mode 100644 index 14e14ee..0000000 Binary files a/plugins/PSSS$9.class and /dev/null differ diff --git a/plugins/PSSS.class b/plugins/PSSS.class deleted file mode 100644 index 54b4ad5..0000000 Binary files a/plugins/PSSS.class and /dev/null differ diff --git a/script/cpython/psss.py b/script/cpython/psss.py new file mode 100755 index 0000000..e5ce177 --- /dev/null +++ b/script/cpython/psss.py @@ -0,0 +1,45 @@ +import numpy as np +from scipy.optimize import curve_fit +import sys + + +def gaus(x, a, x0, sigma, offset): + return offset + a * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2)) + +#Return [amp, mean_val, sigma, offset] +def fit_energy(e_from, e_to, steps, num_shots, data): + energy_range = np.linspace(e_from, e_to, steps) + energy_range_fit = np.linspace(energy_range[0], energy_range[-1], len(energy_range)*10) + centre_line_out = data[:,:,int(data.shape[2]/2)].mean(axis=1) + try: + popt,pcov = curve_fit(gaus,energy_range,centre_line_out,p0=[1,energy_range[np.argmax(centre_line_out)],energy_range.mean()*1e-3,1e3*num_shots]) + except: + raise Exception('Fit failed: spectrum might not be near scan range center \n' + str(sys.exc_info()[1])) + #print('Fit failed: spectrum might not be near scan range center') + #return None + max_ind = np.argmax(centre_line_out) + max_photon_energy=energy_range[max_ind] + print(max_photon_energy) + return popt, centre_line_out + + +#Return [amp, mean_val, sigma, offset] +def fit_crystal_height(xstal_from, xstal_to, steps, data): + xstal_range = np.linspace(xstal_from, xstal_to, steps) + projection = data.mean(axis=1).mean(axis=1) + offset = np.mean(projection[0:100]) + signal_centre = xstal_range[np.argmax(projection)] + xstal_range_fit = np.linspace(xstal_range[0], xstal_range[-1], len(xstal_range)*10) + try: + popt,pcov = curve_fit(gaus,xstal_range,projection,p0=[100,signal_centre,-0.2,offset]) + except: + raise Exception('Fit failed: spectrum might not be near scan range center \n' + str(sys.exc_info()[1])) + #print('Fit failed: spectrum might not be near scan range center') + #return None + return popt, projection + + +def get_signal_centre(data, data_range): + projection = data.mean(axis=1).mean(axis=1) + signal_centre = data_range[np.argmax(projection)] + return signal_centre, projection diff --git a/script/cpython/psss_plot.py b/script/cpython/psss_plot.py new file mode 100755 index 0000000..27080e2 --- /dev/null +++ b/script/cpython/psss_plot.py @@ -0,0 +1,32 @@ +import numpy as np +import matplotlib.pyplot as plt + + +def gaus(x, a, x0, sigma, offset): + return offset + a * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2)) + +def plot_energy(E_from, E_to, steps, Scan_spec, popt, measured_offset): + Energy_range = np.linspace(E_from, E_to, steps) + centre_line_out = Scan_spec[:,:,int(Scan_spec.shape[2]/2)].mean(axis=1) + Energy_range_fit = np.linspace(Energy_range[0], Energy_range[-1], len(Energy_range)*10) + + + plt.figure(figsize=[10,5]) + plt.subplot(121) + plt.title('PSSS scan of set photon energy') + plt.pcolormesh(np.arange(0,Scan_spec.shape[2]), Energy_range, Scan_spec.mean(axis=1),cmap='CMRmap') + plt.vlines(int(Scan_spec.shape[2]/2), Energy_range[0], Energy_range[-1],linestyles='--', colors='orange') + plt.xlim([0,Scan_spec.shape[2]]) + plt.xlabel('Camera pixel') + plt.ylabel('Set PSSS energy [eV] \n SARFE10-PSSS059:ENERGY') + + plt.subplot(122) + plt.title('At camera centre pixel %1i \nCalibrated energy = %.1f [eV]\n Offset from machine = %.1f [eV]'%(int(Scan_spec.shape[2]/2),popt[1],measured_offset)) + plt.plot(centre_line_out,Energy_range,linewidth = 2, color = 'orange',label ='measured') + try: + plt.plot(gaus(Energy_range_fit,*popt),Energy_range_fit,'r:',label='fit') + except: + pass + plt.xticks([]) + plt.legend() + plt.grid(True) \ No newline at end of file diff --git a/script/cpython/wrapper.py b/script/cpython/wrapper.py new file mode 100755 index 0000000..5aa4031 --- /dev/null +++ b/script/cpython/wrapper.py @@ -0,0 +1,36 @@ +from jeputils import * + +RELOAD_CPYTHON = not App.isDetached() + +def fit_energy(e_from, e_to, steps, num_shots, data): + data = to_array(data, 'd') + dims = [len(data), len(data[0]), len(data[0][0])] + data = Convert.flatten(data) + arr = to_npa(data, dims) + popt, centre_line_out = call_jep("cpython/psss", "fit_energy", [e_from, e_to, steps, num_shots, arr], reload=RELOAD_CPYTHON) + return popt.getData(), centre_line_out.getData() + +def fit_crystal_height(xstal_from, xstal_to, steps, data): + data = to_array(data, 'd') + dims = [len(data), len(data[0]), len(data[0][0])] + data = Convert.flatten(data) + arr = to_npa(data, dims) + popt, projection = call_jep("cpython/psss", "fit_crystal_height", [xstal_from, xstal_to, steps, arr], reload=RELOAD_CPYTHON) + return popt.getData(), projection.getData() + +def get_signal_centre(data, data_range): + data = to_array(data, 'd') + dims = [len(data), len(data[0]), len(data[0][0])] + data = Convert.flatten(data) + arr = to_npa(data, dims) + data_range = to_npa(to_array(data_range, 'd')) + signal_centre, projection = call_jep("cpython/psss", "get_signal_centre", [arr, data_range], reload=RELOAD_CPYTHON) + return signal_centre, projection.getData() + +def plot_energy(e_from, e_to, steps, data, popt, measured_offset): + data = to_array(data, 'd') + dims = [len(data), len(data[0]), len(data[0][0])] + data = Convert.flatten(data) + arr = to_npa(data, dims) + ret = call_jep("cpython/psss_plot", "plot_energy", [e_from, e_to, steps, arr, popt, measured_offset], reload=RELOAD_CPYTHON) + return ret diff --git a/script/local.py b/script/local.py index 39306ed..6ce8712 100755 --- a/script/local.py +++ b/script/local.py @@ -2,6 +2,183 @@ # Deployment specific global definitions - executed after startup.py ################################################################################################### +from mathutils import estimate_peak_indexes, fit_gaussians, create_fit_point_list +from mathutils import fit_polynomial,fit_gaussian, fit_harmonic, calculate_peaks, fit_gaussian_offset +from mathutils import PolynomialFunction, Gaussian, HarmonicOscillator, GaussianOffset +from plotutils import plot_function, plot_data + +import java.awt.Color as Color run("psss/psss") +################################################################################################### +# DRY RUN +################################################################################################### +def set_dry_run(value): + global dry_run + dry_run = value + +def is_dry_run(): + if "dry_run" in globals(): + return True if dry_run else False + return False + + +################################################################################################### +# Machine utilities +################################################################################################### + +def is_laser_on(): + return (caget ("SIN-TIMAST-TMA:Beam-Las-Delay-Sel",'d') == 0 ) + +def is_timing_ok(): + return caget("SIN-TIMAST-TMA:SOS-COUNT-CHECK") == 0 + +def get_repetition_rate(): + return caget("SIN-TIMAST-TMA:Evt-15-Freq-I") + + +################################################################################################### +# Shortcut to maths utilities +################################################################################################### + +def gfit(ydata, xdata = None): + """ + Gaussian fit + """ + if xdata is None: + xdata = frange(0, len(ydata), 1) + #ydata = to_list(ydata) + #xdata = to_list(xdata) + max_y= max(ydata) + index_max = ydata.index(max_y) + max_x= xdata[index_max] + print "Max index:" + str(index_max), + print " x:" + str(max_x), + print " y:" + str(max_y) + gaussians = fit_gaussians(ydata, xdata, [index_max,]) + (norm, mean, sigma) = gaussians[0] + p = plot([ydata],["data"],[xdata], title="Fit" )[0] + fitted_gaussian_function = Gaussian(norm, mean, sigma) + scale_x = [float(min(xdata)), float(max(xdata)) ] + points = max((len(xdata)+1), 100) + resolution = (scale_x[1]-scale_x[0]) / points + fit_y = [] + fit_x = frange(scale_x[0],scale_x[1],resolution, True) + for x in fit_x: + fit_y.append(fitted_gaussian_function.value(x)) + p.addSeries(LinePlotSeries("fit")) + p.getSeries(1).setData(fit_x, fit_y) + + if abs(mean - xdata[index_max]) < ((scale_x[0] + scale_x[1])/2): + print "Mean -> " + str(mean) + p.addMarker(mean, None, "Mean="+str(round(norm,2)), Color.MAGENTA.darker()) + return (norm, mean, sigma) + else: + p.addMarker(max_x, None, "Max="+str(round(max_x,2)), Color.GRAY) + print "Invalid gaussian fit: " + str(mean) + return (None, None, None) + + +def hfit(ydata, xdata = None): + """ + Harmonic fit + """ + if xdata is None: + xdata = frange(0, len(ydata), 1) + + max_y= max(ydata) + index_max = ydata.index(max_y) + max_x= xdata[index_max] + + start,end = min(xdata), max(xdata) + (amplitude, angular_frequency, phase) = fit_harmonic(ydata, xdata) + fitted_harmonic_function = HarmonicOscillator(amplitude, angular_frequency, phase) + + print "amplitude = ", amplitude + print "angular frequency = ", angular_frequency + print "phase = ", phase + + f = angular_frequency/ (2* math.pi) + print "frequency = ", f + + resolution = 4.00 # 1.00 + fit_y = [] + for x in frange(start,end,resolution, True): + fit_y.append(fitted_harmonic_function.value(x)) + fit_x = frange(start, end+resolution, resolution) + + p = plot(ydata,"data", xdata, title="HFit")[0] + p.addSeries(LinePlotSeries("fit")) + p.getSeries(1).setData(fit_x, fit_y) + + #m = (phase + math.pi)/ angular_frequency + m = -phase / angular_frequency + if (m