RustPhysicsMQ/analyze.py

149 lines
4.9 KiB
Python
Raw Normal View History

2026-02-04 17:54:41 +00:00
import tkinter as tk
from pathlib import Path
2026-02-04 17:54:41 +00:00
from tkinter import messagebox, ttk
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
class SimVisualizer:
def __init__(self, root: tk.Tk):
self.root = root
self.root.title("Simulation Data Viewer")
# --- Protocol Handler ---
# This handles the "X" button on the window frame
self.root.protocol("WM_DELETE_WINDOW", self.quit_app)
self.results_dir = Path("results")
self.df = None
self.current_file = None
self.setup_ui()
self.refresh_file_list()
def setup_ui(self):
# 1. Create a PanedWindow (Horizontal orientation)
self.paned_window = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL)
self.paned_window.pack(fill=tk.BOTH, expand=True)
# --- Sidebar Frame ---
# Note: We still define a width, but it's now the *initial* width
sidebar = ttk.Frame(self.paned_window, width=300, padding="10")
# 2. Add the sidebar to the PanedWindow
# 'weight=0' keeps it from growing automatically when the window is resized
self.paned_window.add(sidebar, weight=0)
ttk.Label(sidebar, text="Result Files", font=("Helvetica", 12, "bold")).pack(
pady=5
)
self.file_listbox = tk.Listbox(sidebar, height=15)
self.file_listbox.pack(fill=tk.X, pady=5)
self.file_listbox.bind("<<ListboxSelect>>", self.on_file_select)
ttk.Separator(sidebar, orient="horizontal").pack(fill="x", pady=10)
ttk.Label(sidebar, text="Select Axis", font=("Helvetica", 10, "bold")).pack(
pady=5
)
self.axis_var = tk.StringVar(value="x")
for axis in ["x", "y", "z"]:
ttk.Radiobutton(
sidebar,
text=f"{axis.upper()} Axis",
variable=self.axis_var,
value=axis,
command=self.update_plot,
).pack(anchor=tk.W)
# --- Quit Button ---
spacer = ttk.Label(sidebar, text="")
spacer.pack(fill=tk.Y, expand=True)
self.quit_button = ttk.Button(
sidebar, text="Quit Program", command=self.quit_app
)
self.quit_button.pack(fill=tk.X, pady=10)
# --- Plot Frame ---
self.plot_frame = ttk.Frame(self.paned_window, padding="10")
# 3. Add the plot frame to the PanedWindow
# 'weight=1' ensures the plot area expands to take up all remaining space
self.paned_window.add(self.plot_frame, weight=1)
2026-02-04 17:54:41 +00:00
self.fig, self.ax = plt.subplots(figsize=(8, 6))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.plot_frame)
self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
2026-02-04 17:54:41 +00:00
self.toolbar = NavigationToolbar2Tk(self.canvas, self.plot_frame)
self.toolbar.update()
2026-02-04 17:54:41 +00:00
def quit_app(self):
"""Cleanly close the plots and the application."""
plt.close("all")
self.root.destroy()
self.root.quit()
2026-02-04 17:54:41 +00:00
def refresh_file_list(self):
if not self.results_dir.exists():
self.results_dir.mkdir(parents=True)
2026-02-04 17:54:41 +00:00
csv_files = sorted(self.results_dir.glob("*.csv"))
self.file_listbox.delete(0, tk.END)
for f in csv_files:
self.file_listbox.insert(tk.END, f.name)
2026-02-04 17:54:41 +00:00
def on_file_select(self, event):
selection = self.file_listbox.curselection()
if selection:
filename = self.file_listbox.get(selection[0])
self.current_file = self.results_dir / filename
try:
self.df = pd.read_csv(self.current_file)
self.update_plot()
except Exception as e:
messagebox.showerror("Error", f"Could not load file: {e}")
2026-02-04 17:54:41 +00:00
def update_plot(self):
if self.df is None:
return
2026-02-04 17:54:41 +00:00
coord = self.axis_var.get()
self.ax.clear()
2026-02-04 17:54:41 +00:00
self.ax.plot(
self.df["time"], self.df[f"target_{coord}"], label=f"target_{coord}"
)
self.ax.plot(
self.df["time"], self.df[f"current_{coord}"], label=f"current_{coord}"
)
self.ax.plot(
self.df["time"], self.df[f"mot_{coord}"].clip(-1, 1), label=f"mot_{coord}"
)
2026-02-05 20:26:30 +00:00
# self.ax.plot(
# self.df["time"],
# self.df[f"dmot_{coord}"].clip(-1, 1),
# label=f"desired mot_{coord}",
# linestyle="--",
# )
2026-02-04 17:54:41 +00:00
self.ax.set_xlabel("Time (s)")
self.ax.set_ylabel("Value")
self.ax.set_title(f"{self.current_file.name}{coord.upper()} Axis")
self.ax.legend(loc="upper right")
self.ax.grid(True)
2026-02-04 17:54:41 +00:00
ymin, ymax = self.ax.get_ylim()
self.ax.set_ylim(min(ymin, -1.1), max(ymax, 1.1))
self.canvas.draw()
2026-02-04 17:54:41 +00:00
if __name__ == "__main__":
root = tk.Tk()
app = SimVisualizer(root)
root.mainloop()