Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 52 additions & 66 deletions CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ This software is released under a BSD-3-Clause
[License](https://github.com/NatLabRockies/plexosdb/blob/main/LICENSE.txt).

This software was developed under software record SWR-24-90 at the National
Renewable Energy Laboratory ([NREL](https://www.nrel.gov)).
Laboratory of the Rockies (NLR).

## Disclaimer

Expand Down
14 changes: 14 additions & 0 deletions docs/source/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

All notable changes to this project will be documented in this file.

## [1.6.1] - 2026-08-11

### Documentation

- Updated property examples to use the current `datafile_text` and `timeslice`
arguments.
- Documented the current bulk property-record formats and deprecation warning
for the legacy nested format.
- Expanded solution inspection guidance for the 1.6.1 release.

## Current Documentation Updates

- Corrected simulation phase mappings in the report how-to and tutorial.

## [1.0.0] - 2025-04-07

### 🚀 Features
Expand Down
16 changes: 16 additions & 0 deletions docs/source/api/checks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Checks

Validation helpers for checking classes, objects, collections, memberships,
properties, attributes, scenarios, data records, and tags in a `PlexosDB`
database.

```{eval-rst}
.. automodule:: plexosdb.checks
:members:
:undoc-members:
:show-inheritance:
```

The helpers accept a `PlexosDB` instance as their first argument. The same
checks are also available as convenience methods on `PlexosDB` where the class
exposes them.
28 changes: 28 additions & 0 deletions docs/source/api/db_solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# DuckDB Solution Reader

The DuckDB solution reader converts a PLEXOS solution ZIP with `plexos2duckdb`
and exposes lazy DuckDB relations for analysis. Import it explicitly to
distinguish it from the SQLite-backed solution reader:

```python
from plexosdb.db_solution import PlexosSolution
```

```{eval-rst}
.. automodule:: plexosdb.db_solution
:members:
:undoc-members:
:show-inheritance:
```

## Result Types

```{eval-rst}
.. automodule:: plexosdb.db_solution_models
:members:
:undoc-members:
:show-inheritance:
```

See [Reading a PLEXOS Solution](../howtos/read_solution.md) for a complete
ZIP-to-DuckDB workflow.
3 changes: 3 additions & 0 deletions docs/source/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ behavior.
:maxdepth: 2

plexosdb
checks
db_solution
solution_reader
model_attributes
production_attributes
performance_attributes
Expand Down
14 changes: 14 additions & 0 deletions docs/source/api/plexosdb.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# PlexosDB Class

The reference below includes the complete `PlexosDB` class surface. Some
declared methods are reserved for future implementation and currently raise
`NotImplementedError`; they are listed in the API for transparency but should
not be used as supported workflows yet.

Currently unimplemented methods include `add_custom_column`, `add_metadata`,
`add_time_slice`, `add_variable_tag`, `backup_database`,
`create_object_scenario`, `delete_category`, `delete_membership`,
`delete_metadata`, `delete_text`, `get_config`, `get_custom_columns`,
`get_metadata`, `get_property_unit`, `get_text`, `get_unit`, `import_from_csv`,
`list_reports`, `set_config`, `set_date_range`, `to_csv`, `update_attribute`,
`update_category`, `update_properties`, `update_property`, `update_scenario`,
`update_text`, and `validate_database`.

```{eval-rst}
.. automodule:: plexosdb.db
:members:
Expand Down
37 changes: 37 additions & 0 deletions docs/source/api/solution_reader.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# SQLite Solution Reader

The SQLite solution reader imports a PLEXOS solution ZIP into SQLite and
materializes derived result tables for analysis. Import it explicitly to
distinguish it from the DuckDB-backed solution wrapper:

```python
from plexosdb.solution_reader import PlexosSolution
```

```{eval-rst}
.. automodule:: plexosdb.solution_reader.solution
:members:
:undoc-members:
:show-inheritance:
```

## Display Helpers

```{eval-rst}
.. automodule:: plexosdb.solution_reader.display
:members:
:undoc-members:
:show-inheritance:
```

## Result Types

```{eval-rst}
.. automodule:: plexosdb.solution_reader.types
:members:
:undoc-members:
:show-inheritance:
```

See [Inspecting a PLEXOS Solution](../howtos/inspect_solution.md) for a complete
ZIP-to-SQLite workflow.
6 changes: 3 additions & 3 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
project = "plexosdb"
copyright = "2024, Alliance for Sustainable Energy LLC, All rights reserved."
author = "pesap"
release = "1.0"
release = "1.6.1"
extensions = [
"myst_parser",
"sphinx.ext.githubpages",
Expand All @@ -29,13 +29,13 @@
html_title = "plexosdb"
html_theme_options = {
"navigation_with_keys": True,
"source_repository": "https://github.com/NREL/plexosdb/",
"source_repository": "https://github.com/NatLabRockies/plexosdb/",
"source_branch": "main",
"source_directory": "docs/",
"footer_icons": [
{
"name": "GitHub",
"url": "https://github.com/NREL/plexosdb",
"url": "https://github.com/NatLabRockies/plexosdb",
"html": """
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
Expand Down
2 changes: 1 addition & 1 deletion docs/source/howtos/add_attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ from plexosdb.enums import ClassEnum, CollectionEnum

# Initialize database
db = PlexosDB()
db.create_schema()
db.create_schema(version=10)

# Create a generator object if it doesn't exist
if not db.check_object_exists(ClassEnum.Generator, "Generator1"):
Expand Down
2 changes: 1 addition & 1 deletion docs/source/howtos/add_objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ from plexosdb.enums import ClassEnum

# Initialize database
db = PlexosDB()
db.create_schema()
db.create_schema(version=10)

# Add a generator object
db.add_object(
Expand Down
89 changes: 74 additions & 15 deletions docs/source/howtos/add_properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
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

```python
Expand All @@ -11,11 +15,12 @@ from plexosdb.enums import ClassEnum, CollectionEnum

# Initialize database
db = PlexosDB()
db.create_schema()
db.create_schema(version=10)

# Create a generator object if it doesn't exist
if not db.check_object_exists(ClassEnum.Generator, "Generator1"):
db.add_object(ClassEnum.Generator, "Generator1")
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(
Expand All @@ -28,7 +33,7 @@ db.add_property(
# Add another property
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
object_name="Generator2",
name="Min Stable Level",
value=20.0
)
Expand Down Expand Up @@ -64,34 +69,81 @@ db.add_property(
)
```

## Adding Text Data to Properties
## Adding DataFile and Timeslice Text

Properties can include additional text information:
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.

```python
from plexosdb.enums import ClassEnum
# 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",
)

# Add a property with text data
# Attach timeslice metadata when the property is timeslice-specific.
db.add_property(
ClassEnum.Generator,
object_name="Generator1",
name="Max Capacity", # Use a valid property name
value="Main unit",
text={ClassEnum.Generator: "Primary generation unit"}
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.

```python
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.

## Bulk Adding Properties

For efficiency when adding many properties at once (use the flat format; the
nested format is accepted but deprecated and will emit a warning):
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.

```python
# 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"},
{
"name": "Generator2",
Comment thread
mcllerena marked this conversation as resolved.
"property": "Heat Rate",
"value": 9.9,
"datafile_text": "gen2.csv",
"timeslice": "Peak",
},
]

# Nested format (legacy; will be removed in the future)
Expand All @@ -108,6 +160,11 @@ db.add_properties_from_records(
)
```

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:
Expand All @@ -123,5 +180,7 @@ print(f"Valid generator properties: {valid_props}")
```

```{warning}
Adding an invalid property will raise a NameError. Always check if properties are valid for your collection.
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.
```
2 changes: 1 addition & 1 deletion docs/source/howtos/add_reports.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ from plexosdb.enums import ClassEnum, CollectionEnum

# Create or open a database
db = PlexosDB()
db.create_schema()
db.create_schema(version=10)

# First, create a Report object
db.add_object(ClassEnum.Report, "Generator Outputs")
Expand Down
4 changes: 2 additions & 2 deletions docs/source/howtos/bulk_operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ from plexosdb.enums import ClassEnum, CollectionEnum

# Initialize the database
db = PlexosDB()
db.create_schema()
db.create_schema(version=10)

# Create the objects first
db.add_object(ClassEnum.Generator, "Generator1")
Expand Down Expand Up @@ -134,7 +134,7 @@ from plexosdb.utils import create_membership_record

# Initialize the database
db = PlexosDB()
db.create_schema()
db.create_schema(version=10)

# Create parent and child objects
region_id = db.add_object(ClassEnum.Region, "MainRegion")
Expand Down
2 changes: 1 addition & 1 deletion docs/source/howtos/delete_objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ from plexosdb.enums import ClassEnum

# Initialize database
db = PlexosDB()
db.create_schema()
db.create_schema(version=10)

# Add a simple test generator object
db.add_object(
Expand Down
Loading