Masquer le nodata avant étalonnage colormap et colorbar en unités réelles

This commit is contained in:
Antoine Jacquin
2026-09-18 21:05:55 +02:00
parent 3c19dc4226
commit 476f246fe7

View File

@ -189,7 +189,8 @@ for _key, _info in RGB_LEGENDS.items():
def _apply_colormap(data, tif_file, resolution=None):
"""Apply the registered colormap normalization to data based on filename.
Returns (data, cmap, title, legend_label, description, is_rgb).
Returns (data, cmap, title, legend_label, description, is_rgb, vmin, vmax)
où vmin/vmax sont les bornes physiques de la plage rendue (None si sans objet).
"""
name = str(tif_file).lower()
@ -197,7 +198,7 @@ def _apply_colormap(data, tif_file, resolution=None):
for key in RGB_LEGENDS:
if key in name:
info = RGB_LEGENDS[key]
return data, None, info['title'], info['legend'], info['description'], True
return data, None, info['title'], info['legend'], info['description'], True, None, None
# Find matching colormap — sort by key length descending so 'mslrm' matches before 'lrm'
for key in sorted(COLORMAPS.keys(), key=len, reverse=True):
@ -208,7 +209,7 @@ def _apply_colormap(data, tif_file, resolution=None):
if len(valid_data) == 0:
logger.warning(f" Aucune donnée valide pour {Path(tif_file).name} — colormap ignorée")
return data, 'terrain', Path(tif_file).stem.replace('_', ' ').title(), '', '', False
return data, 'terrain', Path(tif_file).stem.replace('_', ' ').title(), '', '', False, None, None
vmin = vmax = None
@ -253,7 +254,7 @@ def _apply_colormap(data, tif_file, resolution=None):
data = np.clip((data - vmin) / max(vmax - vmin, 0.001), 0, 1)
legend = info['legend'].format(vmin=vmin or 0, vmax=vmax or 0)
return data, info['cmap'], info['title'], legend, info['description'], False
return data, info['cmap'], info['title'], legend, info['description'], False, vmin, vmax
# Default: terrain colormap with percentile stretch
valid_data = np.asarray(data.compressed() if hasattr(data, 'compressed') else data.flatten())
@ -265,7 +266,7 @@ def _apply_colormap(data, tif_file, resolution=None):
span = max(p98 - p2, 1e-6)
data = np.clip((data - p2) / span, 0, 1)
title = Path(tif_file).stem.replace('_', ' ').title()
return data, 'terrain', title, 'Altitude normalisée', '', False
return data, 'terrain', title, 'Altitude normalisée', '', False, p2, p98
def _download_location_map(min_x, max_x, min_y, max_y):
@ -453,7 +454,7 @@ def tif_to_png(tif_file, vis_dir, resolution, keep_tif=False, source_info=None,
nan_mask = nan_mask # keep for later
# Apply colormap
data, cmap, title, legend_label, description, is_rgb_result = _apply_colormap(data, tif_file, resolution=resolution)
data, cmap, title, legend_label, description, is_rgb_result, cmap_vmin, cmap_vmax = _apply_colormap(data, tif_file, resolution=resolution)
# Apply NaN mask: make zones without data transparent
has_nan_mask = nan_mask is not None and not is_rgb_result
@ -461,6 +462,10 @@ def tif_to_png(tif_file, vis_dir, resolution, keep_tif=False, source_info=None,
# data is normalized 0-1 from _apply_colormap; apply cmap to get RGBA
# Save the colormap for colorbar before converting to RGBA
saved_cmap = plt.get_cmap(cmap) if isinstance(cmap, str) else cmap
# Bornes physiques de la colorbar (unités réelles, pas 0-1)
if cmap_vmin is not None and cmap_vmax is not None:
saved_vmin, saved_vmax = float(cmap_vmin), float(cmap_vmax)
else:
saved_vmin = float(np.nanmin(data)) if not nan_mask.all() else 0
saved_vmax = float(np.nanmax(data)) if not nan_mask.all() else 1
rgba = saved_cmap(data) # (H, W, 4) float RGBA
@ -806,9 +811,14 @@ def tif_to_crop(tif_file, vis_dir, resolution, keep_tif=False, quality=98, outpu
data = np.moveaxis(data, 0, -1)
else:
data = src.read(1)
# Nodata → NaN : sinon les pixels bord (ex. -9999, 3.4e38)
# polluent les percentiles d'étalonnage de la colormap
if src.nodata is not None:
data = data.astype(np.float32, copy=False)
data[data == src.nodata] = np.nan
# Apply colormap normalization
data, cmap_name, title, legend_label, description, is_rgb_result = _apply_colormap(data, tif_file, resolution=resolution)
data, cmap_name, title, legend_label, description, is_rgb_result, _cvmin, _cvmax = _apply_colormap(data, tif_file, resolution=resolution)
if not is_rgb_result:
data = np.where(np.isnan(data), 0.0, data)