Skip to content

Utils Module

The utils module provides core utility functions for graph conversion, validation, and visualization.

Core Utilities Module.

This module provides essential utilities for graph conversion, data validation, and spatial analysis operations. It serves as the foundation for the city2graph package, offering a standardized data format for handling geospatial relations across GeoPandas, NetworkX objects, and eventually PyTorch Geometric objects. The module enables seamless integration between different graph representations and geospatial data formats through robust data structures and conversion functions.

Functions:

Name Description
gdf_to_nx

Convert GeoDataFrames of nodes and edges to a NetworkX graph.

nx_to_gdf

Convert a NetworkX graph to GeoDataFrames for nodes and/or edges.

nx_to_rx

Convert a NetworkX graph to a rustworkx graph.

rx_to_nx

Convert a rustworkx graph to a NetworkX graph.

validate_gdf

Validate node and edge GeoDataFrames with type detection.

validate_nx

Validate a NetworkX graph with comprehensive type checking.

canonicalize_edges

Canonicalize an edge GeoDataFrame to one deterministic row per undirected pair.

symmetrize_edges

Symmetrize an edge GeoDataFrame by adding the reverse row of each edge.

dual_graph

Convert a primal graph represented by nodes and edges GeoDataFrames to its dual graph.

filter_graph_by_distance

Filter a graph to include only elements within a specified threshold from a center point.

create_tessellation

Create tessellations from given geometries, with optional barriers.

create_isochrone

Generate an isochrone polygon from a graph.

plot_graph

Plot a graph with a unified interface.

clip_graph

Clip a graph to a specific area.

remove_isolated_components

Keep only the largest connected component of a graph.

gdf_to_nx

gdf_to_nx(
    nodes=None, edges=None, keep_geom=True, multigraph=False, directed=False
)

Convert GeoDataFrames of nodes and edges to a NetworkX graph.

This function provides a high-level interface to convert geospatial data, represented as GeoDataFrames, into a NetworkX graph. It supports both homogeneous and heterogeneous graphs.

For homogeneous graphs, provide a single GeoDataFrame for nodes and edges. For heterogeneous graphs, provide dictionaries mapping type names to GeoDataFrames.

Parameters:

Name Type Description Default
nodes GeoDataFrame or dict[str, GeoDataFrame]

Node data. For homogeneous graphs, a single GeoDataFrame. For heterogeneous graphs, a dictionary mapping node type names to GeoDataFrames. Node IDs are taken from the GeoDataFrame index.

None
edges GeoDataFrame or dict[tuple[str, str, str], GeoDataFrame]

Edge data. For homogeneous graphs, a single GeoDataFrame. For heterogeneous graphs, a dictionary mapping edge type tuples (source_type, relation_type, target_type) to GeoDataFrames. Edge relationships are defined by a MultiIndex on the edge GeoDataFrame (source ID, target ID). For MultiGraphs, a third level in the index can be used for edge keys.

None
keep_geom bool

If True, the geometry of the nodes and edges GeoDataFrames will be preserved as attributes in the NetworkX graph.

True
multigraph bool

If True, a networkx.MultiGraph is created, which can store multiple edges between the same two nodes.

False
directed bool

If True, a directed graph (networkx.DiGraph or networkx.MultiDiGraph) is created. Otherwise, an undirected graph is created.

False

Returns:

Type Description
Graph or MultiGraph or DiGraph or MultiDiGraph

A NetworkX graph object representing the spatial network. Graph-level metadata, such as CRS and heterogeneity information, is stored in graph.graph.

See Also

nx_to_gdf : Convert a NetworkX graph back to GeoDataFrames.

Examples:

>>> # Homogeneous graph
>>> import geopandas as gpd
>>> import pandas as pd
>>> from shapely.geometry import Point, LineString
>>> nodes_gdf = gpd.GeoDataFrame(
...     geometry=[Point(0, 0), Point(1, 1)],
...     index=pd.Index([10, 20], name="node_id")
... )
>>> edges_gdf = gpd.GeoDataFrame(
...     {"length": [1.414]},
...     geometry=[LineString([(0, 0), (1, 1)])],
...     index=pd.MultiIndex.from_tuples([(10, 20)], names=["u", "v"])
... )
>>> G = gdf_to_nx(nodes=nodes_gdf, edges=edges_gdf)
>>> print(G.nodes(data=True))
>>> [(0, {'geometry': <POINT (0 0)>,
...       '_original_index': 10,
...       'pos': (0.0, 0.0)}),
...  (1, {'geometry': <POINT (1 1)>,
...       '_original_index': 20,
...       'pos': (1.0, 1.0)})]
>>> print(G.edges(data=True))
>>> [(0, 1, {'length': 1.414,
...          'geometry': <LINESTRING (0 0, 1 1)>,
...          '_original_edge_index': (10, 20)})]
>>> # Heterogeneous graph
>>> buildings_gdf = gpd.GeoDataFrame(geometry=[Point(0, 0)], index=pd.Index(['b1'], name="b_id"))
>>> streets_gdf = gpd.GeoDataFrame(geometry=[Point(1, 1)], index=pd.Index(['s1'], name="s_id"))
>>> connections_gdf = gpd.GeoDataFrame(
...     geometry=[LineString([(0,0), (1,1)])],
...     index=pd.MultiIndex.from_tuples([('b1', 's1')])
... )
>>> nodes_dict = {"building": buildings_gdf, "street": streets_gdf}
>>> edges_dict = {("building", "connects_to", "street"): connections_gdf}
>>> H = gdf_to_nx(nodes=nodes_dict, edges=edges_dict)
>>> print(H.nodes(data=True))
>>> [(0, {'geometry': <POINT (0 0)>,
...       'node_type': 'building',
...       '_original_index': 'b1',
...       'pos': (0.0, 0.0)}),
...  (1, {'geometry': <POINT (1 1)>,
...       'node_type': 'street',
...       '_original_index': 's1',
...       'pos': (1.0, 1.0)})]
>>> print(H.edges(data=True))
>>> [(0, 1, {'geometry': <LINESTRING (0 0, 1 1)>,
...          'full_edge_type': ('building', 'connects_to', 'street'),
...          '_original_edge_index': ('b1', 's1')})]

nx_to_gdf

nx_to_gdf(G, nodes=True, edges=True, set_missing_pos_from=('x', 'y'))

Convert a NetworkX graph to GeoDataFrames for nodes and/or edges.

This function reconstructs GeoDataFrames from a NetworkX graph that was created by gdf_to_nx or follows a similar structure. It can handle both homogeneous and heterogeneous graphs, extracting node and edge attributes and reconstructing geometries from position data.

Parameters:

Name Type Description Default
G Graph or MultiGraph

The NetworkX graph to convert. It is expected to have metadata stored in G.graph to guide the conversion, including CRS and heterogeneity information. Node positions are expected in a 'pos' attribute.

required
nodes bool

If True, a GeoDataFrame for nodes will be created and returned.

True
edges bool

If True, a GeoDataFrame for edges will be created and returned.

True
set_missing_pos_from tuple[str, ...] | None

If provided (or None implies ("x", "y")) set missing node 'pos' from the given attribute name(s). With two names use them as x/y; with one name expect a 2-length coordinate.

("x", "y")

Returns:

Type Description
GeoDataFrame or tuple

The reconstructed GeoDataFrames. The return type depends on the graph structure (homogeneous vs heterogeneous) and the requested components (nodes, edges).

Homogeneous Graphs:

  • If nodes=True and edges=True: Returns (nodes_gdf, edges_gdf) where both are geopandas.GeoDataFrame.
  • If only nodes=True: Returns nodes_gdf (geopandas.GeoDataFrame).
  • If only edges=True: Returns edges_gdf (geopandas.GeoDataFrame).

Heterogeneous Graphs:

  • Returns (nodes_dict, edges_dict) where:

    • nodes_dict is dict[str, geopandas.GeoDataFrame] mapping node types to GeoDataFrames.
    • edges_dict is dict[tuple[str, str, str], geopandas.GeoDataFrame] mapping edge types to GeoDataFrames.

Note: For heterogeneous graphs, the return value is always a tuple of dictionaries, even if only one component is requested (the other will be an empty dict).

Raises:

Type Description
ValueError

If both nodes and edges are False.

See Also

gdf_to_nx : Convert GeoDataFrames to a NetworkX graph.

Examples:

>>> import networkx as nx
>>> # Create a simple graph with spatial attributes
>>> G = nx.Graph(is_hetero=False, crs="EPSG:4326")
>>> G.add_node(0, pos=(0, 0), population=100, geometry=Point(0,0))
>>> G.add_node(1, pos=(1, 1), population=200, geometry=Point(1,1))
>>> G.add_edge(0, 1, weight=1.5, geometry=LineString([(0, 0), (1, 1)]))
>>> # Convert back to GeoDataFrames
>>> nodes_gdf, edges_gdf = nx_to_gdf(G)
>>> print(nodes_gdf)
>>> print(edges_gdf)
>>>           population     geometry
... 0         100           POINT (0 0)
... 1         200           POINT (1 1)
...           weight        geometry
... 0 1       1.5           LINESTRING (0 0, 1 1)

nx_to_rx

nx_to_rx(graph)

Convert a NetworkX graph to a rustworkx graph.

This function converts a NetworkX graph object into a rustworkx graph object, preserving node, edge, and graph attributes. It handles both directed and undirected graphs, as well as multigraphs.

Parameters:

Name Type Description Default
graph Graph or MultiGraph

The NetworkX graph to convert.

required

Returns:

Type Description
PyGraph or PyDiGraph

The converted rustworkx graph.

See Also

rx_to_nx : Convert a rustworkx graph back to NetworkX.

Examples:

>>> rx_G = nx_to_rx(G)

rx_to_nx

rx_to_nx(graph)

Convert a rustworkx graph to a NetworkX graph.

This function converts a rustworkx graph object into a NetworkX graph object, restoring node, edge, and graph attributes.

Parameters:

Name Type Description Default
graph PyGraph or PyDiGraph

The rustworkx graph to convert.

required

Returns:

Type Description
Graph or MultiGraph

The converted NetworkX graph.

See Also

nx_to_rx : Convert a NetworkX graph to rustworkx.

Examples:

>>> # Assuming rx_G is a rustworkx graph
>>> nx_G = rx_to_nx(rx_G)

validate_gdf

validate_gdf(nodes_gdf=None, edges_gdf=None, allow_empty=True)

Validate node and edge GeoDataFrames with type detection.

This function validates both homogeneous and heterogeneous GeoDataFrame inputs, performs type checking, and determines whether the input represents a heterogeneous graph structure.

Parameters:

Name Type Description Default
nodes_gdf GeoDataFrame or dict[str, GeoDataFrame]

The GeoDataFrame containing node data to validate, or a dictionary mapping node type names to GeoDataFrames for heterogeneous graphs.

None
edges_gdf GeoDataFrame or dict[tuple[str, str, str], GeoDataFrame]

The GeoDataFrame containing edge data to validate, or a dictionary mapping edge type tuples to GeoDataFrames for heterogeneous graphs.

None
allow_empty bool

If True, allows the GeoDataFrames to be empty. If False, raises an error.

True

Returns:

Type Description
tuple

A tuple containing:

  • validated nodes_gdf (same type as input)
  • validated edges_gdf (same type as input)
  • is_hetero: boolean indicating if this is a heterogeneous graph

Raises:

Type Description
TypeError

If an input is not a GeoDataFrame or appropriate dictionary type.

ValueError

If the input types are inconsistent or invalid.

See Also

validate_nx : Validate a NetworkX graph.

Examples:

>>> import geopandas as gpd
>>> from shapely.geometry import Point, LineString
>>> nodes = gpd.GeoDataFrame(geometry=[Point(0, 0)])
>>> edges = gpd.GeoDataFrame(geometry=[LineString([(0, 0), (1, 1)])])
>>> try:
...     validated_nodes, validated_edges, is_hetero = validate_gdf(nodes, edges)
...     print(f"Validation successful. Heterogeneous: {is_hetero}")
... except (TypeError, ValueError) as e:
...     print(f"Validation failed: {e}")
Validation successful. Heterogeneous: False

validate_nx

validate_nx(graph)

Validate a NetworkX graph with comprehensive type checking.

Checks if the input is a NetworkX graph, ensures it is not empty (i.e., it has both nodes and edges), and verifies that it contains the necessary metadata for conversion back to GeoDataFrames or PyG objects.

Parameters:

Name Type Description Default
graph Graph or MultiGraph

The NetworkX graph to validate.

required

Returns:

Type Description
None

This function does not return a value.

Raises:

Type Description
TypeError

If the input is not a NetworkX graph.

ValueError

If the graph has no nodes, no edges, or is missing essential metadata.

See Also

validate_gdf : Validate GeoDataFrames for graph conversion.

Examples:

>>> import networkx as nx
>>> from shapely.geometry import Point
>>> G = nx.Graph(is_hetero=False, crs="EPSG:4326")
>>> G.add_node(0, pos=(0, 0))
>>> G.add_node(1, pos=(1, 1))
>>> G.add_edge(0, 1)
>>> try:
...     validate_nx(G)
...     print("Validation successful.")
... except (TypeError, ValueError) as e:
...     print(f"Validation failed: {e}")
Validation successful.

canonicalize_edges

canonicalize_edges(edges, duplicates='first')

Canonicalize an edge GeoDataFrame to one deterministic row per undirected pair.

Reorders the first two MultiIndex levels (source, target) of every non-self-loop edge into a deterministic canonical order, so reciprocal rows (u, v) and (v, u) — the typical shape of bidirectional roads exported from a directed source such as an OSMnx MultiDiGraph — map onto the same unordered key. Attributes and geometry of each row are left untouched; only the index values change (geometries are NOT reversed). Self-loops are returned unchanged.

Rows that share the same unordered key after canonicalization are handled according to duplicates.

Parameters:

Name Type Description Default
edges GeoDataFrame

Edge GeoDataFrame with a two-level (source, target) or three-level (source, target, key) MultiIndex. For heterogeneous graphs, call this function separately on each edge type's GeoDataFrame.

required
duplicates (first, key, error)

How to handle rows sharing the same unordered key after canonicalization:

  • "first": keep the first occurrence and drop the rest. For three-level input the key level participates in the comparison, so distinct parallel keys are preserved.
  • "key": keep all rows and (re)generate an integer key level per unordered pair, producing a valid three-level multigraph index.
  • "error": raise ValueError reporting the offending pairs.
"first"

Returns:

Type Description
GeoDataFrame

The canonicalized edge GeoDataFrame. Row order, columns, attributes, geometry, and CRS are preserved (apart from rows dropped by duplicates="first"). Index level names are kept positionally: level 0 keeps its original name even where values were swapped.

Raises:

Type Description
ValueError

If the index is not a MultiIndex with at least two levels, if duplicates is not a recognized option, or if duplicate unordered keys remain and duplicates="error".

See Also

symmetrize_edges : Inverse operation adding the reverse row of each edge. gdf_to_pyg : Convert GeoDataFrames to PyTorch Geometric objects. segments_to_graph : Convert LineString segments to a graph structure.

Notes

Node identifiers are ordered with a vectorized comparison when they are mutually comparable (e.g. all integers or all strings). For mixed, non-comparable identifier types the order falls back to first-appearance codes, which is deterministic for a given input but input-dependent.

Examples:

>>> import geopandas as gpd
>>> import pandas as pd
>>> from shapely.geometry import LineString
>>> index = pd.MultiIndex.from_tuples([(0, 1), (1, 0)], names=["u", "v"])
>>> edges = gpd.GeoDataFrame(
...     {"name": ["ab", "ba"]},
...     geometry=[LineString([(0, 0), (1, 1)]), LineString([(1, 1), (0, 0)])],
...     index=index,
...     crs="EPSG:32633",
... )
>>> canonicalize_edges(edges).index.tolist()
[(0, 1)]
>>> canonicalize_edges(edges, duplicates="key").index.tolist()
[(0, 1, 0), (0, 1, 1)]

symmetrize_edges

symmetrize_edges(edges)

Symmetrize an edge GeoDataFrame by adding the reverse row of each edge.

For every non-self-loop edge (u, v) whose reverse (v, u) is not already present, appends a row indexed (v, u) with the same attributes and a reversed geometry, so that each row's geometry starts at its source node. This makes neighbourhood queries on the MultiIndex complete (e.g. edges.xs(node, level=0) returns every neighbour of node), at the cost of duplicating edge attributes and geometries. Self-loops and edges whose reverse already exists are left untouched, so the operation is idempotent. Three-level (source, target, key) multigraph indexes keep the key of the original row on the reverse row.

This is the inverse operation of :func:canonicalize_edges.

Parameters:

Name Type Description Default
edges GeoDataFrame

Edge GeoDataFrame with a two-level (source, target) or three-level (source, target, key) MultiIndex. For heterogeneous graphs, call this function separately on each edge type's GeoDataFrame.

required

Returns:

Type Description
GeoDataFrame

The symmetrized edge GeoDataFrame. Original rows come first with columns, attributes, and CRS preserved; reverse rows are appended in the order of the rows they mirror. Index level names are kept positionally.

Raises:

Type Description
ValueError

If the index is not a MultiIndex with at least two levels.

See Also

canonicalize_edges : Inverse operation collapsing reciprocal rows. gdf_to_pyg : Convert GeoDataFrames to PyTorch Geometric objects.

Notes

gdf_to_pyg(..., directed=False) rejects edge tables containing both (u, v) and (v, u) rows as ambiguous. Collapse a symmetrized table with :func:canonicalize_edges first, or pass directed=True to keep the reciprocal rows as directed edges.

Examples:

>>> import geopandas as gpd
>>> import pandas as pd
>>> from shapely.geometry import LineString
>>> index = pd.MultiIndex.from_tuples([(0, 1)], names=["u", "v"])
>>> edges = gpd.GeoDataFrame(
...     {"name": ["ab"]},
...     geometry=[LineString([(0, 0), (1, 1)])],
...     index=index,
...     crs="EPSG:32633",
... )
>>> symmetrize_edges(edges).index.tolist()
[(0, 1), (1, 0)]

dual_graph

dual_graph(
    graph,
    edge_id_col=None,
    keep_original_geom=False,
    source_col=None,
    target_col=None,
    as_nx=False,
)

Convert a primal graph represented by nodes and edges GeoDataFrames to its dual graph.

In the dual graph, original edges become nodes and original nodes become edges connecting adjacent original edges.

Parameters:

Name Type Description Default
graph tuple[GeoDataFrame, GeoDataFrame] or Graph or MultiGraph

A graph containing nodes and edges GeoDataFrames or a NetworkX graph of the primal graph.

required
edge_id_col str

The name of the column in the edges GeoDataFrame to be used as unique identifiers for dual graph nodes. If None, the index of the edges GeoDataFrame is used. Default is None.

None
keep_original_geom bool

If True, preserve the original geometry of the edges in a new column named 'original_geometry' in the dual nodes GeoDataFrame.

False
source_col str

Name of the column or index level representing the source node ID in the edges GeoDataFrame. If provided, it overrides automatic detection.

None
target_col str

Name of the column or index level representing the target node ID in the edges GeoDataFrame. If provided, it overrides automatic detection.

None
as_nx bool

If True, return the dual graph as a NetworkX graph instead of GeoDataFrames.

False

Returns:

Type Description
tuple[GeoDataFrame, GeoDataFrame]

A tuple containing the nodes and edges of the dual graph as GeoDataFrames.

  • Dual nodes GeoDataFrame: Nodes represent original edges. The geometry is the centroid of the original edge's geometry. The index is derived from edge_id_col or the original edge index.
  • Dual edges GeoDataFrame: Edges represent adjacency between original edges (i.e., they shared a node in the primal graph). The geometry is a LineString connecting the centroids of the two dual nodes. The index is a MultiIndex of the connected dual node IDs.
See Also

segments_to_graph : Convert LineString segments to a graph structure.

Examples:

>>> import geopandas as gpd
>>> import pandas as pd
>>> from shapely.geometry import Point, LineString
>>> # Primal graph nodes
>>> nodes = gpd.GeoDataFrame(
...     {"node_id": [0, 1, 2]},
...     geometry=[Point(0, 0), Point(1, 1), Point(1, 0)],
...     crs="EPSG:32633"
... ).set_index("node_id")
>>> # Primal graph edges
>>> edges = gpd.GeoDataFrame(
...     {"u": [0, 1], "v": [1, 2]},
...     geometry=[LineString([(0, 0), (1, 1)]), LineString([(1, 1), (1, 0)])],
...     crs="EPSG:32633"
... )
>>> # Convert to dual graph
>>> dual_nodes, dual_edges = dual_graph((nodes, edges))

filter_graph_by_distance

filter_graph_by_distance(
    graph, center_point, threshold, edge_attr="length", node_id_col=None
)

Filter a graph to include only elements within a specified threshold from a center point.

This function calculates the shortest path from a center point to all nodes in the graph and returns a subgraph containing only the nodes (and their induced edges) that are within the given threshold. The input can be a NetworkX graph or an edges GeoDataFrame.

Parameters:

Name Type Description Default
graph GeoDataFrame or Graph or MultiGraph

The graph to filter. If a GeoDataFrame, it represents the edges of the graph and will be converted to a NetworkX graph internally.

required
center_point Point or Sequence[Point] or GeoSeries or GeoDataFrame

The origin point(s) for the distance calculation. If multiple points are provided, the filter will include nodes reachable from any of them.

required
threshold float

The maximum shortest-path distance (or cost) for a node to be included in the filtered graph.

required
edge_attr str

The name of the edge attribute to use as weight for shortest path calculations (e.g., 'length', 'travel_time').

"length"
node_id_col str

The name of the node identifier column if the input graph is a GeoDataFrame. Defaults to the index.

None

Returns:

Type Description
GeoDataFrame or Graph or MultiGraph

The filtered subgraph. The return type matches the input graph type. If the input was a GeoDataFrame, the output is a GeoDataFrame of the filtered edges.

See Also

create_isochrone : Generate an isochrone polygon from a graph.

Examples:

>>> import networkx as nx
>>> from shapely.geometry import Point
>>> # Create a graph
>>> G = nx.Graph()
>>> G.add_node(0, pos=(0, 0))
>>> G.add_node(1, pos=(10, 0))
>>> G.add_node(2, pos=(20, 0))
>>> G.add_edge(0, 1, length=10)
>>> G.add_edge(1, 2, length=10)
>>> # Filter the graph
>>> center = Point(1, 0)
>>> filtered_graph = filter_graph_by_distance(G, center, threshold=12)
>>> print(list(filtered_graph.nodes))
>>> [0, 1]

create_tessellation

create_tessellation(
    geometry,
    primary_barriers=None,
    shrink=0.4,
    segment=0.5,
    threshold=0.05,
    n_jobs=-1,
    limit=None,
    **kwargs
)

Create tessellations from given geometries, with optional barriers.

This function generates either morphological or enclosed tessellations based on the input geometries. If primary_barriers are provided, it creates an enclosed tessellation; otherwise, it generates a morphological tessellation.

Parameters:

Name Type Description Default
geometry GeoDataFrame or GeoSeries

The geometries (typically building footprints) to tessellate around.

required
primary_barriers GeoDataFrame or GeoSeries

Geometries (typically road network) to use as barriers for enclosed tessellation. If provided, momepy.enclosed_tessellation is used. Default is None.

None
shrink float

The distance to shrink the geometry for the skeleton endpoint generation. Passed to momepy.morphological_tessellation or momepy.enclosed_tessellation.

0.4
segment float

The segment length for discretizing the geometry. Passed to momepy.morphological_tessellation or momepy.enclosed_tessellation.

0.5
threshold float

The threshold for snapping skeleton endpoints to the boundary. Only used for enclosed tessellation.

0.05
n_jobs int

The number of jobs to use for parallel processing. -1 means using all available processors. Only used for enclosed tessellation.

-1
limit geopandas.GeoDataFrame, geopandas.GeoSeries, shapely geometry, or None

Boundary passed to momepy.enclosures for enclosed tessellation. When None, a buffered convex hull of input geometry and barriers is computed.

None
**kwargs object

Additional keyword arguments passed to the underlying momepy tessellation function.

{}

Returns:

Type Description
GeoDataFrame

A GeoDataFrame containing the tessellation cells as polygons. Each cell has a unique tess_id.

Raises:

Type Description
ValueError

If primary_barriers are not provided and the geometry is in a geographic CRS (e.g., EPSG:4326), as morphological tessellation requires a projected CRS.

See Also

momepy.morphological_tessellation : Generate morphological tessellation. momepy.enclosed_tessellation : Generate enclosed tessellation.

Examples:

>>> import geopandas as gpd
>>> from shapely.geometry import Polygon
>>> # Create some building footprints
>>> buildings = gpd.GeoDataFrame(
...     geometry=[Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]),
...               Polygon([(2, 2), (3, 2), (3, 3), (2, 3)])],
...     crs="EPSG:32633"
... )
>>> # Generate morphological tessellation
>>> tessellation = create_tessellation(buildings)
>>> print(tessellation.head())
>>> # Generate enclosed tessellation with roads as barriers
>>> from shapely.geometry import LineString
>>> roads = gpd.GeoDataFrame(
...     geometry=[LineString([(0, -1), (3, -1)]), LineString([(1.5, -1), (1.5, 4)])],
...     crs="EPSG:32633"
... )
>>> enclosed_tess = create_tessellation(buildings, primary_barriers=roads)
>>> print(enclosed_tess.head())

create_isochrone

create_isochrone(
    graph=None,
    nodes=None,
    edges=None,
    center_point=None,
    threshold=None,
    edge_attr=None,
    cut_edge_types=None,
    method="concave_hull_knn",
    **kwargs
)

Generate an isochrone polygon from a graph.

An isochrone represents the area reachable from a center point within a given travel threshold (distance or time). This function computes the set of reachable edges and nodes in a network and generates a polygon that encloses this reachable area.

Parameters:

Name Type Description Default
graph Graph or MultiGraph

The network graph.

None
nodes GeoDataFrame or dict

Nodes of the graph.

None
edges GeoDataFrame or dict

Edges of the graph.

None
center_point Point or Sequence[Point] or GeoSeries or GeoDataFrame

The origin point(s) for the isochrone calculation. When multiple points are provided, reachability is unioned across all centers.

None
threshold float or Sequence[float]

The maximum travel distance (or time) that defines the boundary of the isochrone. When a sequence is provided, the function returns one isochrone layer per threshold using a single shared distance calculation.

None
edge_attr str

The edge attribute to use for distance calculation (e.g., 'length', 'travel_time'). If None, the function will use the default edge attribute.

"travel_time"
cut_edge_types list[tuple[str, str, str]] | None

List of edge types to remove from the graph before processing (e.g., [("bus_stop", "is_next_to", "bus_stop")]).

None
method str

The method to generate the isochrone polygon. Options are:

  • "concave_hull_knn": Creates a concave hull (k-NN) around reachable nodes.
  • "concave_hull_alpha": Creates a concave hull (alpha shape) around reachable nodes.
  • "convex_hull": Creates a convex hull around reachable nodes.
  • "buffer": Creates a buffer around reachable edges/nodes.
"concave_hull_knn"
**kwargs Any

Additional parameters for specific isochrone generation methods:

For method="concave_hull_knn": k : int, default 50 The number of nearest neighbors to consider. Increasing k generally produces a smoother, less concave boundary that moves closer to the convex hull.

For method="concave_hull_alpha": hull_ratio : float, default 0.0 The ratio for concave hull generation (0.0 to 1.0). Higher values mean tighter fit. allow_holes : bool, default False Whether to allow holes in the concave hull.

For method="buffer": buffer_distance : float, default 100 The distance to buffer reachable geometries. cap_style : int, default 1 The cap style for buffering. 1=Round, 2=Flat, 3=Square. join_style : int, default 1 The join style for buffering. 1=Round, 2=Mitre, 3=Bevel. resolution : int, default 16 The resolution of the buffer (number of segments per quarter circle).

{}

Returns:

Type Description
GeoDataFrame

A GeoDataFrame containing Polygon or MultiPolygon geometry. Scalar threshold input returns a single-row GeoDataFrame matching the existing API. Sequence input returns one row per threshold with columns threshold and geometry.

Raises:

Type Description
ValueError

If required inputs are missing or invalid.

plot_graph

plot_graph(
    graph=None,
    nodes=None,
    edges=None,
    ax=None,
    bgcolor="#000000",
    figsize=(12, 12),
    subplots=True,
    ncols=None,
    legend_position="upper left",
    labelcolor="white",
    title_color=None,
    node_color=None,
    node_alpha=None,
    node_zorder=None,
    node_edgecolor=None,
    markersize=None,
    edge_color=None,
    edge_linewidth=None,
    edge_alpha=None,
    edge_zorder=None,
    **kwargs
)

Plot a graph with a unified interface.

This function provides a unified interface for plotting spatial network data, supporting both GeoDataFrame-based and NetworkX-based inputs. NetworkX graphs are automatically converted to GeoDataFrames before plotting. It can handle homogeneous and heterogeneous graphs with customizable styling.

Parameters:

Name Type Description Default
graph Graph or MultiGraph

The NetworkX graph to plot. If provided without nodes/edges, the function will convert it to GeoDataFrames before plotting.

None
nodes GeoDataFrame or dict[str, GeoDataFrame]

Nodes to plot. Can be a single GeoDataFrame (homogeneous) or a dictionary mapping node type names to GeoDataFrames (heterogeneous).

None
edges GeoDataFrame or dict[tuple[str, str, str], GeoDataFrame]

Edges to plot. Can be a single GeoDataFrame (homogeneous) or a dictionary mapping edge type tuples (src_type, rel_type, dst_type) to GeoDataFrames (heterogeneous).

None
ax Axes or ndarray

The axes on which to plot. If None, a new figure and axes are created.

None
bgcolor str

Background color for the plot (Black theme).

"#000000"
figsize tuple[float, float]

Figure size as (width, height) in inches.

(12, 12)
subplots bool

If True and the graph is heterogeneous, plot each node/edge type in a separate subplot. Uses 'ax' as array of subplots if provided.

True
ncols int

Number of columns (subplots per row) when plotting heterogeneous graphs with subplots=True. If None, defaults to min(3, number_of_edge_types).

None
legend_position str or None

Position of the legend for heterogeneous graphs. Common values include "upper left", "upper right", "lower left", "lower right", "center", etc. If None, no legend is displayed.

"upper left"
labelcolor str

Color of the legend text labels.

"white"
title_color str

Color for subplot titles when subplots=True. Falls back to a white title on black backgrounds if not provided.

None
node_color str, float, pd.Series, or dict

Color for nodes. Can be a scalar, column name, Series, or a dictionary mapping node types to colors for heterogeneous graphs.

None
node_alpha float, pd.Series, or dict

Transparency for nodes (0.0-1.0). Can be a scalar, column name, Series, or a dictionary mapping node types to transparency values.

None
node_zorder int, pd.Series, or dict

Drawing order for nodes. Can be a scalar, column name, Series, or a dictionary mapping node types to zorder values.

None
node_edgecolor str, pd.Series, or dict

Color for node borders. Can be a scalar, column name, Series, or a dictionary mapping node types to edge colors.

None
markersize float, pd.Series, or dict

Size of the node markers. Can be a scalar, column name, Series, or a dictionary mapping node types to marker sizes.

None
edge_color str, float, pd.Series, or dict

Color for edges. Can be a scalar, column name, Series, or a dictionary mapping edge types to colors for heterogeneous graphs.

None
edge_linewidth float, pd.Series, or dict

Line width for edges. Can be a scalar, column name, Series, or a dictionary mapping edge types to line widths.

None
edge_alpha float, pd.Series, or dict

Transparency for edges (0.0-1.0). Can be a scalar, column name, Series, or a dictionary mapping edge types to transparency values.

None
edge_zorder int, pd.Series, or dict

Drawing order for edges. Can be a scalar, column name, Series, or a dictionary mapping edge types to zorder values.

None
**kwargs Any

Additional keyword arguments passed to the GeoPandas plotting functions.

Supports attribute-based styling where parameters can be specified as:

  • Scalar values (str/float): Applied uniformly to all geometries
  • Column names (str): If the string matches a column in the GeoDataFrame, that column's values are used for styling
  • pd.Series: Direct values for each geometry

Other common options: etc.

{}

Returns:

Type Description
Axes or ndarray or None

The axes object(s) used for plotting.

Raises:

Type Description
ImportError

If matplotlib is not installed.

ValueError

If no valid input is provided (all parameters are None).

TypeError

If the input data types are not supported.

Examples:

>>> import geopandas as gpd
>>> import pandas as pd
>>> import networkx as nx
>>> # Plot from NetworkX graph (automatically converted to GeoDataFrames)
>>> G = nx.Graph()
>>> G.add_node(0, pos=(0, 0))
>>> G.add_edge(0, 1)
>>> plot_graph(graph=G)
>>> # Plot from GeoDataFrames with scalar styling
>>> plot_graph(nodes=nodes_gdf, edges=edges_gdf, node_color='red')
>>> # Plot with attribute-based node colors (by column name)
>>> plot_graph(nodes=nodes_gdf, edges=edges_gdf, node_color='building_type')
>>> # Plot with pd.Series for edge linewidth
>>> edge_widths = pd.Series([1.0, 2.0, 1.5], index=edges_gdf.index)
>>> plot_graph(nodes=nodes_gdf, edges=edges_gdf, edge_linewidth=edge_widths)
>>> # Plot heterogeneous graph
>>> plot_graph(nodes=nodes_dict, edges=edges_dict)

clip_graph

clip_graph(graph, area, keep_outer_neighbors=False, as_nx=False)

Clip a graph to a specific area.

Filters edges to those within (or intersecting) a polygon area. Nodes are filtered to include only those connected to remaining edges.

Parameters:

Name Type Description Default
graph GeoDataFrame, tuple, or NetworkX graph

Input graph as edges GeoDataFrame, (nodes, edges) tuple, or NetworkX graph.

required
area Polygon, MultiPolygon, GeoDataFrame, or GeoSeries

The area to clip to.

required
keep_outer_neighbors bool

If True, keeps segments that intersect the boundary.

False
as_nx bool

If True, return as NetworkX graph.

False

Returns:

Type Description
GeoDataFrame, tuple, or NetworkX graph

Clipped graph in same format as input, or NetworkX if as_nx=True.

remove_isolated_components

remove_isolated_components(graph, as_nx=False)

Keep only the largest connected component of a graph.

Identifies all connected components and retains only the largest one.

Parameters:

Name Type Description Default
graph GeoDataFrame, tuple, or NetworkX graph

Input graph as edges GeoDataFrame, (nodes, edges) tuple, or NetworkX graph.

required
as_nx bool

If True, return as NetworkX graph.

False

Returns:

Type Description
GeoDataFrame, tuple, or NetworkX graph

Graph with only largest component, in same format as input.