Files
FAT-Servo-Load-Test/Python/plotScope.py
T
2026-08-25 08:16:26 +02:00

195 lines
4.4 KiB
Python

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,<Signal>" 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("<br>"):
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 "<br>" 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()