From c036e40fbeedec575acdb6cedcfbe6fd3753157c Mon Sep 17 00:00:00 2001 From: jmb05 Date: Wed, 19 Nov 2025 00:24:15 +0100 Subject: [PATCH] Added averages plotting --- README.md | 12 ++++++-- lib.py | 68 +++++++++++++++++++++++++++++++++++++++++++++ plot_average.py | 38 +++++++++++++++++++++++++ plot_concatenate.py | 9 ++++++ plotting.py | 42 ---------------------------- speedtesting.py | 33 ++-------------------- 6 files changed, 127 insertions(+), 75 deletions(-) create mode 100644 lib.py create mode 100644 plot_average.py create mode 100644 plot_concatenate.py delete mode 100644 plotting.py diff --git a/README.md b/README.md index 7422dc5..a5c41b5 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,18 @@ The script creates an output file `results_dd_mm_yyyy.csv`. The first line of th ## Plotting the Data -The `plotting.py` script plots the data of a given csv file. +The `plot_concatenate.py` script plots the data of all given csv files in one big plot. +The `plot_average.py` script plots the data of all given csv files by flooring the times +to the nearest hour and then averaging all them producing a plot for the averages at every hour. ### Usage -Execute the command: `.python/bin/python plotting.csv path/to/results_1.csv [path/to/results_2.csv...]`. +Execute the command: `.python/bin/python plot_concatenate.csv path/to/results_1.csv path/to/results_2.csv ...`. + +_or_ + +Execute the command: `.python/bin/python plot_average.csv path/to/results_1.csv path/to/results_2.csv ...`. ### Output -It creates a `bandwidth.svg` and a `ping_jitter.svg`, with the plot for up and down and the plot for ping and jitter respectively. The x-Axis shows the the time when the data was recorded and the y-Axis shows Mbps or ms. +It creates a `bandwidth.svg` and a `ping_jitter.svg`, with the plot for up and down and the plot for ping and jitter respectively. The x-Axis shows the time when the data was recorded and the y-Axis shows Mbps or ms. diff --git a/lib.py b/lib.py new file mode 100644 index 0000000..d51a975 --- /dev/null +++ b/lib.py @@ -0,0 +1,68 @@ +import os +import glob +import matplotlib.pyplot as plt +import math +import csv +from datetime import datetime +from cfspeedtest import CloudflareSpeedtest + +def run_test(): + suite = CloudflareSpeedtest() + results = suite.run_all() + tests = results['tests'] + time = tests['isp'].time + latency = tests['latency'].value + jitter = tests['jitter'].value + h_down = tests['100kB_down_bps'].value + o_down = tests['1MB_down_bps'].value + t_down = tests['10MB_down_bps'].value + q_down = tests['25MB_down_bps'].value + np_down = tests['90th_percentile_down_bps'].value + h_up = tests['100kB_up_bps'].value + o_up = tests['1MB_up_bps'].value + t_up = tests['10MB_up_bps'].value + np_up = tests['90th_percentile_up_bps'].value + return [time, latency, jitter, h_down, o_down, t_down, q_down, h_up, o_up, t_up, np_down, np_up] + +def write_data(filename, data): + with open(filename, 'a', newline='\n') as csvfile: + writer = csv.writer(csvfile) + if os.path.getsize(filename) == 0: + writer.writerow(['time','latency','jitter','100kB_down','1MB_down','10MB_down','25MB_down','100kB_up','1MB_up','10MB_up','90th_percentile_down','90th_percentile_up']) + writer.writerow(data) + +def plot(time, data1, data2, label1, label2, filename, autofmt=True, xticks=None): + fig_length = -11.36 + 5.46 * math.log(len(time)) + fig_length = max(6.0, fig_length) + plt.figure(figsize=[int(fig_length), 6]) + plt.plot(time, data1) + plt.plot(time, data2) + plt.legend([label1, label2]) + if autofmt: + plt.gcf().autofmt_xdate() + if xticks is not None: + plt.xticks(xticks) + plt.savefig(filename) + +def import_csv(filenames): + time_data = [] + ping_data = [] + jitter_data = [] + up_data = [] + down_data = [] + + for i in range(len(filenames)): + files = glob.glob(filenames[i]) + for j in range(len(files)): + with open(files[j], 'r', newline='\n') as csvfile: + reader = csv.reader(csvfile) + line_count = 0 + for row in reader: + if line_count != 0: + time_data.append(datetime.fromtimestamp(float(row[0]))) + ping_data.append(float(row[1])) + jitter_data.append(float(row[2])) + down_data.append(int(row[10]) / 1000000) + up_data.append(int(row[11]) / 1000000) + line_count += 1 + return time_data, ping_data, jitter_data, up_data, down_data \ No newline at end of file diff --git a/plot_average.py b/plot_average.py new file mode 100644 index 0000000..d9c6cef --- /dev/null +++ b/plot_average.py @@ -0,0 +1,38 @@ +import sys +import lib +import numpy as np + +time_data, ping_data, jitter_data, up_data, down_data = lib.import_csv(sys.argv[1:]) + +averaged_data = dict() + +for i in range(0, len(time_data)): + hour_truncated_time = time_data[i].replace(year=time_data[0].year, month=time_data[0].month, day=time_data[0].day, hour=time_data[i].hour, minute=0, second=0, microsecond=0) + averaged_data[hour_truncated_time] = [0, 0, 0, 0, 0] + + +for i in range(0, len(time_data)): + hour_truncated_time = time_data[i].replace(year=time_data[0].year, month=time_data[0].month, day=time_data[0].day, hour=time_data[i].hour, minute=0, second=0, microsecond=0) + averaged_data[hour_truncated_time][0] += ping_data[i] + averaged_data[hour_truncated_time][1] += jitter_data[i] + averaged_data[hour_truncated_time][2] += down_data[i] + averaged_data[hour_truncated_time][3] += up_data[i] + averaged_data[hour_truncated_time][4] += 1 + +truncated_hours = [] +averaged_ping_data = [] +averaged_jitter_data = [] +averaged_down_data = [] +averaged_up_data = [] + +for date in sorted(averaged_data): + truncated_hours.append(date.hour) + averaged_ping_data.append(averaged_data[date][0] / averaged_data[date][4]) + averaged_jitter_data.append(averaged_data[date][1] / averaged_data[date][4]) + averaged_down_data.append(averaged_data[date][2] / averaged_data[date][4]) + averaged_up_data.append(averaged_data[date][3] / averaged_data[date][4]) + +xticks = np.arange(0, 23, step=2) +lib.plot(truncated_hours, averaged_down_data, averaged_up_data, 'down', 'up', 'bandwidth.svg', autofmt=False, xticks=xticks) +lib.plot(truncated_hours, averaged_ping_data, averaged_jitter_data, 'ping', 'jitter', 'ping_jitter.svg', autofmt=False, xticks=xticks) + diff --git a/plot_concatenate.py b/plot_concatenate.py new file mode 100644 index 0000000..6238de7 --- /dev/null +++ b/plot_concatenate.py @@ -0,0 +1,9 @@ +import sys +import lib + +print(sys.argv) + +time_data, ping_data, jitter_data, up_data, down_data = lib.import_csv(sys.argv[1:]) + +lib.plot(time_data, down_data, up_data, 'down', 'up', 'bandwidth.svg') +lib.plot(time_data, ping_data, jitter_data, 'ping', 'jitter', 'ping_jitter.svg') diff --git a/plotting.py b/plotting.py deleted file mode 100644 index fcd8421..0000000 --- a/plotting.py +++ /dev/null @@ -1,42 +0,0 @@ -import csv -import matplotlib.pyplot as plt -import numpy as np -import sys -from datetime import datetime -import math - -time_data = [] -ping_data = [] -jitter_data = [] -up_data = [] -down_data = [] - -for i in range(1, len(sys.argv)): - with open(sys.argv[i], 'r', newline='\n') as csvfile: - reader = csv.reader(csvfile) - line_count = 0 - for row in reader: - if line_count != 0: - time_data.append(datetime.fromtimestamp(float(row[0]))) - ping_data.append(float(row[1])) - jitter_data.append(float(row[2])) - down_data.append(int(row[10]) / 1000000) - up_data.append(int(row[11]) / 1000000) - line_count += 1 - -fig_length = -11.36 + 5.46 * math.log(len(time_data)) -fig_length = max(6, fig_length) -print(fig_length) -plt.figure(figsize=[int(fig_length),6]) -plt.plot(time_data, down_data) -plt.plot(time_data, up_data) -plt.legend(['down', 'up']) -plt.gcf().autofmt_xdate() -plt.savefig("bandwidth.svg") -plt.figure(figsize=[6,6]) -plt.plot(time_data, ping_data) -plt.plot(time_data, jitter_data) -plt.legend(['ping', 'jitter']) -plt.gcf().autofmt_xdate() -plt.savefig("ping_jitter.svg") - diff --git a/speedtesting.py b/speedtesting.py index b466dc5..5e369a6 100644 --- a/speedtesting.py +++ b/speedtesting.py @@ -1,32 +1,5 @@ -from cfspeedtest import CloudflareSpeedtest -import os -import csv import datetime - -def run_test(): - suite = CloudflareSpeedtest() - results = suite.run_all() - tests = results['tests'] - time = tests['isp'].time - latency = tests['latency'].value - jitter = tests['jitter'].value - h_down = tests['100kB_down_bps'].value - o_down = tests['1MB_down_bps'].value - t_down = tests['10MB_down_bps'].value - q_down = tests['25MB_down_bps'].value - np_down = tests['90th_percentile_down_bps'].value - h_up = tests['100kB_up_bps'].value - o_up = tests['1MB_up_bps'].value - t_up = tests['10MB_up_bps'].value - np_up = tests['90th_percentile_up_bps'].value - return [time, latency, jitter, h_down, o_down, t_down, q_down, h_up, o_up, t_up, np_down, np_up] - -def write_data(filename, data): - with open(filename, 'a', newline='\n') as csvfile: - writer = csv.writer(csvfile) - if os.path.getsize(filename) == 0: - writer.writerow(['time','latency','jitter','100kB_down','1MB_down','10MB_down','25MB_down','100kB_up','1MB_up','10MB_up','90th_percentile_down','90th_percentile_up']) - writer.writerow(data) +import lib now = datetime.datetime.now() print("Starting speedtest " + now.strftime("%H:%M:%S")) @@ -34,8 +7,8 @@ date = now.strftime("%d-%m-%Y") filename_lan = 'results_' + date + '_lan.csv' filename_wlan = 'results_' + date + '_wlan.csv' -lan_data = run_test() -write_data(filename_lan, lan_data) +lan_data = lib.run_test() +lib.write_data(filename_lan, lan_data) #if os.system("/bin/bash /home/pi/speedtesting/disable_eth.sh") == 0: # print('Disabled ethernet') # wlan_data = run_test()