dedup the code

This commit is contained in:
Sylvestre Ledru
2026-01-07 23:03:00 +01:00
parent 17a0adefce
commit 2f13eba0a5
4 changed files with 198 additions and 188 deletions
+17 -73
View File
@@ -9,6 +9,9 @@ import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from graph_common import (COLORS, setup_theme, apply_smoothing, style_axes,
add_title, style_legend, add_reference_lines)
if len(sys.argv) <= 2:
print("graph.py: <json file> <title>")
sys.exit()
@@ -22,18 +25,8 @@ df.index = pd.to_datetime(df.index, utc=True)
print(df)
# Set modern Seaborn style with enhanced settings
sns.set_theme(style="ticks", context="talk", palette="muted")
plt.rcParams.update({
'font.family': 'sans-serif',
'font.sans-serif': ['Inter', 'SF Pro Display', 'Segoe UI', 'Arial'],
'axes.facecolor': '#FAFAFA',
'figure.facecolor': 'white',
'axes.edgecolor': '#CCCCCC',
'axes.linewidth': 0.8,
'xtick.color': '#555555',
'ytick.color': '#555555',
})
# Set up modern theme
setup_theme()
# Create figure with better proportions and higher DPI
fig, ax = plt.subplots(figsize=(18, 9), dpi=100)
@@ -53,18 +46,10 @@ df_plot_long = df_plot.melt(id_vars='date', var_name='metric', value_name='count
df_plot_long['count'] = pd.to_numeric(df_plot_long['count'], errors='coerce')
# Apply smoothing using rolling average (window of 15 for smoother lines)
df_plot_long['count_smooth'] = df_plot_long.groupby('metric')['count'].transform(
lambda x: x.rolling(window=15, min_periods=1, center=True).mean()
)
df_plot_long['count_smooth'] = apply_smoothing(df_plot_long, 'metric', 'count')
# Modern vibrant color palette
palette = {
'total': '#0066CC', # Vibrant blue
'pass': '#10B981', # Modern green (Tailwind emerald)
'fail': '#EF4444', # Modern red (Tailwind red)
'error': '#F59E0B', # Modern amber
'skip': '#8B5CF6' # Modern purple (Tailwind violet)
}
# Use color palette from common module
palette = {k: COLORS[k] for k in ['total', 'pass', 'fail', 'error', 'skip']}
# Add gradient-like area fills first (behind lines)
for metric in ['total', 'pass', 'fail']:
@@ -87,62 +72,21 @@ sns.lineplot(
zorder=3
)
# Modern title with better spacing
ax.text(0.5, 1.12, f'uutils coreutils — {title} Test Suite Results',
ha='center', va='bottom', transform=ax.transAxes,
fontsize=26, fontweight='bold', family='sans-serif', color='#1a1a1a')
ax.text(0.5, 1.06, 'Tracking test results over time to measure progress and compatibility',
ha='center', va='bottom', transform=ax.transAxes,
fontsize=13, color='#6B7280', style='italic', alpha=0.9)
# Add title and subtitle
add_title(ax, f'uutils coreutils — {title} Test Suite Results',
'Tracking test results over time to measure progress and compatibility')
ax.set_xlabel('Date', fontsize=15, fontweight='600', labelpad=15, color='#374151')
ax.set_ylabel('Number of Tests', fontsize=15, fontweight='600', labelpad=15, color='#374151')
# Style axes with labels and grid
style_axes(ax, xlabel='Date', ylabel='Number of Tests')
# Modern grid styling with better contrast
ax.grid(True, alpha=0.35, linestyle='-', linewidth=1, color='#E5E7EB', which='major', zorder=0)
ax.grid(True, alpha=0.15, linestyle=':', linewidth=0.5, color='#F3F4F6', which='minor', zorder=0)
ax.set_axisbelow(True)
ax.minorticks_on()
# Add subtle horizontal reference lines at key values
# Add reference lines
y_max = df_plot_long['count_smooth'].max()
if y_max > 100:
ax.axhline(y=y_max * 0.75, color='#D1D5DB', linestyle='--', linewidth=0.8, alpha=0.3, zorder=0)
ax.axhline(y=y_max * 0.5, color='#D1D5DB', linestyle='--', linewidth=0.8, alpha=0.3, zorder=0)
add_reference_lines(ax, y_max)
# Modern legend styling
# Style legend
handles, labels = ax.get_legend_handles_labels()
# Capitalize labels
labels = [label.capitalize() for label in labels]
legend = ax.legend(handles, labels, loc='upper left', frameon=True,
fancybox=False, shadow=False, ncol=len(plot_columns),
bbox_to_anchor=(0, 1.04), fontsize=13,
edgecolor='#D1D5DB', framealpha=0.98,
borderpad=1.2, labelspacing=0.8, columnspacing=2)
legend.get_frame().set_facecolor('#FFFFFF')
legend.get_frame().set_linewidth(2)
legend.get_frame().set_boxstyle('round,pad=0.5')
# Format x-axis dates
plt.xticks(rotation=45, ha='right')
ax.margins(x=0.01)
ax.set_ylim(bottom=0)
# Modern spine styling
sns.despine(ax=ax, top=True, right=True, left=False, bottom=False, offset=8)
ax.spines['left'].set_linewidth(2)
ax.spines['bottom'].set_linewidth(2)
ax.spines['left'].set_color('#9CA3AF')
ax.spines['bottom'].set_color('#9CA3AF')
# Modern gradient-like background
ax.patch.set_facecolor('#FAFAFA')
ax.patch.set_alpha(0.6)
# Add a subtle shadow effect
ax.add_patch(plt.Rectangle((0, 0), 1, 1, transform=ax.transAxes,
facecolor='none', edgecolor='#E5E7EB',
linewidth=3, zorder=-1))
style_legend(ax, handles, labels, ncol=len(plot_columns), loc='upper left')
# Tight layout
plt.tight_layout()
+151
View File
@@ -0,0 +1,151 @@
# This file is part of the uutils coreutils package.
#
# For the full copyright and license information, please view the LICENSE
# file that was distributed with this source code.
"""Common styling and utilities for graph generation."""
import matplotlib.pyplot as plt
import seaborn as sns
# Modern vibrant color palette
COLORS = {
'total': '#0066CC', # Vibrant blue
'pass': '#10B981', # Modern green (Tailwind emerald)
'fail': '#EF4444', # Modern red (Tailwind red)
'error': '#F59E0B', # Modern amber
'skip': '#8B5CF6', # Modern purple (Tailwind violet)
'size': '#6366F1', # Modern indigo
'multisize': '#10B981', # Modern green (Tailwind emerald)
'default': '#10B981', # Modern green (Tailwind emerald)
}
def setup_theme():
"""Set up modern Seaborn theme with enhanced settings."""
sns.set_theme(style="ticks", context="talk", palette="muted")
plt.rcParams.update({
'font.family': 'sans-serif',
'font.sans-serif': ['Inter', 'SF Pro Display', 'Segoe UI', 'Arial'],
'axes.facecolor': '#FAFAFA',
'figure.facecolor': 'white',
'axes.edgecolor': '#CCCCCC',
'axes.linewidth': 0.8,
'xtick.color': '#555555',
'ytick.color': '#555555',
})
def apply_smoothing(df, group_col, value_col, window=15):
"""Apply rolling average smoothing to data.
Args:
df: DataFrame with data to smooth
group_col: Column name to group by (or None for no grouping)
value_col: Column name containing values to smooth
window: Rolling window size (default: 15)
Returns:
Series with smoothed values
"""
if group_col:
return df.groupby(group_col)[value_col].transform(
lambda x: x.rolling(window=window, min_periods=1, center=True).mean()
)
else:
return df[value_col].rolling(window=window, min_periods=1, center=True).mean()
def style_axes(ax, xlabel='Date', ylabel='Value'):
"""Apply modern styling to axes.
Args:
ax: Matplotlib axes object
xlabel: Label for x-axis
ylabel: Label for y-axis
"""
ax.set_xlabel(xlabel, fontsize=15, fontweight='600', labelpad=15, color='#374151')
ax.set_ylabel(ylabel, fontsize=15, fontweight='600', labelpad=15, color='#374151')
# Modern grid styling
ax.grid(True, alpha=0.35, linestyle='-', linewidth=1, color='#E5E7EB', which='major', zorder=0)
ax.grid(True, alpha=0.15, linestyle=':', linewidth=0.5, color='#F3F4F6', which='minor', zorder=0)
ax.set_axisbelow(True)
ax.minorticks_on()
# Format x-axis dates
plt.xticks(rotation=45, ha='right')
ax.margins(x=0.01)
ax.set_ylim(bottom=0)
# Modern spine styling
sns.despine(ax=ax, top=True, right=True, left=False, bottom=False, offset=8)
ax.spines['left'].set_linewidth(2)
ax.spines['bottom'].set_linewidth(2)
ax.spines['left'].set_color('#9CA3AF')
ax.spines['bottom'].set_color('#9CA3AF')
# Modern background
ax.patch.set_facecolor('#FAFAFA')
ax.patch.set_alpha(0.6)
# Add subtle shadow effect
ax.add_patch(plt.Rectangle((0, 0), 1, 1, transform=ax.transAxes,
facecolor='none', edgecolor='#E5E7EB',
linewidth=3, zorder=-1))
def add_title(ax, title, subtitle=None):
"""Add modern title and optional subtitle to axes.
Args:
ax: Matplotlib axes object
title: Main title text
subtitle: Optional subtitle text
"""
ax.text(0.5, 1.12, title,
ha='center', va='bottom', transform=ax.transAxes,
fontsize=26, fontweight='bold', family='sans-serif', color='#1a1a1a')
if subtitle:
ax.text(0.5, 1.06, subtitle,
ha='center', va='bottom', transform=ax.transAxes,
fontsize=13, color='#6B7280', style='italic', alpha=0.9)
def style_legend(ax, handles, labels, ncol=1, loc='upper left'):
"""Apply modern styling to legend.
Args:
ax: Matplotlib axes object
handles: Legend handles
labels: Legend labels
ncol: Number of columns (default: 1)
loc: Legend location (default: 'upper left')
Returns:
Legend object
"""
legend = ax.legend(handles, labels, loc=loc, frameon=True,
fancybox=False, shadow=False, ncol=ncol,
bbox_to_anchor=(0, 1.04) if 'left' in loc else (1, 1.04),
fontsize=13,
edgecolor='#D1D5DB', framealpha=0.98,
borderpad=1.2, labelspacing=0.8, columnspacing=2)
legend.get_frame().set_facecolor('#FFFFFF')
legend.get_frame().set_linewidth(2)
legend.get_frame().set_boxstyle('round,pad=0.5')
return legend
def add_reference_lines(ax, y_max):
"""Add horizontal reference lines at key values.
Args:
ax: Matplotlib axes object
y_max: Maximum y value for calculating reference positions
"""
if y_max > 100:
ax.axhline(y=y_max * 0.75, color='#D1D5DB', linestyle='--', linewidth=0.8, alpha=0.3, zorder=0)
ax.axhline(y=y_max * 0.5, color='#D1D5DB', linestyle='--', linewidth=0.8, alpha=0.3, zorder=0)
+14 -52
View File
@@ -10,26 +10,19 @@ import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from graph_common import (COLORS, setup_theme, apply_smoothing, style_axes,
add_title)
df = pd.read_json(sys.argv[1], orient="index")
df.index = pd.to_datetime(df.index, utc=True)
Path("individual-size-results").mkdir(exist_ok=True)
# Set modern Seaborn style with enhanced settings
sns.set_theme(style="ticks", context="talk", palette="muted")
plt.rcParams.update({
'font.family': 'sans-serif',
'font.sans-serif': ['Inter', 'SF Pro Display', 'Segoe UI', 'Arial'],
'axes.facecolor': '#FAFAFA',
'figure.facecolor': 'white',
'axes.edgecolor': '#CCCCCC',
'axes.linewidth': 0.8,
'xtick.color': '#555555',
'ytick.color': '#555555',
})
# Set up modern theme
setup_theme()
# Modern color for size evolution
size_color = '#10B981' # Modern green (Tailwind emerald)
# Use color from common module
size_color = COLORS['default']
for name, series in df["sizes"].apply(pd.Series).items():
# Filter out None values which indicate missing data for 'name'
@@ -45,11 +38,11 @@ for name, series in df["sizes"].apply(pd.Series).items():
# Prepare data for Seaborn
plot_data = pd.DataFrame({
'date': sizes.index,
'size': pd.to_numeric(sizes['size'], errors='coerce')
'size': pd.to_numeric(sizes.values, errors='coerce')
})
# Apply smoothing using rolling average
plot_data['size_smooth'] = plot_data['size'].rolling(window=15, min_periods=1, center=True).mean()
plot_data['size_smooth'] = apply_smoothing(plot_data, None, 'size')
# Add gradient-like area fill first
ax.fill_between(plot_data['date'], 0, plot_data['size'],
@@ -68,43 +61,12 @@ for name, series in df["sizes"].apply(pd.Series).items():
zorder=3
)
# Modern title
ax.text(0.5, 1.12, f'uutils coreutils — "{name}" Binary Size',
ha='center', va='bottom', transform=ax.transAxes,
fontsize=26, fontweight='bold', family='sans-serif', color='#1a1a1a')
ax.text(0.5, 1.06, f'Individual utility size tracking over development history',
ha='center', va='bottom', transform=ax.transAxes,
fontsize=13, color='#6B7280', style='italic', alpha=0.9)
# Add title and subtitle
add_title(ax, f'uutils coreutils — "{name}" Binary Size',
'Individual utility size tracking over development history')
ax.set_xlabel('Date', fontsize=15, fontweight='600', labelpad=15, color='#374151')
ax.set_ylabel('Size (kilobytes)', fontsize=15, fontweight='600', labelpad=15, color='#374151')
# Modern grid styling
ax.grid(True, alpha=0.35, linestyle='-', linewidth=1, color='#E5E7EB', which='major', zorder=0)
ax.grid(True, alpha=0.15, linestyle=':', linewidth=0.5, color='#F3F4F6', which='minor', zorder=0)
ax.set_axisbelow(True)
ax.minorticks_on()
# Format x-axis dates
plt.xticks(rotation=45, ha='right')
ax.margins(x=0.01)
ax.set_ylim(bottom=0)
# Modern spine styling
sns.despine(ax=ax, top=True, right=True, left=False, bottom=False, offset=8)
ax.spines['left'].set_linewidth(2)
ax.spines['bottom'].set_linewidth(2)
ax.spines['left'].set_color('#9CA3AF')
ax.spines['bottom'].set_color('#9CA3AF')
# Modern background
ax.patch.set_facecolor('#FAFAFA')
ax.patch.set_alpha(0.6)
# Add subtle shadow effect
ax.add_patch(plt.Rectangle((0, 0), 1, 1, transform=ax.transAxes,
facecolor='none', edgecolor='#E5E7EB',
linewidth=3, zorder=-1))
# Style axes with labels and grid
style_axes(ax, xlabel='Date', ylabel='Size (kilobytes)')
# Tight layout
plt.tight_layout()
+16 -63
View File
@@ -9,6 +9,9 @@ import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from graph_common import (COLORS, setup_theme, apply_smoothing, style_axes,
add_title, style_legend)
d = pd.read_json(sys.argv[1], orient="index")
df = pd.DataFrame(d)
@@ -17,18 +20,8 @@ df.index = pd.to_datetime(df.index, utc=True, format="mixed")
print(df)
# Set modern Seaborn style with enhanced settings
sns.set_theme(style="ticks", context="talk", palette="muted")
plt.rcParams.update({
'font.family': 'sans-serif',
'font.sans-serif': ['Inter', 'SF Pro Display', 'Segoe UI', 'Arial'],
'axes.facecolor': '#FAFAFA',
'figure.facecolor': 'white',
'axes.edgecolor': '#CCCCCC',
'axes.linewidth': 0.8,
'xtick.color': '#555555',
'ytick.color': '#555555',
})
# Set up modern theme
setup_theme()
# Create figure with better proportions and higher DPI
fig, ax = plt.subplots(figsize=(18, 9), dpi=100)
@@ -43,14 +36,12 @@ df_plot_long = df_plot.melt(id_vars='date', var_name='binary_type', value_name='
df_plot_long['size_kb'] = pd.to_numeric(df_plot_long['size_kb'], errors='coerce')
# Apply smoothing using rolling average
df_plot_long['size_kb_smooth'] = df_plot_long.groupby('binary_type')['size_kb'].transform(
lambda x: x.rolling(window=15, min_periods=1, center=True).mean()
)
df_plot_long['size_kb_smooth'] = apply_smoothing(df_plot_long, 'binary_type', 'size_kb')
# Modern color palette
# Use color palette from common module
palette = {
'size': '#6366F1', # Modern indigo
'multisize': '#10B981' # Modern green (Tailwind emerald)
'size': COLORS['size'],
'multisize': COLORS['multisize']
}
# Add gradient-like area fills first
@@ -74,59 +65,21 @@ sns.lineplot(
zorder=3
)
# Modern title
ax.text(0.5, 1.12, 'uutils coreutils — Binary Size Evolution',
ha='center', va='bottom', transform=ax.transAxes,
fontsize=26, fontweight='bold', family='sans-serif', color='#1a1a1a')
ax.text(0.5, 1.06, 'Tracking binary size optimization and comparing build strategies',
ha='center', va='bottom', transform=ax.transAxes,
fontsize=13, color='#6B7280', style='italic', alpha=0.9)
# Add title and subtitle
add_title(ax, 'uutils coreutils — Binary Size Evolution',
'Tracking binary size optimization and comparing build strategies')
ax.set_xlabel('Date', fontsize=15, fontweight='600', labelpad=15, color='#374151')
ax.set_ylabel('Size (kilobytes)', fontsize=15, fontweight='600', labelpad=15, color='#374151')
# Style axes with labels and grid
style_axes(ax, xlabel='Date', ylabel='Size (kilobytes)')
# Modern grid styling
ax.grid(True, alpha=0.35, linestyle='-', linewidth=1, color='#E5E7EB', which='major', zorder=0)
ax.grid(True, alpha=0.15, linestyle=':', linewidth=0.5, color='#F3F4F6', which='minor', zorder=0)
ax.set_axisbelow(True)
ax.minorticks_on()
# Modern legend
# Style legend
handles, labels = ax.get_legend_handles_labels()
label_map = {
'size': 'Multiple Binaries',
'multisize': 'Multicall Binary (Optimized)'
}
labels = [label_map.get(label, label) for label in labels]
legend = ax.legend(handles, labels, loc='upper left', frameon=True,
fancybox=False, shadow=False, fontsize=13,
bbox_to_anchor=(0, 1.04),
edgecolor='#D1D5DB', framealpha=0.98,
borderpad=1.2, labelspacing=0.8)
legend.get_frame().set_facecolor('#FFFFFF')
legend.get_frame().set_linewidth(2)
legend.get_frame().set_boxstyle('round,pad=0.5')
# Format x-axis dates
plt.xticks(rotation=45, ha='right')
ax.margins(x=0.01)
ax.set_ylim(bottom=0)
# Modern spine styling
sns.despine(ax=ax, top=True, right=True, left=False, bottom=False, offset=8)
ax.spines['left'].set_linewidth(2)
ax.spines['bottom'].set_linewidth(2)
ax.spines['left'].set_color('#9CA3AF')
ax.spines['bottom'].set_color('#9CA3AF')
# Modern background
ax.patch.set_facecolor('#FAFAFA')
ax.patch.set_alpha(0.6)
# Add subtle shadow effect
ax.add_patch(plt.Rectangle((0, 0), 1, 1, transform=ax.transAxes,
facecolor='none', edgecolor='#E5E7EB',
linewidth=3, zorder=-1))
style_legend(ax, handles, labels, ncol=1, loc='upper left')
# Tight layout
plt.tight_layout()