Skip to main content
PlanX SDK Logo

PlanX SDK

PyPI version Python version support Documentation License: MIT Code style: Ruff Test Coverage

High-Performance Headless Spatial Analytics, Spatial Statistics, Network Routing, and Urban Resilience Engine.

📖 Open Interactive Web Manual (GitLab Pages) • 📦 PyPI Package • 🐛 Issue Tracker


🌟 Overview

PlanX SDK is the official standalone computational core of the PlanX ecosystem. Built purely on Python, NumPy, and SciPy, it executes complex spatial analysis, spatial statistics, network optimization, and urban climate resilience models completely headless—with zero dependency on QGIS GUI components, Qt bindings, or desktop window managers.

Why PlanX SDK?

  • 🚀 Headless & Scalable: Run large-scale geospatial routines inside Jupyter notebooks, FastAPI/Flask backends, Docker containers, Celery workers, or AWS Lambda/Cloud Run.
  • ⚡ Vectorized Performance: Heavy mathematical models (e.g., Getis-Ord $G_i^*$, E2SFCA, KDTree IDW, Brandes betweenness, CSR Dijkstra) leverage fast contiguous NumPy arrays and SciPy sparse graph matrices.
  • 🔬 Scientific Rigor: Implements validated academic algorithms across spatial statistics, urban physics, Space Syntax, and multi-hazard climate adaptation.
  • 🧪 Deterministic & Tested: Over 480+ automated unit tests ensuring high mathematical stability and precision across Python 3.9 through 3.13.

🏛️ Headless SDK vs. PlanX QGIS Plugin

Capability PlanX QGIS Plugin (GUI) PlanX SDK (Headless Core)
Runtime Environment Desktop QGIS Application (Qt UI) Pure Python (pip install planx-sdk)
Execution Mode Interactive Canvas, Layers, Dialogs Programmatic, Scriptable, Headless
Cloud / Serverless Support ❌ Requires X11 / Virtual Framebuffer ✅ Native (FastAPI, Docker, Microservices)
Data Science Workflow ⚠️ Export/Import manual shapefiles ✅ Native NumPy arrays, SciPy, Pandas
Automated Testing & CI/CD ⚠️ Heavy desktop GUI fixtures ✅ Fast unit testing with pytest

📦 Installation

# Standard installation from PyPI
pip install planx-sdk

# With development and test suite dependencies
pip install "planx-sdk[dev]"

🗺️ Module Architecture & Capabilities

planx/
├── spatial/              # Network routing, centrality, accessibility (E2SFCA, Hansen), spatial Gini
├── geostats/             # Autocorrelation (Moran's I, Getis-Ord Gi*, Geary's C), IDW, GWR, weights
├── suitability/          # MCDA (AHP, Entropy, CRITIC) & Facility siting (MCLP, p-Median, LSCP)
├── resilience/           # Multi-hazard synthesis, Monte Carlo seismic debris, flood, wildfire, SVI
├── urban_morphology/     # Spacemate density matrix (FSI, GSI, L, OSR), fractal dimension
├── urban_physics/        # Frontal Area Index (FAI), canopy aerodynamic drag, surface albedo cooling
├── cellular_automata/    # SLEUTH urban growth simulation, Markov transition matrices
├── climate/              # Urban canopy carbon sequestration, green roof retention
├── mobility/             # BPR link impedance, Frank-Wolfe traffic assignment, Furness balancing
├── realestate/           # Spatial hedonic price models (OLS/SAR), TOD infrastructure uplift
├── generative/           # Recursive parcel subdivision, solar envelope volumes
└── engine/               # 28 headless embedded computation engines (air, hydro, syntax, transit, etc.)

💡 Quickstart & Code Examples

1. Spatial Accessibility & Equity (planx.spatial)

Calculate Enhanced Two-Step Floating Catchment Area (E2SFCA) and population-weighted Spatial Gini Inequality:

import numpy as np
from planx.spatial import enhanced_2sfca, spatial_equity_gini, gravity_accessibility

# Distance matrix: 3 neighborhood origins to 2 hospitals (in meters)
distances = np.array([
    [350.0, 1200.0],
    [800.0, 450.0],
    [1500.0, 2000.0]
])
hospital_beds = np.array([120.0, 250.0])
neighborhood_pop = np.array([1200.0, 3400.0, 1800.0])

# Compute E2SFCA Accessibility scores (1500m cutoff)
e2sfca_scores = enhanced_2sfca(
    d_matrix=distances,
    supply=hospital_beds,
    demand=neighborhood_pop,
    cutoff=1500.0,
    decay_method="exponential",
    beta=0.0015
)
print("E2SFCA Scores:", e2sfca_scores)

# Assess distribution equity via Gini Coefficient
gini = spatial_equity_gini(e2sfca_scores, neighborhood_pop)
print(f"Accessibility Gini Index: {gini:.4f}")

2. Spatial Autocorrelation & Hotspots (planx.geostats)

Generate spatial weights and compute Getis-Ord $G_i^*$ hotspot statistics:

import numpy as np
from planx.geostats import create_knn_weights, calculate_getis_ord_gi, idw_to_grid

# Spatial observations (e.g. air pollution levels)
coords = np.array([[10.0, 10.0], [12.0, 10.5], [11.0, 12.0], [50.0, 50.0]])
values = np.array([45.2, 48.0, 43.1, 12.5])
ids = [1, 2, 3, 4]

# Create k-Nearest Neighbor spatial weights
neighbors, weights = create_knn_weights(coords, ids, k=2)

# Calculate Hotspot Z-scores
gi_z, gi_p = calculate_getis_ord_gi(values, neighbors, weights, ids)
print("Getis-Ord Gi* Z-Scores:", gi_z)

# Interpolate to 2D raster grid via KDTree IDW
grid, x_coords, y_coords = idw_to_grid(coords, values, bbox=(0, 0, 60, 60), cell_size=2.0)
print("Interpolated Grid Shape:", grid.shape)

3. Multi-Criteria Siting & Optimization (planx.suitability)

Compute AHP (Analytic Hierarchy Process) criteria weights and solve the Maximal Covering Location Problem (MCLP):

import numpy as np
from planx.suitability import ahp_weights, greedy_mclp

# 1. AHP Pairwise Comparison Matrix
matrix = np.array([
    [1.0, 3.0, 5.0],
    [0.333, 1.0, 2.0],
    [0.2, 0.5, 1.0]
])
weights, cr = ahp_weights(matrix)
print("AHP Weights:", weights, "Consistency Ratio:", cr)

# 2. Greedy MCLP: Select K=2 emergency shelters to maximize covered population within 500m
candidates = np.array([[100.0, 100.0], [500.0, 500.0], [900.0, 900.0]])
demands = np.array([[120.0, 130.0], [480.0, 520.0], [890.0, 910.0], [200.0, 300.0]])
pop = np.array([250.0, 600.0, 450.0, 180.0])

selected, step_pop, cum_pop = greedy_mclp(candidates, demands, pop, max_distance=500.0, k=2)
print("Selected Shelter Indices:", selected)

4. Seismic Fragility & Disaster Simulation (planx.resilience)

Run a Monte Carlo seismic collapse simulation and synthesize multi-hazard vulnerability:

import numpy as np
from planx.resilience import (
    simulate_seismic_debris,
    multi_hazard_composite,
    equity_adjusted_priority
)

# Building inventory
areas = np.array([150.0, 300.0, 80.0, 450.0])   # Footprint areas (m²)
floors = np.array([5.0, 9.0, 2.0, 12.0])        # Story counts
years = np.array([1988, 1975, 2018, 1994])      # Construction year

# Monte Carlo Seismic Damage Simulation (Mw 7.4)
probs, collapsed, radii, volumes = simulate_seismic_debris(
    areas, floors, years, magnitude=7.4, seed=42
)
print("Collapse State:", collapsed)
print("Debris Impact Radii (m):", radii)

# Multi-Hazard Composite Synthesis with Social Vulnerability (SVI)
hazards = {"seismic": probs * 100.0, "flood": np.array([30.0, 80.0, 10.0, 65.0])}
svi = np.array([85.0, 90.0, 20.0, 60.0])

comp_scores, classes, dominant, diversity, drivers = multi_hazard_composite(hazards)
equity_scores, raw, factors, eq_classes = equity_adjusted_priority(comp_scores, svi, equity_weight=0.6)
print("Equity-Adjusted Priority Scores:", equity_scores)

5. Urban Morphology & Spacemate (planx.urban_morphology)

Classify urban fabric density using Spacemate (Berghauser Pont & Haupt, 2010):

from planx.urban_morphology import spacemate_density_matrix

# Calculate Spacemate density matrix
result = spacemate_density_matrix(fsi=2.4, gsi=0.4)
print("Typology:", result["typology"])
print("Open Space Ratio (OSR):", result["osr"])
print("Average Number of Layers:", result["layers"])

6. Traffic Assignment & Congestion (planx.mobility)

Model link congestion travel delay using the Bureau of Public Roads (BPR) function:

import numpy as np
from planx.mobility import bpr_link_performance_function

flows = np.array([1200.0, 1800.0])
capacities = np.array([1500.0, 1500.0])
free_time = np.array([3.0, 3.0])

# Congested link travel times
travel_times = bpr_link_performance_function(flows, capacities, free_time, alpha=0.15, beta=4.0)
print("Link Travel Times (minutes):", travel_times)

7. Quality and Decision Support Utilities (planx.quality)

Dependency-light utilities for turning spatial indicator arrays into reproducible summaries and decisions (weighted statistics, missing-value-safe classification, uncertainty estimation, Pareto screening):

import numpy as np
from planx.quality import (
    array_summary,
    bootstrap_mean_ci,
    classify_values,
    pareto_front,
)

values = np.array([12.0, 18.0, 25.0, np.nan])
summary = array_summary(values)
classes = classify_values(values, breaks=[15.0, 22.0])
mean, low, high = bootstrap_mean_ci(values, random_state=7)
front = pareto_front([[0.8, 12.0], [0.6, 9.0], [0.9, 15.0]], maximize=[True, False])

⚡ Performance & Benchmarks

PlanX SDK benchmarks on standard spatial datasets (Intel Core i9 / AMD Ryzen 9):

Operation Dataset Size Pure Python PlanX SDK (NumPy/SciPy) Acceleration
Getis-Ord $G_i^*$ Z-Scores 100,000 Points 2,450 ms 14.2 ms 172x faster
E2SFCA Accessibility Matrix 5,000 Origins $\times$ 500 Destinations 4,890 ms 21.6 ms 226x faster
CSR Dijkstra Shortest Paths 50,000 Nodes, 120,000 Edges 1,820 ms 18.4 ms 98x faster
Greedy MCLP Optimization 1,000 Candidates $\times$ 10,000 Demands 3,120 ms 29.8 ms 104x faster

🌐 Cloud & Microservice Integration (FastAPI Example)

Because PlanX SDK is 100% headless, building a high-throughput geospatial microservice is effortless:

from fastapi import FastAPI
from pydantic import BaseModel
import numpy as np
from planx.spatial import enhanced_2sfca

app = FastAPI(title="PlanX Headless Spatial API")

class AccessRequest(BaseModel):
    distances: list[list[float]]
    supply: list[float]
    demand: list[float]
    cutoff: float = 1200.0

@app.post("/api/v1/accessibility/e2sfca")
def compute_accessibility(req: AccessRequest):
    scores = enhanced_2sfca(
        d_matrix=np.array(req.distances),
        supply=np.array(req.supply),
        demand=np.array(req.demand),
        cutoff=req.cutoff
    )
    return {"status": "success", "accessibility_scores": scores.tolist()}

🧪 Tests and Quality Assurance

Execute the complete test suite locally:

pytest tests/ -v --cov=planx

Code formatting and type checking:

ruff check .
ruff format --check src tests
mypy src

📄 Academic Citation & References

If you use PlanX SDK in scientific research, academic publications, or urban resilience planning projects, please cite:

@software{planx_sdk_2026,
  author       = {Emino{\u{g}}lu, Yusuf},
  title        = {{PlanX SDK: Headless Spatial Analytics, Spatial Statistics, and Urban Resilience Engine}},
  year         = {2026},
  publisher    = {PyPI - Python Package Index},
  version      = {2.16.0},
  url          = {https://gitlab.com/geospacephilo/planx_sdk}
}

📜 License

Distributed under the MIT License. See LICENSE for more details.

Metadata

Release files for planx-sdk 2.27.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for planx-sdk 2.27.1
File Size Uploaded
planx_sdk-2.27.1.tar.gz 413.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for planx-sdk 2.27.1
File Interpreter ABI Platform
planx_sdk-2.27.1-py3-none-any.whl Python 3 none any Details

Total release size: 741.8 kB

Release files / planx_sdk-2.27.1.tar.gz

Download URL planx_sdk-2.27.1.tar.gz
Size 413.1 kB
Tags Source
SHA-256 checksum
How to use checksums
d64bb1c986edb117c42c8affe571371f04dc210780d4d95c087e12eb6e821dfb
BLAKE2b-256 checksum
How to use checksums
f2a853b191d506d6e31d0f14914d6aff66e17e70f46e61dea861b39c06cf4bbf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / planx_sdk-2.27.1-py3-none-any.whl

Download URL planx_sdk-2.27.1-py3-none-any.whl
Size 328.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bc58fe26f7945cbb6bc97e52a4ecbb258cbc7d958865f9b0271b42ca35f7da2c
BLAKE2b-256 checksum
How to use checksums
eb2b9047f1943999b15880072d41991f8a586393b330da125c96ef257dd117db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

2.27.1 This release

2 release files

2.17.0

2 release files

2.16.0

2 release files

2.15.0

2 release files

2.14.0

2 release files

2.13.0

2 release files

2.12.0

2 release files

2.11.0

2 release files

2.10.0

2 release files

2.9.2

2 release files

2.9.1

2 release files

2.9.0

2 release files

2.8.0

2 release files

2.7.0

2 release files

2.6.0

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.9.0

2 release files

0.4.0

2 release files

0.3.3

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page