import customtkinter as ctk import pandas as pd import matplotlib.pyplot as plt import numpy as np from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from tkinter import filedialog # Function to load data from file def load_data(): filename = filedialog.askopenfilename(title="Select CSV file", filetypes=(("CSV files", "*.csv"), ("All files", "*.*"))) return pd.read_csv(filename) # Function to update data def update_data(): global data data = load_data() update_plot(start_slider.get(), end_slider.get()) # Function to update plot based on slider values def update_plot(start_time, end_time): filtered_data = data[(data["Timestamp"] >= start_time) & (data["Timestamp"] <= end_time)] ax1.clear() ax1.plot(filtered_data["Timestamp"], filtered_data["Value"]) ax1.set_title("Time Domain") ax1.set_xlabel("Timestamp") ax1.set_ylabel("Value") # Remove DC offset data_without_dc = filtered_data["Value"] - filtered_data["Value"].mean() # Perform Fourier analysis fft_values = np.fft.fft(data_without_dc) frequencies = np.fft.fftfreq(len(filtered_data), d=1 / sampling_rate) amplitudes = np.abs(fft_values) # Consider only positive frequencies positive_frequencies = frequencies[:len(frequencies)//2] positive_amplitudes = amplitudes[:len(frequencies)//2] ax2.clear() ax2.plot(positive_frequencies, positive_amplitudes) ax2.set_title("Frequency Domain") ax2.set_xlabel("Frequency (Hz)") ax2.set_ylabel("Amplitude") canvas.draw() # Create the main CustomTkinter window root = ctk.CTk() root.title("CSV Plot with Two Sliders") # Set appearance mode (optional) ctk.set_appearance_mode("dark") # Choose between "dark", "light", or "system" # Create matplotlib figure and axes fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6)) canvas = FigureCanvasTkAgg(fig, master=root) canvas.get_tk_widget().pack(side=ctk.LEFT, fill=ctk.BOTH, expand=True) # Function to initialize the plot def init_plot(): global data global sampling_rate data = load_data() # Read the CSV file and extract timestamps timestamps = data["Timestamp"].tolist() # Calculate time differences time_diffs = [timestamps[i + 1] - timestamps[i] for i in range(len(timestamps) - 1)] # Calculate average time difference average_time_diff = sum(time_diffs) / len(time_diffs) # Sampling rate is the reciprocal of the average time difference sampling_rate = 1 / average_time_diff print("Sampling rate:", sampling_rate, "Hz") # Load only the last 10000 data points data = data.tail(10000) # Plot the initial data ax1.plot(data["Timestamp"], data["Value"]) ax1.set_title("Time Domain") ax1.set_xlabel("Timestamp") ax1.set_ylabel("Value") # Remove DC offset data_without_dc = data["Value"] - data["Value"].mean() # Perform Fourier analysis fft_values = np.fft.fft(data_without_dc) frequencies = np.fft.fftfreq(len(data), d=1 / sampling_rate) amplitudes = np.abs(fft_values) # Consider only positive frequencies positive_frequencies = frequencies[:len(frequencies)//2] positive_amplitudes = amplitudes[:len(frequencies)//2] # Plot frequency spectrum ax2.plot(positive_frequencies, positive_amplitudes) ax2.set_title("Frequency Domain") ax2.set_xlabel("Frequency (Hz)") ax2.set_ylabel("Amplitude") # Initialize the plot init_plot() # Create sliders start_slider = ctk.CTkSlider(master=root, from_=data["Timestamp"].min(), to=data["Timestamp"].max(), command=lambda value: update_plot(value, end_slider.get())) start_slider.pack() end_slider = ctk.CTkSlider(master=root, from_=data["Timestamp"].min(), to=data["Timestamp"].max(), command=lambda value: update_plot(start_slider.get(), value)) end_slider.pack() # Create a frame on the right side for displaying relevant information info_frame = ctk.CTkFrame(master=root) info_frame.pack(side=ctk.RIGHT, fill=ctk.BOTH, expand=True) # Labels for displaying information sampling_rate_label = ctk.CTkLabel(master=info_frame, text=f"Sampling Rate: {sampling_rate} Hz") sampling_rate_label.pack() max_frequency_label = ctk.CTkLabel(master=info_frame, text=f"Max Frequency: {sampling_rate / 2} Hz (Nyquist Frequency)") max_frequency_label.pack() # Button to change data file change_file_button = ctk.CTkButton(master=info_frame, text="Change File", command=update_data) change_file_button.pack() # Run the CustomTkinter event loop root.mainloop()