# -*- coding: utf-8 -*- """ Created on Sun Jan 12 09:38:12 2025 @author: tomoh """ import tkinter as tk from tkinter import filedialog import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg def fourier_self_deconvolution(x, y, deconvwidth, cutoff_freq, cutoff_rate): n = len(y) y_fft = np.fft.fft(y) freq = np.fft.fftfreq(n, d=(x[1] - x[0])) gaussian_filter = np.exp(-2 * (np.pi * deconvwidth * freq) ** 2) # Perform the deconvolution in the Fourier domain y_deconv_fft = y_fft / (gaussian_filter + 0.01) # Apply low-pass Fourier filter low_pass_filter = 1 / (1 + (freq / cutoff_freq) ** (2 * cutoff_rate)) y_filtered_fft = y_deconv_fft * low_pass_filter # Inverse FFT to transform back to the time domain y_deconv_smoothed = np.real(np.fft.ifft(y_filtered_fft)) return y_deconv_smoothed class FourierDeconvolutionApp: def __init__(self, root): self.root = root self.root.title("Fourier Self-Deconvolution") self.data = None self.x = None self.y = None self.create_widgets() def create_widgets(self): # Open File Button open_button = tk.Button(self.root, text="Open File", command=self.open_file) open_button.grid(row=0, column=0, padx=10, pady=10) # Deconvolution Width Slider tk.Label(self.root, text="Deconvolution Width").grid(row=1, column=0) self.deconv_width = tk.DoubleVar(value=0.001) self.deconv_width_slider = tk.Scale( self.root, from_=0.001, to=0.02, resolution=0.001, orient=tk.HORIZONTAL, variable=self.deconv_width, command=self.update_plot ) self.deconv_width_slider.grid(row=1, column=1) # Cutoff Frequency Slider tk.Label(self.root, text="Cutoff Frequency").grid(row=2, column=0) self.cutoff_freq = tk.DoubleVar(value=0.1) self.cutoff_freq_slider = tk.Scale( self.root, from_=0.01, to=0.5, resolution=0.01, orient=tk.HORIZONTAL, variable=self.cutoff_freq, command=self.update_plot ) self.cutoff_freq_slider.grid(row=2, column=1) # Cutoff Rate Slider tk.Label(self.root, text="Cutoff Rate").grid(row=3, column=0) self.cutoff_rate = tk.DoubleVar(value=1) self.cutoff_rate_slider = tk.Scale( self.root, from_=1, to=10, resolution=1, orient=tk.HORIZONTAL, variable=self.cutoff_rate, command=self.update_plot ) self.cutoff_rate_slider.grid(row=3, column=1) # Save File Button save_button = tk.Button(self.root, text="Save File", command=self.save_file) save_button.grid(row=5, column=0, columnspan=2, pady=10) # Canvas for Plot self.figure, self.ax = plt.subplots(figsize=(6, 4)) self.canvas = FigureCanvasTkAgg(self.figure, master=self.root) self.canvas.get_tk_widget().grid(row=6, column=0, columnspan=2, pady=10) def open_file(self): file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv"), ("Excel files", "*.xlsx")]) if file_path: if file_path.endswith(".csv"): self.data = pd.read_csv(file_path) elif file_path.endswith(".xlsx"): self.data = pd.read_excel(file_path) if self.data.shape[1] == 1: self.x = np.arange(len(self.data.iloc[:, 0])) self.y = self.data.iloc[:, 0].values else: self.x = self.data.iloc[:, 0].values self.y = self.data.iloc[:, 1].values tk.messagebox.showinfo("File Loaded", f"Data loaded successfully from {file_path}") self.update_plot() def update_plot(self, *args): if self.data is None: return deconv_width = self.deconv_width.get() * (self.x[-1] - self.x[0]) cutoff_freq = self.cutoff_freq.get() cutoff_rate = self.cutoff_rate.get() result = fourier_self_deconvolution(self.x, self.y, deconv_width, cutoff_freq, cutoff_rate) self.ax.clear() self.ax.plot(self.x, self.y, label="Original Signal", color="black") self.ax.plot(self.x, result, label="Deconvoluted Signal", color="red") self.ax.set_title("Fourier Self-Deconvolution") self.ax.set_xlabel("X") self.ax.set_ylabel("Y") self.ax.legend() self.canvas.draw() def save_file(self): if self.data is None: tk.messagebox.showerror("Error", "No data to save!") return file_path = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV files", "*.csv")]) if file_path: pd.DataFrame({"X": self.x, "Y": self.y}).to_csv(file_path, index=False) tk.messagebox.showinfo("File Saved", f"Data saved to {file_path}") if __name__ == "__main__": root = tk.Tk() app = FourierDeconvolutionApp(root) root.mainloop()