Improved debug output.

This commit is contained in:
Felix Delattre 2026-06-11 17:58:40 +02:00
parent 12578dd1f2
commit 6b7395b617
2 changed files with 17 additions and 11 deletions

View file

@ -82,6 +82,14 @@ PHENOCAM_IMAGE_URL = (
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def _window_mean(data: np.ndarray) -> float | None:
"""Mean of a pixel window; ``None`` when every value is NaN."""
valid = data[~np.isnan(data)]
if valid.size == 0:
return None
return float(np.mean(valid))
def _read_center_pixel(path: Path, lat: float, lon: float) -> float | None: def _read_center_pixel(path: Path, lat: float, lon: float) -> float | None:
"""Return the 3×3 mean GCC value at (lat, lon) from a single-band raster. """Return the 3×3 mean GCC value at (lat, lon) from a single-band raster.
@ -103,9 +111,7 @@ def _read_center_pixel(path: Path, lat: float, lon: float) -> float | None:
if nodata is not None: if nodata is not None:
data = np.where(data == nodata, np.nan, data) data = np.where(data == nodata, np.nan, data)
data[data == 0] = np.nan data[data == 0] = np.nan
with np.errstate(all="ignore"): return _window_mean(data)
val = np.nanmean(data)
return None if np.isnan(val) else float(val)
except Exception: except Exception:
return None return None
@ -334,9 +340,8 @@ def _read_multiband_center(
if nodata is not None: if nodata is not None:
data = np.where(data == nodata, np.nan, data) data = np.where(data == nodata, np.nan, data)
data[data == 0] = np.nan data[data == 0] = np.nan
with np.errstate(all="ignore"): val = _window_mean(data)
val = np.nanmean(data) result[name] = None if val is None else round(val, 6)
result[name] = None if np.isnan(val) else round(float(val), 6)
return result return result
except Exception: except Exception:
return {name: None for name in band_names} return {name: None for name in band_names}

View file

@ -1,9 +1,11 @@
"""Pipeline wrapper: run steps 1 → 2 → 3 → 4 → 5. """Pipeline wrapper: run steps 1 → 2 → 3 → 4 → 5.
Steps 1 and 2 run once for the whole year (skipped when their output already Steps 1 and 2 run once for the whole year (skipped when their output already
exists). Steps 35 run site-by-site for every PASS site from exists). Steps 3 and 4 run site-by-site for every PASS site from
``data/phenocam_screening/{year}.json``; a site is skipped entirely when ``data/phenocam_screening/{year}.json``; a site is skipped when
``data/metrics/{year}/{site}/metrics.json`` already exists. ``data/metrics/{year}/{site}/metrics.json`` already exists. Step 5 always
runs once at the end without ``--site`` so that ``manifest.json`` is written
with all processed sites (not just the last one).
Any failure stops the run immediately. Fix the issue and re-run completed Any failure stops the run immediately. Fix the issue and re-run completed
steps and sites are skipped automatically. steps and sites are skipped automatically.
@ -11,7 +13,7 @@ steps and sites are skipped automatically.
CLI: CLI:
- ``--evaluation-year`` (default 2025) - ``--evaluation-year`` (default 2025)
- ``--site`` single site to run steps 35 for (default: all PASS sites) - ``--site`` single site to run steps 34 for (default: all PASS sites)
""" """
from __future__ import annotations from __future__ import annotations
@ -36,7 +38,6 @@ GLOBAL_STEPS: list[tuple[str, Path]] = [
PER_SITE_STEPS = [ PER_SITE_STEPS = [
"3-sentinel-data.py", "3-sentinel-data.py",
"4-fusion.py", "4-fusion.py",
"5-metrics.py",
] ]