From 142a9e10dadabc676c1ed5787c85b38f17066dab Mon Sep 17 00:00:00 2001 From: Saelyos Date: Mon, 7 Aug 2023 12:18:29 +0200 Subject: [PATCH 1/4] Make geometry optional in dict --- roseau/load_flow/io/dict.py | 9 ++-- roseau/load_flow/io/tests/test_dict.py | 44 ++++++++++++++----- roseau/load_flow/models/branches.py | 4 +- roseau/load_flow/models/buses.py | 4 +- roseau/load_flow/models/grounds.py | 2 +- roseau/load_flow/models/lines/lines.py | 4 +- roseau/load_flow/models/lines/parameters.py | 2 +- .../models/loads/flexible_parameters.py | 6 +-- roseau/load_flow/models/loads/loads.py | 6 +-- roseau/load_flow/models/potential_refs.py | 2 +- roseau/load_flow/models/sources.py | 2 +- .../models/transformers/parameters.py | 2 +- .../models/transformers/transformers.py | 4 +- roseau/load_flow/network.py | 13 ++++-- roseau/load_flow/utils/mixins.py | 9 +++- 15 files changed, 74 insertions(+), 39 deletions(-) diff --git a/roseau/load_flow/io/dict.py b/roseau/load_flow/io/dict.py index f713f0ef..81e4ba8c 100644 --- a/roseau/load_flow/io/dict.py +++ b/roseau/load_flow/io/dict.py @@ -132,13 +132,16 @@ def network_from_dict( return buses, branches_dict, loads, sources, grounds, potential_refs -def network_to_dict(en: "ElectricalNetwork") -> JsonDict: +def network_to_dict(en: "ElectricalNetwork", geometry: bool) -> JsonDict: """Return a dictionary of the current network data. Args: en: The electrical network. + geometry: + If False, the geometry will not be added to the result dictionary. + Returns: The created dictionary. """ @@ -152,7 +155,7 @@ def network_to_dict(en: "ElectricalNetwork") -> JsonDict: sources: list[JsonDict] = [] short_circuits: list[JsonDict] = [] for bus in en.buses.values(): - buses.append(bus.to_dict()) + buses.append(bus.to_dict(geometry=geometry)) for element in bus._connected_elements: if isinstance(element, AbstractLoad): assert element.bus is bus @@ -168,7 +171,7 @@ def network_to_dict(en: "ElectricalNetwork") -> JsonDict: lines_params_dict: dict[Id, LineParameters] = {} transformers_params_dict: dict[Id, TransformerParameters] = {} for branch in en.branches.values(): - branches.append(branch.to_dict()) + branches.append(branch.to_dict(geometry=geometry)) if isinstance(branch, Line): params_id = branch.parameters.id if params_id in lines_params_dict and branch.parameters != lines_params_dict[params_id]: diff --git a/roseau/load_flow/io/tests/test_dict.py b/roseau/load_flow/io/tests/test_dict.py index d4a1725c..6c1c6643 100644 --- a/roseau/load_flow/io/tests/test_dict.py +++ b/roseau/load_flow/io/tests/test_dict.py @@ -1,6 +1,6 @@ import numpy as np import pytest -from shapely import Point +from shapely import LineString, Point from roseau.load_flow import Line from roseau.load_flow.exceptions import RoseauLoadFlowException, RoseauLoadFlowExceptionCode @@ -23,8 +23,8 @@ def test_to_dict(): ground = Ground("ground") vn = 400 / np.sqrt(3) voltages = [vn, vn * np.exp(-2 / 3 * np.pi * 1j), vn * np.exp(2 / 3 * np.pi * 1j)] - source_bus = Bus(id="source", phases="abcn") - load_bus = Bus(id="load bus", phases="abcn") + source_bus = Bus(id="source", phases="abcn", geometry=Point(0.0, 0.0)) + load_bus = Bus(id="load bus", phases="abcn", geometry=Point(0.0, 1.0)) ground.connect(load_bus) p_ref = PotentialRef("pref", element=ground) vs = VoltageSource("vs", source_bus, phases="abcn", voltages=voltages) @@ -33,8 +33,9 @@ def test_to_dict(): lp1 = LineParameters("test", z_line=np.eye(4, dtype=complex), y_shunt=np.eye(4, dtype=complex)) lp2 = LineParameters("test", z_line=np.eye(4, dtype=complex), y_shunt=np.eye(4, dtype=complex) * 1.1) - line1 = Line("line1", source_bus, load_bus, phases="abcn", ground=ground, parameters=lp1, length=10) - line2 = Line("line2", source_bus, load_bus, phases="abcn", ground=ground, parameters=lp2, length=10) + geom = LineString([(0.0, 0.0), (0.0, 1.0)]) + line1 = Line("line1", source_bus, load_bus, phases="abcn", ground=ground, parameters=lp1, length=10, geometry=geom) + line2 = Line("line2", source_bus, load_bus, phases="abcn", ground=ground, parameters=lp2, length=10, geometry=geom) en = ElectricalNetwork( buses=[source_bus, load_bus], branches=[line1, line2], @@ -51,14 +52,25 @@ def test_to_dict(): # Same id, same line parameters -> ok lp2 = LineParameters("test", z_line=np.eye(4, dtype=complex), y_shunt=np.eye(4, dtype=complex)) line2.parameters = lp2 - en.to_dict() + res = en.to_dict() + assert "geometry" in res["buses"][0] + assert "geometry" in res["buses"][1] + assert "geometry" in res["branches"][0] + assert "geometry" in res["branches"][1] + + res = en.to_dict(geometry=False) + assert "geometry" not in res["buses"][0] + assert "geometry" not in res["buses"][1] + assert "geometry" not in res["branches"][0] + assert "geometry" not in res["branches"][1] # Same id, different transformer parameters -> fail ground = Ground("ground") vn = 400 / np.sqrt(3) voltages = [vn, vn * np.exp(-2 / 3 * np.pi * 1j), vn * np.exp(2 / 3 * np.pi * 1j)] - source_bus = Bus(id="source", phases="abcn") - load_bus = Bus(id="load bus", phases="abcn") + geom = Point(0.0, 0.0) + source_bus = Bus(id="source", phases="abcn", geometry=geom) + load_bus = Bus(id="load bus", phases="abcn", geometry=geom) ground.connect(load_bus) ground.connect(source_bus) p_ref = PotentialRef("pref", element=ground) @@ -71,8 +83,8 @@ def test_to_dict(): tp2 = TransformerParameters( "t", type="Dyn11", uhv=20000, ulv=400, sn=200 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100 ) - transformer1 = Transformer(id="Transformer1", bus1=source_bus, bus2=load_bus, parameters=tp1) - transformer2 = Transformer(id="Transformer2", bus1=source_bus, bus2=load_bus, parameters=tp2) + transformer1 = Transformer(id="Transformer1", bus1=source_bus, bus2=load_bus, parameters=tp1, geometry=geom) + transformer2 = Transformer(id="Transformer2", bus1=source_bus, bus2=load_bus, parameters=tp2, geometry=geom) en = ElectricalNetwork( buses=[source_bus, load_bus], branches=[transformer1, transformer2], @@ -91,7 +103,17 @@ def test_to_dict(): "t", type="Dyn11", uhv=20000, ulv=400, sn=160 * 1e3, p0=460, i0=2.3 / 100, psc=2350, vsc=4 / 100 ) transformer2.parameters = tp2 - en.to_dict() + res = en.to_dict() + assert "geometry" in res["buses"][0] + assert "geometry" in res["buses"][1] + assert "geometry" in res["branches"][0] + assert "geometry" in res["branches"][1] + + res = en.to_dict(geometry=False) + assert "geometry" not in res["buses"][0] + assert "geometry" not in res["buses"][1] + assert "geometry" not in res["branches"][0] + assert "geometry" not in res["branches"][1] def test_v0_to_v1_converter(monkeypatch): diff --git a/roseau/load_flow/models/branches.py b/roseau/load_flow/models/branches.py index b83185bb..7381b61a 100644 --- a/roseau/load_flow/models/branches.py +++ b/roseau/load_flow/models/branches.py @@ -126,7 +126,7 @@ def res_voltages(self) -> tuple[Q_[np.ndarray], Q_[np.ndarray]]: def from_dict(cls, data: JsonDict) -> Self: return cls(**data) # not used anymore - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: res = { "id": self.id, "type": self.branch_type, @@ -135,7 +135,7 @@ def to_dict(self) -> JsonDict: "bus1": self.bus1.id, "bus2": self.bus2.id, } - if self.geometry is not None: + if self.geometry is not None and geometry: res["geometry"] = self.geometry.__geo_interface__ return res diff --git a/roseau/load_flow/models/buses.py b/roseau/load_flow/models/buses.py index f022799d..2d8ccb77 100644 --- a/roseau/load_flow/models/buses.py +++ b/roseau/load_flow/models/buses.py @@ -138,11 +138,11 @@ def from_dict(cls, data: JsonDict) -> Self: potentials = [complex(v[0], v[1]) for v in potentials] return cls(id=data["id"], phases=data["phases"], geometry=geometry, potentials=potentials) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: res = {"id": self.id, "phases": self.phases} if not np.allclose(self.potentials, 0): res["potentials"] = [[v.real, v.imag] for v in self._potentials] - if self.geometry is not None: + if self.geometry is not None and geometry: res["geometry"] = self.geometry.__geo_interface__ return res diff --git a/roseau/load_flow/models/grounds.py b/roseau/load_flow/models/grounds.py index 627116a0..9368a9ff 100644 --- a/roseau/load_flow/models/grounds.py +++ b/roseau/load_flow/models/grounds.py @@ -97,7 +97,7 @@ def from_dict(cls, data: JsonDict) -> Self: self._connected_buses = data["buses"] return self - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: # Shunt lines and potential references will have the ground in their dict not here. return { "id": self.id, diff --git a/roseau/load_flow/models/lines/lines.py b/roseau/load_flow/models/lines/lines.py index 7adf47b3..ccc8d8a9 100644 --- a/roseau/load_flow/models/lines/lines.py +++ b/roseau/load_flow/models/lines/lines.py @@ -358,8 +358,8 @@ def res_power_losses(self) -> Q_[np.ndarray]: # # Json Mixin interface # - def to_dict(self) -> JsonDict: - res = {**super().to_dict(), "length": self._length, "params_id": self.parameters.id} + def to_dict(self, geometry: bool = True) -> JsonDict: + res = {**super().to_dict(geometry=geometry), "length": self._length, "params_id": self.parameters.id} if self.ground is not None: res["ground"] = self.ground.id return res diff --git a/roseau/load_flow/models/lines/parameters.py b/roseau/load_flow/models/lines/parameters.py index 8ded124b..b66154b1 100644 --- a/roseau/load_flow/models/lines/parameters.py +++ b/roseau/load_flow/models/lines/parameters.py @@ -656,7 +656,7 @@ def from_dict(cls, data: JsonDict) -> Self: logger.error(msg) raise RoseauLoadFlowException(msg=msg, code=RoseauLoadFlowExceptionCode.BAD_LINE_MODEL) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: """Return the line parameters information as a dictionary format.""" res = { "id": self.id, diff --git a/roseau/load_flow/models/loads/flexible_parameters.py b/roseau/load_flow/models/loads/flexible_parameters.py index ec429021..c7f9853c 100644 --- a/roseau/load_flow/models/loads/flexible_parameters.py +++ b/roseau/load_flow/models/loads/flexible_parameters.py @@ -296,7 +296,7 @@ def from_dict(cls, data: JsonDict) -> Self: logger.error(msg) raise RoseauLoadFlowException(msg=msg, code=RoseauLoadFlowExceptionCode.BAD_CONTROL_TYPE) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: if self.type == "constant": return {"type": "constant"} elif self.type == "p_max_u_production": @@ -410,7 +410,7 @@ def from_dict(cls, data: JsonDict) -> Self: epsilon = data["epsilon"] if "epsilon" in data else cls.DEFAULT_EPSILON return cls(type=data["type"], alpha=alpha, epsilon=epsilon) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: return {"type": self.type, "alpha": self._alpha, "epsilon": self._epsilon} def _results_to_dict(self, warning: bool) -> NoReturn: @@ -806,7 +806,7 @@ def from_dict(cls, data: JsonDict) -> Self: projection = cls._projection_class.from_dict(data["projection"]) return cls(control_p=control_p, control_q=control_q, projection=projection, s_max=data["s_max"]) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: return { "control_p": self.control_p.to_dict(), "control_q": self.control_q.to_dict(), diff --git a/roseau/load_flow/models/loads/loads.py b/roseau/load_flow/models/loads/loads.py index b5b14a21..ea4d47cd 100644 --- a/roseau/load_flow/models/loads/loads.py +++ b/roseau/load_flow/models/loads/loads.py @@ -308,7 +308,7 @@ def res_flexible_powers(self) -> Q_[np.ndarray]: # # Json Mixin interface # - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The load {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) @@ -383,7 +383,7 @@ def currents(self, value: Sequence[complex]) -> None: self._currents = self._validate_value(value) self._invalidate_network_results() - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The load {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) @@ -441,7 +441,7 @@ def impedances(self, impedances: Sequence[complex]) -> None: self._impedances = self._validate_value(impedances) self._invalidate_network_results() - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The load {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) diff --git a/roseau/load_flow/models/potential_refs.py b/roseau/load_flow/models/potential_refs.py index ce28bd6b..708e4292 100644 --- a/roseau/load_flow/models/potential_refs.py +++ b/roseau/load_flow/models/potential_refs.py @@ -86,7 +86,7 @@ def res_current(self) -> Q_[complex]: def from_dict(cls, data: JsonDict) -> Self: return cls(data["id"], data["element"], phase=data.get("phases")) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: res = {"id": self.id} e = self.element if isinstance(e, Bus): diff --git a/roseau/load_flow/models/sources.py b/roseau/load_flow/models/sources.py index b3ef3e90..ed73f770 100644 --- a/roseau/load_flow/models/sources.py +++ b/roseau/load_flow/models/sources.py @@ -153,7 +153,7 @@ def from_dict(cls, data: JsonDict) -> Self: voltages = [complex(v[0], v[1]) for v in data["voltages"]] return cls(data["id"], data["bus"], voltages=voltages, phases=data["phases"]) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The voltage source {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) diff --git a/roseau/load_flow/models/transformers/parameters.py b/roseau/load_flow/models/transformers/parameters.py index 94c64c1c..697bb68a 100644 --- a/roseau/load_flow/models/transformers/parameters.py +++ b/roseau/load_flow/models/transformers/parameters.py @@ -297,7 +297,7 @@ def from_dict(cls, data: JsonDict) -> Self: vsc=data["vsc"], ) - def to_dict(self) -> JsonDict: + def to_dict(self, geometry: bool = True) -> JsonDict: return { "id": self.id, "sn": self._sn, diff --git a/roseau/load_flow/models/transformers/transformers.py b/roseau/load_flow/models/transformers/transformers.py index c3adcbd7..6e894423 100644 --- a/roseau/load_flow/models/transformers/transformers.py +++ b/roseau/load_flow/models/transformers/transformers.py @@ -130,8 +130,8 @@ def parameters(self, value: TransformerParameters) -> None: self._parameters = value self._invalidate_network_results() - def to_dict(self) -> JsonDict: - return {**super().to_dict(), "params_id": self.parameters.id, "tap": self.tap} + def to_dict(self, geometry: bool = True) -> JsonDict: + return {**super().to_dict(geometry=geometry), "params_id": self.parameters.id, "tap": self.tap} def _compute_phases_three( self, diff --git a/roseau/load_flow/network.py b/roseau/load_flow/network.py index f7457a10..feec18df 100644 --- a/roseau/load_flow/network.py +++ b/roseau/load_flow/network.py @@ -422,7 +422,7 @@ def solve_load_flow( # Get the data data = { - "network": self.to_dict(), + "network": self.to_dict(geometry=False), "solver": { "name": solver, "params": solver_params, @@ -1103,9 +1103,14 @@ def from_dict(cls, data: JsonDict) -> Self: potential_refs=p_refs, ) - def to_dict(self) -> JsonDict: - """Convert the electrical network to a dictionary.""" - return network_to_dict(self) + def to_dict(self, geometry: bool = True) -> JsonDict: + """Convert the electrical network to a dictionary. + + Args: + geometry: + If False, the geometry will not be added to the result dictionary. + """ + return network_to_dict(self, geometry) # # Results saving/loading diff --git a/roseau/load_flow/utils/mixins.py b/roseau/load_flow/utils/mixins.py index 7b0119d7..0d8b6dd2 100644 --- a/roseau/load_flow/utils/mixins.py +++ b/roseau/load_flow/utils/mixins.py @@ -50,8 +50,13 @@ def from_json(cls, path: StrPath) -> Self: return cls.from_dict(data=data) @abstractmethod - def to_dict(self) -> JsonDict: - """Return the element information as a dictionary format.""" + def to_dict(self, geometry: bool = True) -> JsonDict: + """Return the element information as a dictionary format. + + Args: + geometry: + If False, the geometry will not be added to the result dictionary. + """ raise NotImplementedError def to_json(self, path: StrPath) -> Path: From b48c1bafb1b6b3a98b20dc6652ae9f3d2d4ec73c Mon Sep 17 00:00:00 2001 From: Saelyos Date: Mon, 7 Aug 2023 12:22:55 +0200 Subject: [PATCH 2/4] Update network parameter --- roseau/load_flow/network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roseau/load_flow/network.py b/roseau/load_flow/network.py index feec18df..4a18f1a1 100644 --- a/roseau/load_flow/network.py +++ b/roseau/load_flow/network.py @@ -1110,7 +1110,7 @@ def to_dict(self, geometry: bool = True) -> JsonDict: geometry: If False, the geometry will not be added to the result dictionary. """ - return network_to_dict(self, geometry) + return network_to_dict(self, geometry=geometry) # # Results saving/loading From 67b6fd37aeafdb751dcbd7f8303625b52e7f1ace Mon Sep 17 00:00:00 2001 From: Saelyos Date: Mon, 7 Aug 2023 14:42:52 +0200 Subject: [PATCH 3/4] Rename --- roseau/load_flow/io/dict.py | 8 ++++---- roseau/load_flow/io/tests/test_dict.py | 4 ++-- roseau/load_flow/models/branches.py | 4 ++-- roseau/load_flow/models/buses.py | 4 ++-- roseau/load_flow/models/grounds.py | 2 +- roseau/load_flow/models/lines/lines.py | 8 ++++++-- roseau/load_flow/models/lines/parameters.py | 2 +- roseau/load_flow/models/loads/flexible_parameters.py | 6 +++--- roseau/load_flow/models/loads/loads.py | 6 +++--- roseau/load_flow/models/potential_refs.py | 2 +- roseau/load_flow/models/sources.py | 2 +- roseau/load_flow/models/transformers/parameters.py | 2 +- roseau/load_flow/models/transformers/transformers.py | 4 ++-- roseau/load_flow/network.py | 8 ++++---- roseau/load_flow/utils/mixins.py | 4 ++-- 15 files changed, 35 insertions(+), 31 deletions(-) diff --git a/roseau/load_flow/io/dict.py b/roseau/load_flow/io/dict.py index 81e4ba8c..b7e4e203 100644 --- a/roseau/load_flow/io/dict.py +++ b/roseau/load_flow/io/dict.py @@ -132,14 +132,14 @@ def network_from_dict( return buses, branches_dict, loads, sources, grounds, potential_refs -def network_to_dict(en: "ElectricalNetwork", geometry: bool) -> JsonDict: +def network_to_dict(en: "ElectricalNetwork", include_geometry: bool) -> JsonDict: """Return a dictionary of the current network data. Args: en: The electrical network. - geometry: + include_geometry: If False, the geometry will not be added to the result dictionary. Returns: @@ -155,7 +155,7 @@ def network_to_dict(en: "ElectricalNetwork", geometry: bool) -> JsonDict: sources: list[JsonDict] = [] short_circuits: list[JsonDict] = [] for bus in en.buses.values(): - buses.append(bus.to_dict(geometry=geometry)) + buses.append(bus.to_dict(include_geometry=include_geometry)) for element in bus._connected_elements: if isinstance(element, AbstractLoad): assert element.bus is bus @@ -171,7 +171,7 @@ def network_to_dict(en: "ElectricalNetwork", geometry: bool) -> JsonDict: lines_params_dict: dict[Id, LineParameters] = {} transformers_params_dict: dict[Id, TransformerParameters] = {} for branch in en.branches.values(): - branches.append(branch.to_dict(geometry=geometry)) + branches.append(branch.to_dict(include_geometry=include_geometry)) if isinstance(branch, Line): params_id = branch.parameters.id if params_id in lines_params_dict and branch.parameters != lines_params_dict[params_id]: diff --git a/roseau/load_flow/io/tests/test_dict.py b/roseau/load_flow/io/tests/test_dict.py index 6c1c6643..cc9a1057 100644 --- a/roseau/load_flow/io/tests/test_dict.py +++ b/roseau/load_flow/io/tests/test_dict.py @@ -58,7 +58,7 @@ def test_to_dict(): assert "geometry" in res["branches"][0] assert "geometry" in res["branches"][1] - res = en.to_dict(geometry=False) + res = en.to_dict(include_geometry=False) assert "geometry" not in res["buses"][0] assert "geometry" not in res["buses"][1] assert "geometry" not in res["branches"][0] @@ -109,7 +109,7 @@ def test_to_dict(): assert "geometry" in res["branches"][0] assert "geometry" in res["branches"][1] - res = en.to_dict(geometry=False) + res = en.to_dict(include_geometry=False) assert "geometry" not in res["buses"][0] assert "geometry" not in res["buses"][1] assert "geometry" not in res["branches"][0] diff --git a/roseau/load_flow/models/branches.py b/roseau/load_flow/models/branches.py index 7381b61a..c9206f6e 100644 --- a/roseau/load_flow/models/branches.py +++ b/roseau/load_flow/models/branches.py @@ -126,7 +126,7 @@ def res_voltages(self) -> tuple[Q_[np.ndarray], Q_[np.ndarray]]: def from_dict(cls, data: JsonDict) -> Self: return cls(**data) # not used anymore - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: res = { "id": self.id, "type": self.branch_type, @@ -135,7 +135,7 @@ def to_dict(self, geometry: bool = True) -> JsonDict: "bus1": self.bus1.id, "bus2": self.bus2.id, } - if self.geometry is not None and geometry: + if self.geometry is not None and include_geometry: res["geometry"] = self.geometry.__geo_interface__ return res diff --git a/roseau/load_flow/models/buses.py b/roseau/load_flow/models/buses.py index 2d8ccb77..5547584d 100644 --- a/roseau/load_flow/models/buses.py +++ b/roseau/load_flow/models/buses.py @@ -138,11 +138,11 @@ def from_dict(cls, data: JsonDict) -> Self: potentials = [complex(v[0], v[1]) for v in potentials] return cls(id=data["id"], phases=data["phases"], geometry=geometry, potentials=potentials) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: res = {"id": self.id, "phases": self.phases} if not np.allclose(self.potentials, 0): res["potentials"] = [[v.real, v.imag] for v in self._potentials] - if self.geometry is not None and geometry: + if self.geometry is not None and include_geometry: res["geometry"] = self.geometry.__geo_interface__ return res diff --git a/roseau/load_flow/models/grounds.py b/roseau/load_flow/models/grounds.py index 9368a9ff..bbaf0cb1 100644 --- a/roseau/load_flow/models/grounds.py +++ b/roseau/load_flow/models/grounds.py @@ -97,7 +97,7 @@ def from_dict(cls, data: JsonDict) -> Self: self._connected_buses = data["buses"] return self - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: # Shunt lines and potential references will have the ground in their dict not here. return { "id": self.id, diff --git a/roseau/load_flow/models/lines/lines.py b/roseau/load_flow/models/lines/lines.py index ccc8d8a9..f6862de8 100644 --- a/roseau/load_flow/models/lines/lines.py +++ b/roseau/load_flow/models/lines/lines.py @@ -358,8 +358,12 @@ def res_power_losses(self) -> Q_[np.ndarray]: # # Json Mixin interface # - def to_dict(self, geometry: bool = True) -> JsonDict: - res = {**super().to_dict(geometry=geometry), "length": self._length, "params_id": self.parameters.id} + def to_dict(self, include_geometry: bool = True) -> JsonDict: + res = { + **super().to_dict(include_geometry=include_geometry), + "length": self._length, + "params_id": self.parameters.id, + } if self.ground is not None: res["ground"] = self.ground.id return res diff --git a/roseau/load_flow/models/lines/parameters.py b/roseau/load_flow/models/lines/parameters.py index b66154b1..b665d562 100644 --- a/roseau/load_flow/models/lines/parameters.py +++ b/roseau/load_flow/models/lines/parameters.py @@ -656,7 +656,7 @@ def from_dict(cls, data: JsonDict) -> Self: logger.error(msg) raise RoseauLoadFlowException(msg=msg, code=RoseauLoadFlowExceptionCode.BAD_LINE_MODEL) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: """Return the line parameters information as a dictionary format.""" res = { "id": self.id, diff --git a/roseau/load_flow/models/loads/flexible_parameters.py b/roseau/load_flow/models/loads/flexible_parameters.py index c7f9853c..327f027b 100644 --- a/roseau/load_flow/models/loads/flexible_parameters.py +++ b/roseau/load_flow/models/loads/flexible_parameters.py @@ -296,7 +296,7 @@ def from_dict(cls, data: JsonDict) -> Self: logger.error(msg) raise RoseauLoadFlowException(msg=msg, code=RoseauLoadFlowExceptionCode.BAD_CONTROL_TYPE) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: if self.type == "constant": return {"type": "constant"} elif self.type == "p_max_u_production": @@ -410,7 +410,7 @@ def from_dict(cls, data: JsonDict) -> Self: epsilon = data["epsilon"] if "epsilon" in data else cls.DEFAULT_EPSILON return cls(type=data["type"], alpha=alpha, epsilon=epsilon) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: return {"type": self.type, "alpha": self._alpha, "epsilon": self._epsilon} def _results_to_dict(self, warning: bool) -> NoReturn: @@ -806,7 +806,7 @@ def from_dict(cls, data: JsonDict) -> Self: projection = cls._projection_class.from_dict(data["projection"]) return cls(control_p=control_p, control_q=control_q, projection=projection, s_max=data["s_max"]) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: return { "control_p": self.control_p.to_dict(), "control_q": self.control_q.to_dict(), diff --git a/roseau/load_flow/models/loads/loads.py b/roseau/load_flow/models/loads/loads.py index ea4d47cd..4b958496 100644 --- a/roseau/load_flow/models/loads/loads.py +++ b/roseau/load_flow/models/loads/loads.py @@ -308,7 +308,7 @@ def res_flexible_powers(self) -> Q_[np.ndarray]: # # Json Mixin interface # - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The load {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) @@ -383,7 +383,7 @@ def currents(self, value: Sequence[complex]) -> None: self._currents = self._validate_value(value) self._invalidate_network_results() - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The load {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) @@ -441,7 +441,7 @@ def impedances(self, impedances: Sequence[complex]) -> None: self._impedances = self._validate_value(impedances) self._invalidate_network_results() - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The load {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) diff --git a/roseau/load_flow/models/potential_refs.py b/roseau/load_flow/models/potential_refs.py index 708e4292..deb25c3e 100644 --- a/roseau/load_flow/models/potential_refs.py +++ b/roseau/load_flow/models/potential_refs.py @@ -86,7 +86,7 @@ def res_current(self) -> Q_[complex]: def from_dict(cls, data: JsonDict) -> Self: return cls(data["id"], data["element"], phase=data.get("phases")) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: res = {"id": self.id} e = self.element if isinstance(e, Bus): diff --git a/roseau/load_flow/models/sources.py b/roseau/load_flow/models/sources.py index ed73f770..4ee826d2 100644 --- a/roseau/load_flow/models/sources.py +++ b/roseau/load_flow/models/sources.py @@ -153,7 +153,7 @@ def from_dict(cls, data: JsonDict) -> Self: voltages = [complex(v[0], v[1]) for v in data["voltages"]] return cls(data["id"], data["bus"], voltages=voltages, phases=data["phases"]) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: if self.bus is None: msg = f"The voltage source {self.id!r} is disconnected and cannot be used anymore." logger.error(msg) diff --git a/roseau/load_flow/models/transformers/parameters.py b/roseau/load_flow/models/transformers/parameters.py index 697bb68a..fdc04d11 100644 --- a/roseau/load_flow/models/transformers/parameters.py +++ b/roseau/load_flow/models/transformers/parameters.py @@ -297,7 +297,7 @@ def from_dict(cls, data: JsonDict) -> Self: vsc=data["vsc"], ) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: return { "id": self.id, "sn": self._sn, diff --git a/roseau/load_flow/models/transformers/transformers.py b/roseau/load_flow/models/transformers/transformers.py index 6e894423..300d8432 100644 --- a/roseau/load_flow/models/transformers/transformers.py +++ b/roseau/load_flow/models/transformers/transformers.py @@ -130,8 +130,8 @@ def parameters(self, value: TransformerParameters) -> None: self._parameters = value self._invalidate_network_results() - def to_dict(self, geometry: bool = True) -> JsonDict: - return {**super().to_dict(geometry=geometry), "params_id": self.parameters.id, "tap": self.tap} + def to_dict(self, include_geometry: bool = True) -> JsonDict: + return {**super().to_dict(include_geometry=include_geometry), "params_id": self.parameters.id, "tap": self.tap} def _compute_phases_three( self, diff --git a/roseau/load_flow/network.py b/roseau/load_flow/network.py index 4a18f1a1..f7c11381 100644 --- a/roseau/load_flow/network.py +++ b/roseau/load_flow/network.py @@ -422,7 +422,7 @@ def solve_load_flow( # Get the data data = { - "network": self.to_dict(geometry=False), + "network": self.to_dict(include_geometry=False), "solver": { "name": solver, "params": solver_params, @@ -1103,14 +1103,14 @@ def from_dict(cls, data: JsonDict) -> Self: potential_refs=p_refs, ) - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: """Convert the electrical network to a dictionary. Args: - geometry: + include_geometry: If False, the geometry will not be added to the result dictionary. """ - return network_to_dict(self, geometry=geometry) + return network_to_dict(self, include_geometry=include_geometry) # # Results saving/loading diff --git a/roseau/load_flow/utils/mixins.py b/roseau/load_flow/utils/mixins.py index 0d8b6dd2..e85aed7c 100644 --- a/roseau/load_flow/utils/mixins.py +++ b/roseau/load_flow/utils/mixins.py @@ -50,11 +50,11 @@ def from_json(cls, path: StrPath) -> Self: return cls.from_dict(data=data) @abstractmethod - def to_dict(self, geometry: bool = True) -> JsonDict: + def to_dict(self, include_geometry: bool = True) -> JsonDict: """Return the element information as a dictionary format. Args: - geometry: + include_geometry: If False, the geometry will not be added to the result dictionary. """ raise NotImplementedError From 84a74c722e74ba8967c477f8f304866d3bd725e1 Mon Sep 17 00:00:00 2001 From: Saelyos Date: Mon, 7 Aug 2023 15:16:27 +0200 Subject: [PATCH 4/4] Add changelog --- doc/Changelog.md | 1 + roseau/load_flow/io/dict.py | 2 +- roseau/load_flow/network.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/Changelog.md b/doc/Changelog.md index 20db0f9f..5e921f97 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -4,6 +4,7 @@ **In development** +* [PR112](https://github.com/RoseauTechnologies/Roseau_Load_Flow/pull/112) Make the geometry serialization optional. * [PR106](https://github.com/RoseauTechnologies/Roseau_Load_Flow/pull/106) Improvements for non-euclidean projections. * [PR104](https://github.com/RoseauTechnologies/Roseau_Load_Flow/pull/104) Remove `roseau.load_flow.utils.BranchType` * [GH99](https://github.com/RoseauTechnologies/Roseau_Load_Flow/issues/99) Add `Line.res_series_currents` diff --git a/roseau/load_flow/io/dict.py b/roseau/load_flow/io/dict.py index b7e4e203..e1b481d3 100644 --- a/roseau/load_flow/io/dict.py +++ b/roseau/load_flow/io/dict.py @@ -140,7 +140,7 @@ def network_to_dict(en: "ElectricalNetwork", include_geometry: bool) -> JsonDict The electrical network. include_geometry: - If False, the geometry will not be added to the result dictionary. + If False, the geometry will not be added to the network dictionary. Returns: The created dictionary. diff --git a/roseau/load_flow/network.py b/roseau/load_flow/network.py index f7c11381..a5c03424 100644 --- a/roseau/load_flow/network.py +++ b/roseau/load_flow/network.py @@ -1108,7 +1108,7 @@ def to_dict(self, include_geometry: bool = True) -> JsonDict: Args: include_geometry: - If False, the geometry will not be added to the result dictionary. + If False, the geometry will not be added to the network dictionary. """ return network_to_dict(self, include_geometry=include_geometry)