Translate the whole project to English and fix outdated comments and help

Comments, docstrings, logs, CLI help, map UI, legends, PDF sheet, scripts,
compose files and AGENTS.md are now English. Data keys stay unchanged
(relief_oriente, densite_sol, visualisations/, API JSON keys, link params).
Wrong comments and help defaults found along the way are corrected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Antoine
2026-09-27 23:16:45 +02:00
parent cc1c22d2b8
commit fb892ea9f2
52 changed files with 4356 additions and 4323 deletions

View File

@ -94,7 +94,7 @@ def test_to_gpu_roundtrip():
# ---------------------------------------------------------------------------
# bin_mean_2d — rasterisation MNT (moyenne z par cellule)
# bin_mean_2d — DTM rasterization (mean z per cell)
# ---------------------------------------------------------------------------
def _scipy_reference(xs, ys, zs, width, height, x_range, y_range):
@ -107,7 +107,7 @@ def _scipy_reference(xs, ys, zs, width, height, x_range, y_range):
def test_bin_mean_core_parity_scipy():
"""Le cœur numpy de bin_mean_2d reproduit binned_statistic_2d (mean)."""
"""The numpy core of bin_mean_2d reproduces binned_statistic_2d (mean)."""
from lidar_pipeline.gpu import _bin_mean_core
rng = np.random.default_rng(42)
x_range, y_range = (1000.0, 1010.0), (6800.0, 6808.0)
@ -116,9 +116,9 @@ def test_bin_mean_core_parity_scipy():
xs = rng.uniform(*x_range, n)
ys = rng.uniform(*y_range, n)
zs = rng.uniform(50.0, 150.0, n)
# Cas limites : bord gauche/bas (inclus), bord droit/haut (inclus dans la
# dernière cellule), hors emprise (ignorés), points exactement sur une
# arête intérieure
# Edge cases: left/bottom edge (included), right/top edge (included in the
# last cell), outside the extent (ignored), points exactly on an interior
# cell boundary
xs = np.concatenate([xs, [1000.0, 1010.0, 999.9, 1010.1, 1002.5]])
ys = np.concatenate([ys, [6800.0, 6808.0, 6808.1, 6807.9, 6804.0]])
zs = np.concatenate([zs, [99.0, 101.0, 777.0, 777.0, 103.0]])
@ -129,25 +129,25 @@ def test_bin_mean_core_parity_scipy():
def test_bin_mean_core_empty_and_single():
"""Cellules vides → NaN ; un seul point → sa valeur partout où présent."""
"""Empty cells → NaN; a single point → its value in its own cell."""
from lidar_pipeline.gpu import _bin_mean_core
x_range, y_range = (0.0, 10.0), (0.0, 10.0)
# Aucun point dans l'emprise
# No point inside the extent
out = _bin_mean_core(np, [-5.0], [-5.0], [1.0], 5, 5, x_range, y_range)
assert out.shape == (5, 5)
assert np.isnan(out).all()
# Un point au centre exact : cellule (2, 2)
# One point exactly at the center: cell (2, 2)
out = _bin_mean_core(np, [5.0], [5.0], [7.5], 5, 5, x_range, y_range)
assert out[2, 2] == 7.5
assert np.isnan(out).sum() == 24
# Cellule avec plusieurs points : moyenne exacte
# Cell with several points: exact mean
out = _bin_mean_core(np, [5.0, 5.1, 5.2], [5.0, 5.0, 5.0],
[10.0, 20.0, 30.0], 5, 5, x_range, y_range)
assert out[2, 2] == 20.0
def test_bin_mean_2d_gpu_or_none():
"""bin_mean_2d : None sans GPU, sinon sortie identique au cœur numpy."""
"""bin_mean_2d: None without a GPU, otherwise output identical to the numpy core."""
from lidar_pipeline.gpu import bin_mean_2d, _bin_mean_core
rng = np.random.default_rng(7)
x_range, y_range = (1000.0, 1200.0), (6800.0, 7000.0)
@ -159,24 +159,24 @@ def test_bin_mean_2d_gpu_or_none():
got = bin_mean_2d(xs, ys, zs, w, h, x_range, y_range)
ref = _bin_mean_core(np, xs, ys, zs, w, h, x_range, y_range)
if got is None:
assert isinstance(ref, np.ndarray) # repli scipy assuré par l'appelant
assert isinstance(ref, np.ndarray) # the caller provides the scipy fallback
else:
assert isinstance(got, np.ndarray)
np.testing.assert_allclose(got, ref, equal_nan=True, rtol=1e-9)
def test_safe_gpu_call_retries_on_cpu_for_any_error(monkeypatch):
"""GPU actif : TOUTE erreur (pas seulement les messages CUDA) désactive
le GPU et retranche le calcul en CPU.
"""GPU active: ANY error (not only CUDA messages) disables the GPU and
retries the computation on CPU.
Cas réel : après un échec de transfert GPU, des types numpy/cupy mêlés
(« Unsupported type <class 'numpy.ndarray'> ») ne contenaient aucun
mot-clé CUDA et propageaient l'erreur — la visualisation entière
échouait alors pour rien.
Real case: after a GPU transfer failure, mixed numpy/cupy types
("Unsupported type <class 'numpy.ndarray'>") contained no CUDA keyword
and propagated the error — the whole visualization then failed for
nothing.
"""
from lidar_pipeline import gpu
class _FakeCP: # GPU « actif » sans CuPy
class _FakeCP: # "active" GPU without CuPy
pass
monkeypatch.setattr(gpu, "_cp", _FakeCP())
@ -190,23 +190,23 @@ def test_safe_gpu_call_retries_on_cpu_for_any_error(monkeypatch):
return x + 1
assert gpu.safe_gpu_call(f, 21) == 22
assert gpu.HAS_GPU is False # GPU désactivé après l'erreur
assert gpu.HAS_GPU is False # GPU disabled after the error
assert gpu._cp is None
# Mode CPU : l'erreur se relance telle quelle (rien à retrancher)
# CPU mode: the error is re-raised as is (nothing to retry)
def g(x):
raise ValueError("boom")
try:
gpu.safe_gpu_call(g, 1)
raise AssertionError("devait relancer l'erreur")
raise AssertionError("should have re-raised the error")
except ValueError:
pass
def test_gpu_worker_slots_bounded_by_free_vram(monkeypatch):
"""Places GPU par la VRAM libre : l'excédent de workers passe en CPU.
"""GPU slots bounded by free VRAM: surplus workers run on CPU.
Cas réel : LIDAR_WORKERS=auto = 12 workers sur 2 RTX 5060 (8 Go) —
6 workers par GPU, soit bien plus que la VRAM libre ne tient au pic
(calage des lignes + comblement GPU) : OOM.
Real case: LIDAR_WORKERS=auto = 12 workers on 2 RTX 5060 (8 GB) —
6 workers per GPU, far more than free VRAM holds at peak (scan-line
alignment + GPU gap filling): OOM.
"""
from lidar_pipeline import gpu
monkeypatch.setattr(gpu, "GPU_WORKER_MIB", 2000)
@ -216,24 +216,24 @@ def test_gpu_worker_slots_bounded_by_free_vram(monkeypatch):
assert len(slots) == 12
assert slots.count(0) == 3 # (7500 - 500) // 2000
assert slots.count(1) == 2 # (4600 - 500) // 2000
assert slots.count(-1) == 7 # reste en CPU
# GPU d'abord, entrelacés : les premiers workers créés se répartissent
assert slots.count(-1) == 7 # the rest on CPU
# GPUs first, interleaved: the first workers created are spread out
assert slots[:4] == [0, 1, 0, 1]
# Moins de workers que de places : aucun CPU forcé
# Fewer workers than slots: no forced CPU
assert gpu.gpu_worker_slots([0, 1], 3, free_mib=free) == [0, 1, 0]
def test_gpu_worker_slots_without_gpu_or_vram_info():
"""Sans GPU : tout en CPU implicite (None). VRAM inconnue : round-robin
historique (pas de bornage sans mesure)."""
"""No GPU: implicit CPU everywhere (None). Unknown VRAM: legacy
round-robin (no bound without a measurement)."""
from lidar_pipeline import gpu
assert gpu.gpu_worker_slots([], 4, free_mib={}) == [None] * 4
assert gpu.gpu_worker_slots([0, 1], 4, free_mib={}) == [0, 1, 0, 1]
def test_gpu_worker_slots_keeps_one_gpu_worker_when_tight(monkeypatch):
"""GPU presque plein : au moins une place pour que le GPU serve encore
(le repli CPU de safe_gpu_call couvre l'OOM éventuel)."""
"""Nearly full GPU: at least one slot so the GPU is still used
(safe_gpu_call's CPU fallback covers a possible OOM)."""
from lidar_pipeline import gpu
monkeypatch.setattr(gpu, "GPU_WORKER_MIB", 2000)
monkeypatch.setattr(gpu, "GPU_RESERVE_MIB", 500)
@ -241,7 +241,7 @@ def test_gpu_worker_slots_keeps_one_gpu_worker_when_tight(monkeypatch):
def test_force_cpu_disables_gpu_selection(monkeypatch):
"""force_cpu() : aucun candidat GPU, CuPy jamais initialisé."""
"""force_cpu(): no GPU candidate, CuPy never initialized."""
import os
from lidar_pipeline import gpu
monkeypatch.setattr(gpu, "_restricted_gpu_ids", None)