From 6ecced62883f11cdf67e3f3891679979ec603a44 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 00:18:26 +0000 Subject: [PATCH 1/5] feat(altair): implement streamline-basic --- .../implementations/altair.py | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 plots/streamline-basic/implementations/altair.py diff --git a/plots/streamline-basic/implementations/altair.py b/plots/streamline-basic/implementations/altair.py new file mode 100644 index 0000000000..7ed2ea9699 --- /dev/null +++ b/plots/streamline-basic/implementations/altair.py @@ -0,0 +1,104 @@ +"""pyplots.ai +streamline-basic: Basic Streamline Plot +Library: altair | Python 3.13 +Quality: pending | Created: 2025-12-31 +""" + +import altair as alt +import numpy as np +import pandas as pd + + +# Disable data row limit +alt.data_transformers.disable_max_rows() + +# Data - Create a vector field for a vortex flow (u = -y, v = x) +np.random.seed(42) + + +# Vector field function: circular vortex +def vector_field(x, y): + u = -y + v = x + return u, v + + +# Compute streamlines using Euler integration +def compute_streamline(x0, y0, dt=0.03, max_steps=250): + """Trace a streamline starting from (x0, y0).""" + points = [(x0, y0)] + x, y = x0, y0 + for _ in range(max_steps): + u, v = vector_field(x, y) + mag = np.sqrt(u**2 + v**2) + if mag < 1e-6: + break + # Normalize and step + x_new = x + dt * u / mag + y_new = y + dt * v / mag + # Stop if out of bounds + if abs(x_new) > 3.2 or abs(y_new) > 3.2: + break + x, y = x_new, y_new + points.append((x, y)) + return points + + +# Generate streamlines from various starting points +# Use a radial distribution for vortex visualization +streamlines_data = [] +streamline_id = 0 + +# Starting points at different radii - more radii for better coverage +radii = [0.4, 0.7, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0] +n_per_radius = 6 + +for r in radii: + for i in range(n_per_radius): + angle = 2 * np.pi * i / n_per_radius + (r * 0.1) # Offset angle by radius + x0 = r * np.cos(angle) + y0 = r * np.sin(angle) + points = compute_streamline(x0, y0) + if len(points) > 5: # Only include streamlines with enough points + for j, (x, y) in enumerate(points): + # Velocity magnitude equals distance from center in this vortex + vel = np.sqrt(x**2 + y**2) + streamlines_data.append( + {"x": float(x), "y": float(y), "streamline_id": streamline_id, "order": j, "velocity": float(vel)} + ) + streamline_id += 1 + +df = pd.DataFrame(streamlines_data) + +# Compute average velocity per streamline for color encoding +avg_velocity = df.groupby("streamline_id")["velocity"].mean().reset_index() +avg_velocity.columns = ["streamline_id", "avg_velocity"] +df = df.merge(avg_velocity, on="streamline_id") + +# Create the streamline chart using line marks +# Color by average velocity (flow speed) for each streamline +chart = ( + alt.Chart(df) + .mark_line(strokeWidth=2.5, opacity=0.85) + .encode( + x=alt.X("x:Q", title="X Position", scale=alt.Scale(domain=[-3.5, 3.5])), + y=alt.Y("y:Q", title="Y Position", scale=alt.Scale(domain=[-3.5, 3.5])), + color=alt.Color( + "avg_velocity:Q", + scale=alt.Scale(scheme="viridis"), + title="Flow Speed", + legend=alt.Legend(titleFontSize=18, labelFontSize=16, gradientLength=200), + ), + detail="streamline_id:N", + order="order:O", + ) + .properties( + width=1600, height=900, title=alt.Title("streamline-basic · altair · pyplots.ai", fontSize=28, anchor="middle") + ) + .configure_axis(labelFontSize=18, titleFontSize=22, gridOpacity=0.3) + .configure_view(strokeWidth=0) +) + +# Save as PNG and HTML +chart.save("plot.png", scale_factor=3.0) +chart.save("plot.html") From 86d48e7b19208fd0a78961abf7c381ae664f1e57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 00:18:40 +0000 Subject: [PATCH 2/5] chore(altair): add metadata for streamline-basic --- plots/streamline-basic/metadata/altair.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plots/streamline-basic/metadata/altair.yaml diff --git a/plots/streamline-basic/metadata/altair.yaml b/plots/streamline-basic/metadata/altair.yaml new file mode 100644 index 0000000000..3cbeb57513 --- /dev/null +++ b/plots/streamline-basic/metadata/altair.yaml @@ -0,0 +1,19 @@ +# Per-library metadata for altair implementation of streamline-basic +# Auto-generated by impl-generate.yml + +library: altair +specification_id: streamline-basic +created: '2025-12-31T00:18:39Z' +updated: '2025-12-31T00:18:39Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 20608708674 +issue: 2861 +python_version: 3.13.11 +library_version: 6.0.0 +preview_url: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot_thumb.png +preview_html: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot.html +quality_score: null +review: + strengths: [] + weaknesses: [] From f2b8d6123165cbfd32d937be62764e4104471dd2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 00:22:22 +0000 Subject: [PATCH 3/5] chore(altair): update quality score 88 and review feedback for streamline-basic --- .../implementations/altair.py | 6 ++--- plots/streamline-basic/metadata/altair.yaml | 22 +++++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/plots/streamline-basic/implementations/altair.py b/plots/streamline-basic/implementations/altair.py index 7ed2ea9699..31eb23a88a 100644 --- a/plots/streamline-basic/implementations/altair.py +++ b/plots/streamline-basic/implementations/altair.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai streamline-basic: Basic Streamline Plot -Library: altair | Python 3.13 -Quality: pending | Created: 2025-12-31 +Library: altair 6.0.0 | Python 3.13.11 +Quality: 88/100 | Created: 2025-12-31 """ import altair as alt diff --git a/plots/streamline-basic/metadata/altair.yaml b/plots/streamline-basic/metadata/altair.yaml index 3cbeb57513..5bf6092f36 100644 --- a/plots/streamline-basic/metadata/altair.yaml +++ b/plots/streamline-basic/metadata/altair.yaml @@ -1,10 +1,7 @@ -# Per-library metadata for altair implementation of streamline-basic -# Auto-generated by impl-generate.yml - library: altair specification_id: streamline-basic created: '2025-12-31T00:18:39Z' -updated: '2025-12-31T00:18:39Z' +updated: '2025-12-31T00:22:22Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20608708674 issue: 2861 @@ -13,7 +10,18 @@ library_version: 6.0.0 preview_url: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot_thumb.png preview_html: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot.html -quality_score: null +quality_score: 88 review: - strengths: [] - weaknesses: [] + strengths: + - Excellent use of Altair declarative grammar for encoding streamline data with + color mapped to velocity + - Beautiful viridis colormap that is colorblind-accessible and visually appealing + - Well-balanced layout with good canvas utilization + - Creative solution for streamline visualization in a library without native streamline + support + - Properly generates both PNG and HTML outputs + weaknesses: + - Code uses helper functions (vector_field, compute_streamline) instead of KISS + flat structure + - Grid lines are not visible despite being configured (gridOpacity may need adjustment) + - Axis labels lack units (even generic ones like units would help) From 280ac832a607503acd3ca9041c04bdc507f7e54f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 00:26:02 +0000 Subject: [PATCH 4/5] fix(altair): address review feedback for streamline-basic - Replace helper functions with flat KISS structure (CQ-01 improvement) - Add explicit grid configuration with gridColor and increased gridOpacity - Add units to axis labels: "X Position (units)", "Y Position (units)" Attempt 1/3 - fixes based on AI review --- .../implementations/altair.py | 79 ++++++++----------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/plots/streamline-basic/implementations/altair.py b/plots/streamline-basic/implementations/altair.py index 31eb23a88a..a213e6788e 100644 --- a/plots/streamline-basic/implementations/altair.py +++ b/plots/streamline-basic/implementations/altair.py @@ -1,4 +1,4 @@ -""" pyplots.ai +"""pyplots.ai streamline-basic: Basic Streamline Plot Library: altair 6.0.0 | Python 3.13.11 Quality: 88/100 | Created: 2025-12-31 @@ -15,56 +15,47 @@ # Data - Create a vector field for a vortex flow (u = -y, v = x) np.random.seed(42) - -# Vector field function: circular vortex -def vector_field(x, y): - u = -y - v = x - return u, v - - -# Compute streamlines using Euler integration -def compute_streamline(x0, y0, dt=0.03, max_steps=250): - """Trace a streamline starting from (x0, y0).""" - points = [(x0, y0)] - x, y = x0, y0 - for _ in range(max_steps): - u, v = vector_field(x, y) - mag = np.sqrt(u**2 + v**2) - if mag < 1e-6: - break - # Normalize and step - x_new = x + dt * u / mag - y_new = y + dt * v / mag - # Stop if out of bounds - if abs(x_new) > 3.2 or abs(y_new) > 3.2: - break - x, y = x_new, y_new - points.append((x, y)) - return points - - -# Generate streamlines from various starting points -# Use a radial distribution for vortex visualization +# Generate streamlines using Euler integration - flat KISS structure streamlines_data = [] streamline_id = 0 -# Starting points at different radii - more radii for better coverage +# Starting points at different radii for vortex visualization radii = [0.4, 0.7, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0] n_per_radius = 6 +dt = 0.03 +max_steps = 250 for r in radii: for i in range(n_per_radius): - angle = 2 * np.pi * i / n_per_radius + (r * 0.1) # Offset angle by radius - x0 = r * np.cos(angle) - y0 = r * np.sin(angle) - points = compute_streamline(x0, y0) - if len(points) > 5: # Only include streamlines with enough points - for j, (x, y) in enumerate(points): + angle = 2 * np.pi * i / n_per_radius + (r * 0.1) + x = r * np.cos(angle) + y = r * np.sin(angle) + points = [(x, y)] + + # Trace streamline using Euler integration + for _ in range(max_steps): + # Vector field: circular vortex (u = -y, v = x) + u = -y + v = x + mag = np.sqrt(u**2 + v**2) + if mag < 1e-6: + break + # Normalize and step + x_new = x + dt * u / mag + y_new = y + dt * v / mag + # Stop if out of bounds + if abs(x_new) > 3.2 or abs(y_new) > 3.2: + break + x, y = x_new, y_new + points.append((x, y)) + + # Only include streamlines with enough points + if len(points) > 5: + for j, (px, py) in enumerate(points): # Velocity magnitude equals distance from center in this vortex - vel = np.sqrt(x**2 + y**2) + vel = np.sqrt(px**2 + py**2) streamlines_data.append( - {"x": float(x), "y": float(y), "streamline_id": streamline_id, "order": j, "velocity": float(vel)} + {"x": float(px), "y": float(py), "streamline_id": streamline_id, "order": j, "velocity": float(vel)} ) streamline_id += 1 @@ -81,8 +72,8 @@ def compute_streamline(x0, y0, dt=0.03, max_steps=250): alt.Chart(df) .mark_line(strokeWidth=2.5, opacity=0.85) .encode( - x=alt.X("x:Q", title="X Position", scale=alt.Scale(domain=[-3.5, 3.5])), - y=alt.Y("y:Q", title="Y Position", scale=alt.Scale(domain=[-3.5, 3.5])), + x=alt.X("x:Q", title="X Position (units)", scale=alt.Scale(domain=[-3.5, 3.5])), + y=alt.Y("y:Q", title="Y Position (units)", scale=alt.Scale(domain=[-3.5, 3.5])), color=alt.Color( "avg_velocity:Q", scale=alt.Scale(scheme="viridis"), @@ -95,7 +86,7 @@ def compute_streamline(x0, y0, dt=0.03, max_steps=250): .properties( width=1600, height=900, title=alt.Title("streamline-basic · altair · pyplots.ai", fontSize=28, anchor="middle") ) - .configure_axis(labelFontSize=18, titleFontSize=22, gridOpacity=0.3) + .configure_axis(labelFontSize=18, titleFontSize=22, grid=True, gridColor="#cccccc", gridOpacity=0.4) .configure_view(strokeWidth=0) ) From 22957162d23ba5945f2e7acc6b1f4e4e56a7adb1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 00:28:21 +0000 Subject: [PATCH 5/5] chore(altair): update quality score 91 and review feedback for streamline-basic --- .../implementations/altair.py | 4 +-- plots/streamline-basic/metadata/altair.yaml | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/plots/streamline-basic/implementations/altair.py b/plots/streamline-basic/implementations/altair.py index a213e6788e..42f6b6731e 100644 --- a/plots/streamline-basic/implementations/altair.py +++ b/plots/streamline-basic/implementations/altair.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai streamline-basic: Basic Streamline Plot Library: altair 6.0.0 | Python 3.13.11 -Quality: 88/100 | Created: 2025-12-31 +Quality: 91/100 | Created: 2025-12-31 """ import altair as alt diff --git a/plots/streamline-basic/metadata/altair.yaml b/plots/streamline-basic/metadata/altair.yaml index 5bf6092f36..310252280d 100644 --- a/plots/streamline-basic/metadata/altair.yaml +++ b/plots/streamline-basic/metadata/altair.yaml @@ -1,7 +1,7 @@ library: altair specification_id: streamline-basic created: '2025-12-31T00:18:39Z' -updated: '2025-12-31T00:22:22Z' +updated: '2025-12-31T00:28:21Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20608708674 issue: 2861 @@ -10,18 +10,19 @@ library_version: 6.0.0 preview_url: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot_thumb.png preview_html: https://storage.googleapis.com/pyplots-images/plots/streamline-basic/altair/plot.html -quality_score: 88 +quality_score: 91 review: strengths: - - Excellent use of Altair declarative grammar for encoding streamline data with - color mapped to velocity - - Beautiful viridis colormap that is colorblind-accessible and visually appealing - - Well-balanced layout with good canvas utilization - - Creative solution for streamline visualization in a library without native streamline - support - - Properly generates both PNG and HTML outputs + - Excellent implementation of Euler integration to trace streamlines in a declarative + visualization library + - Clean viridis color encoding showing velocity magnitude increases with distance + from center + - Proper use of detail encoding to separate individual streamlines and order encoding + for correct line drawing + - Well-balanced streamline density with multiple radii covering the full flow field + - Title and font sizes meet all readability requirements weaknesses: - - Code uses helper functions (vector_field, compute_streamline) instead of KISS - flat structure - - Grid lines are not visible despite being configured (gridOpacity may need adjustment) - - Axis labels lack units (even generic ones like units would help) + - Axis labels lack units - should be "X Position (units)" or specify dimensionless + - Some inner streamlines appear slightly crowded/overlapping near the center + - Does not leverage Altair interactive features (tooltips, zoom/pan) which would + enhance flow exploration