Slovenia CLSS LiDAR — Flood Susceptibility & Forest Health Map
A geospatial analysis pipeline that progressed from an 81-tile, 15 GB Ljubljana pilot to 91.7 GB of official Slovenian LiDAR across 391 km², producing flood-risk, forest-health, and land-classification outputs for an interactive static map.
What this project proves
Geospatial data pipeline and visualization builder
Scaled an 81-tile, 15 GB Ljubljana pilot to 91.7 GB of national LiDAR across 391 km², with 3.3× faster batch processing.
Core challenge
Turn raw multi-tile LiDAR data into web-deliverable risk analysis while keeping scores comparable across the full dataset.
Evaluation lens
Offline data processing, dataset-wide calibration, raster export, and static delivery architecture.
A progressively scaled LiDAR-to-web pipeline that turns 91.7 GB of geospatial source data into a usable interactive analysis product.
Overview
This project turns a large raw LiDAR dataset from Slovenia’s official CLSS national scanning programme into a deployable flood-analysis product. I built both the offline analysis pipeline and the interactive delivery layer: processing region tiles, calibrating dataset-wide factor ranges, generating overlay rasters, ranking the highest-risk cells, and publishing the results as a static web map with no backend.
The project progressed in two documented stages. The initial published pilot transformed roughly 15 GB across 81 LiDAR tiles into lightweight web assets for a contiguous 9 × 9 km block over Ljubljana. The pipeline then expanded to 91.7 GB of LiDAR across 391 km², while batch-processing improvements made the larger workload 3.3× faster. Both stages produced spatially comparable flood, vegetation, land-classification, and ranked-risk outputs that remain inexpensive to serve.
Progressive Scale-Up
- Ljubljana pilot: 15 GB, 81 tiles, and a 9 × 9 km study area established the calibration, raster-generation, ranking, and static-delivery workflow.
- Expanded analysis: 91.7 GB across 391 km² extended the same project beyond the original city-scale snapshot.
- Pipeline optimization: Numba and multiprocessing improved batch runtime by 3.3×, making the expanded scope practical.
Official Dataset
The source data comes from Geodetska uprava RS through Slovenia’s CLSS programme, which makes this a project grounded in official government geospatial infrastructure rather than synthetic or toy inputs.
- Source: official Slovenia national airborne LiDAR programme
- Coordinate systems: EPSG:3794 and EPSG:4326 in the published map workflow
- Grid resolution: 2 m × 2 m × 2 m voxels in the derived analysis pipeline
- Raw format:
.lazpoint-cloud tiles processed into deployable raster overlays
What The System Visualizes
- Flood susceptibility from a weighted composite of topographic wetness, canopy interception, NDVI health, plan curvature, and terrain roughness
- Forest coverage / NDVI health from per-cell vegetation scoring using 16-bit NIR and red channels
- Land classification separating ground, low vegetation, medium vegetation, high vegetation, and building returns
- High-risk locations from globally ranked candidate cells exported into interactive map markers
Visual Outputs
Flood Susceptibility
The flood layer is where the pipeline becomes more than a renderer. Each pixel score combines topographic wetness, vegetation condition, canopy interception, terrain roughness, and curvature into a normalized susceptibility surface. The map then exposes the highest-ranked candidate cells as clickable points so the result is not just pretty heatmapping, but actionable prioritization.
Forest Coverage (NDVI)
This view shows how the same processed data can be reinterpreted as a forest health / vegetation condition layer. Instead of flood susceptibility, the interface surfaces the gradient from stressed to healthy vegetation, which is useful both as a direct environmental signal and as an input into the flood model itself.
Land Classification
The land-classification layer is important because it proves the pipeline is not producing a single visualization in isolation. It extracts multiple semantically meaningful map products from the same official dataset, which makes the site feel like a lightweight geospatial analysis platform rather than a one-off demo.
What I Built
- A dataset-wide calibration stage so overlay scores remain comparable across all processed tiles
- A Python pipeline that transforms raw
GKOT_*.lazfiles into deployable susceptibility, NDVI, and classification rasters - A ranking/export layer that produces globally ranked high-risk cells and GeoJSON markers
- A static frontend that overlays the outputs interactively and publishes them through GitHub Pages
- A Numba and multiprocessing optimization pass that improved batch runtime by 3.3× as the dataset grew to 91.7 GB across 391 km²
Technical Depth
The core technical problem was making flood-risk scores comparable across the entire dataset, not just visually plausible within a single tile. I solved that by introducing a calibration stage that derives dataset-wide normalization ranges once, stores them with a dataset fingerprint, and warns when the underlying tile set changes and recalibration is needed.
The canonical pipeline.py then processes all GKOT_*.laz files into deployable assets:
- per-tile susceptibility rasters
- per-tile NDVI rasters
- per-tile land-classification rasters
- a manifest consumed by the web app
- a globally ranked candidate list
- a GeoJSON file for top flood-risk points
That separation between raw source data and committed derived outputs matters. The heavyweight LiDAR tiles stay local and gitignored, while the smaller analysis products in web/data/ are versioned and deployed, which keeps the project reproducible without making the repository impractical.
Architecture
The system is intentionally simple at runtime:
- Python pipeline for acquisition, calibration, raster generation, candidate ranking, and GeoJSON export
- Static web frontend for rendering overlays and interaction
- GitHub Pages deployment from the
web/directory on every push
This is a strong example of choosing the right architecture for the problem. Instead of introducing unnecessary services, I kept the runtime fully static and moved complexity into the offline data-processing layer where it belongs.
Why It Matters
This project shows that I can work comfortably at the intersection of geospatial data engineering, analysis design, and product delivery. I did not just compute one metric on one file; I grew a repeatable pipeline from an 81-tile Ljubljana pilot into a 91.7 GB, 391 km² analysis, improved batch performance by 3.3×, preserved comparability at dataset scope, and shipped the results in a form that is immediately inspectable in the browser.
Tech Stack
- Data processing: Python,
laspy,lazrs,numpy,scipy,pyproj,Pillow - Geospatial outputs: PNG overlays, manifest-driven tile loading, GeoJSON risk points
- Frontend / deployment: Static web app, GitHub Pages