Diagnostics Module

Diagnostic plotting utilities for debugging terrain processing.

This module provides visualization functions to understand and debug terrain transforms, particularly wavelet denoising, slope-adaptive smoothing, bump removal, road elevation, and upscaling operations.

All functions generate multi-panel matplotlib figures saved to disk.

Wavelet Denoising Diagnostics

src.terrain.diagnostics.plot_wavelet_diagnostics(original, denoised, output_path, title_prefix='Wavelet Denoising', nodata_value=nan, profile_row=None, cmap='terrain')[source]

Generate diagnostic plots showing wavelet denoising effects.

Creates a multi-panel figure showing: - Original DEM - Denoised DEM - Difference (noise removed) - Cross-section profile comparison

Parameters:
  • original (ndarray) – Original DEM before denoising

  • denoised (ndarray) – DEM after wavelet denoising

  • output_path (Path) – Path to save the diagnostic plot

  • title_prefix (str) – Prefix for plot titles

  • nodata_value (float) – Value treated as no data

  • profile_row (int | None) – Row index for cross-section (default: middle row)

  • cmap (str) – Colormap for elevation visualization

Returns:

Path to saved diagnostic plot

Return type:

Path

Generate diagnostic plots showing wavelet denoising effects.

Creates:

  • Original DEM panel

  • Denoised DEM panel

  • Difference map (noise removed)

  • Cross-section profile comparison

Example:

from src.terrain.diagnostics import plot_wavelet_diagnostics

plot_wavelet_diagnostics(
    original=dem_before,
    denoised=dem_after,
    output_path='diagnostics/wavelet.png',
    title_prefix='Wavelet Denoising (db4)',
    cmap='terrain'
)
src.terrain.diagnostics.plot_wavelet_coefficients(original, output_path, wavelet='db4', levels=3, threshold_sigma=2.0, nodata_value=nan)[source]

Generate diagnostic plots showing wavelet coefficient distributions.

Creates a figure showing: - Coefficient histograms before/after thresholding - Decomposition levels visualization - Threshold line for each level

Parameters:
  • original (ndarray) – Original DEM

  • output_path (Path) – Path to save the diagnostic plot

  • wavelet (str) – Wavelet type used for decomposition

  • levels (int) – Number of decomposition levels

  • threshold_sigma (float) – Sigma multiplier for thresholding

  • nodata_value (float) – Value treated as no data

Returns:

Path to saved diagnostic plot

Return type:

Path

Visualize wavelet decomposition coefficients.

src.terrain.diagnostics.generate_full_wavelet_diagnostics(original, denoised, output_dir, prefix='wavelet', wavelet='db4', levels=3, threshold_sigma=2.0, nodata_value=nan)[source]

Generate all wavelet diagnostic plots.

Creates both the before/after comparison and the coefficient analysis.

Parameters:
  • original (ndarray) – Original DEM before denoising

  • denoised (ndarray) – DEM after wavelet denoising

  • output_dir (Path) – Directory to save diagnostic plots

  • prefix (str) – Filename prefix for saved plots

  • wavelet (str) – Wavelet type used for denoising

  • levels (int) – Number of decomposition levels

  • threshold_sigma (float) – Sigma multiplier used for thresholding

  • nodata_value (float) – Value treated as no data

Returns:

Tuple of (comparison_plot_path, coefficient_plot_path)

Return type:

Tuple[Path, Path]

Generate comprehensive wavelet diagnostic report.

Adaptive Smoothing Diagnostics

src.terrain.diagnostics.plot_adaptive_smooth_diagnostics(original, smoothed, output_path, slope_threshold=2.0, smooth_sigma=5.0, transition_width=1.0, title_prefix='Slope-Adaptive Smoothing', nodata_value=nan, profile_row=None, cmap='terrain', pixel_size=None, edge_threshold=None, edge_window=5)[source]

Generate diagnostic plots showing slope-adaptive smoothing effects.

Creates a multi-panel figure showing: - Original DEM - Computed slope map - Smoothing weight mask (where smoothing is applied) - Smoothed DEM - Difference (noise removed) - Cross-section profile comparison

Parameters:
  • original (ndarray) – Original DEM before smoothing

  • smoothed (ndarray) – DEM after slope-adaptive smoothing

  • output_path (Path) – Path to save the diagnostic plot

  • slope_threshold (float) – Slope threshold in degrees used for smoothing

  • smooth_sigma (float) – Gaussian sigma used for smoothing

  • transition_width (float) – Width of sigmoid transition zone

  • title_prefix (str) – Prefix for plot titles

  • nodata_value (float) – Value treated as no data

  • profile_row (int | None) – Row index for cross-section (default: middle row)

  • cmap (str) – Colormap for elevation visualization

  • pixel_size (float | None) – Pixel size in meters (e.g., 30.0 for SRTM data). Required for accurate slope calculation.

  • edge_threshold (float | None) – Edge preservation threshold in meters (default: None). If set, shows which areas are protected due to sharp elevation changes.

  • edge_window (int) – Window size for edge detection (default: 5).

Returns:

Path to saved diagnostic plot

Return type:

Path

Generate diagnostic plots for slope-adaptive smoothing.

Creates:

  • Original DEM

  • Smoothed DEM

  • Difference map

  • Slope mask (shows smoothed vs preserved areas)

  • Cross-section profiles

Example:

from src.terrain.diagnostics import plot_adaptive_smooth_diagnostics

plot_adaptive_smooth_diagnostics(
    original=dem_before,
    smoothed=dem_after,
    slope_mask=slope_mask,
    output_path='diagnostics/adaptive_smooth.png',
    slope_threshold=2.0
)
src.terrain.diagnostics.plot_adaptive_smooth_histogram(original, smoothed, output_path, slope_threshold=2.0, transition_width=1.0, title_prefix='Slope-Adaptive Smoothing', nodata_value=nan, pixel_size=None)[source]

Generate histogram analysis of slope-adaptive smoothing.

Shows distribution of slopes and how much smoothing was applied at different slope values.

Parameters:
  • original (ndarray) – Original DEM before smoothing

  • smoothed (ndarray) – DEM after slope-adaptive smoothing

  • output_path (Path) – Path to save the diagnostic plot

  • slope_threshold (float) – Slope threshold in degrees used for smoothing

  • transition_width (float) – Width of sigmoid transition zone

  • title_prefix (str) – Prefix for plot titles

  • nodata_value (float) – Value treated as no data

  • pixel_size (float | None) – Pixel size in meters (e.g., 30.0 for SRTM data). Required for accurate slope calculation.

Returns:

Path to saved diagnostic plot

Return type:

Path

Histogram showing slope distribution and smoothing threshold.

src.terrain.diagnostics.generate_full_adaptive_smooth_diagnostics(original, smoothed, output_dir, prefix='adaptive_smooth', slope_threshold=2.0, smooth_sigma=5.0, transition_width=1.0, nodata_value=nan, pixel_size=None, edge_threshold=None, edge_window=5)[source]

Generate all slope-adaptive smoothing diagnostic plots.

Creates both the spatial comparison and the histogram analysis.

Parameters:
  • original (ndarray) – Original DEM before smoothing

  • smoothed (ndarray) – DEM after slope-adaptive smoothing

  • output_dir (Path) – Directory to save diagnostic plots

  • prefix (str) – Filename prefix for saved plots

  • slope_threshold (float) – Slope threshold in degrees

  • smooth_sigma (float) – Gaussian sigma used for smoothing

  • transition_width (float) – Width of sigmoid transition zone

  • nodata_value (float) – Value treated as no data

  • pixel_size (float | None) – Pixel size in meters (e.g., 30.0 for SRTM data). Required for accurate slope calculation.

  • edge_threshold (float | None) – Edge preservation threshold in meters (default: None). If set, shows which areas are protected due to sharp elevation changes.

  • edge_window (int) – Window size for edge detection (default: 5).

Returns:

Tuple of (spatial_plot_path, histogram_plot_path)

Return type:

Tuple[Path, Path]

Generate comprehensive adaptive smoothing diagnostic report.

Bump Removal Diagnostics

src.terrain.diagnostics.plot_bump_removal_diagnostics(original, after_removal, output_path, kernel_size=3, title_prefix='Bump Removal', nodata_value=nan, cmap='terrain')[source]

Generate diagnostic plot for morphological bump removal.

Shows: - Original DEM - After bump removal - Bumps removed (difference) - always positive since only peaks are removed - Histogram of bump heights

Parameters:
  • original (ndarray) – Original DEM before bump removal

  • after_removal (ndarray) – DEM after morphological opening

  • output_path (Path) – Path to save the diagnostic plot

  • kernel_size (int) – Kernel size used for removal

  • title_prefix (str) – Prefix for plot titles

  • nodata_value (float) – Value treated as no data

  • cmap (str) – Colormap for elevation visualization

Returns:

Path to saved diagnostic plot

Return type:

Path

Visualize morphological bump removal effects.

Creates:

  • Original DEM with bumps

  • DEM after bump removal

  • Difference map (bumps removed)

  • Histogram of height changes

Example:

from src.terrain.diagnostics import plot_bump_removal_diagnostics

plot_bump_removal_diagnostics(
    original=dem_before,
    processed=dem_after,
    output_path='diagnostics/bump_removal.png',
    kernel_size=5
)
src.terrain.diagnostics.generate_bump_removal_diagnostics(original, after_removal, output_dir, prefix='bump_removal', kernel_size=3, nodata_value=nan)[source]

Generate bump removal diagnostic plot.

Parameters:
  • original (ndarray) – Original DEM before bump removal

  • after_removal (ndarray) – DEM after morphological opening

  • output_dir (Path) – Directory to save diagnostic plot

  • prefix (str) – Filename prefix

  • kernel_size (int) – Kernel size used for removal

  • nodata_value (float) – Value treated as no data

Returns:

Path to saved diagnostic plot

Return type:

Path

Generate comprehensive bump removal diagnostic report.

Upscaling Diagnostics

src.terrain.diagnostics.plot_upscale_diagnostics(original, upscaled, output_path, scale=4, method='unknown', title_prefix='Score Upscaling', nodata_value=nan, cmap='viridis')[source]

Generate diagnostic plots showing score upscaling effects.

Creates a multi-panel figure showing: - Original score grid - Upscaled score grid - Zoomed comparison of a region - Histograms of value distributions - Edge detail comparison

Parameters:
  • original (ndarray) – Original score grid before upscaling

  • upscaled (ndarray) – Score grid after upscaling

  • output_path (Path) – Path to save the diagnostic plot

  • scale (int) – Upscaling factor used

  • method (str) – Upscaling method name (for title)

  • title_prefix (str) – Prefix for plot titles

  • nodata_value (float) – Value treated as no data

  • cmap (str) – Colormap for score visualization

Returns:

Path to saved diagnostic plot

Return type:

Path

Visualize AI super-resolution upscaling results.

Creates:

  • Low-resolution input

  • High-resolution output

  • Difference from nearest-neighbor

  • Sharpness metrics

Example:

from src.terrain.diagnostics import plot_upscale_diagnostics

plot_upscale_diagnostics(
    low_res=score_input,
    high_res=score_upscaled,
    output_path='diagnostics/upscale.png',
    scale_factor=4
)
src.terrain.diagnostics.generate_upscale_diagnostics(original, upscaled, output_dir, prefix='score_upscale', scale=4, method='unknown', nodata_value=nan, cmap='viridis')[source]

Generate upscale diagnostic plot.

Parameters:
  • original (ndarray) – Original score grid before upscaling

  • upscaled (ndarray) – Score grid after upscaling

  • output_dir (Path) – Directory to save diagnostic plot

  • prefix (str) – Filename prefix

  • scale (int) – Upscaling factor used

  • method (str) – Upscaling method name

  • nodata_value (float) – Value treated as no data

  • cmap (str) – Colormap for score visualization

Returns:

Path to saved diagnostic plot

Return type:

Path

Generate comprehensive upscaling diagnostic report.

Road Elevation Diagnostics

src.terrain.diagnostics.plot_road_elevation_diagnostics(dem, road_mask, output_dir, prefix='road_elevation', kernel_radius=3, nodata_value=nan, cmap='terrain', dpi=300)[source]

Plot the max height difference between road pixels and surrounding terrain.

For each road pixel, computes the max elevation of nearby non-road pixels and reports the difference (road - surrounding_max). Negative means the road sits below the highest neighboring terrain; positive means the road is higher than all surrounding non-road pixels.

Saves six separate high-resolution plots: - {prefix}_dem_overlay.png: DEM with road overlay - {prefix}_diff_map.png: Spatial map of road-vs-surrounding max difference - {prefix}_positive_map.png: Roads above surrounding terrain (positive deviations) - {prefix}_negative_map.png: Roads below surrounding terrain (negative deviations) - {prefix}_histogram.png: Distribution of differences - {prefix}_stats.png: Summary statistics panel

Parameters:
  • dem (ndarray) – 2D elevation array (same shape as road_mask)

  • road_mask (ndarray) – 2D array where >0.5 indicates road pixels

  • output_dir (Path) – Directory to save the diagnostic plots

  • prefix (str) – Filename prefix for all output files

  • kernel_radius (int) – Radius of the neighborhood window for computing surrounding terrain max (default: 3 pixels)

  • nodata_value (float) – Value treated as no data in the DEM

  • cmap (str) – Colormap for elevation visualization

  • dpi (int) – Output resolution (default: 300)

Returns:

List of paths to saved diagnostic plots, empty if no roads

Return type:

list[Path]

Visualize DEM smoothing effects along roads.

Creates:

  • Original DEM elevations along roads

  • Smoothed DEM elevations

  • Height differences

  • Road network overlay

Example:

from src.terrain.diagnostics import plot_road_elevation_diagnostics

plot_road_elevation_diagnostics(
    original_dem=dem_before,
    smoothed_dem=dem_after,
    road_mask=road_mask,
    output_path='diagnostics/road_elevation.png'
)
src.terrain.diagnostics.generate_road_elevation_diagnostics(dem, road_mask, output_dir, prefix='road_elevation', kernel_radius=3, nodata_value=nan, dpi=300)[source]

Generate road elevation diagnostic plots (6 separate high-res files).

Parameters:
  • dem (ndarray) – 2D elevation array

  • road_mask (ndarray) – 2D array where >0.5 indicates road pixels

  • output_dir (Path) – Directory to save diagnostic plots

  • prefix (str) – Filename prefix

  • kernel_radius (int) – Radius for surrounding terrain window

  • nodata_value (float) – Value treated as no data

  • dpi (int) – Output resolution (default: 300)

Returns:

List of paths to saved diagnostic plots, empty if no roads

Return type:

list[Path]

Generate comprehensive road elevation diagnostic report.

src.terrain.diagnostics.plot_road_vertex_z_diagnostics(vertices, road_mask, y_valid, x_valid, output_dir, prefix='road_vertex_z', kernel_radius=3, dpi=300, label='')[source]

Plot road-vs-surrounding elevation using actual mesh vertex Z positions.

Reconstructs a Z-height grid from vertex positions, then computes the max height of non-road neighbors for each road pixel. This reflects what the renderer actually sees, including any smoothing/offset already applied.

Saves six separate high-resolution plots: - {prefix}_dem_overlay.png: Vertex Z grid with road overlay - {prefix}_diff_map.png: Spatial difference map (road Z - surrounding max Z) - {prefix}_positive_map.png: Roads above surrounding (positive deviations) - {prefix}_negative_map.png: Roads below surrounding (negative deviations) - {prefix}_histogram.png: Distribution of differences - {prefix}_stats.png: Summary statistics

Parameters:
  • vertices (ndarray) – (N, 3) array of mesh vertex positions (X, Y, Z)

  • road_mask (ndarray) – 2D grid array where >0.5 indicates road pixels

  • y_valid (ndarray) – 1D array mapping surface vertex index -> grid row

  • x_valid (ndarray) – 1D array mapping surface vertex index -> grid column

  • output_dir (Path) – Directory to save diagnostic plots

  • prefix (str) – Filename prefix for all output files

  • kernel_radius (int) – Radius for surrounding terrain window (default: 3)

  • dpi (int) – Output resolution (default: 300)

  • label (str) – Optional label for plot titles (e.g. “pre-smoothing”)

Returns:

List of paths to saved diagnostic plots, empty if no roads

Return type:

list[Path]

Visualize vertex-level road elevation changes.

Pipeline Visualization

src.terrain.diagnostics.plot_processing_pipeline(stages, output_path, title='Processing Pipeline', cmap='terrain', nodata_value=nan)[source]

Generate comparison plots showing multiple processing stages.

Useful for visualizing an entire processing pipeline with multiple transforms (raw → despeckle → wavelet → smooth, etc.)

Parameters:
  • stages (dict[str, ndarray]) – Dictionary mapping stage names to DEM arrays Example: {“Raw”: raw_dem, “Despeckled”: despeckled, “Final”: final}

  • output_path (Path) – Path to save the diagnostic plot

  • title (str) – Plot title

  • cmap (str) – Colormap for elevation

  • nodata_value (float) – Value treated as no data

Returns:

Path to saved diagnostic plot

Return type:

Path

Visualize multi-stage processing pipeline.

Shows before/after for each processing step in sequence.

Example:

from src.terrain.diagnostics import plot_processing_pipeline

plot_processing_pipeline(
    stages=[
        ('Original', dem_original),
        ('Wavelet Denoised', dem_wavelet),
        ('Adaptive Smoothed', dem_adaptive),
        ('Final', dem_final)
    ],
    output_path='diagnostics/pipeline.png'
)

Histogram Generation

src.terrain.diagnostics.generate_rgb_histogram(image_path, output_path)[source]

Generate and save an RGB histogram of a rendered image.

Creates a figure with histograms for each color channel (R, G, B) overlaid on the same axes with transparency. Useful for analyzing color balance and distribution in rendered outputs.

Parameters:
  • image_path (Path) – Path to the rendered image (PNG, JPEG, etc.)

  • output_path (Path) – Path to save the histogram image

Returns:

Path to saved histogram image, or None if failed

Return type:

Path | None

Generate RGB channel histograms for rendered images.

Useful for validating color balance and dynamic range.

Example:

from src.terrain.diagnostics import generate_rgb_histogram

generate_rgb_histogram(
    image_path='render_output.png',
    output_path='diagnostics/rgb_histogram.png'
)
src.terrain.diagnostics.generate_luminance_histogram(image_path, output_path)[source]

Generate and save a luminance (B&W) histogram of a rendered image.

Shows distribution of brightness values with annotations for pure black and pure white pixel counts. Useful for checking exposure and clipping in rendered outputs, especially for print preparation.

Parameters:
  • image_path (Path) – Path to the rendered image (PNG, JPEG, etc.)

  • output_path (Path) – Path to save the histogram image

Returns:

Path to saved histogram image, or None if failed

Return type:

Path | None

Generate grayscale luminance histogram.

Useful for checking exposure and contrast.

Example:

from src.terrain.diagnostics import generate_luminance_histogram

generate_luminance_histogram(
    image_path='render_output.png',
    output_path='diagnostics/luminance_histogram.png'
)

Usage Patterns

Pattern 1: Debug single transform

from src.terrain.diagnostics import plot_wavelet_diagnostics

# Apply transform
denoised = wavelet_denoise_dem(dem, wavelet='db4')

# Generate diagnostics
plot_wavelet_diagnostics(
    original=dem,
    denoised=denoised,
    output_path='debug_wavelet.png'
)

Pattern 2: Full pipeline diagnostics

from src.terrain.diagnostics import plot_processing_pipeline

stages = []
stages.append(('Original', dem))

# Step 1: Wavelet denoise
dem = wavelet_denoise_dem(dem)
stages.append(('Wavelet', dem))

# Step 2: Adaptive smooth
dem = slope_adaptive_smooth(dem)
stages.append(('Adaptive', dem))

# Step 3: Bump removal
dem = remove_bumps(dem)
stages.append(('Bumps Removed', dem))

# Visualize entire pipeline
plot_processing_pipeline(stages, 'pipeline.png')

Pattern 3: Batch diagnostics

from src.terrain.diagnostics import generate_full_wavelet_diagnostics

# Comprehensive diagnostic report (multiple plots)
generate_full_wavelet_diagnostics(
    original=dem_before,
    denoised=dem_after,
    output_dir='diagnostics/wavelet/'
)

See Also