From 98b1b75a2b688670c88e4731c94d1ebc40339419 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 21:33:31 +0000 Subject: [PATCH 1/5] feat(bokeh): implement choropleth-basic --- .../choropleth-basic/implementations/bokeh.py | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 plots/choropleth-basic/implementations/bokeh.py diff --git a/plots/choropleth-basic/implementations/bokeh.py b/plots/choropleth-basic/implementations/bokeh.py new file mode 100644 index 0000000000..457c715373 --- /dev/null +++ b/plots/choropleth-basic/implementations/bokeh.py @@ -0,0 +1,242 @@ +"""pyplots.ai +choropleth-basic: Choropleth Map with Regional Coloring +Library: bokeh | Python 3.13 +Quality: pending | Created: 2025-12-31 +""" + +from bokeh.io import export_png +from bokeh.models import ColorBar, ColumnDataSource, LabelSet, LinearColorMapper +from bokeh.palettes import Blues9 +from bokeh.plotting import figure + + +# Data: US states arranged in a tile grid map layout (all 50 states + DC) +# Grid positions (col, row) - approximating geographic positions +regions = { + "AK": (0, 5), + "HI": (0, 1), + "WA": (1, 5), + "OR": (1, 4), + "CA": (0, 3), + "NV": (1, 3), + "ID": (2, 5), + "MT": (3, 5), + "WY": (3, 4), + "UT": (2, 3), + "AZ": (2, 2), + "CO": (3, 3), + "NM": (3, 2), + "ND": (4, 5), + "SD": (4, 4), + "NE": (4, 3), + "KS": (4, 2), + "OK": (4, 1), + "TX": (3, 1), + "MN": (5, 5), + "IA": (5, 4), + "MO": (5, 3), + "AR": (5, 2), + "LA": (5, 1), + "WI": (6, 5), + "IL": (6, 4), + "IN": (7, 4), + "MI": (7, 5), + "OH": (8, 4), + "KY": (7, 3), + "TN": (6, 3), + "MS": (6, 2), + "AL": (7, 2), + "GA": (8, 2), + "FL": (8, 1), + "SC": (9, 2), + "NC": (9, 3), + "VA": (9, 4), + "WV": (8, 3), + "PA": (10, 4), + "NY": (10, 5), + "VT": (11, 5), + "NH": (11, 4), + "ME": (12, 5), + "MA": (11, 3), + "RI": (12, 3), + "CT": (11, 2), + "NJ": (10, 3), + "DE": (10, 2), + "MD": (9, 1), + "DC": (10, 1), +} + +# Population density values (people per sq mile) - realistic ranges +density_values = { + "AK": 1, + "HI": 226, + "CA": 253, + "TX": 112, + "FL": 411, + "NY": 408, + "PA": 286, + "IL": 227, + "OH": 289, + "GA": 185, + "NC": 218, + "MI": 177, + "NJ": 1263, + "VA": 218, + "WA": 117, + "AZ": 64, + "MA": 901, + "TN": 167, + "IN": 189, + "MO": 89, + "MD": 636, + "WI": 108, + "CO": 57, + "MN": 71, + "SC": 173, + "AL": 99, + "LA": 107, + "KY": 114, + "OR": 44, + "OK": 58, + "CT": 733, + "IA": 57, + "MS": 63, + "AR": 58, + "UT": 40, + "NV": 28, + "KS": 36, + "NM": 17, + "NE": 25, + "WV": 74, + "ID": 23, + "ME": 44, + "NH": 154, + "RI": 1061, + "MT": 8, + "DE": 508, + "SD": 12, + "ND": 11, + "VT": 68, + "WY": 6, + # DC intentionally missing to demonstrate missing data handling +} + +# Prepare data for rectangles +xs = [] +ys = [] +widths = [] +heights = [] +colors = [] +abbrevs = [] +abbrev_x = [] +abbrev_y = [] + +# Color mapping +min_val = min(density_values.values()) +max_val = max(density_values.values()) +palette = list(reversed(Blues9)) +color_mapper = LinearColorMapper(palette=palette, low=min_val, high=max_val, nan_color="#d0d0d0") + +# Process each region - rect is centered, so adjust coords to center of tile +for abbrev, (col, row) in regions.items(): + center_x = col * 1.1 + 0.5 + center_y = row * 1.1 + 0.5 + xs.append(center_x) + ys.append(center_y) + widths.append(1.0) + heights.append(1.0) + abbrev_x.append(center_x) + abbrev_y.append(center_y) + abbrevs.append(abbrev) + + if abbrev in density_values: + density = density_values[abbrev] + # Map to color index + norm = (density - min_val) / (max_val - min_val) + idx = min(int(norm * (len(palette) - 1)), len(palette) - 1) + colors.append(palette[idx]) + else: + # Missing data - gray with pattern indication + colors.append("#d0d0d0") + +# Create data sources +rect_source = ColumnDataSource(data={"x": xs, "y": ys, "width": widths, "height": heights, "fill_color": colors}) + +# Determine text colors based on background +text_colors = [] +for abbrev in abbrevs: + if abbrev not in density_values: + text_colors.append("#333333") + else: + density = density_values[abbrev] + norm = (density - min_val) / (max_val - min_val) + text_colors.append("white" if norm > 0.5 else "#306998") + +label_source = ColumnDataSource(data={"x": abbrev_x, "y": abbrev_y, "text": abbrevs, "text_color": text_colors}) + +# Create figure (4800x2700 for landscape) +p = figure( + width=4800, + height=2700, + title="US Population Density · choropleth-basic · bokeh · pyplots.ai", + x_axis_location=None, + y_axis_location=None, + tools="", + toolbar_location=None, + x_range=(-1, 14), + y_range=(0, 7), +) + +# Remove grid and axes +p.grid.grid_line_color = None +p.outline_line_color = None +p.xaxis.visible = False +p.yaxis.visible = False + +# Draw rectangles for each state +p.rect( + x="x", + y="y", + width="width", + height="height", + source=rect_source, + fill_color="fill_color", + fill_alpha=0.9, + line_color="white", + line_width=2, +) + +# Add state abbreviation labels +labels = LabelSet( + x="x", + y="y", + text="text", + text_color="text_color", + source=label_source, + text_align="center", + text_baseline="middle", + text_font_size="18pt", + text_font_style="bold", +) +p.add_layout(labels) + +# Title styling +p.title.text_font_size = "32pt" +p.title.align = "center" + +# Color bar for legend +color_bar = ColorBar( + color_mapper=color_mapper, + width=40, + height=800, + location=(0, 0), + title="Population Density (per sq mile)", + title_text_font_size="20pt", + major_label_text_font_size="16pt", + title_standoff=15, + padding=20, +) +p.add_layout(color_bar, "right") + +# Save output +export_png(p, filename="plot.png") From 9d4f1468e5c7ace7230931b7785e2200eedb394b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 21:33:44 +0000 Subject: [PATCH 2/5] chore(bokeh): add metadata for choropleth-basic --- plots/choropleth-basic/metadata/bokeh.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plots/choropleth-basic/metadata/bokeh.yaml diff --git a/plots/choropleth-basic/metadata/bokeh.yaml b/plots/choropleth-basic/metadata/bokeh.yaml new file mode 100644 index 0000000000..362bcc6239 --- /dev/null +++ b/plots/choropleth-basic/metadata/bokeh.yaml @@ -0,0 +1,19 @@ +# Per-library metadata for bokeh implementation of choropleth-basic +# Auto-generated by impl-generate.yml + +library: bokeh +specification_id: choropleth-basic +created: '2025-12-31T21:33:44Z' +updated: '2025-12-31T21:33:44Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 20627498185 +issue: 3069 +python_version: 3.13.11 +library_version: 3.8.1 +preview_url: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot_thumb.png +preview_html: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot.html +quality_score: null +review: + strengths: [] + weaknesses: [] From 4d65ddfeb2470cad2d3a97964bfded91c7092796 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 21:35:57 +0000 Subject: [PATCH 3/5] chore(bokeh): update quality score 88 and review feedback for choropleth-basic --- .../choropleth-basic/implementations/bokeh.py | 6 ++--- plots/choropleth-basic/metadata/bokeh.yaml | 24 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/plots/choropleth-basic/implementations/bokeh.py b/plots/choropleth-basic/implementations/bokeh.py index 457c715373..a90f3a2c0b 100644 --- a/plots/choropleth-basic/implementations/bokeh.py +++ b/plots/choropleth-basic/implementations/bokeh.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai choropleth-basic: Choropleth Map with Regional Coloring -Library: bokeh | Python 3.13 -Quality: pending | Created: 2025-12-31 +Library: bokeh 3.8.1 | Python 3.13.11 +Quality: 88/100 | Created: 2025-12-31 """ from bokeh.io import export_png diff --git a/plots/choropleth-basic/metadata/bokeh.yaml b/plots/choropleth-basic/metadata/bokeh.yaml index 362bcc6239..d8ae3486eb 100644 --- a/plots/choropleth-basic/metadata/bokeh.yaml +++ b/plots/choropleth-basic/metadata/bokeh.yaml @@ -1,10 +1,7 @@ -# Per-library metadata for bokeh implementation of choropleth-basic -# Auto-generated by impl-generate.yml - library: bokeh specification_id: choropleth-basic created: '2025-12-31T21:33:44Z' -updated: '2025-12-31T21:33:44Z' +updated: '2025-12-31T21:35:57Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20627498185 issue: 3069 @@ -13,7 +10,20 @@ library_version: 3.8.1 preview_url: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot_thumb.png preview_html: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot.html -quality_score: null +quality_score: 88 review: - strengths: [] - weaknesses: [] + strengths: + - Excellent use of tile grid map approach which works well for Bokeh rect glyph + capabilities + - Smart handling of missing data with gray color and nan_color configuration + - Good text contrast logic - white text on dark backgrounds, blue text on light + backgrounds + - Clean, well-organized code following KISS principles + - Realistic population density data with proper units in the legend + weaknesses: + - Title format should follow exact spec pattern "{spec-id} · {library} · pyplots.ai" + not include data description + - Color bar is functional but relatively small compared to the main plot; could + be more prominent + - Some very low density states (AK, WY, MT, etc.) are nearly indistinguishable from + each other in the lightest color band From cad7a8dd9727b2052b706263322a4150462b67df Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 21:39:20 +0000 Subject: [PATCH 4/5] fix(bokeh): address review feedback for choropleth-basic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attempt 1/3 - fixes based on AI review: - Fixed title format to match spec pattern: {spec-id} · {library} · pyplots.ai - Improved color bar visibility (larger size and fonts) - Changed from linear to log color scale for better differentiation of low-density states 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../choropleth-basic/implementations/bokeh.py | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/plots/choropleth-basic/implementations/bokeh.py b/plots/choropleth-basic/implementations/bokeh.py index a90f3a2c0b..62429ce2e4 100644 --- a/plots/choropleth-basic/implementations/bokeh.py +++ b/plots/choropleth-basic/implementations/bokeh.py @@ -1,11 +1,13 @@ -""" pyplots.ai +"""pyplots.ai choropleth-basic: Choropleth Map with Regional Coloring Library: bokeh 3.8.1 | Python 3.13.11 Quality: 88/100 | Created: 2025-12-31 """ +import math + from bokeh.io import export_png -from bokeh.models import ColorBar, ColumnDataSource, LabelSet, LinearColorMapper +from bokeh.models import ColorBar, ColumnDataSource, LabelSet, LogColorMapper from bokeh.palettes import Blues9 from bokeh.plotting import figure @@ -131,11 +133,11 @@ abbrev_x = [] abbrev_y = [] -# Color mapping -min_val = min(density_values.values()) +# Color mapping - use log scale to better differentiate low-density states +min_val = max(1, min(density_values.values())) # Log scale needs min > 0 max_val = max(density_values.values()) palette = list(reversed(Blues9)) -color_mapper = LinearColorMapper(palette=palette, low=min_val, high=max_val, nan_color="#d0d0d0") +color_mapper = LogColorMapper(palette=palette, low=min_val, high=max_val, nan_color="#d0d0d0") # Process each region - rect is centered, so adjust coords to center of tile for abbrev, (col, row) in regions.items(): @@ -151,8 +153,11 @@ if abbrev in density_values: density = density_values[abbrev] - # Map to color index - norm = (density - min_val) / (max_val - min_val) + # Map to color index using log scale for better low-value differentiation + log_min = math.log10(min_val) + log_max = math.log10(max_val) + log_val = math.log10(max(density, 1)) # Ensure positive for log + norm = (log_val - log_min) / (log_max - log_min) idx = min(int(norm * (len(palette) - 1)), len(palette) - 1) colors.append(palette[idx]) else: @@ -162,14 +167,17 @@ # Create data sources rect_source = ColumnDataSource(data={"x": xs, "y": ys, "width": widths, "height": heights, "fill_color": colors}) -# Determine text colors based on background +# Determine text colors based on background (using log scale) text_colors = [] +log_min = math.log10(min_val) +log_max = math.log10(max_val) for abbrev in abbrevs: if abbrev not in density_values: text_colors.append("#333333") else: density = density_values[abbrev] - norm = (density - min_val) / (max_val - min_val) + log_val = math.log10(max(density, 1)) + norm = (log_val - log_min) / (log_max - log_min) text_colors.append("white" if norm > 0.5 else "#306998") label_source = ColumnDataSource(data={"x": abbrev_x, "y": abbrev_y, "text": abbrevs, "text_color": text_colors}) @@ -178,7 +186,7 @@ p = figure( width=4800, height=2700, - title="US Population Density · choropleth-basic · bokeh · pyplots.ai", + title="choropleth-basic · bokeh · pyplots.ai", x_axis_location=None, y_axis_location=None, tools="", @@ -224,17 +232,18 @@ p.title.text_font_size = "32pt" p.title.align = "center" -# Color bar for legend +# Color bar for legend - made larger for prominence color_bar = ColorBar( color_mapper=color_mapper, - width=40, - height=800, + width=60, + height=1200, location=(0, 0), title="Population Density (per sq mile)", - title_text_font_size="20pt", - major_label_text_font_size="16pt", - title_standoff=15, - padding=20, + title_text_font_size="24pt", + major_label_text_font_size="20pt", + title_standoff=20, + padding=30, + margin=40, ) p.add_layout(color_bar, "right") From 9eec6a965d48a320e126d3750dcde4dd9ed75754 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 21:41:36 +0000 Subject: [PATCH 5/5] chore(bokeh): update quality score 91 and review feedback for choropleth-basic --- .../choropleth-basic/implementations/bokeh.py | 4 +-- plots/choropleth-basic/metadata/bokeh.yaml | 28 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/plots/choropleth-basic/implementations/bokeh.py b/plots/choropleth-basic/implementations/bokeh.py index 62429ce2e4..df3ad45fc5 100644 --- a/plots/choropleth-basic/implementations/bokeh.py +++ b/plots/choropleth-basic/implementations/bokeh.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai choropleth-basic: Choropleth Map with Regional Coloring Library: bokeh 3.8.1 | Python 3.13.11 -Quality: 88/100 | Created: 2025-12-31 +Quality: 91/100 | Created: 2025-12-31 """ import math diff --git a/plots/choropleth-basic/metadata/bokeh.yaml b/plots/choropleth-basic/metadata/bokeh.yaml index d8ae3486eb..f6024e4270 100644 --- a/plots/choropleth-basic/metadata/bokeh.yaml +++ b/plots/choropleth-basic/metadata/bokeh.yaml @@ -1,7 +1,7 @@ library: bokeh specification_id: choropleth-basic created: '2025-12-31T21:33:44Z' -updated: '2025-12-31T21:35:57Z' +updated: '2025-12-31T21:41:36Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20627498185 issue: 3069 @@ -10,20 +10,18 @@ library_version: 3.8.1 preview_url: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot_thumb.png preview_html: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/bokeh/plot.html -quality_score: 88 +quality_score: 91 review: strengths: - - Excellent use of tile grid map approach which works well for Bokeh rect glyph - capabilities - - Smart handling of missing data with gray color and nan_color configuration - - Good text contrast logic - white text on dark backgrounds, blue text on light - backgrounds - - Clean, well-organized code following KISS principles - - Realistic population density data with proper units in the legend + - Excellent use of Bokeh-specific features including LogColorMapper for better differentiation + of low-density states + - Smart contrast handling with dynamic text colors (white on dark, blue on light + backgrounds) + - Good missing data handling demonstrated with DC shown in gray + - Clean tile grid approach that fits all 50 states + DC in a readable layout + - Well-implemented color bar with logarithmic scale and clear labeling weaknesses: - - Title format should follow exact spec pattern "{spec-id} · {library} · pyplots.ai" - not include data description - - Color bar is functional but relatively small compared to the main plot; could - be more prominent - - Some very low density states (AK, WY, MT, etc.) are nearly indistinguishable from - each other in the lightest color band + - Title format should be exactly "choropleth-basic · bokeh · pyplots.ai" without + the "US Population Density" prefix + - Tile grid approach, while creative and readable, differs from traditional geographic + projection that spec mentions (Robinson for world, Albers for US)