Net generation package

Elevation data utilities for district heating network generation.

Provides functions to query terrain elevation (Höhe über NN) for UTM-projected coordinates, either from a local GeoTIFF digital elevation model (DGM) or via the OpenTopoData REST API as an online fallback. The elevation values are then written as Z-coordinates into Shapely/GeoPandas geometries so that pandapipes can use them as height_m on network junctions.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

districtheatingsim.net_generation.elevation_utils.query_elevation_from_geotiff(points_utm: list[tuple[float, float]], dem_path: str, crs_utm: str = 'EPSG:25833') list[float][source]

Read terrain elevations from a local GeoTIFF digital elevation model.

Uses rasterio to sample the raster at the given projected coordinates. The raster CRS is detected automatically; coordinates are re-projected if the raster CRS differs from crs_utm.

Parameters:
  • points_utm (List[Tuple[float, float]]) – List of (x, y) coordinate pairs in the projected CRS

  • dem_path (str) – File system path to the GeoTIFF DEM

  • crs_utm (str) – EPSG string of the input CRS (default "EPSG:25833")

Returns:

Elevation in metres above sea level for each input point. Points that fall outside the raster extent are set to 0.0.

Return type:

List[float]

Raises:
districtheatingsim.net_generation.elevation_utils.query_elevation_from_api(points_utm: list[tuple[float, float]], crs_utm: str = 'EPSG:25833', dataset: str = 'eudem25m') list[float][source]

Query terrain elevations from the OpenTopoData REST API (online fallback).

Transforms UTM coordinates to WGS84, then queries https://api.opentopodata.org/v1/<dataset> in batches of 100. No API key required for the public instance.

Parameters:
  • points_utm (List[Tuple[float, float]]) – List of (x, y) coordinate pairs in the projected CRS

  • crs_utm (str) – EPSG string of the input CRS (default "EPSG:25833")

  • dataset (str) – OpenTopoData dataset name. "eudem25m" (Europe, 25 m) is used by default. Other options: "srtm30m", "aster30m".

Returns:

Elevation in metres above sea level for each input point. Returns 0.0 for points that could not be resolved.

Return type:

List[float]

Raises:

requests.exceptions.RequestException – On network errors

districtheatingsim.net_generation.elevation_utils.build_elevation_lookup(points_utm: list[tuple[float, float]], dem_path: str | None, crs_utm: str = 'EPSG:25833') dict[tuple[float, float], float][source]

Build a {(x, y): z_m} dictionary for a list of UTM points.

Uses the local GeoTIFF if dem_path is provided and rasterio is available; otherwise falls back to the OpenTopoData API. If neither source is reachable, returns a dictionary with 0.0 for every point and emits a warning.

Parameters:
  • points_utm (List[Tuple[float, float]]) – Unique (x, y) coordinate pairs in the projected CRS

  • dem_path (Optional[str]) – Path to a local GeoTIFF DEM, or None to force API

  • crs_utm (str) – EPSG string of the input CRS

Returns:

Mapping from (x, y) to elevation [m]

Return type:

Dict[Tuple[float, float], float]

districtheatingsim.net_generation.elevation_utils.assign_elevation_to_geodataframe(gdf: GeoDataFrame, elevation_lookup: dict[tuple[float, float], float], default_z: float = 0.0) GeoDataFrame[source]

Write Z-coordinates from elevation_lookup into a GeoDataFrame’s geometries.

Supports Point and LineString geometry types. For each vertex (x, y) the corresponding elevation is looked up; if not found, default_z is used. The returned GeoDataFrame has the same CRS and attributes as the input but with 3-D geometries.

Parameters:
  • gdf (gpd.GeoDataFrame) – Input GeoDataFrame with 2-D or 3-D geometries

  • elevation_lookup (Dict[Tuple[float, float], float]) – Mapping {(x, y): z_m}

  • default_z (float) – Fallback elevation when a vertex is not in the lookup

Returns:

GeoDataFrame with 3-D geometries

Return type:

gpd.GeoDataFrame

districtheatingsim.net_generation.elevation_utils.collect_unique_points_from_gdfs(*gdfs: GeoDataFrame) list[tuple[float, float]][source]

Collect all unique 2-D (x, y) vertex coordinates from one or more GeoDataFrames.

This is a convenience function to assemble the list of points that need elevation lookup before building the network.

Parameters:

gdfs – One or more GeoDataFrames with Point or LineString geometries

Returns:

Deduplicated list of (x, y) tuples

Return type:

List[Tuple[float, float]]

Data import and layer processing for district heating network generation.

Handles integration of OpenStreetMap street networks, building locations, and heat generator coordinates into geospatial layers for network optimization.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

districtheatingsim.net_generation.import_and_create_layers.import_osm_street_layer(osm_street_layer_geojson_file: str) GeoDataFrame | None[source]

Import OpenStreetMap street network from GeoJSON.

Parameters:

osm_street_layer_geojson_file (str) – Path to GeoJSON with street network LineStrings

Returns:

Street network GeoDataFrame or None on failure

Return type:

Optional[gpd.GeoDataFrame]

Raises:

Note

Returns None on error to prevent cascading failures. Prints diagnostic messages.

districtheatingsim.net_generation.import_and_create_layers.load_layers(osm_street_layer_geojson_file: str, data_csv_file_name: str, coordinates: list[tuple[float, float]], dem_path: str | None = None, crs: str = 'EPSG:25833') tuple[GeoDataFrame | None, GeoDataFrame | None, GeoDataFrame | None, DataFrame | None][source]

Load all spatial layers for network generation.

If dem_path is provided (or the OpenTopoData API is reachable), building and generator point geometries are enriched with Z-coordinates (elevation above sea level in metres). Downstream network generation functions can then preserve these Z-values in the resulting GeoJSON, enabling pandapipes to use correct height_m values for hydraulic pressure calculations.

Parameters:
  • osm_street_layer_geojson_file (str) – Path to street network GeoJSON

  • data_csv_file_name (str) – Path to CSV with building data (requires UTM_X, UTM_Y columns)

  • coordinates (List[Tuple[float, float]]) – Heat generator coordinate tuples (x, y)

  • dem_path (Optional[str]) – Optional path to a local GeoTIFF DEM for elevation lookup. If None, the OpenTopoData API is used as fallback.

  • crs (str) – Projected CRS of the building coordinates (default "EPSG:25833")

Returns:

Tuple of (street_layer, consumer_layer, generator_layer, consumer_df)

Return type:

Tuple[Optional[gpd.GeoDataFrame], Optional[gpd.GeoDataFrame], Optional[gpd.GeoDataFrame], Optional[pd.DataFrame]]

Raises:

Note

CSV uses semicolon separator. Returns (None, None, None, None) on error. When dem_path is None and no internet connection is available, all elevations default to 0.0 m with a warning.

districtheatingsim.net_generation.import_and_create_layers.generate_and_export_layers(osm_street_layer_geojson_file_name: str, data_csv_file_name: str, coordinates: list[tuple[float, float]], base_path: str, algorithm: str = 'MST', offset_angle: float = 0, offset_distance: float = 0.5, crs: str = 'EPSG:25833', dem_path: str | None = None) None[source]

Generate district heating network and export as GeoJSON.

When dem_path is supplied (or OpenTopoData API is available), all generated line geometries are stored with 3-D coordinates (Z = elevation above sea level). The pandapipes initialisation module reads these Z-values to set height_m on each network junction, which enables correct hydrostatic pressure modelling.

Parameters:
  • osm_street_layer_geojson_file_name (str) – Path to street network GeoJSON

  • data_csv_file_name (str) – Path to building CSV (UTM_X, UTM_Y columns)

  • coordinates (List[Tuple[float, float]]) – Heat generator coordinate tuples (x, y)

  • base_path (str) – Output directory for generated network

  • algorithm (str) – Network algorithm - MST, Advanced MST, or Steiner (default MST)

  • offset_angle (float) – Return line offset angle in degrees (default 0)

  • offset_distance (float) – Return line offset distance in meters (default 0.5)

  • crs (str) – Projected CRS for the output network (default EPSG:25833)

  • dem_path (Optional[str]) – Optional path to a local GeoTIFF DEM. If None, OpenTopoData API is used as fallback.

Raises:

Minimum Spanning Tree generation and road alignment optimization.

Implements MST algorithms for district heating network layout with iterative road alignment adjustment while maintaining connectivity.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

districtheatingsim.net_generation.minimal_spanning_tree.generate_mst(points: GeoDataFrame) GeoDataFrame[source]

Generate Minimum Spanning Tree from point locations.

Parameters:

points (gpd.GeoDataFrame) – Point geometries for network terminals

Returns:

MST network as LineString geometries

Return type:

gpd.GeoDataFrame

Note

Tree topology (n-1 edges for n points). Uses Kruskal’s algorithm with Euclidean distances.

districtheatingsim.net_generation.minimal_spanning_tree.adjust_segments_to_roads(mst_gdf: GeoDataFrame, street_layer: GeoDataFrame, all_end_points_gdf: GeoDataFrame, threshold: float = 5.0, min_improvement: float = 0.5) GeoDataFrame[source]

Iteratively adjust MST segments to follow street network.

Parameters:
  • mst_gdf (gpd.GeoDataFrame) – MST segments to optimize

  • street_layer (gpd.GeoDataFrame) – Street network for alignment

  • all_end_points_gdf (gpd.GeoDataFrame) – Terminal points for MST reconstruction

  • threshold (float) – Distance threshold for adjustment trigger [m] (default 5.0)

  • min_improvement (float) – Minimum improvement required [m] (default 0.5)

Returns:

Road-aligned network maintaining MST connectivity

Return type:

gpd.GeoDataFrame

Raises:
  • ValueError – If invalid geometries or empty network

  • RuntimeError – If fails to converge within iteration limit

Note

Uses iterative improvement with blacklisting to prevent oscillation. Max 50 iterations.

districtheatingsim.net_generation.minimal_spanning_tree.simplify_network(gdf: GeoDataFrame, threshold: float = 10.0) GeoDataFrame[source]

Simplify network by merging nearby points.

Parameters:
  • gdf (gpd.GeoDataFrame) – Network segments to simplify

  • threshold (float) – Distance for merging points [m] (default 10.0)

Returns:

Simplified network with merged points

Return type:

gpd.GeoDataFrame

Note

Merges points within threshold to their centroid, maintaining connectivity.

districtheatingsim.net_generation.minimal_spanning_tree.extract_unique_points_and_create_mst(gdf: GeoDataFrame, all_end_points_gdf: GeoDataFrame) GeoDataFrame[source]

Extract unique points and rebuild MST structure.

Parameters:
  • gdf (gpd.GeoDataFrame) – Network segments for point extraction

  • all_end_points_gdf (gpd.GeoDataFrame) – Terminal points to preserve

Returns:

Reconstructed MST connecting all unique points

Return type:

gpd.GeoDataFrame

Note

Ensures tree topology (n-1 edges for n points) after network adjustments.

Network generation for district heating using graph algorithms.

Implements MST, Advanced MST, and Steiner tree algorithms for cost-optimal network topologies with street alignment and parallel line generation.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

districtheatingsim.net_generation.net_generation.create_offset_points(point: Point, distance: float, angle_degrees: float) Point[source]

Create point offset by specified distance and angle.

Parameters:
  • point (Point) – Original point

  • distance (float) – Offset distance [m]

  • angle_degrees (float) – Offset angle (0°=East, 90°=North)

Returns:

Offset point

Return type:

Point

Note

Uses polar transformation: dx=distance*cos(θ), dy=distance*sin(θ).

districtheatingsim.net_generation.net_generation.offset_lines_by_angle(lines_gdf: GeoDataFrame, distance: float, angle_degrees: float) GeoDataFrame[source]

Build a parallel return network offset from the supply lines.

Each vertex is offset perpendicular to its local network direction, so segments of every orientation are separated by distance. (The previous implementation translated all vertices by one fixed vector, which left segments running parallel to that direction lying on top of the supply line — BACKLOG C3.) angle_degrees now selects the preferred side: of the two perpendiculars at each vertex, the one pointing toward (cos θ, sin θ) is used, giving a globally consistent side.

Connectivity is preserved exactly: the offset is computed once per vertex coordinate, so a vertex shared by several segments maps to a single return coordinate — i.e. a shared return junction (create_network keys junctions on exact coordinate tuples). Z-coordinates (elevation), if present, are carried over.

Parameters:
  • lines_gdf (gpd.GeoDataFrame) – Supply LineStrings to offset.

  • distance (float) – Offset distance [m] (typical 0.5–2.0 m).

  • angle_degrees (float) – Preferred-side reference angle (0°=East, 90°=North).

Returns:

Return LineStrings with preserved CRS.

Return type:

gpd.GeoDataFrame

districtheatingsim.net_generation.net_generation.find_nearest_line(point: Point, line_layer: GeoDataFrame) LineString | None[source]

Find nearest line to a point.

Parameters:
  • point (Point) – Point to find nearest line for

  • line_layer (gpd.GeoDataFrame) – LineStrings to search (typically streets)

Returns:

Nearest LineString or None if no lines found

Return type:

Optional[LineString]

Note

O(n) complexity. Uses Euclidean distance. Returns None on empty layer.

districtheatingsim.net_generation.net_generation.create_perpendicular_line(point: Point, line: LineString) LineString[source]

Create perpendicular connection from point to nearest point on line.

Parameters:
  • point (Point) – Point to connect (typically building)

  • line (LineString) – Line to connect to (typically street)

Returns:

Connection LineString (shortest path)

Return type:

LineString

Note

Uses line.project() and line.interpolate() for optimal connection geometry.

districtheatingsim.net_generation.net_generation.process_layer_points(layer: GeoDataFrame, layer_lines: GeoDataFrame) tuple[list[LineString], set][source]

Process points to create perpendicular connections and extract street endpoints.

Parameters:
  • layer (gpd.GeoDataFrame) – Points to process (buildings, generators)

  • layer_lines (gpd.GeoDataFrame) – LineStrings for connections (streets)

Returns:

Tuple of (connection_lines, unique_street_endpoints)

Return type:

Tuple[List[LineString], set]

Note

Returns street connection points as set for network optimization input.

districtheatingsim.net_generation.net_generation.generate_network(heat_consumer_layer: GeoDataFrame, heat_generator_layer: GeoDataFrame, osm_street_layer: GeoDataFrame, algorithm: str = 'MST', offset_distance: float = 0.5, offset_angle: float = 0) tuple[GeoDataFrame, GeoDataFrame][source]

Generate optimal district heating network with supply and return lines.

Parameters:
  • heat_consumer_layer (gpd.GeoDataFrame) – Consumer locations (buildings)

  • heat_generator_layer (gpd.GeoDataFrame) – Generator locations (plants)

  • osm_street_layer (gpd.GeoDataFrame) – Street network for routing

  • algorithm (str) – MST, Advanced MST, or Steiner (default MST)

  • offset_distance (float) – Return line offset [m] (default 0.5)

  • offset_angle (float) – Offset angle [degrees] (default 0)

Returns:

Tuple of (supply_network, return_network)

Return type:

Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame]

Raises:

ValueError – If unknown algorithm specified

Note

MST=fastest tree, Advanced MST=road-aligned, Steiner=minimal length.

districtheatingsim.net_generation.net_generation.generate_connection_lines(layer: GeoDataFrame, offset_distance: float, offset_angle: float, df: DataFrame | None = None) GeoDataFrame[source]

Generate connection lines with building attributes.

Parameters:
  • layer (gpd.GeoDataFrame) – Building Point locations

  • offset_distance (float) – Connection line offset [m]

  • offset_angle (float) – Connection angle [degrees]

  • df (Optional[pd.DataFrame]) – Building attributes with UTM_X, UTM_Y columns (optional)

Returns:

Connection LineStrings with building attributes

Return type:

gpd.GeoDataFrame

Note

Attributes: Land, Stadt, Adresse, Wärmebedarf, Gebäudetyp, VLT_max, etc.

Unified GeoJSON schema for district heating networks with layered data model.

Author: Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.net_generation.network_geojson_schema.NetworkGeoJSONSchema[source]

Bases: object

Unified GeoJSON schema for district heating networks with editable/protected data separation.

VERSION = '2.0'
FEATURE_TYPE_FLOW = 'network_line_flow'
FEATURE_TYPE_RETURN = 'network_line_return'
FEATURE_TYPE_BUILDING = 'building_connection'
FEATURE_TYPE_GENERATOR = 'generator_connection'
EDIT_LEVEL_EDITABLE = 'editable'
EDIT_LEVEL_GENERATED = 'generated'
EDIT_LEVEL_PROTECTED = 'protected'
static create_metadata(state: str = 'designed') dict[str, Any][source]

Create metadata for network GeoJSON.

Parameters:

state (str) – Network state (‘designed’, ‘calculated’, or ‘optimized’)

Returns:

Metadata dictionary with version, timestamp, and edit levels

Return type:

Dict[str, Any]

static create_network_line_feature(geometry: LineString, layer: str, segment_id: str, color: str = None, calculated_data: dict = None) dict[str, Any][source]

Create a network line feature (flow or return).

Parameters:
  • geometry (LineString) – Line geometry

  • layer (str) – Layer type (‘flow’ or ‘return’)

  • segment_id (str) – Unique segment identifier

  • color (str) – Hex color code (default: #59DB7F for flow, #0C350A for return)

  • calculated_data (Dict) – Calculation results (diameter, flow rate, etc.)

Returns:

GeoJSON Feature with style and calculated properties

Return type:

Dict[str, Any]

static create_building_connection_feature(geometry: LineString, connection_id: str, building_data: dict[str, Any]) dict[str, Any][source]

Create a building connection feature with protected building data.

Parameters:
  • geometry (LineString) – Connection line geometry

  • connection_id (str) – Unique connection identifier

  • building_data (Dict[str, Any]) – Building data from CSV (protected)

Returns:

GeoJSON Feature with building metadata

Return type:

Dict[str, Any]

static create_generator_connection_feature(geometry: LineString, connection_id: str, generator_type: str = 'main', location_index: int = 0) dict[str, Any][source]

Create a generator connection feature.

Coordinate convention – the LineString geometry must follow [Vorlauf_point, Rücklauf_point] order, i.e.:

  • coords[0] → supply / Vorlauf (VL) endpoint

  • coords[1] → return / Rücklauf (RL) endpoint

This convention is required by pp_net_initialisation_geojson.create_network() so that the circulation pump is connected with flow_junction on the VL side and return_junction on the RL side. All network generation helpers (osmnx_steiner_network, import_and_create_layers) already follow this convention. If you create or edit generator connections manually, ensure the line direction is preserved.

Parameters:
  • geometry (LineString) – Connection line geometry (VL→RL direction).

  • connection_id (str) – Unique connection identifier.

  • generator_type (str) – Generator type ('main' or 'secondary').

  • location_index (int) – Generator location index.

Returns:

GeoJSON Feature with generator metadata.

Return type:

Dict[str, Any]

static create_network_geojson(flow_lines: GeoDataFrame, return_lines: GeoDataFrame, building_connections: GeoDataFrame, generator_connections: GeoDataFrame, state: str = 'designed', calculated_data: dict = None, crs: str = 'EPSG:25833') dict[str, Any][source]

Create unified network GeoJSON from separate components.

Parameters:
  • flow_lines (gpd.GeoDataFrame) – Supply line network

  • return_lines (gpd.GeoDataFrame) – Return line network

  • building_connections (gpd.GeoDataFrame) – Building connections with data

  • generator_connections (gpd.GeoDataFrame) – Generator connections

  • state (str) – Network state

  • calculated_data (Dict) – Calculation results indexed by segment_id

  • crs (str) – Projected CRS for the output GeoJSON (default EPSG:25833)

Returns:

Complete GeoJSON FeatureCollection

Return type:

Dict[str, Any]

static export_to_file(geojson: dict[str, Any], filepath: str) None[source]

Export network GeoJSON to file.

Parameters:
  • geojson (Dict[str, Any]) – Network GeoJSON dictionary

  • filepath (str) – Output file path

static validate_version(geojson: dict[str, Any], *, filepath: str = '') str | None[source]

Warn (do not raise) if the network GeoJSON schema version is missing or newer than this app understands (BACKLOG D4).

The version lives inside the file as metadata.version (a semver-ish string, e.g. "2.0") — its own convention, distinct from the int-based _meta block used by the JSON artifacts in utilities/schema.py (a GeoJSON FeatureCollection carries its metadata inline, not in a sidecar). Comparison is on the major version.

Parameters:
  • geojson – The loaded GeoJSON FeatureCollection dict.

  • filepath – Optional source path for clearer log messages.

Returns:

The version string found on disk, or None if absent.

Return type:

str | None

static import_from_file(filepath: str) dict[str, Any][source]

Import network GeoJSON from file.

Parameters:

filepath (str) – Input file path

Returns:

Network GeoJSON dictionary

Return type:

Dict[str, Any]

static split_to_legacy_format(geojson: dict[str, Any], crs: str = None) tuple[GeoDataFrame, GeoDataFrame, GeoDataFrame, GeoDataFrame][source]

Split unified GeoJSON into legacy 4-file format.

The CRS is read from the crs field embedded in the GeoJSON (if present). The crs parameter can override this. Falls back to DEFAULT_CRS when neither source is available.

Parameters:
  • geojson (Dict[str, Any]) – Unified network GeoJSON

  • crs (str or None) – Projected CRS override (EPSG code string). If None, the CRS stored in the GeoJSON file is used.

Returns:

(flow_lines, return_lines, building_connections, generator_connections)

Return type:

Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame, gpd.GeoDataFrame]

static update_calculated_data(geojson: dict[str, Any], flow_results: dict[str, dict], return_results: dict[str, dict]) dict[str, Any][source]

Update calculated data in unified GeoJSON after network dimensioning.

Parameters:
  • geojson (Dict[str, Any]) – Unified network GeoJSON

  • flow_results (Dict[str, Dict]) – Calculation results for flow lines {segment_id: {diameter_mm, …}}

  • return_results (Dict[str, Dict]) – Calculation results for return lines

Returns:

Updated GeoJSON with calculation results

Return type:

Dict[str, Any]

OSMnx-based district heating network generation using OpenStreetMap data, Steiner Tree optimization, and edge-splitting algorithms for optimal street-based routing.

Author: Dipl.-Ing. (FH) Jonas Pfeiffer

districtheatingsim.net_generation.osmnx_steiner_network.download_street_graph(buildings: GeoDataFrame, generator_coords: list[tuple[float, float]], buffer_meters: float = 500.0, network_type: str = 'drive_service', target_crs: str = 'EPSG:25833', custom_filter: str | None = None) MultiDiGraph[source]

Download street network from OpenStreetMap for given building area.

Parameters:
  • buildings (gpd.GeoDataFrame) – Building geometries (Point) in projected CRS

  • generator_coords (List[Tuple[float, float]]) – List of (x, y) heat generator coordinates in same CRS

  • buffer_meters (float) – Buffer distance in meters around buildings

  • network_type (str) – OSM network type (‘drive’, ‘drive_service’, ‘walk’, ‘bike’, ‘all’)

  • target_crs (str) – Target coordinate reference system

  • custom_filter (Optional[str]) – Custom OSM filter string (overrides network_type)

Returns:

Street network graph projected to target CRS

Return type:

nx.MultiDiGraph

Raises:
  • ValueError – If buildings is empty or has invalid CRS

  • ConnectionError – If OSMnx cannot download data from OpenStreetMap

Note

Custom filters use regex: ‘[“highway”~”primary|secondary|tertiary|residential|service|unclassified|track”]’

districtheatingsim.net_generation.osmnx_steiner_network.create_steiner_tree(street_graph: MultiDiGraph, terminal_points: GeoDataFrame, weight: str = 'length') Graph[source]

Create Steiner Tree connecting terminal points on street network using Kou approximation.

Parameters:
  • street_graph (nx.MultiDiGraph) – Street network graph from OSMnx with node coordinates

  • terminal_points (gpd.GeoDataFrame) – Terminal point geometries (buildings, generators)

  • weight (str) – Edge attribute for optimization (default ‘length’)

Returns:

Undirected Steiner Tree subgraph connecting all terminals

Return type:

nx.Graph

Raises:
  • ValueError – If terminal_points is empty or street_graph has no nodes

  • KeyError – If weight attribute not found in edge data

Note

Kou algorithm complexity: O(|T|² |E| log |V|). Node coordinates preserved for edge-splitting.

districtheatingsim.net_generation.osmnx_steiner_network.connect_terminals_with_edge_splitting(steiner_tree: Graph, street_graph: MultiDiGraph, terminal_points: GeoDataFrame, node_threshold: float = 0.1) tuple[list[dict[str, Any]], dict[tuple, list[dict[str, Any]]]][source]

Connect terminal points to Steiner Tree using edge-splitting algorithm.

Parameters:
  • steiner_tree (nx.Graph) – Steiner Tree graph connecting terminal nodes

  • street_graph (nx.MultiDiGraph) – Original street network with node coordinates

  • terminal_points (gpd.GeoDataFrame) – Terminal point geometries

  • node_threshold (float) – Distance threshold for node vs edge connection (meters)

Returns:

(connection_info, edges_to_split) tuple

Return type:

Tuple[List[Dict[str, Any]], Dict[Tuple, List[Dict[str, Any]]]]

Raises:

ValueError – If terminal_points or steiner_tree is empty

Note

Uses exact (x, y) tuples instead of Point objects to prevent floating-point drift.

districtheatingsim.net_generation.osmnx_steiner_network.build_network_from_split_edges(steiner_tree: Graph, street_graph: MultiDiGraph, edges_to_split: dict[tuple, list[dict[str, Any]]], crs: str = 'EPSG:25833') GeoDataFrame[source]

Build network segments from Steiner Tree with edge splitting.

Parameters:
  • steiner_tree (nx.Graph) – Steiner Tree graph to convert

  • street_graph (nx.MultiDiGraph) – Original street graph with node coordinates

  • edges_to_split (Dict[Tuple, List[Dict[str, Any]]]) – Dictionary of edges to split with split point info

  • crs (str) – Coordinate reference system for output

Returns:

Network segments as LineString geometries

Return type:

gpd.GeoDataFrame

Note

Split points sorted by distance along edge to prevent overlapping segments.

districtheatingsim.net_generation.osmnx_steiner_network.remove_dead_ends(network_gdf: GeoDataFrame, protected_endpoints: set, max_iterations: int = 10) GeoDataFrame[source]

Remove dead-end segments while protecting connection endpoints.

Parameters:
  • network_gdf (gpd.GeoDataFrame) – Network segments as LineString geometries

  • protected_endpoints (set) – Set of (x, y) coordinate tuples to protect

  • max_iterations (int) – Maximum iterations for dead-end removal

Returns:

Cleaned network with dead ends removed

Return type:

gpd.GeoDataFrame

Note

Nodes with degree 1 are removed unless in protected_endpoints.

districtheatingsim.net_generation.osmnx_steiner_network.create_connection_lines(connection_info: list[dict[str, Any]], crs: str = 'EPSG:25833') GeoDataFrame[source]

Create connection line geometries from terminals to network attachment points.

Parameters:
  • connection_info (List[Dict[str, Any]]) – Connection information from edge-splitting algorithm

  • crs (str) – Coordinate reference system for output

Returns:

Connection lines as LineString geometries

Return type:

gpd.GeoDataFrame

districtheatingsim.net_generation.osmnx_steiner_network.create_return_network(supply_network: GeoDataFrame, offset_x: float = 1.0, offset_y: float = 0.0) GeoDataFrame[source]

Create return network by offsetting supply network geometries.

Parameters:
  • supply_network (gpd.GeoDataFrame) – Supply network with LineString geometries

  • offset_x (float) – Horizontal offset in meters

  • offset_y (float) – Vertical offset in meters

Returns:

Return network with offset geometries

Return type:

gpd.GeoDataFrame

Note

Typical offsets: 0.5-1.0m (district heating), 0.2-0.5m (building connections).

districtheatingsim.net_generation.osmnx_steiner_network.create_hast_connections(buildings: GeoDataFrame, offset_x: float = 1.0, offset_y: float = 0.0, include_building_data: bool = True) GeoDataFrame[source]

Create HAST (Hausanschlussstation) cross-connections with building metadata.

Parameters:
  • buildings (gpd.GeoDataFrame) – Building locations with Point geometries and attributes

  • offset_x (float) – Horizontal offset matching return network (meters)

  • offset_y (float) – Vertical offset matching return network (meters)

  • include_building_data (bool) – Include all building attributes in output

Returns:

HAST connections with LineStrings and metadata

Return type:

gpd.GeoDataFrame

Note

HAST = building substation connecting district network to building heating system.

districtheatingsim.net_generation.osmnx_steiner_network.create_generator_connection(generator_coords: tuple[float, float], offset_x: float = 1.0, offset_y: float = 0.0, crs: str = 'EPSG:25833') GeoDataFrame[source]

Create Erzeugeranlage (generator) cross-connection between supply and return.

Parameters:
  • generator_coords (Tuple[float, float]) – (x, y) coordinates of generator location

  • offset_x (float) – Horizontal offset matching return network (meters)

  • offset_y (float) – Vertical offset matching return network (meters)

  • crs (str) – Coordinate reference system

Returns:

Generator connection with LineString geometry

Return type:

gpd.GeoDataFrame

districtheatingsim.net_generation.osmnx_steiner_network.generate_osmnx_network(buildings: GeoDataFrame, generator_coords: list[tuple[float, float]], output_dir: str, return_offset: float = 1.0, buffer_meters: float = 500.0, network_type: str = 'drive_service', custom_filter: str | None = None, node_threshold: float = 0.1, remove_dead_ends_flag: bool = True, max_dead_end_iterations: int = 10, include_building_data: bool = True, export_geojson: bool = True, target_crs: str = 'EPSG:25833') dict[str, Any][source]

Generate complete district heating network using OSMnx and Steiner Tree.

Parameters:
  • buildings (gpd.GeoDataFrame) – Building locations with Point geometries in projected CRS

  • generator_coords (List[Tuple[float, float]]) – List of (x, y) generator coordinates in same CRS

  • output_dir (str) – Directory for output GeoJSON files

  • return_offset (float) – Horizontal offset for return network (meters)

  • buffer_meters (float) – Buffer around buildings for street download

  • network_type (str) – OSM network type (‘drive’, ‘drive_service’, etc.)

  • custom_filter (Optional[str]) – Custom OSM filter (overrides network_type)

  • node_threshold (float) – Distance threshold for node vs edge connection

  • remove_dead_ends_flag (bool) – Remove dead-end segments

  • max_dead_end_iterations (int) – Maximum iterations for dead-end removal

  • include_building_data (bool) – Include building metadata in HAST output

  • export_geojson (bool) – Export results to GeoJSON files

  • target_crs (str) – Target coordinate reference system

Returns:

Dictionary with network GeoDataFrames and statistics

Return type:

Dict[str, Any]

Raises:

Note

Exports unified Wärmenetz.geojson with supply, return, HAST, and generator networks.

districtheatingsim.net_generation.osmnx_steiner_network.generate_and_export_osmnx_layers(osm_street_layer_geojson_file_name: str, data_csv_file_name: str, coordinates: list[tuple[float, float]], base_path: str, algorithm: str = 'OSMnx', offset_angle: float = 0, offset_distance: float = 0.5, buffer_meters: float = 500.0, network_type: str = 'drive_service', custom_filter: str | None = None, node_threshold: float = 0.1, remove_dead_ends_flag: bool = True, target_crs: str = 'EPSG:25833') None[source]

Generate OSMnx-based district heating network and export as GeoJSON files.

Parameters:
  • osm_street_layer_geojson_file_name (str) – OSM street network (not used in OSMnx mode)

  • data_csv_file_name (str) – Building data CSV with UTM_X and UTM_Y columns

  • coordinates (List[Tuple[float, float]]) – List of (x, y) generator coordinates

  • base_path (str) – Base directory for export (creates Wärmenetz subdirectory)

  • algorithm (str) – Network generation algorithm identifier

  • offset_angle (float) – Angle for return line offset (degrees)

  • offset_distance (float) – Distance for return line separation (meters)

  • buffer_meters (float) – Buffer around buildings for street download

  • network_type (str) – OSM network type

  • custom_filter (Optional[str]) – Custom OSM filter (overrides network_type)

  • node_threshold (float) – Distance threshold for node vs edge connection

  • remove_dead_ends_flag (bool) – Remove dead-end segments

  • target_crs (str) – Target coordinate reference system

Raises:

Note

GUI-compatible interface matching generate_and_export_layers() for threading.