예제 #1
0
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()
예제 #2
0
    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()
예제 #3
0
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")
예제 #4
0
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)
예제 #5
0
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()
예제 #6
0
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
예제 #7
0
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)
예제 #8
0
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)
예제 #9
0
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()