← GeoAI SkillsCONTENT HISTORY

Update to GeoAI Skills

Snapshot Sep 30, 2026 · 23:13 UTC · version 0.4.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "cartography-geoviz",
  "description": "Always invoke before answering any request to create, compare, design, or review a user-facing map, even if the request is terse or underspecified. Covers publication maps, choropleths, map series and small multiples, comparable multi-date panels, proportional/bivariate/flow maps, raster rendering, and interactive web maps. Includes classification, color, legends, projections, accessibility, and large-data aggregation. Do not trigger for a temporary diagnostic plot inside another analysis.",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 224
    },
    {
      "relative_path": "references/authoritative-sources.md",
      "size_in_bytes": 793
    }
  ],
  "skill_md_contents": "---\nname: cartography-geoviz\ndescription: >-\n  Always invoke before answering any request to create, compare, design, or\n  review a user-facing map, even if the request is terse or underspecified.\n  Covers publication maps, choropleths, map series and small multiples,\n  comparable multi-date panels, proportional/bivariate/flow maps, raster\n  rendering, and interactive web maps. Includes classification, color,\n  legends, projections, accessibility, and large-data aggregation. Do not\n  trigger for a temporary diagnostic plot inside another analysis.\nlicense: MIT\nmetadata:\n  author: Muhammed Enes Duran\n---\n\n# Cartography & Geovisualization\n\nPurpose: maps that communicate honestly. Cartographic choices (class\nbreaks, ramps, normalization, projection) can manufacture or hide\npatterns; this skill treats them as analytical decisions with stated\nrationale, not styling.\n\n## The first three questions\n\n1. **What's the message?** One map = one message. If two variables\n   compete, consider small multiples or a bivariate scheme — not twelve\n   legend classes.\n2. **Normalized?** Choropleths of raw counts are population maps in\n   disguise. Rates, densities, or per-capita for area-based color; raw\n   magnitudes → proportional symbols instead.\n3. **Static or interactive?** Print/PDF/paper → matplotlib/QGIS layout;\n   exploration/stakeholders → Folium/MapLibre; big point data →\n   Kepler.gl/deck.gl (GPU).\n\n## Thematic map type selection\n\n| Data | Map type |\n|---|---|\n| Rate/ratio by polygon | Choropleth |\n| Count/magnitude by place | Proportional/graduated symbols |\n| Two related rates | Bivariate choropleth (3×3 max) |\n| Individual-level density | Dot density or KDE surface (label bandwidth) |\n| Continuous field (raster) | Classified or stretched render + hillshade context |\n| Movement/OD | Flow map (width∝volume), aggregate to avoid hairballs |\n| Change over time | Small multiples > animation for analysis; animation for outreach |\n\n## Classification — the honesty lever\n\n- **Natural breaks (Jenks)**: default for skewed data; breaks are\n  data-specific, so NOT comparable across maps/dates.\n- **Quantiles**: guaranteed color balance; can split near-identical values.\n- **Equal interval**: comparable and intuitive; fails on skew.\n- **Manual/defined**: the ONLY correct choice for map series (same breaks\n  across all dates/regions) and for domain thresholds (WHO limits, slope\n  classes).\n- 5±2 classes; show the histogram with breaks in the workflow; state the\n  scheme in the caption/metadata. Try two schemes — if the story changes\n  materially, the story is the classification, and the reader must be told.\n\n## Color\n\n- Ramps from ColorBrewer/`cmcrameri`/viridis family: sequential (ordered),\n  diverging (meaningful midpoint — zero, mean, threshold), qualitative\n  (categories, ≤ 8).\n- Colorblind-safe by default (~8% of male readers); never red-green\n  diverging without checking a CVD simulator.\n- NoData ≠ zero: render as neutral gray with its own legend entry, never\n  the ramp's low end.\n- Muted basemaps (CartoDB Positron) under thematic layers — the basemap\n  must never win.\n\n## Projection for display\n\n- Web tiles = Web Mercator: fine for city scale; area comparisons at\n  continental scale on Mercator are visual lies — use equal-area\n  projections (Albers, Mollweide, Equal Earth) for static thematic maps of\n  large extents.\n- National mapping → the national grid; polar work → polar stereographic.\n- Label the projection on publication maps.\n\n## Required furniture (publication static maps)\n\nTitle (the message, not the filename), legend (units!, sensible number\nformatting), scale bar (projected CRS only — degrees have no fixed scale),\nnorth arrow (only when north isn't up or the audience expects it), data\nsource + date + projection + author, and an inset locator map for\nunfamiliar regions.\n\n```python\n# GeoPandas static map core\nax = gdf.plot(column=\"rate_per_1k\", scheme=\"naturalbreaks\", k=5,\n              cmap=\"YlGnBu\", legend=True, edgecolor=\"white\", linewidth=0.3,\n              missing_kwds={\"color\": \"#d9d9d9\", \"label\": \"No data\"})\nax.set_axis_off()\n```\n\nExport: 300 dpi PNG/PDF for print; SVG when editors will touch it; COG +\nstyle for GIS handoff.\n\n## Interactive maps\n\n- Folium/MapLibre: tooltips with formatted values, layer control, sensible\n  initial bounds (`fit_bounds`), legend included (Folium needs a manual\n  HTML/branca legend — don't ship without one).\n- Performance: >~50k vector features → tile it (tippecanoe → PMTiles) or\n  switch to deck.gl/Kepler; never dump 500k GeoJSON features into Leaflet.\n- Every popup number formatted (thousands separators, units, rounding\n  matched to precision honesty).\n\n## Verification protocol\n\n1. Squint test: does the message survive at thumbnail size?\n2. CVD simulation pass.\n3. Legend audit: units, rounding, class edges non-overlapping.\n4. Cross-check 3 features' rendered values against the attribute table\n   (classification bugs are silent).\n5. For map series: identical breaks, ramp, and extent across panels.\n\n## Pitfalls checklist\n\n- Raw-count choropleth (population in disguise).\n- Jenks breaks compared across two dates.\n- Red-green diverging ramp, unlabeled midpoint.\n- NoData painted as the lowest class.\n- Scale bar on an unprojected (degree) map.\n- Continental-area comparisons on Web Mercator.\n- Interactive map with no legend or units.\n\n## Execution contract\n\n- **Workflow:** inspect audience, data semantics, scale, and output medium; select projection, normalization, classification, and visual hierarchy; render; verify; export.\n- **Decision rules:** choose map type from the analytical question, normalize counts when exposure differs, and keep breaks fixed for comparisons.\n- **Verification protocol:** run the five checks above and reconcile rendered values, units, class edges, and missing-data treatment against the source.\n- **Failure modes:** stop or qualify delivery when denominators, CRS, units, accessibility, or cross-panel comparability are unresolved.\n- **Deliverables:** final map, legend and units, data/source note, projection and classification rationale, accessibility note, and reproducible style or code.\n- **Source freshness:** consult [the authoritative source registry](references/authoritative-sources.md) before using version-sensitive APIs and record the checked date.\n"
}

SHA-256: 37f4db92c7d321ebe83ef63a9ac79b7a7d7f86dfb49f805ac7521c9d5625fa07