From 9aea54b7345876a190433225b0d1a45bfa035a7d Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 15 Oct 2024 10:43:55 +0200 Subject: [PATCH 01/18] rerun examples Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 22 ++++---- docs/examples/Serialization Example.ipynb | 44 ++++++++-------- docs/examples/Short Circuit Example.ipynb | 9 +--- docs/examples/State Estimation Example.ipynb | 26 +++++----- docs/examples/Validation Examples.ipynb | 54 ++++++++++---------- 5 files changed, 75 insertions(+), 80 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index c084ac3a6..4236bcc04 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -324,7 +324,7 @@ "output_type": "stream", "text": [ "List of component types in result dataset\n", - "['node']\n", + "[]\n", "------node result------\n", " id energized u_pu u u_angle p q\n", "0 1 1 0.998988 10489.375043 -0.003039 3.121451e+07 6.991358e+06\n", @@ -1139,16 +1139,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", + " [ 1.05085968e+056 -4.32115156e-239 -5.52267234e+127]\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.67933810e+092 -1.76263646e-197 1.52450807e-227]\n", + " [ 9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", + " [ 9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n", "Node data with only valid results\n", "[[0.99940117 0.99268579 0.99452137]\n", " [0.99934769 0.98622639 0.98935286]\n", diff --git a/docs/examples/Serialization Example.ipynb b/docs/examples/Serialization Example.ipynb index 201324c0d..d3b39f2c3 100644 --- a/docs/examples/Serialization Example.ipynb +++ b/docs/examples/Serialization Example.ipynb @@ -122,7 +122,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "components: dict_keys(['node', 'line', 'source', 'sym_load'])\n" + "components: dict_keys([, , , ])\n" ] }, { @@ -326,9 +326,9 @@ " {\"id\": 5, \"energized\": 1, \"loading\": 0.1977047433812966, \"p_from\": 1242625.764367574, \"q_from\": -1613928.536947772, \"i_from\": 108.7376088597131, \"s_from\": 2036880.976553238, \"p_to\": -1019999.999999999, \"q_to\": -219999.9999999689, \"i_to\": 55.73199226981006, \"s_to\": 1043455.796859639}\n", " ],\n", " \"source\": [\n", - " {\"id\": 15, \"energized\": 1, \"p\": -7838134.060668075, \"q\": -105359359.482604, \"i\": 5640.069564151436, \"s\": 105650513.3737531, \"pf\": -0.07418926619825886},\n", - " {\"id\": 16, \"energized\": 1, \"p\": 10248883.05839188, \"q\": 102488830.5811948, \"i\": 5498.573991718331, \"s\": 102999999.989541, \"pf\": 0.09950371902361739},\n", - " {\"id\": 17, \"energized\": 1, \"p\": -0.001808079734064212, \"q\": -0.01040918620434095, \"i\": 5.640069564151435e-07, \"s\": 0.01056505133737531, \"pf\": -0.1711378086415808}\n", + " {\"id\": 15, \"energized\": 1, \"p\": -7836685.751732428, \"q\": -105348495.343833, \"i\": 5639.485452974508, \"s\": 105639571.7275539, \"pf\": -0.07418324046166491},\n", + " {\"id\": 16, \"energized\": 1, \"p\": 10248883.05839198, \"q\": 102488830.5811954, \"i\": 5498.573991718361, \"s\": 102999999.9895415, \"pf\": 0.09950371902361781},\n", + " {\"id\": 17, \"energized\": 1, \"p\": -0.001807829591278542, \"q\": -0.0104081191056169, \"i\": 5.639485452974507e-07, \"s\": 0.01056395717275539, \"pf\": -0.1711318553942043}\n", " ],\n", " \"sym_load\": [\n", " {\"id\": 7, \"energized\": 1, \"p\": 1010000, \"q\": 210000, \"i\": 55.07135393955915, \"s\": 1031600.697944704, \"pf\": 0.979060989404389},\n", @@ -367,7 +367,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{\"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.530316910142707e-14,2408997.839438867,-2863495.364674167],[2,1,1.029996969815606,10814.96818306386,-0.004397999804754745,-1009999.99999997,-210000.0000000655],[3,1,1.029483905569345,10809.58100847812,-0.006839956175380238,-1019999.999999999,-219999.9999999689]],\"line\":[[4,1,0.3995319091937107,2408997.839438867,-2863495.364674167,199.7659545968554,3742041.7279784,-2252625.764367544,1403928.536947823,141.6984332838951,2654305.591138465],[5,1,0.1977047433812966,1242625.764367574,-1613928.536947772,108.7376088597131,2036880.976553238,-1019999.999999999,-219999.9999999689,55.73199226981006,1043455.796859639]],\"source\":[[15,1,-7838134.060668075,-105359359.482604,5640.069564151436,105650513.3737531,-0.07418926619825886],[16,1,10248883.05839188,102488830.5811948,5498.573991718331,102999999.989541,0.09950371902361739],[17,1,-0.001808079734064212,-0.01040918620434095,5.640069564151435e-07,0.01056505133737531,-0.1711378086415808]],\"sym_load\":[[7,1,1010000,210000,55.07135393955915,1031600.697944704,0.979060989404389],[8,1,1020000,220000,55.73199226981046,1043455.796859647,0.9775210440823288]]}}\n" + "{\"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.530316910142707e-14,2408997.839438867,-2863495.364674167],[2,1,1.029996969815606,10814.96818306386,-0.004397999804754745,-1009999.99999997,-210000.0000000655],[3,1,1.029483905569345,10809.58100847812,-0.006839956175380238,-1019999.999999999,-219999.9999999689]],\"line\":[[4,1,0.3995319091937107,2408997.839438867,-2863495.364674167,199.7659545968554,3742041.7279784,-2252625.764367544,1403928.536947823,141.6984332838951,2654305.591138465],[5,1,0.1977047433812966,1242625.764367574,-1613928.536947772,108.7376088597131,2036880.976553238,-1019999.999999999,-219999.9999999689,55.73199226981006,1043455.796859639]],\"source\":[[15,1,-7836685.751732428,-105348495.343833,5639.485452974508,105639571.7275539,-0.07418324046166491],[16,1,10248883.05839198,102488830.5811954,5498.573991718361,102999999.9895415,0.09950371902361781],[17,1,-0.001807829591278542,-0.0104081191056169,5.639485452974507e-07,0.01056395717275539,-0.1711318553942043]],\"sym_load\":[[7,1,1010000,210000,55.07135393955915,1031600.697944704,0.979060989404389],[8,1,1020000,220000,55.73199226981046,1043455.796859647,0.9775210440823288]]}}\n" ] } ], @@ -452,25 +452,25 @@ " -219999.9999999689]],\n", " 'source': [[15,\n", " 1,\n", - " -7838134.060668075,\n", - " -105359359.482604,\n", - " 5640.069564151436,\n", - " 105650513.3737531,\n", - " -0.07418926619825886],\n", + " -7836685.751732428,\n", + " -105348495.343833,\n", + " 5639.485452974508,\n", + " 105639571.7275539,\n", + " -0.07418324046166491],\n", " [16,\n", " 1,\n", - " 10248883.05839188,\n", - " 102488830.5811948,\n", - " 5498.573991718331,\n", - " 102999999.989541,\n", - " 0.09950371902361739],\n", + " 10248883.05839198,\n", + " 102488830.5811954,\n", + " 5498.573991718361,\n", + " 102999999.9895415,\n", + " 0.0995037190236178],\n", " [17,\n", " 1,\n", - " -0.001808079734064212,\n", - " -0.01040918620434095,\n", - " 5.640069564151435e-07,\n", - " 0.01056505133737531,\n", - " -0.1711378086415808]],\n", + " -0.001807829591278542,\n", + " -0.0104081191056169,\n", + " 5.639485452974507e-07,\n", + " 0.01056395717275539,\n", + " -0.1711318553942043]],\n", " 'sym_load': [[7,\n", " 1,\n", " 1010000,\n", @@ -595,7 +595,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -609,7 +609,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.13.0" } }, "nbformat": 4, diff --git a/docs/examples/Short Circuit Example.ipynb b/docs/examples/Short Circuit Example.ipynb index 4fd209f1e..bf3479305 100644 --- a/docs/examples/Short Circuit Example.ipynb +++ b/docs/examples/Short Circuit Example.ipynb @@ -327,7 +327,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -341,12 +341,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" - }, - "vscode": { - "interpreter": { - "hash": "f2534ebf7a1a13ecc51c3a04ce741b49cf1feb97b5ca55170ed7b2036b4058c0" - } + "version": "3.13.0" } }, "nbformat": 4, diff --git a/docs/examples/State Estimation Example.ipynb b/docs/examples/State Estimation Example.ipynb index 8bec41a6e..124b0f720 100644 --- a/docs/examples/State Estimation Example.ipynb +++ b/docs/examples/State Estimation Example.ipynb @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 14, "id": "ae11dc9a", "metadata": {}, "outputs": [], @@ -71,7 +71,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 15, "id": "6f008736", "metadata": {}, "outputs": [], @@ -160,7 +160,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 16, "id": "fab31f58", "metadata": {}, "outputs": [], @@ -184,7 +184,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 17, "id": "7ef134e9", "metadata": {}, "outputs": [], @@ -212,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 18, "id": "44c2de63", "metadata": {}, "outputs": [], @@ -235,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 19, "id": "a581a36e", "metadata": {}, "outputs": [ @@ -535,7 +535,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 20, "id": "40e6d425", "metadata": {}, "outputs": [ @@ -639,7 +639,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 21, "id": "699e31af", "metadata": {}, "outputs": [ @@ -806,7 +806,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 22, "id": "b3e3fdc9", "metadata": {}, "outputs": [ @@ -927,7 +927,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 23, "id": "445726f3", "metadata": {}, "outputs": [ @@ -993,7 +993,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 24, "id": "303af910", "metadata": {}, "outputs": [], @@ -1037,7 +1037,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 25, "id": "70f761a3", "metadata": {}, "outputs": [], @@ -1060,7 +1060,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 26, "id": "4d9d5de2", "metadata": {}, "outputs": [ diff --git a/docs/examples/Validation Examples.ipynb b/docs/examples/Validation Examples.ipynb index c041efeb7..4d2f39bfc 100644 --- a/docs/examples/Validation Examples.ipynb +++ b/docs/examples/Validation Examples.ipynb @@ -113,8 +113,8 @@ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mIDWrongType\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[2], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# Without validation\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mPowerGridModel\u001b[49m\u001b[43m(\u001b[49m\u001b[43merror_data\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 3\u001b[0m output_data \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mcalculate_state_estimation(symmetric\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", - "File \u001b[1;32m~\\Documents\\power-grid-model\\src\\power_grid_model\\core\\power_grid_model.py:114\u001b[0m, in \u001b[0;36mPowerGridModel.__init__\u001b[1;34m(self, input_data, system_frequency)\u001b[0m\n\u001b[0;32m 112\u001b[0m prepared_input \u001b[38;5;241m=\u001b[39m prepare_input_view(input_data)\n\u001b[0;32m 113\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_model_ptr \u001b[38;5;241m=\u001b[39m pgc\u001b[38;5;241m.\u001b[39mcreate_model(system_frequency, input_data\u001b[38;5;241m=\u001b[39mprepared_input\u001b[38;5;241m.\u001b[39mget_dataset_ptr())\n\u001b[1;32m--> 114\u001b[0m \u001b[43massert_no_error\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 115\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_all_component_count \u001b[38;5;241m=\u001b[39m {k: v \u001b[38;5;28;01mfor\u001b[39;00m k, v \u001b[38;5;129;01min\u001b[39;00m prepared_input\u001b[38;5;241m.\u001b[39mget_info()\u001b[38;5;241m.\u001b[39mtotal_elements()\u001b[38;5;241m.\u001b[39mitems() \u001b[38;5;28;01mif\u001b[39;00m v \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m}\n", - "File \u001b[1;32m~\\Documents\\power-grid-model\\src\\power_grid_model\\core\\error_handling.py:164\u001b[0m, in \u001b[0;36massert_no_error\u001b[1;34m(batch_size, decode_error)\u001b[0m\n\u001b[0;32m 162\u001b[0m error \u001b[38;5;241m=\u001b[39m find_error(batch_size\u001b[38;5;241m=\u001b[39mbatch_size, decode_error\u001b[38;5;241m=\u001b[39mdecode_error)\n\u001b[0;32m 163\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m error \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 164\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m error\n", + "File \u001b[1;32m~\\Documents\\power-grid-model\\src\\power_grid_model\\core\\power_grid_model.py:125\u001b[0m, in \u001b[0;36mPowerGridModel.__init__\u001b[1;34m(self, input_data, system_frequency)\u001b[0m\n\u001b[0;32m 123\u001b[0m prepared_input \u001b[38;5;241m=\u001b[39m prepare_input_view(_map_to_component_types(input_data))\n\u001b[0;32m 124\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_model_ptr \u001b[38;5;241m=\u001b[39m pgc\u001b[38;5;241m.\u001b[39mcreate_model(system_frequency, input_data\u001b[38;5;241m=\u001b[39mprepared_input\u001b[38;5;241m.\u001b[39mget_dataset_ptr())\n\u001b[1;32m--> 125\u001b[0m \u001b[43massert_no_error\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 126\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_all_component_count \u001b[38;5;241m=\u001b[39m {k: v \u001b[38;5;28;01mfor\u001b[39;00m k, v \u001b[38;5;129;01min\u001b[39;00m prepared_input\u001b[38;5;241m.\u001b[39mget_info()\u001b[38;5;241m.\u001b[39mtotal_elements()\u001b[38;5;241m.\u001b[39mitems() \u001b[38;5;28;01mif\u001b[39;00m v \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m}\n", + "File \u001b[1;32m~\\Documents\\power-grid-model\\src\\power_grid_model\\core\\error_handling.py:169\u001b[0m, in \u001b[0;36massert_no_error\u001b[1;34m(batch_size, decode_error)\u001b[0m\n\u001b[0;32m 167\u001b[0m error \u001b[38;5;241m=\u001b[39m find_error(batch_size\u001b[38;5;241m=\u001b[39mbatch_size, decode_error\u001b[38;5;241m=\u001b[39mdecode_error)\n\u001b[0;32m 168\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m error \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 169\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m error\n", "\u001b[1;31mIDWrongType\u001b[0m: Wrong type for object with id 4\n\nTry validate_input_data() or validate_batch_data() to validate your data.\n" ] } @@ -133,14 +133,14 @@ "outputs": [ { "ename": "ValidationException", - "evalue": "There are 5 validation errors in input_data:\n 1. Fields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 line.\n 3. Field 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)", + "evalue": "There are 5 validation errors in input_data:\n 1. Fields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 ComponentType.line.\n 3. Field 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mValidationException\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[3], line 4\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpower_grid_model\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mvalidation\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m assert_valid_input_data\n\u001b[0;32m 3\u001b[0m \u001b[38;5;66;03m# Assert valid data\u001b[39;00m\n\u001b[1;32m----> 4\u001b[0m \u001b[43massert_valid_input_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43merror_data\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msymmetric\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[0;32m 5\u001b[0m model \u001b[38;5;241m=\u001b[39m PowerGridModel(error_data)\n\u001b[0;32m 6\u001b[0m output_data \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mcalculate_state_estimation(symmetric\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", "File \u001b[1;32m~\\Documents\\power-grid-model\\src\\power_grid_model\\validation\\assertions.py:57\u001b[0m, in \u001b[0;36massert_valid_input_data\u001b[1;34m(input_data, calculation_type, symmetric)\u001b[0m\n\u001b[0;32m 53\u001b[0m validation_errors \u001b[38;5;241m=\u001b[39m validate_input_data(\n\u001b[0;32m 54\u001b[0m input_data\u001b[38;5;241m=\u001b[39minput_data, calculation_type\u001b[38;5;241m=\u001b[39mcalculation_type, symmetric\u001b[38;5;241m=\u001b[39msymmetric\n\u001b[0;32m 55\u001b[0m )\n\u001b[0;32m 56\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m validation_errors:\n\u001b[1;32m---> 57\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ValidationException(validation_errors, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minput_data\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[1;31mValidationException\u001b[0m: There are 5 validation errors in input_data:\n 1. Fields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 line.\n 3. Field 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)" + "\u001b[1;31mValidationException\u001b[0m: There are 5 validation errors in input_data:\n 1. Fields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 ComponentType.line.\n 3. Field 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)" ] } ], @@ -163,11 +163,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "MultiComponentNotUniqueError ['line', 'sym_power_sensor'] : [('line', 6), ('sym_power_sensor', 6)]\n", - "InvalidIdError line : [6]\n", - "NotGreaterThanError sym_power_sensor : [6, 7]\n", - "InvalidIdError sym_power_sensor : [6]\n", - "InvalidIdError sym_power_sensor : [7]\n" + "MultiComponentNotUniqueError [, ] : [(, np.int32(6)), (, np.int32(6))]\n", + "InvalidIdError ComponentType.line : [6]\n", + "NotGreaterThanError ComponentType.sym_power_sensor : [6, 7]\n", + "InvalidIdError ComponentType.sym_power_sensor : [6]\n", + "InvalidIdError ComponentType.sym_power_sensor : [7]\n" ] } ], @@ -195,11 +195,11 @@ "output_type": "stream", "text": [ "There are 5 validation errors in the data:\n", - " 1. Fields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n", - " 2. Field 'to_node' does not contain a valid node id for 1 line.\n", - " 3. Field 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n", - " 4. Field 'measured_object' does not contain a valid line/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n", - " 5. Field 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)\n" + " 1. Fields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n", + " 2. Field 'to_node' does not contain a valid node id for 1 ComponentType.line.\n", + " 3. Field 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n", + " 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n", + " 5. Field 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)\n" ] } ], @@ -227,33 +227,33 @@ "text": [ "There are 5 validation errors in the data:\n", "\n", - "\tFields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n", - "\t\tcomponent: line/sym_power_sensor\n", - "\t\tfield: line.id and sym_power_sensor.id\n", - "\t\tids: [('line', 6), ('sym_power_sensor', 6)]\n", + "\tFields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n", + "\t\tcomponent: ComponentType.line/ComponentType.sym_power_sensor\n", + "\t\tfield: ComponentType.line.id and ComponentType.sym_power_sensor.id\n", + "\t\tids: [(, np.int32(6)), (, np.int32(6))]\n", "\n", - "\tField 'to_node' does not contain a valid node id for 1 line.\n", - "\t\tcomponent: line\n", + "\tField 'to_node' does not contain a valid node id for 1 ComponentType.line.\n", + "\t\tcomponent: ComponentType.line\n", "\t\tfield: 'to_node'\n", "\t\tids: [6]\n", "\t\tref_components: node\n", "\t\tfilters: \n", "\n", - "\tField 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n", - "\t\tcomponent: sym_power_sensor\n", + "\tField 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n", + "\t\tcomponent: ComponentType.sym_power_sensor\n", "\t\tfield: 'power_sigma'\n", "\t\tids: [6, 7]\n", "\t\tref_value: zero\n", "\n", - "\tField 'measured_object' does not contain a valid line/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n", - "\t\tcomponent: sym_power_sensor\n", + "\tField 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n", + "\t\tcomponent: ComponentType.sym_power_sensor\n", "\t\tfield: 'measured_object'\n", "\t\tids: [6]\n", - "\t\tref_components: line/transformer\n", + "\t\tref_components: line/generic_branch/transformer\n", "\t\tfilters: (measured_terminal_type=branch_from)\n", "\n", - "\tField 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)\n", - "\t\tcomponent: sym_power_sensor\n", + "\tField 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)\n", + "\t\tcomponent: ComponentType.sym_power_sensor\n", "\t\tfield: 'measured_object'\n", "\t\tids: [7]\n", "\t\tref_components: source\n", From 738ae054134ed03c9e3b8fd56b7db59a79d6b5c6 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 15 Oct 2024 10:48:52 +0200 Subject: [PATCH 02/18] rerun state estimation notebook Signed-off-by: Martijn Govers --- docs/examples/State Estimation Example.ipynb | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/examples/State Estimation Example.ipynb b/docs/examples/State Estimation Example.ipynb index 124b0f720..8bec41a6e 100644 --- a/docs/examples/State Estimation Example.ipynb +++ b/docs/examples/State Estimation Example.ipynb @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "id": "ae11dc9a", "metadata": {}, "outputs": [], @@ -71,7 +71,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 2, "id": "6f008736", "metadata": {}, "outputs": [], @@ -160,7 +160,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 3, "id": "fab31f58", "metadata": {}, "outputs": [], @@ -184,7 +184,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 4, "id": "7ef134e9", "metadata": {}, "outputs": [], @@ -212,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 5, "id": "44c2de63", "metadata": {}, "outputs": [], @@ -235,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 6, "id": "a581a36e", "metadata": {}, "outputs": [ @@ -535,7 +535,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 7, "id": "40e6d425", "metadata": {}, "outputs": [ @@ -639,7 +639,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 8, "id": "699e31af", "metadata": {}, "outputs": [ @@ -806,7 +806,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 9, "id": "b3e3fdc9", "metadata": {}, "outputs": [ @@ -927,7 +927,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 10, "id": "445726f3", "metadata": {}, "outputs": [ @@ -993,7 +993,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 11, "id": "303af910", "metadata": {}, "outputs": [], @@ -1037,7 +1037,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 12, "id": "70f761a3", "metadata": {}, "outputs": [], @@ -1060,7 +1060,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 13, "id": "4d9d5de2", "metadata": {}, "outputs": [ From 0c0dab7d44e5f681be01e28a2c23f6b4c47076a3 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 15 Oct 2024 16:08:48 +0200 Subject: [PATCH 03/18] add columnar output to pf example Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 50 ++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index 4236bcc04..db64a5a46 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 12, "id": "ae11dc9a", "metadata": {}, "outputs": [], @@ -51,7 +51,7 @@ " # suppress warning about pyarrow as future required dependency\n", " import pandas as pd\n", "\n", - "from power_grid_model import LoadGenType, ComponentType, DatasetType\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" ] @@ -348,6 +348,52 @@ "print(pd.DataFrame(output_data[ComponentType.node]))" ] }, + { + "cell_type": "markdown", + "id": "d129b8de", + "metadata": {}, + "source": [ + "You can also request the output as columnar data" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f52dbdd7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "List of component types in result dataset\n", + "[, ]\n", + "------node result------\n", + " id energized u_pu u u_angle p q\n", + "0 1 1 0.998988 10489.375043 -0.003039 3.121451e+07 6.991358e+06\n", + "1 2 1 0.952126 9997.325181 -0.026031 -2.000000e+07 -5.000000e+06\n", + "2 6 1 0.962096 10102.012975 -0.021895 -1.000000e+07 -2.000000e+06\n" + ] + } + ], + "source": [ + "output_data = model.calculate_power_flow(\n", + " symmetric=True,\n", + " error_tolerance=1e-8,\n", + " max_iterations=20,\n", + " calculation_method=CalculationMethod.newton_raphson,\n", + " output_component_types={\n", + " ComponentType.node: None, # node output shall be row-based\n", + " ComponentType.line: ComponentAttributeFilterOptions.ALL, # request all line attributes as columnar data\n", + " },\n", + ")\n", + "\n", + "print(\"List of component types in result dataset\")\n", + "print(list(output_data.keys()))\n", + "print(\"------node result------\")\n", + "print(pd.DataFrame(output_data[ComponentType.node]))" + ] + }, { "attachments": {}, "cell_type": "markdown", From 7f4fc04a92c20ca70a13dfaca3bd849db6bce523 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 17 Oct 2024 07:37:34 +0200 Subject: [PATCH 04/18] add columnar data formats to power flow example Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 218 +++++++++++++++++++------ 1 file changed, 167 insertions(+), 51 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index db64a5a46..f6a2a91ea 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 1, "id": "ae11dc9a", "metadata": {}, "outputs": [], @@ -53,7 +53,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" + "from power_grid_model import initialize_array, power_grid_meta_data" ] }, { @@ -122,6 +122,39 @@ "}" ] }, + { + "cell_type": "markdown", + "id": "102d862d", + "metadata": {}, + "source": [ + "It is also possible to specify a component input data in a columnar data format.\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." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "1034f6f3", + "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", + "}\n", + "\n", + "input_data = {\n", + " ComponentType.node: node,\n", + " ComponentType.line: line,\n", + " ComponentType.sym_load: sym_load,\n", + " ComponentType.source: source_columns,\n", + "}" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -133,7 +166,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "id": "f0c8c3e8", "metadata": {}, "outputs": [ @@ -174,7 +207,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "id": "40509eaf", "metadata": {}, "outputs": [], @@ -207,7 +240,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "id": "7ef134e9", "metadata": {}, "outputs": [], @@ -244,7 +277,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "44c2de63", "metadata": {}, "outputs": [], @@ -267,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "a581a36e", "metadata": {}, "outputs": [ @@ -315,7 +348,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "id": "30fdf18a", "metadata": {}, "outputs": [ @@ -353,12 +386,61 @@ "id": "d129b8de", "metadata": {}, "source": [ - "You can also request the output as columnar data" + "You can also request the output as a dictionary of attribute and their values columns for each component type." ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, + "id": "95ee7a35", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "List of component types in result dataset\n", + "[]\n", + "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" + ] + } + ], + "source": [ + "output_data = model.calculate_power_flow(\n", + " symmetric=True,\n", + " error_tolerance=1e-8,\n", + " max_iterations=20,\n", + " calculation_method=CalculationMethod.newton_raphson,\n", + " output_component_types={\n", + " ComponentType.line: [\"id\", \"p_from\"], # line output columns id and p_from\n", + " },\n", + ")\n", + "print(\"List of component types in result dataset\")\n", + "print(list(output_data))\n", + "print(\"List of attribute types in line result\")\n", + "print(list(output_data[ComponentType.line]))\n", + "print(\"------line result------\")\n", + "print(output_data[ComponentType.line])" + ] + }, + { + "cell_type": "markdown", + "id": "e564346b", + "metadata": {}, + "source": [ + "You can also mix output types between components. In this example:\n", + "\n", + "* `None` requests row-based data\n", + "* a list of attribute names requests columns for those attributes (as before)\n", + "* `ComponentAttributeFilterOptions.ALL` requests columns for all supported attributes of a component." + ] + }, + { + "cell_type": "code", + "execution_count": 11, "id": "f52dbdd7", "metadata": {}, "outputs": [ @@ -367,12 +449,21 @@ "output_type": "stream", "text": [ "List of component types in result dataset\n", - "[, ]\n", + "[, , ]\n", "------node result------\n", " id energized u_pu u u_angle p q\n", "0 1 1 0.998988 10489.375043 -0.003039 3.121451e+07 6.991358e+06\n", "1 2 1 0.952126 9997.325181 -0.026031 -2.000000e+07 -5.000000e+06\n", - "2 6 1 0.962096 10102.012975 -0.021895 -1.000000e+07 -2.000000e+06\n" + "2 6 1 0.962096 10102.012975 -0.021895 -1.000000e+07 -2.000000e+06\n", + "------line result------\n", + " id p_from\n", + "0 3 1.736010e+07\n", + "1 5 -3.365614e+06\n", + "2 8 1.385441e+07\n", + "------sym_load result------\n", + " id energized p q i s pf\n", + "0 4 1 20000000.0 5000000.0 1190.556524 2.061553e+07 0.970143\n", + "1 7 1 10000000.0 2000000.0 582.838350 1.019804e+07 0.980581\n" ] } ], @@ -383,15 +474,20 @@ " max_iterations=20,\n", " calculation_method=CalculationMethod.newton_raphson,\n", " output_component_types={\n", - " ComponentType.node: None, # node output shall be row-based\n", - " ComponentType.line: ComponentAttributeFilterOptions.ALL, # request all line attributes as columnar data\n", + " ComponentType.node: None, # node output as row-based\n", + " ComponentType.line: [\"id\", \"p_from\"], # line output columns id and p_from\n", + " ComponentType.sym_load: ComponentAttributeFilterOptions.ALL, # all sym_load attributes as columns\n", " },\n", ")\n", "\n", "print(\"List of component types in result dataset\")\n", "print(list(output_data.keys()))\n", "print(\"------node result------\")\n", - "print(pd.DataFrame(output_data[ComponentType.node]))" + "print(pd.DataFrame(output_data[ComponentType.node]))\n", + "print(\"------line result------\")\n", + "print(pd.DataFrame(output_data[ComponentType.line]))\n", + "print(\"------sym_load result------\")\n", + "print(pd.DataFrame(output_data[ComponentType.sym_load]))" ] }, { @@ -422,7 +518,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, "id": "ecbb8eeb", "metadata": {}, "outputs": [ @@ -481,7 +577,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 13, "id": "1d035c65", "metadata": {}, "outputs": [], @@ -499,6 +595,31 @@ "update_data = {ComponentType.sym_load: update_sym_load, ComponentType.line: update_line}" ] }, + { + "cell_type": "markdown", + "id": "fcc57354", + "metadata": {}, + "source": [ + "Columnar data is also supported" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "aaf8fe64", + "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", + "}\n", + "# leave to-side swiching status the same, no need to specify\n", + "\n", + "update_data = {ComponentType.sym_load: update_sym_load, ComponentType.line: columnar_update_line}" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -512,7 +633,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 15, "id": "63ea4cc3", "metadata": {}, "outputs": [], @@ -535,7 +656,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 16, "id": "188f6663", "metadata": {}, "outputs": [], @@ -557,7 +678,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 17, "id": "a93c1e16", "metadata": {}, "outputs": [ @@ -646,7 +767,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 18, "id": "42d5cd8f", "metadata": {}, "outputs": [], @@ -680,7 +801,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 19, "id": "4e25006f", "metadata": { "scrolled": true @@ -723,7 +844,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 20, "id": "afccf7a2", "metadata": { "scrolled": true @@ -760,7 +881,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 21, "id": "9af1be38", "metadata": { "scrolled": true @@ -803,7 +924,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 22, "id": "041368dc", "metadata": {}, "outputs": [], @@ -833,7 +954,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 23, "id": "34338ce3", "metadata": {}, "outputs": [ @@ -865,7 +986,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 24, "id": "04e56690", "metadata": {}, "outputs": [], @@ -897,7 +1018,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 25, "id": "0d5b94c2", "metadata": {}, "outputs": [ @@ -980,7 +1101,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 26, "id": "b5f10bae", "metadata": {}, "outputs": [ @@ -1040,7 +1161,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 27, "id": "1a221507", "metadata": {}, "outputs": [ @@ -1082,7 +1203,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 28, "id": "541af620", "metadata": {}, "outputs": [ @@ -1130,7 +1251,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 29, "id": "20d8285c", "metadata": {}, "outputs": [], @@ -1141,7 +1262,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 30, "id": "b702eb15", "metadata": {}, "outputs": [ @@ -1176,7 +1297,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 31, "id": "1ba71901", "metadata": {}, "outputs": [ @@ -1185,16 +1306,16 @@ "output_type": "stream", "text": [ "Node data with invalid results\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", - " [ 1.05085968e+056 -4.32115156e-239 -5.52267234e+127]\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.67933810e+092 -1.76263646e-197 1.52450807e-227]\n", - " [ 9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", - " [ 9.98688504e-001 9.29997471e-001 9.44441670e-001]]\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", + " [4.53944528e-298 2.91382246e-172 1.82941837e-316]\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", + " [0.00000000e+000 2.42618124e-273 0.00000000e+000]\n", + " [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", + " [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n", "Node data with only valid results\n", "[[0.99940117 0.99268579 0.99452137]\n", " [0.99934769 0.98622639 0.98935286]\n", @@ -1237,7 +1358,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -1251,12 +1372,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" - }, - "vscode": { - "interpreter": { - "hash": "f2534ebf7a1a13ecc51c3a04ce741b49cf1feb97b5ca55170ed7b2036b4058c0" - } + "version": "3.13.0" } }, "nbformat": 4, From b2d63d64bb8faf524572507d5c271ddc2eab8ec3 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 17 Oct 2024 07:47:51 +0200 Subject: [PATCH 05/18] all attributes as columns in pf notebook Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 87 ++++++++++++++++++++------ 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index f6a2a91ea..f1fb11e09 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -490,6 +490,53 @@ "print(pd.DataFrame(output_data[ComponentType.sym_load]))" ] }, + { + "cell_type": "markdown", + "id": "14a34c07", + "metadata": {}, + "source": [ + "Finally, it is possible to request columnar data for all attributes using the `ComponentAttributeFilterOptions.ALL` as a shorthand." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "e89882f5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "List of component types in result dataset\n", + "[, , , ]\n", + "List of attribute types in node result\n", + "['id', 'energized', 'u_pu', 'u', 'u_angle', 'p', 'q']\n", + "------node result------\n", + " id energized u_pu u u_angle p q\n", + "0 1 1 0.998988 10489.375043 -0.003039 3.121451e+07 6.991358e+06\n", + "1 2 1 0.952126 9997.325181 -0.026031 -2.000000e+07 -5.000000e+06\n", + "2 6 1 0.962096 10102.012975 -0.021895 -1.000000e+07 -2.000000e+06\n" + ] + } + ], + "source": [ + "output_data = model.calculate_power_flow(\n", + " symmetric=True,\n", + " error_tolerance=1e-8,\n", + " max_iterations=20,\n", + " calculation_method=CalculationMethod.newton_raphson,\n", + " output_component_types=ComponentAttributeFilterOptions.ALL, # all attributes for all component types as columns\n", + ")\n", + "\n", + "print(\"List of component types in result dataset\")\n", + "print(list(output_data.keys()))\n", + "print(\"List of attribute types in node result\")\n", + "print(list(output_data[ComponentType.node].keys()))\n", + "print(\"------node result------\")\n", + "print(pd.DataFrame(output_data[ComponentType.node]))" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -518,7 +565,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "id": "ecbb8eeb", "metadata": {}, "outputs": [ @@ -577,7 +624,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "id": "1d035c65", "metadata": {}, "outputs": [], @@ -605,7 +652,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "id": "aaf8fe64", "metadata": {}, "outputs": [], @@ -633,7 +680,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "id": "63ea4cc3", "metadata": {}, "outputs": [], @@ -656,7 +703,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "id": "188f6663", "metadata": {}, "outputs": [], @@ -678,7 +725,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 18, "id": "a93c1e16", "metadata": {}, "outputs": [ @@ -767,7 +814,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 19, "id": "42d5cd8f", "metadata": {}, "outputs": [], @@ -801,7 +848,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "id": "4e25006f", "metadata": { "scrolled": true @@ -844,7 +891,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "id": "afccf7a2", "metadata": { "scrolled": true @@ -881,7 +928,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "id": "9af1be38", "metadata": { "scrolled": true @@ -924,7 +971,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "id": "041368dc", "metadata": {}, "outputs": [], @@ -954,7 +1001,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "id": "34338ce3", "metadata": {}, "outputs": [ @@ -986,7 +1033,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "id": "04e56690", "metadata": {}, "outputs": [], @@ -1018,7 +1065,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 26, "id": "0d5b94c2", "metadata": {}, "outputs": [ @@ -1101,7 +1148,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 27, "id": "b5f10bae", "metadata": {}, "outputs": [ @@ -1161,7 +1208,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 28, "id": "1a221507", "metadata": {}, "outputs": [ @@ -1203,7 +1250,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 29, "id": "541af620", "metadata": {}, "outputs": [ @@ -1251,7 +1298,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 30, "id": "20d8285c", "metadata": {}, "outputs": [], @@ -1262,7 +1309,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 31, "id": "b702eb15", "metadata": {}, "outputs": [ @@ -1297,7 +1344,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 32, "id": "1ba71901", "metadata": {}, "outputs": [ From ba5a8a16cd2a769025bc6c60fb471c4801e197df Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 17 Oct 2024 07:49:15 +0200 Subject: [PATCH 06/18] improve section headers Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index f1fb11e09..003dbb579 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -339,7 +339,7 @@ "id": "24893218", "metadata": {}, "source": [ - "### Select component types in the result dataset\n", + "### Select component types and format in the result dataset\n", "\n", "By default `power-grid-model` calculates the result attributes for all components. If you do not need all the component types in your results, for example if you are only interested in `node`, you can specify the list of the component types you want in the result dataset in the argument `output_component_types`.\n", "\n", @@ -1356,11 +1356,11 @@ "[[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", - " [4.53944528e-298 2.91382246e-172 1.82941837e-316]\n", + " [3.94357132e+180 2.87518198e+161 2.04418455e+214]\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", - " [0.00000000e+000 2.42618124e-273 0.00000000e+000]\n", + " [6.23512027e-085 1.05632950e-310 6.01123997e+175]\n", " [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", " [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n", "Node data with only valid results\n", From 414b4c73002e03f3d7e598dd9c6121bbd24fe8df Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 17 Oct 2024 08:20:38 +0200 Subject: [PATCH 07/18] add columnar data to serialization notebook Signed-off-by: Martijn Govers --- docs/examples/Serialization Example.ipynb | 271 +++++++++++++++++++++- 1 file changed, 267 insertions(+), 4 deletions(-) diff --git a/docs/examples/Serialization Example.ipynb b/docs/examples/Serialization Example.ipynb index d3b39f2c3..0528573fc 100644 --- a/docs/examples/Serialization Example.ipynb +++ b/docs/examples/Serialization Example.ipynb @@ -30,7 +30,7 @@ " # suppress warning about pyarrow as future required dependency\n", " from pandas import DataFrame\n", "\n", - "from power_grid_model import PowerGridModel, ComponentType\n", + "from power_grid_model import PowerGridModel, ComponentType, ComponentAttributeFilterOptions\n", "from power_grid_model.utils import json_deserialize, json_serialize" ] }, @@ -42,7 +42,9 @@ "\n", "The data is in the `data/serialized-input.json` file.\n", "\n", - "### Load the JSON file" + "### Load the JSON file\n", + "\n", + "This is just for illustration purposes." ] }, { @@ -122,9 +124,19 @@ "name": "stdout", "output_type": "stream", "text": [ - "components: dict_keys([, , , ])\n" + "components: [, , , ]\n" ] }, + { + "data": { + "text/plain": [ + "array([(1, 10500.), (2, 10500.), (3, 10500.)],\n", + " dtype={'names': ['id', 'u_rated'], 'formats': [', , , ]\n" + ] + }, + { + "data": { + "text/plain": [ + "{'id': array([1, 2, 3], dtype=int32),\n", + " 'u_rated': array([10500., 10500., 10500.])}" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idu_rated
0110500.0
1210500.0
2310500.0
\n", + "
" + ], + "text/plain": [ + " id u_rated\n", + "0 1 10500.0\n", + "1 2 10500.0\n", + "2 3 10500.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "dataset = json_deserialize(data, data_filter=ComponentAttributeFilterOptions.ALL)\n", + "\n", + "print(\"components:\", list(dataset.keys()))\n", + "display(dataset[ComponentType.node])\n", + "display(DataFrame(dataset[ComponentType.node]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Deserialized data format selection per component type\n", + "\n", + "To select specific components and data formats for the deserialized data, provide a dictionary of components and their desired output types to the `data_filter`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "components: [, , , ]\n", + "node attributes: ['id', 'u_rated']\n", + "source attributes: ['id', 'node', 'status', 'u_ref', 'sk']\n", + "sym_load attributes: ['id', 'node', 'status', 'type', 'p_specified', 'q_specified']\n", + "line attributes: ['id', 'from_node', 'to_node', 'from_status', 'to_status', 'r1', 'x1', 'c1', 'tan1', 'i_n']\n", + "-------node data-------\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idu_rated
0110500.0
1210500.0
2310500.0
\n", + "
" + ], + "text/plain": [ + " id u_rated\n", + "0 1 10500.0\n", + "1 2 10500.0\n", + "2 3 10500.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "dataset = json_deserialize(\n", + " data,\n", + " data_filter={\n", + " ComponentType.node: None, # nodes in a row-based data format\n", + " ComponentType.source: [\"id\", \"node\", \"status\", \"u_ref\", \"sk\"], # only specific attributes\n", + " ComponentType.sym_load: ComponentAttributeFilterOptions.ALL, # all attributes as columns\n", + " ComponentType.line: ComponentAttributeFilterOptions.RELEVANT, # only attributes that are not null/nan\n", + " },\n", + ")\n", + "\n", + "print(\"components:\", list(dataset.keys()))\n", + "print(\"node attributes:\", list(dataset[ComponentType.node].dtype.names))\n", + "print(\"source attributes:\", list(dataset[ComponentType.source].keys()))\n", + "print(\"sym_load attributes:\", list(dataset[ComponentType.sym_load].keys()))\n", + "print(\"line attributes:\", list(dataset[ComponentType.line].keys()))\n", + "print(\"-------node data-------\")\n", + "display(DataFrame(dataset[ComponentType.node]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A columnar dataset can also be serialized again, as one would expect." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"version\": \"1.0\",\n", + " \"type\": \"sym_output\",\n", + " \"is_batch\": false,\n", + " \"attributes\": {},\n", + " \"data\": {\n", + " \"node\": [\n", + " {\"id\": 1, \"energized\": 1, \"u_pu\": 1.030000000001025, \"u\": 10815.00000001077, \"u_angle\": -2.530316910142707e-14, \"p\": 2408997.839438867, \"q\": -2863495.364674167},\n", + " {\"id\": 2, \"energized\": 1, \"u_pu\": 1.029996969815606, \"u\": 10814.96818306386, \"u_angle\": -0.004397999804754745, \"p\": -1009999.99999997, \"q\": -210000.0000000655},\n", + " {\"id\": 3, \"energized\": 1, \"u_pu\": 1.029483905569345, \"u\": 10809.58100847812, \"u_angle\": -0.006839956175380238, \"p\": -1019999.999999999, \"q\": -219999.9999999689}\n", + " ],\n", + " \"line\": [\n", + " {\"id\": 4, \"energized\": 1, \"loading\": 0.3995319091937107, \"p_from\": 2408997.839438867, \"q_from\": -2863495.364674167, \"i_from\": 199.7659545968554, \"s_from\": 3742041.7279784, \"p_to\": -2252625.764367544, \"q_to\": 1403928.536947823, \"i_to\": 141.6984332838951, \"s_to\": 2654305.591138465},\n", + " {\"id\": 5, \"energized\": 1, \"loading\": 0.1977047433812966, \"p_from\": 1242625.764367574, \"q_from\": -1613928.536947772, \"i_from\": 108.7376088597131, \"s_from\": 2036880.976553238, \"p_to\": -1019999.999999999, \"q_to\": -219999.9999999689, \"i_to\": 55.73199226981006, \"s_to\": 1043455.796859639}\n", + " ],\n", + " \"source\": [\n", + " {\"id\": 15, \"energized\": 1, \"p\": -7836685.751732428, \"q\": -105348495.343833, \"i\": 5639.485452974508, \"s\": 105639571.7275539, \"pf\": -0.07418324046166491},\n", + " {\"id\": 16, \"energized\": 1, \"p\": 10248883.05839198, \"q\": 102488830.5811954, \"i\": 5498.573991718361, \"s\": 102999999.9895415, \"pf\": 0.09950371902361781},\n", + " {\"id\": 17, \"energized\": 1, \"p\": -0.001807829591278542, \"q\": -0.0104081191056169, \"i\": 5.639485452974507e-07, \"s\": 0.01056395717275539, \"pf\": -0.1711318553942043}\n", + " ],\n", + " \"sym_load\": [\n", + " {\"id\": 7, \"energized\": 1, \"p\": 1010000, \"q\": 210000, \"i\": 55.07135393955915, \"s\": 1031600.697944704, \"pf\": 0.979060989404389},\n", + " {\"id\": 8, \"energized\": 1, \"p\": 1020000, \"q\": 220000, \"i\": 55.73199226981046, \"s\": 1043455.796859647, \"pf\": 0.9775210440823288}\n", + " ]\n", + " }\n", + "}\n" + ] + } + ], + "source": [ + "serialized_output = json_serialize(output)\n", + "\n", + "print(serialized_output)" + ] } ], "metadata": { From e7cc8fd2a75725c0c724977b76cba8f51137a9d5 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 18 Oct 2024 08:48:17 +0200 Subject: [PATCH 08/18] fix formatting of validation error Signed-off-by: Martijn Govers --- docs/examples/Validation Examples.ipynb | 45 +++++++-------- src/power_grid_model/validation/errors.py | 20 +++++-- tests/unit/validation/test_errors.py | 70 +++++++++++++---------- tests/unit/validation/test_rules.py | 8 ++- 4 files changed, 82 insertions(+), 61 deletions(-) diff --git a/docs/examples/Validation Examples.ipynb b/docs/examples/Validation Examples.ipynb index 4d2f39bfc..6b09acf8c 100644 --- a/docs/examples/Validation Examples.ipynb +++ b/docs/examples/Validation Examples.ipynb @@ -133,14 +133,14 @@ "outputs": [ { "ename": "ValidationException", - "evalue": "There are 5 validation errors in input_data:\n 1. Fields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 ComponentType.line.\n 3. Field 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)", + "evalue": "There are 5 validation errors in input_data:\n 1. Fields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 line.\n 3. Field 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mValidationException\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[3], line 4\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpower_grid_model\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mvalidation\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m assert_valid_input_data\n\u001b[0;32m 3\u001b[0m \u001b[38;5;66;03m# Assert valid data\u001b[39;00m\n\u001b[1;32m----> 4\u001b[0m \u001b[43massert_valid_input_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43merror_data\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msymmetric\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[0;32m 5\u001b[0m model \u001b[38;5;241m=\u001b[39m PowerGridModel(error_data)\n\u001b[0;32m 6\u001b[0m output_data \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mcalculate_state_estimation(symmetric\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", "File \u001b[1;32m~\\Documents\\power-grid-model\\src\\power_grid_model\\validation\\assertions.py:57\u001b[0m, in \u001b[0;36massert_valid_input_data\u001b[1;34m(input_data, calculation_type, symmetric)\u001b[0m\n\u001b[0;32m 53\u001b[0m validation_errors \u001b[38;5;241m=\u001b[39m validate_input_data(\n\u001b[0;32m 54\u001b[0m input_data\u001b[38;5;241m=\u001b[39minput_data, calculation_type\u001b[38;5;241m=\u001b[39mcalculation_type, symmetric\u001b[38;5;241m=\u001b[39msymmetric\n\u001b[0;32m 55\u001b[0m )\n\u001b[0;32m 56\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m validation_errors:\n\u001b[1;32m---> 57\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ValidationException(validation_errors, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minput_data\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[1;31mValidationException\u001b[0m: There are 5 validation errors in input_data:\n 1. Fields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 ComponentType.line.\n 3. Field 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)" + "\u001b[1;31mValidationException\u001b[0m: There are 5 validation errors in input_data:\n 1. Fields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n 2. Field 'to_node' does not contain a valid node id for 1 line.\n 3. Field 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n 5. Field 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)" ] } ], @@ -195,11 +195,11 @@ "output_type": "stream", "text": [ "There are 5 validation errors in the data:\n", - " 1. Fields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n", - " 2. Field 'to_node' does not contain a valid node id for 1 ComponentType.line.\n", - " 3. Field 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n", - " 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n", - " 5. Field 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)\n" + " 1. Fields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n", + " 2. Field 'to_node' does not contain a valid node id for 1 line.\n", + " 3. Field 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n", + " 4. Field 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n", + " 5. Field 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)\n" ] } ], @@ -227,33 +227,33 @@ "text": [ "There are 5 validation errors in the data:\n", "\n", - "\tFields ComponentType.line.id and ComponentType.sym_power_sensor.id are not unique for 2 ComponentsTypes.lines/ComponentsTypes.sym_power_sensors.\n", - "\t\tcomponent: ComponentType.line/ComponentType.sym_power_sensor\n", - "\t\tfield: ComponentType.line.id and ComponentType.sym_power_sensor.id\n", + "\tFields line.id and sym_power_sensor.id are not unique for 2 lines/sym_power_sensors.\n", + "\t\tcomponent: line/sym_power_sensor\n", + "\t\tfield: line.id and sym_power_sensor.id\n", "\t\tids: [(, np.int32(6)), (, np.int32(6))]\n", "\n", - "\tField 'to_node' does not contain a valid node id for 1 ComponentType.line.\n", - "\t\tcomponent: ComponentType.line\n", + "\tField 'to_node' does not contain a valid node id for 1 line.\n", + "\t\tcomponent: line\n", "\t\tfield: 'to_node'\n", "\t\tids: [6]\n", "\t\tref_components: node\n", "\t\tfilters: \n", "\n", - "\tField 'power_sigma' is not greater than zero for 2 ComponentsTypes.sym_power_sensors.\n", - "\t\tcomponent: ComponentType.sym_power_sensor\n", + "\tField 'power_sigma' is not greater than zero for 2 sym_power_sensors.\n", + "\t\tcomponent: sym_power_sensor\n", "\t\tfield: 'power_sigma'\n", "\t\tids: [6, 7]\n", "\t\tref_value: zero\n", "\n", - "\tField 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=branch_from)\n", - "\t\tcomponent: ComponentType.sym_power_sensor\n", + "\tField 'measured_object' does not contain a valid line/generic_branch/transformer id for 1 sym_power_sensor. (measured_terminal_type=branch_from)\n", + "\t\tcomponent: sym_power_sensor\n", "\t\tfield: 'measured_object'\n", "\t\tids: [6]\n", "\t\tref_components: line/generic_branch/transformer\n", "\t\tfilters: (measured_terminal_type=branch_from)\n", "\n", - "\tField 'measured_object' does not contain a valid source id for 1 ComponentType.sym_power_sensor. (measured_terminal_type=source)\n", - "\t\tcomponent: ComponentType.sym_power_sensor\n", + "\tField 'measured_object' does not contain a valid source id for 1 sym_power_sensor. (measured_terminal_type=source)\n", + "\t\tcomponent: sym_power_sensor\n", "\t\tfield: 'measured_object'\n", "\t\tids: [7]\n", "\t\tref_components: source\n", @@ -271,7 +271,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -285,12 +285,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" - }, - "vscode": { - "interpreter": { - "hash": "39f035c5e58f53e973c1999fdd4393d6db2dd3f04fe05f524988f90f4bbdb576" - } + "version": "3.13.0" } }, "nbformat": 4, diff --git a/src/power_grid_model/validation/errors.py b/src/power_grid_model/validation/errors.py index a956810a5..f7349ecb7 100644 --- a/src/power_grid_model/validation/errors.py +++ b/src/power_grid_model/validation/errors.py @@ -58,13 +58,26 @@ def component_str(self) -> str: """ A string representation of the component to which this error applies """ - return str(self.component) + if self.component is None: + return str(None) + if isinstance(self.component, list): + return str(list(component.value for component in self.component)) + return self.component.value @property def field_str(self) -> str: """ A string representation of the field to which this error applies """ + + def _unpack(field: str | tuple[ComponentType, str]) -> str: + if isinstance(field, str): + return field + component, component_field = field + return str((component.value, component_field)) + + if isinstance(self.field, list): + return str(list(_unpack(field) for field in self.field)) return f"'{self.field}'" def get_context(self, id_lookup: Optional[list[str] | dict[int, str]] = None) -> dict[str, Any]: @@ -189,12 +202,11 @@ def __init__(self, fields: list[tuple[ComponentType, str]], ids: list[tuple[Comp @property def component_str(self) -> str: - str_components = [str(component) for component in self.component] - return "/".join(str_components) + return "/".join(component.value for component in self.component) @property def field_str(self) -> str: - return self._delimiter.join(f"{component}.{field}" for component, field in self.field) + return self._delimiter.join(f"{component.value}.{field}" for component, field in self.field) class NotIdenticalError(SingleFieldValidationError): diff --git a/tests/unit/validation/test_errors.py b/tests/unit/validation/test_errors.py index 5c0d87968..2c59dbf80 100644 --- a/tests/unit/validation/test_errors.py +++ b/tests/unit/validation/test_errors.py @@ -6,6 +6,7 @@ import pytest +from power_grid_model import ComponentType from power_grid_model.validation.errors import ( ComparisonError, InvalidAssociatedEnumValueError, @@ -24,62 +25,69 @@ def test_validation_error(): def test_single_field_validation_error(): - error = SingleFieldValidationError(component="alpha", field="bravo", ids=[0, 1, 1, 2, 3, 5]) - assert error.component_str == "alpha" + error = SingleFieldValidationError(component=ComponentType.node, field="bravo", ids=[0, 1, 1, 2, 3, 5]) + assert error.component_str == "node" assert error.field_str == "'bravo'" - assert str(error) == "Field 'bravo' is not valid for 6 alphas." + assert str(error) == "Field 'bravo' is not valid for 6 nodes." def test_multi_field_validation_error(): - error = MultiFieldValidationError(component="charlie", fields=["delta", "echo"], ids=[0, 1, 1, 2, 3, 5]) - assert error.component_str == "charlie" + error = MultiFieldValidationError(component=ComponentType.node, fields=["delta", "echo"], ids=[0, 1, 1, 2, 3, 5]) + assert error.component_str == "node" assert error.field_str == "'delta' and 'echo'" - assert str(error) == "Combination of fields 'delta' and 'echo' is not valid for 6 charlies." + assert str(error) == "Combination of fields 'delta' and 'echo' is not valid for 6 nodes." with pytest.raises(ValueError, match="at least two fields"): - MultiFieldValidationError(component="charlie", fields=["delta"], ids=[]) + MultiFieldValidationError(component=ComponentType.node, fields=["delta"], ids=[]) def test_multi_component_validation_error(): error = MultiComponentValidationError( - fields=[("foxtrot", "golf"), ("hotel", "india")], - ids=[("foxtrot", 0), ("foxtrot", 1), ("foxtrot", 1), ("hotel", 2), ("hotel", 3), ("hotel", 5)], + fields=[(ComponentType.node, "golf"), (ComponentType.line, "india")], + ids=[ + (ComponentType.node, 0), + (ComponentType.node, 1), + (ComponentType.node, 1), + (ComponentType.line, 2), + (ComponentType.line, 3), + (ComponentType.line, 5), + ], ) - assert error.component_str == "foxtrot/hotel" - assert error.field_str == "foxtrot.golf and hotel.india" - assert str(error) == "Fields foxtrot.golf and hotel.india are not valid for 6 foxtrots/hotels." + assert error.component_str == "line/node" + assert error.field_str == "line.india and node.golf" + assert str(error) == "Fields line.india and node.golf are not valid for 6 lines/nodes." with pytest.raises(ValueError, match="at least two fields"): - MultiComponentValidationError(fields=[("foxtrot", "golf")], ids=[]) + MultiComponentValidationError(fields=[(ComponentType.node, "golf")], ids=[]) with pytest.raises(ValueError, match="at least two components"): - MultiComponentValidationError(fields=[("foxtrot", "golf"), ("foxtrot", "india")], ids=[]) + MultiComponentValidationError(fields=[(ComponentType.node, "golf"), (ComponentType.node, "india")], ids=[]) def test_invalid_enum_value_error(): class CustomType(IntEnum): pass - error = InvalidEnumValueError(component="kilo", field="lima", ids=[1, 2, 3], enum=CustomType) - assert error.component == "kilo" + error = InvalidEnumValueError(component=ComponentType.node, field="lima", ids=[1, 2, 3], enum=CustomType) + assert error.component == "node" assert error.field == "lima" assert error.ids == [1, 2, 3] assert error.enum is CustomType - assert str(error) == "Field 'lima' contains invalid CustomType values for 3 kilos." + assert str(error) == "Field 'lima' contains invalid CustomType values for 3 nodes." def test_invalid_id_error(): - error = InvalidIdError(component="mike", field="november", ids=[1, 2, 3], ref_components=["oscar", "papa"]) - assert error.component == "mike" + error = InvalidIdError(ComponentType.node, field="november", ids=[1, 2, 3], ref_components=["oscar", "papa"]) + assert error.component == "node" assert error.field == "november" assert error.ids == [1, 2, 3] assert error.ref_components == ["oscar", "papa"] - assert str(error) == "Field 'november' does not contain a valid oscar/papa id for 3 mikes." + assert str(error) == "Field 'november' does not contain a valid oscar/papa id for 3 nodes." def test_comparison_error(): - error = ComparisonError(component="quebec", field="romeo", ids=[1, 2, 3], ref_value=0) - assert error.component == "quebec" + error = ComparisonError(component=ComponentType.node, field="romeo", ids=[1, 2, 3], ref_value=0) + assert error.component == "node" assert error.field == "romeo" assert error.ids == [1, 2, 3] assert error.ref_value == 0 @@ -93,10 +101,10 @@ def test_comparison_error(): def test_error_context(): - error = ComparisonError(component="sierra", field="tango", ids=[1, 2, 3], ref_value=0) + error = ComparisonError(component=ComponentType.node, field="tango", ids=[1, 2, 3], ref_value=0) context = error.get_context() assert len(context) == 4 - assert context["component"] == "sierra" + assert context["component"] == "node" assert context["field"] == "'tango'" assert context["ids"] == [1, 2, 3] assert context["ref_value"] == "zero" @@ -109,20 +117,24 @@ def test_error_context(): def test_error_context_tuple_ids(): - error = MultiComponentValidationError(fields=[("a", "x"), ("b", "y")], ids=[("a", 1), ("b", 2), ("a", 3)]) + error = MultiComponentValidationError( + fields=[(ComponentType.node, "x"), ("b", "y")], ids=[(ComponentType.node, 1), ("b", 2), (ComponentType.node, 3)] + ) context = error.get_context(id_lookup={1: "Victor", 3: "Whiskey"}) - assert context["ids"] == {("a", 1): "Victor", ("b", 2): None, ("a", 3): "Whiskey"} + assert context["ids"] == {("node", 1): "Victor", ("b", 2): None, ("node", 3): "Whiskey"} def test_invalid_associated_enum_value_error(): class CustomType(IntEnum): pass - error = InvalidAssociatedEnumValueError(component="foo", fields=["bar", "baz"], ids=[1, 2], enum=[CustomType]) - assert error.component == "foo" + error = InvalidAssociatedEnumValueError( + component=ComponentType.node, fields=["bar", "baz"], ids=[1, 2], enum=[CustomType] + ) + assert error.component == "node" assert error.field == ["bar", "baz"] assert error.ids == [1, 2] assert len(error.enum) == 1 for actual, expected in zip(error.enum, [CustomType]): assert actual is expected - assert str(error) == "The combination of fields 'bar' and 'baz' results in invalid CustomType values for 2 foos." + assert str(error) == "The combination of fields 'bar' and 'baz' results in invalid CustomType values for 2 nodes." diff --git a/tests/unit/validation/test_rules.py b/tests/unit/validation/test_rules.py index 6f258826e..ff22676e0 100644 --- a/tests/unit/validation/test_rules.py +++ b/tests/unit/validation/test_rules.py @@ -7,7 +7,7 @@ import numpy as np import pytest -from power_grid_model import LoadGenType, initialize_array, power_grid_meta_data +from power_grid_model import ComponentType, LoadGenType, initialize_array, power_grid_meta_data from power_grid_model.enum import Branch3Side, BranchSide, FaultPhase, FaultType from power_grid_model.validation.errors import ( ComparisonError, @@ -304,14 +304,16 @@ def test_all_cross_unique(cross_only): "node": np.array([(1, 0.1), (2, 0.2), (3, 0.3)], dtype=[("id", "i4"), ("foo", "f8")]), "line": np.array([(4, 0.4), (5, 0.5), (6, 0.6), (7, 0.7)], dtype=[("id", "i4"), ("bar", "f8")]), } - errors = all_cross_unique(valid, [("node", "foo"), ("line", "bar")], cross_only=cross_only) + errors = all_cross_unique(valid, [(ComponentType.node, "foo"), (ComponentType.line, "bar")], cross_only=cross_only) assert not errors invalid = { "node": np.array([(1, 0.1), (2, 0.2), (3, 0.2)], dtype=[("id", "i4"), ("foo", "f8")]), "line": np.array([(4, 0.2), (5, 0.1), (6, 0.3), (7, 0.3)], dtype=[("id", "i4"), ("bar", "f8")]), } - errors = all_cross_unique(invalid, [("node", "foo"), ("line", "bar")], cross_only=cross_only) + errors = all_cross_unique( + invalid, [(ComponentType.node, "foo"), (ComponentType.line, "bar")], cross_only=cross_only + ) assert len(errors) == 1 error = errors.pop() assert isinstance(error, MultiComponentNotUniqueError) From 97d10598b42d54f27e4fce4bf858801f72f78b71 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 18 Oct 2024 13:26:15 +0200 Subject: [PATCH 09/18] Update docs/examples/Power Flow Example.ipynb Co-authored-by: Nitish Bharambe <78108900+nitbharambe@users.noreply.github.com> Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index 003dbb579..460cec7d0 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -339,7 +339,7 @@ "id": "24893218", "metadata": {}, "source": [ - "### Select component types and format in the result dataset\n", + "### Select components / attributes and format of result dataset\n", "\n", "By default `power-grid-model` calculates the result attributes for all components. If you do not need all the component types in your results, for example if you are only interested in `node`, you can specify the list of the component types you want in the result dataset in the argument `output_component_types`.\n", "\n", From 9c0d586fec68a9d2cd4a2b9cd67156f0592c1fc6 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 18 Oct 2024 13:36:32 +0200 Subject: [PATCH 10/18] Update docs/examples/Serialization Example.ipynb Signed-off-by: Martijn Govers Co-authored-by: Nitish Bharambe <78108900+nitbharambe@users.noreply.github.com> Signed-off-by: Martijn Govers --- docs/examples/Serialization Example.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/Serialization Example.ipynb b/docs/examples/Serialization Example.ipynb index 0528573fc..2ccecfcd1 100644 --- a/docs/examples/Serialization Example.ipynb +++ b/docs/examples/Serialization Example.ipynb @@ -609,7 +609,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Advanced control over deserialized dataset\n", + "## Selective deserialization and dataset format\n", "\n", "To control the dataset returned by the deserialization functionality, you can use the `data_filter` argument.\n", "\n", From 7b6aa7d09c08d4237c33fe04aac8184f1b7ccb34 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 18 Oct 2024 13:37:33 +0200 Subject: [PATCH 11/18] apply suggestions Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 51 +++++++++++--------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index 460cec7d0..106adc845 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -451,19 +451,11 @@ "List of component types in result dataset\n", "[, , ]\n", "------node result------\n", - " id energized u_pu u u_angle p q\n", - "0 1 1 0.998988 10489.375043 -0.003039 3.121451e+07 6.991358e+06\n", - "1 2 1 0.952126 9997.325181 -0.026031 -2.000000e+07 -5.000000e+06\n", - "2 6 1 0.962096 10102.012975 -0.021895 -1.000000e+07 -2.000000e+06\n", - "------line result------\n", - " id p_from\n", - "0 3 1.736010e+07\n", - "1 5 -3.365614e+06\n", - "2 8 1.385441e+07\n", - "------sym_load result------\n", - " id energized p q i s pf\n", - "0 4 1 20000000.0 5000000.0 1190.556524 2.061553e+07 0.970143\n", - "1 7 1 10000000.0 2000000.0 582.838350 1.019804e+07 0.980581\n" + "('id', 'energized', 'u_pu', 'u', 'u_angle', 'p', 'q')\n", + "------line result attributes------\n", + "['id', 'p_from']\n", + "------sym_load result attributes------\n", + "['id', 'energized', 'p', 'q', 'i', 's', 'pf']\n" ] } ], @@ -483,11 +475,11 @@ "print(\"List of component types in result dataset\")\n", "print(list(output_data.keys()))\n", "print(\"------node result------\")\n", - "print(pd.DataFrame(output_data[ComponentType.node]))\n", - "print(\"------line result------\")\n", - "print(pd.DataFrame(output_data[ComponentType.line]))\n", - "print(\"------sym_load result------\")\n", - "print(pd.DataFrame(output_data[ComponentType.sym_load]))" + "print(output_data[ComponentType.node].dtype.names)\n", + "print(\"------line result attributes------\")\n", + "print(list(output_data[ComponentType.line].keys()))\n", + "print(\"------sym_load result attributes------\")\n", + "print(list(output_data[ComponentType.sym_load].keys()))" ] }, { @@ -510,13 +502,12 @@ "text": [ "List of component types in result dataset\n", "[, , , ]\n", - "List of attribute types in node result\n", - "['id', 'energized', 'u_pu', 'u', 'u_angle', 'p', 'q']\n", "------node result------\n", - " id energized u_pu u u_angle p q\n", - "0 1 1 0.998988 10489.375043 -0.003039 3.121451e+07 6.991358e+06\n", - "1 2 1 0.952126 9997.325181 -0.026031 -2.000000e+07 -5.000000e+06\n", - "2 6 1 0.962096 10102.012975 -0.021895 -1.000000e+07 -2.000000e+06\n" + "['id', 'energized', 'u_pu', 'u', 'u_angle', 'p', 'q']\n", + "------line result attributes------\n", + "['id', 'energized', 'loading', 'p_from', 'q_from', 'i_from', 's_from', 'p_to', 'q_to', 'i_to', 's_to']\n", + "------sym_load result attributes------\n", + "['id', 'energized', 'p', 'q', 'i', 's', 'pf']\n" ] } ], @@ -531,10 +522,12 @@ "\n", "print(\"List of component types in result dataset\")\n", "print(list(output_data.keys()))\n", - "print(\"List of attribute types in node result\")\n", - "print(list(output_data[ComponentType.node].keys()))\n", "print(\"------node result------\")\n", - "print(pd.DataFrame(output_data[ComponentType.node]))" + "print(list(output_data[ComponentType.node].keys()))\n", + "print(\"------line result attributes------\")\n", + "print(list(output_data[ComponentType.line].keys()))\n", + "print(\"------sym_load result attributes------\")\n", + "print(list(output_data[ComponentType.sym_load].keys()))" ] }, { @@ -1356,11 +1349,11 @@ "[[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", - " [3.94357132e+180 2.87518198e+161 2.04418455e+214]\n", + " [6.01347174e-154 7.39986091e-038 6.55490955e-260]\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", - " [6.23512027e-085 1.05632950e-310 6.01123997e+175]\n", + " [6.95277073e-310 6.95277073e-310 6.95277073e-310]\n", " [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", " [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n", "Node data with only valid results\n", From 81a812ec94f1d0e1b04ebfcf8a6739a98323d252 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 21 Oct 2024 11:09:46 +0200 Subject: [PATCH 12/18] improve coverage by merging error type output Signed-off-by: Martijn Govers --- src/power_grid_model/validation/errors.py | 23 +++++------------------ tests/unit/validation/test_errors.py | 3 +++ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/power_grid_model/validation/errors.py b/src/power_grid_model/validation/errors.py index f7349ecb7..58bc84649 100644 --- a/src/power_grid_model/validation/errors.py +++ b/src/power_grid_model/validation/errors.py @@ -61,7 +61,7 @@ def component_str(self) -> str: if self.component is None: return str(None) if isinstance(self.component, list): - return str(list(component.value for component in self.component)) + return "/".join(component.value for component in self.component) return self.component.value @property @@ -72,13 +72,12 @@ def field_str(self) -> str: def _unpack(field: str | tuple[ComponentType, str]) -> str: if isinstance(field, str): - return field - component, component_field = field - return str((component.value, component_field)) + return f"'{field}'" + return ".".join(field) if isinstance(self.field, list): - return str(list(_unpack(field) for field in self.field)) - return f"'{self.field}'" + return self._delimiter.join(_unpack(field) for field in self.field) + return _unpack(self.field) if self.field else str(self.field) def get_context(self, id_lookup: Optional[list[str] | dict[int, str]] = None) -> dict[str, Any]: """ @@ -168,10 +167,6 @@ def __init__(self, component: ComponentType, fields: list[str], ids: list[int]): if len(self.field) < 2: raise ValueError(f"{type(self).__name__} expects at least two fields: {self.field}") - @property - def field_str(self) -> str: - return self._delimiter.join(f"'{field}'" for field in self.field) - class MultiComponentValidationError(ValidationError): """ @@ -200,14 +195,6 @@ def __init__(self, fields: list[tuple[ComponentType, str]], ids: list[tuple[Comp if len(self.component) < 2: raise ValueError(f"{type(self).__name__} expects at least two components: {self.component}") - @property - def component_str(self) -> str: - return "/".join(component.value for component in self.component) - - @property - def field_str(self) -> str: - return self._delimiter.join(f"{component.value}.{field}" for component, field in self.field) - class NotIdenticalError(SingleFieldValidationError): """ diff --git a/tests/unit/validation/test_errors.py b/tests/unit/validation/test_errors.py index 2c59dbf80..f4c980399 100644 --- a/tests/unit/validation/test_errors.py +++ b/tests/unit/validation/test_errors.py @@ -22,6 +22,9 @@ def test_validation_error(): error = ValidationError() assert str(error) == "An unknown validation error occurred." + assert error.component_str == str(None) + assert error.field_str == str(None) + assert not error.ids def test_single_field_validation_error(): From f6cd2be69d58c392975e3140134c39dc8c140b65 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 21 Oct 2024 11:12:54 +0200 Subject: [PATCH 13/18] update pf example Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index 106adc845..857fe44a7 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -448,8 +448,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "List of component types in result dataset\n", - "[, , ]\n", + "List of component types in result dataset and associated data types\n", + "{'ComponentType.node': , 'ComponentType.line': , 'ComponentType.sym_load': }\n", "------node result------\n", "('id', 'energized', 'u_pu', 'u', 'u_angle', 'p', 'q')\n", "------line result attributes------\n", @@ -472,8 +472,8 @@ " },\n", ")\n", "\n", - "print(\"List of component types in result dataset\")\n", - "print(list(output_data.keys()))\n", + "print(\"List of component types in result dataset and associated data types\")\n", + "print({str(component_type): type(component_data) for component_type, component_data in output_data.items()})\n", "print(\"------node result------\")\n", "print(output_data[ComponentType.node].dtype.names)\n", "print(\"------line result attributes------\")\n", @@ -500,8 +500,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "List of component types in result dataset\n", - "[, , , ]\n", + "List of component types in result dataset and associated data types\n", + "{'ComponentType.node': , 'ComponentType.line': , 'ComponentType.sym_load': , 'ComponentType.source': }\n", "------node result------\n", "['id', 'energized', 'u_pu', 'u', 'u_angle', 'p', 'q']\n", "------line result attributes------\n", @@ -520,8 +520,8 @@ " output_component_types=ComponentAttributeFilterOptions.ALL, # all attributes for all component types as columns\n", ")\n", "\n", - "print(\"List of component types in result dataset\")\n", - "print(list(output_data.keys()))\n", + "print(\"List of component types in result dataset and associated data types\")\n", + "print({str(component_type): type(component_data) for component_type, component_data in output_data.items()})\n", "print(\"------node result------\")\n", "print(list(output_data[ComponentType.node].keys()))\n", "print(\"------line result attributes------\")\n", @@ -1349,11 +1349,11 @@ "[[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.01347174e-154 7.39986091e-038 6.55490955e-260]\n", + " [1.26558258e-311 6.95272884e-310 1.26558638e-311]\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", - " [6.95277073e-310 6.95277073e-310 6.95277073e-310]\n", + " [6.95272884e-310 1.26558638e-311 6.95272884e-310]\n", " [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", " [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n", "Node data with only valid results\n", From c9aaeeeff8b36a3f331a602bc763199c8c09d710 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 21 Oct 2024 11:26:34 +0200 Subject: [PATCH 14/18] rerun notebooks Signed-off-by: Martijn Govers --- .../Asymmetric Calculation Example.ipynb | 9 ++----- docs/examples/Make Test Dataset.ipynb | 9 ++----- docs/examples/Power Flow Example.ipynb | 25 +++++++++---------- docs/examples/Serialization Example.ipynb | 6 ++--- docs/examples/State Estimation Example.ipynb | 4 +-- docs/examples/Transformer Examples.ipynb | 9 ++----- 6 files changed, 23 insertions(+), 39 deletions(-) diff --git a/docs/examples/Asymmetric Calculation Example.ipynb b/docs/examples/Asymmetric Calculation Example.ipynb index 54724adde..0b3175711 100644 --- a/docs/examples/Asymmetric Calculation Example.ipynb +++ b/docs/examples/Asymmetric Calculation Example.ipynb @@ -815,7 +815,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -829,12 +829,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" - }, - "vscode": { - "interpreter": { - "hash": "f2534ebf7a1a13ecc51c3a04ce741b49cf1feb97b5ca55170ed7b2036b4058c0" - } + "version": "3.13.0" } }, "nbformat": 4, diff --git a/docs/examples/Make Test Dataset.ipynb b/docs/examples/Make Test Dataset.ipynb index 54e15205a..1258600be 100644 --- a/docs/examples/Make Test Dataset.ipynb +++ b/docs/examples/Make Test Dataset.ipynb @@ -431,7 +431,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -445,12 +445,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" - }, - "vscode": { - "interpreter": { - "hash": "39f035c5e58f53e973c1999fdd4393d6db2dd3f04fe05f524988f90f4bbdb576" - } + "version": "3.13.0" } }, "nbformat": 4, diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index 857fe44a7..da1e83956 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -468,7 +468,7 @@ " output_component_types={\n", " ComponentType.node: None, # node output as row-based\n", " ComponentType.line: [\"id\", \"p_from\"], # line output columns id and p_from\n", - " ComponentType.sym_load: ComponentAttributeFilterOptions.ALL, # all sym_load attributes as columns\n", + " ComponentType.sym_load: ComponentAttributeFilterOptions.everything, # all sym_load attributes as columns\n", " },\n", ")\n", "\n", @@ -517,7 +517,7 @@ " error_tolerance=1e-8,\n", " max_iterations=20,\n", " calculation_method=CalculationMethod.newton_raphson,\n", - " output_component_types=ComponentAttributeFilterOptions.ALL, # all attributes for all component types as columns\n", + " output_component_types=ComponentAttributeFilterOptions.everything, # all attributes for all component types as columns\n", ")\n", "\n", "print(\"List of component types in result dataset and associated data types\")\n", @@ -1346,16 +1346,16 @@ "output_type": "stream", "text": [ "Node data with invalid results\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", - " [1.26558258e-311 6.95272884e-310 1.26558638e-311]\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", - " [6.95272884e-310 1.26558638e-311 6.95272884e-310]\n", - " [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", - " [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\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", "Node data with only valid results\n", "[[0.99940117 0.99268579 0.99452137]\n", " [0.99934769 0.98622639 0.98935286]\n", @@ -1372,7 +1372,6 @@ "# we run the batch calculation with continue_on_batch_error=True,\n", "# it will return the results with partially valid data\n", "\n", - "\n", "output_data = model.calculate_power_flow(update_data=time_series_mutation, continue_on_batch_error=True)\n", "\n", "# print node data for u_pu, note that the data is rubbish for scenario 3 and 7\n", diff --git a/docs/examples/Serialization Example.ipynb b/docs/examples/Serialization Example.ipynb index 2ccecfcd1..a964cd557 100644 --- a/docs/examples/Serialization Example.ipynb +++ b/docs/examples/Serialization Example.ipynb @@ -695,7 +695,7 @@ } ], "source": [ - "dataset = json_deserialize(data, data_filter=ComponentAttributeFilterOptions.ALL)\n", + "dataset = json_deserialize(data, data_filter=ComponentAttributeFilterOptions.everything)\n", "\n", "print(\"components:\", list(dataset.keys()))\n", "display(dataset[ComponentType.node])\n", @@ -790,8 +790,8 @@ " data_filter={\n", " ComponentType.node: None, # nodes in a row-based data format\n", " ComponentType.source: [\"id\", \"node\", \"status\", \"u_ref\", \"sk\"], # only specific attributes\n", - " ComponentType.sym_load: ComponentAttributeFilterOptions.ALL, # all attributes as columns\n", - " ComponentType.line: ComponentAttributeFilterOptions.RELEVANT, # only attributes that are not null/nan\n", + " ComponentType.sym_load: ComponentAttributeFilterOptions.everything, # all attributes as columns\n", + " ComponentType.line: ComponentAttributeFilterOptions.relevant, # only attributes that are not null/nan\n", " },\n", ")\n", "\n", diff --git a/docs/examples/State Estimation Example.ipynb b/docs/examples/State Estimation Example.ipynb index 8bec41a6e..5066ac316 100644 --- a/docs/examples/State Estimation Example.ipynb +++ b/docs/examples/State Estimation Example.ipynb @@ -1089,7 +1089,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -1103,7 +1103,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.13.0" } }, "nbformat": 4, diff --git a/docs/examples/Transformer Examples.ipynb b/docs/examples/Transformer Examples.ipynb index 147dd1e38..e949cc0da 100644 --- a/docs/examples/Transformer Examples.ipynb +++ b/docs/examples/Transformer Examples.ipynb @@ -1722,7 +1722,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "venv", "language": "python", "name": "python3" }, @@ -1736,12 +1736,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" - }, - "vscode": { - "interpreter": { - "hash": "f2534ebf7a1a13ecc51c3a04ce741b49cf1feb97b5ca55170ed7b2036b4058c0" - } + "version": "3.13.0" } }, "nbformat": 4, From e9e79956b5f695839ccad55238b5274b659a88e8 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 21 Oct 2024 13:12:18 +0200 Subject: [PATCH 15/18] more code coverage Signed-off-by: Martijn Govers --- tests/unit/validation/test_errors.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit/validation/test_errors.py b/tests/unit/validation/test_errors.py index f4c980399..bb76d64bc 100644 --- a/tests/unit/validation/test_errors.py +++ b/tests/unit/validation/test_errors.py @@ -88,6 +88,22 @@ def test_invalid_id_error(): assert str(error) == "Field 'november' does not contain a valid oscar/papa id for 3 nodes." +def test_invalid_id_error_with_filters(): + error = InvalidIdError( + ComponentType.node, + field="november", + ids=[1, 2, 3], + ref_components=["oscar", "papa"], + filters={"foo": "bar", "baz": ComponentType.node}, + ) + assert error.component == "node" + assert error.field == "november" + assert error.ids == [1, 2, 3] + assert error.ref_components == ["oscar", "papa"] + assert error.filters_str == "(foo=bar, baz=node)" + assert str(error) == "Field 'november' does not contain a valid oscar/papa id for 3 nodes. (foo=bar, baz=node)" + + def test_comparison_error(): error = ComparisonError(component=ComponentType.node, field="romeo", ids=[1, 2, 3], ref_value=0) assert error.component == "node" From 8220bc7166376f6ef82d56900444343b0e2264d2 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 21 Oct 2024 15:11:17 +0200 Subject: [PATCH 16/18] process comments Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 4 +- docs/examples/Serialization Example.ipynb | 120 +--------------------- 2 files changed, 5 insertions(+), 119 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index da1e83956..dcb198358 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -435,7 +435,7 @@ "\n", "* `None` requests row-based data\n", "* a list of attribute names requests columns for those attributes (as before)\n", - "* `ComponentAttributeFilterOptions.ALL` requests columns for all supported attributes of a component." + "* `ComponentAttributeFilterOptions.everything` requests columns for all supported attributes of a component." ] }, { @@ -487,7 +487,7 @@ "id": "14a34c07", "metadata": {}, "source": [ - "Finally, it is possible to request columnar data for all attributes using the `ComponentAttributeFilterOptions.ALL` as a shorthand." + "Finally, it is possible to request columnar data for all attributes using the `ComponentAttributeFilterOptions.everything` as a shorthand." ] }, { diff --git a/docs/examples/Serialization Example.ipynb b/docs/examples/Serialization Example.ipynb index a964cd557..b718946da 100644 --- a/docs/examples/Serialization Example.ipynb +++ b/docs/examples/Serialization Example.ipynb @@ -637,69 +637,13 @@ }, "metadata": {}, "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
idu_rated
0110500.0
1210500.0
2310500.0
\n", - "
" - ], - "text/plain": [ - " id u_rated\n", - "0 1 10500.0\n", - "1 2 10500.0\n", - "2 3 10500.0" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ "dataset = json_deserialize(data, data_filter=ComponentAttributeFilterOptions.everything)\n", "\n", "print(\"components:\", list(dataset.keys()))\n", - "display(dataset[ComponentType.node])\n", - "display(DataFrame(dataset[ComponentType.node]))" + "display(dataset[ComponentType.node])" ] }, { @@ -724,64 +668,8 @@ "node attributes: ['id', 'u_rated']\n", "source attributes: ['id', 'node', 'status', 'u_ref', 'sk']\n", "sym_load attributes: ['id', 'node', 'status', 'type', 'p_specified', 'q_specified']\n", - "line attributes: ['id', 'from_node', 'to_node', 'from_status', 'to_status', 'r1', 'x1', 'c1', 'tan1', 'i_n']\n", - "-------node data-------\n" + "line attributes: ['id', 'from_node', 'to_node', 'from_status', 'to_status', 'r1', 'x1', 'c1', 'tan1', 'i_n']\n" ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
idu_rated
0110500.0
1210500.0
2310500.0
\n", - "
" - ], - "text/plain": [ - " id u_rated\n", - "0 1 10500.0\n", - "1 2 10500.0\n", - "2 3 10500.0" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "source": [ @@ -799,9 +687,7 @@ "print(\"node attributes:\", list(dataset[ComponentType.node].dtype.names))\n", "print(\"source attributes:\", list(dataset[ComponentType.source].keys()))\n", "print(\"sym_load attributes:\", list(dataset[ComponentType.sym_load].keys()))\n", - "print(\"line attributes:\", list(dataset[ComponentType.line].keys()))\n", - "print(\"-------node data-------\")\n", - "display(DataFrame(dataset[ComponentType.node]))" + "print(\"line attributes:\", list(dataset[ComponentType.line].keys()))" ] }, { From 313834a6f1d04e8eaf5d7e1ffbae85260a3b463c Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 21 Oct 2024 15:19:30 +0200 Subject: [PATCH 17/18] minor elaboration on columnar data Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index dcb198358..ab6830ebf 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -129,6 +129,8 @@ "source": [ "It is also possible to specify a component input data in a columnar data format.\n", "\n", + "A columnar data format allows better integration with existing 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." ] }, @@ -145,6 +147,7 @@ " \"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", + " # We're not creating columns for u_ref_angle, sk, ... Instead, the default values are used. This saves us memory.\n", "}\n", "\n", "input_data = {\n", @@ -1346,16 +1349,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.01347174e-154 7.39986091e-038 6.55490955e-260]\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", + " [6.95195146e-310 6.95195146e-310 6.95195146e-310]\n", + " [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", + " [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n", "Node data with only valid results\n", "[[0.99940117 0.99268579 0.99452137]\n", " [0.99934769 0.98622639 0.98935286]\n", From 19be23d2e1fb0845782525f92415246617bb2a4a Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 21 Oct 2024 15:20:05 +0200 Subject: [PATCH 18/18] minor elaboration on columnar data Signed-off-by: Martijn Govers --- docs/examples/Power Flow Example.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/Power Flow Example.ipynb b/docs/examples/Power Flow Example.ipynb index ab6830ebf..251332de1 100644 --- a/docs/examples/Power Flow Example.ipynb +++ b/docs/examples/Power Flow Example.ipynb @@ -129,7 +129,7 @@ "source": [ "It is also possible to specify a component input data in a columnar data format.\n", "\n", - "A columnar data format allows better integration with existing databases. In addition, it may bring memory and, in some cases, even computational performance improvements, because unused attribute columns can be omitted.\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." ] @@ -1352,11 +1352,11 @@ "[[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.01347174e-154 7.39986091e-038 6.55490955e-260]\n", + " [0.00000000e+000 3.04369633e+101 3.41345331e+241]\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", - " [6.95195146e-310 6.95195146e-310 6.95195146e-310]\n", + " [1.66994188e-321 3.12878333e-312 9.75772002e+199]\n", " [9.98796126e-001 9.37530046e-001 9.50447962e-001]\n", " [9.98688504e-001 9.29997471e-001 9.44441670e-001]]\n", "Node data with only valid results\n",