Skip to content

Modifying Network Elements

This guide covers common patterns for modifying existing networks: finding elements, changing properties, bulk updates, adding notes, and deleting elements.

Full Example

View the complete code: 03_modify_network.py

Loading and Finding Elements

Load an Existing Network

python
from pyptp import NetworkMV, configure_logging

configure_logging(level="INFO")

network = NetworkMV.from_file("network.vnf")

Find Elements by Name

python
from uuid import UUID
from pyptp.elements.element_utils import Guid

# Get GUID string by name
node_guid_str = network.get_node_guid_by_name("Substation_01")

# Convert to Guid object for dictionary lookup
node_guid = Guid(UUID(node_guid_str))

# Access the element
node = network.nodes[node_guid]

Why Two GUID Types?

TypeUsage
strHuman-readable, returned by lookup methods
GuidDictionary key type, wraps UUID for proper hashing

The conversion Guid(UUID(guid_str)) is required because Python's dict uses the object's hash for lookups, and Guid provides the correct hash implementation.

Find by Iteration

python
# Find first node matching a condition
target_node = next(
    (n for n in network.nodes.values() if n.general.unom > 20.0),
    None
)

# Find all loads above threshold
large_loads = [
    load for load in network.loads.values()
    if load.general.P > 500.0
]
Find

Modifying Properties

Single Element Update

python
from pyptp.ptp_log import logger

node.general.unom = 11.0  # Change voltage from 10kV to 11kV
logger.info("Updated {} voltage to {}kV", node.general.name, node.general.unom)

Properties are accessed through the element's nested dataclass structure:

text
element
├── general          # Core properties (name, GUID, etc.)
│   ├── name
│   ├── guid
│   └── unom
├── presentations    # Visual data
└── [other groups]   # Element-specific (protection, etc.)

Bulk Updates

python
# Increase all loads by 10%
for load in network.loads.values():
    load.general.P *= 1.1
    load.general.Q *= 1.1

logger.info("Scaled {} loads by 10%", len(network.loads))

Conditional Updates

python
# Update only loads on specific node
target_node_guid = network.get_node_guid_by_name("Substation_A")

for load in network.loads.values():
    if str(load.general.node) == target_node_guid:
        load.general.P *= 1.2
Modify

Adding Notes

Elements support notes for documentation and audit trails:

python
from pyptp.elements.mixins import Note

line = next(iter(network.lines.values()))
line.notes.append(Note(text="Verified 2025-01"))

Note Properties

PropertyDescription
textThe note content
authorOptional author name
timestampOptional creation time

Notes are preserved through save/load cycles and appear in Gaia/Vision.

Annotate

Deleting Elements

Delete by GUID

python
# Get the GUID of the element to delete
source_guid = next(iter(network.sources.keys()))

# Remove from the collection
del network.sources[source_guid]

Delete with Validation

python
def safe_delete_source(network, guid):
    """Delete source if it exists, return success status."""
    if guid in network.sources:
        del network.sources[guid]
        return True
    return False

Cascading Deletions

Deleting a node does not automatically delete connected branches or elements. You must manually remove dependent elements to maintain network integrity.

Delete Connected Elements

python
def delete_node_cascade(network, node_guid):
    """Delete a node and all elements referencing it."""
    # Remove loads connected to this node
    loads_to_delete = [
        guid for guid, load in network.loads.items()
        if load.general.node == node_guid
    ]
    for guid in loads_to_delete:
        del network.loads[guid]

    # Remove lines connected to this node
    lines_to_delete = [
        guid for guid, line in network.lines.items()
        if line.general.node1 == node_guid or line.general.node2 == node_guid
    ]
    for guid in lines_to_delete:
        del network.lines[guid]

    # Finally remove the node
    del network.nodes[node_guid]
Delete

Saving Changes

python
network.save("network_modified.vnf")
logger.info("Network modifications saved")

Save to Different File

Saving to a new filename preserves the original:

python
# Load original
network = NetworkMV.from_file("original.vnf")

# Make modifications
# ...

# Save as new file (original unchanged)
network.save("modified.vnf")
Save

Complete Example

python
"""Modify existing network elements."""

from uuid import UUID

from pyptp import NetworkMV, configure_logging
from pyptp.elements.element_utils import Guid
from pyptp.elements.mixins import Note
from pyptp.ptp_log import logger

configure_logging(level="INFO")

# Load network
network = NetworkMV.from_file("network.vnf")

# Find and modify a node by name
node_guid_str = network.get_node_guid_by_name("Substation_01")
node_guid = Guid(UUID(node_guid_str))
node = network.nodes[node_guid]
node.general.unom = 11.0
logger.info("Updated {} voltage to {}kV", node.general.name, node.general.unom)

# Modify all loads
for load in network.loads.values():
    load.general.P *= 1.1
    load.general.Q *= 1.1
logger.info("Scaled {} loads by 10%", len(network.loads))

# Add note to specific element
line = next(iter(network.lines.values()))
line.notes.append(Note(text="Verified 2025-01"))

# Delete element
del network.sources[next(iter(network.sources.keys()))]

# Save modified network
network.save("network_modified.vnf")
logger.info("Network modifications saved")

Next Steps