From 17b77d96e515422e5da151b218474670ab44059f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 10:56:00 +0000 Subject: [PATCH 1/3] feat(altair): implement subplot-mosaic --- .../subplot-mosaic/implementations/altair.py | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 plots/subplot-mosaic/implementations/altair.py diff --git a/plots/subplot-mosaic/implementations/altair.py b/plots/subplot-mosaic/implementations/altair.py new file mode 100644 index 0000000000..d16d10cd1f --- /dev/null +++ b/plots/subplot-mosaic/implementations/altair.py @@ -0,0 +1,170 @@ +"""pyplots.ai +subplot-mosaic: Mosaic Subplot Layout with Varying Sizes +Library: altair | Python 3.13 +Quality: pending | Created: 2025-12-31 +""" + +import altair as alt +import numpy as np +import pandas as pd + + +# Data - Create diverse datasets for dashboard-style mosaic layout +np.random.seed(42) + +# Panel A: Wide time series (top, spanning 2 columns) +dates = pd.date_range("2024-01-01", periods=100, freq="D") +df_timeseries = pd.DataFrame( + {"date": dates, "value": np.cumsum(np.random.randn(100)) + 50, "category": "Revenue Trend"} +) + +# Panel B: Small metric (top right corner) +df_gauge = pd.DataFrame({"metric": ["Current"], "value": [78], "max_value": [100]}) + +# Panel C: Bar chart (middle left) +df_bars = pd.DataFrame({"region": ["North", "South", "East", "West", "Central"], "sales": [45, 38, 52, 29, 41]}) + +# Panel D: Scatter plot (middle right, spanning 2 rows) +n_points = 80 +df_scatter = pd.DataFrame( + { + "efficiency": np.random.uniform(60, 95, n_points), + "output": np.random.uniform(100, 500, n_points) + np.random.uniform(60, 95, n_points) * 3, + "size": np.random.uniform(20, 100, n_points), + } +) + +# Panel E: Small bar chart (bottom left) +df_categories = pd.DataFrame({"type": ["Type A", "Type B", "Type C"], "count": [24, 18, 31]}) + +# Panel F: Small area chart (bottom middle) +df_area = pd.DataFrame( + { + "hour": list(range(24)), + "traffic": [10, 8, 5, 4, 6, 15, 35, 55, 48, 42, 38, 45, 50, 48, 52, 60, 65, 55, 40, 30, 25, 20, 15, 12], + } +) + +# Note: Data is small enough to not need max_rows configuration + +# Create individual charts with proper styling + +# Chart A: Wide time series (spans 2 columns at top) +chart_a = ( + alt.Chart(df_timeseries) + .mark_line(strokeWidth=3, color="#306998") + .encode( + x=alt.X("date:T", title="Date", axis=alt.Axis(labelFontSize=14, titleFontSize=16)), + y=alt.Y("value:Q", title="Revenue ($K)", axis=alt.Axis(labelFontSize=14, titleFontSize=16)), + ) + .properties(width=700, height=200, title=alt.Title("Monthly Revenue Overview", fontSize=20)) +) + +# Chart B: Gauge-style metric (small, top right) +chart_b_bg = ( + alt.Chart(df_gauge).mark_arc(innerRadius=50, outerRadius=80, theta=3.14159, theta2=0, color="#E0E0E0").encode() +) + +chart_b_value = ( + alt.Chart(df_gauge) + .mark_arc( + innerRadius=50, + outerRadius=80, + theta=3.14159, + theta2=alt.expr("3.14159 - (datum.value / datum.max_value) * 3.14159"), + color="#306998", + ) + .encode() +) + +chart_b_text = ( + alt.Chart(df_gauge) + .mark_text(fontSize=28, fontWeight="bold", color="#306998") + .encode(text=alt.Text("value:Q", format=".0f")) +) + +chart_b = alt.layer(chart_b_bg, chart_b_value, chart_b_text).properties( + width=200, height=200, title=alt.Title("Performance Score", fontSize=18) +) + +# Chart C: Bar chart (middle left) +chart_c = ( + alt.Chart(df_bars) + .mark_bar(color="#306998", cornerRadiusTopLeft=4, cornerRadiusTopRight=4) + .encode( + x=alt.X("region:N", title="Region", axis=alt.Axis(labelFontSize=14, titleFontSize=16, labelAngle=0)), + y=alt.Y("sales:Q", title="Sales ($K)", axis=alt.Axis(labelFontSize=14, titleFontSize=16)), + ) + .properties(width=280, height=180, title=alt.Title("Sales by Region", fontSize=18)) +) + +# Chart D: Scatter plot (spans 2 rows on right side) +chart_d = ( + alt.Chart(df_scatter) + .mark_circle(opacity=0.7) + .encode( + x=alt.X( + "efficiency:Q", + title="Efficiency (%)", + scale=alt.Scale(domain=[55, 100]), + axis=alt.Axis(labelFontSize=14, titleFontSize=16), + ), + y=alt.Y("output:Q", title="Output (units)", axis=alt.Axis(labelFontSize=14, titleFontSize=16)), + size=alt.Size("size:Q", scale=alt.Scale(range=[50, 300]), legend=None), + color=alt.Color("efficiency:Q", scale=alt.Scale(scheme="blues"), legend=None), + ) + .properties(width=320, height=400, title=alt.Title("Efficiency vs Output", fontSize=18)) +) + +# Chart E: Small bar chart (bottom left) +chart_e = ( + alt.Chart(df_categories) + .mark_bar(color="#FFD43B") + .encode( + x=alt.X("type:N", title=None, axis=alt.Axis(labelFontSize=12, labelAngle=0)), + y=alt.Y("count:Q", title="Count", axis=alt.Axis(labelFontSize=12, titleFontSize=14)), + ) + .properties(width=180, height=160, title=alt.Title("By Category", fontSize=16)) +) + +# Chart F: Area chart (bottom middle) +chart_f = ( + alt.Chart(df_area) + .mark_area(color="#306998", opacity=0.7, line={"color": "#306998", "strokeWidth": 2}) + .encode( + x=alt.X("hour:Q", title="Hour", axis=alt.Axis(labelFontSize=12, titleFontSize=14)), + y=alt.Y("traffic:Q", title="Traffic", axis=alt.Axis(labelFontSize=12, titleFontSize=14)), + ) + .properties(width=200, height=160, title=alt.Title("Daily Traffic Pattern", fontSize=16)) +) + +# Build mosaic layout using Altair's concatenation +# Layout pattern: "AAB" +# "CDD" +# "EFD" + +# Top row: time series (wide) + gauge +top_row = alt.hconcat(chart_a, chart_b, spacing=20) + +# Middle row: bars + scatter (scatter spans into bottom row via vconcat) +# Bottom row: categories + area (scatter continues from middle) + +# Left column for middle and bottom rows +left_middle = chart_c +left_bottom = alt.hconcat(chart_e, chart_f, spacing=15) +left_column = alt.vconcat(left_middle, left_bottom, spacing=15) + +# Right side is the tall scatter plot +middle_bottom_row = alt.hconcat(left_column, chart_d, spacing=20) + +# Combine all rows +mosaic = ( + alt.vconcat(top_row, middle_bottom_row, spacing=25) + .properties(title=alt.Title("subplot-mosaic · altair · pyplots.ai", fontSize=28, anchor="middle", offset=20)) + .configure(background="white") + .configure_view(strokeWidth=0) +) + +# Save outputs +mosaic.save("plot.png", scale_factor=3.0) +mosaic.save("plot.html") From d951f92196238b6a7e2fa66c2d22b1e2ecc9476f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 10:56:12 +0000 Subject: [PATCH 2/3] chore(altair): add metadata for subplot-mosaic --- plots/subplot-mosaic/metadata/altair.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plots/subplot-mosaic/metadata/altair.yaml diff --git a/plots/subplot-mosaic/metadata/altair.yaml b/plots/subplot-mosaic/metadata/altair.yaml new file mode 100644 index 0000000000..9f87a2120f --- /dev/null +++ b/plots/subplot-mosaic/metadata/altair.yaml @@ -0,0 +1,19 @@ +# Per-library metadata for altair implementation of subplot-mosaic +# Auto-generated by impl-generate.yml + +library: altair +specification_id: subplot-mosaic +created: '2025-12-31T10:56:12Z' +updated: '2025-12-31T10:56:12Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 20617510407 +issue: 3002 +python_version: 3.13.11 +library_version: 6.0.0 +preview_url: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/altair/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/altair/plot_thumb.png +preview_html: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/altair/plot.html +quality_score: null +review: + strengths: [] + weaknesses: [] From cdd607f8d7c1856ecdd6cfed3be3a4784a37e2af Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 11:07:48 +0000 Subject: [PATCH 3/3] chore(altair): update quality score 91 and review feedback for subplot-mosaic --- .../subplot-mosaic/implementations/altair.py | 6 ++--- plots/subplot-mosaic/metadata/altair.yaml | 22 +++++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/plots/subplot-mosaic/implementations/altair.py b/plots/subplot-mosaic/implementations/altair.py index d16d10cd1f..3a5d865536 100644 --- a/plots/subplot-mosaic/implementations/altair.py +++ b/plots/subplot-mosaic/implementations/altair.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai subplot-mosaic: Mosaic Subplot Layout with Varying Sizes -Library: altair | Python 3.13 -Quality: pending | Created: 2025-12-31 +Library: altair 6.0.0 | Python 3.13.11 +Quality: 91/100 | Created: 2025-12-31 """ import altair as alt diff --git a/plots/subplot-mosaic/metadata/altair.yaml b/plots/subplot-mosaic/metadata/altair.yaml index 9f87a2120f..3e6c21dcf5 100644 --- a/plots/subplot-mosaic/metadata/altair.yaml +++ b/plots/subplot-mosaic/metadata/altair.yaml @@ -1,10 +1,7 @@ -# Per-library metadata for altair implementation of subplot-mosaic -# Auto-generated by impl-generate.yml - library: altair specification_id: subplot-mosaic created: '2025-12-31T10:56:12Z' -updated: '2025-12-31T10:56:12Z' +updated: '2025-12-31T11:07:48Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20617510407 issue: 3002 @@ -13,7 +10,18 @@ library_version: 6.0.0 preview_url: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/altair/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/altair/plot_thumb.png preview_html: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/altair/plot.html -quality_score: null +quality_score: 91 review: - strengths: [] - weaknesses: [] + strengths: + - Excellent demonstration of mosaic layout concept using Altair concatenation operators + (hconcat, vconcat) + - Clean, professional visual design with consistent color scheme (#306998 blue theme) + - Good variety of chart types (line, bar, scatter, area, gauge) showing layout flexibility + - Descriptive axis labels with appropriate units throughout + - Realistic business dashboard scenario with plausible data + weaknesses: + - No demonstration of empty cells using placeholder characters (e.g., "." for gaps) + as mentioned in spec + - Scatter plot lacks legend for the color encoding (efficiency gradient) + - HTML version could benefit from interactive features (tooltips, selection) which + Altair excels at