- Sur la webapp légère, le rebuild ne voyait que le cache local : la
coquille HTML embarquait un sous-ensemble des tuiles et le premier
chargement n'affichait pas les tuiles récentes du worker — elles
n'arrivaient qu'au sondage /api/tiles suivant (15 s).
- _merge_remote_index() applique au rebuild la même fusion que
/api/tiles (l'index distant prime, le local complète) et réécrit
index_tiles.json ET la liste embarquée dans index.html.
- AGENTS.md : avertissement — le Pi de prod tourne en compose+override
(labels Traefik + /srv/lidar/output), jamais via serve-webapp.sh.
- Le Dockerfile principal (worker, --serve, local-2m) n'avait pas l'étape
de bake : le repli de webapp.py tentait d'écrire webapp_assets/ dans le
paquet installé (dist-packages, propriété de root) et faisait planter
l'import de la webapp sous l'utilisateur lidar.
- Même étape de bake que Dockerfile.webapp, avec cd /tmp pour cibler le
paquet installé (sinon la copie source /app capte l'import via sys.path).
- Le repli de webapp.py ne casse plus l'import si le dossier du paquet
n'est pas inscriptible : réécriture dans un répertoire temporaire.
- Les assets de l'interface étaient écrits dans le volume (output/assets)
et servis d'ici : sur la webapp légère, un app.js périmé restait servi
même après rebuild de l'image.
- app.js/app.css (+ Leaflet vendorisé) sont désormais bâchés dans l'image
au build (Dockerfile.webapp) et servis depuis l'image ; le volume ne
porte que les données (index.html, vignettes, tuiles).
- _write_ui_assets() génère les assets dans un dossier cible ; repli de
régénération au démarrage si non bâchés (dev). build_index continue
d'écrire output/assets/ pour le mode serveur statique.
- Clic sur la carte pour choisir des dalles précises, même sans données
existantes (via /api/cell) ; les zones dessinées s'ajoutent à la
sélection au lieu de la remplacer
- Une demande lancée pendant un run part en file d'attente côté serveur
et démarre à la fin du travail en cours (plus de refus 409), file
vidable depuis l'interface
- Tuiles et interface toujours fraîches : images servies sans cache
navigateur (revalidation 304), rechargement de la carte seulement une
fois le rebuild de l'index terminé
- serve-webapp.sh : sous-commande update retirée, documentation de
déploiement corrigée en conséquence
Au rechargement de la page, l'index obsolète du worker (16 couches)
polluait le /api/tiles fusionné et mergeTilesData réajoutait les couches
retirées au menu. viz_meta est désormais filtré aux couches du panneau
(PANEL_VIZ) côté serveur, et le panneau client est figé au chargement
(clés VIZ_META initiales) : aucun flux ne peut réintroduire de couche
hors panneau, même avec un index distant périmé.
Le bouton ⌖ recentre la carte sur la position GPS du téléphone. L'API
Geolocation exige un contexte sécurisé : la webapp sert désormais du HTTP
et le TLS est porté par le reverse proxy (Traefik, labels dans l'override
local) ; le webapp est transparent au proxy (URLs relatives, X-Forwarded-For
pour la restriction LIDAR_REGEN_CIDR). Ajoute le modèle d'override
docker-compose.webapp.override.yml.example, un rebuild d'index à la demande
et met à jour doc/déploiement ; les tuiles sont servies à la demande.
- POST /api/stop : SIGTERM au pipeline (groupe isolé via start_new_session),
SIGKILL du groupe après 15 s ; forwardé au worker en mode deux machines
- « Régénérer » n'implique plus la reclassification : le DTM en cache est
réutilisé tant que la méthode ne change pas ; nouvelle case « Reclasser le
sol » (--force-classification) et rappel de la classification existante
- Tâche marquée « Interrompu » (returncode négatif ou nul) au lieu d'Échec
Les images (visualisations, vignettes, sous-tuiles) sont rapatriées depuis
la machine de traitement par HTTP au moment où elles sont affichées, puis
servies depuis le disque : une image absente est téléchargée, une image
périmée ( ?v= plus récent que sa mtime, tuile régénérée) est rafraîchie.
/api/tiles fusionne l'index du worker (cache 60 s) avec le cache local, si
bien que les tuiles non cachées apparaissent quand même sur la carte.
Worker hors ligne : disjoncteur 2 min après 3 échecs, index local seul,
/api/status répond running=null — aucune erreur cliente.
- URLs images versionnées (?v=mtime) : une tuile recalculée change d'URL et
force le rechargement navigateur (cache heuristique contourné), y compris
en plein run via /api/tiles ; veille permanente 15 s sur la carte
- simulation locale du mode deux machines (docker-compose.local-2m.yml) :
worker GPU :8974 + webapp légère :8973 au cache séparé output-webapp/
- override webapp pour le Pi 5 (192.168.3.3) : volume /srv/lidar/output,
rsync vers le worker, labels Traefik (proxy/websecure/myresolver)
- purge 0,5 m : worker/process et politique générale passés à 0,2 m seul
- intègre le travail parallèle non commité : export mosaïque multi-dalles
(export.py + /api/export), sous-tuilage intégral des couches, légendes
VIZ_LEGENDS, docs et tests associés (213 tests verts)
index.py rewritten as a continuous Leaflet map: rotated L93 tiles, stackable
visualization layers (per-layer opacity, drag-reorder persisted in
localStorage), tile info panel, live rebuild after each tile during a run.
Leaflet is vendored in assets/vendor/ so the map works fully offline;
georeferencing falls back rasterio -> pyproj -> affine so the lightweight
webapp (no GDAL) is supported.
docker-compose.worker.yml adds the tile generator service (full image + GPU)
that remote webapps call via LIDAR_GENERATION_URL, plus a one-shot process
profile. webapp.py gains LIDAR_AUTO_SYNC_SECONDS periodic cache refresh and
LIDAR_REGEN_CIDR restricting generation to the local network. run.sh
--serve-webapp now mounts ~/.ssh read-only so the rsync sync works.
docs/DEPLOY_WEBAPP.md completed for Raspberry Pi deployment: prerequisites,
git clone install, SSH key setup, first sync, update procedure and
troubleshooting.
La webapp (carte + vignettes) et la génération de tuiles se déploient sur
deux machines : image légère Dockerfile.webapp (FastAPI + Pillow AVIF
natif + pyproj) sur Raspberry Pi, pipeline complet sur la machine de
traitement. LIDAR_GENERATION_URL délègue /api/generate, /api/preview et
/api/status ; /api/sync ramène les tuiles par rsync puis régénère
vignettes et index localement. Token partagé optionnel
(LIDAR_API_TOKEN/LIDAR_REMOTE_TOKEN). Retire du dépôt les journaux
internes (.swival, audit-findings) et les données (data/, notebooks/).
Doc : docs/DEPLOY_WEBAPP.md.
- Web map: multi-select picker in the generation bar (aspect, slope,
positive openness, anisotropic openness, wavelet) passed to the API;
the layer panel is restricted to the same shortlist (PANEL_VIZ) and
a refresh button rebuilds the index when new layers appear on disk;
jobs started outside the UI are now adopted into the visible queue
- Uniform colors across tiles: openness/anisotropic/sailore now store
local z-scores, and all renderers use fixed ranges (0-3 sigma, SVF
0-1 physical, slope 0-30 deg) instead of per-tile percentile stretches
- Ray-tracing falls back to CPU when VRAM is exhausted so openness and
SVF no longer fail silently on shared GPUs
- build_index merges visualizations available at only one resolution
into the displayed tile so in-progress layers stay visible
- 11 new tests (142 passing)
- webapp.py: FastAPI serving the continuous map (port 8973) with
/api/preview, /api/generate and /api/status; tiles are downloaded
from IGN and processed in a logged subprocess, tracked live in a
side "File de génération" panel that survives page reloads
- fetch_ign.py: download missing 1 km LiDAR HD tiles from the IGN
geoplateforme before processing
- index.py: tile thumbnails and 500 m subtiles are now invalidated by
mtime so regenerating a tile refreshes its cached images; progress
logging per tile
- dtm.py: back to the historical gap handling (small gaps filled by
fillnodata only, larger holes left as nodata rendered black);
lowest-return floor only via --bare-earth, IGN class selection via
--ign-classes
- cli.py: positional input now optional (--rebuild-index works alone)
- docker-compose.yml: serve (GPU, port 8973) and process services;
launch via docker compose only (documented in AGENTS.md/AGENTS.md)
- tests: 131 passing, incl. regressions for thumbnail staleness,
--rebuild-index without input, and nodata rendering