Overview G Core Inequality S Composite Scoring H Harmonization DataFrames CLI Reference
Docs / Getting Started / Introduction

Introduction to moveq

moveq is a fast, modular, and mathematically auditable Python toolkit for transport equity analysis, spatial justice auditing, and cross-country policy benchmarking.

It transforms raw municipal transit metrics (e.g. trips per neighborhood, morning peak frequency, evening coverage buffers) paired with spatial population arrays into population-weighted inequality coefficients, resilient composite scores, and validated cross-country questionnaire catalogues.

Core Mathematical Principle
In spatial justice and transport equity, transit service is a resource, population is the distribution weight, and socioeconomic indicators define priority ranks. moveq guarantees deterministic invariance against spatial zone reordering and tied rank deciles.

Design Philosophy

Unlike monolithic GIS toolboxes that require heavy C libraries (GDAL, GEOS, PROJ) or opaque spreadsheet formulas that fail silently when demographic columns are missing, moveq was built from first principles with four non-negotiable architectural invariants:

  • 1. Pure NumPy Zero-Bloat Core: The primary mathematical engine (moveq-core) depends strictly on NumPy. It imports in under 5 milliseconds and runs identically on laptops, embedded IoT routers, microservices, AWS Lambda, and browser WebAssembly.
  • 2. Continuous Boundary Slicing: Standard quantile binning produces erratic jumps when demographic zones cross the 40% or 90% population thresholds. moveq calculates exact continuous proportional splitting across boundary units.
  • 3. Graceful Renormalization Over Silent Padding: If an indicator (e.g., weekend night frequency) is missing from a dataset cut, moveq does NOT pad with zeros (which falsely penalizes scores). Instead, it drops the missing term and dynamically renormalizes the remaining design weights, generating an explicit note in the audit trail.
  • 4. Strict Harmonization Contracts: When comparing transit equity across borders (e.g., UK LSOAs vs. French IRIS zones vs. US Census Tracts), moveq-catalogue strictly validates whether each section is same, replace (with new title), or omit (with justification note).

Installation Options

moveq is packaged into modular distributions so you only install what you need:

Terminal pip / uv / conda
# 1. Full Stack: Core math + Composite Scoring + Catalogue + CLI + Pandas DataFrame helpers
pip install "moveq[cli,frames]"

# 2. Lightning-fast UV package manager
uv add "moveq[cli,frames]"

# 3. Pure NumPy Core Only (zero GIS/Pandas dependencies, < 50KB package size)
pip install moveq-core

# 4. Conda Forge Distribution
conda install -c conda-forge moveq

Quickstart Tutorial

Here is a complete, runnable example computing the Gini coefficient, Palma ratio, Wagstaff Concentration Index, and composite accessibility score:

quickstart.py Python 3.10+
import numpy as np
from moveq import (
    compute_gini,
    compute_palma_ratio,
    compute_concentration_index,
    compute_score,
)

# 1. Define municipal data for 5 spatial zones (e.g. Census Tracts or LSOAs)
trips_per_capita = np.array([10.0, 20.0, 5.0, 50.0, 8.0])
population = np.array([1000, 800, 1200, 300, 900])
deprivation_rank = np.array([1, 3, 2, 5, 4])  # 1 = most deprived neighborhood

# 2. Population-Weighted Gini Coefficient (Overall Inequality)
gini = compute_gini(trips_per_capita, population)
print(f"Gini Coefficient: {gini:.4f}")
# Output: Gini Coefficient: 0.3902

# 3. Continuous Boundary Palma Ratio (Top 10% vs Bottom 40%)
palma = compute_palma_ratio(trips_per_capita, population)
print(f"Palma Ratio: {palma:.4f}")
# Output: Palma Ratio: 7.0732

# 4. Wagstaff Concentration Index (Pro-Poor vs Pro-Rich Disparity)
ci = compute_concentration_index(trips_per_capita, deprivation_rank, population)
print(f"Concentration Index: {ci:.4f}")
# Output: Concentration Index: 0.2457 (> 0 indicates service favors less deprived areas)

# 5. Composite Accessibility Score (with missing term dropped)
score_result = compute_score(
    terms={
        "buffer_400m": 0.85,    # 85% coverage
        "evening_freq": 0.60,   # 60% standard
        "night_service": None,  # Data not collected in this city
    },
    weights={
        "buffer_400m": 0.50,
        "evening_freq": 0.30,
        "night_service": 0.20,
    },
    labels={
        "buffer_400m": "400m Transit Stop Access",
        "evening_freq": "Evening Service Frequency",
        "night_service": "24-Hour Night Transit",
    }
)

print(f"Composite Score: {score_result.score:.1f} / 100")
print(f"Audit Trail Note: {score_result.note}")
# Output:
# Composite Score: 75.6 / 100
# Audit Trail Note: 24-hour night transit not in this cut — weights renormalised.

Architecture & Module Matrix

The library is split into 4 decoupled subpackages under the moveq umbrella:

Package Primary Imports Purpose & Core Invariants
moveq-core moveq_core.equity
moveq_core.score
Pure NumPy engine for Gini, continuous Palma, Concentration Index, and composite scoring with dynamic weight renormalization.
moveq-catalogue moveq_catalogue.catalogue Harmonization registry enforcing explicit same / replace / omit questionnaire mapping for cross-country studies.
moveq import moveq Convenience top-level re-export package providing clean imports across all modules.
moveq-cli moveq command Standalone command-line interface for running equity audits on CSV files and JSON payloads in headless CI/CD pipelines.