Translate Sienna to PLEXOS
Parse the source model, translate its components, and export the target model.
Translation source · Configuration
Mapping Overview
Section titled “Mapping Overview”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
Generator Collapse
Section titled “Generator Collapse”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:
uv syncAdd your source parser checkout so the script can read the native input model:
uv add --editable /path/to/r2x-siennaAdd the target parser/exporter checkout, then verify that the command completes before running the Python example:
uv add --editable /path/to/r2x-plexosExample script
Section titled “Example script”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 Pathfrom typing import cast
from r2x_plexos import PLEXOSConfigfrom r2x_plexos.exporter import PLEXOSExporterfrom r2x_sienna.parser import SiennaParserfrom r2x_sienna.plugin_config import SiennaConfigfrom r2x_sienna_to_plexos.plugin_config import SiennaToPlexosConfigfrom r2x_sienna_to_plexos.translation import sienna_to_plexos
from r2x_core import DataStore, PluginContextfrom 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 PARSERmodel_year = 2023weather_year = 2012json_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 Storageplexos_sys = sienna_to_plexos(sienna_sys, SiennaToPlexosConfig())
# PLEXOS Exporterresults_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_direxporter.solve_year = model_yearexporter.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.