StudyManager References¶
StudyManager
¶
Central orchestrator for multi-scenario energy systems analysis using MESQUAL's three-tier collection system.
StudyManager provides unified access to scenarios, scenario comparisons, and combined datasets, implementing MESQUAL's core architectural principle that "Everything is a Dataset". It manages the complete lifecycle of multi-scenario studies including data organization, automatic delta computation, and export functionality.
The class implements three primary data access patterns
.scen: Access to individual scenario data (DatasetConcatCollection).comp: Access to scenario comparison deltas (DatasetConcatCollectionOfComparisons).scen_comp: Unified access to both scenarios and comparisons with type distinction
Attributes:
| Name | Type | Description |
|---|---|---|
scen |
DatasetConcatCollection
|
Collection of scenario datasets with consistent .fetch() interface |
comp |
DatasetConcatCollectionOfComparisons
|
Collection of scenario comparisons with automatic delta calculation |
scen_comp |
DatasetConcatCollection
|
Unified collection combining scenarios and comparisons |
Examples:
Basic multi-scenario study setup:
>>> from mesqual import StudyManager
>>> from mesqual_pypsa import PyPSADataset
>>>
>>> study = StudyManager.factory_from_scenarios(
... scenarios=[
... PyPSADataset(base_network, name='base'),
... PyPSADataset(high_res_network, name='high_res'),
... PyPSADataset(low_gas_network, name='cheap_gas'),
... ],
... comparisons=[('high_res', 'base'), ('cheap_gas', 'base')], # StudyManager handles automatic naming with '*variation_dataset_name* vs *reference_dataset_name*'
... )
Three-tier data access:
>>> # Access scenario data across all scenarios
>>> scenario_prices = study.scen.fetch('buses_t.marginal_price')
>>> print(scenario_prices) # Print price time-series df for all scenarios concatenated with MultiIndex
dataset base ... n_cheap_gas
Bus 1 10 ... 99 99_220kV
snapshot ...
2011-01-01 00:00:00 -0.44 5.77 ... 23.83 23.79
2011-01-01 01:00:00 -0.58 6.10 ... 22.38 22.33
... ... ... ... ... ...
2011-01-01 22:00:00 20.98 20.44 ... 22.72 22.67
2011-01-01 23:00:00 13.43 18.94 ... 22.59 22.54
>>> # Access comparison deltas automatically calculated across all comparisons
>>> price_changes = study.comp.fetch('buses_t.marginal_price')
>>> print(price_changes) # Print price time-series df for all comparisons concatenated with MultiIndex
dataset high_res vs base ... n_cheap_gas vs base
Bus 1 10 ... 99 99_220kV
snapshot ...
2011-01-01 00:00:00 0.21 0.02 ... 0.10 0.11
2011-01-01 01:00:00 0.02 0.06 ... -0.81 -0.82
... ... ... ... ... ...
2011-01-01 22:00:00 0.04 -0.05 ... -2.10 -2.14
2011-01-01 23:00:00 2.33 0.46 ... -1.74 -1.78
>>> # Access unified view with type-level distinction
>>> unified_scen_and_comp_price_data = study.scen_comp.fetch('buses_t.marginal_price')
>>> print(unified_scen_and_comp_price_data) # Print price time-series df for all scenarios and comparisons concatenated with additional level on MultiIndex:
type scenario ... comparison
dataset base ... n_cheap_gas vs base
Bus 1 10 ... 99 99_220kV
snapshot ...
2011-01-01 00:00:00 -0.44 5.77 ... 0.10 0.11
2011-01-01 01:00:00 -0.58 6.10 ... -0.81 -0.82
.. ... ... ... ... ...
2011-01-01 22:00:00 20.98 20.44 ... -2.10 -2.14
2011-01-01 23:00:00 13.43 18.94 ... -1.74 -1.78
Access individual datasets:
>>> # Access to data from individual scenario
>>> ds_base = study.scen.get_dataset('base')
>>> base_prices = ds_base.fetch('buses_t.marginal_price')
>>> print(base_prices) # Print price time-series df for base scenario
Bus 1 10 ... 99 99_220kV
snapshot ...
2011-01-01 00:00:00 -0.44 5.77 ... 23.72 23.69
2011-01-01 01:00:00 -0.58 6.10 ... 23.19 23.14
... ... ... ... ... ...
2011-01-01 22:00:00 20.98 20.44 ... 24.81 24.81
2011-01-01 23:00:00 13.43 18.94 ... 24.33 24.32
>>> base_buses_model_df = ds_base.fetch('buses')
>>> print(base_buses_model_df) # Print bus model df for base scenario
v_nom type ... v_mag_pu_max control
Bus ...
1 220.00 ... inf Slack
2 380.00 ... inf PQ
... ... ... ... ... ...
450_220kV 220.00 ... inf PQ
458_220kV 220.00 ... inf PQ
>>> # Access to individual comparison dataset
>>> ds_comp_high_res = study.comp.get_dataset('high_res vs base')
>>> price_changes_high_res = ds_comp_high_res.fetch('buses_t.marginal_price')
>>> print(price_changes_high_res) # Print price time-series df changes (deltas) comparing high_res to base
Bus 1 10 ... 99 99_220kV
snapshot ...
2011-01-01 00:00:00 0.21 0.02 ... 0.01 0.01
2011-01-01 01:00:00 0.02 0.06 ... -0.07 -0.07
... ... ... ... ... ...
2011-01-01 22:00:00 0.04 -0.05 ... -0.00 -0.00
2011-01-01 23:00:00 2.33 0.46 ... -0.09 -0.09
>>> bus_model_changes_high_res = ds_comp_high_res.fetch('buses')
>>> print(bus_model_changes_high_res) # Print bus model df changes comparing high_res to base
v_nom type ... v_mag_pu_max control
Bus ...
1 0.00 ... NaN Slack
2 0.00 ... NaN PQ
... ... ... ... ... ...
450_220kV 0.00 ... NaN PQ
458_220kV 0.00 ... NaN PQ
Access to merged (model) dfs for all sub datasets:
>>> # Access merged dataframe (useful to get unified model_df in case of different objects across scenarios)
>>> bus_model_df_merged = study.scen.fetch_merged('buses')
>>> print(bus_model_df_merged) # Print merged bus model df for all scenarios
v_nom type ... v_mag_pu_max control
Bus ...
1 220.00 ... inf Slack
2 380.00 ... inf PQ
... ... ... ... ... ...
450_220kV 220.00 ... inf PQ
458_220kV 220.00 ... inf PQ
Notes
- All collections share the same .fetch(flag) interface for consistent data access
- Scenario comparisons are computed automatically as deltas (variation - reference)
- The unified collection uses 'type' as the concat_level_name to distinguish data sources
- Supports dynamic addition of scenarios and comparisons after initialization
Source code in submodules/mesqual/mesqual/study_manager.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |