Skip to main content

kortagerd

Generate Iceland maps from cached LMI data — static (matplotlib) and interactive (Leaflet), with ISN93 derived cache.

معلومات المصدر

المستودع
jokull/icelandic-data
آخر نشاط في المصدر
١٠ سبتمبر ٢٠٢٦ في ١٥:٠٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥٤
التفرعات
٤

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
kortagerd
description
Generate Iceland maps from cached LMI data — static (matplotlib) and interactive (Leaflet), with ISN93 derived cache.
# Kortagerð (Mapmaking) — Iceland Maps **Requires:** Tier 1 (maps) — geopandas + matplotlib rendering; `uv sync --group maps`. Generate high-quality maps of Iceland using cached LMI geodata. Supports interactive HTML (Leaflet) and static PNG/SVG (geopandas + matplotlib). ## Quick Start ```bash # Ensure geodata is cached uv run python scripts/lmi.py download # Interactive map (full-screen, layer toggles, popups) uv run python scripts/kortagerð.py html -o reports/map.html # Static map (publication-quality PNG) uv run python scripts/kortagerð.py static -o reports/map.png # Zoomed to capital area with Reykjavík highlighted uv run python scripts/kortagerð.py static --bounds capital --highlight "Reykjavíkurborg" -o reports/rvk.png # Overlay custom points from CSV uv run python scripts/kortagerð.py static --points data/my_locations.csv -o reports/custom.png ``` ## Bounding Box Presets | Name | Area | Bounds [W, S, E, N] | |------|------|---------------------| | `iceland` | Full country (default) | -24.7, 63.2, -13.1, 66.6 | | `capital` / `reykjavik` | Greater Reykjavík | -22.1, 63.95, -21.3, 64.25 | | `southwest` | Reykjanes to Hekla | -22.5, 63.6, -19.5, 64.5 | | `north` | Skagafjörður to Húsavík | -20.0, 65.2, -15.0, 66.6 | | `east` | Eastfjords | -16.0, 64.2, -13.3, 65.8 | | `westfjords` | Westfjords | -24.7, 65.0, -21.0, 66.6 | | `south` | South coast | -21.0, 63.2, -17.5, 64.3 | | `akureyri` | Akureyri area | -18.4, 65.5, -17.7, 65.8 | ## Cached Layers (in `data/geodata/`) | File | What | When to use | |------|------|-------------| | `Landmask.geojson` | Iceland land polygon | Always — base fill for any map | | `CoastalLine.geojson` | Coastline | Border outline | | `AdministrativeUnit_level2.geojson` | 128 municipalities | Choropleth, boundaries, `--highlight` | | `RoadLines.geojson` | Road network | Infrastructure, transport maps | | `WatercourseLine.geojson` | Rivers (28k features) | Hydrology (skip for perf if not needed) | | `Lake_Reservoir.geojson` | Lakes | Hydrology, geography | | `LandIceArea.geojson` | Glaciers | Terrain, geography | | `BuiltupAreaPoints.geojson` | 98 settlements + pop | City labels, settlement maps | | `NatureParkArea.geojson` | National parks | Environmental, tourism maps | | `IslandArea.geojson` | Islands | Offshore geography | | `Airport_Airfield_points.geojson` | Airports | Transport maps | | `Port.geojson` | Harbors | Maritime, transport maps | ## Caching strategy (for raster-overlay maps) Vector layers are pre-cached at Tier 1 (`data/geodata/`). For maps that overlay rasters (e.g. Copernicus HRL Grassland), three more tiers exist under `data/cache/` to avoid re-downloading and re-projecting on every render. | Tier | Path | Built by | What | Speedup | |------|------|----------|------|--------:| | 1 | `data/geodata/*.geojson` | `scripts/lmi.py download` | LMI WFS vectors (~50 MB) | — | | 2 | `data/raw/lmi_hrl/*.tif` | `scripts/lmi_hrl.py fetch grassland` | Source HRL GeoTIFFs (~860 MB) | — | | 3 | `data/cache/rasters/*.tif` | `scripts/build_cache.py rasters` | LZW + ISN93-projected GeoTIFFs (~9 MB each — **98× smaller**) | skip 30 s reproject per render | | 4 | `data/cache/constants.json` | `scripts/build_cache.py constants` | Iceland total area + 4-CRS bbox + per-source SHA-256 + grassland area | skip 1.5 s polygon area + 826 MB scan per render | | 5 | `data/cache/arrays/*.npy` | written automatically on first map render | Decoded probability arrays (e.g. GRAVPI) | skip 5 s RGB-decode + reproject | Render scripts read these tiers via `scripts/utils/cache.py`: ```python from scripts.utils.cache import iceland_constants, cached_raster, CacheMissingError try: K = iceland_constants() iceland_km2 = K["iceland_total_area_km2"] except CacheMissingError as e: print(e.hint) # tells you the build_cache.py command to run ``` Tier 3+4 are explicit (`build_cache.py all`); Tier 5 is opportunistic (populated on first render). Sources are SHA-256 fingerprinted in `constants.json` so `scripts/build_cache.py status` flags stale entries when an upstream raster changes. ### Benchmark ```bash # Cold (full re-download): ~120 s for grassland # Warm-raw (rebuild Tier 3+4): ~10 s for grassland # Warm (steady state): ~3-6 s uv run python scripts/bench_maps.py run --mode warm uv run python scripts/bench_maps.py history ``` Results land in `data/cache/benchmarks.json` with timestamps and a delta vs. the last `warm` baseline. ### Tests ```bash # Cache-source consistency + map-output smoke tests uv run pytest tests/test_cache_consistency.py tests/test_maps_render.py -v ``` ### Troubleshooting - *"Missing data/cache/constants.json"* → run `scripts/build_cache.py all` - *"STALE — source changed"* in status → run `scripts/build_cache.py rasters` - Render is slow despite cache → check `scripts/build_cache.py status`; the tier-5 `.npy` file may be missing for `grassland_probability_heatmap.py` (auto-rebuilds on next run). ## Python Code Templates ### Load a layer with geopandas ```python import geopandas as gpd from pathlib import Path GEODATA = Path("data/geodata") land = gpd.read_file(GEODATA / "Landmask.geojson") municipalities = gpd.read_file(GEODATA / "AdministrativeUnit_level2.geojson") ``` ### Simple choropleth map ```python import geopandas as gpd import matplotlib.pyplot as plt from pathlib import Path GEODATA = Path("data/geodata") land = gpd.read_file(GEODATA / "Landmask.geojson") munic = gpd.read_file(GEODATA / "AdministrativeUnit_level2.geojson") # Merge your data onto municipalities # munic = munic.merge(your_data, left_on="namn", right_on="municipality") fig, ax = plt.subplots(figsize=(12, 8), facecolor="#f0f4f8") ax.set_facecolor("#c8d6e5") land.plot(ax=ax, color="#f5f0e6", edgecolor="#2d3436", linewidth=0.6) munic.plot(ax=ax, column="your_metric", cmap="YlOrRd", legend=True, edgecolor="#636e72", linewidth=0.3, alpha=0.8) ax.set_xlim(-24.7, -13.1) ax.set_ylim(63.2, 66.6) ax.set_aspect(1 / 0.42) # latitude correction at 65°N ax.set_title("Your Title") plt.tight_layout() fig.savefig("reports/choropleth.png", dpi=200, bbox_inches="tight") ``` ### Overlay custom points ```python import polars as pl import geopandas as gpd import matplotlib.pyplot as plt GEODATA = Path("data/geodata") land = gpd.read_file(GEODATA / "Landmask.geojson") # Your point data pts = pl.read_csv("data/processed/your_points.csv") fig, ax = plt.subplots(figsize=(12, 8)) land.plot(ax=ax, color="#f5f0e6", edgecolor="#2d3436", linewidth=0.6) ax.scatter(pts["lon"], pts["lat"], c="#e74c3c", s=20, zorder=10) ``` ### Interactive HTML with custom data overlay ```python import json from pathlib import Path GEODATA = Path("data/geodata") # Load base layers with open(GEODATA / "Landmask.geojson") as f: landmask = json.load(f) # Build Leaflet HTML with your data embedded as JSON # Follow the pattern in scripts/kortagerð.py cmd_html() ``` ## R Code Templates ### Load layers with sf ```r library(sf) library(ggplot2) geodata <- "data/geodata" land <- st_read(file.path(geodata, "Landmask.geojson")) munic <- st_read(file.path(geodata, "AdministrativeUnit_level2.geojson")) roads <- st_read(file.path(geodata, "RoadLines.geojson")) glaciers <- st_read(file.path(geodata, "LandIceArea.geojson")) lakes <- st_read(file.path(geodata, "Lake_Reservoir.geojson")) ``` ### Basic ggplot2 map ```r ggplot() + geom_sf(data = land, fill = "#f5f0e6", color = "#2d3436", linewidth = 0.3) + geom_sf(data = glaciers, fill = "#dfe6e9", color = "#b2bec3", linewidth = 0.2) + geom_sf(data = lakes, fill = "#74b9ff", color = "#0984e3", linewidth = 0.2) + geom_sf(data = roads, color = "#e17055", linewidth = 0.3) + coord_sf(xlim = c(-24.7, -13.1), ylim = c(63.2, 66.6)) + theme_minimal() + labs(title = "Iceland") ``` ### Choropleth with municipality data ```r # Merge your data onto municipalities munic_data <- munic %>% left_join(your_data, by = c("namn" = "municipality")) ggplot() + geom_sf(data = land, fill = "#f5f0e6", color = "#2d3436", linewidth = 0.3) + geom_sf(data = munic_data, aes(fill = your_metric), color = "#636e72", linewidth = 0.2) + scale_fill_viridis_c() + coord_sf(xlim = c(-24.7, -13.1), ylim = c(63.2, 66.6)) + theme_minimal() ``` ## Color Palette Standard colors used by `kortagerð.py`: | Element | Fill | Stroke | |---------|------|--------| | Ocean | `#c8d6e5` | — | | Land | `#f5f0e6` | `#2d3436` | | Glaciers | `#dfe6e9` | `#b2bec3` | | Lakes | `#74b9ff` | `#0984e3` | | Rivers | `#0984e3` | — | | Major roads | `#d63031` | — | | Minor roads | `#e17055` | — | | Nature parks | `#a8e6cf` | `#00b894` | | Municipalities | `#b2bec3` (dashed) | — | | Highlight | `#ffeaa7` | `#fdcb6e` | | Settlements | `#2d3436` | `#fff` | ## Tips - **Latitude correction**: At 65°N, set `ax.set_aspect(1/0.42)` in matplotlib or the map will appear stretched - **WatercourseLine** has 28k features — skip for faster rendering on zoomed maps - **Municipality names** are in the `namn` column of `AdministrativeUnit_level2.geojson` - **Settlement population** is in the `ppl` column of `BuiltupAreaPoints.geojson` - **Road classification**: filter by `rtt` field (1-3 = highways, 4-10 = regional, >10 = local) - For **extra layers** not pre-cached: `uv run python scripts/lmi.py fetch ERM:WetlandArea`
عرض على GitHub