import re import datetime as dt import matplotlib.pyplot as plt import tkinter as tk from tkinter import filedialog, messagebox def parse_log(file_path): t = [] rms = [] freq = [] with open(file_path, encoding='utf-8', errors='ignore') as f: for line in f: # Match only valid ptp4l stat lines match = re.search( r'^(\w+ \d+ \d+:\d+:\d+).*rms (\d+).*freq ([+-]?\d+)', line ) if match: try: # Add year (needed for parsing) timestr = match.group(1) + " 2026" timestamp = dt.datetime.strptime( timestr, "%b %d %H:%M:%S %Y" ) t.append(timestamp) rms.append(int(match.group(2))) freq.append(int(match.group(3))) except Exception: # Skip malformed lines safely pass return t, rms, freq def plot_data(t, rms, freq): if not t: messagebox.showerror("Error", "No valid PTP lines found.") return fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True) ax1.plot(t, rms) ax1.set_ylabel("RMS (ns)") ax1.set_title("PTP RMS Offset") ax2.plot(t, freq) ax2.set_ylabel("Frequency deviation") ax2.set_xlabel("Time") ax2.set_title("PTP Frequency Deviation") plt.xticks(rotation=30) plt.tight_layout() plt.show() def open_file(): file_path = filedialog.askopenfilename( title="Select PTP log file", filetypes=[("Log files", "*.log *.txt"), ("All files", "*.*")] ) if not file_path: return t, rms, freq = parse_log(file_path) plot_data(t, rms, freq) # --- GUI setup --- root = tk.Tk() root.title("PTP Log Viewer") root.geometry("300x150") label = tk.Label(root, text="PTP Log Plotter", font=("Arial", 14)) label.pack(pady=10) btn = tk.Button(root, text="Open Log File", command=open_file) btn.pack(pady=10) root.mainloop()