Sienna scaling and raw dataset access#
Sienna writes simulation results in per-unit; GAT scales them to MW for the
high-level get_* API. This page documents where the scaling factor
(base_power) comes from and how to access unscaled data when you need it.
Where base_power comes from#
GAT resolves base_power for a scenario in this order:
The h5 simulation file’s group attrs —
base_powerlives on each decision-model group (e.g./simulation/decision_models/UC/.attrs/base_power). This is the authoritative source for simulation results because PowerSimulations serializes the value the model actually used.sys.json’sunits_settings.base_value— fallback when the h5 attr is missing. This is the system-level base; it usually matches the simulation but may not (e.g. when a single system is used to run simulations at different bases).100.0— final fallback.100 MVAis the PowerSimulations.jl default, so this is almost always correct when the upstream sources are silent.
Why per-decision-model matters: a UC and an ED model in the same
simulation_store can in principle have different base_power. GAT looks at
the model attrs each time, not just at construction.
SiennaScenario.unit_base_value exposes the resolved value:
import gat
scenario, _, _ = gat.load(scenario="my_uc_scenario")
print(scenario.unit_base_value) # → 100.0 for an RTS-GMLC fixture
Reading unscaled data#
The high-level methods (get_generation, get_area_dispatch,
get_line_flow, etc.) return MW values (per-unit × base_power). For
unscaled data — the values exactly as they appear in the h5 file — use
get_raw_dataset:
import gat
scenario, _, _ = gat.load(scenario="my_uc_scenario")
# Short alias (resolved against the parser's emulation_model index):
raw = scenario.get_raw_dataset("ActivePowerVariable__ThermalStandard")
# Or a full h5 path:
raw = scenario.get_raw_dataset(
"/simulation/emulation_model/variables/ActivePowerVariable__ThermalStandard"
)
The DataFrame is timestamps × generators (no scaling applied). For an MW
view of the same data, use scenario.get_generation().
When to use which#
Task |
Use |
|---|---|
Plotting MW dispatch, computing reserve margins, comparing across scenarios |
High-level: |
Inspecting exactly what PowerSimulations wrote to disk |
|
Applying custom scaling (e.g. converting to GW, applying a different per-unit base) |
|
Debugging a scaling discrepancy |
|
Worked example with the v4 fixture#
import gat
from gat.scenariohandlers import SiennaScenario
# Skipping gat.load for a one-off path-based instantiation:
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
s = SiennaScenario(
simulation_files="example_data/sienna/v4/simulation_store.h5",
system_file="example_data/sienna/v4/sys.json",
)
raw_max = s.get_raw_dataset("ActivePowerVariable__ThermalStandard").max().max()
scaled_max = s.get_generation().max().max()
print(f"raw max: {raw_max:.2f} (per-unit)")
print(f"scaled max: {scaled_max:.2f} (MW)")
print(f"unit_base_value: {s.unit_base_value}")
assert scaled_max == raw_max * s.unit_base_value
Notes#
get_raw_datasetworks for any 2D h5 path. Decision-model paths can be 3D (executions × entities × periods); those error in the current parser. Use the emulation model alias path for 2D access.The v1
SiennaSimulationclass (gat.simulations.sienna_v1) exposes the samebase_powerresolution via itsbase_powerproperty — the underlying parser is shared.For background on the broader Sienna data model, see Scenarios and simulations.