181 lines
6.3 KiB
Python
181 lines
6.3 KiB
Python
import pandas as pd
|
|
from statistics import multimode, mean, median, stdev
|
|
import matplotlib.pyplot as plt
|
|
from matplotlib.backends.backend_pdf import PdfPages
|
|
|
|
def calculate_statistics(execution_times):
|
|
"""Calculate mean, median, mode, and standard deviation."""
|
|
mean_time = mean(execution_times)
|
|
median_time = median(execution_times)
|
|
modes = multimode(execution_times)
|
|
std_dev = stdev(execution_times)
|
|
|
|
# Handle multiple modes
|
|
if len(modes) == 1:
|
|
mode_time = modes[0]
|
|
else:
|
|
mode_time = modes # List of modes
|
|
|
|
return mean_time, median_time, mode_time, std_dev
|
|
|
|
def plot_histogram(execution_times, mean_time, median_time, mode_time, std_dev):
|
|
"""Plot a histogram of execution times with mean, median, mode, and standard deviation."""
|
|
plt.figure(figsize=(10, 6))
|
|
|
|
# Define bin range to focus between 25 and 35 ms
|
|
bin_start = 25
|
|
bin_end = 35
|
|
bins = list(range(bin_start, bin_end + 1)) # Bins from 25 to 35
|
|
|
|
# Plot the main histogram
|
|
plt.hist(execution_times, bins=bins, edgecolor='black', alpha=0.7, label='Execution Times (25-35 ms)')
|
|
|
|
# Plot outliers (below 25 or above 35 ms)
|
|
outliers = [x for x in execution_times if x < bin_start or x > bin_end]
|
|
if outliers:
|
|
# Determine appropriate bins for outliers
|
|
outlier_min = min(outliers)
|
|
outlier_max = max(outliers)
|
|
outlier_bins = list(range(outlier_min, outlier_max + 2))
|
|
plt.hist(outliers, bins=outlier_bins, edgecolor='black', alpha=0.7, color='red', label='Outliers (<25 or >35 ms)')
|
|
|
|
plt.title('Histogram of Execution Times')
|
|
plt.xlabel('Execution Time (ms)')
|
|
plt.ylabel('Frequency')
|
|
|
|
# Plot mean
|
|
plt.axvline(mean_time, color='blue', linestyle='dashed', linewidth=1.5, label=f'Mean: {mean_time:.2f} ms')
|
|
|
|
# Plot median
|
|
plt.axvline(median_time, color='green', linestyle='dashed', linewidth=1.5, label=f'Median: {median_time} ms')
|
|
|
|
# Plot mode(s)
|
|
if isinstance(mode_time, list):
|
|
for m in mode_time:
|
|
plt.axvline(m, color='purple', linestyle='dashed', linewidth=1.5, label=f'Mode: {m} ms')
|
|
else:
|
|
plt.axvline(mode_time, color='purple', linestyle='dashed', linewidth=1.5, label=f'Mode: {mode_time} ms')
|
|
|
|
# Shade the area within one standard deviation from the mean
|
|
plt.axvspan(mean_time - std_dev, mean_time + std_dev, color='yellow', alpha=0.2, label='±1 Standard Deviation')
|
|
|
|
# Set x-axis limits to focus on 25-35 ms with some padding for outliers
|
|
plt.xlim(bin_start - 5, bin_end + 5) # Extending a bit to show outliers
|
|
|
|
plt.legend()
|
|
plt.tight_layout()
|
|
return plt.gcf() # Return the current figure
|
|
|
|
def plot_boxplot(execution_times):
|
|
"""Plot a box plot of execution times."""
|
|
plt.figure(figsize=(10, 6))
|
|
plt.boxplot(execution_times, vert=False, patch_artist=True, boxprops=dict(facecolor='lightblue'))
|
|
plt.title('Box Plot of Execution Times')
|
|
plt.xlabel('Execution Time (ms)')
|
|
plt.tight_layout()
|
|
return plt.gcf()
|
|
|
|
def generate_pdf_report(csv_file, output_pdf):
|
|
"""Generate a PDF report containing statistics and visualizations."""
|
|
# Read the CSV file with error handling
|
|
try:
|
|
data = pd.read_csv(csv_file)
|
|
except FileNotFoundError:
|
|
print(f"Error: The file '{csv_file}' was not found.")
|
|
return
|
|
except pd.errors.EmptyDataError:
|
|
print(f"Error: The file '{csv_file}' is empty.")
|
|
return
|
|
except pd.errors.ParserError:
|
|
print(f"Error: The file '{csv_file}' does not appear to be in CSV format.")
|
|
return
|
|
|
|
# Check if 'ExecutionTime_ms' column exists
|
|
if 'ExecutionTime_ms' not in data.columns:
|
|
print("Error: 'ExecutionTime_ms' column not found in the CSV file.")
|
|
return
|
|
|
|
# Extract execution times
|
|
execution_times = data['ExecutionTime_ms'].tolist()
|
|
|
|
# Validate execution times
|
|
if not execution_times:
|
|
print("Error: No execution time data found.")
|
|
return
|
|
|
|
# Check for non-numeric values
|
|
non_numeric = [x for x in execution_times if not isinstance(x, (int, float))]
|
|
if non_numeric:
|
|
print("Error: Non-numeric values found in 'ExecutionTime_ms' column.")
|
|
print(non_numeric)
|
|
return
|
|
|
|
# Check if there are enough data points for standard deviation
|
|
if len(execution_times) < 2:
|
|
print("Error: At least two execution time data points are required to calculate standard deviation.")
|
|
return
|
|
|
|
# Calculate statistics
|
|
mean_time, median_time, mode_time, std_dev = calculate_statistics(execution_times)
|
|
|
|
# Debug print statements
|
|
print(f"Mean: {mean_time:.2f} ms")
|
|
print(f"Median: {median_time} ms")
|
|
print(f"Mode: {mode_time if isinstance(mode_time, list) else [mode_time]} ms")
|
|
print(f"Standard Deviation: {std_dev:.2f} ms")
|
|
|
|
# Create histogram plot with standard deviation shaded
|
|
fig_hist = plot_histogram(execution_times, mean_time, median_time, mode_time, std_dev)
|
|
|
|
# Create box plot
|
|
fig_box = plot_boxplot(execution_times)
|
|
|
|
# Prepare statistics text
|
|
if isinstance(mode_time, list):
|
|
mode_str = ', '.join(map(str, mode_time))
|
|
else:
|
|
mode_str = str(mode_time)
|
|
|
|
stats_text = f"""
|
|
Execution Time Statistics
|
|
=========================
|
|
|
|
Total Runs: {len(execution_times)}
|
|
|
|
Mean: {mean_time:.2f} ms
|
|
Median: {median_time} ms
|
|
Mode: {mode_str} ms
|
|
Standard Deviation: {std_dev:.2f} ms
|
|
"""
|
|
|
|
# Create PDF
|
|
with PdfPages(output_pdf) as pdf:
|
|
# Page 1: Histogram
|
|
pdf.savefig(fig_hist)
|
|
plt.close(fig_hist)
|
|
|
|
# Page 2: Box Plot
|
|
pdf.savefig(fig_box)
|
|
plt.close(fig_box)
|
|
|
|
# Page 3: Statistics Summary
|
|
plt.figure(figsize=(8.5, 11))
|
|
plt.axis('off') # Hide axes
|
|
|
|
# Add text to the figure
|
|
plt.text(0.5, 0.5, stats_text, horizontalalignment='center', verticalalignment='center', fontsize=12, wrap=True)
|
|
|
|
# Add the statistics page to the PDF
|
|
pdf.savefig()
|
|
plt.close()
|
|
|
|
print(f"PDF report '{output_pdf}' has been generated successfully.")
|
|
|
|
if __name__ == "__main__":
|
|
# Define input and output files
|
|
csv_file = 'execution_times.csv'
|
|
output_pdf = 'execution_time_report.pdf'
|
|
|
|
# Generate the PDF report
|
|
generate_pdf_report(csv_file, output_pdf)
|