Fix bugs and improve pipeline flexibility
- Fix gpu_cleanup import missing in visualizations.py (NameError in workers) - Fix t_pdf referenced before assignment when PDF is skipped - Skip classification+DTM when DTM exists regardless of --force - --force now only regenerates WebP/PDF, not classification/DTM - --force-classification forces reclassification when needed - Add laspy repair fallback for corrupt LAZ files (EVLR errors) - Keep DTM TIF by default for reuse (--no-keep-tif to delete) - Increase space between image and bottom cartouche (0.12→0.19) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -246,10 +246,57 @@ def classify_ground(laz_file, temp_dir, method='auto', force=False):
|
||||
logger.info(f" ✓ Classification sol {method.upper()} terminée")
|
||||
return output_las
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f" ✗ Erreur classification PDAL ({method.upper()}): {e.stderr.decode()}")
|
||||
error_msg = e.stderr.decode() if e.stderr else str(e)
|
||||
logger.warning(f" ✗ Erreur classification PDAL ({method.upper()}): {error_msg}")
|
||||
|
||||
# Try repairing file with laspy if PDAL fails on EVLR/VLR
|
||||
if 'VLR' in error_msg or 'Invalid' in error_msg:
|
||||
logger.info(f" → Tentative de réparation du fichier avec laspy...")
|
||||
repaired_las = temp_dir / f"{laz_base}_repaired.las"
|
||||
if _repair_laz_with_laspy(laz_file, repaired_las):
|
||||
# Retry PDAL pipeline with repaired file
|
||||
pipeline_json = _create_ground_pipeline(repaired_las, output_las, method)
|
||||
with open(pipeline_file, 'w') as f:
|
||||
f.write(pipeline_json)
|
||||
try:
|
||||
subprocess.run(
|
||||
["pdal", "pipeline", str(pipeline_file)],
|
||||
capture_output=True, check=True
|
||||
)
|
||||
logger.info(f" ✓ Classification sol {method.upper()} terminée (fichier réparé)")
|
||||
return output_las
|
||||
except subprocess.CalledProcessError as e2:
|
||||
error_msg2 = e2.stderr.decode() if e2.stderr else str(e2)
|
||||
logger.error(f" ✗ Échec classification même après réparation: {error_msg2}")
|
||||
else:
|
||||
logger.error(f" ✗ Impossible de réparer le fichier")
|
||||
return None
|
||||
|
||||
|
||||
def _repair_laz_with_laspy(input_laz, output_las):
|
||||
"""Try to repair a corrupt LAZ file by re-reading with laspy and saving as LAS.
|
||||
|
||||
Works around PDAL errors like 'Invalid Extended VLR size' by stripping
|
||||
problematic VLR/EVLR metadata during re-save.
|
||||
|
||||
Args:
|
||||
input_laz: Path to corrupt LAZ/LAS file.
|
||||
output_las: Path for repaired LAS output.
|
||||
|
||||
Returns:
|
||||
True if repair succeeded, False otherwise.
|
||||
"""
|
||||
import laspy
|
||||
try:
|
||||
las = laspy.read(str(input_laz))
|
||||
las.write(str(output_las))
|
||||
logger.info(f" ✓ Fichier réparé via laspy ({len(las.points):,} points)")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f" ✗ Réparation laspy échouée: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def create_dtm_fast(las_file, basename, dtm_dir, resolution, force=False):
|
||||
"""Create DTM using fast binning method with gap filling.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user