TopologyBuilder
A TopologyBuilder turns the streets of the DataRegistry into a
street network split into region topologies, which all later
pipeline stages consume. Two implementations differ only in how regions
are defined:
PolygonTopologyBuilder— regions are derived from a polygon layer.SimpleTopologyBuilder— regions are listed explicitly (street ids or row indices per region).
Streets are registered — and optionally cleaned — with
DataRegistry.register_streets.
from geopipe.topology_builder.topology_builder import (
SimpleTopologyBuilder, PolygonTopologyBuilder,
)
What build() does
- Query the streets for the builder's area from the registry
(
DataRegistry.streets(area)): the polygons, or the area set withset_area. - Assign regions — every street gets a region id (column and edge
attribute
region_id); streets outside all regions get none. - Build the street network — the streets are converted into a
networkx.Graph(see Network structure). - Split into region topologies — one sub-graph per region. Streets
without a region stay in
networkonly; connections between regions may run over them. - Check connectivity — every region topology must be a single
connected graph (
set_topology_connections_check, on by default).
Common API
| Setter | Arguments | Default | Description |
|---|---|---|---|
set_data_registry |
data_registry: DataRegistry |
— (required) | Source of the streets; its CRS is the project CRS. |
set_topology_connections_check |
enabled: bool |
True |
Raise a ValueError if a region topology is not connected, listing the ids of the streets not connected to its largest group. |
build |
— | — | Run the steps above and return a TopologyBuildResult. |
TopologyBuildResult
build() returns a dataclass (geopipe.topology_builder.TopologyBuildResult):
| Field | Type | Description |
|---|---|---|
network |
networkx.Graph |
The full street network, including streets without a region. Pass this to EnergySystemBuilder.set_system_topology. |
region_topologies |
dict[Any, networkx.Graph] |
One sub-graph per region id. |
streets |
GeoDataFrame |
The streets with the region_id column. |
Network structure
- Nodes are
(x, y)coordinate tuples in the project CRS. - Edges connect each pair of consecutive vertices of a street geometry, i.e. a street with n vertices becomes n − 1 edges. Streets are only connected where they share a vertex (see divide at junctions).
- Edge attributes:
length— Euclidean length of the edge in CRS units,geometry— the geometry of the street the edge belongs to,region_id— the edge's region (Noneoutside all regions),source_street_id,source_share— the input street the edge stems from and the edge's share of that street's length. Street-keyed data (StreetValueDataset) is mapped onto regions with them,- every other column of the streets, copied unchanged. Values such
as demands are not split onto the edges — use a
StreetValueDatasetfor them.
- The graph's CRS is stored in
network.graph["crs"].
PolygonTopologyBuilder
Every street that lies completely within polygon k belongs to region k. The polygons are also the area whose streets are queried.
- Streets are not split at polygon boundaries: a street crossing a boundary belongs to no region.
- A street lying within more than one (overlapping) polygon raises a
ValueErrorlisting the affected streets and polygons.
| Setter | Arguments | Default | Description |
|---|---|---|---|
set_polygons_data |
polygons_data: GeoDataFrame \| Path, id_column: str |
— (required) | Polygon layer (Polygon / MultiPolygon); id_column holds the region id. A Path is loaded via geopandas.read_file; the polygons are reprojected to the registry CRS. |
from pathlib import Path
from geopipe.topology_builder.topology_builder import PolygonTopologyBuilder
tb = PolygonTopologyBuilder()
tb.set_data_registry(data_reg)
tb.set_polygons_data(Path("input/polygons.geojson"), id_column="id")
result = tb.build()
SimpleTopologyBuilder
Regions are listed explicitly in a YAML file or dict: each region ID maps to a column name and the list of values to match. A street belongs to region k iff its value in that column is one of the values listed under k. Use this when you already know the region membership of every street.
| Setter | Arguments | Default | Description |
|---|---|---|---|
set_area |
area: GeoDataFrame \| Path |
— (required) | Study area whose streets are queried from the registry. |
set_grouping |
grouping: dict \| Path |
— (required) | Region grouping (see region_grouping.yaml). A Path is loaded as YAML. |
from pathlib import Path
from geopipe.topology_builder.topology_builder import SimpleTopologyBuilder
tb = SimpleTopologyBuilder()
tb.set_data_registry(data_reg)
tb.set_area(Path("input/study_area.geojson"))
tb.set_grouping(Path("input/region_grouping.yaml"))
result = tb.build()
region_grouping.yaml
Maps region ID → column name → list of values to match. Region IDs
must be integers, column names strings and the values lists (otherwise
build() raises TypeError). Each region is the union of street rows
whose street_id is in the list:
0:
street_id:
- DEHE04620001hKyX
- DEHE04620001hKzm
1:
street_id:
- DEHE04620001hKzc
Use the special key index instead of a column name to match row
indices. If a street matches several regions, the last one wins.
The grouping is applied to the registered streets: if they were cleaned, split pieces and connectors carry new IDs and the row index is reset, so they no longer match the original IDs/indices.