initial commit
This commit is contained in:
@@ -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,<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()
|
||||
Reference in New Issue
Block a user