From 7c038911f88a7df8cc8f4de736d13e0ddb3825ce Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Wed, 1 Oct 2025 14:32:21 +0200 Subject: [PATCH 01/10] feat: add extra components from pgm Signed-off-by: jaapschoutenalliander --- .../_core/model/arrays/__init__.py | 8 ++ .../_core/model/arrays/pgm_arrays.py | 26 +++++- .../_core/model/dtypes/branches.py | 92 +++++++++++++++++++ .../_core/model/dtypes/sensors.py | 23 +++++ .../_core/model/grids/base.py | 14 ++- src/power_grid_model_ds/arrays.py | 8 ++ tests/unit/model/grids/test_grid_base.py | 4 + 7 files changed, 173 insertions(+), 2 deletions(-) diff --git a/src/power_grid_model_ds/_core/model/arrays/__init__.py b/src/power_grid_model_ds/_core/model/arrays/__init__.py index 780deb25..891ef7ef 100644 --- a/src/power_grid_model_ds/_core/model/arrays/__init__.py +++ b/src/power_grid_model_ds/_core/model/arrays/__init__.py @@ -7,14 +7,18 @@ """ from power_grid_model_ds._core.model.arrays.pgm_arrays import ( + AsymCurrentSensorArray, + AsymLineArray, AsymVoltageSensorArray, Branch3Array, BranchArray, + GenericBranchArray, IdArray, LineArray, LinkArray, NodeArray, SourceArray, + SymCurrentSensorArray, SymGenArray, SymLoadArray, SymPowerSensorArray, @@ -26,8 +30,10 @@ __all__ = [ "AsymVoltageSensorArray", + "AsymCurrentSensorArray", "Branch3Array", "BranchArray", + "GenericBranchArray", "IdArray", "LineArray", "LinkArray", @@ -35,8 +41,10 @@ "SourceArray", "SymLoadArray", "SymGenArray", + "SymCurrentSensorArray", "SymPowerSensorArray", "SymVoltageSensorArray", + "AsymLineArray", "ThreeWindingTransformerArray", "TransformerArray", "TransformerTapRegulatorArray", diff --git a/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py b/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py index 9280d727..e37746c8 100644 --- a/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py +++ b/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py @@ -13,8 +13,10 @@ from power_grid_model_ds._core.model.arrays.base.array import FancyArray from power_grid_model_ds._core.model.dtypes.appliances import Source, SymGen, SymLoad from power_grid_model_ds._core.model.dtypes.branches import ( + AsymLine, Branch, Branch3, + GenericBranch, Line, Link, ThreeWindingTransformer, @@ -23,7 +25,13 @@ from power_grid_model_ds._core.model.dtypes.id import Id from power_grid_model_ds._core.model.dtypes.nodes import Node from power_grid_model_ds._core.model.dtypes.regulators import TransformerTapRegulator -from power_grid_model_ds._core.model.dtypes.sensors import AsymVoltageSensor, SymPowerSensor, SymVoltageSensor +from power_grid_model_ds._core.model.dtypes.sensors import ( + AsymCurrentSensor, + AsymVoltageSensor, + SymCurrentSensor, + SymPowerSensor, + SymVoltageSensor, +) # pylint: disable=missing-class-docstring @@ -99,6 +107,14 @@ class TransformerArray(Transformer, BranchArray): pass +class GenericBranchArray(GenericBranch, BranchArray): + pass + + +class AsymLineArray(AsymLine, BranchArray): + pass + + class Branch3Array(IdArray, Branch3): def as_branches(self) -> BranchArray: """Convert Branch3Array to BranchArray.""" @@ -140,3 +156,11 @@ class SymVoltageSensorArray(IdArray, SymVoltageSensor): class AsymVoltageSensorArray(IdArray, AsymVoltageSensor): pass + + +class SymCurrentSensorArray(IdArray, SymCurrentSensor): + pass + + +class AsymCurrentSensorArray(IdArray, AsymCurrentSensor): + pass diff --git a/src/power_grid_model_ds/_core/model/dtypes/branches.py b/src/power_grid_model_ds/_core/model/dtypes/branches.py index e4a2aea1..cdadc0fa 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/branches.py +++ b/src/power_grid_model_ds/_core/model/dtypes/branches.py @@ -43,6 +43,29 @@ class Line(Branch): i_n: NDArray[np.float64] # rated current +class GenericBranch(Branch): + """GenericBranch data type (generic_branch in power-grid-model) + + Off-nominal ratio k and phase shift theta are modelled explicitly. Rated power sn optional. + The impedance (r1, x1) and admittance (g1, b1) are given wrt the to-side. + """ + + r1: NDArray[np.float64] # positive-sequence resistance + x1: NDArray[np.float64] # positive-sequence reactance + g1: NDArray[np.float64] # positive-sequence conductance + b1: NDArray[np.float64] # positive-sequence susceptance + k: NDArray[np.float64] # off-nominal ratio + theta: NDArray[np.float64] # angle shift (radian) + sn: NDArray[np.float64] # rated power + + _defaults = { + **Branch._defaults, + "k": 1.0, + "theta": 0.0, + "sn": 0.0, + } + + class Transformer(Branch): """Transformer data type""" @@ -115,3 +138,72 @@ class ThreeWindingTransformer(Branch3): pk_12_max: NDArray[np.float64] pk_13_max: NDArray[np.float64] pk_23_max: NDArray[np.float64] + + +class AsymLine(Branch): + """Asymmetric Line data type (asym_line in power-grid-model) + + Supports 3 or 4 phase (with neutral) resistance / reactance matrices and optional capacitance matrix + or sequence capacitances c0/c1. If c_* matrix is omitted, c0 & c1 may be specified instead. + Only include fields; validation logic handled elsewhere (not implemented here yet). + """ + + # Resistance matrix entries (series) + r_aa: NDArray[np.float64] + r_ba: NDArray[np.float64] + r_bb: NDArray[np.float64] + r_ca: NDArray[np.float64] + r_cb: NDArray[np.float64] + r_cc: NDArray[np.float64] + r_na: NDArray[np.float64] # optional neutral + r_nb: NDArray[np.float64] + r_nc: NDArray[np.float64] + r_nn: NDArray[np.float64] + + # Reactance matrix entries (series) + x_aa: NDArray[np.float64] + x_ba: NDArray[np.float64] + x_bb: NDArray[np.float64] + x_ca: NDArray[np.float64] + x_cb: NDArray[np.float64] + x_cc: NDArray[np.float64] + x_na: NDArray[np.float64] + x_nb: NDArray[np.float64] + x_nc: NDArray[np.float64] + x_nn: NDArray[np.float64] + + # Capacitance matrix entries (shunt) optional + c_aa: NDArray[np.float64] + c_ba: NDArray[np.float64] + c_bb: NDArray[np.float64] + c_ca: NDArray[np.float64] + c_cb: NDArray[np.float64] + c_cc: NDArray[np.float64] + + # Alternative sequence capacitances + c0: NDArray[np.float64] + c1: NDArray[np.float64] + + i_n: NDArray[np.float64] # rated current + + _defaults = { + **Branch._defaults, + # neutral / optional values default to empty sentinel so we can detect omission + "r_na": empty, + "r_nb": empty, + "r_nc": empty, + "r_nn": empty, + "x_na": empty, + "x_nb": empty, + "x_nc": empty, + "x_nn": empty, + "c_aa": empty, + "c_ba": empty, + "c_bb": empty, + "c_ca": empty, + "c_cb": empty, + "c_cc": empty, + "c0": empty, + "c1": empty, + "i_n": empty, + } diff --git a/src/power_grid_model_ds/_core/model/dtypes/sensors.py b/src/power_grid_model_ds/_core/model/dtypes/sensors.py index 513e0169..b441e089 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/sensors.py +++ b/src/power_grid_model_ds/_core/model/dtypes/sensors.py @@ -61,3 +61,26 @@ class AsymVoltageSensor(GenericVoltageSensor): u_sigma: NDArray3[np.float64] # std of 3 voltages u_measured: NDArray3[np.float64] # measured 3 voltages u_angle_measured: NDArray3[np.float64] # measured 3 phases + + +class GenericCurrentSensor(Sensor): + """Base class for current sensor data type""" + + measured_terminal_type: NDArray[np.int32] + angle_measurement_type: NDArray[np.int32] + i_sigma: NDArray[np.float64] + i_angle_sigma: NDArray[np.float64] + + +class SymCurrentSensor(GenericCurrentSensor): + """SymCurrentSensor data type""" + + i_measured: NDArray[np.float64] + i_angle_measured: NDArray[np.float64] + + +class AsymCurrentSensor(GenericCurrentSensor): + """AsymCurrentSensor data type""" + + i_measured: NDArray3[np.float64] + i_angle_measured: NDArray3[np.float64] diff --git a/src/power_grid_model_ds/_core/model/grids/base.py b/src/power_grid_model_ds/_core/model/grids/base.py index 2dc64ed7..e8f868c9 100644 --- a/src/power_grid_model_ds/_core/model/grids/base.py +++ b/src/power_grid_model_ds/_core/model/grids/base.py @@ -17,13 +17,17 @@ from power_grid_model_ds._core import fancypy as fp from power_grid_model_ds._core.model.arrays import ( + AsymCurrentSensorArray, + AsymLineArray, AsymVoltageSensorArray, Branch3Array, BranchArray, + GenericBranchArray, LineArray, LinkArray, NodeArray, SourceArray, + SymCurrentSensorArray, SymGenArray, SymLoadArray, SymPowerSensorArray, @@ -72,6 +76,8 @@ class Grid(FancyArrayContainer): three_winding_transformer: ThreeWindingTransformerArray line: LineArray link: LinkArray + generic_branch: GenericBranchArray + asym_line: AsymLineArray source: SourceArray sym_load: SymLoadArray @@ -84,6 +90,8 @@ class Grid(FancyArrayContainer): sym_power_sensor: SymPowerSensorArray sym_voltage_sensor: SymVoltageSensorArray asym_voltage_sensor: AsymVoltageSensorArray + sym_current_sensor: SymCurrentSensorArray + asym_current_sensor: AsymCurrentSensorArray def __str__(self) -> str: """String representation of the grid. @@ -114,8 +122,12 @@ def __str__(self) -> str: suffix_str = f"{suffix_str},link" elif branch.id in self.line.id: pass # no suffix needed + elif branch.id in self.generic_branch.id: + suffix_str = f"{suffix_str},generic_branch" + elif branch.id in self.asym_line.id: + suffix_str = f"{suffix_str},asym_line" else: - raise ValueError(f"Branch {branch.id} is not a transformer, link or line") + raise ValueError(f"Branch {branch.id} is not a transformer, link, line, generic_branch or asym_line") grid_str += f"{from_node_str} {to_node_str} {suffix_str}\n" return grid_str diff --git a/src/power_grid_model_ds/arrays.py b/src/power_grid_model_ds/arrays.py index 5fdfc450..80f08c60 100644 --- a/src/power_grid_model_ds/arrays.py +++ b/src/power_grid_model_ds/arrays.py @@ -3,14 +3,18 @@ # SPDX-License-Identifier: MPL-2.0 from power_grid_model_ds._core.model.arrays import ( + AsymCurrentSensorArray, + AsymLineArray, AsymVoltageSensorArray, Branch3Array, BranchArray, + GenericBranchArray, IdArray, LineArray, LinkArray, NodeArray, SourceArray, + SymCurrentSensorArray, SymGenArray, SymLoadArray, SymPowerSensorArray, @@ -26,6 +30,8 @@ "BranchArray", "LinkArray", "LineArray", + "GenericBranchArray", + "AsymLineArray", "TransformerArray", "Branch3Array", "ThreeWindingTransformerArray", @@ -34,6 +40,8 @@ "SymLoadArray", "TransformerTapRegulatorArray", "AsymVoltageSensorArray", + "AsymCurrentSensorArray", "SymPowerSensorArray", "SymVoltageSensorArray", + "SymCurrentSensorArray", ] diff --git a/tests/unit/model/grids/test_grid_base.py b/tests/unit/model/grids/test_grid_base.py index 3f8dc3fb..42663408 100644 --- a/tests/unit/model/grids/test_grid_base.py +++ b/tests/unit/model/grids/test_grid_base.py @@ -37,10 +37,14 @@ def test_initialize_empty_grid(grid: Grid): "_id_counter", "transformer_tap_regulator", "asym_voltage_sensor", + "sym_current_sensor", + "asym_current_sensor", "three_winding_transformer", "transformer", "node", "line", + "generic_branch", + "asym_line", "sym_gen", "graphs", "sym_voltage_sensor", From 211a9cb2b1fd3530436671ee24f7773b3b390f70 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Wed, 1 Oct 2025 14:37:40 +0200 Subject: [PATCH 02/10] feat: add extra components from pgm Signed-off-by: jaapschoutenalliander --- src/power_grid_model_ds/_core/model/dtypes/branches.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/power_grid_model_ds/_core/model/dtypes/branches.py b/src/power_grid_model_ds/_core/model/dtypes/branches.py index cdadc0fa..9106cb45 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/branches.py +++ b/src/power_grid_model_ds/_core/model/dtypes/branches.py @@ -59,7 +59,6 @@ class GenericBranch(Branch): sn: NDArray[np.float64] # rated power _defaults = { - **Branch._defaults, "k": 1.0, "theta": 0.0, "sn": 0.0, @@ -187,8 +186,6 @@ class AsymLine(Branch): i_n: NDArray[np.float64] # rated current _defaults = { - **Branch._defaults, - # neutral / optional values default to empty sentinel so we can detect omission "r_na": empty, "r_nb": empty, "r_nc": empty, From b30f2ce6c1dfe931297fed4f5ece98e763465b69 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Wed, 1 Oct 2025 19:46:15 +0200 Subject: [PATCH 03/10] chore: implement feedback Signed-off-by: jaapschoutenalliander --- .../_core/model/dtypes/branches.py | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/src/power_grid_model_ds/_core/model/dtypes/branches.py b/src/power_grid_model_ds/_core/model/dtypes/branches.py index 9106cb45..8b259398 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/branches.py +++ b/src/power_grid_model_ds/_core/model/dtypes/branches.py @@ -154,10 +154,6 @@ class AsymLine(Branch): r_ca: NDArray[np.float64] r_cb: NDArray[np.float64] r_cc: NDArray[np.float64] - r_na: NDArray[np.float64] # optional neutral - r_nb: NDArray[np.float64] - r_nc: NDArray[np.float64] - r_nn: NDArray[np.float64] # Reactance matrix entries (series) x_aa: NDArray[np.float64] @@ -166,41 +162,9 @@ class AsymLine(Branch): x_ca: NDArray[np.float64] x_cb: NDArray[np.float64] x_cc: NDArray[np.float64] - x_na: NDArray[np.float64] - x_nb: NDArray[np.float64] - x_nc: NDArray[np.float64] - x_nn: NDArray[np.float64] - - # Capacitance matrix entries (shunt) optional - c_aa: NDArray[np.float64] - c_ba: NDArray[np.float64] - c_bb: NDArray[np.float64] - c_ca: NDArray[np.float64] - c_cb: NDArray[np.float64] - c_cc: NDArray[np.float64] # Alternative sequence capacitances c0: NDArray[np.float64] c1: NDArray[np.float64] i_n: NDArray[np.float64] # rated current - - _defaults = { - "r_na": empty, - "r_nb": empty, - "r_nc": empty, - "r_nn": empty, - "x_na": empty, - "x_nb": empty, - "x_nc": empty, - "x_nn": empty, - "c_aa": empty, - "c_ba": empty, - "c_bb": empty, - "c_ca": empty, - "c_cb": empty, - "c_cc": empty, - "c0": empty, - "c1": empty, - "i_n": empty, - } From 825da3f1835b55cc4160cc4b336beccb42dbead3 Mon Sep 17 00:00:00 2001 From: jaapschoutenalliander Date: Wed, 1 Oct 2025 21:00:25 +0200 Subject: [PATCH 04/10] chore: small changes where branch types are mentioned Signed-off-by: jaapschoutenalliander --- src/power_grid_model_ds/_core/model/grids/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/power_grid_model_ds/_core/model/grids/base.py b/src/power_grid_model_ds/_core/model/grids/base.py index e8f868c9..daa14ae8 100644 --- a/src/power_grid_model_ds/_core/model/grids/base.py +++ b/src/power_grid_model_ds/_core/model/grids/base.py @@ -153,7 +153,7 @@ def branch_arrays(self) -> list[BranchArray]: return branch_arrays def get_typed_branches(self, branch_ids: list[int] | npt.NDArray[np.int32]) -> BranchArray: - """Find a matching LineArray, LinkArray or TransformerArray for the given branch_ids + """Find a matching Branch-subtype array for the given branch_ids Raises: ValueError: @@ -174,7 +174,7 @@ def reverse_branches(self, branches: BranchArray): """Reverse the direction of the branches.""" if not branches.size: return - if not isinstance(branches, (LineArray, LinkArray, TransformerArray)): + if not isinstance(branches, (LineArray, LinkArray, TransformerArray, GenericBranchArray, AsymLineArray)): try: branches = self.get_typed_branches(branches.id) except ValueError: From deca40b189e8a94632ffdfe9be215cf6ddb7e780 Mon Sep 17 00:00:00 2001 From: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> Date: Tue, 18 Nov 2025 21:34:07 +0100 Subject: [PATCH 05/10] feat: add AsymPowerSensorArray and remove optional columns from GenericBranch (#113) * Add AsymPowerSensorArray Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> * rename and update test Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> * remove defaulted fields for consistency Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> * revert change Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> * cleanup Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --------- Signed-off-by: Thijs Baaijen <13253091+Thijss@users.noreply.github.com> --- .../_core/model/arrays/__init__.py | 2 ++ .../_core/model/arrays/pgm_arrays.py | 9 +++++-- .../_core/model/dtypes/branches.py | 9 ------- .../_core/model/dtypes/sensors.py | 9 +++++++ .../_core/model/grids/base.py | 4 ++- tests/unit/model/arrays/test_build.py | 24 ++++------------- tests/unit/model/grids/test_grid_base.py | 27 ++++++++++--------- 7 files changed, 40 insertions(+), 44 deletions(-) diff --git a/src/power_grid_model_ds/_core/model/arrays/__init__.py b/src/power_grid_model_ds/_core/model/arrays/__init__.py index 891ef7ef..a69bba0e 100644 --- a/src/power_grid_model_ds/_core/model/arrays/__init__.py +++ b/src/power_grid_model_ds/_core/model/arrays/__init__.py @@ -9,6 +9,7 @@ from power_grid_model_ds._core.model.arrays.pgm_arrays import ( AsymCurrentSensorArray, AsymLineArray, + AsymPowerSensorArray, AsymVoltageSensorArray, Branch3Array, BranchArray, @@ -29,6 +30,7 @@ ) __all__ = [ + "AsymPowerSensorArray", "AsymVoltageSensorArray", "AsymCurrentSensorArray", "Branch3Array", diff --git a/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py b/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py index e37746c8..0e4b9bcf 100644 --- a/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py +++ b/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py @@ -27,6 +27,7 @@ from power_grid_model_ds._core.model.dtypes.regulators import TransformerTapRegulator from power_grid_model_ds._core.model.dtypes.sensors import ( AsymCurrentSensor, + AsymPowerSensor, AsymVoltageSensor, SymCurrentSensor, SymPowerSensor, @@ -154,11 +155,15 @@ class SymVoltageSensorArray(IdArray, SymVoltageSensor): pass -class AsymVoltageSensorArray(IdArray, AsymVoltageSensor): +class SymCurrentSensorArray(IdArray, SymCurrentSensor): pass -class SymCurrentSensorArray(IdArray, SymCurrentSensor): +class AsymPowerSensorArray(IdArray, AsymPowerSensor): + pass + + +class AsymVoltageSensorArray(IdArray, AsymVoltageSensor): pass diff --git a/src/power_grid_model_ds/_core/model/dtypes/branches.py b/src/power_grid_model_ds/_core/model/dtypes/branches.py index 8b259398..87e868ea 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/branches.py +++ b/src/power_grid_model_ds/_core/model/dtypes/branches.py @@ -54,15 +54,6 @@ class GenericBranch(Branch): x1: NDArray[np.float64] # positive-sequence reactance g1: NDArray[np.float64] # positive-sequence conductance b1: NDArray[np.float64] # positive-sequence susceptance - k: NDArray[np.float64] # off-nominal ratio - theta: NDArray[np.float64] # angle shift (radian) - sn: NDArray[np.float64] # rated power - - _defaults = { - "k": 1.0, - "theta": 0.0, - "sn": 0.0, - } class Transformer(Branch): diff --git a/src/power_grid_model_ds/_core/model/dtypes/sensors.py b/src/power_grid_model_ds/_core/model/dtypes/sensors.py index b441e089..20a728ba 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/sensors.py +++ b/src/power_grid_model_ds/_core/model/dtypes/sensors.py @@ -43,6 +43,15 @@ class SymPowerSensor(GenericPowerSensor): q_sigma: NDArray[np.float64] # std of reactive power +class AsymPowerSensor(GenericPowerSensor): + """AsymPowerSensor data type""" + + p_measured: NDArray3[np.float64] # measured active power + q_measured: NDArray3[np.float64] # measured reactive power + p_sigma: NDArray3[np.float64] # std of active power + q_sigma: NDArray3[np.float64] # std of reactive power + + class GenericVoltageSensor(Sensor): """Base class for voltage sensor data type""" diff --git a/src/power_grid_model_ds/_core/model/grids/base.py b/src/power_grid_model_ds/_core/model/grids/base.py index 248aee1a..17a97809 100644 --- a/src/power_grid_model_ds/_core/model/grids/base.py +++ b/src/power_grid_model_ds/_core/model/grids/base.py @@ -19,6 +19,7 @@ from power_grid_model_ds._core.model.arrays import ( AsymCurrentSensorArray, AsymLineArray, + AsymPowerSensorArray, AsymVoltageSensorArray, Branch3Array, BranchArray, @@ -89,8 +90,9 @@ class Grid(FancyArrayContainer): # sensors sym_power_sensor: SymPowerSensorArray sym_voltage_sensor: SymVoltageSensorArray - asym_voltage_sensor: AsymVoltageSensorArray sym_current_sensor: SymCurrentSensorArray + asym_power_sensor: AsymPowerSensorArray + asym_voltage_sensor: AsymVoltageSensorArray asym_current_sensor: AsymCurrentSensorArray def __str__(self) -> str: diff --git a/tests/unit/model/arrays/test_build.py b/tests/unit/model/arrays/test_build.py index 07f90458..2bbfe82d 100644 --- a/tests/unit/model/arrays/test_build.py +++ b/tests/unit/model/arrays/test_build.py @@ -8,7 +8,7 @@ from numpy.typing import NDArray from power_grid_model_ds._core import fancypy as fp -from power_grid_model_ds._core.model.arrays import AsymVoltageSensorArray, SymPowerSensorArray +from power_grid_model_ds._core.model.arrays import AsymVoltageSensorArray from power_grid_model_ds._core.model.arrays.base.array import FancyArray from power_grid_model_ds._core.model.arrays.base.errors import ArrayDefinitionError from power_grid_model_ds._core.model.constants import EMPTY_ID @@ -232,27 +232,13 @@ def test_initialization_from_args_with_extra_columns(): assert "undefined" not in array.dtype.names -def test_sensor_array(): - test_len = 2 - # test proper intiliazation of a SensorArray - pow_sens = SymPowerSensorArray.empty(test_len) - sym_pow_fields = [ - "measured_object", - "measured_terminal_type", - "power_sigma", - "p_measured", - "p_sigma", - "q_measured", - "q_sigma", - ] - for field in sym_pow_fields: - assert field in pow_sens.dtype.fields - +def test_asymmetric_sensor_array(): + array_length = 2 # test if asymmetric array has NDArray3 fields, i.e. with 3 floats per element (one per phase) - asym_volt_sens = AsymVoltageSensorArray.empty(test_len) + asym_volt_sens = AsymVoltageSensorArray.empty(array_length) nd3_fields = ["u_sigma", "u_measured", "u_angle_measured"] for field in nd3_fields: - assert asym_volt_sens[field].shape == (test_len, 3) + assert asym_volt_sens[field].shape == (array_length, 3) def test_inherit_defaults_from_multiple_parents(): diff --git a/tests/unit/model/grids/test_grid_base.py b/tests/unit/model/grids/test_grid_base.py index cfbffa6e..ef20f159 100644 --- a/tests/unit/model/grids/test_grid_base.py +++ b/tests/unit/model/grids/test_grid_base.py @@ -31,24 +31,25 @@ def test_initialize_empty_grid(grid: Grid): assert isinstance(grid, Grid) fields = dataclasses.asdict(grid).keys() assert { - "link", - "sym_load", - "sym_power_sensor", - "source", "_id_counter", - "transformer_tap_regulator", - "asym_voltage_sensor", - "sym_current_sensor", "asym_current_sensor", - "three_winding_transformer", - "transformer", - "node", - "line", - "generic_branch", "asym_line", - "sym_gen", + "asym_power_sensor", + "asym_voltage_sensor", + "generic_branch", "graphs", + "line", + "link", + "node", + "source", + "sym_current_sensor", + "sym_gen", + "sym_load", + "sym_power_sensor", "sym_voltage_sensor", + "three_winding_transformer", + "transformer", + "transformer_tap_regulator", } == set(fields) From 5b82d3f0a54c7cfd460dc3a19a0107c33e5f8ab8 Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Wed, 3 Dec 2025 15:49:49 +0100 Subject: [PATCH 06/10] support new branches in export/import as string Signed-off-by: Vincent Koppen --- .../_core/model/grids/_text_sources.py | 10 ++++++++-- src/power_grid_model_ds/_core/model/grids/base.py | 9 +++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/power_grid_model_ds/_core/model/grids/_text_sources.py b/src/power_grid_model_ds/_core/model/grids/_text_sources.py index ab9c1a9c..548242e3 100644 --- a/src/power_grid_model_ds/_core/model/grids/_text_sources.py +++ b/src/power_grid_model_ds/_core/model/grids/_text_sources.py @@ -7,6 +7,8 @@ import logging from typing import TYPE_CHECKING +from power_grid_model import ComponentType + from power_grid_model_ds._core.model.enums.nodes import NodeType if TYPE_CHECKING: @@ -94,10 +96,14 @@ def add_branch(self, branch: tuple[str, str], comments: list[str]): from_node = int(from_node_str.replace("S", "")) to_node = int(to_node_str.replace("S", "")) - if "transformer" in comments: + if ComponentType.transformer.value in comments: new_branch = self.grid.transformer.empty(1) - elif "link" in comments: + elif ComponentType.link.value in comments: new_branch = self.grid.link.empty(1) + elif ComponentType.generic_branch.value in comments: + new_branch = self.grid.generic_branch.empty(1) + elif ComponentType.asym_line.value in comments: + new_branch = self.grid.asym_line.empty(1) else: # assume it is a line new_branch = self.grid.line.empty(1) diff --git a/src/power_grid_model_ds/_core/model/grids/base.py b/src/power_grid_model_ds/_core/model/grids/base.py index 17a97809..f35e9342 100644 --- a/src/power_grid_model_ds/_core/model/grids/base.py +++ b/src/power_grid_model_ds/_core/model/grids/base.py @@ -14,6 +14,7 @@ import numpy as np import numpy.typing as npt +from power_grid_model import ComponentType from power_grid_model_ds._core import fancypy as fp from power_grid_model_ds._core.model.arrays import ( @@ -119,15 +120,15 @@ def __str__(self) -> str: suffix_str = f"{suffix_str},open" if branch.id in self.transformer.id: - suffix_str = f"{suffix_str},transformer" + suffix_str = f"{suffix_str},{ComponentType.transformer.value}" elif branch.id in self.link.id: - suffix_str = f"{suffix_str},link" + suffix_str = f"{suffix_str},{ComponentType.link.value}" elif branch.id in self.line.id: pass # no suffix needed elif branch.id in self.generic_branch.id: - suffix_str = f"{suffix_str},generic_branch" + suffix_str = f"{suffix_str},{ComponentType.generic_branch.value}" elif branch.id in self.asym_line.id: - suffix_str = f"{suffix_str},asym_line" + suffix_str = f"{suffix_str},{ComponentType.asym_line.value}" else: raise ValueError(f"Branch {branch.id} is not a transformer, link, line, generic_branch or asym_line") From 23eeede5070c4d36cd5be206e3b5668cd28a37f2 Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Wed, 3 Dec 2025 16:12:21 +0100 Subject: [PATCH 07/10] add support from txt and visualizer Signed-off-by: Vincent Koppen --- .../_core/visualizer/app.py | 13 +++-- .../_core/visualizer/layout/colors.py | 5 ++ .../visualizer/layout/cytoscape_styling.py | 34 ++++++++++++- .../_core/visualizer/layout/header_legenda.py | 6 +++ .../_core/visualizer/parsers.py | 13 +++-- tests/integration/visualizer_tests.py | 50 ++++++++++++------- tests/unit/model/grids/test_grid_base.py | 15 ++++++ 7 files changed, 106 insertions(+), 30 deletions(-) diff --git a/src/power_grid_model_ds/_core/visualizer/app.py b/src/power_grid_model_ds/_core/visualizer/app.py index 169aacbc..c6775113 100644 --- a/src/power_grid_model_ds/_core/visualizer/app.py +++ b/src/power_grid_model_ds/_core/visualizer/app.py @@ -5,6 +5,7 @@ import dash_bootstrap_components as dbc from dash import Dash, dcc, html from dash_bootstrap_components.icons import FONT_AWESOME +from power_grid_model import ComponentType from power_grid_model_ds._core.model.grids.base import Grid from power_grid_model_ds._core.visualizer.callbacks import ( # noqa: F401 # pylint: disable=unused-import @@ -57,11 +58,13 @@ def _get_columns_store(grid: Grid) -> dcc.Store: return dcc.Store( id="columns-store", data={ - "node": grid.node.columns, - "line": grid.line.columns, - "link": grid.link.columns, - "transformer": grid.transformer.columns, - "three_winding_transformer": grid.three_winding_transformer.columns, + ComponentType.node: grid.node.columns, + ComponentType.line: grid.line.columns, + ComponentType.link: grid.link.columns, + ComponentType.transformer: grid.transformer.columns, + ComponentType.three_winding_transformer: grid.three_winding_transformer.columns, + ComponentType.asym_line: grid.asym_line.columns, + ComponentType.generic_branch: grid.generic_branch.columns, "branch": grid.branches.columns, }, ) diff --git a/src/power_grid_model_ds/_core/visualizer/layout/colors.py b/src/power_grid_model_ds/_core/visualizer/layout/colors.py index 47be645a..32df9853 100644 --- a/src/power_grid_model_ds/_core/visualizer/layout/colors.py +++ b/src/power_grid_model_ds/_core/visualizer/layout/colors.py @@ -2,15 +2,20 @@ # # SPDX-License-Identifier: MPL-2.0 + YELLOW = "#facc37" CYTO_COLORS = { "line": YELLOW, "link": "#008000", "transformer": "#4290f5", "node": YELLOW, + "generic_branch": "#dddddd", + "asym_line": "#2de2ca", "selected": "#e28743", "selected_transformer": "#0349a3", "selected_link": "#004000", + "selected_generic_branch": "#9e9e9e", + "selected_asym_line": "#1D9181", "substation_node": "purple", "open_branch": "#c9c9c9", "highlighted": "#a10000", diff --git a/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py b/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py index ef0db275..658c667d 100644 --- a/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py +++ b/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py @@ -4,6 +4,8 @@ """Contains selectors for the Cytoscape stylesheet.""" +from power_grid_model import ComponentType + from power_grid_model_ds._core.visualizer.layout.colors import CYTO_COLORS NODE_SIZE = 100 @@ -12,8 +14,8 @@ _BRANCH_STYLE = { "selector": "edge", "style": { - "line-color": CYTO_COLORS["line"], - "target-arrow-color": CYTO_COLORS["line"], + "line-color": CYTO_COLORS[ComponentType.line], + "target-arrow-color": CYTO_COLORS[ComponentType.line], "curve-style": "bezier", "target-arrow-shape": "triangle", "width": BRANCH_WIDTH, @@ -85,6 +87,30 @@ "style": {"line-color": CYTO_COLORS["selected_link"], "target-arrow-color": CYTO_COLORS["selected_link"]}, } +_GENERIC_BRANCH_STYLE = { + "selector": "edge[group = 'generic_branch']", + "style": {"line-color": CYTO_COLORS["generic_branch"], "target-arrow-color": CYTO_COLORS["generic_branch"]}, +} +_SELECTED_GENERIC_BRANCH_STYLE = { + "selector": "edge[group = 'generic_branch']:selected, edge[group = 'generic_branch']:active", + "style": { + "line-color": CYTO_COLORS["selected_generic_branch"], + "target-arrow-color": CYTO_COLORS["selected_generic_branch"], + }, +} + +_ASYM_LINE_STYLE = { + "selector": "edge[group = 'asym_line']", + "style": {"line-color": CYTO_COLORS["asym_line"], "target-arrow-color": CYTO_COLORS["asym_line"]}, +} + +_SELECTED_ASYM_LINE_STYLE = { + "selector": "edge[group = 'asym_line']:selected, edge[group = 'asym_line']:active", + "style": { + "line-color": CYTO_COLORS["selected_asym_line"], + "target-arrow-color": CYTO_COLORS["selected_asym_line"], + }, +} _OPEN_BRANCH_STYLE = { "selector": "edge[from_status = 0], edge[to_status = 0]", "style": { @@ -124,4 +150,8 @@ _OPEN_BRANCH_STYLE, _OPEN_FROM_SIDE_BRANCH_STYLE, _OPEN_TO_SIDE_BRANCH_STYLE, + _GENERIC_BRANCH_STYLE, + _SELECTED_GENERIC_BRANCH_STYLE, + _ASYM_LINE_STYLE, + _SELECTED_ASYM_LINE_STYLE, ] diff --git a/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py b/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py index e66d36f8..68865d75 100644 --- a/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py +++ b/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py @@ -19,6 +19,8 @@ _LINE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["line"]} _LINK_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["link"]} _TRANSFORMER_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["transformer"]} +_GENERIC_BRANCH_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["generic_branch"]} +_ASYM_LINE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["asym_line"]} _OPEN_BRANCH_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["open_branch"]} LEGENDA_ELEMENTS = [ html.I(className="fas fa-circle", id="node-icon", style=NODE_ICON_STYLE), @@ -31,6 +33,10 @@ dbc.Tooltip("Transformer", target="transformer-icon", placement="bottom"), html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="link-icon", style=_LINK_ICON_STYLE), dbc.Tooltip("Link", target="link-icon", placement="bottom"), + html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="generic-branch-icon", style=_GENERIC_BRANCH_ICON_STYLE), + dbc.Tooltip("Generic Branch", target="generic-branch-icon", placement="bottom"), + html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="asym-line-icon", style=_ASYM_LINE_ICON_STYLE), + dbc.Tooltip("Asymmetrical Line", target="asym-line-icon", placement="bottom"), html.I(className="fas fa-ellipsis", id="open-branch-icon", style=_OPEN_BRANCH_ICON_STYLE), dbc.Tooltip("Open Branch", target="open-branch-icon", placement="bottom"), ] diff --git a/src/power_grid_model_ds/_core/visualizer/parsers.py b/src/power_grid_model_ds/_core/visualizer/parsers.py index 50b048fd..218ea1f1 100644 --- a/src/power_grid_model_ds/_core/visualizer/parsers.py +++ b/src/power_grid_model_ds/_core/visualizer/parsers.py @@ -4,6 +4,8 @@ from typing import Any, Literal +from power_grid_model import ComponentType + from power_grid_model_ds._core.model.arrays.base.array import FancyArray from power_grid_model_ds._core.model.grids.base import Grid from power_grid_model_ds.arrays import Branch3Array, BranchArray, NodeArray @@ -29,10 +31,13 @@ def parse_node_array(nodes: NodeArray) -> list[dict[str, Any]]: def parse_branches(grid: Grid) -> list[dict[str, Any]]: """Parse the branches.""" parsed_branches = [] - parsed_branches.extend(parse_branch_array(grid.line, "line")) - parsed_branches.extend(parse_branch_array(grid.link, "link")) - parsed_branches.extend(parse_branch_array(grid.transformer, "transformer")) - parsed_branches.extend(parse_branch3_array(grid.three_winding_transformer, "transformer")) + parsed_branches.extend(parse_branch_array(grid.line, ComponentType.line)) + parsed_branches.extend(parse_branch_array(grid.link, ComponentType.link)) + parsed_branches.extend(parse_branch_array(grid.transformer, ComponentType.transformer)) + parsed_branches.extend(parse_branch_array(grid.generic_branch, ComponentType.generic_branch)) + parsed_branches.extend(parse_branch_array(grid.asym_line, ComponentType.asym_line)) + parsed_branches.extend(parse_branch3_array(grid.three_winding_transformer, ComponentType.three_winding_transformer)) + return parsed_branches diff --git a/tests/integration/visualizer_tests.py b/tests/integration/visualizer_tests.py index 2cb437a5..8c47a7cf 100644 --- a/tests/integration/visualizer_tests.py +++ b/tests/integration/visualizer_tests.py @@ -2,31 +2,31 @@ # # SPDX-License-Identifier: MPL-2.0 -from dataclasses import dataclass from power_grid_model_ds import Grid from power_grid_model_ds._core.visualizer.app import visualize from power_grid_model_ds.generators import RadialGridGenerator -from tests.unit.visualizer.test_parsers import CoordinatedNodeArray +# from tests.unit.visualizer.test_parsers import CoordinatedNodeArray -@dataclass -class CoordinatedGrid(Grid): - node: CoordinatedNodeArray + +# @dataclass +# class CoordinatedGrid(Grid): +# node: CoordinatedNodeArray def get_radial_grid() -> Grid: return RadialGridGenerator(Grid).run() -def get_coordinated_grid() -> CoordinatedGrid: - scale = 500 - grid = CoordinatedGrid.from_txt("S1 2 open", "2 3", "3 4", "S1 500000000", "500000000 6", "6 7 transformer") - grid.node.x = [3, 2.5, 2, 1.5, 3.5, 4, 4.5] - grid.node.x *= scale - grid.node.y = [3, 4, 3, 4, 3, 4, 3] - grid.node.y *= scale - return grid +# def get_coordinated_grid() -> CoordinatedGrid: +# scale = 500 +# grid = CoordinatedGrid.from_txt("S1 2 open", "2 3", "3 4", "S1 500000000", "500000000 6", "6 7 transformer") +# grid.node.x = [3, 2.5, 2, 1.5, 3.5, 4, 4.5] +# grid.node.x *= scale +# grid.node.y = [3, 4, 3, 4, 3, 4, 3] +# grid.node.y *= scale +# return grid def get_grid_with_links() -> Grid: @@ -38,18 +38,30 @@ def visualize_grid(): visualize(grid=get_radial_grid(), debug=True) -def visualize_coordinated_grid(): - visualize( - grid=get_coordinated_grid(), - debug=True, - ) +# def visualize_coordinated_grid(): +# visualize( +# grid=get_coordinated_grid(), +# debug=True, +# ) def visualize_grid_with_links(): visualize(grid=get_grid_with_links(), debug=True) +def visualize_grid_with_all_types(): + grid = Grid.from_txt( + "S1 2", + "2 3 asym_line", + "3 4 generic_branch", + "4 5 link", + "5 6 transformer", + ) + visualize(grid=grid, debug=True) + + if __name__ == "__main__": - visualize_grid() + # visualize_grid() # visualize_coordinated_grid() # visualize_grid_with_links() + visualize_grid_with_all_types() diff --git a/tests/unit/model/grids/test_grid_base.py b/tests/unit/model/grids/test_grid_base.py index ef20f159..5faf3ac5 100644 --- a/tests/unit/model/grids/test_grid_base.py +++ b/tests/unit/model/grids/test_grid_base.py @@ -406,3 +406,18 @@ def test_from_txt_file(self, tmp_path: Path): assert 1 == grid.branches.filter(to_status=0).size assert 1 == grid.transformer.size np.testing.assert_array_equal([14, 10, 11, 12, 13, 15, 16, 17], grid.branches.id) + + def test_from_txt_all_branch_types(self): + grid = Grid.from_txt( + "1 2 12", + "2 3 link,23", + "3 4 transformer,34", + "4 5 generic_branch,45", + "5 6 asym_line,56", + ) + + assert grid.line.id.tolist() == [12] + assert grid.link.id.tolist() == [23] + assert grid.transformer.id.tolist() == [34] + assert grid.generic_branch.id.tolist() == [45] + assert grid.asym_line.id.tolist() == [56] From 60d0d030901d5e7ecfa04f4b0dbba8db3be0eb32 Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Wed, 3 Dec 2025 16:16:56 +0100 Subject: [PATCH 08/10] fix linting Signed-off-by: Vincent Koppen --- .../_core/visualizer/parsers.py | 15 +++++++++++++-- tests/integration/visualizer_tests.py | 8 +------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/power_grid_model_ds/_core/visualizer/parsers.py b/src/power_grid_model_ds/_core/visualizer/parsers.py index 218ea1f1..071f5b98 100644 --- a/src/power_grid_model_ds/_core/visualizer/parsers.py +++ b/src/power_grid_model_ds/_core/visualizer/parsers.py @@ -41,7 +41,9 @@ def parse_branches(grid: Grid) -> list[dict[str, Any]]: return parsed_branches -def parse_branch3_array(branches: Branch3Array, group: Literal["transformer"]) -> list[dict[str, Any]]: +def parse_branch3_array( + branches: Branch3Array, group: Literal[ComponentType.three_winding_transformer] +) -> list[dict[str, Any]]: """Parse the three-winding transformer array.""" parsed_branches = [] columns = branches.columns @@ -61,7 +63,16 @@ def parse_branch3_array(branches: Branch3Array, group: Literal["transformer"]) - return parsed_branches -def parse_branch_array(branches: BranchArray, group: Literal["line", "link", "transformer"]) -> list[dict[str, Any]]: +def parse_branch_array( + branches: BranchArray, + group: Literal[ + ComponentType.line, + ComponentType.link, + ComponentType.transformer, + ComponentType.generic_branch, + ComponentType.asym_line, + ], +) -> list[dict[str, Any]]: """Parse the branch array.""" parsed_branches = [] columns = branches.columns diff --git a/tests/integration/visualizer_tests.py b/tests/integration/visualizer_tests.py index 8c47a7cf..724ec265 100644 --- a/tests/integration/visualizer_tests.py +++ b/tests/integration/visualizer_tests.py @@ -50,13 +50,7 @@ def visualize_grid_with_links(): def visualize_grid_with_all_types(): - grid = Grid.from_txt( - "S1 2", - "2 3 asym_line", - "3 4 generic_branch", - "4 5 link", - "5 6 transformer", - ) + grid = Grid.from_txt("S1 2", "2 3 asym_line", "3 4 generic_branch", "4 5 link", "5 6 transformer", "") visualize(grid=grid, debug=True) From 526452cca9af442cfb54322dba7f6d5bf91e513e Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Wed, 3 Dec 2025 16:21:21 +0100 Subject: [PATCH 09/10] simplify Signed-off-by: Vincent Koppen --- .../_core/visualizer/parsers.py | 26 ++++-------- tests/integration/visualizer_tests.py | 41 ++++++++++--------- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/power_grid_model_ds/_core/visualizer/parsers.py b/src/power_grid_model_ds/_core/visualizer/parsers.py index 071f5b98..9ed131a8 100644 --- a/src/power_grid_model_ds/_core/visualizer/parsers.py +++ b/src/power_grid_model_ds/_core/visualizer/parsers.py @@ -4,8 +4,6 @@ from typing import Any, Literal -from power_grid_model import ComponentType - from power_grid_model_ds._core.model.arrays.base.array import FancyArray from power_grid_model_ds._core.model.grids.base import Grid from power_grid_model_ds.arrays import Branch3Array, BranchArray, NodeArray @@ -31,19 +29,17 @@ def parse_node_array(nodes: NodeArray) -> list[dict[str, Any]]: def parse_branches(grid: Grid) -> list[dict[str, Any]]: """Parse the branches.""" parsed_branches = [] - parsed_branches.extend(parse_branch_array(grid.line, ComponentType.line)) - parsed_branches.extend(parse_branch_array(grid.link, ComponentType.link)) - parsed_branches.extend(parse_branch_array(grid.transformer, ComponentType.transformer)) - parsed_branches.extend(parse_branch_array(grid.generic_branch, ComponentType.generic_branch)) - parsed_branches.extend(parse_branch_array(grid.asym_line, ComponentType.asym_line)) - parsed_branches.extend(parse_branch3_array(grid.three_winding_transformer, ComponentType.three_winding_transformer)) + parsed_branches.extend(parse_branch_array(grid.line, "line")) + parsed_branches.extend(parse_branch_array(grid.link, "link")) + parsed_branches.extend(parse_branch_array(grid.transformer, "transformer")) + parsed_branches.extend(parse_branch_array(grid.generic_branch, "generic_branch")) + parsed_branches.extend(parse_branch_array(grid.asym_line, "asym_line")) + parsed_branches.extend(parse_branch3_array(grid.three_winding_transformer, "transformer")) return parsed_branches -def parse_branch3_array( - branches: Branch3Array, group: Literal[ComponentType.three_winding_transformer] -) -> list[dict[str, Any]]: +def parse_branch3_array(branches: Branch3Array, group: Literal["transformer"]) -> list[dict[str, Any]]: """Parse the three-winding transformer array.""" parsed_branches = [] columns = branches.columns @@ -65,13 +61,7 @@ def parse_branch3_array( def parse_branch_array( branches: BranchArray, - group: Literal[ - ComponentType.line, - ComponentType.link, - ComponentType.transformer, - ComponentType.generic_branch, - ComponentType.asym_line, - ], + group: Literal["line", "link", "transformer", "generic_branch", "asym_line"], ) -> list[dict[str, Any]]: """Parse the branch array.""" parsed_branches = [] diff --git a/tests/integration/visualizer_tests.py b/tests/integration/visualizer_tests.py index 724ec265..ebb3db4e 100644 --- a/tests/integration/visualizer_tests.py +++ b/tests/integration/visualizer_tests.py @@ -3,30 +3,31 @@ # SPDX-License-Identifier: MPL-2.0 +from dataclasses import dataclass + from power_grid_model_ds import Grid from power_grid_model_ds._core.visualizer.app import visualize from power_grid_model_ds.generators import RadialGridGenerator - -# from tests.unit.visualizer.test_parsers import CoordinatedNodeArray +from tests.unit.visualizer.test_parsers import CoordinatedNodeArray -# @dataclass -# class CoordinatedGrid(Grid): -# node: CoordinatedNodeArray +@dataclass +class CoordinatedGrid(Grid): + node: CoordinatedNodeArray def get_radial_grid() -> Grid: return RadialGridGenerator(Grid).run() -# def get_coordinated_grid() -> CoordinatedGrid: -# scale = 500 -# grid = CoordinatedGrid.from_txt("S1 2 open", "2 3", "3 4", "S1 500000000", "500000000 6", "6 7 transformer") -# grid.node.x = [3, 2.5, 2, 1.5, 3.5, 4, 4.5] -# grid.node.x *= scale -# grid.node.y = [3, 4, 3, 4, 3, 4, 3] -# grid.node.y *= scale -# return grid +def get_coordinated_grid() -> CoordinatedGrid: + scale = 500 + grid = CoordinatedGrid.from_txt("S1 2 open", "2 3", "3 4", "S1 500000000", "500000000 6", "6 7 transformer") + grid.node.x = [3, 2.5, 2, 1.5, 3.5, 4, 4.5] + grid.node.x *= scale + grid.node.y = [3, 4, 3, 4, 3, 4, 3] + grid.node.y *= scale + return grid def get_grid_with_links() -> Grid: @@ -38,11 +39,11 @@ def visualize_grid(): visualize(grid=get_radial_grid(), debug=True) -# def visualize_coordinated_grid(): -# visualize( -# grid=get_coordinated_grid(), -# debug=True, -# ) +def visualize_coordinated_grid(): + visualize( + grid=get_coordinated_grid(), + debug=True, + ) def visualize_grid_with_links(): @@ -55,7 +56,7 @@ def visualize_grid_with_all_types(): if __name__ == "__main__": - # visualize_grid() + visualize_grid() # visualize_coordinated_grid() # visualize_grid_with_links() - visualize_grid_with_all_types() + # visualize_grid_with_all_types() From f3b29c6bfbca5b8f4f7375f5d350124e3503223c Mon Sep 17 00:00:00 2001 From: Vincent Koppen Date: Wed, 3 Dec 2025 16:27:49 +0100 Subject: [PATCH 10/10] cleanup test Signed-off-by: Vincent Koppen --- tests/integration/visualizer_tests.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/integration/visualizer_tests.py b/tests/integration/visualizer_tests.py index ebb3db4e..77e6ca75 100644 --- a/tests/integration/visualizer_tests.py +++ b/tests/integration/visualizer_tests.py @@ -51,12 +51,18 @@ def visualize_grid_with_links(): def visualize_grid_with_all_types(): - grid = Grid.from_txt("S1 2", "2 3 asym_line", "3 4 generic_branch", "4 5 link", "5 6 transformer", "") + grid = Grid.from_txt( + "1 2 12", + "2 3 link,23", + "3 4 transformer,34", + "4 5 generic_branch,45", + "5 6 asym_line,56", + ) visualize(grid=grid, debug=True) if __name__ == "__main__": - visualize_grid() + # visualize_grid() # visualize_coordinated_grid() # visualize_grid_with_links() - # visualize_grid_with_all_types() + visualize_grid_with_all_types()