Adding Properties to Objects¶
Properties define attributes of objects in your PLEXOS model, such as a generator’s capacity or a node’s location.
The examples in this guide use the PlexosDB 1.6.1 API. The first argument to
add_property is positional-only; the remaining property arguments are passed
by name where that makes the example easier to read.
Basic Property Addition¶
from plexosdb import PlexosDB
from plexosdb.enums import ClassEnum, CollectionEnum
# Initialize database
db = PlexosDB()
db.create_schema(version=10)
# Create a generator object if it doesn't exist
for generator_name in ("Generator1", "Generator2", "Generator3"):
if not db.check_object_exists(ClassEnum.Generator, generator_name):
db.add_object(ClassEnum.Generator, generator_name)
# Add a property to the generator
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Capacity",
value=100.0
)
# Add another property
db.add_property(
ClassEnum.Generator,
object_name="Generator2",
name="Min Stable Level",
value=20.0
)
Adding Properties with Scenarios¶
Properties can be associated with specific scenarios:
# Add a property with a scenario
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Capacity",
value=120.0,
scenario="High Demand"
)
Adding Properties with Bands¶
For properties that have band data:
# Add a property with a band
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Heat Rate",
value=10.5,
band=1
)
Adding DataFile and Timeslice Text¶
Use datafile_text to attach file-path metadata to a property. This is the
supported replacement for the older text example; add_property does not
accept a text keyword. Use timeslice for timeslice metadata.
# Attach DataFile metadata to the property data record.
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Capacity",
value=100.0,
datafile_text="gen1.csv",
)
# Attach timeslice metadata when the property is timeslice-specific.
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Capacity",
value=110.0,
timeslice="Peak",
)
datafile_text and timeslice store text metadata on the property data record;
they do not change the property’s numeric or string value. A DataFile or
Timeslice object does not need to be created manually for these associations.
Adding Date- and Scenario-Specific Properties¶
Scenarios are created automatically when the supplied scenario does not yet
exist. Date bounds must be datetime objects.
from datetime import datetime
db.add_property(
ClassEnum.Generator,
"Generator1",
"Max Capacity",
120.0,
scenario="High Demand",
date_from=datetime(2030, 1, 1),
date_to=datetime(2030, 12, 31),
band=1,
)
For non-default memberships, pass collection_enum, parent_class_enum, and
optionally parent_object_name to select the membership to which the property
is added. When omitted, the default collection is selected, the parent class
defaults to ClassEnum.System, and the membership is resolved from the object
and collection.
Updating Properties¶
Use update_property to change the value of an existing property without
removing its scenario, band, date, or text metadata:
db.update_property(
"Generator1",
"Max Capacity",
125.0,
object_class=ClassEnum.Generator,
)
When a property has multiple bands, pass band to update only the matching
band. Pass scenario to update a scenario-specific value. If scenario is
omitted, only the base, non-scenario property is updated.
db.update_property(
"Generator1",
"Heat Rate",
9.8,
object_class=ClassEnum.Generator,
band=2,
scenario="High Demand",
)
The collection and parent_class arguments can be supplied when the property
belongs to a non-default collection or membership:
db.update_property(
"Generator1",
"Max Capacity",
130.0,
object_class=ClassEnum.Generator,
collection=CollectionEnum.Generators,
parent_class=ClassEnum.System,
)
The method raises NotFoundError when the object or matching property row does
not exist, and NameError when the property is invalid for the selected
collection.
Bulk Adding Properties¶
For efficiency when adding many properties at once, use flat records. Each flat
record contains name, property, and value; band, datafile_text, and
timeslice are optional per-record fields. The legacy nested format is still
accepted but deprecated and emits a warning.
# Flat format (recommended)
flat_records = [
{"name": "Generator1", "property": "Max Capacity", "value": 100, "band": 1},
{"name": "Generator1", "property": "Max Capacity", "value": 200, "band": 2},
{
"name": "Generator2",
"property": "Heat Rate",
"value": 9.9,
"datafile_text": "gen2.csv",
"timeslice": "Peak",
},
]
# Nested format (legacy; will be removed in the future)
nested_records = [
{"name": "Generator3", "properties": {"Max Capacity": {"value": 150, "band": 1}}},
]
db.add_properties_from_records(
flat_records + nested_records,
object_class=ClassEnum.Generator,
parent_class=ClassEnum.System,
collection=CollectionEnum.Generators,
scenario="Base Case",
)
The bulk method applies the supplied scenario to all records, defaults
parent_class to ClassEnum.System, and processes records in chunks of 10,000
by default. Set chunksize to tune memory use for larger imports. It uses a
transaction, so an insertion error rolls back the bulk operation.
Checking Valid Properties¶
Before adding properties, you can check if they are valid for a collection:
# Check if properties are valid
valid_props = db.list_valid_properties(
CollectionEnum.Generators,
parent_class_enum=ClassEnum.System,
child_class_enum=ClassEnum.Generator
)
print(f"Valid generator properties: {valid_props}")
Warning
Adding an invalid property raises NameError; a missing object raises
NotFoundError. Always check if properties are valid for your collection and
create the target object before adding its properties.