Diagnostic Tools
Terrain-maker includes comprehensive diagnostic tools for visualizing and debugging terrain processing pipelines. These tools help you understand how transforms affect your data and optimize rendering parameters.
Overview
The terrain.diagnostics module provides visualization functions for:
Wavelet denoising - Analyze noise removal and frequency decomposition
Slope-adaptive smoothing - Visualize smoothing intensity based on terrain slope
Bump removal - Debug morphological filtering effects
Score upscaling - Compare original vs upscaled score grids
Render histograms - Analyze color distribution in output images
Wavelet Denoising Diagnostics
plot_wavelet_diagnostics
Shows before/after comparison of wavelet denoising with difference maps and cross-section profiles.
from src.terrain.diagnostics import plot_wavelet_diagnostics
plot_wavelet_diagnostics(
original=dem_original,
denoised=dem_denoised,
output_path=Path("diagnostics/wavelet.png"),
title_prefix="DEM Wavelet Denoising",
profile_row=500, # Row for cross-section
)
Output panels:
Original DEM
Denoised DEM
Difference (noise removed)
Cross-section profile comparison
plot_wavelet_coefficients
Visualizes the wavelet decomposition showing detail coefficients at each level.
from src.terrain.diagnostics import plot_wavelet_coefficients
plot_wavelet_coefficients(
data=dem_data,
output_path=Path("diagnostics/wavelet_coeffs.png"),
wavelet="db4",
levels=3,
)
generate_full_wavelet_diagnostics
Generates complete wavelet diagnostic report with multiple visualizations.
from src.terrain.diagnostics import generate_full_wavelet_diagnostics
generate_full_wavelet_diagnostics(
original=dem_original,
denoised=dem_denoised,
output_dir=Path("diagnostics/"),
wavelet="db4",
levels=3,
threshold_sigma=2.0,
)
Slope-Adaptive Smoothing Diagnostics
plot_adaptive_smooth_diagnostics
Visualizes how smoothing varies based on terrain slope - showing more smoothing on flat areas and less on steep terrain.
from src.terrain.diagnostics import plot_adaptive_smooth_diagnostics
plot_adaptive_smooth_diagnostics(
original=dem_original,
smoothed=dem_smoothed,
output_path=Path("diagnostics/adaptive_smooth.png"),
pixel_size=30.0, # meters per pixel
)

Output panels:
Original DEM
Smoothed DEM
Computed slope map
Smoothing weight mask (bright = more smoothing)
Difference map
Cross-section profiles
plot_adaptive_smooth_histogram
Shows histograms comparing original vs smoothed elevation distributions.
from src.terrain.diagnostics import plot_adaptive_smooth_histogram
plot_adaptive_smooth_histogram(
original=dem_original,
smoothed=dem_smoothed,
output_path=Path("diagnostics/adaptive_histogram.png"),
)

Bump Removal Diagnostics
plot_bump_removal_diagnostics
Visualizes morphological bump removal showing original, smoothed, and removed features.
from src.terrain.diagnostics import plot_bump_removal_diagnostics
plot_bump_removal_diagnostics(
original=dem_original,
smoothed=dem_smoothed,
output_path=Path("diagnostics/bump_removal.png"),
kernel_size=5,
structure="disk",
)

Output panels:
Original DEM
After bump removal
Removed features (bumps)
Histograms of elevation changes
Score Upscaling Diagnostics
plot_upscale_diagnostics
Compares original and upscaled score grids with zoomed regions and histograms.
from src.terrain.diagnostics import plot_upscale_diagnostics
plot_upscale_diagnostics(
original=scores_lowres,
upscaled=scores_hires,
output_path=Path("diagnostics/upscale.png"),
scale=4,
method="esrgan",
title_prefix="Sledding Scores",
)

Output panels:
Original score grid (full view)
Upscaled score grid (full view)
Zoomed comparison of high-variance region
Value distribution histograms
Edge sharpness comparison
generate_upscale_diagnostics
Convenience function that handles file paths and method detection.
from src.terrain.diagnostics import generate_upscale_diagnostics
generate_upscale_diagnostics(
original=scores,
upscaled=scores_upscaled,
output_dir=Path("diagnostics/"),
name="sledding",
scale=4,
method="esrgan",
)
Render Histogram Analysis
generate_rgb_histogram
Creates RGB channel histograms for rendered images to analyze color balance.
from src.terrain.diagnostics import generate_rgb_histogram
generate_rgb_histogram(
image_path=Path("render.png"),
output_path=Path("render_histogram.png"),
)
Shows:
Overlaid R, G, B channel histograms
Mean and standard deviation for each channel
Useful for detecting color casts or imbalances
generate_luminance_histogram
Creates luminance (brightness) histogram with clipping analysis.
from src.terrain.diagnostics import generate_luminance_histogram
generate_luminance_histogram(
image_path=Path("render.png"),
output_path=Path("render_luminance.png"),
)
Shows:
Luminance distribution (ITU-R BT.601 formula)
Pure black (0) and pure white (255) pixel counts
Clipping warnings for print preparation
CLI Integration
The detroit_combined_render.py example automatically generates diagnostics when using certain flags:
# Generate upscale diagnostics
python examples/detroit_combined_render.py --upscale-scores
# Generates:
# diagnostics/sledding_upscale_diagnostics.png
# diagnostics/xc_upscale_diagnostics.png
# Generate adaptive smooth diagnostics
python examples/detroit_combined_render.py --adaptive-smooth --diagnostics
# Generate all render diagnostics (histograms)
python examples/detroit_combined_render.py --print-quality
# Generates:
# output_histogram.png
# output_luminance.png
Best Practices
When to Use Diagnostics
Tuning parameters - Use diagnostics to find optimal values for smoothing, denoising, upscaling
Debugging artifacts - Identify source of visual problems in renders
Print preparation - Check histograms for clipping before printing
Quality assurance - Verify transforms produce expected results
Performance Considerations
Diagnostic plots add ~1-3 seconds to processing time
Large arrays (>4000x4000) may use significant memory for plotting
Consider generating diagnostics only during development, not production
API Reference
- 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:
- 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:
- Returns:
Path to saved diagnostic plot
- Return type:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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:
- Returns:
Path to saved diagnostic plot
- Return type:
- 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:
- 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:
- 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.
- 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.
See Also
Combined Render: Full-Featured Example - Full example using diagnostics
wavelet_denoise_dem()- Wavelet denoising transformslope_adaptive_smooth()- Adaptive smoothing transformupscale_scores()- Score upscaling function