NetworkX Integration
This guide covers converting PyPtP networks to NetworkX graphs for analysis, visualization, and export to other formats.
Full Example
View the complete code: 07_NetworkX.py
Overview
Converting to NetworkX lets you:
- Analyze topology (connectivity, paths, cycles)
- Detect isolated sections
- Visualize networks with matplotlib
- Export to standard graph formats (GraphML, GEXF, JSON)
- Apply graph algorithms (shortest path, centrality, clustering)
Converting Networks
Balanced Networks (VNF/Vision)
python
from pyptp.graph.networkx_converter import NetworkxConverter
from pyptp.IO.importers.vnf_importer import VnfImporter
# Load balanced network
vnf_importer = VnfImporter()
mv_network = vnf_importer.import_vnf("network.vnf")
# Convert to NetworkX graph
mv_graph = NetworkxConverter.graph_mv(mv_network)Unbalanced Networks (GNF/Gaia)
python
from pyptp.IO.importers.gnf_importer import GnfImporter
# Load unbalanced network
gnf_importer = GnfImporter()
lv_network = gnf_importer.import_gnf("network.gnf")
# Convert to NetworkX graph
lv_graph = NetworkxConverter.graph_lv(lv_network)Using the High-Level API
python
from pyptp import NetworkMV, NetworkLV
# Alternative: use the Network classes directly
mv_network = NetworkMV.from_file("network.vnf") # Balanced model
lv_network = NetworkLV.from_file("network.gnf") # Unbalanced model
# Then convert
mv_graph = NetworkxConverter.graph_mv(mv_network)
lv_graph = NetworkxConverter.graph_lv(lv_network)Graph Structure
The converter represents all network elements as graph nodes:
| Graph Node Type | PyPtP Element |
|---|---|
| Network node | Busbar, junction |
| Branch | Cable, link, transformer, reactance coil |
| Element | Load, source, generator, battery, PV, etc. |
| Secondary | Fuse, load switch, circuit breaker, measure field |
Edges represent connections between these nodes:
- Network nodes connect to branches via edges
- Elements connect to their parent network node via an edge
- Secondary elements are inserted in the path between network nodes and branches
python
# Example graph structure for a simple network:
# NetworkNode1 ─── Cable ─── NetworkNode2
# │
# Load
# Becomes this graph:
# Nodes: [NetworkNode1, Cable, NetworkNode2, Load]
# Edges: [NetworkNode1-Cable, Cable-NetworkNode2, NetworkNode2-Load]This design makes it easy to:
- Find all elements connected to a network node
- Trace paths through the network
- Identify equipment between any two points
python
print(f"MV Network: {mv_graph.number_of_nodes()} nodes, {mv_graph.number_of_edges()} edges")
print(f"LV Network: {lv_graph.number_of_nodes()} nodes, {lv_graph.number_of_edges()} edges")Network Analysis
Connectivity Check
python
import networkx as nx
# Check if entire network is connected
is_connected = nx.is_connected(mv_graph)
print(f"Network is connected: {is_connected}")Find Disconnected Sections
python
# Get all connected components
components = list(nx.connected_components(mv_graph))
print(f"Number of separate sections: {len(components)}")
# Largest component
largest = max(components, key=len)
print(f"Largest section has {len(largest)} nodes")Path Analysis
python
# Find shortest path between two nodes
source_node = "node_guid_1"
target_node = "node_guid_2"
if nx.has_path(mv_graph, source_node, target_node):
path = nx.shortest_path(mv_graph, source_node, target_node)
print(f"Path length: {len(path)} nodes")
else:
print("No path exists between nodes")Network Statistics
python
# Degree distribution (connections per node)
degrees = dict(mv_graph.degree())
avg_degree = sum(degrees.values()) / len(degrees)
print(f"Average connections per node: {avg_degree:.2f}")
# Find nodes with most connections
max_degree_node = max(degrees, key=degrees.get)
print(f"Most connected node: {max_degree_node} ({degrees[max_degree_node]} connections)")
# Network diameter (longest shortest path)
if nx.is_connected(mv_graph):
diameter = nx.diameter(mv_graph)
print(f"Network diameter: {diameter}")Querying by Element Type
Each graph node stores its element type:
python
# Get element type for a node
node_type = mv_graph.nodes[node_guid].get('type')
# Find all cables
cables = [n for n, d in mv_graph.nodes(data=True) if d.get('type') == 'CableMV']
# Find all transformers
transformers = [n for n, d in mv_graph.nodes(data=True)
if d.get('type') in ('TransformerMV', 'ThreewindingTransformerMV')]
# Count elements by type
from collections import Counter
type_counts = Counter(d.get('type') for n, d in mv_graph.nodes(data=True))
for element_type, count in type_counts.most_common():
print(f"{element_type}: {count}")Cycle Detection
python
# Find all cycles (loops in network)
cycles = nx.cycle_basis(mv_graph)
print(f"Number of loops: {len(cycles)}")
# Networks with loops may need special handling for load flowVisualization
Basic Plot
python
import matplotlib.pyplot as plt
import networkx as nx
plt.figure(figsize=(12, 8))
nx.draw(mv_graph, with_labels=True, node_size=300, font_size=8)
plt.title("Network Topology")
plt.savefig("network_graph.png", dpi=150)
plt.show()Custom Layout
python
# Spring layout (force-directed)
pos = nx.spring_layout(mv_graph, k=2, iterations=50)
# Or use spectral layout for cleaner visualization
pos = nx.spectral_layout(mv_graph)
nx.draw(mv_graph, pos, with_labels=True)Export Formats
NetworkX supports many export formats for interoperability:
GraphML (XML-based)
python
nx.write_graphml(mv_graph, "network.graphml")GEXF (Gephi format)
python
nx.write_gexf(mv_graph, "network.gexf")JSON (Web-friendly)
python
from networkx.readwrite import json_graph
import json
data = json_graph.node_link_data(mv_graph)
with open("network.json", "w") as f:
json.dump(data, f, indent=2)Adjacency List
python
nx.write_adjlist(mv_graph, "network.adjlist")Complete Example
python
"""NetworkX Usage Examples.
Demonstrates how to convert electrical networks to NetworkX graphs
for analysis and visualization.
Graph Structure:
- All network elements (nodes, branches, elements) become graph NODES
- Edges represent connections between elements
- Each graph node has a 'type' attribute with the element class name
"""
from pyptp.graph.networkx_converter import NetworkxConverter
from pyptp.IO.importers.gnf_importer import GnfImporter
from pyptp.IO.importers.vnf_importer import VnfImporter
# Convert MV network to NetworkX graph
vnf_importer = VnfImporter()
mv_network = vnf_importer.import_vnf("PATH_TO_VNF")
mv_graph = NetworkxConverter.graph_mv(mv_network)
# Convert LV network to NetworkX graph
gnf_importer = GnfImporter()
lv_network = gnf_importer.import_gnf("PATH_TO_GNF")
lv_graph = NetworkxConverter.graph_lv(lv_network)
# Basic statistics
print(f"MV Network: {mv_graph.number_of_nodes()} nodes, {mv_graph.number_of_edges()} edges")
print(f"LV Network: {lv_graph.number_of_nodes()} nodes, {lv_graph.number_of_edges()} edges")
# Example: Use NetworkX algorithms
import networkx as nx
# Check if network is connected
is_connected = nx.is_connected(mv_graph)
print(f"Network is connected: {is_connected}")
# Query element types from the graph
# Each node has a 'type' attribute with the element class name
for node, attrs in mv_graph.nodes(data=True):
print(f"Node {node}: type={attrs.get('type')}")
# Find all nodes of a specific type
cables = [n for n, d in mv_graph.nodes(data=True) if d.get('type') == 'CableMV']
print(f"Found {len(cables)} cables")
# Find shortest path between nodes
# path = nx.shortest_path(mv_graph, source_node, target_node)
# Export to various NetworkX formats
# nx.write_gexf(mv_graph, "network.gexf")
# nx.write_graphml(mv_graph, "network.graphml")