Serialization example

This example illustrates how to load a dataset from JSON, run the model on that dataset and write the output back to JSON. At the end the example is also shown for msgpack.

Load dependencies

import json
import pprint
import warnings

with warnings.catch_warnings(action="ignore", category=DeprecationWarning):
    # suppress warning about pyarrow as future required dependency
    from pandas import DataFrame

from power_grid_model import PowerGridModel
from power_grid_model.utils import json_deserialize, json_serialize

Load a dataset from a JSON file

The data is in the data/serialized-input.json file.

Load the JSON file

with open("data/serialized_input.json") as fp:
    data = fp.read()

pprint.pprint(json.loads(data))
{'attributes': {'node': ['id', 'u_rated'],
                'source': ['id', 'node', 'status', 'u_ref', 'sk'],
                'sym_load': ['id',
                             'node',
                             'status',
                             'type',
                             'p_specified',
                             'q_specified']},
 'data': {'line': [{'c1': 4e-05,
                    'from_node': 1,
                    'from_status': 1,
                    'i_n': 500.0,
                    'id': 4,
                    'r1': 0.11,
                    'tan1': 0.1,
                    'to_node': 2,
                    'to_status': 1,
                    'x1': 0.12},
                   {'c1': 5e-05,
                    'from_node': 2,
                    'from_status': 1,
                    'i_n': 550.0,
                    'id': 5,
                    'r1': 0.15,
                    'tan1': 0.12,
                    'to_node': 3,
                    'to_status': 1,
                    'x1': 0.16}],
          'node': [[1, 10500.0], [2, 10500.0], [3, 10500.0]],
          'source': [[15, 1, 1, 1.03, 1e+20],
                     [16, 1, 1, 1.04, None],
                     {'id': 17,
                      'node': 1,
                      'rx_ratio': 0.2,
                      'sk': 10000000000.0,
                      'status': 1,
                      'u_ref': 1.03}],
          'sym_load': [[7, 2, 1, 0, 1010000.0, 210000.0],
                       [8, 3, 1, 0, 1020000.0, 220000.0]]},
 'is_batch': False,
 'type': 'input',
 'version': '1.0'}

Deserialize the JSON data

dataset = json_deserialize(data)

print("components:", dataset.keys())
display(DataFrame(dataset["node"]))
components: dict_keys(['node', 'line', 'source', 'sym_load'])
id u_rated
0 1 10500.0
1 2 10500.0
2 3 10500.0

Run power flow calculation on the loaded input data

model = PowerGridModel(dataset)
output = model.calculate_power_flow()

display(DataFrame(output["node"]))
id energized u_pu u u_angle p q
0 1 1 1.030000 10815.000000 -2.527860e-14 2.408998e+06 -2.863495e+06
1 2 1 1.029997 10814.968183 -4.398000e-03 -1.010000e+06 -2.100000e+05
2 3 1 1.029484 10809.581008 -6.839956e-03 -1.020000e+06 -2.200000e+05

Serialize the output dataset

Default format

By default, the data is formatted nicely

serialized_output = json_serialize(output)

print(serialized_output)
{
  "version": "1.0",
  "type": "sym_output",
  "is_batch": false,
  "attributes": {},
  "data": {
    "node": [
      {"id": 1, "energized": 1, "u_pu": 1.030000000001025, "u": 10815.00000001077, "u_angle": -2.527859536004767e-14, "p": 2408997.839438984, "q": -2863495.364673933},
      {"id": 2, "energized": 1, "u_pu": 1.029996969815605, "u": 10814.96818306385, "u_angle": -0.004397999804754551, "p": -1010000.000000146, "q": -210000.0000001819},
      {"id": 3, "energized": 1, "u_pu": 1.029483905569344, "u": 10809.58100847811, "u_angle": -0.006839956175380042, "p": -1019999.99999994, "q": -220000.000000028}
    ],
    "line": [
      {"id": 4, "energized": 1, "loading": 0.3995319091936997, "p_from": 2408997.839438984, "q_from": -2863495.364673933, "i_from": 199.7659545968498, "s_from": 3742041.727978296, "p_to": -2252625.764367662, "q_to": 1403928.536947472, "i_to": 141.6984332838906, "s_to": 2654305.591138379},
      {"id": 5, "energized": 1, "loading": 0.1977047433812886, "p_from": 1242625.764367516, "q_from": -1613928.536947712, "i_from": 108.7376088597087, "s_from": 2036880.976553155, "p_to": -1019999.99999994, "q_to": -220000.000000028, "i_to": 55.73199226980768, "s_to": 1043455.796859594}
    ],
    "source": [
      {"id": 15, "energized": 1, "p": -7840728.150705829, "q": -105359100.0736002, "i": 5640.066029671385, "s": 105650447.1654151, "pf": -0.07421386620758674},
      {"id": 16, "energized": 1, "p": 10248883.05839162, "q": 102488830.5811948, "i": 5498.573991718331, "s": 102999999.989541, "pf": 0.09950371902361486},
      {"id": 17, "energized": 1, "p": -0.001808335374213852, "q": -0.01040913507631103, "i": 5.640066029671386e-07, "s": 0.01056504471654151, "pf": -0.1711621126773437}
    ],
    "sym_load": [
      {"id": 7, "energized": 1, "p": 1010000, "q": 210000, "i": 55.07135393955917, "s": 1031600.697944704, "pf": 0.979060989404389},
      {"id": 8, "energized": 1, "p": 1020000, "q": 220000, "i": 55.7319922698105, "s": 1043455.796859647, "pf": 0.9775210440823288}
    ]
  }
}

Compact serialization

In the full result, all attributes are explicitly listed for each component. In addition, all attributes are listed on a separate whiteline. This is fairly expensive memory-wise.

If you need a more memory-efficient output, you can tell the serializer to use compact lists and to avoid using redundant newlines and whitespaces.

serialized_output = json_serialize(output, use_compact_list=True, indent=-1)

print(serialized_output)
{"version":"1.0","type":"sym_output","is_batch":false,"attributes":{"node":["id","energized","u_pu","u","u_angle","p","q"],"line":["id","energized","loading","p_from","q_from","i_from","s_from","p_to","q_to","i_to","s_to"],"source":["id","energized","p","q","i","s","pf"],"sym_load":["id","energized","p","q","i","s","pf"]},"data":{"node":[[1,1,1.030000000001025,10815.00000001077,-2.527859536004767e-14,2408997.839438984,-2863495.364673933],[2,1,1.029996969815605,10814.96818306385,-0.004397999804754551,-1010000.000000146,-210000.0000001819],[3,1,1.029483905569344,10809.58100847811,-0.006839956175380042,-1019999.99999994,-220000.000000028]],"line":[[4,1,0.3995319091936997,2408997.839438984,-2863495.364673933,199.7659545968498,3742041.727978296,-2252625.764367662,1403928.536947472,141.6984332838906,2654305.591138379],[5,1,0.1977047433812886,1242625.764367516,-1613928.536947712,108.7376088597087,2036880.976553155,-1019999.99999994,-220000.000000028,55.73199226980768,1043455.796859594]],"source":[[15,1,-7840728.150705829,-105359100.0736002,5640.066029671385,105650447.1654151,-0.07421386620758674],[16,1,10248883.05839162,102488830.5811948,5498.573991718331,102999999.989541,0.09950371902361486],[17,1,-0.001808335374213852,-0.01040913507631103,5.640066029671386e-07,0.01056504471654151,-0.1711621126773437]],"sym_load":[[7,1,1010000,210000,55.07135393955917,1031600.697944704,0.979060989404389],[8,1,1020000,220000,55.7319922698105,1043455.796859647,0.9775210440823288]]}}

The compact result is still valid JSON

pprint.pprint(json.loads(serialized_output))
{'attributes': {'line': ['id',
                         'energized',
                         'loading',
                         'p_from',
                         'q_from',
                         'i_from',
                         's_from',
                         'p_to',
                         'q_to',
                         'i_to',
                         's_to'],
                'node': ['id', 'energized', 'u_pu', 'u', 'u_angle', 'p', 'q'],
                'source': ['id', 'energized', 'p', 'q', 'i', 's', 'pf'],
                'sym_load': ['id', 'energized', 'p', 'q', 'i', 's', 'pf']},
 'data': {'line': [[4,
                    1,
                    0.3995319091936997,
                    2408997.839438984,
                    -2863495.364673933,
                    199.7659545968498,
                    3742041.727978296,
                    -2252625.764367662,
                    1403928.536947472,
                    141.6984332838906,
                    2654305.591138379],
                   [5,
                    1,
                    0.1977047433812886,
                    1242625.764367516,
                    -1613928.536947712,
                    108.7376088597087,
                    2036880.976553155,
                    -1019999.99999994,
                    -220000.000000028,
                    55.73199226980768,
                    1043455.796859594]],
          'node': [[1,
                    1,
                    1.030000000001025,
                    10815.00000001077,
                    -2.527859536004767e-14,
                    2408997.839438984,
                    -2863495.364673933],
                   [2,
                    1,
                    1.029996969815605,
                    10814.96818306385,
                    -0.004397999804754551,
                    -1010000.000000146,
                    -210000.0000001819],
                   [3,
                    1,
                    1.029483905569344,
                    10809.58100847811,
                    -0.006839956175380042,
                    -1019999.99999994,
                    -220000.000000028]],
          'source': [[15,
                      1,
                      -7840728.150705829,
                      -105359100.0736002,
                      5640.066029671385,
                      105650447.1654151,
                      -0.07421386620758674],
                     [16,
                      1,
                      10248883.05839162,
                      102488830.5811948,
                      5498.573991718331,
                      102999999.989541,
                      0.09950371902361486],
                     [17,
                      1,
                      -0.001808335374213852,
                      -0.01040913507631103,
                      5.640066029671386e-07,
                      0.01056504471654151,
                      -0.1711621126773437]],
          'sym_load': [[7,
                        1,
                        1010000,
                        210000,
                        55.07135393955917,
                        1031600.697944704,
                        0.979060989404389],
                       [8,
                        1,
                        1020000,
                        220000,
                        55.7319922698105,
                        1043455.796859647,
                        0.9775210440823288]]},
 'is_batch': False,
 'type': 'sym_output',
 'version': '1.0'}

Msgpack serialization

To have even higher performance and smaller space, you can use the binary format msgpack. The example below shows a round trip to dump and load msgpack data, and intantiate model.

Serialize to msgpack

We can serialize the output data into msgpack binary with and without compact list. The result is a bytes object. See the resulted differences in length of the data. The differences will be significant when you have a large dataset.

from power_grid_model.utils import msgpack_serialize

msgpack_data_not_compact = msgpack_serialize(output, use_compact_list=False)
msgpack_data_compact = msgpack_serialize(output, use_compact_list=True)

print(f"Type of the returned objects: {type(msgpack_data_not_compact)}, {type(msgpack_data_compact)}")
print(f"Length of not-compact data: {len(msgpack_data_not_compact)}")
print(f"Length of compact data: {len(msgpack_data_compact)}")
Type of the returned objects: <class 'bytes'>, <class 'bytes'>
Length of not-compact data: 977
Length of compact data: 802

Deserialize from msgpack

We can deserialize the data we just created. We then print the node result. Note that they are exactly the same.

from power_grid_model.utils import msgpack_deserialize

output_data_not_compact = msgpack_deserialize(msgpack_data_not_compact)
output_data_compact = msgpack_deserialize(msgpack_data_compact)

print("----Node result from not compact data----")
print(DataFrame(output_data_not_compact["node"]))
print("----Node result from compact data----")
print(DataFrame(output_data_compact["node"]))
----Node result from not compact data----
   id  energized      u_pu             u       u_angle             p  \
0   1          1  1.030000  10815.000000 -2.527860e-14  2.408998e+06   
1   2          1  1.029997  10814.968183 -4.398000e-03 -1.010000e+06   
2   3          1  1.029484  10809.581008 -6.839956e-03 -1.020000e+06   

              q  
0 -2.863495e+06  
1 -2.100000e+05  
2 -2.200000e+05  
----Node result from compact data----
   id  energized      u_pu             u       u_angle             p  \
0   1          1  1.030000  10815.000000 -2.527860e-14  2.408998e+06   
1   2          1  1.029997  10814.968183 -4.398000e-03 -1.010000e+06   
2   3          1  1.029484  10809.581008 -6.839956e-03 -1.020000e+06   

              q  
0 -2.863495e+06  
1 -2.100000e+05  
2 -2.200000e+05