WORKAN WOOOO
This commit is contained in:
@@ -1,103 +0,0 @@
|
||||
# stolen from https://austinsnerdythings.com/2025/02/14/revisiting-microsecond-accurate-ntp-for-raspberry-pi-with-gps-pps-in-2025/
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
from datetime import datetime
|
||||
|
||||
def parse_chrony_stats(file_path):
|
||||
"""
|
||||
Parse chrony statistics log file and return a pandas DataFrame
|
||||
"""
|
||||
# read file contents first
|
||||
with open(file_path, 'r') as f:
|
||||
file_contents = f.readlines()
|
||||
|
||||
# for each line, if it starts with '=' or ' ', skip it
|
||||
file_contents = [line for line in file_contents if not line.startswith('=') and not line.startswith(' ')]
|
||||
|
||||
# exclude lines that include 'PPS'
|
||||
file_contents = [line for line in file_contents if 'PPS' not in line]
|
||||
|
||||
# Use StringIO to create a file-like object from the filtered contents
|
||||
from io import StringIO
|
||||
csv_data = StringIO(''.join(file_contents))
|
||||
|
||||
# Read the filtered data using pandas
|
||||
df = pd.read_csv(csv_data,
|
||||
delim_whitespace=True,
|
||||
names=['Date', 'Time', 'IP_Address', 'Std_dev', 'Est_offset', 'Offset_sd',
|
||||
'Diff_freq', 'Est_skew', 'Stress', 'Ns', 'Bs', 'Nr', 'Asym'])
|
||||
|
||||
|
||||
# Combine Date and Time columns into a datetime column
|
||||
df['timestamp'] = pd.to_datetime(df['Date'] + ' ' + df['Time'])
|
||||
|
||||
return df
|
||||
|
||||
def plot_est_offset(df):
|
||||
"""
|
||||
Create a plot of Est_offset vs time for each IP address
|
||||
"""
|
||||
plt.figure(figsize=(12, 6))
|
||||
|
||||
# Plot each IP address as a separate series
|
||||
for ip in df['IP_Address'].unique():
|
||||
ip_data = df[df['IP_Address'] == ip]
|
||||
plt.plot(ip_data['timestamp'], ip_data['Est_offset'],
|
||||
marker='o', label=ip, linestyle='-', markersize=4)
|
||||
|
||||
plt.xlabel('Time')
|
||||
plt.ylabel('Estimated Offset (seconds)')
|
||||
plt.title('Chrony Estimated Offset Over Time by IP Address')
|
||||
plt.legend()
|
||||
plt.grid(True)
|
||||
|
||||
# Rotate x-axis labels for better readability
|
||||
plt.xticks(rotation=45)
|
||||
|
||||
# Adjust layout to prevent label cutoff
|
||||
plt.tight_layout()
|
||||
|
||||
return plt
|
||||
|
||||
def analyze_chrony_stats(file_path):
|
||||
"""
|
||||
Main function to analyze chrony statistics
|
||||
"""
|
||||
# Parse the data
|
||||
df = parse_chrony_stats(file_path)
|
||||
|
||||
# Create summary statistics
|
||||
summary = {
|
||||
'IP Addresses': df['IP_Address'].nunique(),
|
||||
'Time Range': f"{df['timestamp'].min()} to {df['timestamp'].max()}",
|
||||
'Average Est Offset by IP': df.groupby('IP_Address')['Est_offset'].mean().to_dict(),
|
||||
'Max Est Offset by IP': df.groupby('IP_Address')['Est_offset'].max().to_dict(),
|
||||
'Min Est Offset by IP': df.groupby('IP_Address')['Est_offset'].min().to_dict(),
|
||||
'Median Est Offset by IP': df.groupby('IP_Address')['Est_offset'].median().to_dict()
|
||||
}
|
||||
|
||||
# Create the plot
|
||||
plot = plot_est_offset(df)
|
||||
|
||||
return df, summary, plot
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
file_path = "chrony_statistics.log" # Replace with your file path
|
||||
df, summary, plot = analyze_chrony_stats(file_path)
|
||||
|
||||
# Print summary statistics
|
||||
print("\nChrony Statistics Summary:")
|
||||
print("-" * 30)
|
||||
print(f"Number of IP Addresses: {summary['IP Addresses']}")
|
||||
print(f"Time Range: {summary['Time Range']}")
|
||||
print("\nAverage Estimated Offset by IP:")
|
||||
for ip, avg in summary['Average Est Offset by IP'].items():
|
||||
print(f"{ip}: {avg:.2e}")
|
||||
|
||||
print("\nMedian Estimated Offset by IP:")
|
||||
for ip, median in summary['Median Est Offset by IP'].items():
|
||||
print(f"{ip}: {median:.2e}")
|
||||
|
||||
# Show the plot
|
||||
plt.show()
|
||||
Reference in New Issue
Block a user