ADR-001: Vector-First Architecture
Status
Accepted
Context
The BlueGreenCity-KI system needs to process urban tree data with various spatial and non-spatial attributes to compute risk scores. The data comes from multiple sources including:
- Tree inventories (points with attributes like age, vitality, species)
- Street networks (line geometries with classifications)
- Environmental data (rasters: land use, temperature, elevation)
- Soil data (polygons with capacity values)
We need to decide on the fundamental data processing approach:
- Should we process everything as raster data (grid-based)?
- Should we process everything as vector data (feature-based)?
- Should we use a hybrid approach?
Key constraints:
- Tree locations are fundamentally point features
- Most criteria operate on per-tree attributes
- Raster data exists but represents environmental context
- Performance is critical (processing tens of thousands of trees per run; ~90k in the current v6 inventory)
- Results need to be per-tree, not gridded
Decision
We will adopt a vector-first architecture where:
- All scoring computations operate on vector data (GeoPandas DataFrames)
- Each tree is a row with a unique identifier (index)
- Raster inputs are sampled once at tree locations and cached as DataFrame columns
- All criterion scores are pandas Series aligned by tree ID
- Final aggregation produces a per-tree DataFrame with all scores and risk
The workflow is:
Raster Data → Sample at tree points → Cached columns
↓
Tree Vector Data + Cached Raster Values → Criteria Scoring → Results DataFrame
Consequences
Positive Consequences
- Performance: Vector operations on DataFrames are fast for tree-scale datasets (10k-100k features)
- Memory efficient: Only store values at tree locations, not full grids
- Flexibility: Easy to add new attributes or criteria without changing data structure
- Clarity: Each tree is an explicit entity with clear identity throughout pipeline
- Tool compatibility: GeoPandas integrates well with spatial tools (PostGIS, QGIS, ArcGIS)
- Testing: Easy to create test datasets with specific tree configurations
- Debugging: Can inspect per-tree values directly in DataFrames
Negative Consequences
- Raster resampling overhead: Must sample raster at each tree location during data loading
- Limited spatial analysis: Cannot easily perform neighborhood operations on continuous surfaces
- Memory for large rasters: Loading large rasters into memory for sampling can be expensive
- Two data models: Developers must understand both vector and raster paradigms
Neutral Consequences
- Caching required: Raster values must be sampled once and cached; repeated access would be slow
- Index alignment critical: All Series must maintain consistent tree ID indexing
- Geometry optional: For non-spatial criteria, geometry column is not used
Alternatives Considered
Alternative 1: Raster-First Architecture
Description: Rasterize all data (trees, roads, attributes) and perform all computations on grids.
Pros:
- Uniform data model (everything is a grid)
- Neighborhood operations are straightforward
- Can leverage raster algebra libraries
- Works well for continuous phenomena (temperature, moisture)
Cons:
- Tree identity is lost (multiple trees per pixel or trees span multiple pixels)
- Discrete attributes (tree ID, species) don’t rasterize well
- Output would need to be converted back to per-tree results
- High memory usage for fine-resolution grids
- Poor representation of point features
Reason for rejection: Trees are fundamentally discrete point features, and risk assessment is inherently per-tree. Rasterization would lose critical information and add conversion overhead.
Alternative 2: Hybrid Processing (Both Raster and Vector Pipelines)
Description: Process some criteria on rasters (temperature, land use) and others on vectors (age, vitality), then merge results.
Pros:
- “Best of both worlds” for different criterion types
- Can optimize each criterion’s data model
- More flexible for complex spatial operations
Cons:
- Complex architecture with two parallel pipelines
- Difficult to maintain index alignment across models
- Harder to understand and debug
- Risk of inconsistencies between pipelines
- More code complexity
Reason for rejection: Added complexity outweighs benefits. Sampling raster values once is sufficient for our use cases, and maintaining two pipelines would increase maintenance burden.
Alternative 3: Pure DataFrame (No Spatial)
Description: Convert all data to non-spatial pandas DataFrames, dropping geometry.
Pros:
- Fastest processing (no spatial overhead)
- Simpler dependencies (no GeoPandas)
- Easier testing
Cons:
- Cannot compute spatial criteria (nearest neighbors, spatial joins)
- Cannot visualize results spatially
- Cannot write to spatial formats (GPKG, PostGIS)
- Loses key advantage of GIS integration
Reason for rejection: Spatial operations are essential for several criteria (planting structure, street proximity), and spatial outputs are required for stakeholders.
References
Date: 2024-03-15
Author: BlueGreenCity-KI Team
Reviewers: Architecture Review Board