diff --git a/docs/demos/connecting_new_consumer.ipynb b/docs/demos/connecting_new_consumer.ipynb index 1785656..aac309f 100644 --- a/docs/demos/connecting_new_consumer.ipynb +++ b/docs/demos/connecting_new_consumer.ipynb @@ -73,8 +73,8 @@ "\n", "grid.set_feeder_ids()\n", "\n", - "grid.node.x_coor = np.random.uniform(100, 500, len(grid.node))\n", - "grid.node.y_coor = np.random.uniform(100, 500, len(grid.node))" + "grid.node[\"x_coor\"] = np.random.uniform(100, 500, len(grid.node))\n", + "grid.node[\"y_coor\"] = np.random.uniform(100, 500, len(grid.node))" ] }, { @@ -149,24 +149,26 @@ "):\n", " closest_node_idx = find_closest_node(\n", " grid=grid,\n", - " x=new_consumer.x_coor[0],\n", - " y=new_consumer.y_coor[0],\n", + " x=new_consumer[\"x_coor\"].item(),\n", + " y=new_consumer[\"y_coor\"].item(),\n", " )\n", " closest_node = grid.node[closest_node_idx]\n", "\n", " grid.append(new_consumer)\n", - " new_consumer_load.node = new_consumer.id\n", + " new_consumer_load[\"node\"] = new_consumer[\"id\"]\n", " grid.append(new_consumer_load)\n", "\n", - " dist = np.sqrt((closest_node.x_coor - new_consumer.x_coor) ** 2 + (closest_node.y_coor - new_consumer.y_coor) ** 2)\n", + " distance = np.sqrt(\n", + " (closest_node[\"x_coor\"] - new_consumer[\"x_coor\"]) ** 2 + (closest_node[\"y_coor\"] - new_consumer[\"y_coor\"]) ** 2\n", + " )\n", "\n", " new_line = ExtendedLineArray(\n", " from_node=[closest_node.id],\n", " to_node=[new_consumer.id],\n", " from_status=[1],\n", " to_status=[1],\n", - " r1=[R_PER_KM * dist / 1_000],\n", - " x1=[X_PER_KM * dist / 1_000],\n", + " r1=[R_PER_KM * distance / 1_000],\n", + " x1=[X_PER_KM * distance / 1_000],\n", " c1=[0],\n", " tan1=[0],\n", " i_n=[200],\n", @@ -231,8 +233,8 @@ "metadata": {}, "outputs": [], "source": [ - "print(f\"Overloaded nodes: {grid.node[grid.node.is_overloaded].id}\")\n", - "print(f\"Overloaded lines: {grid.line[grid.line.is_overloaded].id}\")" + "print(f\"Overloaded nodes: {grid.node[grid.node.is_overloaded]['id']}\")\n", + "print(f\"Overloaded lines: {grid.line[grid.line.is_overloaded]['id']}\")" ] }, { @@ -255,8 +257,8 @@ " connect_new_consumer(grid, new_consumer, new_consumer_load)\n", "update_grid(grid)\n", "\n", - "print(f\"Overloaded nodes: {grid.node[grid.node.is_overloaded].id}\")\n", - "print(f\"Overloaded lines: {grid.line[grid.line.is_overloaded].id}\")" + "print(f\"Overloaded nodes: {grid.node[grid.node.is_overloaded]['id']}\")\n", + "print(f\"Overloaded lines: {grid.line[grid.line.is_overloaded]['id']}\")" ] } ], diff --git a/docs/examples/generators/generator_examples.ipynb b/docs/examples/generators/generator_examples.ipynb index 606f206..c076bdc 100644 --- a/docs/examples/generators/generator_examples.ipynb +++ b/docs/examples/generators/generator_examples.ipynb @@ -140,14 +140,14 @@ "# Setup initial nodes and sources\n", "grid = Grid.empty()\n", "nodes = NodeArray.zeros(4)\n", - "nodes.id = [0, 1, 2, 3]\n", - "nodes.u_rated = [10_500] * 4\n", + "nodes[\"id\"] = [0, 1, 2, 3]\n", + "nodes[\"u_rated\"] = [10_500] * 4\n", "\n", "sources = SourceArray.zeros(1)\n", - "sources.id = [4]\n", - "sources.node = [0]\n", - "sources.status = [1]\n", - "sources.u_ref = [1]\n", + "sources[\"id\"] = [4]\n", + "sources[\"node\"] = [0]\n", + "sources[\"status\"] = [1]\n", + "sources[\"u_ref\"] = [1]\n", "\n", "grid.append(nodes)\n", "grid.append(sources)\n", diff --git a/docs/examples/model/array_examples.ipynb b/docs/examples/model/array_examples.ipynb index 92779cc..a341571 100644 --- a/docs/examples/model/array_examples.ipynb +++ b/docs/examples/model/array_examples.ipynb @@ -67,6 +67,7 @@ "source": [ "# Accessing a single column\n", "id_column = fancy_array[\"id\"]\n", + "# Alternative syntax (not recommended: not type-safe)\n", "id_column = fancy_array.id\n", "\n", "# Accessing multiple columns\n", @@ -89,12 +90,14 @@ "outputs": [], "source": [ "# Setting new values to a column\n", - "fancy_array.id = np.array([9, 9, 9])\n", "fancy_array[\"id\"] = np.array([9, 9, 9])\n", - "fancy_array.id = [9, 9, 9]\n", "fancy_array[\"id\"] = [9, 9, 9]\n", - "fancy_array.id = 9\n", - "fancy_array[\"id\"] = 9" + "fancy_array[\"id\"] = 9\n", + "\n", + "# Alternative syntax (not recommended: not type-safe)\n", + "fancy_array.id = np.array([9, 9, 9])\n", + "fancy_array.id = [9, 9, 9]\n", + "fancy_array.id = 9" ] }, { @@ -176,7 +179,7 @@ "outputs": [], "source": [ "# Example analysis: sum of a column\n", - "total = np.sum(fancy_array.test_int)" + "total = np.sum(fancy_array[\"test_int\"])" ] }, { diff --git a/docs/examples/model/grid_examples.ipynb b/docs/examples/model/grid_examples.ipynb index 2d745ec..f6a5b68 100644 --- a/docs/examples/model/grid_examples.ipynb +++ b/docs/examples/model/grid_examples.ipynb @@ -107,13 +107,13 @@ "source": [ "from power_grid_model_ds.arrays import TransformerArray\n", "\n", - "trafo = TransformerArray.empty(1)\n", - "trafo.id = 301\n", - "trafo.from_status = 1\n", - "trafo.to_status = 1\n", - "trafo.from_node = 102\n", - "trafo.to_node = 106\n", - "grid.append(trafo, check_max_id=False)" + "transformer = TransformerArray.empty(1)\n", + "transformer[\"id\"] = 301\n", + "transformer[\"from_status\"] = 1\n", + "transformer[\"to_status\"] = 1\n", + "transformer[\"from_node\"] = 102\n", + "transformer[\"to_node\"] = 106\n", + "grid.append(transformer, check_max_id=False)" ] }, { @@ -284,8 +284,8 @@ "from power_grid_model_ds.arrays import LineArray\n", "\n", "new_line_array = LineArray.zeros(1)\n", - "new_line_array.from_node = 102\n", - "new_line_array.to_node = 105\n", + "new_line_array[\"from_node\"] = 102\n", + "new_line_array[\"to_node\"] = 105\n", "grid.add_branch(branch=new_line_array)" ] }, @@ -330,8 +330,8 @@ "from power_grid_model_ds.arrays import LinkArray\n", "\n", "new_link_array = LinkArray.zeros(1)\n", - "new_link_array.from_node = 102\n", - "new_link_array.to_node = 105\n", + "new_link_array[\"from_node\"] = 102\n", + "new_link_array[\"to_node\"] = 105\n", "grid.add_branch(branch=new_link_array)" ] }, @@ -355,8 +355,8 @@ "from power_grid_model_ds.arrays import TransformerArray\n", "\n", "new_transformer_array = TransformerArray.zeros(1)\n", - "new_transformer_array.from_node = 102\n", - "new_transformer_array.to_node = 105\n", + "new_transformer_array[\"from_node\"] = 102\n", + "new_transformer_array[\"to_node\"] = 105\n", "grid.add_branch(branch=new_transformer_array)" ] }, diff --git a/docs/model_interface.ipynb b/docs/model_interface.ipynb index ab85431..ed9685c 100644 --- a/docs/model_interface.ipynb +++ b/docs/model_interface.ipynb @@ -71,8 +71,8 @@ "from power_grid_model_ds.arrays import LineArray\n", "\n", "new_line_array = LineArray.zeros(1)\n", - "new_line_array.from_node = 2\n", - "new_line_array.to_node = 5\n", + "new_line_array[\"from_node\"] = 2\n", + "new_line_array[\"to_node\"] = 5\n", "grid.add_branch(branch=new_line_array)" ] }, diff --git a/src/power_grid_model_ds/_core/data_source/generator/arrays/base.py b/src/power_grid_model_ds/_core/data_source/generator/arrays/base.py index 2923a05..5423f06 100644 --- a/src/power_grid_model_ds/_core/data_source/generator/arrays/base.py +++ b/src/power_grid_model_ds/_core/data_source/generator/arrays/base.py @@ -12,7 +12,7 @@ class BaseGenerator: """Base class to build a generator for grid elements""" - def __init__(self, grid: Grid, seed: int) -> None: + def __init__(self, grid: Grid, seed: int | None) -> None: """Initializes generator with grid and amount""" self.grid = grid diff --git a/src/power_grid_model_ds/_core/data_source/generator/arrays/line.py b/src/power_grid_model_ds/_core/data_source/generator/arrays/line.py index 1f5eb49..797a536 100644 --- a/src/power_grid_model_ds/_core/data_source/generator/arrays/line.py +++ b/src/power_grid_model_ds/_core/data_source/generator/arrays/line.py @@ -52,19 +52,19 @@ def create_routes(self, number_of_routes: int): """Create a number of lines from the substation to unconnected nodes""" # each source should have at least one route number_of_sources = len(self.grid.source) - from_nodes = self.rng.choice(self.grid.source.node, number_of_routes - number_of_sources, replace=True) - not_source_mask = ~np.isin(self.grid.node.id, self.grid.source.node) - to_nodes = self.rng.choice(self.grid.node.id[not_source_mask], number_of_routes, replace=False) + from_nodes = self.rng.choice(self.grid.source["node"], number_of_routes - number_of_sources, replace=True) + not_source_mask = ~np.isin(self.grid.node["id"], self.grid.source["node"]) + to_nodes = self.rng.choice(self.grid.node["id"][not_source_mask], number_of_routes, replace=False) capacities = 100 + self.rng.exponential(200, number_of_routes) line_array = self.grid.line.__class__.zeros(number_of_routes) - line_array.id = 1 + self.grid.max_id + np.arange(number_of_routes) - line_array.from_node = np.concatenate((self.grid.source.node, from_nodes)) - line_array.to_node = to_nodes - line_array.from_status = [1] * number_of_routes - line_array.to_status = [1] * number_of_routes - line_array.r1 = self.rng.exponential(0.2, number_of_routes) - line_array.x1 = self.rng.exponential(0.02, number_of_routes) - line_array.i_n = capacities + line_array["id"] = 1 + self.grid.max_id + np.arange(number_of_routes) + line_array["from_node"] = np.concatenate((self.grid.source["node"], from_nodes)) + line_array["to_node"] = to_nodes + line_array["from_status"] = [1] * number_of_routes + line_array["to_status"] = [1] * number_of_routes + line_array["r1"] = self.rng.exponential(0.2, number_of_routes) + line_array["x1"] = self.rng.exponential(0.02, number_of_routes) + line_array["i_n"] = capacities self.line_array = line_array def determine_number_of_routes(self) -> int: @@ -78,56 +78,56 @@ def determine_number_of_routes(self) -> int: def connect_nodes(self): """Add a new line between an active and inactive line""" to_node = self.rng.choice(self.unconnected_nodes) - to_voltage = self.grid.node[self.grid.node.id == to_node].u_rated[0] - same_voltage_mask = self.grid.node.u_rated == to_voltage - same_voltage_nodes = self.grid.node[same_voltage_mask] - options_mask = np.isin(self.connected_nodes, same_voltage_nodes.id) + to_voltage = self.grid.node.data[self.grid.node["id"] == to_node]["u_rated"][0] + same_voltage_mask = self.grid.node["u_rated"] == to_voltage + same_voltage_nodes = self.grid.node.data[same_voltage_mask] + options_mask = np.isin(self.connected_nodes, same_voltage_nodes["id"]) from_node = self.rng.choice(np.array(self.connected_nodes)[options_mask]) capacity = 100 + self.rng.exponential(200, 1) new_line = self.grid.line.__class__.zeros(1) - new_line.id = 1 + max(max(self.line_array.id), self.grid.max_id) # pylint: disable=nested-min-max - new_line.from_node = from_node - new_line.to_node = to_node - new_line.from_status = [1] - new_line.to_status = [1] - new_line.r1 = self.rng.exponential(0.2, 1) - new_line.x1 = self.rng.exponential(0.02, 1) - new_line.i_n = capacity + new_line["id"] = 1 + max(max(self.line_array["id"]), self.grid.max_id) # pylint: disable=nested-min-max + new_line["from_node"] = from_node + new_line["to_node"] = to_node + new_line["from_status"] = [1] + new_line["to_status"] = [1] + new_line["r1"] = self.rng.exponential(0.2, 1) + new_line["x1"] = self.rng.exponential(0.02, 1) + new_line["i_n"] = capacity self.line_array = fp.concatenate(self.line_array, new_line) def create_nop_lines(self, number_of_nops: int): """Create the inactive lines between different routes (Normally Open Points)""" - nops = [self.rng.choice(self.grid.node.id, 2, replace=False) for _ in range(number_of_nops)] + nops = [self.rng.choice(self.grid.node["id"], 2, replace=False) for _ in range(number_of_nops)] from_nodes = [nop[0] for nop in nops] to_nodes = [nop[1] for nop in nops] capacities = 100 + self.rng.exponential(200, number_of_nops) nop_lines = self.grid.line.__class__.zeros(number_of_nops) - nop_lines.id = 1 + self.line_array.id.max() + np.arange(number_of_nops) - nop_lines.from_node = from_nodes - nop_lines.to_node = to_nodes - nop_lines.from_status = [1] * number_of_nops - nop_lines.to_status = [0] * number_of_nops - nop_lines.r1 = self.rng.exponential(0.2, number_of_nops) - nop_lines.x1 = self.rng.exponential(0.02, number_of_nops) - nop_lines.i_n = capacities + nop_lines["id"] = 1 + self.line_array["id"].max() + np.arange(number_of_nops) + nop_lines["from_node"] = from_nodes + nop_lines["to_node"] = to_nodes + nop_lines["from_status"] = [1] * number_of_nops + nop_lines["to_status"] = [0] * number_of_nops + nop_lines["r1"] = self.rng.exponential(0.2, number_of_nops) + nop_lines["x1"] = self.rng.exponential(0.02, number_of_nops) + nop_lines["i_n"] = capacities self.line_array = fp.concatenate(self.line_array, nop_lines) def set_unconnected_nodes(self) -> None: """From a line array and total set of nodes determine which are not yet connected""" connected_link_mask = np.logical_or( - np.isin(self.grid.node.id, self.line_array.from_node), - np.isin(self.grid.node.id, self.line_array.to_node), + np.isin(self.grid.node["id"], self.line_array["from_node"]), + np.isin(self.grid.node["id"], self.line_array["to_node"]), ) connected_trafo_mask = np.logical_or( - np.isin(self.grid.node.id, self.trafo_array.from_node), - np.isin(self.grid.node.id, self.trafo_array.to_node), + np.isin(self.grid.node["id"], self.trafo_array["from_node"]), + np.isin(self.grid.node["id"], self.trafo_array["to_node"]), ) connected_mask = np.logical_or( connected_link_mask, connected_trafo_mask, ) - connected_nodes = self.grid.node.id[connected_mask] - unconnected_nodes = self.grid.node.id[~connected_mask] + connected_nodes = self.grid.node["id"][connected_mask] + unconnected_nodes = self.grid.node["id"][~connected_mask] self.unconnected_nodes = unconnected_nodes.tolist() self.connected_nodes = connected_nodes.tolist() diff --git a/src/power_grid_model_ds/_core/data_source/generator/arrays/node.py b/src/power_grid_model_ds/_core/data_source/generator/arrays/node.py index c1964e4..620d168 100644 --- a/src/power_grid_model_ds/_core/data_source/generator/arrays/node.py +++ b/src/power_grid_model_ds/_core/data_source/generator/arrays/node.py @@ -16,22 +16,22 @@ class NodeGenerator(BaseGenerator): def run(self, amount: int, voltage_level: int = 10_500): """Generate nodes in a grid with two possible load scenarios""" node_array = self.grid.node.__class__.zeros(amount) - node_array.id = 1 + self.grid.max_id + np.arange(amount) - node_array.u_rated = voltage_level + node_array["id"] = 1 + self.grid.max_id + np.arange(amount) + node_array["u_rated"] = voltage_level load_low_array = self.grid.sym_load.__class__.zeros(amount) - load_low_array.id = 1 + node_array.id.max() + np.arange(amount) - load_low_array.node = node_array.id - load_low_array.status = 1 + load_low_array["id"] = 1 + node_array["id"].max() + np.arange(amount) + load_low_array["node"] = node_array["id"] + load_low_array["status"] = 1 load_high_array = self.grid.sym_load.__class__.zeros(amount) - load_high_array.id = 1 + load_low_array.id.max() + np.arange(amount) - load_high_array.node = node_array.id - load_high_array.status = 1 + load_high_array["id"] = 1 + load_low_array["id"].max() + np.arange(amount) + load_high_array["node"] = node_array["id"] + load_high_array["status"] = 1 # power consumption in Watt - load_low_array.p_specified = np.round(self.rng.normal(200_000, 150_000, amount)) - load_low_array.q_specified = np.round(self.rng.normal(20_000, 15_000, amount)) - load_high_array.p_specified = np.round(self.rng.normal(-100_000, 350_000, amount)) - load_high_array.q_specified = np.round(self.rng.normal(-5_000, 35_000, amount)) + load_low_array["p_specified"] = np.round(self.rng.normal(200_000, 150_000, amount)) + load_low_array["q_specified"] = np.round(self.rng.normal(20_000, 15_000, amount)) + load_high_array["p_specified"] = np.round(self.rng.normal(-100_000, 350_000, amount)) + load_high_array["q_specified"] = np.round(self.rng.normal(-5_000, 35_000, amount)) return node_array, load_low_array, load_high_array diff --git a/src/power_grid_model_ds/_core/data_source/generator/arrays/source.py b/src/power_grid_model_ds/_core/data_source/generator/arrays/source.py index d4893e6..0934ee0 100644 --- a/src/power_grid_model_ds/_core/data_source/generator/arrays/source.py +++ b/src/power_grid_model_ds/_core/data_source/generator/arrays/source.py @@ -17,14 +17,14 @@ class SourceGenerator(BaseGenerator): def run(self, amount: int) -> tuple[NodeArray, SourceArray]: """Generate nodes in a grid which are sources (substations)""" substation_node_array = self.grid.node.__class__.empty(amount) - substation_node_array.id = 1 + self.grid.max_id + np.arange(amount) - substation_node_array.u_rated = 10_500 - substation_node_array.node_type = NodeType.SUBSTATION_NODE.value + substation_node_array["id"] = 1 + self.grid.max_id + np.arange(amount) + substation_node_array["u_rated"] = 10_500 + substation_node_array["node_type"] = NodeType.SUBSTATION_NODE.value source_array = self.grid.source.__class__.empty(amount) - source_array.id = 1 + substation_node_array.id.max() + np.arange(amount) - source_array.node = substation_node_array.id - source_array.status = 1 - source_array.u_ref = 1 + source_array["id"] = 1 + substation_node_array["id"].max() + np.arange(amount) + source_array["node"] = substation_node_array["id"] + source_array["status"] = 1 + source_array["u_ref"] = 1 return substation_node_array, source_array diff --git a/src/power_grid_model_ds/_core/data_source/generator/arrays/transformer.py b/src/power_grid_model_ds/_core/data_source/generator/arrays/transformer.py index b5fe3ab..61017f1 100644 --- a/src/power_grid_model_ds/_core/data_source/generator/arrays/transformer.py +++ b/src/power_grid_model_ds/_core/data_source/generator/arrays/transformer.py @@ -17,21 +17,21 @@ def run(self, amount: int) -> TransformerArray: """Generate transformers""" # Create transformers from 10kV to 3kV - from_mask = self.grid.node.u_rated == 10_500 - from_nodes = self.rng.choice(self.grid.node.id[from_mask], amount, replace=True) - to_mask = self.grid.node.u_rated == 3_000 - to_nodes = self.rng.choice(self.grid.node.id[to_mask], amount, replace=False) + from_mask = self.grid.node["u_rated"] == 10_500 + from_nodes = self.rng.choice(self.grid.node["id"][from_mask], amount, replace=True) + to_mask = self.grid.node["u_rated"] == 3_000 + to_nodes = self.rng.choice(self.grid.node["id"][to_mask], amount, replace=False) transformer_array = self.grid.transformer.__class__.zeros(amount) - transformer_array.id = 1 + self.grid.max_id + np.arange(amount) - transformer_array.from_node = from_nodes - transformer_array.to_node = to_nodes - transformer_array.from_status = [1] * amount - transformer_array.to_status = [1] * amount - transformer_array.u1 = [10_500] * amount - transformer_array.u2 = [3_000] * amount - transformer_array.sn = [30e6] * amount - transformer_array.clock = [12] * amount - transformer_array.uk = [0.203] * amount - transformer_array.pk = [100e3] * amount + transformer_array["id"] = 1 + self.grid.max_id + np.arange(amount) + transformer_array["from_node"] = from_nodes + transformer_array["to_node"] = to_nodes + transformer_array["from_status"] = [1] * amount + transformer_array["to_status"] = [1] * amount + transformer_array["u1"] = [10_500] * amount + transformer_array["u2"] = [3_000] * amount + transformer_array["sn"] = [30e6] * amount + transformer_array["clock"] = [12] * amount + transformer_array["uk"] = [0.203] * amount + transformer_array["pk"] = [100e3] * amount return transformer_array diff --git a/src/power_grid_model_ds/_core/data_source/generator/grid_generators.py b/src/power_grid_model_ds/_core/data_source/generator/grid_generators.py index 6493325..ebf4250 100644 --- a/src/power_grid_model_ds/_core/data_source/generator/grid_generators.py +++ b/src/power_grid_model_ds/_core/data_source/generator/grid_generators.py @@ -75,6 +75,6 @@ def run(self, seed=None, create_10_3_kv_net: bool = False) -> T: grid.append(transformers) lines = line_generator.run(amount=0, number_of_routes=0) - grid.append(lines[~np.isin(lines.id, grid.line.id)]) + grid.append(lines[~np.isin(lines["id"], grid.line["id"])]) return grid diff --git a/src/power_grid_model_ds/_core/fancypy.py b/src/power_grid_model_ds/_core/fancypy.py index 7f3b8a8..9b265fd 100644 --- a/src/power_grid_model_ds/_core/fancypy.py +++ b/src/power_grid_model_ds/_core/fancypy.py @@ -4,7 +4,7 @@ """A set of helper functions that mimic numpy functions but are specifically designed for FancyArrays.""" -from typing import TYPE_CHECKING, TypeVar, Union +from typing import TYPE_CHECKING, TypeVar, Union, overload import numpy as np @@ -26,7 +26,15 @@ def concatenate(fancy_array: T, *other_arrays: Union[T, np.ndarray]) -> T: return fancy_array.__class__(data=concatenated) -def unique(array: T, **kwargs): +@overload +def unique(array: T) -> T: ... + + +@overload +def unique(array: T, **kwargs) -> tuple[T, ...]: ... + + +def unique(array, **kwargs): """Return the unique elements of the array.""" for column in array.columns: if np.issubdtype(array.dtype[column], np.floating) and np.isnan(array[column]).any(): diff --git a/src/power_grid_model_ds/_core/model/arrays/base/_modify.py b/src/power_grid_model_ds/_core/model/arrays/base/_modify.py index 8568986..2ced12d 100644 --- a/src/power_grid_model_ds/_core/model/arrays/base/_modify.py +++ b/src/power_grid_model_ds/_core/model/arrays/base/_modify.py @@ -10,7 +10,7 @@ def re_order(array: np.ndarray, new_order: ArrayLike, column: str = "id") -> np.ndarray: """Re-order an id-array by the id column so that it follows a new_order. - Expects the new_order input to contain the same values as self.id + Expects the new_order input to contain the same values as self["id"] """ if column not in (array.dtype.names or ()): raise ValueError(f"Cannot re-order array: column {column} does not exist.") diff --git a/src/power_grid_model_ds/_core/model/arrays/base/_string.py b/src/power_grid_model_ds/_core/model/arrays/base/_string.py index a6e2ae6..9d98b1a 100644 --- a/src/power_grid_model_ds/_core/model/arrays/base/_string.py +++ b/src/power_grid_model_ds/_core/model/arrays/base/_string.py @@ -63,7 +63,7 @@ def _determine_column_widths(array: "FancyArray") -> list[tuple[str, int]]: return column_widths for column in array.dtype.names: - data = array.data[column] + data = array[column] if data.size: # if float, round to 3 decimals if data.dtype.kind == "f": 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 9280d72..1abc255 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 @@ -52,12 +52,12 @@ class BranchArray(IdArray, Branch): @property def node_ids(self): """Return both from_node and to_node in one array""" - return np.concatenate([self.data["from_node"], self.data["to_node"]]) + return np.concatenate([self["from_node"], self["to_node"]]) @property def is_active(self) -> NDArray[np.bool_]: """Returns boolean whether branch is closed at both ends""" - return np.logical_and(self.from_status == 1, self.to_status == 1) + return np.logical_and(self["from_status"] == 1, self["to_status"] == 1) def filter_parallel(self, n_parallel: int, mode: Literal["eq", "neq"]) -> "BranchArray": """Return branches that have n_parallel connections. @@ -84,7 +84,7 @@ def filter_parallel(self, n_parallel: int, mode: Literal["eq", "neq"]) -> "Branc if mode == "eq" and n_parallel == 1: return self[index][counts_mask] filtered_branches = self[index][counts_mask] - return self.filter(from_node=filtered_branches.from_node, to_node=filtered_branches.to_node) + return self.filter(from_node=filtered_branches["from_node"], to_node=filtered_branches["to_node"]) class LinkArray(Link, BranchArray): @@ -102,23 +102,23 @@ class TransformerArray(Transformer, BranchArray): class Branch3Array(IdArray, Branch3): def as_branches(self) -> BranchArray: """Convert Branch3Array to BranchArray.""" - branches_1_2 = BranchArray.empty(self.size) - branches_1_2.from_node = self.node_1 - branches_1_2.to_node = self.node_2 - branches_1_2.from_status = self.status_1 - branches_1_2.to_status = self.status_2 - - branches_1_3 = BranchArray.empty(self.size) - branches_1_3.from_node = self.node_1 - branches_1_3.to_node = self.node_3 - branches_1_3.from_status = self.status_1 - branches_1_3.to_status = self.status_3 - - branches_2_3 = BranchArray.empty(self.size) - branches_2_3.from_node = self.node_2 - branches_2_3.to_node = self.node_3 - branches_2_3.from_status = self.status_2 - branches_2_3.to_status = self.status_3 + branches_1_2 = BranchArray.empty(len(self)) + branches_1_2["from_node"] = self["node_1"] + branches_1_2["to_node"] = self["node_2"] + branches_1_2["from_status"] = self["status_1"] + branches_1_2["to_status"] = self["status_2"] + + branches_1_3 = BranchArray.empty(len(self)) + branches_1_3["from_node"] = self["node_1"] + branches_1_3["to_node"] = self["node_3"] + branches_1_3["from_status"] = self["status_1"] + branches_1_3["to_status"] = self["status_3"] + + branches_2_3 = BranchArray.empty(len(self)) + branches_2_3["from_node"] = self["node_2"] + branches_2_3["to_node"] = self["node_3"] + branches_2_3["from_status"] = self["status_2"] + branches_2_3["to_status"] = self["status_3"] return concatenate(branches_1_2, branches_1_3, branches_2_3) diff --git a/src/power_grid_model_ds/_core/model/containers/base.py b/src/power_grid_model_ds/_core/model/containers/base.py index 97fc2f5..65209fd 100644 --- a/src/power_grid_model_ds/_core/model/containers/base.py +++ b/src/power_grid_model_ds/_core/model/containers/base.py @@ -13,6 +13,7 @@ import numpy as np from power_grid_model_ds._core import fancypy as fp +from power_grid_model_ds._core.model.arrays import IdArray from power_grid_model_ds._core.model.arrays.base.array import FancyArray from power_grid_model_ds._core.model.arrays.base.errors import RecordDoesNotExist from power_grid_model_ds._core.model.constants import EMPTY_ID @@ -75,7 +76,7 @@ def find_array_field(cls, array_type: Type[FancyArray]) -> dataclasses.Field: @property def max_id(self) -> int: """Returns the max id across all arrays within the container.""" - max_per_array = [np.max(array.id) if array.size > 0 else 0 for array in self.all_arrays()] + max_per_array = [np.max(array["id"]) if array.size > 0 else 0 for array in self.all_arrays()] return int(max(max_per_array)) def check_ids(self, check_between_arrays: bool = True, check_within_arrays: bool = True) -> None: @@ -89,7 +90,7 @@ def check_ids(self, check_between_arrays: bool = True, check_within_arrays: bool ValueError: if duplicates are found. """ - id_arrays = [array for array in self.all_arrays() if hasattr(array, "id")] + id_arrays = [array for array in self.all_arrays() if isinstance(array, IdArray)] if not id_arrays: return # no arrays to check @@ -113,7 +114,7 @@ def append(self, array: FancyArray, check_max_id: bool = True) -> None: Args: array(FancyArray): the asset_array to be appended (e.g. a NodeArray instance). - check_max_id(bool): whether to check max(array.id) with the id counter + check_max_id(bool): whether to check max(array["id"]) with the id counter Returns: None @@ -132,12 +133,12 @@ def attach_ids(self, array: FancyArray) -> FancyArray: if not array.size: return array - if (id_set := set(array.id)) != {array.get_empty_value("id")}: + if (id_set := set(array["id"])) != {array.get_empty_value("id")}: raise ValueError(f"Cannot attach ids to array that contains non-empty ids: {id_set}") start = self._id_counter + 1 end = start + len(array) - array.id = np.arange(start, end) + array["id"] = np.arange(start, end) self._id_counter = max(self._id_counter, end - 1) return array @@ -175,7 +176,7 @@ def _append(self, array: FancyArray, check_max_id: bool = True) -> None: Append the given asset_array to the corresponding field of Grid and generate ids. Args: array: the asset_array to be appended (e.g. a KabelArray instance). - check_max_id: whether to check max(array.id) with the id counter + check_max_id: whether to check max(array["id"]) with the id counter Returns: None. """ if array.size == 0: @@ -183,7 +184,7 @@ def _append(self, array: FancyArray, check_max_id: bool = True) -> None: array_field = self.find_array_field(array.__class__) - if hasattr(array, "id"): + if isinstance(array, IdArray): self._update_id_counter(array, check_max_id) # Add the given asset_array to the corresponding array in the Grid. @@ -208,30 +209,30 @@ def _get_empty_arrays(cls) -> dict: } def _update_id_counter(self, array, check_max_id: bool = True): - if np.all(array.id == EMPTY_ID): + if np.all(array["id"] == EMPTY_ID): array = self.attach_ids(array) - elif np.any(array.id == EMPTY_ID): + elif np.any(array["id"] == EMPTY_ID): raise ValueError(f"Cannot append: array contains empty [{EMPTY_ID}] and non-empty ids.") elif check_max_id and self.id_counter > 0: # Only check for overlaps when array has prescribed (non-empty) IDs # Check if any incoming ID might overlap with existing IDs # This prevents overlaps since counter tracks the highest used ID - new_min_id = np.min(array.id) + new_min_id = np.min(array["id"]) if new_min_id <= self._id_counter: raise ValueError( f"Cannot append: minimum id {new_min_id} is not greater than " f"the current id counter {self._id_counter}" ) - new_max_id = np.max(array.id) + new_max_id = np.max(array["id"]) # Update _id_counter self._id_counter = max(self._id_counter, new_max_id) @staticmethod - def _get_duplicates_between_arrays(id_arrays: list[FancyArray], check: bool) -> np.ndarray: + def _get_duplicates_between_arrays(id_arrays: list[IdArray], check: bool) -> np.ndarray: if not check: return np.array([]) - unique_ids_per_array = [np.unique(array.id) for array in id_arrays] + unique_ids_per_array = [np.unique(array["id"]) for array in id_arrays] all_ids = np.concatenate(unique_ids_per_array) @@ -240,7 +241,7 @@ def _get_duplicates_between_arrays(id_arrays: list[FancyArray], check: bool) -> return unique_ids[duplicate_mask] @staticmethod - def _get_arrays_with_duplicates(id_arrays: list[FancyArray], check: bool) -> list: + def _get_arrays_with_duplicates(id_arrays: list[IdArray], check: bool) -> list: arrays_with_duplicates: list[Type] = [] if not check: return arrays_with_duplicates diff --git a/src/power_grid_model_ds/_core/model/graphs/container.py b/src/power_grid_model_ds/_core/model/graphs/container.py index acfb87f..b2f5aa8 100644 --- a/src/power_grid_model_ds/_core/model/graphs/container.py +++ b/src/power_grid_model_ds/_core/model/graphs/container.py @@ -95,8 +95,8 @@ def delete_branch3(self, branch: Branch3Array) -> None: def make_active(self, branch: BranchArray) -> None: """Add branch to all active_only graphs""" - from_node = branch.from_node.item() - to_node = branch.to_node.item() + from_node = branch["from_node"].item() + to_node = branch["to_node"].item() for field in dataclasses.fields(self): graph = getattr(self, field.name) if graph.active_only: @@ -105,8 +105,8 @@ def make_active(self, branch: BranchArray) -> None: def make_inactive(self, branch: BranchArray) -> None: """Remove a branch from all active_only graphs""" - from_node = branch.from_node.item() - to_node = branch.to_node.item() + from_node = branch["from_node"].item() + to_node = branch["to_node"].item() for field in dataclasses.fields(self): graph = getattr(self, field.name) if graph.active_only: @@ -128,10 +128,10 @@ def from_arrays(cls, arrays: "Grid") -> "GraphContainer": @staticmethod def _validate_branches(arrays: "Grid") -> None: for array in arrays.branch_arrays: - if any(~np.isin(array.from_node, arrays.node.id)): - raise RecordDoesNotExist(f"Found invalid .from_node values in {array.__class__.__name__}") - if any(~np.isin(array.to_node, arrays.node.id)): - raise RecordDoesNotExist(f"Found invalid .to_node values in {array.__class__.__name__}") + if any(~np.isin(array["from_node"], arrays.node["id"])): + raise RecordDoesNotExist(f"Found invalid from_node values in {array.__class__.__name__}") + if any(~np.isin(array["to_node"], arrays.node["id"])): + raise RecordDoesNotExist(f"Found invalid to_node values in {array.__class__.__name__}") def _append(self, array: FancyArray) -> None: if isinstance(array, NodeArray): diff --git a/src/power_grid_model_ds/_core/model/graphs/models/base.py b/src/power_grid_model_ds/_core/model/graphs/models/base.py index 30dcfc0..87d2b49 100644 --- a/src/power_grid_model_ds/_core/model/graphs/models/base.py +++ b/src/power_grid_model_ds/_core/model/graphs/models/base.py @@ -119,7 +119,7 @@ def add_node_array(self, node_array: NodeArray, raise_on_fail: bool = True) -> N def delete_node_array(self, node_array: NodeArray, raise_on_fail: bool = True) -> None: """Delete all nodes in node_array from the graph""" for node in node_array: - self.delete_node(node.id.item(), raise_on_fail=raise_on_fail) + self.delete_node(node["id"].item(), raise_on_fail=raise_on_fail) def has_branch(self, from_ext_node_id: int, to_ext_node_id: int) -> bool: """Check if a branch exists between two nodes.""" @@ -180,7 +180,7 @@ def delete_branch_array(self, branch_array: BranchArray, raise_on_fail: bool = T """Delete all branches in branch_array from the graph.""" for branch in branch_array: if self._branch_is_relevant(branch): - self.delete_branch(branch.from_node.item(), branch.to_node.item(), raise_on_fail=raise_on_fail) + self.delete_branch(branch["from_node"].item(), branch["to_node"].item(), raise_on_fail=raise_on_fail) def delete_branch3_array(self, branch3_array: Branch3Array, raise_on_fail: bool = True) -> None: """Delete all branch3s in the branch3 array from the graph.""" @@ -399,7 +399,7 @@ def _delete_branch(self, from_node_id, to_node_id) -> None: """ @abstractmethod - def _get_shortest_path(self, source, target): ... + def _get_shortest_path(self, source, target) -> tuple[list[int], int]: ... @abstractmethod def _get_all_paths(self, source, target) -> list[list[int]]: ... 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 ab9c1a9..ffd7ec7 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 @@ -74,13 +74,13 @@ def add_nodes(self, nodes: set[str]): for node_id in source_nodes: new_node = self.grid.node.empty(1) - new_node.id = node_id - new_node.node_type = NodeType.SUBSTATION_NODE + new_node["id"] = node_id + new_node["node_type"] = NodeType.SUBSTATION_NODE self.grid.append(new_node, check_max_id=False) for node_id in regular_nodes: new_node = self.grid.node.empty(1) - new_node.id = node_id + new_node["id"] = node_id self.grid.append(new_node, check_max_id=False) def add_branches(self, branches: dict[tuple[str, str], list[str]]): @@ -105,13 +105,13 @@ def add_branch(self, branch: tuple[str, str], comments: list[str]): if branch_ids: if len(branch_ids) > 1: raise ValueError(f"Multiple branch ids found in row {branch} {','.join(comments)}") - new_branch.id = int(branch_ids[0]) + new_branch["id"] = int(branch_ids[0]) - new_branch.from_node = from_node - new_branch.to_node = to_node - new_branch.from_status = 1 + new_branch["from_node"] = from_node + new_branch["to_node"] = to_node + new_branch["from_status"] = 1 if "open" in comments: - new_branch.to_status = 0 + new_branch["to_status"] = 0 else: - new_branch.to_status = 1 + new_branch["to_status"] = 1 self.grid.append(new_branch, check_max_id=False) 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 aacd636..3890739 100644 --- a/src/power_grid_model_ds/_core/model/grids/base.py +++ b/src/power_grid_model_ds/_core/model/grids/base.py @@ -95,27 +95,33 @@ def __str__(self) -> str: for transformer3 in self.three_winding_transformer: nodes = [transformer3.node_1.item(), transformer3.node_2.item(), transformer3.node_3.item()] for combo in itertools.combinations(nodes, 2): - grid_str += f"S{combo[0]} S{combo[1]} {transformer3.id.item()},3-transformer\n" + grid_str += f"S{combo[0]} S{combo[1]} {transformer3['id'].item()},3-transformer\n" for branch in self.branches: - from_node = self.node.get(id=branch.from_node).record - to_node = self.node.get(id=branch.to_node).record - - from_node_str = f"S{from_node.id}" if from_node.node_type == NodeType.SUBSTATION_NODE else str(from_node.id) - to_node_str = f"S{to_node.id}" if to_node.node_type == NodeType.SUBSTATION_NODE else str(to_node.id) - - suffix_str = str(branch.id.item()) - if branch.from_status.item() == 0 or branch.to_status.item() == 0: + from_node = self.node.get(id=branch["from_node"]) + to_node = self.node.get(id=branch["to_node"]) + + from_node_str = ( + f"S{from_node['id']}" + if from_node["node_type"] == NodeType.SUBSTATION_NODE + else str(from_node["id"].item()) + ) + to_node_str = ( + f"S{to_node['id']}" if to_node["node_type"] == NodeType.SUBSTATION_NODE else str(to_node["id"].item()) + ) + + suffix_str = str(branch["id"].item()) + if branch["from_status"].item() == 0 or branch["to_status"].item() == 0: suffix_str = f"{suffix_str},open" - if branch.id in self.transformer.id: + if branch["id"] in self.transformer["id"]: suffix_str = f"{suffix_str},transformer" - elif branch.id in self.link.id: + elif branch["id"] in self.link["id"]: suffix_str = f"{suffix_str},link" - elif branch.id in self.line.id: + elif branch["id"] in self.line["id"]: pass # no suffix needed 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 or line") grid_str += f"{from_node_str} {to_node_str} {suffix_str}\n" return grid_str @@ -126,7 +132,7 @@ def branches(self) -> BranchArray: branch_dtype = BranchArray.get_dtype() branches = BranchArray() for array in self.branch_arrays: - new_branch = BranchArray(data=array.data[list(branch_dtype.names)]) + new_branch = BranchArray(data=array[list(branch_dtype.names)]) branches = fp.concatenate(branches, new_branch) return branches @@ -152,7 +158,7 @@ def get_typed_branches(self, branch_ids: list[int] | npt.NDArray[np.int32]) -> B raise ValueError("No branch_ids provided.") for branch_array in self.branch_arrays: array = branch_array.filter(branch_ids) - if 0 < array.size != len(branch_ids): + if array.size > 0 and array.size != len(branch_ids): raise ValueError("Branches are not of the same type.") if array.size: return array @@ -164,19 +170,19 @@ def reverse_branches(self, branches: BranchArray): return if not isinstance(branches, (LineArray, LinkArray, TransformerArray)): try: - branches = self.get_typed_branches(branches.id) + branches = self.get_typed_branches(branches["id"]) except ValueError: # If the branches are not of the same type, reverse them per type (though this is slower) for array in self.branch_arrays: - self.reverse_branches(array.filter(branches.id)) + self.reverse_branches(array.filter(branches["id"])) return - from_nodes = branches.from_node - to_nodes = branches.to_node + from_nodes = branches["from_node"] + to_nodes = branches["to_node"] array_field = self.find_array_field(branches.__class__) array = getattr(self, array_field.name) - array.update_by_id(branches.id, from_node=to_nodes, to_node=from_nodes) + array.update_by_id(branches["id"], from_node=to_nodes, to_node=from_nodes) @classmethod def empty(cls: Type[Self], graph_model: type[BaseGraphModel] = RustworkxGraphModel) -> Self: @@ -213,7 +219,7 @@ def add_branch(self, branch: BranchArray) -> None: self._append(array=branch) self.graphs.add_branch_array(branch_array=branch) - logging.debug(f"added branch {branch.id} from {branch.from_node} to {branch.to_node}") + logging.debug(f"added branch {branch['id']} from {branch['from_node']} to {branch['to_node']}") def delete_branch(self, branch: BranchArray) -> None: """Remove a branch from the grid @@ -224,7 +230,7 @@ def delete_branch(self, branch: BranchArray) -> None: _delete_branch_array(branch=branch, grid=self) self.graphs.delete_branch(branch=branch) logging.debug( - f"""deleted branch {branch.id.item()} from {branch.from_node.item()} to {branch.to_node.item()}""" + f"""deleted branch {branch["id"].item()} from {branch["from_node"].item()} to {branch["to_node"].item()}""" ) def delete_branch3(self, branch: Branch3Array) -> None: @@ -244,7 +250,7 @@ def add_node(self, node: NodeArray) -> None: """ self._append(array=node) self.graphs.add_node_array(node_array=node) - logging.debug(f"added rail {node.id}") + logging.debug(f"added rail {node['id']}") def delete_node(self, node: NodeArray) -> None: """Remove a node from the grid @@ -252,17 +258,17 @@ def delete_node(self, node: NodeArray) -> None: Args: node (NodeArray): The node to remove """ - self.node = self.node.exclude(id=node.id) - self.sym_load = self.sym_load.exclude(node=node.id) - self.source = self.source.exclude(node=node.id) + self.node = self.node.exclude(id=node["id"]) + self.sym_load = self.sym_load.exclude(node=node["id"]) + self.source = self.source.exclude(node=node["id"]) for branch_array in self.branch_arrays: - matching_branches = branch_array.filter(from_node=node.id, to_node=node.id, mode_="OR") + matching_branches = branch_array.filter(from_node=node["id"], to_node=node["id"], mode_="OR") for branch in matching_branches: self.delete_branch(branch) self.graphs.delete_node(node=node) - logging.debug(f"deleted rail {node.id}") + logging.debug(f"deleted rail {node['id']}") def make_active(self, branch: BranchArray) -> None: """Make a branch active @@ -272,13 +278,13 @@ def make_active(self, branch: BranchArray) -> None: """ array_field = self.find_array_field(branch.__class__) array_attr = getattr(self, array_field.name) - branch_mask = array_attr.id == branch.id - array_attr.from_status[branch_mask] = 1 - array_attr.to_status[branch_mask] = 1 + branch_mask = array_attr["id"] == branch["id"] + array_attr["from_status"][branch_mask] = 1 + array_attr["to_status"][branch_mask] = 1 setattr(self, array_field.name, array_attr) self.graphs.make_active(branch=branch) - logging.debug(f"activated branch {branch.id}") + logging.debug(f"activated branch {branch['id']}") def make_inactive(self, branch: BranchArray, at_to_side: bool = True) -> None: """Make a branch inactive. This is done by setting from or to status to 0. @@ -290,13 +296,13 @@ def make_inactive(self, branch: BranchArray, at_to_side: bool = True) -> None: """ array_field = self.find_array_field(branch.__class__) array_attr = getattr(self, array_field.name) - branch_mask = array_attr.id == branch.id + branch_mask = array_attr["id"] == branch["id"] status_side = "to_status" if at_to_side else "from_status" array_attr[status_side][branch_mask] = 0 setattr(self, array_field.name, array_attr) self.graphs.make_inactive(branch=branch) - logging.debug(f"deactivated branch {branch.id}") + logging.debug(f"deactivated branch {branch['id']}") def get_branches_in_path(self, nodes_in_path: list[int]) -> BranchArray: """Returns all branches within a path of nodes @@ -325,7 +331,7 @@ def get_nearest_substation_node(self, node_id: int): substation_nodes = self.node.filter(node_type=NodeType.SUBSTATION_NODE.value) for node in connected_nodes: - if node in substation_nodes.id: + if node in substation_nodes["id"]: return substation_nodes.get(node) raise RecordDoesNotExist(f"No {NodeType.SUBSTATION_NODE.name} connected to node {node_id}") @@ -352,11 +358,11 @@ def get_downstream_nodes(self, node_id: int, inclusive: bool = False): """ substation_nodes = self.node.filter(node_type=NodeType.SUBSTATION_NODE.value) - if node_id in substation_nodes.id: + if node_id in substation_nodes["id"]: raise NotImplementedError("get_downstream_nodes is not implemented for substation nodes!") return self.graphs.active_graph.get_downstream_nodes( - node_id=node_id, start_node_ids=list(substation_nodes.id), inclusive=inclusive + node_id=node_id, start_node_ids=list(substation_nodes["id"]), inclusive=inclusive ) def cache(self, cache_dir: Path, cache_name: str, compress: bool = True): @@ -463,6 +469,6 @@ def _delete_branch_array(branch: BranchArray | Branch3Array, grid: Grid): """Delete a branch array from the grid""" array_field = grid.find_array_field(branch.__class__) array_attr = getattr(grid, array_field.name) - setattr(grid, array_field.name, array_attr.exclude(id=branch.id)) + setattr(grid, array_field.name, array_attr.exclude(id=branch["id"])) - grid.transformer_tap_regulator = grid.transformer_tap_regulator.exclude(regulated_object=branch.id) + grid.transformer_tap_regulator = grid.transformer_tap_regulator.exclude(regulated_object=branch["id"]) diff --git a/src/power_grid_model_ds/_core/model/grids/helpers.py b/src/power_grid_model_ds/_core/model/grids/helpers.py index 0dcbbc3..958ebf1 100644 --- a/src/power_grid_model_ds/_core/model/grids/helpers.py +++ b/src/power_grid_model_ds/_core/model/grids/helpers.py @@ -60,15 +60,15 @@ def set_feeder_ids(grid: "Grid"): for array in grid.branch_arrays: array.update_by_id( - component_branches.id, - feeder_branch_id=feeder_branch.id.item(), + component_branches["id"], + feeder_branch_id=feeder_branch["id"].item(), feeder_node_id=feeder_node_id, allow_missing=True, ) grid.node.update_by_id( component_node_ids, - feeder_branch_id=feeder_branch.id.item(), + feeder_branch_id=feeder_branch["id"].item(), feeder_node_id=feeder_node_id, allow_missing=True, ) @@ -76,11 +76,11 @@ def set_feeder_ids(grid: "Grid"): def set_is_feeder(grid: "Grid") -> None: "Set the is_feeder property for all branches in the network." - feeder_node_ids = grid.node.filter(node_type=NodeType.SUBSTATION_NODE).id + feeder_node_ids = grid.node.filter(node_type=NodeType.SUBSTATION_NODE)["id"] array: BranchArray for array in [grid.link, grid.line, grid.transformer]: - array.is_feeder = np.logical_xor( - np.isin(array.from_node, feeder_node_ids), np.isin(array.to_node, feeder_node_ids) + array["is_feeder"] = np.logical_xor( + np.isin(array["from_node"], feeder_node_ids), np.isin(array["to_node"], feeder_node_ids) ) diff --git a/src/power_grid_model_ds/_core/visualizer/parsers.py b/src/power_grid_model_ds/_core/visualizer/parsers.py index 50b048f..237f8bb 100644 --- a/src/power_grid_model_ds/_core/visualizer/parsers.py +++ b/src/power_grid_model_ds/_core/visualizer/parsers.py @@ -18,10 +18,11 @@ def parse_node_array(nodes: NodeArray) -> list[dict[str, Any]]: columns = nodes.columns for node in nodes: cyto_elements = {"data": _array_to_dict(node, columns)} - cyto_elements["data"]["id"] = str(node.id.item()) + cyto_elements["data"]["id"] = str(node["id"].item()) cyto_elements["data"]["group"] = "node" if with_coords: - cyto_elements["position"] = {"x": node.x.item(), "y": -node.y.item()} # invert y-axis for visualization + y_value = -node["y"].item() # invert y-axis for visualization + cyto_elements["position"] = {"x": node["x"].item(), "y": y_value} parsed_nodes.append(cyto_elements) return parsed_nodes @@ -46,9 +47,9 @@ def parse_branch3_array(branches: Branch3Array, group: Literal["transformer"]) - cyto_elements["data"].update( { # IDs need to be unique, so we combine the branch ID with the from and to nodes - "id": str(branch3.id.item()) + f"_{branch1.from_node.item()}_{branch1.to_node.item()}", - "source": str(branch1.from_node.item()), - "target": str(branch1.to_node.item()), + "id": str(branch3["id"].item()) + f"_{branch1['from_node'].item()}_{branch1['to_node'].item()}", + "source": str(branch1["from_node"].item()), + "target": str(branch1["to_node"].item()), "group": group, } ) @@ -64,9 +65,9 @@ def parse_branch_array(branches: BranchArray, group: Literal["line", "link", "tr cyto_elements = {"data": _array_to_dict(branch, columns)} cyto_elements["data"].update( { - "id": str(branch.id.item()), - "source": str(branch.from_node.item()), - "target": str(branch.to_node.item()), + "id": str(branch["id"].item()), + "source": str(branch["from_node"].item()), + "target": str(branch["to_node"].item()), "group": group, } ) diff --git a/tests/fixtures/grids.py b/tests/fixtures/grids.py index 245488e..9787aff 100644 --- a/tests/fixtures/grids.py +++ b/tests/fixtures/grids.py @@ -69,21 +69,21 @@ def build_basic_grid(grid: T) -> T: # Add a transformer transformer = grid.transformer.__class__.empty(1) - transformer.id = 301 - transformer.from_status = 1 - transformer.to_status = 1 - transformer.from_node = 102 - transformer.to_node = 106 + transformer["id"] = 301 + transformer["from_status"] = 1 + transformer["to_status"] = 1 + transformer["from_node"] = 102 + transformer["to_node"] = 106 grid.append(transformer, check_max_id=False) # Add a link link = grid.link.__class__.empty(1) - link.id = 601 - link.from_status = 1 - link.to_status = 1 - link.from_node = 104 - link.to_node = 105 + link["id"] = 601 + link["from_status"] = 1 + link["to_status"] = 1 + link["from_node"] = 104 + link["to_node"] = 105 grid.append(link, check_max_id=False) @@ -161,38 +161,38 @@ def build_basic_grid_with_three_winding(grid: T) -> T: # Add a transformer three_winding_transformer = ThreeWindingTransformerArray.empty(1) - three_winding_transformer.id = [301] - three_winding_transformer.node_1 = [101] - three_winding_transformer.node_2 = [102] - three_winding_transformer.node_3 = [103] - three_winding_transformer.status_1 = [1] - three_winding_transformer.status_2 = [1] - three_winding_transformer.status_3 = [1] - three_winding_transformer.u1 = [150_000] - three_winding_transformer.u2 = [20_000] - three_winding_transformer.u3 = [10_000] - three_winding_transformer.sn_1 = [1e5] - three_winding_transformer.sn_2 = [1e5] - three_winding_transformer.sn_3 = [1e5] - three_winding_transformer.uk_12 = [0.09] - three_winding_transformer.uk_13 = [0.06] - three_winding_transformer.uk_23 = [0.06] - three_winding_transformer.pk_12 = [1e3] - three_winding_transformer.pk_13 = [1e3] - three_winding_transformer.pk_23 = [1e3] - three_winding_transformer.i0 = [0] - three_winding_transformer.p0 = [0] - three_winding_transformer.winding_1 = [2] - three_winding_transformer.winding_2 = [1] - three_winding_transformer.winding_3 = [1] - three_winding_transformer.clock_12 = [5] - three_winding_transformer.clock_13 = [5] - three_winding_transformer.tap_side = [0] - three_winding_transformer.tap_pos = [0] - three_winding_transformer.tap_min = [-10] - three_winding_transformer.tap_max = [10] - three_winding_transformer.tap_nom = [0] - three_winding_transformer.tap_size = [1380] + three_winding_transformer["id"] = [301] + three_winding_transformer["node_1"] = [101] + three_winding_transformer["node_2"] = [102] + three_winding_transformer["node_3"] = [103] + three_winding_transformer["status_1"] = [1] + three_winding_transformer["status_2"] = [1] + three_winding_transformer["status_3"] = [1] + three_winding_transformer["u1"] = [150_000] + three_winding_transformer["u2"] = [20_000] + three_winding_transformer["u3"] = [10_000] + three_winding_transformer["sn_1"] = [1e5] + three_winding_transformer["sn_2"] = [1e5] + three_winding_transformer["sn_3"] = [1e5] + three_winding_transformer["uk_12"] = [0.09] + three_winding_transformer["uk_13"] = [0.06] + three_winding_transformer["uk_23"] = [0.06] + three_winding_transformer["pk_12"] = [1e3] + three_winding_transformer["pk_13"] = [1e3] + three_winding_transformer["pk_23"] = [1e3] + three_winding_transformer["i0"] = [0] + three_winding_transformer["p0"] = [0] + three_winding_transformer["winding_1"] = [2] + three_winding_transformer["winding_2"] = [1] + three_winding_transformer["winding_3"] = [1] + three_winding_transformer["clock_12"] = [5] + three_winding_transformer["clock_13"] = [5] + three_winding_transformer["tap_side"] = [0] + three_winding_transformer["tap_pos"] = [0] + three_winding_transformer["tap_min"] = [-10] + three_winding_transformer["tap_max"] = [10] + three_winding_transformer["tap_nom"] = [0] + three_winding_transformer["tap_size"] = [1380] grid.append(three_winding_transformer, check_max_id=False) diff --git a/tests/integration/loadflow/conftest.py b/tests/integration/loadflow/conftest.py index 17da253..0eb1a2b 100644 --- a/tests/integration/loadflow/conftest.py +++ b/tests/integration/loadflow/conftest.py @@ -21,31 +21,31 @@ @pytest.fixture def simple_loadflow_grid(grid: Grid) -> Grid: nodes = NodeArray.zeros(2) - nodes.id = [0, 1] - nodes.u_rated = [10_500] * 2 + nodes["id"] = [0, 1] + nodes["u_rated"] = [10_500] * 2 lines = LineArray.zeros(1) - lines.id = [2] - lines.from_node = [0] - lines.to_node = [1] - lines.from_status = [1] - lines.to_status = [1] - lines.r1 = [0.1] - lines.x1 = [0.01] + lines["id"] = [2] + lines["from_node"] = [0] + lines["to_node"] = [1] + lines["from_status"] = [1] + lines["to_status"] = [1] + lines["r1"] = [0.1] + lines["x1"] = [0.01] sources = SourceArray.zeros(1) - sources.id = [3] - sources.node = [0] - sources.status = [1] - sources.u_ref = [1] + sources["id"] = [3] + sources["node"] = [0] + sources["status"] = [1] + sources["u_ref"] = [1] loads = SymLoadArray.zeros(1) - loads.id = [4] - loads.node = [1] - loads.status = [1] - loads.type = [LoadGenType.const_power] - loads.p_specified = [250_000] - loads.q_specified = [50_000] + loads["id"] = [4] + loads["node"] = [1] + loads["status"] = [1] + loads["type"] = [LoadGenType.const_power] + loads["p_specified"] = [250_000] + loads["q_specified"] = [50_000] grid.append(nodes) grid.append(lines) @@ -57,30 +57,30 @@ def simple_loadflow_grid(grid: Grid) -> Grid: @pytest.fixture def loadflow_grid_with_transformer(grid: Grid) -> Grid: nodes = NodeArray.zeros(3) - nodes.id = [0, 1, 2] - nodes.u_rated = [10_500] * 2 + [3_000] + nodes["id"] = [0, 1, 2] + nodes["u_rated"] = [10_500] * 2 + [3_000] lines = LineArray.zeros(1) - lines.id = 3 - lines.from_node = 0 - lines.to_node = 1 - lines.from_status = 1 - lines.to_status = 1 - lines.r1 = 0.1 - lines.x1 = 0.01 + lines["id"] = 3 + lines["from_node"] = 0 + lines["to_node"] = 1 + lines["from_status"] = 1 + lines["to_status"] = 1 + lines["r1"] = 0.1 + lines["x1"] = 0.01 sources = SourceArray.zeros(1) - sources.id = 4 - sources.node = 0 - sources.status = 1 - sources.u_ref = 1 + sources["id"] = 4 + sources["node"] = 0 + sources["status"] = 1 + sources["u_ref"] = 1 loads = SymLoadArray.zeros(2) - loads.id = [5, 6] - loads.node = [1, 2] - loads.status = [1, 1] - loads.p_specified = [25_000] * 2 - loads.q_specified = [5_000] * 2 + loads["id"] = [5, 6] + loads["node"] = [1, 2] + loads["status"] = [1, 1] + loads["p_specified"] = [25_000] * 2 + loads["q_specified"] = [5_000] * 2 transformers = TransformerArray( id=[7], @@ -118,55 +118,55 @@ def loadflow_grid_with_transformer(grid: Grid) -> Grid: @pytest.fixture def grid_with_three_winding_transformer(grid: Grid) -> Grid: nodes = NodeArray.zeros(3) - nodes.id = [0, 1, 2] - nodes.u_rated = [150_000, 20_000, 10_000] + nodes["id"] = [0, 1, 2] + nodes["u_rated"] = [150_000, 20_000, 10_000] sources = SourceArray.zeros(1) - sources.id = 4 - sources.node = 0 - sources.status = 1 - sources.u_ref = 1 + sources["id"] = 4 + sources["node"] = 0 + sources["status"] = 1 + sources["u_ref"] = 1 loads = SymLoadArray.zeros(2) - loads.id = [5, 6] - loads.node = [1, 2] - loads.status = [1, 1] - loads.p_specified = [25_000] * 2 - loads.q_specified = [5_000] * 2 + loads["id"] = [5, 6] + loads["node"] = [1, 2] + loads["status"] = [1, 1] + loads["p_specified"] = [25_000] * 2 + loads["q_specified"] = [5_000] * 2 three_winding_transformer = ThreeWindingTransformerArray.empty(1) - three_winding_transformer.id = [7] - three_winding_transformer.node_1 = [0] - three_winding_transformer.node_2 = [1] - three_winding_transformer.node_3 = [2] - three_winding_transformer.status_1 = [1] - three_winding_transformer.status_2 = [1] - three_winding_transformer.status_3 = [1] - three_winding_transformer.u1 = [150_000] - three_winding_transformer.u2 = [20_000] - three_winding_transformer.u3 = [10_000] - three_winding_transformer.sn_1 = [1e5] - three_winding_transformer.sn_2 = [1e5] - three_winding_transformer.sn_3 = [1e5] - three_winding_transformer.uk_12 = [0.09] - three_winding_transformer.uk_13 = [0.06] - three_winding_transformer.uk_23 = [0.06] - three_winding_transformer.pk_12 = [1e3] - three_winding_transformer.pk_13 = [1e3] - three_winding_transformer.pk_23 = [1e3] - three_winding_transformer.i0 = [0] - three_winding_transformer.p0 = [0] - three_winding_transformer.winding_1 = [2] - three_winding_transformer.winding_2 = [1] - three_winding_transformer.winding_3 = [1] - three_winding_transformer.clock_12 = [5] - three_winding_transformer.clock_13 = [5] - three_winding_transformer.tap_side = [0] - three_winding_transformer.tap_pos = [0] - three_winding_transformer.tap_min = [-10] - three_winding_transformer.tap_max = [10] - three_winding_transformer.tap_nom = [0] - three_winding_transformer.tap_size = [1380] + three_winding_transformer["id"] = [7] + three_winding_transformer["node_1"] = [0] + three_winding_transformer["node_2"] = [1] + three_winding_transformer["node_3"] = [2] + three_winding_transformer["status_1"] = [1] + three_winding_transformer["status_2"] = [1] + three_winding_transformer["status_3"] = [1] + three_winding_transformer["u1"] = [150_000] + three_winding_transformer["u2"] = [20_000] + three_winding_transformer["u3"] = [10_000] + three_winding_transformer["sn_1"] = [1e5] + three_winding_transformer["sn_2"] = [1e5] + three_winding_transformer["sn_3"] = [1e5] + three_winding_transformer["uk_12"] = [0.09] + three_winding_transformer["uk_13"] = [0.06] + three_winding_transformer["uk_23"] = [0.06] + three_winding_transformer["pk_12"] = [1e3] + three_winding_transformer["pk_13"] = [1e3] + three_winding_transformer["pk_23"] = [1e3] + three_winding_transformer["i0"] = [0] + three_winding_transformer["p0"] = [0] + three_winding_transformer["winding_1"] = [2] + three_winding_transformer["winding_2"] = [1] + three_winding_transformer["winding_3"] = [1] + three_winding_transformer["clock_12"] = [5] + three_winding_transformer["clock_13"] = [5] + three_winding_transformer["tap_side"] = [0] + three_winding_transformer["tap_pos"] = [0] + three_winding_transformer["tap_min"] = [-10] + three_winding_transformer["tap_max"] = [10] + three_winding_transformer["tap_nom"] = [0] + three_winding_transformer["tap_size"] = [1380] grid.append(nodes) grid.append(sources) @@ -178,29 +178,29 @@ def grid_with_three_winding_transformer(grid: Grid) -> Grid: @pytest.fixture def grid_with_link(grid: Grid) -> Grid: nodes = NodeArray.zeros(2) - nodes.id = [0, 1] - nodes.u_rated = [10_500] * 2 + nodes["id"] = [0, 1] + nodes["u_rated"] = [10_500] * 2 lines = LinkArray.zeros(1) - lines.id = 2 - lines.from_node = 0 - lines.to_node = 1 - lines.from_status = 1 - lines.to_status = 1 + lines["id"] = 2 + lines["from_node"] = 0 + lines["to_node"] = 1 + lines["from_status"] = 1 + lines["to_status"] = 1 sources = SourceArray.zeros(1) - sources.id = 3 - sources.node = 0 - sources.status = 1 - sources.u_ref = 1 + sources["id"] = 3 + sources["node"] = 0 + sources["status"] = 1 + sources["u_ref"] = 1 loads = SymLoadArray.zeros(1) - loads.id = 4 - loads.node = 1 - loads.status = 1 - loads.type = [LoadGenType.const_power] - loads.p_specified = [250_000] - loads.q_specified = [50_000] + loads["id"] = 4 + loads["node"] = 1 + loads["status"] = 1 + loads["type"] = [LoadGenType.const_power] + loads["p_specified"] = [250_000] + loads["q_specified"] = [50_000] grid.append(nodes) grid.append(lines) @@ -220,74 +220,74 @@ def grid_with_tap_regulator(grid: Grid) -> Grid: """ # source sources = SourceArray.zeros(1) - sources.id = [1] - sources.node = [2] - sources.status = [1] - sources.u_ref = [1.0] + sources["id"] = [1] + sources["node"] = [2] + sources["status"] = [1] + sources["u_ref"] = [1.0] grid.append(sources) # node nodes = NodeArray.zeros(3) - nodes.id = [2, 3, 4] - nodes.u_rated = [1e4, 4e2, 4e2] + nodes["id"] = [2, 3, 4] + nodes["u_rated"] = [1e4, 4e2, 4e2] grid.append(nodes) # transformer transformers = TransformerArray.zeros(1) - transformers.id = [5] - transformers.from_node = [2] - transformers.to_node = [3] - transformers.from_status = [1] - transformers.to_status = [1] - transformers.u1 = [1e4] - transformers.u2 = [4e2] - transformers.sn = [1e5] - transformers.uk = [0.1] - transformers.pk = [1e3] - transformers.i0 = [1.0e-6] - transformers.p0 = [0.1] - transformers.winding_from = [2] - transformers.winding_to = [1] - transformers.clock = [5] - transformers.tap_side = [0] - transformers.tap_pos = [3] - transformers.tap_min = [-11] - transformers.tap_max = [9] - transformers.tap_size = [100] + transformers["id"] = [5] + transformers["from_node"] = [2] + transformers["to_node"] = [3] + transformers["from_status"] = [1] + transformers["to_status"] = [1] + transformers["u1"] = [1e4] + transformers["u2"] = [4e2] + transformers["sn"] = [1e5] + transformers["uk"] = [0.1] + transformers["pk"] = [1e3] + transformers["i0"] = [1.0e-6] + transformers["p0"] = [0.1] + transformers["winding_from"] = [2] + transformers["winding_to"] = [1] + transformers["clock"] = [5] + transformers["tap_side"] = [0] + transformers["tap_pos"] = [3] + transformers["tap_min"] = [-11] + transformers["tap_max"] = [9] + transformers["tap_size"] = [100] grid.append(transformers) # line lines = LineArray.zeros(1) - lines.id = [6] - lines.from_node = [3] - lines.to_node = [4] - lines.from_status = [1] - lines.to_status = [1] - lines.r1 = [10.0] - lines.x1 = [0.0] - lines.c1 = [0.0] - lines.tan1 = [0.0] + lines["id"] = [6] + lines["from_node"] = [3] + lines["to_node"] = [4] + lines["from_status"] = [1] + lines["to_status"] = [1] + lines["r1"] = [10.0] + lines["x1"] = [0.0] + lines["c1"] = [0.0] + lines["tan1"] = [0.0] grid.append(lines) # load sym_loads = SymLoadArray.zeros(1) - sym_loads.id = [7] - sym_loads.node = [4] - sym_loads.status = [1] - sym_loads.type = [LoadGenType.const_power] - sym_loads.p_specified = [1e3] - sym_loads.q_specified = [5e3] + sym_loads["id"] = [7] + sym_loads["node"] = [4] + sym_loads["status"] = [1] + sym_loads["type"] = [LoadGenType.const_power] + sym_loads["p_specified"] = [1e3] + sym_loads["q_specified"] = [5e3] grid.append(sym_loads) # transformer tap regulator transformer_tap_regulators = TransformerTapRegulatorArray.zeros(1) - transformer_tap_regulators.id = [8] - transformer_tap_regulators.regulated_object = [5] - transformer_tap_regulators.status = [1] - transformer_tap_regulators.control_side = [BranchSide.to_side.value] - transformer_tap_regulators.u_set = [400.0] - transformer_tap_regulators.u_band = [20.0] - transformer_tap_regulators.line_drop_compensation_r = [0.0] - transformer_tap_regulators.line_drop_compensation_x = [0.0] + transformer_tap_regulators["id"] = [8] + transformer_tap_regulators["regulated_object"] = [5] + transformer_tap_regulators["status"] = [1] + transformer_tap_regulators["control_side"] = [BranchSide.to_side.value] + transformer_tap_regulators["u_set"] = [400.0] + transformer_tap_regulators["u_band"] = [20.0] + transformer_tap_regulators["line_drop_compensation_r"] = [0.0] + transformer_tap_regulators["line_drop_compensation_x"] = [0.0] grid.append(transformer_tap_regulators) return grid diff --git a/tests/integration/loadflow/test_power_grid_model.py b/tests/integration/loadflow/test_power_grid_model.py index 9529e6d..cf6a776 100644 --- a/tests/integration/loadflow/test_power_grid_model.py +++ b/tests/integration/loadflow/test_power_grid_model.py @@ -165,7 +165,7 @@ def test_batch_run(self): core_interface = PowerGridModelInterface(grid=grid) update_sym_load = initialize_array("update", "sym_load", (10, len(grid.sym_load))) - update_sym_load["id"] = [grid.sym_load.id.tolist()] + update_sym_load["id"] = [grid.sym_load["id"].tolist()] update_sym_load["p_specified"] = [grid.sym_load.p_specified.tolist()] * np.linspace(0, 1, 10).reshape(-1, 1) update_sym_load["q_specified"] = [grid.sym_load.q_specified.tolist()] * np.linspace(0, 1, 10).reshape(-1, 1) update_data = { diff --git a/tests/integration/visualizer_tests.py b/tests/integration/visualizer_tests.py index 2cb437a..bae4da2 100644 --- a/tests/integration/visualizer_tests.py +++ b/tests/integration/visualizer_tests.py @@ -22,10 +22,10 @@ def get_radial_grid() -> 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 + 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 diff --git a/tests/performance/_constants.py b/tests/performance/_constants.py index e531976..bfd1bdb 100644 --- a/tests/performance/_constants.py +++ b/tests/performance/_constants.py @@ -10,7 +10,7 @@ "structured": "import numpy as np;" + NUMPY_DTYPE + "input_array = np.zeros({size}, dtype=dtype)", "rec": "import numpy as np;" + NUMPY_DTYPE + "input_array = np.recarray(({size},),dtype=dtype)", "fancy": "from tests.conftest import FancyTestArray; input_array=FancyTestArray.zeros({size});" - + "import numpy as np;input_array.id = np.arange({size})", + + "import numpy as np;input_array['id'] = np.arange({size})", } GRAPH_SETUP_CODES = { diff --git a/tests/performance/graph_performance_tests.py b/tests/performance/graph_performance_tests.py index 61c7e2d..7089932 100644 --- a/tests/performance/graph_performance_tests.py +++ b/tests/performance/graph_performance_tests.py @@ -17,7 +17,7 @@ def perftest_initialize(): def perftest_get_components(): code_to_test = ( "from power_grid_model_ds.enums import NodeType;" - + "feeder_node_ids=grid.node.filter(node_type=NodeType.SUBSTATION_NODE).id;" + + "feeder_node_ids=grid.node.filter(node_type=NodeType.SUBSTATION_NODE)['id'];" + "grid.graphs.active_graph.get_components(feeder_node_ids)" ) do_performance_test(code_to_test, GRAPH_SIZES, 100, setup_codes=GRAPH_SETUP_CODES) diff --git a/tests/performance/grid_performance_tests.py b/tests/performance/grid_performance_tests.py index a3d822e..871be9c 100644 --- a/tests/performance/grid_performance_tests.py +++ b/tests/performance/grid_performance_tests.py @@ -28,8 +28,8 @@ def perf_test_add_lines(): + "nodes = NodeArray.zeros({size});" + "grid.append(nodes);" + "lines = LineArray.zeros({size});" - + "lines.from_node = nodes.id;" - + "lines.to_node = nodes.id;" + + "lines['from_node'] = nodes['id'];" + + "lines['to_node'] = nodes['id'];" } code_to_test = ["grid.append(lines);"] @@ -45,7 +45,7 @@ def perf_test_get_downstream_nodes_performance(): + "from power_grid_model_ds.generators import RadialGridGenerator;" + "from power_grid_model_ds.graph_models import RustworkxGraphModel;" + "grid=RadialGridGenerator(nr_nodes={size}, grid_class=Grid, graph_model=RustworkxGraphModel).run();" - + "non_substation_node = grid.node.filter(node_type=NodeType.UNSPECIFIED).id;" + + "non_substation_node = grid.node.filter(node_type=NodeType.UNSPECIFIED)['id'];" + "node_id = np.random.choice(non_substation_node)" } diff --git a/tests/unit/data_source/generator/test_grid_generators.py b/tests/unit/data_source/generator/test_grid_generators.py index 700c700..1c2fede 100644 --- a/tests/unit/data_source/generator/test_grid_generators.py +++ b/tests/unit/data_source/generator/test_grid_generators.py @@ -31,7 +31,7 @@ def test_generate_random_grid(): assert 2 == len(grid.source) assert 100 == len(grid.sym_load) - inactive_mask = np.logical_or(grid.line.from_status == 0, grid.line.to_status == 0) + inactive_mask = np.logical_or(grid.line["from_status"] == 0, grid.line["to_status"] == 0) inactive_lines = grid.line[inactive_mask] assert 10 == len(inactive_lines) assert len(grid.line) - 10 == grid.graphs.active_graph.nr_branches @@ -61,8 +61,8 @@ def test_generate_random_nodes(grid: Grid): assert isinstance(loads_high, SymLoadArray) # All loads are coupled to a node in the nodes array - assert all(np.isin(loads_high.node, nodes.id)) - assert all(np.isin(loads_low.node, nodes.id)) + assert all(np.isin(loads_high["node"], nodes["id"])) + assert all(np.isin(loads_low["node"], nodes["id"])) def test_generate_random_sources(grid: Grid): @@ -79,20 +79,20 @@ def test_generate_random_sources(grid: Grid): assert isinstance(sources, SourceArray) # All sources are coupled to a node in the nodes array - assert all(np.isin(sources.node, nodes.id)) + assert all(np.isin(sources["node"], nodes["id"])) def test_generate_random_lines(grid: Grid): """Generate random lines""" nodes = NodeArray.zeros(4) - nodes.id = [0, 1, 2, 3] - nodes.u_rated = [10_500] * 4 + nodes["id"] = [0, 1, 2, 3] + nodes["u_rated"] = [10_500] * 4 sources = SourceArray.zeros(1) - sources.id = [4] - sources.node = [0] - sources.status = [1] - sources.u_ref = [1] + sources["id"] = [4] + sources["node"] = [0] + sources["status"] = [1] + sources["u_ref"] = [1] grid.append(nodes) grid.append(sources) @@ -103,27 +103,27 @@ def test_generate_random_lines(grid: Grid): # We have generated at least 5 lines assert len(lines) >= 5 # Two lines are inactive - inactive_line_mask = np.logical_or(lines.from_status == 0, lines.to_status == 0) + inactive_line_mask = np.logical_or(lines["from_status"] == 0, lines["to_status"] == 0) assert 2 == sum(inactive_line_mask) assert isinstance(lines, LineArray) # All lines have from and to nodes in the nodes array - assert all(np.isin(lines.from_node, nodes.id)) - assert all(np.isin(lines.to_node, nodes.id)) + assert all(np.isin(lines["from_node"], nodes["id"])) + assert all(np.isin(lines["to_node"], nodes["id"])) def test_create_routes(grid: Grid): """Generate new routes""" nodes = NodeArray.zeros(4) - nodes.id = [0, 1, 2, 3] - nodes.u_rated = [10_500] * 4 + nodes["id"] = [0, 1, 2, 3] + nodes["u_rated"] = [10_500] * 4 sources = SourceArray.zeros(1) - sources.id = [4] - sources.node = [0] - sources.status = [1] - sources.u_ref = [1] + sources["id"] = [4] + sources["node"] = [0] + sources["status"] = [1] + sources["u_ref"] = [1] grid.append(nodes) grid.append(sources) @@ -136,15 +136,15 @@ def test_create_routes(grid: Grid): assert 2 == len(line_generator.line_array) # These lines are active inactive_line_mask = np.logical_or( - line_generator.line_array.from_status == 0, - line_generator.line_array.to_status == 0, + line_generator.line_array["from_status"] == 0, + line_generator.line_array["to_status"] == 0, ) assert 0 == sum(inactive_line_mask) - # All lines have from node in sources.node - assert all(np.isin(line_generator.line_array.from_node, sources.node)) - # All lines have to node in nodes.id - assert all(np.isin(line_generator.line_array.to_node, nodes.id)) + # All lines have from node in sources["node"] + assert all(np.isin(line_generator.line_array["from_node"], sources["node"])) + # All lines have to node in nodes["id"] + assert all(np.isin(line_generator.line_array["to_node"], nodes["id"])) def test_determine_number_of_routes(grid: Grid): @@ -172,21 +172,21 @@ def test_determine_number_of_routes(grid: Grid): def test_connect_nodes(grid: Grid): """Connect nodes""" nodes = NodeArray.zeros(4) - nodes.id = [0, 1, 2, 3] - nodes.u_rated = [10_500] * 4 + nodes["id"] = [0, 1, 2, 3] + nodes["u_rated"] = [10_500] * 4 sources = SourceArray.zeros(1) - sources.id = [4] - sources.node = [0] - sources.status = [1] - sources.u_ref = [1] + sources["id"] = [4] + sources["node"] = [0] + sources["status"] = [1] + sources["u_ref"] = [1] line_array = LineArray.zeros(1) - line_array.id = [5] - line_array.from_node = [0] - line_array.to_node = [1] - line_array.from_status = [1] - line_array.to_status = [1] + line_array["id"] = [5] + line_array["from_node"] = [0] + line_array["to_node"] = [1] + line_array["from_status"] = [1] + line_array["to_status"] = [1] grid.append(nodes) grid.append(sources) @@ -209,21 +209,21 @@ def test_connect_nodes(grid: Grid): def test_create_nops(grid: Grid): """Create normally open points""" nodes = NodeArray.zeros(4) - nodes.id = [0, 1, 2, 3] - nodes.u_rated = [10_500] * 4 + nodes["id"] = [0, 1, 2, 3] + nodes["u_rated"] = [10_500] * 4 sources = SourceArray.zeros(1) - sources.id = [4] - sources.node = [0] - sources.status = [1] - sources.u_ref = [1] + sources["id"] = [4] + sources["node"] = [0] + sources["status"] = [1] + sources["u_ref"] = [1] line_array = LineArray.zeros(2) - line_array.id = [5, 6] - line_array.from_node = [0, 0] - line_array.to_node = [1, 2] - line_array.from_status = [1, 1] - line_array.to_status = [1, 1] + line_array["id"] = [5, 6] + line_array["from_node"] = [0, 0] + line_array["to_node"] = [1, 2] + line_array["from_status"] = [1, 1] + line_array["to_status"] = [1, 1] grid.append(nodes) grid.append(sources) @@ -238,8 +238,8 @@ def test_create_nops(grid: Grid): assert 3 == len(line_generator.line_array) # This line is inactive inactive_line_mask = np.logical_or( - line_generator.line_array.from_status == 0, - line_generator.line_array.to_status == 0, + line_generator.line_array["from_status"] == 0, + line_generator.line_array["to_status"] == 0, ) assert 1 == sum(inactive_line_mask) @@ -251,8 +251,8 @@ def test_generate_random_grid_with_tranformers(): # two ten to 3 kv transformers have been added assert 2 == len(grid.transformer) - assert all(np.isclose([10_500] * 2, grid.transformer.u1.tolist())) - assert all(np.isclose([3_000] * 2, grid.transformer.u2.tolist())) + assert all(np.isclose([10_500] * 2, grid.transformer["u1"].tolist())) + assert all(np.isclose([3_000] * 2, grid.transformer["u2"].tolist())) core_interface = PowerGridModelInterface(grid=grid) core_interface.create_input_from_grid() diff --git a/tests/unit/model/arrays/test_array.py b/tests/unit/model/arrays/test_array.py index c727687..ce0d0ce 100644 --- a/tests/unit/model/arrays/test_array.py +++ b/tests/unit/model/arrays/test_array.py @@ -51,7 +51,7 @@ def test_setattr(fancy_test_array: FancyTestArray): fancy_test_array.id = [9, 9, 9] assert_array_equal(fancy_test_array.id, [9, 9, 9]) - assert_array_equal(fancy_test_array.data["id"], [9, 9, 9]) + assert_array_equal(fancy_test_array["id"], [9, 9, 9]) def test_prevent_delete_numpy_attribute(fancy_test_array: FancyTestArray): @@ -75,18 +75,18 @@ def test_getitem_unique_multiple_columns(fancy_test_array: FancyTestArray): def test_getitem_array_index(fancy_test_array: FancyTestArray): - assert fancy_test_array[0].data.tolist() == fancy_test_array.data[0:1].tolist() + assert fancy_test_array[0].tolist() == fancy_test_array[0:1].tolist() def test_getitem_array_nested_index(fancy_test_array: FancyTestArray): nested_array = fancy_test_array[0][0][0][0][0][0] assert isinstance(nested_array, FancyArray) assert nested_array.data.shape == (1,) - assert nested_array.data.tolist() == fancy_test_array.data[0:1].tolist() + assert nested_array.tolist() == fancy_test_array[0:1].tolist() def test_getitem_array_slice(fancy_test_array: FancyTestArray): - assert fancy_test_array.data[0:2].tolist() == fancy_test_array[0:2].tolist() + assert fancy_test_array[0:2].tolist() == fancy_test_array[0:2].tolist() def test_getitem_with_array_mask(fancy_test_array: FancyTestArray): diff --git a/tests/unit/model/arrays/test_build.py b/tests/unit/model/arrays/test_build.py index 07f9045..c866325 100644 --- a/tests/unit/model/arrays/test_build.py +++ b/tests/unit/model/arrays/test_build.py @@ -59,7 +59,7 @@ def test_build_without_array_definition(): def test_build_without_args_or_kwargs(): array = FancyTestArray() - assert_array_equal(array.id, []) + assert_array_equal(array["id"], []) assert 0 == array.size @@ -72,11 +72,11 @@ def test_build_from_kwargs(): test_bool=[True, False, True], ) assert array.size == 3 - assert_array_equal(array.id, [1, 2, 3]) - assert_array_equal(array.test_int, [3, 0, 4]) - assert_array_equal(array.test_float, [4.0, 4.0, 1.0]) - assert_array_equal(array.test_str, ["a", "c", "d"]) - assert_array_equal(array.test_bool, [True, False, True]) + assert_array_equal(array["id"], [1, 2, 3]) + assert_array_equal(array["test_int"], [3, 0, 4]) + assert_array_equal(array["test_float"], [4.0, 4.0, 1.0]) + assert_array_equal(array["test_str"], ["a", "c", "d"]) + assert_array_equal(array["test_bool"], [True, False, True]) def test_build_from_kwargs_with_missing_input_fields(): @@ -129,7 +129,7 @@ def test_build_from_numpy_2d_shape_2_4(): numpy_array = np.array([[1, 2, 3, 4, 5], [9, 9, 9, 9, 9]]) assert (2, 5) == numpy_array.shape array = FancyTestArray(numpy_array) - assert_array_equal([2, 9], array.test_int) + assert_array_equal([2, 9], array["test_int"]) assert 2 == array.size @@ -137,7 +137,7 @@ def test_build_from_numpy_2d_shape_4_2(): numpy_array = np.array([[15, 9], [2, 9], [3, 9], [4, 9], [7, 9]]) assert (5, 2) == numpy_array.shape array = FancyTestArray(numpy_array) - assert_array_equal([2, 9], array.test_int) + assert_array_equal([2, 9], array["test_int"]) assert 2 == array.size @@ -149,14 +149,13 @@ def test_array_invalid_columns_before_initialization(): def test_some_zeros(): array = FancyTestArray.zeros(3) assert 3 == array.size - assert_array_equal([np.iinfo(np.int32).min] * 3, array.id) - assert_array_equal([0, 0, 0], array.test_int) - assert 3 == array.size + assert_array_equal([np.iinfo(np.int32).min] * 3, array["id"]) + assert_array_equal([0, 0, 0], array["test_int"]) assert 3 == len(array) assert 3 == len(array.data) - assert 3 == len(array.id) - assert 3 == len(array.test_int) - assert 3 == len(array.test_float) + assert 3 == len(array["id"]) + assert 3 == len(array["test_int"]) + assert 3 == len(array["test_float"]) def test_many_zeros(): @@ -164,46 +163,46 @@ def test_many_zeros(): assert int(1e6) == array.size assert int(1e6) == len(array) assert int(1e6) == len(array.data) - assert int(1e6) == len(array.id) - assert int(1e6) == len(array.test_int) - assert int(1e6) == len(array.test_float) + assert int(1e6) == len(array["id"]) + assert int(1e6) == len(array["test_int"]) + assert int(1e6) == len(array["test_float"]) def test_empty(): array = FancyTestArray.empty(3) assert 3 == array.size - assert_array_equal([EMPTY_ID, EMPTY_ID, EMPTY_ID], array.id) + assert_array_equal([EMPTY_ID, EMPTY_ID, EMPTY_ID], array["id"]) min_int64 = np.iinfo(np.int64).min - assert_array_equal([min_int64] * 3, array.test_int) + assert_array_equal([min_int64] * 3, array["test_int"]) def test_empty_with_sized_dtypes(): array = SizedDTypesArray.empty(1) - assert_array_equal([np.iinfo(np.int8).min], array.test_int8) - assert_array_equal([np.iinfo(np.int16).min], array.test_int16) - assert_array_equal([np.iinfo(np.int32).min], array.test_int32) - assert_array_equal([np.iinfo(np.int64).min], array.test_int64) + assert_array_equal([np.iinfo(np.int8).min], array["test_int8"]) + assert_array_equal([np.iinfo(np.int16).min], array["test_int16"]) + assert_array_equal([np.iinfo(np.int32).min], array["test_int32"]) + assert_array_equal([np.iinfo(np.int64).min], array["test_int64"]) - assert_array_equal([np.nan], array.test_float16) - assert_array_equal([np.nan], array.test_float32) - assert_array_equal([np.nan], array.test_float64) + assert_array_equal([np.nan], array["test_float16"]) + assert_array_equal([np.nan], array["test_float32"]) + assert_array_equal([np.nan], array["test_float64"]) def test_empty_with_defaults(): array = DefaultedFancyTestArray.empty(3) assert 3 == array.size - assert_array_equal([-1, -1, -1], array.id) - assert_array_equal([4, 4, 4], array.test_int) - assert_array_equal([4.5, 4.5, 4.5], array.test_float) - assert_array_equal(["DEFAULT", "DEFAULT", "DEFAULT"], array.test_str) + assert_array_equal([-1, -1, -1], array["id"]) + assert_array_equal([4, 4, 4], array["test_int"]) + assert_array_equal([4.5, 4.5, 4.5], array["test_float"]) + assert_array_equal(["DEFAULT", "DEFAULT", "DEFAULT"], array["test_str"]) def test_from_structured_subarray_with_defaults(fancy_test_array: FancyTestArray): array = ExtendedFancyTestArray(fancy_test_array.data) assert 3 == array.size - assert all(np.isnan(array.test_float2)) - assert_array_equal([42.0, 42.0, 42.0], array.test_float3) + assert all(np.isnan(array["test_float2"])) + assert_array_equal([42.0, 42.0, 42.0], array["test_float3"]) def test_from_structured_subarray_no_defaults(fancy_test_array: FancyTestArray): @@ -258,8 +257,8 @@ def test_sensor_array(): def test_inherit_defaults_from_multiple_parents(): array = ChildArray.empty(3) assert 3 == array.size - assert_array_equal([-1, -1, -1], array.id) - assert_array_equal([4, 4, 4], array.test_int) - assert_array_equal([4.5, 4.5, 4.5], array.test_float) - assert_array_equal(["DEFAULT", "DEFAULT", "DEFAULT"], array.test_str) - assert_array_equal([42.0, 42.0, 42.0], array.test_float4) + assert_array_equal([-1, -1, -1], array["id"]) + assert_array_equal([4, 4, 4], array["test_int"]) + assert_array_equal([4.5, 4.5, 4.5], array["test_float"]) + assert_array_equal(["DEFAULT", "DEFAULT", "DEFAULT"], array["test_str"]) + assert_array_equal([42.0, 42.0, 42.0], array["test_float4"]) diff --git a/tests/unit/model/arrays/test_filters_exclude.py b/tests/unit/model/arrays/test_filters_exclude.py index 9970bdf..0ff31e2 100644 --- a/tests/unit/model/arrays/test_filters_exclude.py +++ b/tests/unit/model/arrays/test_filters_exclude.py @@ -17,35 +17,35 @@ def test_exclude_by_id_kwarg(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(id=1) assert isinstance(array, FancyTestArray) assert array.size == 2 - assert_array_equal(array.id, [2, 3]) + assert_array_equal(array["id"], [2, 3]) def test_exclude_by_id_arg(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(1) assert array.size == 2 - assert_array_equal(array.id, [2, 3]) + assert_array_equal(array["id"], [2, 3]) def test_exclude_by_int(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(test_int=4) assert array.size == 2 - assert_array_equal(array.test_int, [3, 0]) + assert_array_equal(array["test_int"], [3, 0]) def test_exclude_by_float(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(test_float=1.0) assert array.size == 2 - assert_array_equal(array.test_float, [4.0, 4.0]) + assert_array_equal(array["test_float"], [4.0, 4.0]) def test_exclude_by_str(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(test_str="c") assert array.size == 2 - assert_array_equal(array.test_str, ["a", "d"]) + assert_array_equal(array["test_str"], ["a", "d"]) def test_exclude_no_match(fancy_test_array: FancyTestArray): - assert fancy_test_array.size == 3 + assert len(fancy_test_array) == 3 array = fancy_test_array.exclude(test_str="z") assert array.size == 3 @@ -53,8 +53,7 @@ def test_exclude_no_match(fancy_test_array: FancyTestArray): def test_exclude_multiple_matches(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(test_float=4.0) assert array.size == 1 - record = array.record - assert math.isclose(record.test_float, 1.0) + assert math.isclose(array["test_float"].item(), 1.0) def test_exclude_no_input(fancy_test_array: FancyTestArray): @@ -71,7 +70,7 @@ def test_exclude_empty_list_input(fancy_test_array: FancyTestArray): def test_exclude_mode_or(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(test_float=1.0, test_str="a", mode_="OR") assert 1 == array.size - assert_array_equal(array.id, [2]) + assert_array_equal(array["id"], [2]) def test_exclude_mask_by_id_kwarg(fancy_test_array: FancyTestArray): @@ -129,4 +128,4 @@ def test_exclude_kwarg_set_input(fancy_test_array: FancyTestArray): array = fancy_test_array.exclude(id={1}) assert isinstance(array, FancyTestArray) assert array.size == 2 - assert 1 not in array.id + assert 1 not in array["id"] diff --git a/tests/unit/model/arrays/test_filters_filter.py b/tests/unit/model/arrays/test_filters_filter.py index 191f472..e26201e 100644 --- a/tests/unit/model/arrays/test_filters_filter.py +++ b/tests/unit/model/arrays/test_filters_filter.py @@ -17,39 +17,38 @@ def test_filter_by_id_kwarg(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(id=1) assert isinstance(array, FancyTestArray) assert array.size == 1 - assert array.id == 1 + assert array["id"] == 1 def test_filter_by_id_arg(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(1) assert array.size == 1 - assert array.id == 1 + assert array["id"] == 1 def test_filter_keeps_original_order(): original_array = FancyTestArray.zeros(9) - original_array.id = [1, 3, 2, 4, 5, 6, 7, 8, 16] + original_array["id"] = [1, 3, 2, 4, 5, 6, 7, 8, 16] array = original_array.filter(id=[2, 4, 5, 16, 3]) - np.testing.assert_array_equal([3, 2, 4, 5, 16], array.id) + np.testing.assert_array_equal([3, 2, 4, 5, 16], array["id"]) def test_filter_by_int(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(test_int=4) assert array.size == 1 - assert array.test_int == 4 + assert array["test_int"] == 4 def test_filter_by_float(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(test_float=1.0) assert array.size == 1 - record = array.record - assert math.isclose(record.test_float, 1.0) + assert math.isclose(array["test_float"].item(), 1.0) def test_filter_by_str(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(test_str="c") assert array.size == 1 - assert array.test_str == "c" + assert array["test_str"] == "c" def test_filter_no_match(fancy_test_array: FancyTestArray): @@ -60,7 +59,7 @@ def test_filter_no_match(fancy_test_array: FancyTestArray): def test_filter_multiple_matches(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(test_float=4.0) assert array.size == 2 - assert_array_equal(array.test_float, [4.0, 4.0]) + assert_array_equal(array["test_float"], [4.0, 4.0]) def test_filter_no_input(fancy_test_array: FancyTestArray): @@ -76,7 +75,7 @@ def test_filter_empty_list_input(fancy_test_array: FancyTestArray): def test_filter_mode_or(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(test_float=1.0, test_str="a", mode_="OR") assert 2 == array.size - assert_array_equal(array.id, [1, 3]) + assert_array_equal(array["id"], [1, 3]) def test_filter_mask_by_id_kwarg(fancy_test_array: FancyTestArray): @@ -134,11 +133,11 @@ def test_filter_kwarg_by_set_input(fancy_test_array: FancyTestArray): array = fancy_test_array.filter(id={1}) assert isinstance(array, FancyTestArray) assert array.size == 1 - assert array.id == 1 + assert array["id"] == 1 def test_filter_arg_by_set_input(fancy_test_array: FancyTestArray): array = fancy_test_array.filter({1, 2}) assert isinstance(array, FancyTestArray) assert array.size == 2 - assert_array_equal(array.id, [1, 2]) + assert_array_equal(array["id"], [1, 2]) diff --git a/tests/unit/model/arrays/test_filters_get.py b/tests/unit/model/arrays/test_filters_get.py index 57607a0..9009fa7 100644 --- a/tests/unit/model/arrays/test_filters_get.py +++ b/tests/unit/model/arrays/test_filters_get.py @@ -15,28 +15,28 @@ def test_get_by_id_kwarg(fancy_test_array: FancyTestArray): array = fancy_test_array.get(id=1) assert isinstance(array, FancyTestArray) - assert array.id == 1 + assert array["id"] == 1 def test_get_by_id_arg(fancy_test_array: FancyTestArray): array = fancy_test_array.get(1) assert isinstance(array, FancyTestArray) - assert array.id == 1 + assert array["id"] == 1 def test_get_by_int(fancy_test_array: FancyTestArray): array = fancy_test_array.get(test_int=4) - assert array.test_int == 4 + assert array["test_int"] == 4 def test_get_by_float(fancy_test_array: FancyTestArray): - record = fancy_test_array.get(test_float=1.0).record - assert math.isclose(record.test_float, 1.0) + array = fancy_test_array.get(test_float=1.0) + assert math.isclose(array["test_float"].item(), 1.0) def test_get_by_str(fancy_test_array: FancyTestArray): array = fancy_test_array.get(test_str="c") - assert array.test_str == "c" + assert array["test_str"] == "c" def test_get_no_match(fancy_test_array: FancyTestArray): @@ -58,4 +58,4 @@ def test_get_kwarg_set_input(fancy_test_array: FancyTestArray): array = fancy_test_array.get(id={1}) assert isinstance(array, FancyTestArray) assert array.size == 1 - assert array.id == 1 + assert array["id"] == 1 diff --git a/tests/unit/model/arrays/test_modify.py b/tests/unit/model/arrays/test_modify.py index 598df90..fbfa545 100644 --- a/tests/unit/model/arrays/test_modify.py +++ b/tests/unit/model/arrays/test_modify.py @@ -14,18 +14,18 @@ class TestReorder: def test_reorder_by_id(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) reordered = fancy_test_array.re_order([3, 1, 2]) - assert_array_equal(reordered.id, [3, 1, 2]) - assert_array_equal(reordered.test_str, ["d", "a", "c"]) + assert_array_equal(reordered["id"], [3, 1, 2]) + assert_array_equal(reordered["test_str"], ["d", "a", "c"]) def test_reorder_by_test_str(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) reordered = fancy_test_array.re_order(["d", "a", "c"], column="test_str") - assert_array_equal(reordered.id, [3, 1, 2]) - assert_array_equal(reordered.test_str, ["d", "a", "c"]) + assert_array_equal(reordered["id"], [3, 1, 2]) + assert_array_equal(reordered["test_str"], ["d", "a", "c"]) def test_reorder_mismatched_length(self, fancy_test_array: FancyTestArray): with pytest.raises(ValueError): @@ -34,30 +34,30 @@ def test_reorder_mismatched_length(self, fancy_test_array: FancyTestArray): class TestUpdateById: def test_get_update_by_id(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) updated = fancy_test_array.get_updated_by_id([1, 3], test_str="e") - assert_array_equal(updated.id, [1, 3]) - assert_array_equal(updated.test_str, ["e", "e"]) + assert_array_equal(updated["id"], [1, 3]) + assert_array_equal(updated["test_str"], ["e", "e"]) - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["e", "c", "e"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["e", "c", "e"]) def test_get_update_by_id_duplicate_id_input(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) updated = fancy_test_array.get_updated_by_id([1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3], test_str="e") - assert_array_equal(updated.id, [1, 3]) + assert_array_equal(updated["id"], [1, 3]) def test_update_by_id_multiple_columns(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) fancy_test_array.update_by_id([1, 3], test_str="e", test_int=[88, 99]) - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["e", "c", "e"]) - assert_array_equal(fancy_test_array.test_int, [88, 0, 99]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["e", "c", "e"]) + assert_array_equal(fancy_test_array["test_int"], [88, 0, 99]) def test_update_by_id_invalid_column(self, fancy_test_array: FancyTestArray): with pytest.raises(ValueError): @@ -73,7 +73,7 @@ def test_update_by_id_invalid_id(self, fancy_test_array: FancyTestArray): def test_update_by_id_invalid_id_allow_missing(self, fancy_test_array: FancyTestArray): fancy_test_array.update_by_id([1, 4], test_str="e", allow_missing=True) - assert fancy_test_array.get(1).record.test_str == "e" + assert fancy_test_array.get(1)["test_str"] == "e" def test_update_by_id_no_id_column(self): fancy_non_id_array = FancyNonIdArray.zeros(10) @@ -87,11 +87,11 @@ def test_update_by_id_non_existing_id(self, fancy_test_array: FancyTestArray): class TestConcatenate: def test_concatenate_fancy_array(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) concatenated = fp.concatenate(fancy_test_array, fancy_test_array) - assert_array_equal(concatenated.id, [1, 2, 3, 1, 2, 3]) - assert_array_equal(concatenated.test_str, ["a", "c", "d", "a", "c", "d"]) + assert_array_equal(concatenated["id"], [1, 2, 3, 1, 2, 3]) + assert_array_equal(concatenated["test_str"], ["a", "c", "d", "a", "c", "d"]) def test_concatenate_to_empty_array(self, fancy_test_array: FancyTestArray): empty_array = FancyTestArray() @@ -104,18 +104,18 @@ def test_concatenate_empty_arrays(self): assert concatenated.size == 0 def test_concatenate_multiple_fancy_arrays(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) concatenated = fp.concatenate(fancy_test_array, fancy_test_array, fancy_test_array) - assert_array_equal(concatenated.id, [1, 2, 3, 1, 2, 3, 1, 2, 3]) - assert_array_equal(concatenated.test_str, ["a", "c", "d", "a", "c", "d", "a", "c", "d"]) + assert_array_equal(concatenated["id"], [1, 2, 3, 1, 2, 3, 1, 2, 3]) + assert_array_equal(concatenated["test_str"], ["a", "c", "d", "a", "c", "d", "a", "c", "d"]) def test_concatenate_ndarray(self, fancy_test_array: FancyTestArray): - assert_array_equal(fancy_test_array.id, [1, 2, 3]) - assert_array_equal(fancy_test_array.test_str, ["a", "c", "d"]) + assert_array_equal(fancy_test_array["id"], [1, 2, 3]) + assert_array_equal(fancy_test_array["test_str"], ["a", "c", "d"]) concatenated = fp.concatenate(fancy_test_array, fancy_test_array.data) - assert_array_equal(concatenated.id, [1, 2, 3, 1, 2, 3]) - assert_array_equal(concatenated.test_str, ["a", "c", "d", "a", "c", "d"]) + assert_array_equal(concatenated["id"], [1, 2, 3, 1, 2, 3]) + assert_array_equal(concatenated["test_str"], ["a", "c", "d", "a", "c", "d"]) def test_concatenate_different_fancy_array(self, fancy_test_array: FancyTestArray): different_array = FancyNonIdArray.zeros(10) @@ -131,7 +131,7 @@ def test_concatenate_different_fancy_array_same_dtype(self, fancy_test_array: Fa sub_array = fancy_test_array[["test_str", "test_int"]] different_array = FancyNonIdArray.zeros(10) - different_sub_array = different_array[["test_str", "test_int"]] + different_sub_array = different_array.data[["test_str", "test_int"]] concatenated = np.concatenate([sub_array, different_sub_array]) assert concatenated.size == 13 diff --git a/tests/unit/model/arrays/test_pgm_arrays.py b/tests/unit/model/arrays/test_pgm_arrays.py index d9a6d96..1dc0e50 100644 --- a/tests/unit/model/arrays/test_pgm_arrays.py +++ b/tests/unit/model/arrays/test_pgm_arrays.py @@ -13,24 +13,24 @@ @pytest.fixture(name="branches") def parallel_branches(): branches = BranchArray.zeros(3) - branches.from_node = [0, 0, 1] - branches.to_node = [1, 1, 2] + branches["from_node"] = [0, 0, 1] + branches["to_node"] = [1, 1, 2] return branches class TestBranchArray: def test_branch_is_active(self): branches = BranchArray.zeros(4) - branches.from_status = [1, 1, 0, 0] - branches.to_status = [1, 0, 1, 0] + branches["from_status"] = [1, 1, 0, 0] + branches["to_status"] = [1, 0, 1, 0] assert_array_equal(branches.is_active, [True, False, False, False]) assert branches[0].is_active def test_branch_node_ids(self): branches = BranchArray.zeros(2) - branches.from_node = [0, 1] - branches.to_node = [1, 2] + branches["from_node"] = [0, 1] + branches["to_node"] = [1, 2] assert_array_equal(branches.node_ids, [0, 1, 1, 2]) @@ -58,10 +58,10 @@ def test_as_branches_single(self): assert branch_array.size == 3 - assert branch_array.from_node.tolist() == [1, 1, 2] - assert branch_array.to_node.tolist() == [2, 3, 3] - assert branch_array.from_status.tolist() == [1, 1, 1] - assert branch_array.to_status.tolist() == [1, 0, 0] + assert branch_array["from_node"].tolist() == [1, 1, 2] + assert branch_array["to_node"].tolist() == [2, 3, 3] + assert branch_array["from_status"].tolist() == [1, 1, 1] + assert branch_array["to_status"].tolist() == [1, 0, 0] def test_as_branches_multiple(self): branch3 = Branch3Array( @@ -77,7 +77,7 @@ def test_as_branches_multiple(self): branch_array.sort(order=["from_node", "to_node"]) assert branch_array.size == 6 - assert branch_array.from_node.tolist() == [1, 1, 2, 4, 4, 5] - assert branch_array.to_node.tolist() == [2, 3, 3, 5, 6, 6] - assert branch_array.from_status.tolist() == [1, 1, 1, 1, 1, 1] - assert branch_array.to_status.tolist() == [1, 1, 1, 1, 0, 0] + assert branch_array["from_node"].tolist() == [1, 1, 2, 4, 4, 5] + assert branch_array["to_node"].tolist() == [2, 3, 3, 5, 6, 6] + assert branch_array["from_status"].tolist() == [1, 1, 1, 1, 1, 1] + assert branch_array["to_status"].tolist() == [1, 1, 1, 1, 0, 0] diff --git a/tests/unit/model/arrays/test_string.py b/tests/unit/model/arrays/test_string.py index 60b4914..b9150d7 100644 --- a/tests/unit/model/arrays/test_string.py +++ b/tests/unit/model/arrays/test_string.py @@ -24,7 +24,7 @@ def test_str_empty_array(): def test_str_large_array(): array = FancyTestArray.zeros(100) - array.test_str = "ABC" + array["test_str"] = "ABC" array_str = str(array) splits = array_str.replace("\n", "|").split("|") @@ -44,8 +44,8 @@ def test_str_long_column_name(): def test_str_long_values(): array = FancyTestArray.zeros(1) - array.test_str = "this_is_a_very_long_value" - array.test_int = 112233445566778899 + array["test_str"] = "this_is_a_very_long_value" + array["test_int"] = 112233445566778899 array_str = array.as_table(column_width=15) splits = array_str.replace("\n", "|").split("|") @@ -63,8 +63,8 @@ def test_str_long_column_name_autosize(): def test_str_long_values_autosize(): array = FancyTestArray.zeros(1) - array.test_str = "this_is_a_very_long_value" - array.test_int = 112233445566778899 + array["test_str"] = "this_is_a_very_long_value" + array["test_int"] = 112233445566778899 array_str = str(array) assert "| this_is_a_very_long_value" in array_str assert "| 112233445566778899" in array_str diff --git a/tests/unit/model/graphs/test_container.py b/tests/unit/model/graphs/test_container.py index 0624a12..a664ce9 100644 --- a/tests/unit/model/graphs/test_container.py +++ b/tests/unit/model/graphs/test_container.py @@ -22,8 +22,8 @@ def test_from_arrays(basic_grid: Grid): assert basic_grid.graphs.active_graph.nr_nodes == graphs.active_graph.nr_nodes assert basic_grid.graphs.active_graph.nr_branches == 5 - assert set(basic_grid.node.id) == set(graphs.active_graph.external_ids) - assert set(basic_grid.node.id) == set(graphs.complete_graph.external_ids) + assert set(basic_grid.node["id"]) == set(graphs.active_graph.external_ids) + assert set(basic_grid.node["id"]) == set(graphs.complete_graph.external_ids) @pytest.fixture @@ -31,7 +31,7 @@ def graph_container_with_5_nodes(): graph_container = GraphContainer.empty() for node_id in range(1, 6): node = NodeArray.empty(1) - node.id = node_id + node["id"] = node_id graph_container.add_node_array(node) return graph_container @@ -39,13 +39,13 @@ def graph_container_with_5_nodes(): @pytest.fixture def three_winding_transformers(): three_winding_transformers = ThreeWindingTransformerArray.empty(2) - three_winding_transformers.id = [301, 302] - three_winding_transformers.node_1 = [1, 1] - three_winding_transformers.node_2 = [2, 4] - three_winding_transformers.node_3 = [3, 5] - three_winding_transformers.status_1 = [1, 1] - three_winding_transformers.status_2 = [1, 1] - three_winding_transformers.status_3 = [0, 1] + three_winding_transformers["id"] = [301, 302] + three_winding_transformers["node_1"] = [1, 1] + three_winding_transformers["node_2"] = [2, 4] + three_winding_transformers["node_3"] = [3, 5] + three_winding_transformers["status_1"] = [1, 1] + three_winding_transformers["status_2"] = [1, 1] + three_winding_transformers["status_3"] = [0, 1] return three_winding_transformers @@ -83,16 +83,16 @@ def test_delete_branch3( def test_from_arrays_active_three_winding(basic_grid: Grid): nodes = NodeArray.zeros(3) - nodes.id = [1000, 1001, 1002] + nodes["id"] = [1000, 1001, 1002] basic_grid.append(nodes) three_winding_transformer = ThreeWindingTransformerArray.zeros(1) - three_winding_transformer.node_1 = 1000 - three_winding_transformer.node_2 = 1001 - three_winding_transformer.node_3 = 1002 - three_winding_transformer.status_1 = 1 - three_winding_transformer.status_2 = 1 - three_winding_transformer.status_3 = 1 + three_winding_transformer["node_1"] = 1000 + three_winding_transformer["node_2"] = 1001 + three_winding_transformer["node_3"] = 1002 + three_winding_transformer["status_1"] = 1 + three_winding_transformer["status_2"] = 1 + three_winding_transformer["status_3"] = 1 basic_grid.append(three_winding_transformer) graphs = GraphContainer.from_arrays(basic_grid) @@ -105,16 +105,16 @@ def test_from_arrays_active_three_winding(basic_grid: Grid): def test_from_arrays_partially_active_three_winding(basic_grid: Grid): nodes = NodeArray.zeros(3) - nodes.id = [1000, 1001, 1002] + nodes["id"] = [1000, 1001, 1002] basic_grid.append(nodes) three_winding_transformer = ThreeWindingTransformerArray.zeros(1) - three_winding_transformer.node_1 = 1000 - three_winding_transformer.node_2 = 1001 - three_winding_transformer.node_3 = 1002 - three_winding_transformer.status_1 = 1 - three_winding_transformer.status_2 = 1 - three_winding_transformer.status_3 = 0 + three_winding_transformer["node_1"] = 1000 + three_winding_transformer["node_2"] = 1001 + three_winding_transformer["node_3"] = 1002 + three_winding_transformer["status_1"] = 1 + three_winding_transformer["status_2"] = 1 + three_winding_transformer["status_3"] = 0 basic_grid.append(three_winding_transformer) graphs = GraphContainer.from_arrays(basic_grid) diff --git a/tests/unit/model/graphs/test_graph_model.py b/tests/unit/model/graphs/test_graph_model.py index 0c3d149..a3b9f79 100644 --- a/tests/unit/model/graphs/test_graph_model.py +++ b/tests/unit/model/graphs/test_graph_model.py @@ -209,7 +209,7 @@ def test_get_components_with_tmp_removed_substation_nodes(graph_with_2_routes): def test_from_arrays(basic_grid: Grid): new_graph = basic_grid.graphs.complete_graph.__class__.from_arrays(basic_grid) - assert_array_equal(new_graph.external_ids, basic_grid.node.id) + assert_array_equal(new_graph.external_ids, basic_grid.node["id"]) class TestPathMethods: diff --git a/tests/unit/model/grids/test_custom_grid.py b/tests/unit/model/grids/test_custom_grid.py index 5b6ede8..680a9bc 100644 --- a/tests/unit/model/grids/test_custom_grid.py +++ b/tests/unit/model/grids/test_custom_grid.py @@ -36,10 +36,10 @@ def test_add_active_branch(): grid.append(nodes) line = CustomLineArray.zeros(1) - line.from_node = nodes[0].id - line.to_node = nodes[1].id - line.from_status = 1 - line.to_status = 1 + line["from_node"] = nodes["id"][0] + line["to_node"] = nodes["id"][1] + line["from_status"] = 1 + line["to_status"] = 1 assert 0 == grid.line.size grid.append(line) assert 1 == grid.line.size diff --git a/tests/unit/model/grids/test_grid_base.py b/tests/unit/model/grids/test_grid_base.py index 1527a80..be7c371 100644 --- a/tests/unit/model/grids/test_grid_base.py +++ b/tests/unit/model/grids/test_grid_base.py @@ -77,7 +77,7 @@ def test_grid_build(basic_grid: Grid): # 4 of these have a load attaches assert 4 == len(grid.sym_load) - inactive_mask = np.logical_or(grid.line.from_status == 0, grid.line.to_status == 0) + inactive_mask = np.logical_or(grid.line["from_status"] == 0, grid.line["to_status"] == 0) inactive_lines = grid.line[inactive_mask] # we have placed 1 normally open point assert 1 == len(inactive_lines) @@ -90,7 +90,7 @@ def test_grid_build(basic_grid: Grid): assert nr_branches == grid.graphs.complete_graph.nr_branches assert nr_branches - 1 == grid.graphs.active_graph.nr_branches - inactive_mask = np.logical_or(grid.line.from_status == 0, grid.line.to_status == 0) + inactive_mask = np.logical_or(grid.line["from_status"] == 0, grid.line["to_status"] == 0) inactive_lines = grid.line[inactive_mask] # we have placed 1 normally open point assert 1 == len(inactive_lines) @@ -106,8 +106,8 @@ def test_grid_add_node(basic_grid: Grid): grid.add_node(node=new_node) assert 7 == len(grid.node) - assert EMPTY_ID not in grid.node.id - assert grid.node[-1].id.item() in grid.graphs.complete_graph.external_ids + assert EMPTY_ID not in grid.node["id"] + assert grid.node[-1]["id"].item() in grid.graphs.complete_graph.external_ids assert EMPTY_ID not in grid.graphs.complete_graph.external_ids @@ -118,7 +118,7 @@ def test_grid_delete_node(basic_grid: Grid): grid.delete_node(node=target_node) assert 5 == len(grid.node) - assert target_node.id not in grid.node.id + assert target_node["id"] not in grid.node["id"] # pylint: disable=no-member @@ -126,15 +126,15 @@ def test_grid_add_line(basic_grid: Grid): grid = basic_grid line = LineArray.zeros(1) - line.from_node = 102 - line.to_node = 105 + line["from_node"] = 102 + line["to_node"] = 105 assert not grid.graphs.complete_graph.has_branch(102, 105) grid.add_branch(branch=line) assert 5 == len(grid.line) - assert EMPTY_ID not in grid.line.id + assert EMPTY_ID not in grid.line["id"] assert grid.graphs.complete_graph.has_branch(102, 105) @@ -143,36 +143,36 @@ def test_grid_delete_line(basic_grid: Grid): line = grid.line.get(201) - assert grid.graphs.complete_graph.has_branch(line.from_node.item(), line.to_node.item()) + assert grid.graphs.complete_graph.has_branch(line["from_node"].item(), line["to_node"].item()) grid.delete_branch(branch=line) assert 3 == len(grid.line) - assert line.id not in grid.line.id + assert line["id"] not in grid.line["id"] - assert not grid.graphs.complete_graph.has_branch(line.from_node.item(), line.to_node.item()) + assert not grid.graphs.complete_graph.has_branch(line["from_node"].item(), line["to_node"].item()) def test_grid_delete_inactive_line(basic_grid: Grid): grid = basic_grid - inactive_mask = grid.line.from_status == 0 + inactive_mask = grid.line["from_status"] == 0 target_line = grid.line[inactive_mask] - assert grid.graphs.complete_graph.has_branch(target_line.from_node.item(), target_line.to_node.item()) + assert grid.graphs.complete_graph.has_branch(target_line["from_node"].item(), target_line["to_node"].item()) grid.delete_branch(branch=target_line) assert 3 == len(grid.line) - assert target_line.id not in grid.line.id + assert target_line["id"] not in grid.line["id"] - assert not grid.graphs.complete_graph.has_branch(target_line.from_node.item(), target_line.to_node.item()) + assert not grid.graphs.complete_graph.has_branch(target_line["from_node"].item(), target_line["to_node"].item()) def test_grid_delete_transformer_with_regulator(basic_grid: Grid): grid = basic_grid transformer_regulator = TransformerTapRegulatorArray.zeros(1) - transformer_regulator.regulated_object = 301 + transformer_regulator["regulated_object"] = 301 grid.append(transformer_regulator) assert 1 == len(grid.transformer_tap_regulator) @@ -181,21 +181,21 @@ def test_grid_delete_transformer_with_regulator(basic_grid: Grid): grid.delete_branch(branch=transformer) assert 0 == len(grid.transformer) - assert transformer.id not in grid.transformer.id + assert transformer["id"] not in grid.transformer["id"] def test_grid_add_link(basic_grid: Grid): grid = basic_grid new_link_array = LinkArray.zeros(1) - new_link_array.from_node = 105 - new_link_array.to_node = 103 + new_link_array["from_node"] = 105 + new_link_array["to_node"] = 103 assert 1 == len(grid.link) assert not grid.graphs.complete_graph.has_branch(105, 103) grid.add_branch(new_link_array) assert 2 == len(grid.link) - assert EMPTY_ID not in grid.link.id + assert EMPTY_ID not in grid.link["id"] assert grid.graphs.complete_graph.has_branch(105, 103) @@ -203,14 +203,14 @@ def test_grid_add_tranformer(basic_grid: Grid): grid = basic_grid new_transformer_array = TransformerArray.zeros(1) - new_transformer_array.from_node = 105 - new_transformer_array.to_node = 103 + new_transformer_array["from_node"] = 105 + new_transformer_array["to_node"] = 103 assert 1 == len(grid.transformer) assert not grid.graphs.complete_graph.has_branch(105, 103) grid.add_branch(new_transformer_array) assert 2 == len(grid.transformer) - assert EMPTY_ID not in grid.transformer.id + assert EMPTY_ID not in grid.transformer["id"] assert grid.graphs.complete_graph.has_branch(105, 103) @@ -218,29 +218,29 @@ def test_grid_delete_tranformer(basic_grid: Grid): grid = basic_grid transformer = grid.transformer.get(301) - assert grid.graphs.complete_graph.has_branch(transformer.from_node.item(), transformer.to_node.item()) + assert grid.graphs.complete_graph.has_branch(transformer["from_node"].item(), transformer["to_node"].item()) grid.delete_branch(branch=transformer) assert 0 == len(grid.transformer) - assert transformer.id not in grid.transformer.id + assert transformer["id"] not in grid.transformer["id"] - assert not grid.graphs.complete_graph.has_branch(transformer.from_node.item(), transformer.to_node.item()) + assert not grid.graphs.complete_graph.has_branch(transformer["from_node"].item(), transformer["to_node"].item()) def test_grid_add_three_winding_transformer(): grid = Grid.empty() nodes = NodeArray.zeros(3) - nodes.id = [102, 103, 104] + nodes["id"] = [102, 103, 104] grid.append(nodes) three_winding_transformer = ThreeWindingTransformerArray.zeros(1) - three_winding_transformer.node_1 = 102 - three_winding_transformer.node_2 = 103 - three_winding_transformer.node_3 = 104 - three_winding_transformer.status_1 = 1 - three_winding_transformer.status_2 = 1 - three_winding_transformer.status_3 = 1 + three_winding_transformer["node_1"] = 102 + three_winding_transformer["node_2"] = 103 + three_winding_transformer["node_3"] = 104 + three_winding_transformer["status_1"] = 1 + three_winding_transformer["status_2"] = 1 + three_winding_transformer["status_3"] = 1 grid.append(three_winding_transformer) assert 1 == len(grid.three_winding_transformer) @@ -268,32 +268,32 @@ def test_grid_activate_branch(basic_grid: Grid): grid = basic_grid line = grid.line.get(203) - assert line.from_status == 0 or line.to_status == 0 + assert line["from_status"] == 0 or line["to_status"] == 0 - assert not grid.graphs.active_graph.has_branch(line.from_node.item(), line.to_node.item()) + assert not grid.graphs.active_graph.has_branch(line["from_node"].item(), line["to_node"].item()) grid.make_active(branch=line) - assert grid.graphs.active_graph.has_branch(line.from_node.item(), line.to_node.item()) + assert grid.graphs.active_graph.has_branch(line["from_node"].item(), line["to_node"].item()) target_line_after = grid.line.get(203) - assert target_line_after.from_status == 1 - assert target_line_after.to_status == 1 + assert target_line_after["from_status"] == 1 + assert target_line_after["to_status"] == 1 def test_grid_inactivate_branch(basic_grid: Grid): grid = basic_grid target_line = grid.line.get(202) - assert target_line.from_status == 1 and target_line.to_status == 1 + assert target_line["from_status"] == 1 and target_line["to_status"] == 1 grid.make_inactive(branch=target_line) target_line_after = grid.line.get(202) - assert target_line_after.from_status == 1 - assert target_line_after.to_status == 0 + assert target_line_after["from_status"] == 1 + assert target_line_after["to_status"] == 0 graph = grid.graphs.active_graph - assert not graph.has_branch(target_line.from_node.item(), target_line.to_node.item()) + assert not graph.has_branch(target_line["from_node"].item(), target_line["to_node"].item()) def test_grid_make_inactive_from_side(basic_grid: Grid): @@ -301,11 +301,11 @@ def test_grid_make_inactive_from_side(basic_grid: Grid): target_line = grid.line.get(202) # line 7 is expected to be active - assert target_line.from_status == 1 and target_line.to_status == 1 + assert target_line["from_status"] == 1 and target_line["to_status"] == 1 grid.make_inactive(branch=target_line, at_to_side=False) target_line_after = grid.line.get(202) - assert 0 == target_line_after.from_status + assert 0 == target_line_after["from_status"] def test_grid_make_inactive_to_side(basic_grid: Grid): @@ -313,11 +313,11 @@ def test_grid_make_inactive_to_side(basic_grid: Grid): target_line = grid.line.get(202) # line 7 is expected to be active - assert target_line.from_status == 1 and target_line.to_status == 1 + assert target_line["from_status"] == 1 and target_line["to_status"] == 1 grid.make_inactive(branch=target_line) target_line_after = grid.line.get(202) - assert 0 == target_line_after.to_status + assert 0 == target_line_after["to_status"] def test_grid_as_str(basic_grid: Grid): @@ -344,7 +344,7 @@ def test_from_txt_lines(self): assert 8 == grid.node.size 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) + np.testing.assert_array_equal([14, 10, 11, 12, 13, 15, 16, 17], grid.branches["id"]) def test_from_txt_string(self): txt_string = "S1 2\nS1 3 open\n2 7\n3 5\n3 6 transformer\n5 7\n7 8\n8 9" @@ -373,7 +373,7 @@ def test_from_txt_with_branch_ids(self): assert 8 == grid.node.size assert 1 == grid.branches.filter(to_status=0).size assert 1 == grid.transformer.size - np.testing.assert_array_equal([95, 91, 92, 93, 94, 96, 97, 98], grid.branches.id) + np.testing.assert_array_equal([95, 91, 92, 93, 94, 96, 97, 98], grid.branches["id"]) def test_from_txt_with_conflicting_ids(self): with pytest.raises(ValueError): @@ -400,4 +400,4 @@ def test_from_txt_file(self, tmp_path: Path): assert 8 == grid.node.size 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) + np.testing.assert_array_equal([14, 10, 11, 12, 13, 15, 16, 17], grid.branches["id"]) diff --git a/tests/unit/model/grids/test_grid_search.py b/tests/unit/model/grids/test_grid_search.py index f42891b..acdb80a 100644 --- a/tests/unit/model/grids/test_grid_search.py +++ b/tests/unit/model/grids/test_grid_search.py @@ -14,7 +14,7 @@ def test_grid_get_nearest_substation_node(basic_grid): substation_node = basic_grid.get_nearest_substation_node(node_id=103) - assert NodeType.SUBSTATION_NODE == substation_node.node_type + assert NodeType.SUBSTATION_NODE == substation_node["node_type"] def test_grid_get_nearest_substation_node_no_substation(basic_grid): @@ -40,12 +40,12 @@ def test_get_downstream_nodes_from_substation_node(self): class TestGetBranchesInPath: def test_get_branches_in_path(self, basic_grid): branches = basic_grid.get_branches_in_path([106, 102, 101]) - np.testing.assert_array_equal(branches.id, [301, 201]) + np.testing.assert_array_equal(branches["id"], [301, 201]) def test_get_branches_in_path_inactive(self, basic_grid): branches = basic_grid.get_branches_in_path([101, 102, 103, 104, 105]) # branch 203 is the normally open point should not be in the result - np.testing.assert_array_equal(branches.id, [201, 202, 204, 601]) + np.testing.assert_array_equal(branches["id"], [201, 202, 204, 601]) def test_get_branches_in_path_one_node(self, basic_grid): branches = basic_grid.get_branches_in_path([106]) @@ -57,7 +57,7 @@ def test_get_branches_in_path_empty_path(self, basic_grid): def test_component_three_winding_transformer(grid_with_3wt): - substation_nodes = grid_with_3wt.node.filter(node_type=NodeType.SUBSTATION_NODE.value).id + substation_nodes = grid_with_3wt.node.filter(node_type=NodeType.SUBSTATION_NODE.value)["id"] with grid_with_3wt.graphs.active_graph.tmp_remove_nodes(substation_nodes): component_list = grid_with_3wt.graphs.active_graph.get_components() diff --git a/tests/unit/model/grids/test_helpers.py b/tests/unit/model/grids/test_helpers.py index afd5b48..a478f27 100644 --- a/tests/unit/model/grids/test_helpers.py +++ b/tests/unit/model/grids/test_helpers.py @@ -16,18 +16,18 @@ def test_set_feeder_ids(grid): grid = build_basic_grid(grid=grid) # Set all feeder ids to a value to check they have been reset - grid.branches.feeder_branch_id = 1 - grid.node.feeder_branch_id = 1 - grid.branches.feeder_node_id = 1 - grid.node.feeder_node_id = 1 + grid.branches["feeder_branch_id"] = 1 + grid.node["feeder_branch_id"] = 1 + grid.branches["feeder_node_id"] = 1 + grid.node["feeder_node_id"] = 1 grid.set_feeder_ids() - assert_array_equal(grid.branches.is_feeder, np.array([False, True, False, False, True, False])) - assert_array_equal(grid.branches.feeder_branch_id, np.array([201, 201, 201, EMPTY_ID, 204, 204])) - assert_array_equal(grid.node.feeder_branch_id, np.array([EMPTY_ID, 201, 201, 204, 204, 201])) - assert_array_equal(grid.branches.feeder_node_id, np.array([101, 101, 101, EMPTY_ID, 101, 101])) - assert_array_equal(grid.node.feeder_node_id, np.array([EMPTY_ID, 101, 101, 101, 101, 101])) + assert_array_equal(grid.branches["is_feeder"], np.array([False, True, False, False, True, False])) + assert_array_equal(grid.branches["feeder_branch_id"], np.array([201, 201, 201, EMPTY_ID, 204, 204])) + assert_array_equal(grid.node["feeder_branch_id"], np.array([EMPTY_ID, 201, 201, 204, 204, 201])) + assert_array_equal(grid.branches["feeder_node_id"], np.array([101, 101, 101, EMPTY_ID, 101, 101])) + assert_array_equal(grid.node["feeder_node_id"], np.array([EMPTY_ID, 101, 101, 101, 101, 101])) def test_set_feeder_ids_unconnected_node(grid): @@ -37,11 +37,11 @@ def test_set_feeder_ids_unconnected_node(grid): grid.append(extra_node) grid.set_feeder_ids() - assert_array_equal(grid.branches.is_feeder, np.array([False, True, False, False, True, False])) - assert_array_equal(grid.branches.feeder_branch_id, np.array([201, 201, 201, EMPTY_ID, 204, 204])) - assert_array_equal(grid.node.feeder_branch_id, np.array([EMPTY_ID, 201, 201, 204, 204, 201, EMPTY_ID])) - assert_array_equal(grid.branches.feeder_node_id, np.array([101, 101, 101, EMPTY_ID, 101, 101])) - assert_array_equal(grid.node.feeder_node_id, np.array([EMPTY_ID, 101, 101, 101, 101, 101, EMPTY_ID])) + assert_array_equal(grid.branches["is_feeder"], np.array([False, True, False, False, True, False])) + assert_array_equal(grid.branches["feeder_branch_id"], np.array([201, 201, 201, EMPTY_ID, 204, 204])) + assert_array_equal(grid.node["feeder_branch_id"], np.array([EMPTY_ID, 201, 201, 204, 204, 201, EMPTY_ID])) + assert_array_equal(grid.branches["feeder_node_id"], np.array([101, 101, 101, EMPTY_ID, 101, 101])) + assert_array_equal(grid.node["feeder_node_id"], np.array([EMPTY_ID, 101, 101, 101, 101, 101, EMPTY_ID])) def test_set_feeder_ids_parallel_line(grid): @@ -50,19 +50,19 @@ def test_set_feeder_ids_parallel_line(grid): # Add a second (parallel) line from 101 to 102 extra_line = LineArray.empty(1) - extra_line.from_node = 101 - extra_line.to_node = 102 - extra_line.from_status = 1 - extra_line.to_status = 1 + extra_line["from_node"] = 101 + extra_line["to_node"] = 102 + extra_line["from_status"] = 1 + extra_line["to_status"] = 1 grid.append(extra_line) grid.set_feeder_ids() - assert_array_equal(grid.branches.is_feeder, np.array([False, True, False, False, True, True, False])) - assert_array_equal(grid.branches.feeder_branch_id, np.array([201, 201, 201, EMPTY_ID, 204, 201, 204])) - assert_array_equal(grid.node.feeder_branch_id, np.array([EMPTY_ID, 201, 201, 204, 204, 201])) - assert_array_equal(grid.branches.feeder_node_id, np.array([101, 101, 101, EMPTY_ID, 101, 101, 101])) - assert_array_equal(grid.node.feeder_node_id, np.array([EMPTY_ID, 101, 101, 101, 101, 101])) + assert_array_equal(grid.branches["is_feeder"], np.array([False, True, False, False, True, True, False])) + assert_array_equal(grid.branches["feeder_branch_id"], np.array([201, 201, 201, EMPTY_ID, 204, 201, 204])) + assert_array_equal(grid.node["feeder_branch_id"], np.array([EMPTY_ID, 201, 201, 204, 204, 201])) + assert_array_equal(grid.branches["feeder_node_id"], np.array([101, 101, 101, EMPTY_ID, 101, 101, 101])) + assert_array_equal(grid.node["feeder_node_id"], np.array([EMPTY_ID, 101, 101, 101, 101, 101])) def test_set_feeder_ids_inactive(grid): @@ -74,11 +74,11 @@ def test_set_feeder_ids_inactive(grid): grid.set_feeder_ids() - assert_array_equal(grid.branches.is_feeder, np.array([False, True, False, False, True, False])) - assert_array_equal(grid.branches.feeder_branch_id, np.array([201, 201, 201, 201, EMPTY_ID, 201])) - assert_array_equal(grid.node.feeder_branch_id, np.array([EMPTY_ID, 201, 201, 201, 201, 201])) - assert_array_equal(grid.branches.feeder_node_id, np.array([101, 101, 101, 101, EMPTY_ID, 101])) - assert_array_equal(grid.node.feeder_node_id, np.array([EMPTY_ID, 101, 101, 101, 101, 101])) + assert_array_equal(grid.branches["is_feeder"], np.array([False, True, False, False, True, False])) + assert_array_equal(grid.branches["feeder_branch_id"], np.array([201, 201, 201, 201, EMPTY_ID, 201])) + assert_array_equal(grid.node["feeder_branch_id"], np.array([EMPTY_ID, 201, 201, 201, 201, 201])) + assert_array_equal(grid.branches["feeder_node_id"], np.array([101, 101, 101, 101, EMPTY_ID, 101])) + assert_array_equal(grid.node["feeder_node_id"], np.array([EMPTY_ID, 101, 101, 101, 101, 101])) def test_set_feeder_to_node(grid): @@ -96,17 +96,17 @@ def test_set_feeder_to_node(grid): # Add Lines lines = LineArray.empty(2) - lines.id = [200, 201] - lines.from_status = [1] * 2 - lines.to_status = [1] * 2 - lines.from_node = [100, 102] - lines.to_node = [101, 101] + lines["id"] = [200, 201] + lines["from_status"] = [1] * 2 + lines["to_status"] = [1] * 2 + lines["from_node"] = [100, 102] + lines["to_node"] = [101, 101] grid.append(lines, check_max_id=False) grid.set_feeder_ids() - assert_array_equal(grid.branches.is_feeder, np.array([False, True])) - assert_array_equal(grid.branches.feeder_branch_id, np.array([EMPTY_ID, 201])) - assert_array_equal(grid.node.feeder_branch_id, np.array([EMPTY_ID, EMPTY_ID, 201])) - assert_array_equal(grid.branches.feeder_node_id, np.array([EMPTY_ID, 101])) - assert_array_equal(grid.node.feeder_node_id, np.array([EMPTY_ID, EMPTY_ID, 101])) + assert_array_equal(grid.branches["is_feeder"], np.array([False, True])) + assert_array_equal(grid.branches["feeder_branch_id"], np.array([EMPTY_ID, 201])) + assert_array_equal(grid.node["feeder_branch_id"], np.array([EMPTY_ID, EMPTY_ID, 201])) + assert_array_equal(grid.branches["feeder_node_id"], np.array([EMPTY_ID, 101])) + assert_array_equal(grid.node["feeder_node_id"], np.array([EMPTY_ID, EMPTY_ID, 101])) diff --git a/tests/unit/model/test_containers.py b/tests/unit/model/test_containers.py index f83d781..548d4c5 100644 --- a/tests/unit/model/test_containers.py +++ b/tests/unit/model/test_containers.py @@ -47,10 +47,10 @@ def test_deepcopy(): copied_container = deepcopy(container) - assert container.node.id == copied_container.node.id - assert container.line.id == copied_container.line.id - assert container.transformer.id == copied_container.transformer.id - assert container.link.id == copied_container.link.id + assert container.node["id"] == copied_container.node["id"] + assert container.line["id"] == copied_container.line["id"] + assert container.transformer["id"] == copied_container.transformer["id"] + assert container.link["id"] == copied_container.link["id"] def test_all_arrays(): @@ -82,9 +82,9 @@ def test_check_ids_4_arrays_3_with_id(): def test_check_ids_two_arrays_no_conflicts(): container = _TwoArraysContainer.empty() container.array_1 = IdArray.zeros(1) - container.array_1.id = 1 + container.array_1["id"] = 1 container.array_2 = IdArray.zeros(1) - container.array_1.id = 2 + container.array_1["id"] = 2 assert 2 == len(list(container.all_arrays())) container.check_ids() @@ -93,9 +93,9 @@ def test_check_ids_two_arrays_no_conflicts(): def test_check_ids_two_arrays_with_conflict(): container = _TwoArraysContainer.empty() container.array_1 = IdArray.zeros(1) - container.array_1.id = 1 + container.array_1["id"] = 1 container.array_2 = IdArray.zeros(1) - container.array_2.id = 1 + container.array_2["id"] = 1 assert 2 == len(list(container.all_arrays())) @@ -106,9 +106,9 @@ def test_check_ids_two_arrays_with_conflict(): def test_check_ids_two_arrays_with_conflict_in_same_array(): container = _TwoArraysContainer.empty() container.array_1 = IdArray.zeros(2) - container.array_1.id = [1, 1] + container.array_1["id"] = [1, 1] container.array_2 = IdArray.zeros(1) - container.array_2.id = 2 + container.array_2["id"] = 2 assert 2 == len(list(container.all_arrays())) @@ -125,10 +125,10 @@ def test_search_for_id_no_arrays(): def test_search_for_id_match_in_two_arrays(): container = Grid.empty() container.node = NodeArray.zeros(1) - container.node.id = 42 + container.node["id"] = 42 container.line = LineArray.zeros(1) - container.line.id = 42 + container.line["id"] = 42 result = container.search_for_id(42) expected_result = [container.node[0:1], container.line[0:1]] @@ -139,10 +139,10 @@ def test_search_for_id_match_in_two_arrays(): def test_search_for_id_no_match_in_two_arrays(): container = Grid.empty() container.node = NodeArray.zeros(1) - container.node.id = 41 + container.node["id"] = 41 container.line = LineArray.zeros(1) - container.line.id = 42 + container.line["id"] = 42 with pytest.raises(RecordDoesNotExist): container.search_for_id(43) @@ -161,12 +161,12 @@ def test_append_with_overlapping_ids(): # Create first array with IDs [1, 2, 3] nodes_1 = NodeArray.zeros(3) - nodes_1.id = [1, 2, 3] + nodes_1["id"] = [1, 2, 3] grid.append(nodes_1) # Create second array with overlapping IDs [3, 4, 5] (ID 3 overlaps) nodes_2 = NodeArray.zeros(3) - nodes_2.id = [3, 4, 5] + nodes_2["id"] = [3, 4, 5] # This should raise a ValueError due to overlapping ID 3 with pytest.raises(ValueError, match="Cannot append: minimum id 3 is not greater than the current id counter 3"): @@ -179,12 +179,12 @@ def test_append_with_non_overlapping_ids(): # Create first array with IDs [1, 2, 3] nodes_1 = NodeArray.zeros(3) - nodes_1.id = [1, 2, 3] + nodes_1["id"] = [1, 2, 3] grid.append(nodes_1) # Create second array with non-overlapping IDs [4, 5, 6] nodes_2 = NodeArray.zeros(3) - nodes_2.id = [4, 5, 6] + nodes_2["id"] = [4, 5, 6] # This should work without error grid.append(nodes_2) @@ -192,7 +192,7 @@ def test_append_with_non_overlapping_ids(): # Verify all nodes are in the grid assert grid.node.size == 6 expected_ids = [1, 2, 3, 4, 5, 6] - assert sorted(grid.node.id.tolist()) == expected_ids + assert sorted(grid.node["id"].tolist()) == expected_ids def test_branches(grid: Grid): @@ -201,16 +201,16 @@ def test_branches(grid: Grid): for branch_class in (LineArray, TransformerArray, LinkArray): branches = branch_class.zeros(10) - branches.from_node = nodes.id - branches.to_node = list(reversed(nodes.id.tolist())) + branches["from_node"] = nodes["id"] + branches["to_node"] = list(reversed(nodes["id"].tolist())) grid.append(branches) - expected_ids = np.concatenate((grid.line.id, grid.transformer.id, grid.link.id)) - assert set(expected_ids) == set(grid.branches.id) + expected_ids = np.concatenate((grid.line["id"], grid.transformer["id"], grid.link["id"])) + assert set(expected_ids) == set(grid.branches["id"]) def test_delete_node_without_additional_properties(basic_grid: Grid): - assert 106 in basic_grid.node.id + assert 106 in basic_grid.node["id"] assert 106 in basic_grid.transformer["to_node"] original_grid = deepcopy(basic_grid) @@ -218,35 +218,35 @@ def test_delete_node_without_additional_properties(basic_grid: Grid): basic_grid.delete_node(node) assert 106 not in basic_grid.transformer["to_node"] - assert 106 not in basic_grid.node.id + assert 106 not in basic_grid.node["id"] assert len(original_grid.node) == len(basic_grid.node) + 1 assert len(original_grid.transformer) == len(basic_grid.transformer) + 1 def test_delete_node_with_source(basic_grid: Grid): - assert 101 in basic_grid.node.id - assert 101 in basic_grid.source.node + assert 101 in basic_grid.node["id"] + assert 101 in basic_grid.source["node"] original_grid = deepcopy(basic_grid) node = basic_grid.node.get(id=101) basic_grid.delete_node(node) - assert 101 not in basic_grid.node.id - assert 101 not in basic_grid.source.node + assert 101 not in basic_grid.node["id"] + assert 101 not in basic_grid.source["node"] assert len(original_grid.node) == len(basic_grid.node) + 1 assert len(original_grid.source) == len(basic_grid.source) + 1 def test_delete_node_with_load(basic_grid: Grid): - assert 102 in basic_grid.node.id - assert 102 in basic_grid.sym_load.node + assert 102 in basic_grid.node["id"] + assert 102 in basic_grid.sym_load["node"] original_grid = deepcopy(basic_grid) node = basic_grid.node.get(id=102) basic_grid.delete_node(node) - assert 102 not in basic_grid.node.id - assert 102 not in basic_grid.sym_load.node + assert 102 not in basic_grid.node["id"] + assert 102 not in basic_grid.sym_load["node"] assert len(original_grid.node) == len(basic_grid.node) + 1 assert len(original_grid.sym_load) == len(basic_grid.sym_load) + 1 @@ -302,9 +302,9 @@ def test_reverse_line(self, basic_grid: Grid): new_line = basic_grid.line.get(from_node=103, to_node=102) - assert new_line.from_node == line.to_node - assert new_line.to_node == line.from_node - assert new_line.id == line.id + assert new_line["from_node"] == line["to_node"] + assert new_line["to_node"] == line["from_node"] + assert new_line["id"] == line["id"] def test_reverse_branch(self, basic_grid: Grid): branch = basic_grid.branches.get(from_node=101, to_node=102) @@ -315,18 +315,18 @@ def test_reverse_branch(self, basic_grid: Grid): new_branch = basic_grid.line.get(from_node=102, to_node=101) - assert new_branch.from_node == branch.to_node - assert new_branch.to_node == branch.from_node - assert new_branch.id == branch.id + assert new_branch["from_node"] == branch["to_node"] + assert new_branch["to_node"] == branch["from_node"] + assert new_branch["id"] == branch["id"] def test_reverse_all_branches(self, basic_grid: Grid): - from_nodes = basic_grid.branches.from_node - to_nodes = basic_grid.branches.to_node + from_nodes = basic_grid.branches["from_node"] + to_nodes = basic_grid.branches["to_node"] basic_grid.reverse_branches(basic_grid.branches) - assert np.all(from_nodes == basic_grid.branches.to_node) - assert np.all(to_nodes == basic_grid.branches.from_node) + assert np.all(from_nodes == basic_grid.branches["to_node"]) + assert np.all(to_nodes == basic_grid.branches["from_node"]) def test_reverse_no_branches(self, basic_grid: Grid): basic_grid.reverse_branches(BranchArray())