Moved webapp to top level.

This commit is contained in:
Felix Delattre 2026-06-10 15:33:03 +02:00
parent 17f2d1d659
commit 5389776c8a
4 changed files with 7 additions and 7 deletions

View file

@ -14,7 +14,7 @@ Worldwide PhenoCam EFAST feasibility screening. Human summary: [`README.md`](REA
| `4-fusion.py` | Step 4: GCC computation + EFAST BtI/ItB fusion loop | | `4-fusion.py` | Step 4: GCC computation + EFAST BtI/ItB fusion loop |
| `5-metrics.py` | Step 5: timeseries, covariates, `metrics.json`, webapp manifest | | `5-metrics.py` | Step 5: timeseries, covariates, `metrics.json`, webapp manifest |
| `data/` | Manifests, per-site caches, screening outputs (large; mostly generated) | | `data/` | Manifests, per-site caches, screening outputs (large; mostly generated) |
| `webapp/` | Static QA viewer (`make serve` from workspace root) | | `index.html`, `common.js` | Static QA viewer (`make serve` from workspace root) |
Workspace orchestration: [`../AGENTS.md`](../AGENTS.md). Workspace orchestration: [`../AGENTS.md`](../AGENTS.md).
@ -29,7 +29,7 @@ Workspace orchestration: [`../AGENTS.md`](../AGENTS.md).
| S2/S3 download + EFAST prep | `3-sentinel-data.py` | | S2/S3 download + EFAST prep | `3-sentinel-data.py` |
| GCC + fusion | `4-fusion.py` | | GCC + fusion | `4-fusion.py` |
| Metrics + webapp index | `5-metrics.py` | | Metrics + webapp index | `5-metrics.py` |
| Web QA | `../Makefile` target `serve``webapp/index.html` | | Web QA | `../Makefile` target `serve``index.html` |
--- ---

View file

@ -54,4 +54,4 @@ The 2025 manifest currently lists **739** cameras with archive overlap; most per
## Web viewer ## Web viewer
From the workspace root, `make serve` serves `processing/` at [http://localhost:8000/webapp/index.html](http://localhost:8000/webapp/index.html). Requires step 5 (`data/metrics/manifest.json`). From the workspace root, `make serve` serves `processing/` at [http://localhost:8000/index.html](http://localhost:8000/index.html). Requires step 5 (`data/metrics/manifest.json`).

View file

@ -358,7 +358,7 @@ async function fetchJson(url) {
} }
async function loadMetrics(year, site) { async function loadMetrics(year, site) {
const base = `../data/metrics/${year}/${site}`; const base = `data/metrics/${year}/${site}`;
const [tsEntries, rasterEntries, metricsData, covariatesData] = await Promise.all([ const [tsEntries, rasterEntries, metricsData, covariatesData] = await Promise.all([
Promise.all(Object.entries(TS_FILES).map(async ([k, f]) => [k, await fetchJson(`${base}/${f}`)])), Promise.all(Object.entries(TS_FILES).map(async ([k, f]) => [k, await fetchJson(`${base}/${f}`)])),
Promise.all(Object.entries(RASTER_FILES).map(async ([k, f]) => [k, await fetchJson(`${base}/${f}`)])), Promise.all(Object.entries(RASTER_FILES).map(async ([k, f]) => [k, await fetchJson(`${base}/${f}`)])),
@ -443,7 +443,7 @@ function renderSitePanel(meta, cov) {
// ── init ── // ── init ──
async function init() { async function init() {
try { try {
manifest = await fetch("../data/metrics/manifest.json").then(r => r.json()); manifest = await fetch("data/metrics/manifest.json").then(r => r.json());
} catch { } catch {
qs("#empty").textContent = "manifest.json not found — run 5-metrics.py first."; qs("#empty").textContent = "manifest.json not found — run 5-metrics.py first.";
return; return;
@ -534,7 +534,7 @@ async function selectSite(site) {
renderSitePanel(meta, loaded.covariates); renderSitePanel(meta, loaded.covariates);
renderInspector(loaded.ts); renderInspector(loaded.ts);
} else { } else {
ts = await loadCsvTs(`../data/phenocam/${currentYear}/${site}_1day.csv`); ts = await loadCsvTs(`data/phenocam/${currentYear}/${site}_1day.csv`);
qs("#metricsSection").style.display = "none"; qs("#metricsSection").style.display = "none";
renderInspector(null); renderInspector(null);
} }
@ -743,7 +743,7 @@ async function loadOverlay(id, item, dateEl) {
if (!item || !maps3[id]) return; if (!item || !maps3[id]) return;
dateEl.textContent = fmtDate8(item.date); dateEl.textContent = fmtDate8(item.date);
try { try {
const buf = await fetch(`../${item.path}`).then(r => r.arrayBuffer()); const buf = await fetch(item.path).then(r => r.arrayBuffer());
const { dataUrl, bbox, crsCode } = await geotiffToCanvasDataUrl(buf); const { dataUrl, bbox, crsCode } = await geotiffToCanvasDataUrl(buf);
let bounds; let bounds;
if (crsCode === "EPSG:4326") { if (crsCode === "EPSG:4326") {