import pandas as pd import plotly.graph_objects as go from plotly.subplots import make_subplots import tkinter as tk from tkinter import filedialog, messagebox # -------------------------------------------------- # CSV einlesen # -------------------------------------------------- def load_scope_csv(filename): with open(filename, "r", encoding="utf-8", errors="ignore") as f: lines = [line.strip() for line in f] # Headerzeile suchen header_idx = None signal_names = [] for i, line in enumerate(lines): if line.startswith("Name,ACTPOS"): header_idx = i cols = line.split(',') # Signalnamen aus den "Name," Paaren holen for j in range(0, len(cols), 2): if j + 1 < len(cols): signal_names.append(cols[j + 1]) break if header_idx is None: raise Exception("Signaldefinition nicht gefunden") # Datenblock suchen data_start = None for i in range(header_idx, len(lines)): if lines[i].startswith("
"): data_start = i + 1 break if data_start is None: raise Exception("Datenblock nicht gefunden") numeric_rows = [] for line in lines[data_start:]: if not line: continue if "
" in line: continue parts = line.split(",") try: float(parts[0]) numeric_rows.append(parts) except: continue if not numeric_rows: raise Exception("Keine Daten gefunden") # Zeit + Kanäle aufbauen time = [] signals = {name: [] for name in signal_names} for row in numeric_rows: time.append(float(row[0])) idx = 1 for signal in signal_names: signals[signal].append(float(row[idx])) idx += 2 df = pd.DataFrame({"Time_ms": time}) for sig in signal_names: df[sig] = signals[sig] return df # -------------------------------------------------- # Plot erstellen # -------------------------------------------------- def create_plot(): selected = [name for name, var in signal_vars.items() if var.get()] if not selected: messagebox.showwarning("Hinweis", "Mindestens ein Signal auswählen.") return fig = go.Figure() for signal in selected: fig.add_trace( go.Scatter( x=df["Time_ms"], y=df[signal], mode="lines", name=signal ) ) # Y-Achse if auto_scale_var.get(): y_range = None else: try: ymin = float(ymin_entry.get()) ymax = float(ymax_entry.get()) y_range = [ymin, ymax] except: messagebox.showerror("Fehler", "Ungültige Y-Achsen Werte") return fig.update_layout( title="TwinCAT Scope Daten", xaxis_title="Zeit [ms]", yaxis_title="Wert", yaxis_range=y_range, hovermode="x unified", template="plotly_white" ) fig.show() # -------------------------------------------------- # Datei auswählen # -------------------------------------------------- root = tk.Tk() root.withdraw() filename = filedialog.askopenfilename( title="TwinCAT Scope CSV auswählen", filetypes=[("CSV Dateien", "*.csv"), ("Alle Dateien", "*.*")] ) if not filename: raise SystemExit df = load_scope_csv(filename) # -------------------------------------------------- # GUI # -------------------------------------------------- root = tk.Tk() root.title("TwinCAT Scope Plotter") signal_vars = {} tk.Label(root, text="Signale auswählen").pack(anchor="w") for col in df.columns[1:]: var = tk.BooleanVar(value=True) tk.Checkbutton( root, text=col, variable=var ).pack(anchor="w") signal_vars[col] = var auto_scale_var = tk.BooleanVar(value=True) tk.Checkbutton( root, text="Automatische Y-Skalierung", variable=auto_scale_var ).pack(anchor="w", pady=10) frame = tk.Frame(root) frame.pack() tk.Label(frame, text="Y-Min").grid(row=0, column=0) ymin_entry = tk.Entry(frame, width=10) ymin_entry.grid(row=0, column=1) tk.Label(frame, text="Y-Max").grid(row=0, column=2) ymax_entry = tk.Entry(frame, width=10) ymax_entry.grid(row=0, column=3) tk.Button( root, text="Plot anzeigen", command=create_plot ).pack(pady=10) root.mainloop()