SHOP JSON Standard#
JSON is a new alternative to YAML and ASCII. JSON is the primary way of interacting with SHOP Server, but can also be parsed with pyshop.
Reading and writing#
JSON data can be read using the load_json function as shown below. The function can either read from a file or read a JSON string:
from pyshop import ShopSession
shop = ShopSession()
shop.load_json(json_file_path='basic_model.json')
shop.load_json(json_string='''
{
"model": {
"reservoir": {
"Reservoir1": {
"inflow": {
"name": "Inflow",
"timestamps": [
"2018-01-23T00:00:00Z",
"2018-01-23T03:00:00Z"
],
"values": [
[
10.0,
15.0
]
]
}
}
}
}
}
''')
With SHOP versions ≥ 17.9.0, there is an option to skip commands with the parameter skip_commands (default = False).
Similarly, with SHOP versions ≥ 17.4.0, the model can be dumped as a JSON file using the dump_json function or to string with the dump_json_string function. The functions have three boolean options:
Option |
Default |
Description |
|---|---|---|
input_only |
True |
Only write input data to file |
compress_txy |
True |
Only print timeseries value for timestep if value has changed from previous timestep to keep file compact |
output_only |
False |
Only write output data to file |
shop.dump_json('basic_model_results.json', False, True, True)
JSON schema#
Similar to YAML, there are 4 root nodes:
time- mapmodel- mapconnections- listcommands- list
A basic overview. This listing represents the basic root structure of a JSON model.
{
"time": {
},
"model": {
},
"connections": [
],
"commands": [
]
}
Time#
Global simulation settings. Even though the string format "2024-01-01T00:00:00Z" includes a timezone specifier, SHOP does not use that information.
{
"time": {
"start_time": "2024-01-01T00:00:00Z",
"end_time": "2024-01-02T00:00:00Z",
"time_unit": "minute",
"time_resolution": {
"timestamps": [
"2024-01-00T00:00:00Z"
],
"values": [
[
60
]
]
}
}
}
Model#
The model structure is model / object-type / object-name / object-attributes.
Look at object table for all allowed objects.
{
"model": {
"reservoir": {
},
"plant": {
},
"generator": {
},
"tunnel": {
},
"river": {
}
}
}
Connections#
All fields are required.
{
"connections": [
{
"relation_type": "default",
"relation_direction": "both",
"from_type": "reservoir",
"from": "upper_rsv",
"to_type": "river",
"to": "upper_river"
},
]
}
Commands#
The command table lists all available commands in SHOP, they have the following JSON format:
{
"commands": [
{
"command": "log file",
"options": [],
"values": [
"logfile.log"
]
}
]
}
JSON Attribute Datatypes#
Int#
{
"model": {
"plant": {
"Plant1": {
"time_delay": 0
}
}
}
}
Int array#
Array of ints.
{
"model": {
"plant": {
"Plant1": {
"gen_priority":
[
1, 2, 3, 4
]
}
}
}
}
Double#
{
"model": {
"reservoir": {
"Lower": {
"max_vol": 100.0,
"lrl": 1050.50,
"hrl": 1550.90
}
}
}
}
Double array#
A list of doubles.
{
"model": {
"generator": {
"Gen1": {
"discrete_droop_values": [
0.1,
0.5,
1.5
]
}
}
}
}
NaN values (not-a-number) can be used for certain attributes, and is the literal case-insensitive string "NaN".
[
0.0,
0.1,
0.2,
0.3,
"NaN",
0.5,
"NaN",
0.6,
0.7,
0.8,
0.1
]
String#
{
"model": {
"plant": {
"Plant1": {
"reserve_type_name": "FCR_N_UP"
}
}
}
}
String array#
Array of strings. Currently only used for output.
Xy#
{
"model": {
"reservoir": {
"Lower": {
"vol_head": {
"x_values": [
0.0,
5.5,
10.6,
15.2,
20.6
],
"y_values": [
1000.0,
1001.5,
1003.0,
1010.0,
1015.42
]
}
}
}
}
}
Ref defaults to 0.0. To explicitly set ref, see the following example.
"vol_head": {
"ref": 42.0,
"x_values": [
0.0,
5.5,
10.6,
15.2,
20.6
],
"y_values": [
1000.0,
1001.5,
1003.0,
1010.0,
1015.42
]
}
Xy array#
Array of XYs.
{
"model": {
"generator": {
"plant1_plant2": {
"turb_eff_curves": {
"170": {
"x_values": [
10.5,
30.5
],
"y_values": [
20.5,
35.0
]
},
"200": {
"x_values": [
50.1,
60.4
],
"y_values": [
95.0,
99.9
]
},
"230": {
"x_values": [
1.0,
2.2
],
"y_values": [
20.0,
22.2
]
}
}
}
}
}
}
Txy#
With classic SHOP (ASCII, YAML) there is a difference between non-stochastic and stochastic Txy-variables. Txy in JSON are always stochastic. The non-stochastic case is a stochastic with only 1 dimension.
{
"model": {
"reservoir": {
"Lower": {
"tactical_limit_min": {
"name": "TacticalLevelMin",
"timestamps": [
"2024-01-01T00:00:00Z"
],
"values": [
[
2.0
]
]
},
"tactical_limit_max": {
"name": "TacticalLevelMax",
"timestamps": [
"2024-01-01T00:00:00Z"
],
"values": [
[
100.0
]
]
}
}
}
}
}
Example of a stochastic txy variable in JSON. All value dimensions must be of same size.
"stockastic_example": {
"name": "Stocastic",
"timestamps": [
"2024-01-01T00:00:00Z",
"2024-02-01T00:00:00Z"
],
"values": [
[
100.0, 110.0, 120.0, 130.0
],
[
200.0, 210.0, 220.0, 230.0
],
]
}
Xyt#
Array of XYs where the reference value are time stamps.
{
"model": {
"reservoir": {
"rsv1": {
"average_level_rolling_ramping_up": {
"2000-01-01T06:36:00Z": {
"x_values": [
1.0,
2.0,
3.0
],
"y_values": [
4.0,
5.0,
6.0
]
},
"2009-12-31T16:48:00Z": {
"x_values": [
10.0,
20.0,
30.0
],
"y_values": [
40.0,
50.0,
60.0
]
}
}
}
}
}
}
Sy#
The sy datatype is a list of string-double-pairs.
Some attributes expect the string to be a timestamp. Internally SHOP uses SHOP-timestamp. For an improved user experience, SHOP JSON API will convert any JSON timestamps to SHOP timestamps for all string values, if possible. If the string does not correspond to a timestamp, nothing will be transformed and the string will be sent to SHOP core as is.
When fetching sy data through the JSON interface, the SHOP timestamp will be converted to JSON timestamp format.
{
"model": {
"reservoir": {
"rsv1": {
"average_level_period_ramping_up_offset": [
[
"2000-01-01T06:36:00Z",
10.0
],
[
"2005-01-01T06:36:00Z",
500.0
]
]
}
}
}
}