def main(felixfiles, location, norm_method, output_filename="averaged"): dat_location = location / "EXPORT" widget = FELion_Tk(title="Felix Averaged plot", location=location / "OUT") fig, canvas = widget.Figure() if norm_method == "Relative": ylabel = "Relative Depletion (%)" else: ylabel = "Norm. Intensity" ax = widget.make_figure_layout(title="Felix Averaged plot", xaxis="Wavenumber $cm^{-1}$", yaxis=ylabel, yscale="linear", savename="felix_averaged") datfiles = [ dat_location / f"{filename.stem}.dat" for filename in felixfiles ] avgfile = dat_location / f"{output_filename}.dat" wn, inten = read_dat_file(avgfile, norm_method) ax.plot(wn, inten, "k.-", label="Averaged", alpha=0.7, zorder=100) print(f"felix dat files: {datfiles}\nAveraged file: {avgfile}") for felixfile, datfile in zip(felixfiles, datfiles): wn, inten = read_dat_file(datfile, norm_method) ax.plot(wn, inten, ".", label=f"{felixfile.name}") widget.plot_legend = ax.legend() widget.mainloop()
def InteractivePlots(self): widget = FELion_Tk(title=self.felixfile, location=self.location/"OUT") self.fig, self.canvas = widget.Figure(dpi=120) self.ax = self.fig.add_subplot(111) self.line = Line2D(self.xs, self.ys, marker='s', ls='', ms=6, c='b', markeredgecolor='b', animated=True) self.ax.add_line(self.line) self.inter_xs = np.arange(self.xs[0], self.xs[-1]) self.funcLine = Line2D([], [], marker='', ls='-', c='b', animated=True) self.ax.add_line(self.funcLine) self.redraw_f_line() self._ind = None self.canvas.mpl_connect('draw_event', self.draw_callback) self.canvas.mpl_connect('button_press_event', self.button_press_callback) self.canvas.mpl_connect('key_press_event', self.key_press_callback) self.canvas.mpl_connect('button_release_event', self.button_release_callback) self.canvas.mpl_connect('motion_notify_event', self.motion_notify_callback) if not self.opo: res, b0, trap = var_find(f"{self.location}/DATA/{self.felixfile}") label = f"{self.felixfile}: Res:{res}; B0: {b0}ms; trap: {trap}ms" else: label = f"{self.felixfile}" self.baseline_data = widget.make_figure_layout(ax=self.ax, xdata=self.data[0], ydata=self.data[1], label=label, savename=self.felixfile, title=f"Create Baseline", xaxis="Wavenumber (cm-1)", yaxis="Counts", ls='', marker='o', ms=5, markeredgecolor='r', c='r') def on_closing(): def ask(check, change, txt=""): if check: yes = askyesno(f"Save corrected as {self.fname}{txt} file?", f"You haven't saved the corrected file\nPress 'Yes' to save the {txt} file and quit OR 'No' to just quit.") if yes: return change() else: return print(f"[{txt}] Changes haven't saved") else: return print(f"[{txt}] No changes have made") ask(self.felix_corrected, self.save_cfelix, ".cfelix") ask(self.baseline_corrected, self.SaveBase, ".base") widget.destroy() widget.protocol("WM_DELETE_WINDOW", on_closing) widget.mainloop()
def massplot(massfiles, tkplot): os.chdir(massfiles[0].parent) if tkplot: if len(massfiles) == 1: savename = massfiles[0].stem else: savename = "combined_masspec" widget = FELion_Tk(title=f"Mass spectrum: {savename}", location=massfiles[0].parent) fig, canvas = widget.Figure() ax = widget.make_figure_layout(title="Mass Spectrum", xaxis="Mass [u]", yaxis="Counts", yscale="log", savename=savename) else: data = {} for massfile in massfiles: masses_temp, counts_temp = np.genfromtxt(massfile).T res, b0, trap = var_find(massfile) label = f"{massfile.stem}: Res:{res}; B0: {b0}ms; trap: {trap}ms" if tkplot: ax.plot(masses_temp, counts_temp, label=label) else: data[massfile.stem] = { "x": list(masses_temp), "y": list(counts_temp), "name": label, "mode": "lines", "showlegend": True } if not tkplot: print("Done") sendData(data) else: widget.plot_legend = ax.legend() widget.mainloop() print("Done")
def main(filenames, delta, tkplot, gamma=None): global widget os.chdir(filenames[0].parent) if tkplot: widget = FELion_Tk(title="THz Scan", location=filenames[0].parent) fig, canvas = widget.Figure(default_save_widget=False) widget.save_fmt = widget.Entries("Entry", "png", 0.1, 0.05*9+0.02) widget.save_btn = widget.Buttons("Save", 0.5, 0.05*9, save_fig) if len(filenames) == 1: savename=filenames[0].stem else: savename = "averaged_thzScan" ax = widget.make_figure_layout(title="THz scan", xaxis="Frequency (GHz)", yaxis="Depletion (%)", savename=savename) fit_data = plot_thz(ax=ax, tkplot=True) widget.plot_legend = ax.legend(title=f"Intensity: {fit_data.max():.2f} %") widget.mainloop() else: data = plot_thz() sendData(data)
def opoplot(opofiles, tkplot): if tkplot: widget = FELion_Tk(title="Mass spectrum", location=opofiles[0].parent) fig, canvas = widget.Figure() if len(opofiles) == 1: savename = opofiles[0].stem else: savename = "combined_masspec" ax = widget.make_figure_layout(title="Mass Spectrum", xaxis="Mass [u]", yaxis="Counts", yscale="log", savename=savename) else: data = {"real": {}, "relative": {}} c = 0 for i, opofile in enumerate(opofiles): basefile = opofile.parent / f"{opofile.stem}.obase" wn, counts = np.genfromtxt(opofile).T baseCal = BaselineCalibrator(basefile) baseCounts = baseCal.val(wn) ratio = counts / baseCounts relative_depletion = (1 - ratio) * 100 label = f"{opofile.name}" if tkplot: ax.plot(wn, counts, label=label) else: data["real"][opofile.name] = { "x": list(wn), "y": list(counts), "name": label, "mode": "lines", "showlegend": True, "legendgroup": f'group{i}', "line": { "color": f"rgb{colors[c]}" }, } data["real"][f"{opofile.name}_line"] = { "x": list(wn), "y": list(baseCounts), "mode": "lines", "name": f"{opofile.name}_line", "marker": { "color": "black" }, "legendgroup": f'group{i}', "showlegend": False, } data["relative"][opofile.name] = { "x": list(wn), "y": list(relative_depletion), "name": label, "mode": "lines", "showlegend": True, "line": { "color": f"rgb{colors[c]}" } } c += 2 if c >= len(colors): c = 1 if not tkplot: sendData(data) else: widget.plot_legend = ax.legend() widget.mainloop()
class timescanplot: def __init__(self, scanfile, tkplot=False): self.scanfile = scanfile = pt(scanfile) self.location = location = scanfile.parent os.chdir(location) if tkplot: self.widget = FELion_Tk(title=scanfile, location=scanfile.parent) self.fig, self.canvas = self.widget.Figure( default_save_widget=False) self.widget.save_fmt = self.widget.Entries("Entry", "png", 0.1, 0.05 * 9 + 0.02) self.widget.save_btn = self.widget.Buttons("Save", 0.5, 0.05 * 9, self.savefig_timescan) savename = scanfile.stem ax = self.widget.make_figure_layout( title=f"Timescan: {scanfile.name}", xaxis="Time (ms)", yaxis="Counts", yscale="linear", savename=savename) self.widget.lines = {} if tkplot: time, mean, error = self.read_timescan_file(ax=ax) self.widget.lines["SUM"] = ax.errorbar(time, mean.sum(axis=0), yerr=error.sum(axis=0), label="SUM", fmt="k.-") self.widget.plot_legend = ax.legend() self.widget.mainloop() else: m = {} time, mean, error = self.read_timescan_file(tkplot=False, m=m) m["SUM"] = { "x": list(time), "y": list(mean.sum(axis=0)), "name": f"SUM", "mode": 'lines+markers', "line": { "color": "black" }, "error_y": { "type": "data", "array": list(error.sum(axis=0)), "visible": True } } sendData(m) self.time, self.mean, self.error = time, mean, error def get_data(self): return self.time, self.mean, self.error, self.mass, self.t_res, self.t_b0 def savefig_timescan(self): save_fname = f"{self.widget.name.get()}.{self.widget.save_fmt.get()}" print(f"Saving filename: {save_fname}") save_filename = self.location / save_fname if not self.widget.latex.get(): self.widget.save_fig() else: style_path = pt( __file__).parent / "matplolib_styles/styles/science.mplstyle" with plt.style.context([f"{style_path}"]): fig, ax = plt.subplots() time, mean, error = self.read_timescan_file(ax=ax) ax.errorbar(time, mean.sum(axis=0), yerr=error.sum(axis=0), label="SUM", fmt="k.-") ax.grid(self.widget.plotGrid.get()) legend = ax.legend(bbox_to_anchor=[1, 1], fontsize=self.widget.xlabelSz.get() / 2) legend.set_visible(self.widget.plotLegend.get()) # Setting title ax.set_title(self.widget.plotTitle.get().replace("_", "\_"), fontsize=self.widget.titleSz.get()) # Setting X and Y label if self.widget.plotYscale.get(): scale = "log" else: scale = "linear" ax.set(yscale=scale) ax.set(ylabel=self.widget.plotYlabel.get().replace("%", "\%"), xlabel=self.widget.plotXlabel.get()) # Xlabel and Ylabel fontsize ax.xaxis.label.set_size(self.widget.xlabelSz.get()) ax.yaxis.label.set_size(self.widget.ylabelSz.get()) ax.tick_params(axis='x', which='major', labelsize=self.widget.xlabelSz.get()) ax.tick_params(axis='y', which='major', labelsize=self.widget.ylabelSz.get()) try: fig.savefig(save_filename, dpi=self.widget.dpi_value.get() * 2) print(f"File saved:\n{save_filename}") if askokcancel( 'Open savedfile?', f'File: {save_fname}\nsaved in directory: {self.location}' ): print("Opening file: ", save_filename) os.system(f"{save_filename}") except: showerror("Error", traceback.format_exc(5)) def read_timescan_file(self, ax=None, tkplot=True, m=None): location = self.scanfile.parent skip = get_skip_line(self.scanfile.name, location) iterations = get_iterations(self.scanfile.name, location) # opening File data = np.genfromtxt(self.scanfile, skip_header=skip) cycle = int(len(data) / iterations.sum()) run = len(iterations) time = data[:, 1][:cycle] # in ms # Calculating mean and std_devs j, mass_count = 0, 0 mean, error, mass = [], [], [] t_res, t_b0 = var_find(self.scanfile, location, time=True) self.t_res, self.t_b0 = t_res, t_b0 self.timedata = { "mass_value": [], "time": [], "Counts": [], "error": [], "SUM": [], "SUM_error": [] } for iteration in iterations: k = iteration * cycle mass_value = data[:, 0][j:k + j][0] if mass_value in mass: mass_count += 1 mass_value = f'{mass_value}_{mass_count}' mass_sort = data[:, 2][j:k + j].reshape(iteration, cycle).mean(axis=0) error_sort = data[:, 2][j:k + j].reshape(iteration, cycle).std(axis=0) mass = np.append(mass, mass_value) mean = np.append(mean, mass_sort) error = np.append(error, error_sort) label = f"{mass_value}u[{iteration}]:{t_b0}ms[{t_res}V]" if tkplot: print(f"{mass_value}: error value:\n{error_sort}") self.widget.lines[f"{mass_value}"] = ax.errorbar( time, mass_sort, yerr=error_sort, label=label, fmt=".-") else: m[f"{mass_value}u"] = { "x": list(time), "y": list(mass_sort), "name": label, "mode": 'lines+markers', "error_y": { "type": "data", "array": list(error_sort), "visible": True } } j = k + j self.mass = mass mean = mean.reshape(run, cycle) error = error.reshape(run, cycle) return time, mean, error
class depletionplot: def __init__(self, location, resOnFile=None, resOffFile=None, power=None, nshots=10, massIndex=0, timeStart=1): self.location = pt(location) self.scanfiles = list(self.location.glob("*.scan")) self.resOnFile = resOnFile self.resOffFile = resOffFile self.power = {"resOn": power[0]/1000, "resOff": power[1]/1000} # mJ to J self.nshots = nshots self.massIndex = massIndex self.timeStart = timeStart self.widget = FELion_Tk(title="Depletion Plot", location=self.location) self.create_figure() self.startPlotting() self.widget.mainloop() def create_figure(self): self.fig, self.canvas = self.widget.Figure(default_widget=False, dpi=200) self.fig.suptitle("Depletion Scan") self.fig.subplots_adjust(top=0.86, bottom=0.20, right=0.97, wspace=0.34) self.ax0 = self.fig.add_subplot(121) self.ax1 = self.fig.add_subplot(122) def change_title(self, event=None): self.fig.suptitle(self.widget.plotTitle.get()) self.canvas.draw() def change_grid(self, event=None): self.ax0.grid(not self.grid.get()) self.ax1.grid(not self.grid.get()) self.canvas.draw() def change_legend(self, event=None): self.ax0.legend().set_visible(not self.plotlegend.get()) self.ax1.legend().set_visible(not self.plotlegend.get()) if not self.plotlegend.get(): fontSz = self.legend_slider.get() self.ax0.legend(labels=[self.lg1, self.lg2], title=f"Mass: {self.mass[0]}u, Res: {self.t_res}V, B0: {self.t_b0}ms", fontsize=fontSz, title_fontsize=fontSz+2) self.ax1.legend(["Fitted", f"A: {self.uA:.3uP}", "Experiment"], fontsize=fontSz+5) self.canvas.draw() def change_legend_size(self, event=None): fontSz = self.legend_slider.get() self.ax0.legend(labels=[self.lg1, self.lg2], title=f"Mass: {self.mass[0]}u, Res: {self.t_res}V, B0: {self.t_b0}ms", fontsize=fontSz, title_fontsize=fontSz+2) self.ax1.legend(["Fitted", f"A: {self.uA:.3uP}", "Experiment"], fontsize=fontSz+5) self.canvas.draw() def depletion_widgets(self, Koff, Kon, N, Na0, Nn0): # Position x0, x_diff = 0.1, 0.4 y, y_diff = 0.14, 0.05 # Row 1 self.widget.plotTitle = self.widget.Entries("Entry", "Depletion Scan", x0, y, bind_key=True, bind_func=self.change_title, relwidth=0.7) # Row 2 y += y_diff self.widget.koff_slider = self.widget.Sliders("Koff", Koff, x0, y, self.update, relwidth=0.5) self.widget.n_slider = self.widget.Sliders("N", N, x0, y+y_diff, self.update, relwidth=0.5) self.widget.kon_slider = self.widget.Sliders("Kon", Kon, x0, y+2*y_diff, self.update, relwidth=0.5) self.widget.na_slider = self.widget.Sliders("Na", Na0, x0, y+3*y_diff, self.update, relwidth=0.5) self.widget.nn_slider = self.widget.Sliders("Nn", Nn0, x0, y+4*y_diff, self.update, relwidth=0.5) # Row 3 y += 5*y_diff self.widget.Labels("ON", x0, y) self.widget.Labels("OFF", x0+x_diff, y) # Row 4 y += y_diff scanfiles_name = [name.name for name in self.scanfiles] self.widget.resOnList = self.widget.Dropdown(scanfiles_name, x0, y) self.widget.resOnList.set(self.resOnFile.name) self.widget.resOffList = self.widget.Dropdown(scanfiles_name, x0+x_diff, y) self.widget.resOffList.set(self.resOffFile.name) # Row 5 y += y_diff self.new_power = self.widget.Entries("Entry", "21, 21", x0, y) self.new_nshots = self.widget.Entries("Entry", 10, x0+x_diff, y) # Row 6 y += y_diff self.widget.Labels("MassIndex", x0, y) self.widget.Labels("TimeStartIndex", x0+x_diff, y) # Row 7 y += y_diff self.new_massIndex = self.widget.Entries("Entry", self.massIndex, x0, y, bind_return=True, bind_func=self.replot) self.new_timeStart = self.widget.Entries("Entry", self.timeStart, x0+x_diff, y, bind_return=True, bind_func=self.replot) # Row 8 y += y_diff self.submit = self.widget.Buttons("Replot", x0, y, self.replot) # Row 9 y += y_diff self.plotlegend = self.widget.Entries("Check", "Legend", x0, y, relwidth=0.2, default=True, bind_btn=True, bind_func = self.change_legend) self.legend_slider = self.widget.Sliders("", 5, x0+x_diff/2, y+0.02, self.change_legend_size, relwidth=0.3) # Row 10 y += y_diff self.grid = self.widget.Entries("Check", "Grid", x0, y, default=True, bind_btn=True, bind_func = self.change_grid) # Row 11 y += y_diff self.latex = self.widget.Entries("Check", "Latex", x0, y) self.save_fig = self.widget.Buttons("Save", x0+x_diff, y, self.savefig) def replot(self, event=None): self.ax0.clear() self.ax1.clear() self.resOnFile = self.location / self.widget.resOnList.get() self.resOffFile = self.location / self.widget.resOffList.get() power = np.asarray(self.new_power.get().split(","), dtype=np.float) self.power = {"resOn": power[0]/1000, "resOff": power[1]/1000} # mJ to J self.nshots = self.new_nshots.get() self.massIndex = int(self.new_massIndex.get()) self.timeStart = int(self.new_timeStart.get()) print(f"ON: {self.resOnFile}\nOFF: {self.resOffFile}\nPower: {self.power}\nMassIndex: {self.massIndex}\nTimeStartIndex: {self.timeStart}") self.startPlotting(make_slider_widget=False) self.canvas.draw() def startPlotting(self, make_slider_widget=True): try: self.ax0.set(xlabel="n*t*E (mJ)", ylabel="Counts", title="Res ON-OFF scan") self.ax1.set(xlabel="n*t*E (mJ)", ylabel="Relative abundace of active isomer", title="$D(t)=A*(1-e^{-K_{ON}*(ntE)})$") for ax in (self.ax0, self.ax1): ax.grid() # Get timescan details self.get_timescan_data() # Fitt resOff and resOn Koff, N = self.resOff_fit() Na0, Nn0, Kon = self.resOn_fit(Koff, N) # if make_slider_widget: self.make_slider(Koff, Kon, N, Na0, Nn0) if make_slider_widget: self.depletion_widgets(Koff, Kon, N, Na0, Nn0) else: self.widget.koff_slider.set(Koff) self.widget.n_slider.set(N) self.widget.kon_slider.set(Kon) self.widget.na_slider.set(Na0) self.widget.nn_slider.set(Nn0) self.runFit(Koff, Kon, N, Na0, Nn0) except: showerror("Error occured", traceback.format_exc(5)) def runFit(self, Koff, Kon, N, Na0, Nn0, plot=True): uKoff = uf(Koff, self.Koff_err) uN = uf(N, self.N_err) uNa0 = uf(Na0, self.Na0_err) uNn0 = uf(Nn0, self.Nn0_err) uKon = uf(Kon, self.Kon_err) self.lg1 = f"Kon: {uKon:.2uP}, Na: {uNa0:.2uP}, Nn: {uNn0:.2uP}" self.lg2 = f"Koff: {uKoff:.2uP}, N: {uN:.2uP}" self.ax0.legend(labels=[self.lg1, self.lg2], title=f"Mass: {self.mass[0]}u, Res: {self.t_res}V, B0: {self.t_b0}ms", fontsize=5, title_fontsize=7) self.get_depletion_fit(Koff, N, uKoff, uN, Na0, Nn0, Kon, uNa0, uNn0, uKon, plot) self.get_relative_abundance_fit(plot) self.ax1.legend(["Fitted", f"A: {self.uA:.3uP}", "Experiment"], fontsize=5, title_fontsize=7) def update(self, event=None): Koff = self.widget.koff_slider.get() Kon = self.widget.kon_slider.get() N = self.widget.n_slider.get() Na0 = self.widget.na_slider.get() Nn0 = self.widget.nn_slider.get() self.runFit(Koff, Kon, N, Na0, Nn0, plot=False) self.ax0_plot["resOn"].set_ydata(self.fitOn) self.ax0_plot["resOff"].set_ydata(self.fitOff) self.fit_plot.set_ydata(self.depletion_fitted) self.relativeFit_plot.set_ydata(self.relative_abundance) self.canvas.draw_idle() def savefig(self): try: if not self.latex.get(): save_name = f"{self.widget.name.get()}.png" save_file = self.location / save_name self.fig.savefig(save_file, dpi=self.widget.dpi_value.get()) print(f"File saved: {save_name} in {self.location}") showinfo("Saved", f"File saved: {save_name} in {self.location}") else: self.latexPlot() except: showerror("Error occured", traceback.format_exc(5)) def latexPlot(self): style_path = pt(__file__).parent / "matplolib_styles/styles/science.mplstyle" with plt.style.context([f"{style_path}"]): fig, ax0 = plt.subplots() fig2, ax1 = plt.subplots() ax0.set(xlabel="n*t*E (mJ)", ylabel="Counts", title="Res ON-OFF scan") ax1.set(xlabel="n*t*E (mJ)", ylabel="Relative abundace of active isomer", title="$D(t)=A*(1-e^{-K_{ON}*(ntE)})$") ax0.grid() ax1.grid() for index, fitY, i in zip(["resOn", "resOff"], [self.fitOn, self.fitOff], [0, 1]): ax0.errorbar(self.power[index], self.counts[index], yerr=self.error[index], fmt=f"C{i}.") ax0.plot(self.fitX, fitY, f"C{i}") ax1.errorbar(self.power["resOn"], self.depletion_exp, yerr=self.depletion_exp_err, fmt="k.") ax1.plot(self.fitX, self.depletion_fitted) ax1.plot(self.fitX, self.relative_abundance) ax0.legend(labels=["ResON", "ResOFF"], title=f"Mass: {self.mass[0]}u, Res: {self.t_res}V, B0: {self.t_b0}ms") ax1.legend(["Fitted", f"A: {self.uA:.3f}", "Experiment"]) save_name = f"{self.widget.name.get()}_timescan.png" save_name2 = f"{self.widget.name.get()}_depletion.png" save_file = self.location / save_name save_file2 = self.location / save_name2 fig.savefig(save_file, dpi=self.widget.dpi_value.get()*3) fig2.savefig(save_file2, dpi=self.widget.dpi_value.get()*3) showinfo("Saved", f"File saved: {save_name} and {save_name2} \nin {self.location}") def get_timescan_data(self): self.data1 = {"resOn":{}, "resOff": {}} self.time = {"resOn":[], "resOff": []} self.counts = {"resOn":[], "resOff": []} self.error = {"resOn":[], "resOff": []} self.ax0_plot = {} for index, scanfile, i in zip(["resOn", "resOff"], [self.resOnFile, self.resOffFile], [0, 1]): time, counts, error, self.mass, self.t_res, self.t_b0 = timescanplot(scanfile).get_data() time = time/1000 # ms to s self.time[index] = np.array(time[self.timeStart:]) self.counts[index] = np.array(counts[self.massIndex][self.timeStart:]) self.error[index] = np.array(error[self.massIndex][self.timeStart:]) self.power[index] = np.array((self.power[index] * self.nshots * self.time[index])) self.ax0.errorbar(self.power[index], self.counts[index], yerr=self.error[index], fmt=f"C{i}.") def N_OFF(self, x, K_OFF, N): return (N)*np.exp(-K_OFF*x) def resOff_fit(self, auto_plot=True): K_OFF_init = 0 N_init = self.counts["resOff"].max() pop_off, popc_off = curve_fit( self.N_OFF, self.power["resOff"], self.counts["resOff"], sigma=self.error["resOff"], absolute_sigma=True, p0=[K_OFF_init, N_init], bounds=[(-np.inf, 0), (np.inf, N_init*2)] ) perr_off = np.sqrt(np.diag(popc_off)) Koff, N= pop_off self.Koff_err, self.N_err= perr_off if auto_plot: return Koff, N def N_ON(self, x, Na0, Nn0, K_ON): K_OFF = self.Koff return Na0*np.exp(-K_ON*x)*np.exp(-K_OFF*x) + Nn0*np.exp(-K_OFF*x) def resOn_fit(self, Koff, N, auto_plot=True): self.Koff = Koff Na0_init, Nn0_init, K_ON_init = N, N/2, 0 pop_on, popc_on = curve_fit( self.N_ON, self.power["resOn"], self.counts["resOn"], sigma=self.error["resOn"], absolute_sigma=True, p0=[Na0_init, Nn0_init, K_ON_init], bounds=[(0, 0, -np.inf), (N , N*2, np.inf)] ) perr_on = np.sqrt(np.diag(popc_on)) Na0, Nn0, Kon = pop_on self.Na0_err, self.Nn0_err, self.Kon_err = perr_on if auto_plot: return Na0, Nn0, Kon def uN_OFF(self, x, uN, uK_OFF): return uN*unp.exp(-uK_OFF*x) def uN_ON(self, x, uNa0, uNn0, uK_OFF, uK_ON): return uNa0 * \ unp.exp(-uK_ON*x)*unp.exp(-uK_OFF*x) + uNn0*unp.exp(-uK_OFF*x) def get_depletion_fit(self, Koff, N, uKoff, uN, Na0, Nn0, Kon, uNa0, uNn0, uKon, plot=True): self.Kon = Kon self.Koff = Koff maxPower = np.append(self.power["resOn"], self.power["resOff"]).max()*2 self.fitX = np.linspace(0, maxPower, 20) ufitX = unp.uarray(self.fitX, np.zeros(len(self.fitX))) self.fitOn = self.N_ON(self.fitX, Na0, Nn0, self.Kon) self.fitOff = self.N_OFF(self.fitX, Koff, N) self.fitOn_with_err = self.uN_ON(ufitX, uNa0, uNn0, uKoff, uKon) self.fitOff_with_err = self.uN_OFF(ufitX, uKoff, uN) self.fitted_counts_error = {"resOn": unp.std_devs(self.fitOn_with_err), "resOff": unp.std_devs(self.fitOff_with_err)} print(f"Exp counts error: {self.error}\nFitted counts error: {self.fitted_counts_error}\n") self.fitted_counts = {"resOn":np.array(self.fitOn), "resOff": np.array(self.fitOff)} print(f"Counts: {self.counts}\nFitted: {self.fitted_counts}\n") if plot: for index, fitY, i in zip(["resOn", "resOff"], [self.fitOn, self.fitOff], [0, 1]): self.ax0_plot[index], = self.ax0.plot(self.fitX, fitY, f"C{i}") def Depletion(self, x, A): K_ON = self.Kon return A*(1-np.exp(-K_ON*x)) def get_relative_abundance_fit(self, plot=True): self.depletion_fitted = 1 - (self.fitted_counts["resOn"]/self.fitted_counts["resOff"]) depletion_fitted_with_err = 1 - (unp.uarray(self.fitted_counts["resOn"], self.fitted_counts_error["resOn"])/unp.uarray(self.fitted_counts["resOff"], self.fitted_counts_error["resOff"])) self.depletion_fitted_err = unp.std_devs(depletion_fitted_with_err) self.depletion_exp = 1 - (self.counts["resOn"]/self.counts["resOff"]) depletion_exp_with_err = 1 - (unp.uarray(self.counts["resOn"], self.error["resOn"])/unp.uarray(self.counts["resOff"], self.error["resOff"])) self.depletion_exp_err = unp.std_devs(depletion_exp_with_err) A_init = 0.5 pop_depletion, popc_depletion = curve_fit( self.Depletion, self.fitX, self.depletion_fitted, sigma=self.depletion_fitted_err, absolute_sigma=True, p0=[A_init], bounds=[(0), (1)] ) perr_depletion = np.sqrt(np.diag(popc_depletion)) A = pop_depletion A_err = perr_depletion self.uA = uf(A, A_err) print(f"A: {self.uA:.3uP}") self.relative_abundance = self.Depletion(self.fitX, A) if plot: self.ax1.errorbar(self.power["resOn"], self.depletion_exp, yerr=self.depletion_exp_err, fmt="k.") self.fit_plot, = self.ax1.plot(self.fitX, self.depletion_fitted) self.relativeFit_plot, = self.ax1.plot(self.fitX, self.relative_abundance)
def fit_all_peaks(filename, norm_method, prominence=None, width=None, height=None, fitall=False, overwrite=False, tkplot=False, fullfiles=None): wn, inten = read_dat_file(filename, norm_method) if tkplot: widget = FELion_Tk(title=f"Fitted: {filename.name}", location=filename.parent.parent / "OUT") fig, canvas = widget.Figure() if norm_method == "Relative": ylabel = "Relative Depletion (%)" else: ylabel = "Norm. Intensity" ax = widget.make_figure_layout(title=f"Experimental fitted Spectrum: {filename.name}", xaxis="Wavenumber $(cm^{-1})$", yaxis=ylabel, yscale="linear", savename=f"{filename.stem}_expfit") ax.plot(wn, inten, ".", label=filename.name) indices, _ = peak(inten, prominence=prominence, width=width, height=height) _["wn_range"] = np.array([wn[_["left_bases"]], wn[_["right_bases"]]]).T for item in _: _[item] = _[item].tolist() wn_ = list(wn[indices]) inten_ = list(inten[indices]) data = {"data": {}, "extras": _, "annotations":{}} if filename.stem == "averaged": line_color = "black" else: index = fullfiles.index(filename.stem) line_color = f"rgb{colors[2*index]}" data["data"] = { "x":wn_, "y":inten_, "name":"peaks", "mode":"markers", "marker":{ "color":"blue", "symbol": "star-triangle-up", "size": 12 } } data["annotations"] = [ { "x": x, "y": y, "xref": 'x', "yref": 'y', "text": f'{x:.2f}', "showarrow": True, "arrowhead": 2, "ax": -25, "ay": -40, "font":{"color":line_color}, "arrowcolor":line_color } for x, y in zip(wn_, inten_) ] dataToSend = [{"data": data["data"]}, {"extras":data["extras"]}, {"annotations":data["annotations"]}] if not fitall: sendData(dataToSend) else: location = filename.parent.parent output_filename = filename.stem fit_data = [{"data": data["data"]}, {"extras":data["extras"]}] filename = f"{output_filename}.expfit" datfile_location = location/"EXPORT" expfile = datfile_location/filename if overwrite: method = "w" else: method = "a" annotations = [] get_data = [] with open(expfile, method) as f: if overwrite: f.write(f"#Frequency\t#Freq_err\t#Sigma\t#Sigma_err\t#FWHM\t#FWHM_err\t#Amplitude\t#Amplitude_err\n") for wavelength in _["wn_range"]: get_data_temp, uline_freq, usigma, uamplitude, ufwhm, line_color = exp_fit(location, norm_method, wavelength[0], wavelength[1], output_filename, getvalue=True, fullfiles=fullfiles) if uline_freq.nominal_value < 0 or ufwhm.nominal_value > 100: continue if tkplot: print("Fitting for wavelength range: ", wavelength[0], wavelength[1]) ax.plot(get_data_temp["fit"]["x"], get_data_temp["fit"]["y"], "k-", label=get_data_temp["fit"]["name"]) xcord, ycord = uline_freq.nominal_value, uamplitude.nominal_value text_frac = 0.01 ax.annotate(f'{uline_freq:.2uP}', xy=(xcord, ycord), xycoords='data', xytext=(xcord+xcord*text_frac, ycord+ycord*text_frac), textcoords='data', arrowprops=dict(arrowstyle="->", connectionstyle="arc3") ) else: annotate = { "x": uline_freq.nominal_value, "y": uamplitude.nominal_value, "xref": 'x', "yref": 'y', "text": f'{uline_freq:.2uP}', "font":{"color":line_color}, "arrowcolor":line_color, "showarrow": True, "arrowhead": 2, "ax": -25, "ay": -40 } annotations.append(annotate) get_data.append(get_data_temp) f.write(f"{uline_freq.nominal_value:.4f}\t{uline_freq.std_dev:.4f}\t{usigma.nominal_value:.4f}\t{usigma.std_dev:.4f}\t{ufwhm.nominal_value:.4f}\t{ufwhm.std_dev:.4f}\t{uamplitude.nominal_value:.4f}\t{uamplitude.std_dev:.4f}\n") if tkplot: widget.plot_legend = ax.legend() widget.mainloop() else: fit_data.append({"annotations":annotations}) fit_data.append(get_data) sendData(fit_data)
def exp_theory(theoryfiles, location, norm_method, sigma, scale, tkplot, output_filename="averaged"): location = pt(location) if tkplot: widget = FELion_Tk(title="Exp. Vs Theory", location=theoryfiles[0].parent) fig, canvas = widget.Figure() if len(theoryfiles) == 1: savename = theoryfiles[0].stem else: savename = "Exp vs Theory" if norm_method == "Relative": ylabel = "Relative Depletion (%)" else: ylabel = "Norm. Intensity" ax = widget.make_figure_layout(title="Experimental vs Theory", xaxis="Wavenumber $(cm^{-1})$", yaxis=ylabel, yscale="linear", savename=savename) if location.name is "DATA": datfile_location = location.parent / "EXPORT" else: datfile_location = location / "EXPORT" avgfile = datfile_location / f"{output_filename}.dat" xs, ys = read_dat_file(avgfile, norm_method) if tkplot: ax.plot(xs, ys, "k-", label="Experiment", alpha=0.9) else: data = { "line_simulation": {}, "averaged": { "x": list(xs), "y": list(ys), "name": "Exp", "mode": "lines", "marker": { "color": "black" }, } } for theoryfile in theoryfiles: x, y = np.genfromtxt(theoryfile).T[:2] x = x * scale norm_factor = ys.max() / y.max() y = norm_factor * y theory_x, theory_y = [], [] for wn, inten in zip(x, y): size = 1000 diff = 4 * sigma x = np.linspace(wn - diff, wn + diff, size) y = gaussian(x, inten, sigma, wn) theory_x = np.append(theory_x, x) theory_y = np.append(theory_y, y) if tkplot: ax.fill(theory_x, theory_y, label=theoryfile.stem) else: data["line_simulation"][f"{theoryfile.name}"] = { "x": list(theory_x), "y": list(theory_y), "name": f"{theoryfile.stem}", "fill": "tozerox" } if not tkplot: sendData(data) else: widget.plot_legend = ax.legend() widget.mainloop()