Copying Objects¶
PlexosDB allows you to create copies of existing objects along with their properties, memberships, attributes and related property records.
Basic Object Copying¶
Copy an object and all its memberships, properties and attributes:
from plexosdb import PlexosDB
from plexosdb.enums import ClassEnum, CollectionEnum
# Initialize database
db = PlexosDB.from_xml("/path/to/model.xml")
# Assumes the model already contains a generator named "Generator1".
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Capacity",
value=100.0,
scenario="Base Case"
)
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Energy",
value=20.0,
scenario="Base Case"
)
# Copy a generator with its memberships, properties and attributes
new_object_id = db.copy_object(
object_class=ClassEnum.Generator,
original_object_name="Generator1",
new_object_name="Generator1_Copy",
copy_properties=True, # Default is True
copy_attributes=True # Default is True
)
print(f"Created new object with ID: {new_object_id}")
Note
Object-level attributes (stored in t_attribute_data) are also copied when using copy_object.
Copying Objects Without Properties¶
You can also copy only the object and its memberships by disabling property and attribute copying:
# Add Generator object
db.add_object(ClassEnum.Generator, "Generator1")
# Add property
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Capacity",
value=20.0,
scenario="Base Case"
)
# Copy object structure only
new_object_id = db.copy_object(
object_class=ClassEnum.Generator,
original_object_name="Generator1",
new_object_name="Generator1_Skeleton",
copy_properties=False,
copy_attributes=False
)
Copying Memberships¶
When copying an object, PlexosDB also attempts to copy its memberships (except any that cannot be recreated due to model constraints):
# First create some objects with memberships
db.add_object(ClassEnum.Region, "Region1")
db.add_object(ClassEnum.Node, "Node1")
# Add membership
db.add_membership(
parent_class_enum=ClassEnum.Region,
child_class_enum=ClassEnum.Node,
parent_object_name="Region1",
child_object_name="Node1",
collection_enum=CollectionEnum.ReferenceNode
)
# Now copy the node with its memberships
new_object_id = db.copy_object(
object_class=ClassEnum.Node,
original_object_name="Node1",
new_object_name="Node1_Copy",
copy_properties=False,
copy_attributes=False
)
# Check the memberships of the new object
memberships = db.list_object_memberships(
ClassEnum.Node,
name="Node1_Copy"
)
print(f"New object has {len(memberships)} memberships")
Programmatic Membership Copying¶
You can also copy all non-system memberships programmatically:
db.add_object(ClassEnum.Node, "Node1")
db.add_object(ClassEnum.Generator, "Generator1")
db.add_object(ClassEnum.Generator, "Generator1_Copy")
db.add_membership(
parent_class_enum=ClassEnum.Generator,
child_class_enum=ClassEnum.Node,
parent_object_name="Generator1",
child_object_name="Node1",
collection_enum=CollectionEnum.Nodes
)
membership_mapping = db.copy_object_memberships(
object_class=ClassEnum.Generator,
original_name="Generator1",
new_name="Generator1_Copy"
)
print(f"Copied {len(membership_mapping)} memberships")
Practical Example: Duplicating a Set of Objects¶
This example shows how to duplicate a group of related objects:
# Create a function to copy memberships from an existing generator
def duplicate_generator_with_connections(db, original_name, new_name):
# Create the new generator (memberships are copied manually below)
db.add_object(ClassEnum.Generator, new_name)
# Find and copy all connections
memberships = db.list_object_memberships(
ClassEnum.Generator,
name=original_name,
exclude_system_membership=True
)
# Process each membership to maintain the network structure
for membership in memberships:
if membership["parent_name"] == original_name:
# Original generator was the parent, connect child to new generator
db.add_membership(
parent_class_enum=ClassEnum[membership["parent_class_name"]],
child_class_enum=ClassEnum[membership["child_class_name"]],
parent_object_name=new_name,
child_object_name=membership["child_name"],
collection_enum=CollectionEnum[membership["collection_name"]]
)
else:
# Original generator was the child, connect new generator to parent
db.add_membership(
parent_class_enum=ClassEnum[membership["parent_class_name"]],
child_class_enum=ClassEnum[membership["child_class_name"]],
parent_object_name=membership["parent_name"],
child_object_name=new_name,
collection_enum=CollectionEnum[membership["collection_name"]]
)
return new_name
# Existing generator to duplicate
db.add_object(ClassEnum.Generator, "Generator1")
# Use the function to duplicate a generator with all its connections
duplicate_generator_with_connections(db, "Generator1", "Generator1_Full_Copy")
Note
When copying objects with properties that reference other objects (like “Node” for a generator), you may need to update these properties manually if you want them to reference different objects.