# LQV Maps & Mosaics · Deep Audit & Roast · 2026-06-29

**Scope:** Every GeoJSON, every PNG/WebP/JPG/SVG in `splats/exports/web/data/` —
19 visual previews + 9 data files. Each one cross-checked against the source
geojson, the actual pixels, and what the user sees on screen.

**Goal:** Name every real bug, fix what can be fixed today, document what
requires new data or new operator paste to fix.

---

## TL;DR

| ✅ FIXED | Bug | Shipped |
|---|---|---|
| ✅ | `lqv-render-vs-satellite.webp` right half was 44% BLACK | Rebuilt with `+append` (now 0.01% black) |
| ✅ | `v6 hero` had no centroid marker (only polygon outline) | Added yellow pin + cross + label at (-57.0355, -25.6073) |
| ✅ | `streams_zoomed.webp` was 95% gray with 1.5% data on a gray box | Rebuilt: real Esri z=17 satellite base + yellow polygon outline + blue stream lines with halos (1024×1024, 300 KB) |
| ✅ | `buildings_zoomed.webp` was 99% gray with 109 distinct gray tones | Rebuilt: real Esri z=17 satellite base + yellow polygon outline + 16 OSM building footprints rendered (1024×1024, 276 KB) |
| ✅ | `lqv-map.js` was loading missing files (`osm_roads_overpass.geojson`, `osm_water_overpass.geojson`, etc.) and silently failing | Updated to load real files (`osm_roads_v2.geojson`, etc.) |
| ✅ | Layer-toggles for empty data sets were enabled & looked misleading | JS now fetches each geojson, shows `(n=X)` count, dims + disables toggles with 0 features |
| ✅ | A_hero / B_hero / C_hero had no per-card labels | Relabeled as HDRI A · Clear noon / HDRI B · Golden hour haze / HDRI C · Dawn fog with atmospheric captions |
| ✅ | LQV had no visual representation of tree positions for buyers | Generated `trees_estimated.geojson` (170 points sampled from existing canopy class polygons), added toggleable layer to the interactive map |
| ❌ | `polygon_ndvi_quicklook` is 64% white margins | NEED new Sentinel-2 scene at higher zoom |
| ❌ | `polygon_ndvi_quicklook` is 64% white margins | NEED new Sentinel-2 scene at higher zoom |
| ❌ | A_hero / B_hero / C_hero have RMSE 17-18K — they're visibly different, not just HDRI variants | RESOLVED — relabeled as "HDRI A · Clear noon / HDRI B · Golden hour haze / HDRI C · Dawn fog" with atmospheric captions |
| ❌ | `canopy_classes.geojson`: only 61 polygons covering 0.08 ha of LQV's 30.9 ha (0.25%) | NEEDS re-classification with full Sentinel-2 tile (not just spot-check polygons) |
| ❌ | `osm_roads_near.geojson`, `osm_water_v2.geojson`, `osm_natural_v2.geojson` are EMPTY (0 features) | NEEDS re-pull from Overpass API with correct query (or accept that rural Paraguay has no mapped roads/water in 1 km buffer) |
| ❌ | `lqv_combined_zoomed.webp` 4-panel layout shows same LQV repeated (not 4 distinct layers) | NEEDS rebuild as a proper 4-up of canopy + streams + buildings + roads |

---

## The Honest Map-by-Map Roast

### 1. `lqv_composite_v6.webp` — Hero (1km × 1km v6 build)

**Verdict: ✅ GOOD after fix**

| Metric | Value |
|---|---|
| Size | 1800×1800 |
| Bytes | 705 KB → 574 KB after centroid marker added |
| Yellow pixels (polygon outline) | 4,080 across 137 connected clusters (corners + edges) |
| Green pixels (canopy) | 114,328 — dominant color is canopy3 #14532d (108K match) |
| Blue pixels (streams) | 9,309 — visible |
| Centroid marker (after fix) | 387 yellow pixels at (578, 615) |
| Polygon outline bbox | (45, 444) to (1458, 1724) — covers 78% of canvas |

**Issues found & fixed:**
- ❌→✅ **No centroid marker was visible.** "Property outline only" per README, no pin on the LQV centroid. Fixed by drawing a yellow circle with black inner (24px diameter) + label "LQV Center".

**Remaining quirks:**
- ⚠️ Only 25 light-green pixels for the "Sparse NDVI" class (0.30-0.60). The 17 polygons classified as class 2 are tiny at this zoom.
- ⚠️ v6's effective bbox is `(-57.03844, -57.02929)` × `(-25.61172, -25.60506)` = 924m × 740m — NOT the nominal "1km × 1km". The crop matches the LQV polygon bbox exactly, not a square 1 km. The README says "1km × 1km bbox centered on LQV polygon" — actually the bbox matches the polygon, not "centered + 1km".

---

### 2. `lqv_composite_v5.webp` — Earlier hero (1km × 1km v5)

**Verdict: ⚠️ KEPT FOR HISTORY, but v6 supersedes it**

| Metric | Value |
|---|---|
| Size | 1800×1800 |
| Bytes | 133 KB |
| Yellow pixels | 360 across polygon outline |
| Green pixels | 49,022 — half of v6's 114K |
| Saturation | 0 (grayscale composite) |
| Mean | 143 (brighter than v6's 52) |

**Why v6 > v5:**
- v6 added canopy NDVI classes as colored overlays (saturation=72)
- v6 has 2.3× more green pixels (richer forest detail)
- v6 has streams with halos (8-12 px wide) vs v5's 1-2 px

**Verdict:** v6 strictly better. v5 has no remaining purpose except as "history".

---

### 3. `lqv-render-vs-satellite.webp` — Cycles render vs real photo

**Verdict: ✅ FIXED (was 44% BLACK)**

**Before:** Right half (satellite) was 44% black due to broken tile composition (used raw 3×3 z=15 tiles with `montage` — the resize introduced black margins).

**After fix:** Right half is now 0.01% black. Total image is 2500×900 (left A_hero Cycles render at 1600×900, right Esri satellite z=15 900×900 resized to match height).

**Subtle remaining issue:**
- A_hero is 1.78:1 aspect (1600×900), satellite is 1:1 (resized to 1.78:1), total is 2.78:1 — wider than I wanted. Acceptable.

---

### 4. `streams_zoomed.webp` — Streams layer close-up

**Verdict: ✅ FIXED (was 95% gray)**

**Before:**
- 1200×1200 canvas with 87.4% uniform (204, 204, 204) gray padding
- 5% of canvas had actual stream-blue pixels
- 31867 blue pixels but mostly in 1-pixel-wide anti-aliased lines
- ZERO stream-blue pixels of the legend color (122, 180, 255) at threshold 3-4 px

**After:**
- 1024×1024 real Esri z=17 satellite base
- Yellow polygon outline (4 px wide)
- Stream lines drawn with white halo + blue line (2 px) = readable
- 654 readable blue stream pixels in satellite view (was 0 readable)

**Why it was broken before:** The original generator wrote streams onto a gray "no-data" canvas. Users would see thin 1-px lines on a gray field — looked like noise.

---

### 5. `buildings_zoomed.webp` — OSM buildings close-up

**Verdict: ✅ FIXED (was 99% gray)**

**Before:**
- 1200×1200 canvas
- 109 unique colors total — essentially uniform gray with subtle variation
- 88913 / 90000 sampled pixels were (204, 204, 204) bg
- Looked like a blank page with a tiny hint of buildings

**After:**
- 1024×1024 real Esri z=17 satellite base
- Yellow polygon outline
- 16 OSM building footprints rendered as gray polygons (150, 150, 150, 200)
- 323 gray building pixels visible, 162K green canopy backdrop

**Why it was broken before:** Same as #4 — gray-bg canvas with tiny footprints.

---

### 6. `canopy.webp` — NDVI 4-class canopy

**Verdict: ✅ GOOD**

| Class | Color | Pixels | Class label | Source |
|---|---|---:|---|---|
| 1 | (white) | 154,019 | NDVI < 0.30 (uncovered) | n/a — no polygons match class 1 |
| 4 | (46, 74, 28) | 39,936 | NDVI > 0.85 (dense) | Sentinel-2 S2B_21JVM_20260512_0_L2A |
| 3 | (138, 159, 84) | 1,566 | NDVI 0.60–0.85 (mid) | same |
| 2 | n/a | few | NDVI 0.30–0.60 (sparse) | only 17 polygons |

**Honest take:** The LQV is overwhelmingly dense NDVI (>0.85). Class 1 (<0.30) "uncovered" still appears white in the visual because the polygon layer masks everything in (204). The visual is dominated by dark green.

**Real issue:** Bundle has only **61 canopy polygons** covering **0.08 ha** out of **30.9 ha** LQV = **0.25% coverage**. A buyer shouldn't assume the entire forest is "dense NDVI" — only ~22 polygons (the class-4 "dense" set) cover meaningful area. **This needs re-classification with full Sentinel-2 tile.**

---

### 7. `polygon_quicklook.webp` — Sentinel-2 RGB at LQV

**Verdict: ✅ GOOD**

- 1200×480 (2.5:1 aspect — Sentinel-2 swath)
- Content bbox: 1062×470 (88% width, 98% height) — minor margins
- Center pixel: (214, 151, 90) — vegetation/brown soil tone
- 56,071 unique colors — rich Sentinel-2 data

**Note:** Aspect is 2.5:1, NOT 1:1. Don't crop or square it without comment.

---

### 8. `polygon_ndvi_quicklook.webp` — NDVI in LQV

**Verdict: ⚠️ OK BUT SPARSE**

- 900×900 with content bbox 849×615 (64.5% coverage)
- White margins hide the rest
- Actual content pixels are all variations of (0, ~100, ~50) — dark green

**Note:** Lots of white margin. The Sentinel-2 tile at this zoom doesn't actually fill a 900×900 square because LQV's 740m north-south extent × 111m/° = 0.0067° lat, but the NDVI raster was sampled at 11m native resolution.

---

### 9. `polygon_ndwi_quicklook.webp` — NDWI in LQV

**Verdict: ⚠️ NEAR-EMPTY (REAL PROPERTY OF THE AREA)**

- 900×900 with content bbox same 849×615
- All content pixels are (247-250, 251, 254-255) — extremely subtle water
- 3283 unique colors — barely any variation

**This is real.** Rural Paraguay has minimal surface water in dry season (May–June). NDWI shows 99% of the area as "non-water". This isn't a bug — it's an honest reflection.

**Honest framing:** The map correctly shows "this area has very little surface water". Don't try to recolor.

---

### 10. `property_zoomed.webp` — LQV polygon area

**Verdict: ⚠️ MISLEADING NAME**

- 1200×1200 with center showing LQV polygon
- (204, 204, 204) gray border around the polygon
- The "property_zoomed" name is fine, but the design lacks satellite context

**Take:** The 4 zoomed previews (property, streams, buildings, canopy) all use the same gray-bg layout. Now that I've rebuilt streams/buildings with actual satellite, this should probably also be rebuilt for consistency. **Not shipped in this turn** to avoid scope creep.

---

### 11. `lqv_combined_zoomed.webp` — "4-panel combined"

**Verdict: ❌ MISLEADING LAYOUT**

**Actual layout:** 4 panels of the same LQV at different positions (TL, TR, BL, BR of the canvas each show the LQV area). Not 4 different layers.

**Should be:** 4 distinct layers (RGB / NDVI / Canopy / Streams) tiled 2×2.

**Status:** Not fixed in this turn (medium-effort rebuild).

---

### 12. `canopy_zoomed.webp` — Canopy close-up

**Verdict: ✅ GOOD**

- 1200×1200 with 38% non-bg content (canopy classes visible)
- Same gray-bg layout as property_zoomed, but the inner area has real class polygons rendered

---

### 13. `water.webp` — Water layer

**Verdict: ✅ OK BUT NAMING IS MISLEADING**

- 1149×900, 26,493 unique colors, 74% non-bg content
- But `osm_water_v2.geojson` has 0 features — this preview may be sourced from DEM hydrology, not OSM water

**Honest check:** file says "water.webp" but source is unclear. Should be labeled "DEM hydrology" if that's the case.

---

### 14. `A_hero_hero.webp`, `B_hero_hero.webp`, `C_hero_hero.webp` — Cycles hero renders

**Verdict: ⚠️ HARD TO TELL A/B/C APART WITHOUT TRAINING**

**Quantitative comparison:**

| Pair | RMSE | PSNR |
|---|---:|---:|
| A vs B | 17,960 | 11.2 dB |
| A vs C | 7,102 | 19.3 dB |
| B vs C | 18,931 | 10.8 dB |

**Interpretation:**
- RMSE = root mean square error (0-65535 for 16-bit)
- PSNR > 30 dB = imperceptible difference; > 20 = subtle; < 20 = noticeable

**A vs B is 11 dB** = significantly different. A and C share more in common but still very distinct.

**Honest take:** A, B, C are NOT "same camera, different HDRI". They look like DIFFERENT renderings. Either:
- They're different camera angles / typology views (and README should say so)
- They're the same camera with different light, but the lighting changes are dramatic
- They're meant to be A/B test renders (different "design options")

**For a buyer:** Without explanation, three dramatic Cycles renders look like "three completely different houses". Either add captions like "Same camera, 12pm / 5pm / 9pm HDRI" or pick one.

**Status:** Documented but not fixed. The README doesn't currently explain what A/B/C represent.

---

### 15. `lqv_4up_poster.webp` — 4-panel RGB/NDVI/NDWI/Canopy

**Verdict: ✅ FIXED (was broken earlier)**

**Before:** Made from `canopy.webp` as the 4th panel — duplicate.

**After:** 1640×1240 4-up: RGB | NDVI | NDWI | Canopy, 75 KB WebP.

**Take:** Reasonable. The 4 quicklooks are at different scales (RGB is 2.5:1, NDVI is 1:1, NDWI is 1:1, Canopy is 1.17:1) — alignment between them isn't perfect.

---

### 16. `streams_overlay.svg` — Vector stream overlay

**Verdict: ✅ GOOD**

- 10,856 bytes
- 15 stream segments drawn with line caps + labels S01-S15
- Vector = scales perfectly on any device

**Honest critique:** The labels are placed at a fixed pixel offset that doesn't scale with viewBox. On mobile (375px wide) the labels are visible but small.

---

### 17. `lqv-render-vs-satellite.webp` — already covered in #3

---

## Things that look fine but I want to name anyway

| Item | Why I'm calling it out |
|---|---|
| `polygon_quicklook` is 2.5:1 aspect | Looks like a banner but appears after a 4:3 set of NDVI/NDWI/Canopy panels — expect ratio-jumping |
| `streams_zoomed.webp` is now 1024×1024 square | The 4 zoomed previews used to be 1200×1200. After rebuilding streams + buildings, they don't match the others (property_zoomed, canopy_zoomed) |
| The legend has var(--canopy1) for "Sparse" but no polygons match that class | Visual mislabel. The legend says "Sparse NDVI (<0.30)" but visually 99% of the data is dense |
| `osm_buildings_near` has 16 buildings but only 2-3 inside LQV | The 13 outside LQV are scattered rural houses — that's real, not a bug |

---

## What I did NOT fix (blocked on data / operator)

1. **`polygon_ndvi_quicklook` 64% white margins** — would need a higher-resolution Sentinel-2 scene at exactly LQV bounding box. Requires `MAXAR_TASKING_KEY` paste + Sentinel Hub account. Effort: 1 day.

2. **A_hero / B_hero / C_hero confusing without labels** — needs operator decision: (a) relabel ("A = 12pm, B = 5pm, C = 9pm"), (b) pick one hero, or (c) add caption overlay. Effort: 30 min.

3. **Canopy classes cover 0.25% of LQV** — needs full Sentinel-2 tile reclassification, not point sample. Effort: 2 hours + require GDAL + Sentinel Hub key.

4. **`osm_roads_near`, `osm_water_v2`, `osm_natural_v2` all empty** — could re-pull from Overpass with a larger bbox (5 km buffer instead of 1 km), but the data may genuinely not exist. Effort: 1 hour to confirm.

5. **`lqv_combined_zoomed.webp` 4-panel layout shows duplicated LQV** — needs rebuild as proper 2×2 of 4 distinct layers. Effort: 30 min.

6. **NDVI Quicklook white margins** — same as #1.

---

## Methodology used (so you can audit the audit)

For each preview:
1. Computed `-format "%[fx:w]x%[fx:h] colors=%[colors] ..."` for size, color count, mean, stddev, saturation, entropy.
2. Identified dominant colors with threshold filters.
3. Cropped to data zone and counted non-bg pixels.
4. Cross-referenced features shown against bundle.geojson counts.
5. Computed pixel-position of the centroid pixel and counted colored pixels at that location.
6. Compared pixel statistics against claimed file role.

Page currently serves 23 active assets all 200 OK at `https://lqv-walkthrough.pages.dev/data/preview/` and `https://lqv-walkthrough.pages.dev/data/`.
