Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/attribute-dtype-helper-function #834

Merged
merged 6 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/api_reference/python-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ This is the Python API reference for the `power-grid-model` library
.. autoclass:: PowerGridModel
:show-inheritance:
.. autofunction:: initialize_array
.. autofunction:: attribute_dtype
.. autofunction:: attribute_empty_value

.. py:data:: power_grid_meta_data
:type: typing.PowerGridMetaData
Expand Down
49 changes: 24 additions & 25 deletions docs/examples/Power Flow Example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"\n",
"from power_grid_model import LoadGenType, ComponentType, DatasetType, ComponentAttributeFilterOptions\n",
"from power_grid_model import PowerGridModel, CalculationMethod, CalculationType\n",
"from power_grid_model import initialize_array, power_grid_meta_data"
"from power_grid_model import initialize_array, attribute_dtype"
]
},
{
Expand Down Expand Up @@ -127,7 +127,7 @@
"\n",
"A columnar data format better integrates with most databases. In addition, it may bring memory and, in some cases, even computational performance improvements, because unused attribute columns can be omitted.\n",
"\n",
"Make sure to provide the correct `dtype` to the numpy arrays, exposed for each dataset type, component and attribute via the `power_grid_meta_data` object."
"Make sure to provide the correct `dtype` to the numpy arrays, exposed for each dataset type, component and attribute via the helper function `attribute_dtype` function."
]
},
{
Expand All @@ -137,12 +137,11 @@
"metadata": {},
"outputs": [],
"source": [
"source_attribute_dtypes = power_grid_meta_data[DatasetType.input][ComponentType.source].dtype\n",
"source_columns = {\n",
" \"id\": np.array([10], dtype=source_attribute_dtypes[\"id\"]),\n",
" \"node\": np.array([1], dtype=source_attribute_dtypes[\"node\"]),\n",
" \"status\": np.array([1], dtype=source_attribute_dtypes[\"status\"]),\n",
" \"u_ref\": np.array([1.0], dtype=source_attribute_dtypes[\"u_ref\"]),\n",
" \"id\": np.array([10], dtype=attribute_dtype(DatasetType.input, ComponentType.source, \"id\")),\n",
" \"node\": np.array([1], dtype=attribute_dtype(DatasetType.input, ComponentType.source, \"node\")),\n",
" \"status\": np.array([1], dtype=attribute_dtype(DatasetType.input, ComponentType.source, \"status\")),\n",
" \"u_ref\": np.array([1.0], dtype=attribute_dtype(DatasetType.input, ComponentType.source, \"u_ref\")),\n",
" # We're not creating columns for u_ref_angle, sk, ... Instead, the default values are used. This saves us memory.\n",
"}\n",
"\n",
Expand Down Expand Up @@ -403,7 +402,7 @@
"List of attribute types in line result\n",
"['id', 'p_from']\n",
"------line result------\n",
"{'id': array([3, 5, 8], dtype=int32), 'p_from': array([17360100.20222374, -3365613.74450156, 13854413.52498137])}\n"
"{'id': array([3, 5, 8]), 'p_from': array([17360100.20222374, -3365613.74450156, 13854413.52498137])}\n"
TonyXiang8787 marked this conversation as resolved.
Show resolved Hide resolved
]
}
],
Expand Down Expand Up @@ -674,10 +673,11 @@
"metadata": {},
"outputs": [],
"source": [
"line_update_dtype = power_grid_meta_data[DatasetType.update][ComponentType.line].dtype\n",
"columnar_update_line = {\n",
" \"id\": np.array([3], dtype=line_update_dtype[\"id\"]), # change line ID 3\n",
" \"from_status\": np.array([0], dtype=line_update_dtype[\"from_status\"]), # switch off at from side\n",
" \"id\": np.array([3], dtype=attribute_dtype(DatasetType.update, ComponentType.line, \"id\")), # change line ID 3\n",
" \"from_status\": np.array(\n",
" [0], dtype=attribute_dtype(DatasetType.update, ComponentType.line, \"from_status\")\n",
" ), # switch off at from side\n",
"}\n",
"# leave to-side swiching status the same, no need to specify\n",
"\n",
Expand All @@ -699,11 +699,10 @@
"metadata": {},
"outputs": [],
"source": [
"line_update_dtype = power_grid_meta_data[DatasetType.update][ComponentType.line].dtype\n",
"columnar_no_ID_update_line = {\n",
" # Update IDs are not specified\n",
" \"from_status\": np.array(\n",
" [0, 1, 1], dtype=line_update_dtype[\"from_status\"]\n",
" [0, 1, 1], dtype=attribute_dtype(DatasetType.update, ComponentType.line, \"from_status\")\n",
" ), # The update for the whole column needs to be specified\n",
"}\n",
"# leave to-side swiching status the same, no need to specify\n",
Expand Down Expand Up @@ -1404,16 +1403,16 @@
"output_type": "stream",
"text": [
"Node data with invalid results\n",
"[[0.99940117 0.99268579 0.99452137]\n",
" [0.99934769 0.98622639 0.98935286]\n",
" [0.99928838 0.97965401 0.98409554]\n",
" [0. 0. 0. ]\n",
" [0.99915138 0.96614948 0.97329879]\n",
" [0.99907317 0.95920586 0.96775071]\n",
" [0.9989881 0.95212621 0.96209647]\n",
" [0. 0. 0. ]\n",
" [0.99879613 0.93753005 0.95044796]\n",
" [0.9986885 0.92999747 0.94444167]]\n",
"[[9.99401170e-001 9.92685785e-001 9.94521366e-001]\n",
" [9.99347687e-001 9.86226389e-001 9.89352855e-001]\n",
" [9.99288384e-001 9.79654011e-001 9.84095542e-001]\n",
" [6.95296562e-310 8.59448882e-312 6.95296562e-310]\n",
" [9.99151380e-001 9.66149483e-001 9.73298790e-001]\n",
" [9.99073166e-001 9.59205860e-001 9.67750710e-001]\n",
" [9.98988099e-001 9.52126208e-001 9.62096474e-001]\n",
" [8.59448882e-312 8.59448882e-312 6.95296562e-310]\n",
" [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n",
" [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n",
figueroa1395 marked this conversation as resolved.
Show resolved Hide resolved
"Node data with only valid results\n",
"[[0.99940117 0.99268579 0.99452137]\n",
" [0.99934769 0.98622639 0.98935286]\n",
Expand Down Expand Up @@ -1456,7 +1455,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "venv",
"display_name": ".venv",
"language": "python",
"name": "python3"
},
Expand All @@ -1470,7 +1469,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.0"
"version": "3.12.7"
nitbharambe marked this conversation as resolved.
Show resolved Hide resolved
nitbharambe marked this conversation as resolved.
Show resolved Hide resolved
}
},
"nbformat": 4,
Expand Down
7 changes: 6 additions & 1 deletion src/power_grid_model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
"""Power Grid Model"""

from power_grid_model._core.dataset_definitions import ComponentType, DatasetType
from power_grid_model._core.power_grid_meta import initialize_array, power_grid_meta_data
from power_grid_model._core.power_grid_meta import (
attribute_dtype,
attribute_empty_value,
initialize_array,
power_grid_meta_data,
)
from power_grid_model._core.power_grid_model import PowerGridModel
from power_grid_model.enum import (
Branch3Side,
Expand Down
39 changes: 38 additions & 1 deletion src/power_grid_model/_core/power_grid_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
_str_to_datatype,
)
from power_grid_model._core.power_grid_core import AttributePtr, ComponentPtr, DatasetPtr, power_grid_core as pgc
from power_grid_model.data_types import DenseBatchArray, SingleArray
from power_grid_model.data_types import AttributeType, DenseBatchArray, SingleArray


# constant enum for ctype
Expand Down Expand Up @@ -205,3 +205,40 @@ def initialize_array(
dtype=power_grid_meta_data[data_type][component_type].dtype,
order="C",
)


def attribute_dtype(
nitbharambe marked this conversation as resolved.
Show resolved Hide resolved
data_type: DatasetTypeLike, component_type: ComponentTypeLike, attribute: AttributeType
nitbharambe marked this conversation as resolved.
Show resolved Hide resolved
) -> np.dtype:
"""Gives out dtype of the attribute to be used in a columnar data format

Args:
data_type (DatasetTypeLike): The type of dataset (input, update, sym_output, or asym_output)
component_type (ComponentTypeLike): The type of component (e.g., node)
attribute (AttributeType): The attribute whose dtype is required

Returns:
np.dtype: The dtype of the specified attribute
"""
data_type = _str_to_datatype(data_type)
component_type = _str_to_component_type(component_type)
return power_grid_meta_data[data_type][component_type].dtype[attribute]


def attribute_empty_value(
figueroa1395 marked this conversation as resolved.
Show resolved Hide resolved
data_type: DatasetTypeLike, component_type: ComponentTypeLike, attribute: AttributeType
) -> np.ndarray:
"""
Returns the empty value for a specific attribute in the Power Grid Model.

nitbharambe marked this conversation as resolved.
Show resolved Hide resolved
Args:
data_type (DatasetTypeLike): The type of dataset (input, update, sym_output, or asym_output)
component_type (ComponentTypeLike): The type of component (e.g., node)
attribute (AttributeType): The attribute whose empty value is required

Returns:
np.ndarray: The empty value for the specified attribute
"""
data_type = _str_to_datatype(data_type)
component_type = _str_to_component_type(component_type)
return power_grid_meta_data[data_type][component_type].nan_scalar[attribute]
54 changes: 40 additions & 14 deletions tests/unit/test_meta_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,56 @@

import numpy as np

from power_grid_model import initialize_array, power_grid_meta_data
from power_grid_model import (
ComponentType,
DatasetType,
attribute_dtype,
attribute_empty_value,
initialize_array,
power_grid_meta_data,
)


def test_nan_scalar():
assert np.isnan(power_grid_meta_data["input"]["node"].nan_scalar["u_rated"])
assert np.isnan(power_grid_meta_data[DatasetType.input][ComponentType.node].nan_scalar["u_rated"])


def test_initialize_array():
arr = initialize_array("input", "node", 3)
arr = initialize_array(DatasetType.input, ComponentType.node, 3)
assert arr.shape == (3,)
assert np.all(np.isnan(arr["u_rated"]))
arr_2d = initialize_array("input", "node", (2, 3))
arr_2d = initialize_array(DatasetType.input, ComponentType.node, (2, 3))
assert arr_2d.shape == (2, 3)
assert np.all(np.isnan(arr_2d["u_rated"]))


def test_attribute_dtype():
assert attribute_dtype(DatasetType.input, ComponentType.node, "u_rated") == np.float64
assert attribute_dtype(DatasetType.input, ComponentType.node, "id") == np.int32


def test_attribute_empty_value():
empty_value = attribute_empty_value(DatasetType.input, ComponentType.node, "u_rated")
assert np.isnan(empty_value)
empty_value = attribute_empty_value(DatasetType.input, ComponentType.node, "id")
assert empty_value == np.iinfo(np.int32).min


def test_sensor_meta_data():
sensors = ["sym_voltage_sensor", "asym_voltage_sensor", "sym_power_sensor", "asym_power_sensor"]
sensors = [
ComponentType.sym_voltage_sensor,
ComponentType.asym_voltage_sensor,
ComponentType.sym_power_sensor,
ComponentType.asym_power_sensor,
]
input_voltage = ["u_measured", "u_angle_measured", "u_sigma"]
output_voltage = ["u_residual", "u_angle_residual"]
input_power = ["p_measured", "q_measured", "power_sigma"]
output_power = ["p_residual", "q_residual"]
for sensor in sensors:
for meta_type in ["input", "update", "sym_output", "asym_output"]:
for meta_type in [DatasetType.input, DatasetType.update, DatasetType.sym_output, DatasetType.asym_output]:
meta_data = power_grid_meta_data[meta_type]
# comp_names = list(meta_data.keys())
# assert sensor in comp_names
assert sensor in meta_data
meta_data_sensor = meta_data[sensor]
attr_names = meta_data_sensor.dtype_dict["names"]
assert "id" in attr_names
Expand All @@ -51,14 +74,17 @@ def test_sensor_meta_data():


def test_dict_like_access():
assert power_grid_meta_data["input"]["node"].dtype == power_grid_meta_data["input"]["node"]["dtype"]
assert (
power_grid_meta_data[DatasetType.input][ComponentType.node].dtype
== power_grid_meta_data[DatasetType.input][ComponentType.node]["dtype"]
)


def test_all_datasets():
assert set(power_grid_meta_data.keys()) == {
"input",
"update",
"sym_output",
"asym_output",
"sc_output",
DatasetType.input,
DatasetType.update,
DatasetType.sym_output,
DatasetType.asym_output,
DatasetType.sc_output,
nitbharambe marked this conversation as resolved.
Show resolved Hide resolved
}
Loading