diff --git a/Python/plotScope.py b/Python/plotScope.py new file mode 100644 index 0000000..34b1bc3 --- /dev/null +++ b/Python/plotScope.py @@ -0,0 +1,194 @@ +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()