Skip to content
Back to Projects
Research 2026-06

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.

LiDAR Coverage 391 km²
PythonLiDARGISRemote SensingNDVIGeoJSONNumPySciPyGitHub Pages

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.

Flood susceptibility visualization over Ljubljana. High-risk cells are derived from terrain wetness, canopy interception, NDVI health, plan curvature, and terrain roughness.

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: .laz point-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

Flood susceptibility overlays generated from the official CLSS LiDAR data. Left: Ljubljana-wide visualization. Right: coastal example showing the same pipeline on a different terrain profile.

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)

Forest coverage / NDVI view derived from the same tile set. This makes vegetation health and urban-vs-forest transitions legible at city scale.

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

Land-classification outputs from the processed CLSS point cloud. These views distinguish ground, vegetation bands, and building footprints across very different terrain and settlement patterns.
A coastal/industrial example showing that the same classification pipeline continues to separate built form, ground, and vegetation under a very different spatial pattern.

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_*.laz files 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