networks
Compute network centralities. Two centrality methods are available, using shortest-path (metric) or simplest-path (angular) heuristics:
Metrics are specified as {name: expression} dicts using variables c (cost) and p (normalised progress). For shortest paths, c is metric distance and p = c / threshold. For simplest paths, c is angular cost and p is normalised time progress.
Four categories of metrics are supported:
- closeness: per-reached-node accumulation (e.g.
{"harmonic": "1/c", "density": "1"}) - betweenness: target seed weight in Brandes backpropagation (e.g.
{"betweenness": "1"}) - cycles: circuit rank (boolean flag)
- postprocess: derived from computed columns in Python (e.g.
{"hillier": "density**2 / farness"})
Pass None for defaults or {} to skip a category.
Per-node weight values (default 1.0, set on the nodes GeoDataFrame or read from NetworkX node attributes) apply gravity-style weighting to centrality: closeness weights each reachable node by its destination weight (so density becomes sum_j w_j rather than a plain count), and betweenness weights each origin-destination pair by the product of its endpoint weights. The same weighting is applied identically whether or not sampling is used. Land-use, mixed-use, and statistical aggregations are intentionally not node-weighted.
When segment_weighted=True, node weights are temporarily set to the primal edge (street segment) lengths so that centrality measures reflect total reachable street length rather than node counts (closeness by destination length, betweenness by the product of endpoint lengths). This is a convenience preset over the per-node weight mechanism and requires a dual graph representation.
When sample=True, only a subset of nodes are used as sources for centrality computation, with results corrected to approximate the full computation.
The reasons for picking one approach over another are varied:
- Columns prefixed
cc_are managed by cityseer: recomputing a metric for the same distance overwrites the matchingcc_columns in place (intended for re-runs). Don’t store your own data under this prefix. - Centralities can be distorted by messy graph topologies such as unnecessary intermediate points along streets
(used to describe road curvature) or overly complex representations of street intersections. Clean the network
first using the
graphmodule (see the automatic graph cleaning for examples). harmoniccentrality can produce inflated values when nodes are very close together, because the inverse-distance calculation amplifies small distances. This is more likely with simplest-path measures or short distance thresholds.- Simplest (angular) measures require a dual graph representation. Convert primal graphs with
graphs.nx_to_dualbefore ingesting them. - Metrics should only be compared across networks that use the same graph representation (both primal or both dual), because the differing number of nodes and edges between representations affects the metric values. For example, a four-way intersection consisting of one node with four edges on a primal graph translates to four nodes and six edges on the dual. This effect is amplified for denser regions of the network.
- Standard closeness and normalised closeness do not work well with distance-bounded analysis. Use harmonic closeness or Hillier normalisation instead.
centrality_shortest
Compute centrality using shortest paths with a single Dijkstra per source. Metrics are specified as {name: expression} dicts. Expressions use two variables:
c: the raw cost (metric distance in metres for shortest-path analysis)p: normalised progress from 0 at the source to 1 at the distance threshold (p = c / threshold)
Pass None for defaults or {} to skip a category.
Tip: compute only what you need — a smaller closeness / betweenness dict, {} to skip a whole category, or cycles=False — evaluates fewer expressions and emits fewer columns.
Parameters
A GeoDataFrame representing nodes. The outputs of calculations will be written to this GeoDataFrame.
Distance thresholds in metres at which to compute centrality measures.
Walking times in minutes; converted to distance thresholds using speed_m_s.
Closeness metric expressions. Each entry is {name: expr(c, p)}, accumulated per reached node. None uses defaults: density, farness, harmonic, decay.
Betweenness metric expressions. Each entry is {name: expr(c, p)}, used as the weight assigned to each destination when accumulating betweenness contributions along shortest paths. None uses defaults: betweenness, betweenness_decay.
If True, compute circuit rank (cycle count) for each node. Default True.
Derived metrics computed in Python from the closeness/betweenness results. None uses default: {"hillier": "density**2 / farness"}.
Speed in metres per second for converting minutes to distance thresholds.
Relative tolerance for betweenness path equality, as a percentage (e.g. 1.0 = 1%).
If True, weight by primal edge (street segment) lengths. Requires a dual graph.
Optional seed for reproducible sampling.
If True, enables adaptive sampling at longer distance thresholds.
Error tolerance for sampling. Defaults to sampling.HOEFFDING_EPSILON (0.05).
Returns
The input nodes_gdf parameter is returned with additional centrality columns.
Notes
from cityseer.tools import mock, graphs, io
from cityseer.metrics import networks
G = mock.mock_graph()
G = graphs.nx_simple_geoms(G)
nodes_gdf, edges_gdf, network_structure = io.network_structure_from_nx(G)
nodes_gdf = networks.centrality_shortest(
network_structure,
nodes_gdf,
distances=[400, 800],
)
print(nodes_gdf[["cc_harmonic_400", "cc_betweenness_800"]])
build_od_matrix
Build an OdMatrix from OD flow data and zone boundaries. Computes zone centroids, snaps them to the nearest network nodes, and constructs a sparse OD weight matrix for use with betweenness_od.
Parameters
Origin-destination flow data with columns for origin zone, destination zone, and weight.
Zone boundaries (polygons) or centroids (points). Must be in a projected CRS matching the network, or in EPSG
(will be auto-reprojected).The network to snap zone centroids to.
Column in od_df containing origin zone identifiers.
Column in od_df containing destination zone identifiers.
Column in od_df containing trip weights (e.g., number of bicycle commuters).
Column in zones_gdf containing zone identifiers matching origin_col/destination_col. If None, uses the GeoDataFrame index.
Maximum distance (in CRS units, typically metres) for snapping a centroid to a network node. Centroids beyond this distance are excluded with a warning.
Returns
Sparse OD matrix ready for use with betweenness_od.
betweenness_od
Compute OD-weighted betweenness centrality using the shortest path heuristic.
Parameters
A GeoDataFrame representing nodes. The outputs of calculations will be written to this GeoDataFrame.
An OdMatrix mapping (origin, destination) node pairs to trip weights. Build with build_od_matrix.
Distance thresholds in metres at which to compute betweenness.
Walking times in minutes; converted to distance thresholds using speed_m_s.
Betweenness metric expressions. None uses defaults: betweenness, betweenness_decay.
Speed in metres per second for converting minutes to distance thresholds.
Relative tolerance for path equality, as a percentage.
Returns
The input nodes_gdf parameter is returned with additional betweenness columns.
betweenness_demand
Compute demand-weighted (flow) betweenness from a spatial interaction model. Trips are allocated between weighted origins (e.g. population) and weighted destinations (e.g. attractors) using a singly (origin-)constrained spatial interaction model, then routed along shortest network paths so that intermediate nodes accumulate the flow that passes through them. For each origin :math:o and reachable destination :math:d the allocated flow is
.. math:: W_{od} = W_o \cdot \frac{W_d \cdot f(c_{od})}{\sum_{d’} W_{d’} \cdot f(c_{od’})}
where :math:f is decay_fn and :math:c_{od} is the network distance. Each origin’s full weight is conserved and distributed across reachable destinations (destination totals are not constrained — that would require a doubly-constrained / Furness model). The gravity model is the classic instance of this form, recovered with an exponential decay_fn.
This is the modelled-matrix counterpart to betweenness_od: rather than supplying an explicit OD matrix, the per-pair weights are derived from the network distances revealed during routing, computed in a single traversal per origin.
Parameters
A nodes GeoDataFrame; flow betweenness columns are written to it and it is returned.
A GeoDataFrame of demand origins (points or centroids).
A GeoDataFrame of demand destinations / attractors (points or centroids).
Column in origins_gdf giving each origin’s weight (e.g. population).
Column in destinations_gdf giving each destination’s attractiveness weight.
Distance thresholds in metres at which to compute flow betweenness.
Walking times in minutes; converted to distance thresholds using speed_m_s.
Distance-decay expression for the allocation, using c (metric cost) and p (normalised progress = c / threshold). Defaults to "exp(-4 * p)" (scale-free, re-normalised per threshold). For a classic gravity model on absolute distance use e.g. "exp(-0.002 * c)".
If True, each origin routes its full weight to its single nearest reachable destination instead of allocating across all of them.
Name used for the output column (cc_{metric_name}_{distance}). Defaults to "demand".
Maximum distance for snapping origin/destination points to network nodes. Points farther than this are dropped (with a logged count).
Speed in metres per second for converting minutes to distance thresholds.
Relative tolerance for shortest-path equality, as a percentage.
Returns
The input nodes_gdf with a flow-betweenness column added per distance threshold.
centrality_simplest
Compute centrality using simplest (angular) paths with a single Dijkstra per source. Expressions use c (angular cost) and p (normalised time progress).
Tip: compute only what you need — pass a smaller closeness / betweenness dict, or {} to skip a whole category — to evaluate fewer expressions and emit fewer columns.
Parameters
A GeoDataFrame representing nodes. The outputs of calculations will be written to this GeoDataFrame.
Distance thresholds in metres at which to compute centrality measures.
Walking times in minutes; converted to distance thresholds using speed_m_s.
Closeness metric expressions. None uses defaults: density, farness, harmonic.
Betweenness metric expressions. None uses defaults: betweenness.
Derived metrics. None uses default: {"hillier": "density**2 / farness"}.
Speed in metres per second for converting minutes to distance thresholds.
Relative tolerance for angular betweenness path equality, as a percentage.
If True, weight by primal edge (street segment) lengths. Requires a dual graph.
Optional seed for reproducible sampling.
If True, enables adaptive sampling at longer distance thresholds.
Error tolerance for sampling. Defaults to sampling.HOEFFDING_EPSILON (0.05).
Returns
The input nodes_gdf parameter is returned with additional centrality columns.
Notes
from cityseer.tools import mock, graphs, io
from cityseer.metrics import networks
G = mock.mock_graph()
G = graphs.nx_simple_geoms(G)
G_dual = graphs.nx_to_dual(G)
nodes_gdf, edges_gdf, network_structure = io.network_structure_from_nx(G_dual)
nodes_gdf = networks.centrality_simplest(
network_structure,
nodes_gdf,
distances=[400, 800],
)
print(nodes_gdf[["cc_harmonic_400_ang", "cc_betweenness_800_ang"]])
closeness_shortest
Compute closeness centrality using shortest paths. Wraps centrality_shortest with betweenness disabled.
closeness_simplest
Compute closeness centrality using simplest (angular) paths. Wraps centrality_simplest with betweenness disabled.
betweenness_shortest
Compute betweenness centrality using shortest paths. Wraps centrality_shortest with closeness disabled.
betweenness_simplest
Compute betweenness centrality using simplest (angular) paths. Wraps centrality_simplest with closeness disabled.
node_centrality_shortest
Deprecated 4.24 alias for centrality_shortest.
Deprecated
Since version 5.0. Use centrality_shortest with closeness / betweenness expression dicts. This shim preserves
the 4.24 output (columns cc_density, cc_farness, cc_harmonic, cc_beta, cc_cycles,
cc_hillier, cc_betweenness, cc_betweenness_beta) and will be removed in a future major release.
See COMPATIBILITY.md.
node_centrality_simplest
Deprecated 4.24 alias for centrality_simplest.
Deprecated
Since version 5.0. Use centrality_simplest with closeness / betweenness expression dicts. This shim preserves the
4.24 output (angular columns cc_density_ang, cc_farness_ang, cc_harmonic_ang, cc_hillier_ang,
cc_betweenness_ang) and will be removed in a future major release. See COMPATIBILITY.md.
segment_centrality
Removed in 5.0; raises with guidance.
Deprecated
Since version 5.0. The continuous-segment engine (segment_density / harmonic / beta / betweenness) was removed
at the low level, so the old numbers cannot be reproduced. The nearest equivalent is
centrality_shortest(..., segment_weighted=True) — a different calculation. See COMPATIBILITY.md.