Skip to main content

Python tools for X-minute accessibility, hex-based population mapping, and proximity-based urban planning.

Project description

accessX

Network-based accessibility analysis for X-minute cities, proximity planning, and urban opportunity mapping.

accessX is a Python library for studying what people can reach, how easily they can reach it, and how accessibility is distributed across places and populations.

The X can represent any network cost threshold: walking minutes, cycling time, distance, generalized cost, or a custom edge-weight measure.

Built on GeoPandas, OSMnx, NetworkX, H3, and rasterio, accessX provides a focused API for reproducible accessibility workflows without hiding the underlying geospatial data.

Healthcare accessibility across Amsterdam, Athens, and Milan

Design Principles

  • Plug-n-play, without locking you in: accessX provides ready-to-use methods for common accessibility workflows while keeping the underlying GeoDataFrames and OSMnx graphs available for customization.
  • Use the data you have: work with OSM POIs and WorldPop data, or provide your own destinations, capacities, population grids, demographic groups, and demand measures.
  • Define accessibility through the cost that matters: estimate walking accessibility with a standard average speed, use slope-sensitive travel time, or assign your own edge cost to an OSMnx graph for factors such as comfort, safety, effort, distance, or a generalized impedance.
  • Network-based by default: accessibility is calculated over the street graph rather than straight-line distance.
  • Transparent and composable: modules can be used independently, outputs remain reusable GeoDataFrames, and intermediate layers can be saved, inspected, and replaced.
  • Built for reproducible long-running analysis: retries, progress bars, clear errors, and graph/data persistence support workflows that can be rerun and audited.

What Can You Study?

  • How many services are reachable within 5, 10, or 15 minutes?
  • What is the network travel cost to the nearest healthcare facility or park?
  • How does accessibility change when nearby opportunities are weighted more strongly?
  • Where is service supply high or low relative to population demand?
  • How many people can access the same POI?
  • How evenly is accessibility distributed across neighborhoods or population groups?

Workflow

Area of interest
    -> H3 hex grid
    -> walking or cycling network
    -> edge travel costs
    -> OSM POIs and population demand
    -> accessibility scores
    -> co-accessibility and equity analysis

Isochrones are available as an optional communication and visualization layer.

Case Study Gallery

The case-study notebooks save their intermediate and final GeoDataFrames, so figures can be regenerated from existing outputs without rerunning network routing or data downloads.

Population demand aggregated to hexagons

Population demand is allocated to H3 hexagons and used as the demand surface for supply-demand accessibility models such as 2SFCA.

OpenStreetMap POI categories

OpenStreetMap features are grouped into analytical opportunity categories while preserving their original OSM tags and identifiers.

Sufficientarian accessibility scores

Equity workflows can summarize whether each origin satisfies a basket of minimum accessibility thresholds.

Age-group co-accessibility to Amsterdam parks and public squares

Co-accessibility identifies parks and public squares where children, adults, and older adults have walkable access, using Shannon diversity to highlight stronger potential intergenerational encounter opportunities.

Installation

pip install accessx

Python 3.10 or newer is required.

For local development:

pip install -e .

Quick Start

import accessx as acx
import osmnx as ox

# 1. Area of interest and origins
aoi = ox.geocode_to_gdf("Municipality of Athens, Greece")
hexes = acx.make_hex_grid(aoi, resolution=9)

# 2. Walking network and travel-time cost
graph = acx.build_network(
    aoi,
    city_epsg=2100,
    buffer_m=1000,
    network_type="walk",
    show_progress=True,
)
graph = acx.add_time_cost_constant_speed(
    graph,
    speed_kmh=4.5,
    cost_col="walk_time",
)

# 3. POIs with custom analytical categories backed by explicit OSM tags
pois = acx.get_pois_osm(
    aoi,
    poi_groups={
        "healthcare": {
            "amenity": ["pharmacy", "clinic", "doctors"],
        },
        "open_space": {
            "leisure": ["park", "playground", "garden"],
        },
    },
    show_progress=True,
)

# 4. Cumulative opportunities within 15 walking minutes
counts = acx.count_accessible_pois(
    graph,
    hexes.to_crs(2100),
    pois.to_crs(2100),
    max_cost=15,
    cost_attr="walk_time",
    show_progress=True,
)

Cost as the Routing Currency

The core accessibility functions route over any numeric edge cost on the network. accessX provides built-in helpers for common travel-cost definitions, such as constant-speed travel time and slope-sensitive walking time.

For other interpretations of cost, users can define their own edge-weight function with add_edge_cost. This makes it possible to route over custom measures such as distance, comfort penalties, safety scores, effort, or generalized impedance, as long as they are encoded as numeric edge costs.

For example, you can use a built-in travel-time helper:

graph = acx.add_time_cost_constant_speed(
    graph,
    speed_kmh=4.5,
    cost_col="walk_time",
)

Or define your own cost function:

def comfort_cost(edge):
    return edge["length"] * edge.get("comfort_penalty", 1.0)

graph = acx.add_edge_cost(
    graph,
    cost_fn=comfort_cost,
    cost_col="comfort_cost",
)

The same origins and destinations can then be evaluated through different definitions of accessibility simply by changing cost_attr.

Accessibility Models

Model Function Question Answered Typical Use
Cumulative opportunity measure count_accessible_pois How many opportunities can each origin reach within X cost? X-minute city and service proximity analysis
Nearest POI cost compute_nearest_poi_cost What is the minimum network cost to the nearest opportunity? Closest-service gaps and minimum burden
Hansen accessibility compute_hansen_accessibility How much opportunity is available when nearby destinations contribute more? Distance-decay accessibility surfaces
2SFCA / E2SFCA-like accessibility compute_2sfca_accessibility How strong is supply relative to accessible demand? Population-adjusted access to capacity or services
Co-accessibility compute_co_accessibility How many people can access each destination? Destination-side demand, exposure, and potential encounter analysis

All routing models support custom edge cost attributes and optional progress bars for long calculations.

Equity and Distribution

accessX includes tools for moving from accessibility scores to equity questions: who benefits, where thresholds are met, and how unevenly access is distributed.

A, P, gini, sorted_vals = acx.calculate_lorenz(
    ["count_healthcare", "nearest_cost_healthcare_1"],
    gdf,
    weights="population",
)

sufficient = acx.compute_sufficientarian_score(
    gdf,
    thresholds_ge={
        "count_healthcare": 1,
        "count_daily_needs": 3,
        "count_public_transport": 1,
    },
    thresholds_le={
        "nearest_cost_healthcare_1": 15,
    },
)

Lorenz/Gini workflows summarize inequality across places or population-weighted groups. Sufficientarian scores evaluate whether each origin meets explicit minimum accessibility standards.

Data Inputs

POIs and population are treated as transparent inputs to the accessibility models rather than hidden assumptions.

  • get_pois_osm queries explicit OSM tags or custom analytical groups, while preserving the original OSM keys, values, feature IDs, and geometries.
  • Population workflows can download and clip WorldPop rasters, convert rasters to vector grids, and aggregate one or more population-group columns to H3 hexagons.
  • Area-weighted overlap is used for population aggregation, so raster or polygon population cells are split proportionally across intersecting hexes.

Modules

accessx.cost

Define the travel cost used by network routing.

  • add_time_cost_constant_speed: add travel time using a constant speed
  • add_slope_based_time: create a Tobler hiking-time cost function
  • add_edge_cost: add any custom numeric edge cost

accessx.accessibility

Calculate origin-based and destination-based accessibility.

  • count_accessible_pois: cumulative opportunity measure by category
  • compute_nearest_poi_cost: nearest POI costs in list, long, or wide output formats
  • compute_hansen_accessibility: distance-decayed opportunity accessibility
  • compute_2sfca_accessibility: supply-demand catchment accessibility with binary or exponential decay
  • compute_co_accessibility: accessible population around each POI, using cumulative or Hansen-style decay

accessx.equity

Assess how accessibility is distributed.

  • calculate_lorenz: calculate Lorenz curves and Gini indices
  • plot_lorenz_curves: visualize accessibility distributions
  • compute_sufficientarian_score: score whether explicit accessibility thresholds are met
  • plot_sufficientarian_score: visualize score distributions and attainment levels

accessx.aoi

Prepare analysis areas and spatial origins.

  • load_aoi: load an AOI from a vector file or bounding box, optionally buffer and dissolve it
  • make_hex_grid: create an H3 hex grid over an AOI

accessx.graph

Build and persist OSM street networks.

  • build_network: download, clean, and project a walking, cycling, or other OSMnx network
  • save_graph: save graph nodes and edges
  • load_graph: rebuild a graph from saved node and edge files

accessx.poi

Collect and organize destinations from OpenStreetMap.

  • get_pois_osm: query explicit OSM tags or custom POI groups, with retries, reports, and progress
  • POIQueryError: raised when one or more OSM queries fail after retries

accessx.population

Prepare population demand data.

  • infer_country_from_geometry: identify the country intersecting an AOI or hex grid
  • get_worldpop_raster: download and optionally clip a WorldPop raster
  • raster_to_population_grid: convert raster cells into a vector population grid
  • map_population_to_hexes: aggregate raster population to hexes
  • map_population_grid_to_hexes: aggregate one or more population columns from a vector grid

accessx.isochrone

Create walksheds and isochrone geometries.

  • calculate_isochrones: generate one or more cost-threshold polygons per origin
  • Supports edges and hull polygon methods, serial or parallel execution, progress bars, and optional CSV export

accessx.io

Read and write GeoDataFrames.

  • read_gdf
  • save_gdf

Case Studies

The notebooks provide focused, reproducible examples:

License

accessX is released under the MIT License.

Relevant Research

The methods in accessX are connected to the following research and tools. Some works used related computational code, while others provide the conceptual or methodological basis for the library.

Co-Accessibility

Equity

Accessibility Models

  • Hansen, W. G. (1959). How accessibility shapes land use. Journal of the American Institute of Planners, 25(2), 73–76.
  • Luo, W., & Wang, F. (2003). Measures of spatial accessibility to health care in a GIS environment: Synthesis and a case study in the Chicago region. Environment and Planning B: Planning and Design, 30(6), 865–884.

Broader Concepts

  • Moreno, C., Allam, Z., Chabaud, D., Gall, C., & Pratlong, F. (2021). Introducing the “15-Minute City”: Sustainability, resilience and place identity in future post-pandemic cities. Smart Cities, 4(1), 93–111. https://doi.org/10.3390/smartcities4010006
  • Handy, S. (2020). Is accessibility an idea whose time has finally come? Transportation Research Part D: Transport and Environment, 83, 102319. https://doi.org/10.1016/j.trd.2020.102319

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

accessx-0.1.0.tar.gz (42.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

accessx-0.1.0-py3-none-any.whl (40.9 kB view details)

Uploaded Python 3

File details

Details for the file accessx-0.1.0.tar.gz.

File metadata

  • Download URL: accessx-0.1.0.tar.gz
  • Upload date:
  • Size: 42.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for accessx-0.1.0.tar.gz
Algorithm Hash digest
SHA256 68a7c7d7a4ddc34d815ce5bb70b81951272650e286f09b8efac7f8da97d04c52
MD5 624585c1db9aa0ad3e1469159e1e557c
BLAKE2b-256 f863ff6c56b53f444b337479f5dbb8c137a72bc37b5bedc882502df98e2484a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for accessx-0.1.0.tar.gz:

Publisher: workflow.yml on TransformTransport/accessX

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file accessx-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: accessx-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 40.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for accessx-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f54b723634500ddd1a6db729b2f0ee351bebf53c7d4d7eb266fb5b98892b091f
MD5 01ae0aa50cb59238d7d0e2f72be82e74
BLAKE2b-256 cc5fabd96450bbf8f98c5d29cc570cc1ca5393233d1c34d2c10840bc7f316b56

See more details on using hashes here.

Provenance

The following attestation bundles were made for accessx-0.1.0-py3-none-any.whl:

Publisher: workflow.yml on TransformTransport/accessX

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page