Skip to content

Commit d1253b9

Browse files
authored
Merge pull request #11 from SmilingPixel/feat/smooth_graph_0829
Feat/smooth graph 0829
2 parents 0158be8 + 5873fab commit d1253b9

File tree

3 files changed

+228
-21
lines changed

3 files changed

+228
-21
lines changed

analyzer/main.py

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636

3737
import matplotlib.pyplot as plt
3838
import numpy as np
39+
import pandas as pd
40+
import seaborn as sns
3941
from matplotlib.ticker import MaxNLocator
4042
import re
4143

@@ -287,45 +289,97 @@ def generate_report(
287289
return "\n".join(report_lines), all_stats
288290

289291

290-
def create_and_save_plots(
292+
def create_and_save_plots_seaborn_optimized(
291293
all_metrics_data: Dict[str, List[Any]],
292294
output_dir: Path,
293295
) -> None:
294296
"""
295-
Creates and saves line charts for each metric.
297+
Creates and saves enhanced, readable line charts for each metric using seaborn.
298+
299+
For large datasets, markers are decimated to avoid clutter. Each plot includes
300+
the original data line and a smoothed trendline.
296301
297302
Args:
298303
all_metrics_data (Dict[str, List[Any]]): The prepared metrics data.
299304
output_dir (Path): The directory where plots will be saved.
300305
"""
301306
print(f"Generating and saving plots to {output_dir}...")
302-
sample_indices = range(len(all_metrics_data["timestamps"]))
307+
308+
# Set the aesthetic style of the plots
309+
sns.set_theme(style="whitegrid", palette="muted")
303310

304311
for friendly_name, key in METRICS_TO_ANALYZE:
305-
metric_data = all_metrics_data.get(key, [])
306-
if not metric_data:
307-
print(f"Skipping plot for '{friendly_name}' due to no data.")
312+
metric_data = all_metrics_data.get(key)
313+
314+
if not metric_data or len(metric_data) < 2:
315+
num_points = len(metric_data) if metric_data else 0
316+
print(f"Skipping plot for '{friendly_name}' due to insufficient data (found {num_points} points).")
308317
continue
309318

310-
fig, ax = plt.subplots(figsize=(12, 6))
311-
ax.plot(sample_indices, metric_data, marker=".", linestyle="-", markersize=4)
319+
num_points = len(metric_data)
320+
print(f" - Processing '{friendly_name}' with {num_points} data points...")
321+
322+
# Create a pandas DataFrame
323+
df = pd.DataFrame({
324+
"Sample Index": range(num_points),
325+
friendly_name: metric_data
326+
})
327+
328+
# Create the plot
329+
fig, ax = plt.subplots(figsize=(14, 7))
330+
331+
# 1. Plot the original data with no markers
332+
sns.lineplot(
333+
data=df,
334+
x="Sample Index",
335+
y=friendly_name,
336+
ax=ax,
337+
label="Original Data",
338+
color=sns.color_palette("muted")[0]
339+
)
340+
341+
# 2. Add a smoothed trendline using LOWESS regression
342+
try:
343+
sns.regplot(
344+
data=df,
345+
x="Sample Index",
346+
y=friendly_name,
347+
ax=ax,
348+
lowess=True,
349+
scatter=False,
350+
label="Smoothed Trend",
351+
color=sns.color_palette("muted")[1],
352+
line_kws={'linewidth': 2.5},
353+
ci=None # Disable confidence interval for a cleaner look
354+
)
355+
except Exception as e:
356+
print(f" - Could not generate smoothed trend for '{friendly_name}': {e}")
312357

313-
ax.set_title(f"{friendly_name} Over Time", fontsize=16)
314-
ax.set_xlabel("Sample Index", fontsize=12)
315-
ax.set_ylabel(friendly_name, fontsize=12)
316-
ax.grid(True, which="both", linestyle="--", linewidth=0.5)
358+
# --- Customize the plot ---
359+
ax.set_title(f"{friendly_name} Over Time", fontsize=18, fontweight='bold', pad=20)
360+
ax.set_xlabel("Sample Index", fontsize=14)
361+
ax.set_ylabel(friendly_name, fontsize=14)
317362

318-
# Ensure x-axis has integer ticks
319363
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
364+
plt.xticks(rotation=0)
365+
366+
ax.legend(title="Legend", frameon=True, fontsize=12)
367+
ax.grid(True, which="both", linestyle="--", linewidth=0.5)
320368

321369
fig.tight_layout()
322370

323-
# Sanitize filename
371+
# --- Sanitize filename and save the plot ---
324372
filename_key = key.replace(" ", "_").replace("(", "").replace(")", "").replace("%", "percent")
325-
plot_path = output_dir / f"{filename_key}_chart.png"
326-
fig.savefig(plot_path, dpi=150)
327-
plt.close(fig)
328-
print(f" - Saved {plot_path.name}")
373+
plot_path = output_dir / f"{filename_key}_chart_seaborn.png"
374+
375+
try:
376+
fig.savefig(plot_path, dpi=150, bbox_inches='tight')
377+
print(f" - Saved {plot_path.name}")
378+
except Exception as e:
379+
print(f" - Failed to save plot for '{friendly_name}': {e}")
380+
finally:
381+
plt.close(fig)
382+
329383

330384

331385
def main() -> None:
@@ -357,7 +411,7 @@ def main() -> None:
357411

358412
# 3. Optionally create and save plots
359413
if args.plot:
360-
create_and_save_plots(metrics_data, args.output_dir)
414+
create_and_save_plots_seaborn_optimized(metrics_data, args.output_dir)
361415

362416
print("Analysis complete.")
363417

analyzer/pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ readme = "README.md"
66
requires-python = ">=3.13"
77
dependencies = [
88
"matplotlib>=3.10.3",
9+
"pandas>=2.3.2",
10+
"seaborn[stats]>=0.13.2",
911
]

0 commit comments

Comments
 (0)