Building Networks from Scratch
This guide walks through creating an electrical network programmatically. You'll learn how to create sheets, nodes, branches, and elements with proper presentations for visualization in Gaia/Vision.
Full Example
View the complete code: 02_build_network.py
Overview
Building a network from scratch involves four key concepts:
- Sheets: Canvas pages where network elements are displayed
- Nodes: Electrical connection points (busbars, substations)
- Branches: Elements connecting two nodes (lines, cables, links)
- Elements: Components attached to a single node (sources, loads)
Every element requires a presentation: visual metadata defining how it appears on a sheet.
Create the Network and Sheet
from pyptp import NetworkMV, configure_logging
from pyptp.elements.color_utils import CL_GRAY
from pyptp.elements.element_utils import Guid
from pyptp.elements.mv.sheet import SheetMV
configure_logging(level="INFO")
# Create an empty network
network = NetworkMV()
# Create a sheet (required for any visual elements)
sheet = SheetMV(SheetMV.General(name="Main", color=CL_GRAY))
sheet.register(network)
sheet_guid: Guid = sheet.general.guidWhat's being imported?
NetworkMV: Empty balanced network containerconfigure_logging: Enables PyPtP's logging outputCL_GRAY: Predefined sheet color constantGuid: Type alias for GUID stringsSheetMV: Sheet element class
Key Concepts
register(network)adds the element to the network's internal collections and assigns a GUID if not already setsheet.general.guidretrieves the auto-generated GUID for referencing this sheet later
Color Constants
PyPtP provides predefined colors: CL_GRAY, CL_BLUE, CL_GREEN, CL_RED from pyptp.elements.color_utils.
Create Nodes
from pyptp.elements.mv.node import NodeMV
from pyptp.elements.mv.presentations import NodePresentation
# Create source node
source_node = NodeMV(
NodeMV.General(name="Source", unom=10.0),
presentations=[NodePresentation(sheet=sheet_guid, x=150, y=250)],
)
source_node.register(network)
# Create load node
load_node = NodeMV(
NodeMV.General(name="Load", unom=10.0),
presentations=[NodePresentation(sheet=sheet_guid, x=450, y=250)],
)
load_node.register(network)Node Structure
Nodes are constructed with:
| Parameter | Description |
|---|---|
General | Core properties: name, nominal voltage (unom), GUID |
presentations | List of visual positions on sheets |
NodePresentation
Nodes require a NodePresentation specifying the sheet, x, and y position. Optional parameters include symbol and size.
Full Reference
See Presentations Guide for all parameters.
Create a Source
from pyptp.elements.mv.source import SourceMV
from pyptp.elements.mv.presentations import ElementPresentation
source = SourceMV(
SourceMV.General(node=source_node.general.guid, sk2nom=100.0),
presentations=[ElementPresentation(sheet=sheet_guid, x=150, y=100)],
)
source.general.sk2nom = 900.0 # Modify after creation
source.register(network)Source Properties
node: GUID of the node this source is connected tosk2nom: Two-phase short-circuit power in MVA (grid strength indicator)
Sources use ElementPresentation which positions the symbol near its connected node.
Modifying Properties
Element properties can be modified after construction but before or after register(). The example shows setting sk2nom after initial construction.
Connect Nodes with a Branch
from pyptp.elements.mv.link import LinkMV
from pyptp.elements.mv.presentations import BranchPresentation
link = LinkMV(
LinkMV.General(node1=source_node.general.guid, node2=load_node.general.guid),
presentations=[
BranchPresentation(
sheet=sheet_guid,
first_corners=[(150, 250), (300, 250)],
second_corners=[(450, 250)],
)
],
)
link.general.switch_state1 = 1 # Switch closed at node1
link.general.switch_state2 = 1 # Switch closed at node2
link.register(network)Branch Presentation Coordinates
Branch presentations define the visual path:
first_corners: Polyline starting from node1, traveling outwardsecond_corners: Polyline starting from node2, traveling outward
The rendering engine draws a connection between the last point of each list.
first_corners: [(150,250), (300,250)]second_corners: [(450,250)]Common Mistake
second_corners must start at node2, not end at it.
Deep Dive
See Branch Corners for complex routing patterns.
Switch States
| Value | Meaning |
|---|---|
0 | Switch open (disconnected) |
1 | Switch closed (connected) |
Add a Load
from pyptp.elements.mv.load import LoadMV
load = LoadMV(
LoadMV.General(node=load_node.general.guid, P=100.0, Q=50.0),
presentations=[ElementPresentation(sheet=sheet_guid, x=450, y=350)],
)
load.register(network)Load Properties
| Property | Unit | Description |
|---|---|---|
P | kW | Active power consumption |
Q | kVAr | Reactive power consumption |
Save the Network
from pyptp.ptp_log import logger
network.save("simple_network.vnf")
logger.info("Network created with {} nodes and {} links", len(network.nodes), len(network.links))The save() method serializes all elements to the VNF format.
Complete Example
"""Build a simple network from scratch."""
from pyptp import NetworkMV, configure_logging
from pyptp.elements.color_utils import CL_GRAY
from pyptp.elements.element_utils import Guid
from pyptp.elements.mv.link import LinkMV
from pyptp.elements.mv.load import LoadMV
from pyptp.elements.mv.node import NodeMV
from pyptp.elements.mv.presentations import BranchPresentation, ElementPresentation, NodePresentation
from pyptp.elements.mv.sheet import SheetMV
from pyptp.elements.mv.source import SourceMV
from pyptp.ptp_log import logger
configure_logging(level="INFO")
# Create balanced network (works for any voltage level)
network = NetworkMV()
# Create sheet
sheet = SheetMV(SheetMV.General(name="Main", color=CL_GRAY))
sheet.register(network)
sheet_guid: Guid = sheet.general.guid
# Create source node
source_node = NodeMV(
NodeMV.General(name="Source", unom=10.0),
presentations=[NodePresentation(sheet=sheet_guid, x=150, y=250)],
)
source_node.register(network)
# Create source
source = SourceMV(
SourceMV.General(node=source_node.general.guid, sk2nom=100.0),
presentations=[ElementPresentation(sheet=sheet_guid, x=150, y=100)],
)
source.general.sk2nom = 900.0
source.register(network)
# Create load node
load_node = NodeMV(
NodeMV.General(name="Load", unom=10.0),
presentations=[NodePresentation(sheet=sheet_guid, x=450, y=250)],
)
load_node.register(network)
# Connect with link
link = LinkMV(
LinkMV.General(node1=source_node.general.guid, node2=load_node.general.guid),
presentations=[
BranchPresentation(
sheet=sheet_guid,
first_corners=[(150, 250), (300, 250)],
second_corners=[(450, 250)],
)
],
)
link.general.switch_state1 = 1
link.general.switch_state2 = 1
link.register(network)
# Add load
load = LoadMV(
LoadMV.General(node=load_node.general.guid, P=100.0, Q=50.0),
presentations=[ElementPresentation(sheet=sheet_guid, x=450, y=350)],
)
load.register(network)
# Save
network.save("simple_network.vnf")
logger.info("Network created with {} nodes and {} links", len(network.nodes), len(network.links))