Time Series Aggregation
Warning
This functionality is currently under development and being tested! Do not trust it blindly.
The time series aggregation function uses dependencies that are not automatically installed with pybalmorel: riprepy (a Python wrapper for ripgrep) and the time series aggregation package tsam. Install them into your virtual environment with pip:
pip install tsam
pip install riprepy
Overview
Balmorel.temporal_aggregation aggregates the time series input data of a Balmorel scenario from a full hourly resolution down to a user-defined number of representative seasons (periods) and terms (hours per period). It uses tsam under the hood to cluster the time series data, and then writes new .inc files for the aggregated scenario into a new scenario folder named {scenario}_S{seasons}T{terms}.
The method works in three steps:
Collect and standardise — loads all
.incfiles (manually or automatically) and extracts every time-indexed GAMS symbol (those withSSS/TTTdomains). Each symbol’s data is placed on a common(SSS, TTT)index and joined into a single DataFrame.Cluster — runs tsam to find representative periods for the collected data.
Save — writes new
.incfiles containing the aggregated data, plus updatedS.incandT.incset definitions, into a new scenario folder.
Warning
Any .inc files that define both SSS/TTT-related symbols AND symbols without any SSS/TTT dependency will result in new .inc files that does NOT include the non-SSS/TTT dependant symbols. Hence, remember to copy paste those parts into the newly generated .inc files after aggregation, or re-organise before.
This is also true for GAMS statements unrelated to the SSS/TTT symbols, such as this one in HYRSDATA.inc. Such lines would simply not be included in the new aggregated files.
If you have several .inc files in the scenario/data folder that define the same symbol through some option in balopt.opt (like EV_profile, selecting only one of the profiles), only one of these files will contain data after aggregation. Remember to rename the one containing the data to match the selection in balopt.opt or just delete the .inc files that are not selected before aggregation.
Basic Usage
from pybalmorel import Balmorel
model = Balmorel('path/to/Balmorel')
model.temporal_aggregation(
scenario='base',
seasons=8,
terms=24,
)
This produces a new scenario folder path/to/Balmorel/base_S8T24/ containing the aggregated .inc files
with 8 seasons and 24 terms.
Parameters
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
— |
The scenario folder to aggregate. |
|
|
— |
Number of representative seasons (periods) to cluster to. |
|
|
— |
Number of hours per period. |
|
|
|
Clustering method. See Clustering methods. |
|
|
|
How cluster centres are represented. See Representation options. |
|
|
|
|
|
|
|
Required when |
|
|
|
Re-collect and re-standardise input data even if cached |
Clustering Methods
The method parameter is passed directly to tsam. Available options:
Method |
Description |
|---|---|
|
(default) Clusters consecutive time steps together, preserving temporal order. |
|
Simple averaging within clusters. |
|
k-means clustering. |
|
k-medoids clustering. |
|
k-maxoids clustering. |
|
Agglomerative hierarchical clustering. |
Representation Options
The representation parameter controls how the representative value for each cluster is chosen:
Option |
Description |
|---|---|
|
(default) Preserves the distribution of each time series and matches the min/max values. |
|
Uses the mean of the cluster. |
|
Uses the medoid (the actual time step closest to the centroid). |
|
Uses the time step with the highest overall load. |
|
Preserves the distribution of each time series. |
|
Matches the min and max values and uses the mean otherwise. |
Automatic Symbol Detection
By default (symbols_to_aggregate='auto'), the method scans all loaded .inc files and GAMS symbols to find every parameter that has SSS or TTT in its domain. It categorises them into three groups:
'SSS,TTT'— symbols indexed over both seasons and terms (e.g.DE_VAR_T,WND_VAR_T).'SSS'— symbols indexed over seasons only.'TTT'— symbols indexed over terms only.
Certain meta-data symbols are excluded automatically (e.g. WEIGHT_S, CHRONOHOUR, S, T). Symbols with all-constant time series are also skipped.
Intermediate results are cached as .pkl files in the scenario folder (std_ts_data.pkl, symbols_to_agg.pkl, incfile_symbol_relation.pkl). On subsequent runs, these are loaded directly unless overwrite=True is passed, to reduce computational time when doing several clusterings of the same data.
Manual Symbol Selection
If you want precise control over which symbols are aggregated, pass a dict to symbols_to_aggregate and a companion dict to incfile_symbol_relation:
model.temporal_aggregation(
scenario='base',
seasons=8,
terms=24,
symbols_to_aggregate={
'SSS,TTT': ['DE_VAR_T', 'WND_VAR_T'],
'SSS': [],
'TTT': [],
},
incfile_symbol_relation={
'DE_VAR_T': ['base/data/DE_VAR_T.inc',
'base/data/INDIVUSERS_DE_VAR_T.inc'
'base/data/TRANSPORT_DE_VAR_T.inc'],
'WND_VAR_T': ['base/data/WND_VAR_T.inc'],
},
)
Each key in incfile_symbol_relation is a symbol name, and the value is a list of .inc file paths. The first path
will receive the aggregated data; the remaining files are written as empty stubs (since all appending to the symbol
from addons will be contained in the first file, and the others therefore need
to be empty to avoid reading of its ‘../../base/data’ counterpart).
Output
After a successful run, a new scenario folder is created:
Balmorel/
└── base_S8T24/
└── data/
├── S.inc ← updated season set (S01 … S08)
├── T.inc ← updated term set (T001 … T024)
├── DE_VAR_T.inc ← aggregated demand profiles
├── WND_VAR_T.inc ← aggregated wind profiles
└── ...
└── temporal_aggregation.md ← log of aggregation settings
The temporal_aggregation.md log records the timestamp, method, representation, and the aggregated resolution.
Important Notes
If an
.incfile contains both time-dependent symbols and symbols withoutS/Tsets, the newly generated file will only contain the time-dependent data. You must manually copy the non-time-dependent parts back into the new file or re-organise into several files before aggregation.The
overwrite=Falsedefault means repeated calls are fast — the standardisation step is skipped if cached data is found. Passoverwrite=Trueif your input data has changed since the last run.GAMS-dependent input loading (via
load_incfiles) is performed internally; make sure a GAMS installation is available andgams_system_directoryis set on theBalmorelobject if GAMS cannot be found automatically.