diff --git a/plots/scatter-map-geographic/implementations/python/plotnine.py b/plots/scatter-map-geographic/implementations/python/plotnine.py index 34cca3046b..e5ffc91611 100644 --- a/plots/scatter-map-geographic/implementations/python/plotnine.py +++ b/plots/scatter-map-geographic/implementations/python/plotnine.py @@ -1,10 +1,11 @@ -""" pyplots.ai +""" anyplot.ai scatter-map-geographic: Scatter Map with Geographic Points -Library: plotnine 0.15.2 | Python 3.13.11 -Quality: 91/100 | Created: 2026-01-10 +Library: plotnine 0.15.4 | Python 3.13.13 +Quality: 97/100 | Updated: 2026-05-18 """ -import numpy as np +import os + import pandas as pd from plotnine import ( aes, @@ -24,9 +25,18 @@ ) -# Data: Major world cities with population and region -np.random.seed(42) +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +BASEMAP_COLOR = "#E8E3D8" if THEME == "light" else "#2A2A26" +BASEMAP_EDGE = "#C0B5A8" if THEME == "light" else "#4A4945" +GRID_COLOR = INK if THEME == "light" else INK +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" + +OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9"] +# Data: Major world cities with population and region cities_data = { "city": [ "Tokyo", @@ -255,15 +265,14 @@ df_continents = pd.DataFrame(continents) -# Define region colors using colorblind-safe palette (Python Blue first) -# Order alphabetically as plotnine uses alphabetical ordering for scale_color_manual +# Define region colors using Okabe-Ito palette region_colors = { - "Africa": "#9467BD", - "Asia": "#306998", - "Europe": "#FFD43B", - "N. America": "#2CA02C", - "Oceania": "#17BECF", - "S. America": "#D62728", + "Africa": OKABE_ITO[0], + "Asia": OKABE_ITO[1], + "Europe": OKABE_ITO[2], + "N. America": OKABE_ITO[3], + "Oceania": OKABE_ITO[4], + "S. America": OKABE_ITO[5], } # Create the geographic scatter map @@ -272,33 +281,33 @@ + geom_polygon( aes(x="lon", y="lat", group="continent"), data=df_continents, - fill="#E8E8E8", - color="#B0B0B0", + fill=BASEMAP_COLOR, + color=BASEMAP_EDGE, size=0.5, - alpha=0.8, + alpha=0.6, ) - + geom_point(aes(x="longitude", y="latitude", color="region", size="population"), data=df, alpha=0.85, stroke=0.3) + + geom_point(aes(x="longitude", y="latitude", color="region", size="population"), data=df, alpha=0.8, stroke=0.5) + scale_color_manual(values=list(region_colors.values()), name="Region") - + scale_size_continuous(range=(3, 18), name="Population (M)") - + labs( - title="World Major Cities · scatter-map-geographic · plotnine · pyplots.ai", x="Longitude (°)", y="Latitude (°)" - ) + + scale_size_continuous(range=(4, 20), name="Population (M)") + + labs(title="scatter-map-geographic · python · plotnine · anyplot.ai", x="Longitude (°)", y="Latitude (°)") + coord_fixed(ratio=1.0, xlim=(-180, 180), ylim=(-60, 80)) + theme_minimal() + theme( figure_size=(16, 9), - plot_title=element_text(size=24, weight="bold"), - axis_title=element_text(size=20), - axis_text=element_text(size=16), - legend_title=element_text(size=18), - legend_text=element_text(size=14), + plot_title=element_text(size=24, color=INK), + axis_title=element_text(size=20, color=INK), + axis_text=element_text(size=16, color=INK_SOFT), + legend_title=element_text(size=18, color=INK), + legend_text=element_text(size=14, color=INK_SOFT), + legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT, size=0.3), legend_position="right", - panel_grid_major=element_line(color="#DDDDDD", size=0.3, alpha=0.5), + panel_grid_major=element_line(color=GRID_COLOR, size=0.3, alpha=0.08), panel_grid_minor=element_blank(), - panel_background=element_rect(fill="#D4E8F7", color=None), - plot_background=element_rect(fill="#F5F5F5", color=None), + panel_background=element_rect(fill=PAGE_BG, color=None), + plot_background=element_rect(fill=PAGE_BG, color=None), + panel_border=element_blank(), ) ) -# Save PNG (dpi=300 gives 4800x2700 from 16x9 inches) -plot.save("plot.png", dpi=300, verbose=False) +# Save PNG +plot.save(f"plot-{THEME}.png", dpi=300, verbose=False) diff --git a/plots/scatter-map-geographic/metadata/python/plotnine.yaml b/plots/scatter-map-geographic/metadata/python/plotnine.yaml index a98826197a..1b2048f3d8 100644 --- a/plots/scatter-map-geographic/metadata/python/plotnine.yaml +++ b/plots/scatter-map-geographic/metadata/python/plotnine.yaml @@ -1,162 +1,170 @@ library: plotnine +language: python specification_id: scatter-map-geographic created: '2026-01-10T06:02:56Z' -updated: '2026-01-10T06:06:02Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20873879624 +updated: '2026-05-18T18:06:21Z' +generated_by: claude-haiku +workflow_run: 26050750874 issue: 3617 -python_version: 3.13.11 -library_version: 0.15.2 -preview_url: https://storage.googleapis.com/anyplot-images/plots/scatter-map-geographic/plotnine/plot.png -preview_html: null -quality_score: 91 +language_version: 3.13.13 +library_version: 0.15.4 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-map-geographic/python/plotnine/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-map-geographic/python/plotnine/plot-dark.png +preview_html_light: null +preview_html_dark: null +quality_score: 97 review: strengths: - - Creative solution using geom_polygon for continent basemap in a library without - native map support - - Excellent use of plotnine grammar of graphics with layered geoms - - High-quality colorblind-safe palette with good contrast - - Clean, well-structured code following KISS principles - - Both color and size legends are clear and informative + - 'Perfect palette compliance: first series is #009E73, full Okabe-Ito order followed' + - 'Exceptional theme adaptation: both light and dark renders fully readable with + proper color tokens' + - 'Excellent geographic visualization: uses coord_fixed correctly for proper lat/long + aspect ratio' + - 'Complete feature implementation: all spec requirements met (color, size, basemap, + legends)' + - 'Strong library mastery: demonstrates understanding of plotnine''s grammar through + custom polygon layers' + - 'Real, neutral data: 30 major cities with realistic populations' + - 'Clean, reproducible code: deterministic with no random state needed' weaknesses: - - Title format slightly non-standard (data description first instead of spec-id - first) - - Simplified continent polygons are crude approximations (especially Africa shape) - - Element visibility could be improved for smaller cities - image_description: 'The plot displays a world map showing 30 major cities as scatter - points positioned by their latitude and longitude coordinates. The basemap consists - of simplified continent polygon outlines (light gray with darker gray borders) - against a light blue ocean background (#D4E8F7). Cities are color-coded by region: - Africa (purple), Asia (blue #306998), Europe (yellow #FFD43B), N. America (green - #2CA02C), Oceania (cyan #17BECF), and S. America (red #D62728). Point sizes vary - based on population, ranging from approximately 5M (Cape Town) to 37M (Tokyo). - The title "World Major Cities · scatter-map-geographic · plotnine · pyplots.ai" - is displayed prominently at the top in bold 24pt font. Two legends appear on the - right side: a categorical "Region" legend with colored dots for each of the 6 - regions, and a "Population (M)" legend showing size scaling with example values - of 10, 20, and 30 million. Axis labels show "Longitude (°)" on the x-axis and - "Latitude (°)" on the y-axis with appropriate tick marks at regular intervals. - The overall layout uses the full 16:9 canvas effectively with the map occupying - the central area and legends positioned cleanly on the right without overlapping - the data.' + - Design Excellence slightly below maximum (17/20) — could add more visual hierarchy + or sophisticated refinements + - Visual storytelling could be enhanced with annotations or more dramatic visual + emphasis + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) with continent outlines in light beige + Chrome: Title, axis labels, and tick labels all dark text, clearly readable against light surface + Data: Points color-coded by region using Okabe-Ito (Africa #009E73, Asia #D55E00, Europe #0072B2, N. America #CC79A7, Oceania #E69F00, S. America #56B4E9); sizes encode population (4-20px range) + Legibility verdict: PASS - all text fully readable, no light-on-light failures + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) with continent outlines in darker gray + Chrome: Title, axis labels, tick labels appear in light gray/off-white, all clearly readable; no dark-on-dark failures + Data: Colors identical to light render (#009E73 for Africa, etc.); only chrome has flipped themes + Legibility verdict: PASS - excellent contrast, all elements distinguishable, brand green visible criteria_checklist: visual_quality: - score: 36 - max: 40 + score: 30 + max: 30 items: - id: VQ-01 name: Text Legibility - score: 10 - max: 10 + score: 8 + max: 8 passed: true - comment: Title 24pt bold, axis titles 20pt, axis text 16pt, legend text 14-18pt - - all perfectly readable + comment: All fonts properly sized and readable in both light and dark themes - id: VQ-02 name: No Overlap - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: No overlapping text; city markers have natural overlap in dense regions - handled with alpha=0.85 + comment: Clean layout with acceptable geographic data clustering; no interference - id: VQ-03 name: Element Visibility score: 6 - max: 8 + max: 6 passed: true - comment: Markers sized appropriately for 30 points; some smaller cities could - be slightly larger + comment: All markers clearly visible and distinct by color and size - id: VQ-04 name: Color Accessibility - score: 5 - max: 5 + score: 2 + max: 2 passed: true - comment: Colorblind-safe palette with distinct hues and good contrast against - basemap + comment: Okabe-Ito palette is colorblind-safe with color+size redundancy - id: VQ-05 - name: Layout Balance - score: 3 - max: 5 + name: Layout & Canvas + score: 4 + max: 4 passed: true - comment: Good overall layout; simplified continent shapes leave some empty - areas + comment: 16:9 aspect ratio well-suited for global map; generous margins - id: VQ-06 - name: Axis Labels + name: Axis Labels & Title score: 2 max: 2 passed: true - comment: 'Descriptive labels with units: Longitude (°) and Latitude (°)' + comment: Title format correct; axes labeled with units - id: VQ-07 - name: Grid & Legend + name: Palette Compliance score: 2 max: 2 passed: true - comment: Subtle grid with alpha=0.5, legends well-positioned on right + comment: 'First series #009E73, Okabe-Ito order, correct backgrounds, identical + colors between themes' + design_excellence: + score: 17 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 7 + max: 8 + passed: true + comment: Custom basemap, theme-adaptive design, professional typography + - id: DE-02 + name: Visual Refinement + score: 5 + max: 6 + passed: true + comment: Clean minimal style, subtle grid, custom legend background + - id: DE-03 + name: Data Storytelling + score: 5 + max: 6 + passed: true + comment: Clear geographic distribution, good visual hierarchy, color and size + encoding spec_compliance: - score: 23 - max: 25 + score: 15 + max: 15 items: - id: SC-01 name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct geographic scatter map with points positioned by lat/lon - - id: SC-02 - name: Data Mapping score: 5 max: 5 passed: true - comment: Longitude to X, Latitude to Y correctly assigned - - id: SC-03 + comment: Correct scatter map with lat/long positioning + - id: SC-02 name: Required Features score: 4 - max: 5 + max: 4 passed: true - comment: Has color encoding, size encoding, basemap context; simplified polygons - instead of country boundaries - - id: SC-04 - name: Data Range + comment: Color, size, basemap, and legends all present + - id: SC-03 + name: Data Mapping score: 3 max: 3 passed: true - comment: Axes show full world extent (-180 to 180 lon, -60 to 80 lat) - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 + comment: Longitude and latitude correctly mapped + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 passed: true - comment: Both region color and population size legends are accurate - - id: SC-06 - name: Title Format - score: 1 - max: 2 - passed: false - comment: Title uses data description first instead of spec-id first + comment: Title format correct; region labels and population scale displayed data_quality: - score: 19 - max: 20 + score: 15 + max: 15 items: - id: DQ-01 name: Feature Coverage - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: Shows cities across all 6 regions with varying population sizes; - demonstrates color and size encoding well + comment: All aspects of scatter-map-geographic shown with 30 cities across + 6 regions - id: DQ-02 name: Realistic Context - score: 7 - max: 7 + score: 5 + max: 5 passed: true - comment: Real world cities with accurate coordinates and realistic population - figures + comment: Real world cities with realistic populations; neutral data selection - id: DQ-03 name: Appropriate Scale score: 4 - max: 5 + max: 4 passed: true - comment: Population values realistic; coordinates accurate; basemap scale - reasonable but simplified + comment: Population range 4.8M-37.4M; sizes 4-20px appropriate for visibility code_quality: score: 10 max: 10 @@ -166,42 +174,48 @@ review: score: 3 max: 3 passed: true - comment: Clean imports, data, plot, save structure; no functions or classes + comment: No functions/classes; direct execution; straightforward and readable - id: CQ-02 name: Reproducibility - score: 3 - max: 3 + score: 2 + max: 2 passed: true - comment: np.random.seed(42) is set even though data is deterministic + comment: All data deterministic; no randomness - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used; appropriate plotnine components imported + comment: Only necessary imports; all used - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 + name: Code Elegance + score: 2 + max: 2 passed: true - comment: Uses current plotnine API + comment: Theme handling via environment variables; no fake UI - id: CQ-05 - name: Output Correct + name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png with dpi=300 - library_features: - score: 3 - max: 5 + comment: Saves as plot-{THEME}.png with DPI 300 + library_mastery: + score: 10 + max: 10 items: - - id: LF-01 + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: Proper ggplot composition, correct geom usage, coord_fixed for mapping + - id: LM-02 name: Distinctive Features - score: 3 + score: 5 max: 5 passed: true - comment: Uses plotnine grammar well (aes, geom_polygon, geom_point, scale_*, - theme); creative geom_polygon basemap workaround + comment: Custom polygon basemap, theme-adaptive design, coordinate projection + mastery verdict: APPROVED impl_tags: dependencies: [] @@ -212,4 +226,3 @@ impl_tags: dataprep: [] styling: - alpha-blending - - grid-styling