Net generation package
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:
FileNotFoundError – If GeoJSON file missing
ValueError – If invalid GeoJSON format
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]]) Tuple[GeoDataFrame | None, GeoDataFrame | None, GeoDataFrame | None, DataFrame | None][source]
Load all spatial layers for network generation.
- Parameters:
- 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:
FileNotFoundError – If files not found
KeyError – If UTM_X or UTM_Y missing from CSV
ValueError – If coordinate conversion fails
Note
CSV uses semicolon separator. Returns (None, None, None, None) on error.
- 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) None[source]
Generate district heating network and export as GeoJSON.
- 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)
- Raises:
FileNotFoundError – If input files not found
ValueError – If invalid algorithm or malformed data
OSError – If output directory cannot be created
Note
Exports unified GeoJSON to base_path/Wärmenetz/Wärmenetz.geojson in EPSG:25833.
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:
- 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]
Offset all LineStrings by fixed distance and angle.
- Parameters:
- Returns:
Offset LineStrings with preserved CRS
- Return type:
gpd.GeoDataFrame
Note
Creates parallel return lines from supply lines. Maintains topology and connectivity.
- 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:
- 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:
objectUnified 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.
- 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:
- 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.
- 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.
- static create_network_geojson(flow_lines: GeoDataFrame, return_lines: GeoDataFrame, building_connections: GeoDataFrame, generator_connections: GeoDataFrame, state: str = 'designed', calculated_data: Dict = None) 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
- 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.
- static split_to_legacy_format(geojson: Dict[str, Any]) Tuple[GeoDataFrame, GeoDataFrame, GeoDataFrame, GeoDataFrame][source]
Split unified GeoJSON into legacy 4-file format.
- Parameters:
geojson (Dict[str, Any]) – Unified network GeoJSON
- 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:
- 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”]’
- 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
- 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:
- 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:
- 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.
- 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:
- 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:
- 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:
- 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:
ValueError – If buildings is empty or has invalid CRS
FileNotFoundError – If output_dir cannot be created
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:
FileNotFoundError – If CSV file not found
KeyError – If required CSV columns missing
ValueError – If invalid data or parameters
ConnectionError – If OSM download fails
Note
GUI-compatible interface matching generate_and_export_layers() for threading.