Skip to content

Translate Sienna to PLEXOS

Parse the source model, translate its components, and export the target model.

Translation source · Configuration

PLEXOS does not distinguish all of the generator families represented by Sienna. The reverse translation therefore collapses multiple Sienna generator types into PLEXOSGenerator, with the exported category and memberships preserving the information PLEXOS can represent.

flowchart LR
  S["Sienna components"] --> N["Resolve topology"]
  S --> G["Map generator families"]
  N --> P["PLEXOS objects"]
  G --> P
  T["Time series"] -. "aggregate hydro budgets" .-> P
  class S source
  class N,G process
  class P target
  class T data
  classDef source fill:#d9effa,stroke:#0079c2,color:#003a69,stroke-width:2px
  classDef process fill:#f4f7f9,stroke:#7890a0,color:#293d4d
  classDef target fill:#003a69,stroke:#003a69,color:#ffffff,stroke-width:2px
  classDef data fill:#fff7e6,stroke:#c58625,color:#684716

ThermalStandard, ThermalMultiStart, HydroDispatch, HydroEnergyReservoir, HydroTurbine, HydroPumpTurbine, RenewableDispatch, and RenewableNonDispatch all export as PLEXOSGenerator. PLEXOS-specific category values and memberships are added by the translation helpers after rule application.

For field-by-field mappings, see Sienna to PLEXOS property mappings.

Use Python 3.11–3.13 and uv. From this repository checkout, replace the editable package paths below with your local parser and exporter checkouts. These commands update the workspace environment and lockfile:

First, install the dependencies pinned by this checkout:

Terminal window
uv sync

Add your source parser checkout so the script can read the native input model:

Terminal window
uv add --editable /path/to/r2x-sienna

Add the target parser/exporter checkout, then verify that the command completes before running the Python example:

Terminal window
uv add --editable /path/to/r2x-plexos

Replace the model paths and years with your input data. A successful run writes the target model and time-series files to the configured results directory. run() executes the plugin lifecycle and raises an error if a hook fails.

from pathlib import Path
from typing import cast
from r2x_plexos import PLEXOSConfig
from r2x_plexos.exporter import PLEXOSExporter
from r2x_sienna.parser import SiennaParser
from r2x_sienna.plugin_config import SiennaConfig
from r2x_sienna_to_plexos.plugin_config import SiennaToPlexosConfig
from r2x_sienna_to_plexos.translation import sienna_to_plexos
from r2x_core import DataStore, PluginContext
from r2x_core.logger import setup_logging
setup_logging(verbosity=1)
base_path = Path("/path/to/sienna-to-plexos")
sys_name = "EI_PCM_2023_2012"
sys_folder = base_path / sys_name
# Sienna PARSER
model_year = 2023
weather_year = 2012
json_path = sys_folder / f"{sys_name}.json"
sienna_config = SiennaConfig(
json_path=str(json_path),
model_year=model_year,
system_name=sys_name,
skip_validation=True,
models=("r2x_sienna.models", "r2x_plexos.models", "r2x_sienna_to_plexos.getters"),
)
store = DataStore.from_data_files([], path=json_path.parent)
context = PluginContext(config=sienna_config, store=store, skip_validation=True)
parser = cast(SiennaParser, SiennaParser.from_context(context))
sienna_sys = parser.run()
sienna_sys = sienna_sys.system
# Define Time Series Storage
plexos_sys = sienna_to_plexos(sienna_sys, SiennaToPlexosConfig())
# PLEXOS Exporter
results_dir = base_path / f"{sys_name}_results"
results_dir.mkdir(exist_ok=True)
plexos_config = PLEXOSConfig(model_name=sys_name, timeseries_dir=str(results_dir), horizon_year=model_year)
exporter_context = PluginContext(config=plexos_config, system=plexos_sys)
exporter = PLEXOSExporter.from_context(exporter_context)
exporter.output_path = results_dir
exporter.solve_year = model_year
exporter.weather_year = weather_year
exporter.run()

To export hydro budgets as monthly profiles instead of the default weekly aggregation, set SiennaToPlexosConfig(hydro_budget_ts="monthly") in the call to sienna_to_plexos.