Diffuser la qualité des dalles dans l'inventaire et la conserver sur la carte légère
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -1220,11 +1220,15 @@ def build_index(output_dir, output_format='avif'):
|
||||
for k in _VIZ_FALLBACK_ORDER if k in all_viz_keys}
|
||||
for k in sorted(all_viz_keys):
|
||||
viz_meta.setdefault(k, {'label': VIZ_LABELS.get(k, k)})
|
||||
from .quality import load_quality_table
|
||||
inventory_path = output_dir / 'index_tiles.json'
|
||||
inventory_path.write_text(json.dumps({
|
||||
'tiles': display_tiles,
|
||||
'viz_meta': viz_meta,
|
||||
'stats': {'n_tiles': len(display_tiles)},
|
||||
# Qualité par dalle (encart de l'export PDF) : recopiée sur les
|
||||
# machines légères pour rester disponible amont éteint.
|
||||
'quality': load_quality_table(output_dir),
|
||||
}, ensure_ascii=False), encoding='utf-8')
|
||||
|
||||
logger.info(f"Inventaire généré : {inventory_path} "
|
||||
|
||||
@ -653,3 +653,15 @@ def test_urls_versioned_by_served_file_mtime(tmp_path):
|
||||
url_after = tiles05b[0]['viz']['hillshade_multi']['thumb']
|
||||
assert url_after.split('?')[0] == url_before.split('?')[0]
|
||||
assert url_after != url_before
|
||||
|
||||
|
||||
def test_inventory_contains_quality_table(tmp_path):
|
||||
import json
|
||||
from lidar_pipeline.index import build_index
|
||||
from lidar_pipeline.quality import write_quality
|
||||
from lidar_pipeline.tests.test_tiles import _make_dalle
|
||||
base = _make_dalle(tmp_path, 1054, 6882, ["relief_oriente"])
|
||||
write_quality(tmp_path, base, {"version": 1, "ground_density": 7.5})
|
||||
build_index(tmp_path, "webp")
|
||||
inv = json.loads((tmp_path / "index_tiles.json").read_text(encoding="utf-8"))
|
||||
assert inv["quality"] == {base: {"version": 1, "ground_density": 7.5}}
|
||||
|
||||
@ -712,3 +712,20 @@ def test_webp_subtiles_indexed_and_rendered_nearest(tmp_path):
|
||||
assert img is not None
|
||||
grays = {p[0] for p in img.getdata() if p[3] == 255}
|
||||
assert grays <= {0, 255} # aucun gris intermédiaire inventé
|
||||
|
||||
|
||||
def test_remote_quality_persisted_locally(tmp_path, monkeypatch):
|
||||
"""La table qualité amont est recopiée en sidecars locaux (Pi autonome)."""
|
||||
from lidar_pipeline import tiles
|
||||
from lidar_pipeline.quality import read_quality
|
||||
payload = _remote_payload()
|
||||
base = "LHD_FXX_1054_6882_PTS_LAMB93_IGN69"
|
||||
payload["quality"] = {base: {"version": 1, "ground_density": 3.0},
|
||||
"../evasion": {"version": 1}}
|
||||
monkeypatch.setattr(tiles, "REMOTE_SOURCE_URL", "http://amont")
|
||||
monkeypatch.setattr(tiles, "_remote_payload", lambda force=False: payload)
|
||||
monkeypatch.setattr(tiles, "_remote_cache", dict(tiles._remote_cache, index=None, built=None))
|
||||
tiles._remote_index(tmp_path, force=True)
|
||||
assert read_quality(tmp_path, base) == {"version": 1, "ground_density": 3.0}
|
||||
assert not (tmp_path / "evasion.json").exists()
|
||||
assert list((tmp_path / "quality").iterdir()) == [tmp_path / "quality" / f"{base}.json"]
|
||||
|
||||
@ -305,6 +305,30 @@ def _remote_payload(force=False):
|
||||
return payload
|
||||
|
||||
|
||||
_SAFE_BASENAME = re.compile(r"^[A-Za-z0-9_.-]+$")
|
||||
|
||||
|
||||
def _persist_remote_quality(output_dir, payload):
|
||||
"""Recopie la table qualité amont en sidecars locaux.
|
||||
|
||||
L'encart qualité de l'export PDF lit toujours le disque local : la
|
||||
carte autonome (amont éteint) garde ainsi les dernières valeurs connues.
|
||||
Returns: nombre de sidecars (ré)écrits.
|
||||
"""
|
||||
from .quality import QUALITY_VERSION, write_quality
|
||||
written = 0
|
||||
for base, data in (payload.get("quality") or {}).items():
|
||||
if (not isinstance(base, str) or not _SAFE_BASENAME.match(base)
|
||||
or base.startswith(".") or not isinstance(data, dict)
|
||||
or data.get("version") != QUALITY_VERSION):
|
||||
continue
|
||||
try:
|
||||
written += bool(write_quality(output_dir, base, data))
|
||||
except OSError as e:
|
||||
logger.debug(f"Sidecar qualité non recopié ({base}) : {e}")
|
||||
return written
|
||||
|
||||
|
||||
def _remote_index(output_dir, force=False):
|
||||
"""Inventaire construit depuis l'amont : sources non encore rapatriées.
|
||||
|
||||
@ -320,6 +344,7 @@ def _remote_index(output_dir, force=False):
|
||||
and _remote_cache.get("built") is payload):
|
||||
return _remote_cache["index"]
|
||||
output_dir = Path(output_dir)
|
||||
_persist_remote_quality(output_dir, payload)
|
||||
layers = {}
|
||||
for entry in payload["tiles"]:
|
||||
col, row = entry.get("col"), entry.get("row")
|
||||
|
||||
Reference in New Issue
Block a user