From ff8f3ec30bfb1ef4db5014d18c9a8f708518952e Mon Sep 17 00:00:00 2001 From: Boris Filin Date: Tue, 28 Jul 2026 13:27:07 +1000 Subject: [PATCH] Move soon-to-be-deprecated methods to the end of the file Signed-off-by: Boris Filin --- .../iec61968/assetinfo/relay_info.py | 20 +- .../iec61968/common/contact_details.py | 50 ++--- .../iec61970/base/feeder/lv_feeder.py | 136 ++++++------ .../iec61970/base/feeder/lv_substation.py | 136 ++++++------ .../protection/protection_relay_function.py | 96 ++++----- .../protection/protection_relay_scheme.py | 16 +- .../protection/protection_relay_system.py | 16 +- .../assetinfo/power_transformer_info.py | 38 ++-- .../assetinfo/transformer_tank_info.py | 40 ++-- .../ewb/model/cim/iec61968/assets/asset.py | 26 +-- .../ewb/model/cim/iec61968/common/location.py | 30 +-- .../model/cim/iec61968/customers/customer.py | 12 +- .../iec61968/customers/customer_agreement.py | 12 +- .../iec61968/customers/pricing_structure.py | 12 +- .../iec61968/infiec61968/infassets/pole.py | 12 +- .../model/cim/iec61968/metering/end_device.py | 26 +-- .../cim/iec61968/metering/usage_point.py | 138 ++++++------ .../operations/operational_restriction.py | 12 +- .../base/core/conducting_equipment.py | 54 ++--- .../iec61970/base/core/connectivity_node.py | 38 ++-- .../model/cim/iec61970/base/core/equipment.py | 66 +++--- .../iec61970/base/core/equipment_container.py | 202 +++++++++--------- .../model/cim/iec61970/base/core/feeder.py | 50 ++--- .../iec61970/base/core/geographical_region.py | 12 +- .../base/core/power_system_resource.py | 12 +- .../base/core/sub_geographical_region.py | 12 +- .../cim/iec61970/base/core/substation.py | 106 ++++----- .../iec61970/base/diagramlayout/diagram.py | 12 +- .../base/diagramlayout/diagram_object.py | 30 +-- .../generation/production/battery_unit.py | 12 +- .../iec61970/base/wires/ac_line_segment.py | 132 ++++++------ .../iec61970/base/wires/energy_consumer.py | 8 +- .../iec61970/base/wires/power_transformer.py | 60 +++--- .../base/wires/power_transformer_end.py | 34 +-- 34 files changed, 834 insertions(+), 834 deletions(-) diff --git a/src/zepben/ewb/model/cim/extensions/iec61968/assetinfo/relay_info.py b/src/zepben/ewb/model/cim/extensions/iec61968/assetinfo/relay_info.py index a893928fa..1422e7455 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61968/assetinfo/relay_info.py +++ b/src/zepben/ewb/model/cim/extensions/iec61968/assetinfo/relay_info.py @@ -41,6 +41,16 @@ def reclose_delays(self) -> Generator[float, None, None]: """ return ngen(self._reclose_delays) + def set_delays(self, delays: List[float]) -> RelayInfo: + """ + Set the reclose delays for this :class:`RelayInfo`. + + :param delays: The delays to set. The provided list will be copied. + :return: A reference to this :class:`RelayInfo` to allow fluent use. + """ + self._reclose_delays = delays.copy() + return self + def num_delays(self) -> int: """ Get the number of reclose delays for this :class:`RelayInfo` @@ -86,16 +96,6 @@ def add_delay(self, delay: float, index: int = None) -> RelayInfo: self._reclose_delays.insert(index, delay) return self - def set_delays(self, delays: List[float]) -> RelayInfo: - """ - Set the reclose delays for this :class:`RelayInfo`. - - :param delays: The delays to set. The provided list will be copied. - :return: A reference to this :class:`RelayInfo` to allow fluent use. - """ - self._reclose_delays = delays.copy() - return self - def remove_delay(self, delay: float) -> RelayInfo: """ Remove a delay from the list. diff --git a/src/zepben/ewb/model/cim/extensions/iec61968/common/contact_details.py b/src/zepben/ewb/model/cim/extensions/iec61968/common/contact_details.py index 2a40b0ab2..c7cbe845b 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61968/common/contact_details.py +++ b/src/zepben/ewb/model/cim/extensions/iec61968/common/contact_details.py @@ -93,6 +93,31 @@ def phone_numbers(self) -> Generator[TelephoneNumber, None, None]: """[ZBEX] Phone numbers.""" return ngen(self._phone_numbers) + @zbex + @property + def electronic_addresses(self) -> Generator[ElectronicAddress, None, None]: + """[ZBEX] Electronic addresses.""" + return ngen(self._electronic_addresses) + + def __eq__(self, other: Any) -> bool: + # + # NOTE: We implement the equals to allow us to compare the entire ``ContactDetails`` as a value. We do this since it isnt an + # ``IdentifiedObject``, so our other helpers don't support it. + if not isinstance(other, ContactDetails): + return False + return all(( + self.is_primary == other.is_primary, + self.mrid == other.mrid, + self.contact_address == other.contact_address, + self.contact_type == other.contact_type, + self.first_name == other.first_name, + self.last_name == other.last_name, + self.preferred_contact_method == other.preferred_contact_method, + self.business_name == other.business_name, + self._phone_numbers == other._phone_numbers, + self._electronic_addresses == other._electronic_addresses, + )) + def num_phone_numbers(self) -> int: """Get the number of entries in the ``TelephoneNumber`` collection.""" return nlen(self._phone_numbers) @@ -131,12 +156,6 @@ def clear_phone_numbers(self) -> "ContactDetails": self._phone_numbers = None return self - @zbex - @property - def electronic_addresses(self) -> Generator[ElectronicAddress, None, None]: - """[ZBEX] Electronic addresses.""" - return ngen(self._electronic_addresses) - def num_electronic_addresses(self) -> int: """Get the number of entries in the [ElectronicAddress] collection.""" return nlen(self._electronic_addresses) @@ -175,22 +194,3 @@ def clear_electronic_addresses(self) -> "ContactDetails": """ self._electronic_addresses = None return self - - def __eq__(self, other: Any) -> bool: - # - # NOTE: We implement the equals to allow us to compare the entire ``ContactDetails`` as a value. We do this since it isnt an - # ``IdentifiedObject``, so our other helpers don't support it. - if not isinstance(other, ContactDetails): - return False - return all(( - self.is_primary == other.is_primary, - self.mrid == other.mrid, - self.contact_address == other.contact_address, - self.contact_type == other.contact_type, - self.first_name == other.first_name, - self.last_name == other.last_name, - self.preferred_contact_method == other.preferred_contact_method, - self.business_name == other.business_name, - self._phone_numbers == other._phone_numbers, - self._electronic_addresses == other._electronic_addresses, - )) diff --git a/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_feeder.py b/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_feeder.py index 9e040ed1c..e41f23369 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_feeder.py +++ b/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_feeder.py @@ -95,6 +95,74 @@ def normal_energizing_feeders(self) -> Generator[Feeder, None, None]: """ return ngen(self._normal_energizing_feeders) + @property + def current_energizing_feeders(self) -> Generator[Feeder, None, None]: + """ + [ZBEX] The HV/MV feeders that currently energize this LV feeder. + """ + return ngen(self._current_energizing_feeders) + + @property + def current_equipment(self) -> Generator[Equipment, None, None]: + """ + Contained `Equipment` using the current state of the network. + """ + return ngen(self._current_equipment) + + def num_current_equipment(self): + """ + Returns The number of `Equipment` associated with this `LvFeeder` in the current state of the network. + """ + return nlen(self._current_equipment) + + def get_current_equipment(self, mrid: str) -> Equipment: + """ + Get the `Equipment` contained in this `LvFeeder` in the current state of the network, identified by `mrid` + + `mrid` The mRID of the required `Equipment` + Returns The `Equipment` with the specified `mrid` if it exists + Raises `KeyError` if `mrid` wasn't present. + """ + if not self._current_equipment: + raise KeyError(mrid) + try: + return self._current_equipment[mrid] + except AttributeError: + raise KeyError(mrid) + + def add_current_equipment(self, equipment: Equipment) -> LvFeeder: + """ + Associate `equipment` with this `LvFeeder` in the current state of the network. + + `equipment` the `Equipment` to associate with this `LvFeeder` in the current state of the network. + Returns A reference to this `LvFeeder` to allow fluent use. + Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `LvFeeder`. + """ + if self._validate_reference(equipment, self.get_current_equipment, "An Equipment"): + return self + self._current_equipment = dict() if self._current_equipment is None else self._current_equipment + self._current_equipment[equipment.mrid] = equipment + return self + + def remove_current_equipment(self, equipment: Equipment) -> LvFeeder: + """ + Disassociate `equipment` from this `LvFeeder` in the current state of the network. + + `equipment` The `Equipment` to disassociate from this `LvFeeder` in the current state of the network. + Returns A reference to this `LvFeeder` to allow fluent use. + Raises `KeyError` if `equipment` was not associated with this `LvFeeder`. + """ + self._current_equipment = safe_remove_by_id(self._current_equipment, equipment) + return self + + def clear_current_equipment(self) -> LvFeeder: + """ + Clear all `Equipment` from this `LvFeeder` in the current state of the network. + Returns A reference to this `LvFeeder` to allow fluent use. + """ + self._current_equipment = None + return self + def num_normal_energizing_feeders(self) -> int: """ Get the number of HV/MV feeders that normally energize this LV feeder. @@ -149,13 +217,6 @@ def clear_normal_energizing_feeders(self) -> LvFeeder: self._normal_energizing_feeders = None return self - @property - def current_energizing_feeders(self) -> Generator[Feeder, None, None]: - """ - [ZBEX] The HV/MV feeders that currently energize this LV feeder. - """ - return ngen(self._current_energizing_feeders) - def num_current_energizing_feeders(self) -> int: """ Get the number of HV/MV feeders that currently energize this LV feeder. @@ -209,64 +270,3 @@ def clear_current_energizing_feeders(self) -> LvFeeder: """ self._current_energizing_feeders = None return self - - @property - def current_equipment(self) -> Generator[Equipment, None, None]: - """ - Contained `Equipment` using the current state of the network. - """ - return ngen(self._current_equipment) - - def num_current_equipment(self): - """ - Returns The number of `Equipment` associated with this `LvFeeder` in the current state of the network. - """ - return nlen(self._current_equipment) - - def get_current_equipment(self, mrid: str) -> Equipment: - """ - Get the `Equipment` contained in this `LvFeeder` in the current state of the network, identified by `mrid` - - `mrid` The mRID of the required `Equipment` - Returns The `Equipment` with the specified `mrid` if it exists - Raises `KeyError` if `mrid` wasn't present. - """ - if not self._current_equipment: - raise KeyError(mrid) - try: - return self._current_equipment[mrid] - except AttributeError: - raise KeyError(mrid) - - def add_current_equipment(self, equipment: Equipment) -> LvFeeder: - """ - Associate `equipment` with this `LvFeeder` in the current state of the network. - - `equipment` the `Equipment` to associate with this `LvFeeder` in the current state of the network. - Returns A reference to this `LvFeeder` to allow fluent use. - Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `LvFeeder`. - """ - if self._validate_reference(equipment, self.get_current_equipment, "An Equipment"): - return self - self._current_equipment = dict() if self._current_equipment is None else self._current_equipment - self._current_equipment[equipment.mrid] = equipment - return self - - def remove_current_equipment(self, equipment: Equipment) -> LvFeeder: - """ - Disassociate `equipment` from this `LvFeeder` in the current state of the network. - - `equipment` The `Equipment` to disassociate from this `LvFeeder` in the current state of the network. - Returns A reference to this `LvFeeder` to allow fluent use. - Raises `KeyError` if `equipment` was not associated with this `LvFeeder`. - """ - self._current_equipment = safe_remove_by_id(self._current_equipment, equipment) - return self - - def clear_current_equipment(self) -> LvFeeder: - """ - Clear all `Equipment` from this `LvFeeder` in the current state of the network. - Returns A reference to this `LvFeeder` to allow fluent use. - """ - self._current_equipment = None - return self diff --git a/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py b/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py index c90054d3c..8d203e09a 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py +++ b/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py @@ -57,6 +57,32 @@ def normal_energizing_feeders(self) -> Generator["Feeder", None, None]: """[ZBEX] The HV/MV feeders that normally energize this ``LvSubstation``.""" return ngen(self._normal_energizing_feeders_by_id) + @zbex + @property + def normal_energized_lv_feeders(self) -> Generator[LvFeeder, None, None]: + """[ZBEX] the ``LvFeeders`` that are normally energized by this ``LvSubstation``.""" + return ngen(self._normal_energized_lv_feeders_by_id) + + @zbex + @property + def current_energizing_feeders(self) -> Generator['Feeder', None, None]: + """ + [ZBEX] The HV/MV feeders that currently energize this LV substation. + """ + return ngen(self._current_energizing_feeders_by_id) + + def normal_energized_lv_switch_feeders(self) -> Generator[LvFeeder, None, None]: + """ + Retrieves all normally energized LvFeeders that represent low voltage network connected below a switch on the edge of this LvSubstation. This is all + LvFeeders in the normalEnergizedLvFeeders that has a normalHeadTerminal attached to a Switch. + """ + # NOTE: import exists here due to a circular import problem + from zepben.ewb.model.cim.iec61970.base.wires.switch import Switch + + for lv_feeder in self.normal_energized_lv_feeders: + if (it := lv_feeder.normal_head_terminal) is not None and isinstance(it.conducting_equipment, Switch): + yield lv_feeder + def num_normal_energizing_feeders(self) -> int: """Get the number of entries in the normal ``Feeder`` collection.""" return nlen(self._normal_energizing_feeders_by_id) @@ -104,66 +130,6 @@ def clear_normal_energizing_feeders(self) -> "LvSubstation": self._normal_energizing_feeders_by_id = None return self - @zbex - @property - def normal_energized_lv_feeders(self) -> Generator[LvFeeder, None, None]: - """[ZBEX] the ``LvFeeders`` that are normally energized by this ``LvSubstation``.""" - return ngen(self._normal_energized_lv_feeders_by_id) - - def num_normal_energized_lv_feeders(self) -> int: - """Get the number of entries in the normal ``LvFeeder`` collection.""" - return nlen(self._normal_energized_lv_feeders_by_id) - - def get_normal_energized_lv_feeder(self, mrid: str) -> LvFeeder | None: - """ - Retrieve an energized ``LvFeeder`` using the normal state of the network. - - :param mrid: the mRID of the required normal ``LvFeeder`` - :returns: The ``LvFeeder`` with the specified ``mRID`` if it exists, otherwise null - """ - return get_by_mrid(self._normal_energized_lv_feeders_by_id, mrid) - - def add_normal_energized_lv_feeder(self, lv_feeder: LvFeeder) -> "LvSubstation": - """ - Associate this ``LvSubstation`` with an ``LvFeeder`` in the normal state of the network. - - :param lv_feeder: the ``LvFeeder`` to associate with this feeder in the normal state of the network. - :returns: This ``LvSubstation`` for fluent use. - """ - if self._validate_reference(lv_feeder, self.get_normal_energized_lv_feeder, "An LvFeeder"): - return self - - if self._normal_energized_lv_feeders_by_id is None: - self._normal_energized_lv_feeders_by_id = dict() - self._normal_energized_lv_feeders_by_id[lv_feeder.mrid] = lv_feeder - return self - - def remove_normal_energized_lv_feeder(self, lv_feeder: LvFeeder) -> "LvSubstation": - """ - Disassociate this ``LvSubstation`` from an ``LvFeeder`` in the normal state of the network. - - :param lv_feeder: the ``LvFeeder`` to disassociate from this HV/MV feeder in the normal state of the network. - """ - self._normal_energized_lv_feeders_by_id = safe_remove_by_id(self._normal_energized_lv_feeders_by_id, lv_feeder) - return self - - def clear_normal_energized_lv_feeders(self) -> "LvSubstation": - """ - Clear all ``LvFeeder``'s associated with this ``LvSubstation`` in the normal state of the network. - - :returns: This ``LvSubstation`` for fluent use. - """ - self._normal_energized_lv_feeders_by_id = None - return self - - @zbex - @property - def current_energizing_feeders(self) -> Generator['Feeder', None, None]: - """ - [ZBEX] The HV/MV feeders that currently energize this LV substation. - """ - return ngen(self._current_energizing_feeders_by_id) - def num_current_energizing_feeders(self) -> int: """ Get the number of entries in the current ``Feeder`` collection. @@ -212,14 +178,48 @@ def clear_current_energizing_feeders(self) -> "LvSubstation": self._current_energizing_feeders_by_id = None return self - def normal_energized_lv_switch_feeders(self) -> Generator[LvFeeder, None, None]: + def num_normal_energized_lv_feeders(self) -> int: + """Get the number of entries in the normal ``LvFeeder`` collection.""" + return nlen(self._normal_energized_lv_feeders_by_id) + + def get_normal_energized_lv_feeder(self, mrid: str) -> LvFeeder | None: """ - Retrieves all normally energized LvFeeders that represent low voltage network connected below a switch on the edge of this LvSubstation. This is all - LvFeeders in the normalEnergizedLvFeeders that has a normalHeadTerminal attached to a Switch. + Retrieve an energized ``LvFeeder`` using the normal state of the network. + + :param mrid: the mRID of the required normal ``LvFeeder`` + :returns: The ``LvFeeder`` with the specified ``mRID`` if it exists, otherwise null """ - # NOTE: import exists here due to a circular import problem - from zepben.ewb.model.cim.iec61970.base.wires.switch import Switch + return get_by_mrid(self._normal_energized_lv_feeders_by_id, mrid) - for lv_feeder in self.normal_energized_lv_feeders: - if (it := lv_feeder.normal_head_terminal) is not None and isinstance(it.conducting_equipment, Switch): - yield lv_feeder + def add_normal_energized_lv_feeder(self, lv_feeder: LvFeeder) -> "LvSubstation": + """ + Associate this ``LvSubstation`` with an ``LvFeeder`` in the normal state of the network. + + :param lv_feeder: the ``LvFeeder`` to associate with this feeder in the normal state of the network. + :returns: This ``LvSubstation`` for fluent use. + """ + if self._validate_reference(lv_feeder, self.get_normal_energized_lv_feeder, "An LvFeeder"): + return self + + if self._normal_energized_lv_feeders_by_id is None: + self._normal_energized_lv_feeders_by_id = dict() + self._normal_energized_lv_feeders_by_id[lv_feeder.mrid] = lv_feeder + return self + + def remove_normal_energized_lv_feeder(self, lv_feeder: LvFeeder) -> "LvSubstation": + """ + Disassociate this ``LvSubstation`` from an ``LvFeeder`` in the normal state of the network. + + :param lv_feeder: the ``LvFeeder`` to disassociate from this HV/MV feeder in the normal state of the network. + """ + self._normal_energized_lv_feeders_by_id = safe_remove_by_id(self._normal_energized_lv_feeders_by_id, lv_feeder) + return self + + def clear_normal_energized_lv_feeders(self) -> "LvSubstation": + """ + Clear all ``LvFeeder``'s associated with this ``LvSubstation`` in the normal state of the network. + + :returns: This ``LvSubstation`` for fluent use. + """ + self._normal_energized_lv_feeders_by_id = None + return self diff --git a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py index bee0105f0..0dc128bfb 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py +++ b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py @@ -121,6 +121,42 @@ def thresholds(self) -> Generator[RelaySetting, None, None]: """ return ngen(self._thresholds) + @property + def time_limits(self) -> Generator[float, None, None]: + """ + [ZBEX] Yields all the time limits (in seconds) for this relay function. Order of entries corresponds to the order of entries in thresholds. + + :return: A generator that iterates over all time limits for this relay function. + """ + return ngen(self._time_limits) + + @property + def sensors(self) -> Generator[Sensor, None, None]: + """ + [ZBEX] Yields all the :class:`Sensors` for this relay function. + + :return: A generator that iterates over all :class:`Sensors` for this relay function. + """ + return ngen(self._sensors) + + @property + def protected_switches(self) -> Generator[ProtectedSwitch, None, None]: + """ + [ZBEX] Yields the :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. + + :return: A generator that iterates over all :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. + """ + return ngen(self._protected_switches) + + @property + def schemes(self) -> Generator[ProtectionRelayScheme, None, None]: + """ + [ZBEX] Yields the :class:`ProtectionRelaySchemes` this :class:`ProtectionRelayFunction` operates under. + + :return: A generator that iterates over all :class:`ProtectionRelaySchemes` this :class:`ProtectionRelayFunction` operates under. + """ + return ngen(self._schemes) + def for_each_threshold(self, action: Callable[[int, RelaySetting], Any]): """ Call the `action` on each :class:`RelaySetting` in the `thresholds` collection @@ -200,15 +236,6 @@ def clear_thresholds(self) -> ProtectionRelayFunction: self._thresholds = None return self - @property - def time_limits(self) -> Generator[float, None, None]: - """ - [ZBEX] Yields all the time limits (in seconds) for this relay function. Order of entries corresponds to the order of entries in thresholds. - - :return: A generator that iterates over all time limits for this relay function. - """ - return ngen(self._time_limits) - def for_each_time_limit(self, action: Callable[[int, float], Any]): """ Call the `action` on each time limit in the `time_limits` collection @@ -285,14 +312,13 @@ def clear_time_limits(self) -> ProtectionRelayFunction: self._time_limits = None return self - @property - def sensors(self) -> Generator[Sensor, None, None]: + def num_sensors(self) -> int: """ - [ZBEX] Yields all the :class:`Sensors` for this relay function. + Get the number of :class:`Sensors` for this :class:`ProtectionRelayFunction`. - :return: A generator that iterates over all :class:`Sensors` for this relay function. + :return: The number of :class:`Sensors` for this :class:`ProtectionRelayFunction`. """ - return ngen(self._sensors) + return nlen(self._sensors) def get_sensor(self, mrid: str) -> Sensor: """ @@ -317,14 +343,6 @@ def add_sensor(self, sensor: Sensor) -> ProtectionRelayFunction: self._sensors.append(sensor) return self - def num_sensors(self) -> int: - """ - Get the number of :class:`Sensors` for this :class:`ProtectionRelayFunction`. - - :return: The number of :class:`Sensors` for this :class:`ProtectionRelayFunction`. - """ - return nlen(self._sensors) - def remove_sensor(self, sensor: Optional[Sensor]) -> ProtectionRelayFunction: """ Disassociate this :class:`ProtectionRelayFunction` from a :class:`Sensor`. @@ -345,14 +363,13 @@ def clear_sensors(self) -> ProtectionRelayFunction: self._sensors = None return self - @property - def protected_switches(self) -> Generator[ProtectedSwitch, None, None]: + def num_protected_switches(self) -> int: """ - [ZBEX] Yields the :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. + Get the number of :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. - :return: A generator that iterates over all :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. + :return: The number of :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. """ - return ngen(self._protected_switches) + return nlen(self._protected_switches) def get_protected_switch(self, mrid: str) -> ProtectedSwitch: """ @@ -377,14 +394,6 @@ def add_protected_switch(self, protected_switch: ProtectedSwitch) -> ProtectionR self._protected_switches.append(protected_switch) return self - def num_protected_switches(self) -> int: - """ - Get the number of :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. - - :return: The number of :class:`ProtectedSwitches` operated by this :class:`ProtectionRelayFunction`. - """ - return nlen(self._protected_switches) - def remove_protected_switch(self, protected_switch: Optional[ProtectedSwitch]) -> ProtectionRelayFunction: """ Disassociate this :class:`ProtectionRelayFunction` from a :class:`ProtectedSwitch`. @@ -405,14 +414,13 @@ def clear_protected_switches(self) -> ProtectionRelayFunction: self._protected_switches = None return self - @property - def schemes(self) -> Generator[ProtectionRelayScheme, None, None]: + def num_schemes(self) -> int: """ - [ZBEX] Yields the :class:`ProtectionRelaySchemes` this :class:`ProtectionRelayFunction` operates under. + Get the number of :class:`ProtectionRelaySchemes` this :class:`ProtectionRelayFunction` operates under. - :return: A generator that iterates over all :class:`ProtectionRelaySchemes` this :class:`ProtectionRelayFunction` operates under. + :return: The number of:class:`ProtectionRelaySchemes` operated by this :class:`ProtectionRelayFunction`. """ - return ngen(self._schemes) + return nlen(self._schemes) def get_scheme(self, mrid: str) -> ProtectionRelayScheme: """ @@ -437,14 +445,6 @@ def add_scheme(self, scheme: ProtectionRelayScheme) -> ProtectionRelayFunction: self._schemes.append(scheme) return self - def num_schemes(self) -> int: - """ - Get the number of :class:`ProtectionRelaySchemes` this :class:`ProtectionRelayFunction` operates under. - - :return: The number of:class:`ProtectionRelaySchemes` operated by this :class:`ProtectionRelayFunction`. - """ - return nlen(self._schemes) - def remove_scheme(self, scheme: Optional[ProtectionRelayScheme]) -> ProtectionRelayFunction: """ Disassociate this :class:`ProtectionRelayFunction` from a :class:`ProtectionRelayScheme`. diff --git a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_scheme.py b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_scheme.py index 7786fb78d..8895badfe 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_scheme.py +++ b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_scheme.py @@ -47,6 +47,14 @@ def functions(self) -> Generator[ProtectionRelayFunction, None, None]: """ return ngen(self._functions) + def num_functions(self) -> int: + """ + Get the number of :class:`ProtectionRelayFunctions` operated as part of this :class:`ProtectionRelayScheme`. + + :return: The number of :class:`ProtectionRelayFunctions` operated as part of this :class:`ProtectionRelayScheme`. + """ + return nlen(self._functions) + def get_function(self, mrid: str) -> ProtectionRelayFunction: """ Get a :class:`ProtectionRelayFunction` operated as part of this :class:`ProtectionRelayScheme`. @@ -70,14 +78,6 @@ def add_function(self, function: ProtectionRelayFunction) -> ProtectionRelaySche self._functions.append(function) return self - def num_functions(self) -> int: - """ - Get the number of :class:`ProtectionRelayFunctions` operated as part of this :class:`ProtectionRelayScheme`. - - :return: The number of :class:`ProtectionRelayFunctions` operated as part of this :class:`ProtectionRelayScheme`. - """ - return nlen(self._functions) - def remove_function(self, function: Optional[ProtectionRelayFunction]) -> ProtectionRelayScheme: """ Disassociate this :class:`ProtectionRelayScheme` from a :class:`ProtectionRelayFunction`. diff --git a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_system.py b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_system.py index 27d8b9ff9..83c1ae601 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_system.py +++ b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_system.py @@ -47,6 +47,14 @@ def schemes(self) -> Generator[ProtectionRelayScheme, None, None]: """ return ngen(self._schemes) + def num_schemes(self) -> int: + """ + Get the number of :class:`ProtectionRelaySchemes` for this :class:`ProtectionRelaySystem`. + + :return: The number of :class:`ProtectionRelaySchemes` for this :class:`ProtectionRelaySystem`. + """ + return nlen(self._schemes) + def get_scheme(self, mrid: str) -> ProtectionRelayScheme: """ Get a :class:`ProtectionRelayScheme` for this :class:`ProtectionRelaySystem` by its mRID. @@ -70,14 +78,6 @@ def add_scheme(self, scheme: ProtectionRelayScheme) -> ProtectionRelaySystem: self._schemes.append(scheme) return self - def num_schemes(self) -> int: - """ - Get the number of :class:`ProtectionRelaySchemes` for this :class:`ProtectionRelaySystem`. - - :return: The number of :class:`ProtectionRelaySchemes` for this :class:`ProtectionRelaySystem`. - """ - return nlen(self._schemes) - def remove_scheme(self, scheme: Optional[ProtectionRelayScheme]) -> ProtectionRelaySystem: """ Remove a :class:`ProtectionRelayScheme` from this :class:`ProtectionRelaySystem`. diff --git a/src/zepben/ewb/model/cim/iec61968/assetinfo/power_transformer_info.py b/src/zepben/ewb/model/cim/iec61968/assetinfo/power_transformer_info.py index b89a293de..eb939df8f 100644 --- a/src/zepben/ewb/model/cim/iec61968/assetinfo/power_transformer_info.py +++ b/src/zepben/ewb/model/cim/iec61968/assetinfo/power_transformer_info.py @@ -31,12 +31,6 @@ def __init__(self, *args, transformer_tank_infos: List[TransformerTankInfo] = No for ti in transformer_tank_infos: self.add_transformer_tank_info(ti) - def num_transformer_tank_infos(self): - """ - Get the number of `TransformerTankInfo`s associated with this `PowerTransformerInfo`. - """ - return nlen(self._transformer_tank_infos) - @property def transformer_tank_infos(self) -> Generator[TransformerTankInfo, None, None]: """ @@ -44,6 +38,25 @@ def transformer_tank_infos(self) -> Generator[TransformerTankInfo, None, None]: """ return ngen(self._transformer_tank_infos) + def resistance_reactance(self, end_number: int) -> Optional[ResistanceReactance]: + """ + Get the `ResistanceReactance` for the specified `end_number` from the datasheet information. + `end_number` The number of the end to fetch the ResistanceReactance for. + Returns a `ResistanceReactance` for the specified end, or None if one couldn't be calculated. + """ + for tti in self.transformer_tank_infos: + rr = tti.resistance_reactance(end_number) + if rr is not None: + return rr + else: + return None + + def num_transformer_tank_infos(self): + """ + Get the number of `TransformerTankInfo`s associated with this `PowerTransformerInfo`. + """ + return nlen(self._transformer_tank_infos) + def get_transformer_tank_info(self, mrid: str) -> TransformerTankInfo: """ Get the `TransformerTankInfo` for this `PowerTransformerInfo` identified by `mrid`. @@ -90,16 +103,3 @@ def clear_transformer_tank_infos(self) -> PowerTransformerInfo: """ self._transformer_tank_infos = None return self - - def resistance_reactance(self, end_number: int) -> Optional[ResistanceReactance]: - """ - Get the `ResistanceReactance` for the specified `end_number` from the datasheet information. - `end_number` The number of the end to fetch the ResistanceReactance for. - Returns a `ResistanceReactance` for the specified end, or None if one couldn't be calculated. - """ - for tti in self.transformer_tank_infos: - rr = tti.resistance_reactance(end_number) - if rr is not None: - return rr - else: - return None diff --git a/src/zepben/ewb/model/cim/iec61968/assetinfo/transformer_tank_info.py b/src/zepben/ewb/model/cim/iec61968/assetinfo/transformer_tank_info.py index 17948c927..79d84f371 100644 --- a/src/zepben/ewb/model/cim/iec61968/assetinfo/transformer_tank_info.py +++ b/src/zepben/ewb/model/cim/iec61968/assetinfo/transformer_tank_info.py @@ -35,12 +35,6 @@ def __init__(self, *args, transformer_end_infos: List[TransformerEndInfo] = None for tei in transformer_end_infos: self.add_transformer_end_info(tei) - def num_transformer_end_infos(self): - """ - Get the number of `TransformerEndInfo`s associated with this `TransformerTankInfo`. - """ - return nlen(self._transformer_end_infos) - @property def transformer_end_infos(self) -> Generator[TransformerEndInfo, None, None]: """ @@ -48,6 +42,26 @@ def transformer_end_infos(self) -> Generator[TransformerEndInfo, None, None]: """ return ngen(self._transformer_end_infos) + def resistance_reactance(self, end_number: int) -> Optional[ResistanceReactance]: + """ + Get the `ResistanceReactance` for the specified `end_number` from the datasheet information. + `end_number` The number of the end to fetch the ResistanceReactance for. + Returns a `ResistanceReactance` for the specified end, or None if one couldn't be calculated. + """ + for tei in self.transformer_end_infos: + if tei.end_number == end_number: + rr = tei.resistance_reactance() + if rr is not None: + return rr + else: + return None + + def num_transformer_end_infos(self): + """ + Get the number of `TransformerEndInfo`s associated with this `TransformerTankInfo`. + """ + return nlen(self._transformer_end_infos) + def get_transformer_end_info(self, mrid: str) -> TransformerEndInfo: """ Get the `TransformerEndInfo` for this `TransformerTankInfo` identified by `mrid`. @@ -94,17 +108,3 @@ def clear_transformer_end_infos(self) -> TransformerTankInfo: """ self._transformer_end_infos = None return self - - def resistance_reactance(self, end_number: int) -> Optional[ResistanceReactance]: - """ - Get the `ResistanceReactance` for the specified `end_number` from the datasheet information. - `end_number` The number of the end to fetch the ResistanceReactance for. - Returns a `ResistanceReactance` for the specified end, or None if one couldn't be calculated. - """ - for tei in self.transformer_end_infos: - if tei.end_number == end_number: - rr = tei.resistance_reactance() - if rr is not None: - return rr - else: - return None diff --git a/src/zepben/ewb/model/cim/iec61968/assets/asset.py b/src/zepben/ewb/model/cim/iec61968/assets/asset.py index 975ad67ac..ce0e138f4 100644 --- a/src/zepben/ewb/model/cim/iec61968/assets/asset.py +++ b/src/zepben/ewb/model/cim/iec61968/assets/asset.py @@ -46,12 +46,6 @@ def __init__(self, *args, organisation_roles: List[AssetOrganisationRole] = None for resource in power_system_resources: self.add_power_system_resource(resource) - def num_organisation_roles(self) -> int: - """ - Get the number of `AssetOrganisationRole`s associated with this `Asset`. - """ - return nlen(self._organisation_roles) - @property def organisation_roles(self) -> Generator[AssetOrganisationRole, None, None]: """ @@ -59,6 +53,19 @@ def organisation_roles(self) -> Generator[AssetOrganisationRole, None, None]: """ return ngen(self._organisation_roles) + @property + def power_system_resources(self) -> Generator[PowerSystemResource, None, None]: + """ + The `PowerSystemResource`s of this `Asset`. + """ + return ngen(self._power_system_resources) + + def num_organisation_roles(self) -> int: + """ + Get the number of `AssetOrganisationRole`s associated with this `Asset`. + """ + return nlen(self._organisation_roles) + def get_organisation_role(self, mrid: str) -> AssetOrganisationRole: """ Get the `AssetOrganisationRole` for this asset identified by `mrid`. @@ -107,13 +114,6 @@ def num_power_system_resources(self) -> int: """ return nlen(self._power_system_resources) - @property - def power_system_resources(self) -> Generator[PowerSystemResource, None, None]: - """ - The `PowerSystemResource`s of this `Asset`. - """ - return ngen(self._power_system_resources) - def get_power_system_resource(self, mrid: str) -> PowerSystemResource: """ Get the `PowerSystemResource` for this asset identified by `mrid`. diff --git a/src/zepben/ewb/model/cim/iec61968/common/location.py b/src/zepben/ewb/model/cim/iec61968/common/location.py index 3eb6aa109..361d964a7 100644 --- a/src/zepben/ewb/model/cim/iec61968/common/location.py +++ b/src/zepben/ewb/model/cim/iec61968/common/location.py @@ -36,12 +36,6 @@ def __init__(self, *args, position_points: List[PositionPoint] = None, **kwargs) for point in position_points: self.add_point(point) - def num_points(self): - """ - Returns The number of `PositionPoint`s in this `Location` - """ - return nlen(self._position_points) - @property def points(self) -> Generator[PositionPoint, None, None]: """ @@ -50,6 +44,21 @@ def points(self) -> Generator[PositionPoint, None, None]: for point in ngen(self._position_points): yield point + def for_each_point(self, action: Callable[[int, PositionPoint], Any]): + """ + Call the `action` on each :class:`PositionPoint` in the `points` collection + + :param action: An action to apply to each :class:`PositionPoint` in the `points` collection, taking the index of the point, and the point itself. + """ + for index, point in enumerate(self.points): + action(index, point) + + def num_points(self): + """ + Returns The number of `PositionPoint`s in this `Location` + """ + return nlen(self._position_points) + def get_point(self, sequence_number: int) -> PositionPoint: """ Get the `sequence_number` `PositionPoint` for this `Location`. @@ -63,15 +72,6 @@ def get_point(self, sequence_number: int) -> PositionPoint: def __getitem__(self, item): return self.get_point(item) - def for_each_point(self, action: Callable[[int, PositionPoint], Any]): - """ - Call the `action` on each :class:`PositionPoint` in the `points` collection - - :param action: An action to apply to each :class:`PositionPoint` in the `points` collection, taking the index of the point, and the point itself. - """ - for index, point in enumerate(self.points): - action(index, point) - def add_point(self, point: PositionPoint) -> Location: """ Associate a `PositionPoint` with this `Location`, assigning it a sequence_number of `num_points`. diff --git a/src/zepben/ewb/model/cim/iec61968/customers/customer.py b/src/zepben/ewb/model/cim/iec61968/customers/customer.py index 0aa212301..1fd03ab43 100644 --- a/src/zepben/ewb/model/cim/iec61968/customers/customer.py +++ b/src/zepben/ewb/model/cim/iec61968/customers/customer.py @@ -38,12 +38,6 @@ def __init__(self, *args, customer_agreements: List[CustomerAgreement] = None, * for agreement in customer_agreements: self.add_agreement(agreement) - def num_agreements(self) -> int: - """ - Get the number of `CustomerAgreement`s associated with this `Customer`. - """ - return nlen(self._customer_agreements) - @property def agreements(self) -> Generator[CustomerAgreement, None, None]: """ @@ -51,6 +45,12 @@ def agreements(self) -> Generator[CustomerAgreement, None, None]: """ return ngen(self._customer_agreements) + def num_agreements(self) -> int: + """ + Get the number of `CustomerAgreement`s associated with this `Customer`. + """ + return nlen(self._customer_agreements) + def get_agreement(self, mrid: str) -> CustomerAgreement: """ Get the `CustomerAgreement` for this `Customer` identified by `mrid`. diff --git a/src/zepben/ewb/model/cim/iec61968/customers/customer_agreement.py b/src/zepben/ewb/model/cim/iec61968/customers/customer_agreement.py index ef07543b4..836c36b02 100644 --- a/src/zepben/ewb/model/cim/iec61968/customers/customer_agreement.py +++ b/src/zepben/ewb/model/cim/iec61968/customers/customer_agreement.py @@ -51,12 +51,6 @@ def customer(self, cust): else: raise ValueError(f"customer for {str(self)} has already been set to {self._customer}, cannot reset this field to {cust}") - def num_pricing_structures(self): - """ - The number of `PricingStructure`s associated with this `CustomerAgreement` - """ - return nlen(self._pricing_structures) - @property def pricing_structures(self) -> Generator[PricingStructure, None, None]: """ @@ -64,6 +58,12 @@ def pricing_structures(self) -> Generator[PricingStructure, None, None]: """ return ngen(self._pricing_structures) + def num_pricing_structures(self): + """ + The number of `PricingStructure`s associated with this `CustomerAgreement` + """ + return nlen(self._pricing_structures) + def get_pricing_structure(self, mrid: str) -> PricingStructure: """ Get the `PricingStructure` for this `CustomerAgreement` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61968/customers/pricing_structure.py b/src/zepben/ewb/model/cim/iec61968/customers/pricing_structure.py index df603b40d..dc8202907 100644 --- a/src/zepben/ewb/model/cim/iec61968/customers/pricing_structure.py +++ b/src/zepben/ewb/model/cim/iec61968/customers/pricing_structure.py @@ -39,12 +39,6 @@ def __init__(self, *args, tariffs: List[Tariff] = None, **kwargs): for tariff in tariffs: self.add_tariff(tariff) - def num_tariffs(self): - """ - Returns The number of `Tariff`s associated with this `PricingStructure` - """ - return nlen(self._tariffs) - @property def tariffs(self) -> Generator[Tariff, None, None]: """ @@ -52,6 +46,12 @@ def tariffs(self) -> Generator[Tariff, None, None]: """ return ngen(self._tariffs) + def num_tariffs(self): + """ + Returns The number of `Tariff`s associated with this `PricingStructure` + """ + return nlen(self._tariffs) + def get_tariff(self, mrid: str) -> Tariff: """ Get the `Tariff` for this `PricingStructure` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61968/infiec61968/infassets/pole.py b/src/zepben/ewb/model/cim/iec61968/infiec61968/infassets/pole.py index a883db230..df77d8465 100644 --- a/src/zepben/ewb/model/cim/iec61968/infiec61968/infassets/pole.py +++ b/src/zepben/ewb/model/cim/iec61968/infiec61968/infassets/pole.py @@ -32,12 +32,6 @@ def __init__(self, *args, streetlights: List[Streetlight] = None, **kwargs): for light in streetlights: self.add_streetlight(light) - def num_streetlights(self) -> int: - """ - Get the number of `Streetlight`s associated with this `Pole`. - """ - return nlen(self._streetlights) - @property def streetlights(self) -> Generator[Streetlight, None, None]: """ @@ -45,6 +39,12 @@ def streetlights(self) -> Generator[Streetlight, None, None]: """ return ngen(self._streetlights) + def num_streetlights(self) -> int: + """ + Get the number of `Streetlight`s associated with this `Pole`. + """ + return nlen(self._streetlights) + def get_streetlight(self, mrid: str) -> Streetlight: """ Get the `Streetlight` for this asset identified by `mrid`. diff --git a/src/zepben/ewb/model/cim/iec61968/metering/end_device.py b/src/zepben/ewb/model/cim/iec61968/metering/end_device.py index 16a8c95cf..fcd5210da 100644 --- a/src/zepben/ewb/model/cim/iec61968/metering/end_device.py +++ b/src/zepben/ewb/model/cim/iec61968/metering/end_device.py @@ -55,12 +55,6 @@ def __init__(self, *args, usage_points: List[UsagePoint] = None, functions: List for edf in functions: self.add_function(edf) - def num_usage_points(self): - """ - Returns The number of `UsagePoint`s associated with this `EndDevice` - """ - return nlen(self._usage_points) - @property def usage_points(self) -> Generator[UsagePoint, None, None]: """ @@ -68,6 +62,19 @@ def usage_points(self) -> Generator[UsagePoint, None, None]: """ return ngen(self._usage_points) + @property + def functions(self) -> Generator[EndDeviceFunction, None, None]: + """ + The `EndDeviceFunction`s associated with this `EndDevice` + """ + return ngen(self._functions) + + def num_usage_points(self): + """ + Returns The number of `UsagePoint`s associated with this `EndDevice` + """ + return nlen(self._usage_points) + def get_usage_point(self, mrid: str) -> UsagePoint: """ Get the `UsagePoint` for this `EndDevice` identified by `mrid` @@ -117,13 +124,6 @@ def num_functions(self): """ return nlen(self._functions) - @property - def functions(self) -> Generator[EndDeviceFunction, None, None]: - """ - The `EndDeviceFunction`s associated with this `EndDevice` - """ - return ngen(self._functions) - def get_function(self, mrid: str) -> EndDeviceFunction: """ Get the `EndDeviceFunction` for this `EndDevice` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61968/metering/usage_point.py b/src/zepben/ewb/model/cim/iec61968/metering/usage_point.py index a3add9aae..764e395cf 100644 --- a/src/zepben/ewb/model/cim/iec61968/metering/usage_point.py +++ b/src/zepben/ewb/model/cim/iec61968/metering/usage_point.py @@ -72,18 +72,6 @@ def __init__(self, *args, equipment: List[Equipment] = None, end_devices: List[E for c in contacts: self.add_contact(c) - def num_equipment(self): - """ - Returns The number of `Equipment`s associated with this `UsagePoint` - """ - return nlen(self._equipment) - - def num_end_devices(self): - """ - Returns The number of `EndDevice`s associated with this `UsagePoint` - """ - return nlen(self._end_devices) - @property def end_devices(self) -> Generator[EndDevice, None, None]: """ @@ -98,49 +86,52 @@ def equipment(self) -> Generator[Equipment, None, None]: """ return ngen(self._equipment) - def get_equipment(self, mrid: str) -> Equipment: + def is_metered(self): """ - Get the `Equipment` for this `UsagePoint` identified by `mrid` - - `mrid` The mRID of the required `Equipment` - Returns The `Equipment` with the specified `mrid` if it exists - Raises `KeyError` if `mrid` wasn't present. + Check whether this `UsagePoint` is metered. A `UsagePoint` is metered if it's associated with at least one `EndDevice`. + Returns True if this `UsagePoint` has an `EndDevice`, False otherwise. """ - return get_by_mrid(self._equipment, mrid) + return nlen(self._end_devices) > 0 - def add_equipment(self, equipment: Equipment) -> UsagePoint: - """ - Associate an `Equipment` with this `UsagePoint` + @property + def contacts(self) -> Generator[ContactDetails, None, None]: + """[ZBEX] All contact details for this `UsagePoint`""" + return ngen(self._contacts) - `equipment` The `Equipment` to associate with this `UsagePoint`. - Returns A reference to this `UsagePoint` to allow fluent use. - Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `UsagePoint`. - """ - if self._validate_reference(equipment, self.get_equipment, "An Equipment"): + def num_contacts(self): + """Get the number of entries in the `ContactDetails` collection""" + return nlen(self._contacts) + + def get_contact(self, _id: str) -> ContactDetails: + """All End devices at this usage point.""" # TODO: again, lol, also jvmsdk + try: + return next((it for it in self.contacts if it.id == _id)) + except StopIteration: + raise KeyError(_id) + + def add_contact(self, contact: ContactDetails) -> UsagePoint: + """Add a `ContactDetails` to this `UsagePoint`""" + if self._validate_reference(contact, self.get_contact, "A ContactDetails"): return self - self._equipment = list() if self._equipment is None else self._equipment - self._equipment.append(equipment) + if self._contacts is None: + self._contacts = list() + self._contacts.append(contact) return self - def remove_equipment(self, equipment: Equipment) -> UsagePoint: - """ - Disassociate an `Equipment` from this `UsagePoint` + def remove_contact(self, contact: ContactDetails) -> UsagePoint: + self._contacts = safe_remove(self._contacts, contact) + return self - `equipment` The `Equipment` to disassociate with this `UsagePoint`. - Returns A reference to this `UsagePoint` to allow fluent use. - Raises `ValueError` if `equipment` was not associated with this `UsagePoint`. - """ - self._equipment = safe_remove(self._equipment, equipment) + def clear_contacts(self) -> UsagePoint: + self._contacts = None return self - def clear_equipment(self) -> UsagePoint: + def num_end_devices(self): """ - Clear all equipment. - Returns A reference to this `UsagePoint` to allow fluent use. + Returns The number of `EndDevice`s associated with this `UsagePoint` """ - self._equipment = None - return self + return nlen(self._end_devices) def get_end_device(self, mrid: str) -> EndDevice: """ @@ -185,43 +176,52 @@ def clear_end_devices(self) -> UsagePoint: self._end_devices = None return self - def is_metered(self): + def num_equipment(self): """ - Check whether this `UsagePoint` is metered. A `UsagePoint` is metered if it's associated with at least one `EndDevice`. - Returns True if this `UsagePoint` has an `EndDevice`, False otherwise. + Returns The number of `Equipment`s associated with this `UsagePoint` """ - return nlen(self._end_devices) > 0 + return nlen(self._equipment) - @property - def contacts(self) -> Generator[ContactDetails, None, None]: - """[ZBEX] All contact details for this `UsagePoint`""" - return ngen(self._contacts) + def get_equipment(self, mrid: str) -> Equipment: + """ + Get the `Equipment` for this `UsagePoint` identified by `mrid` - def num_contacts(self): - """Get the number of entries in the `ContactDetails` collection""" - return nlen(self._contacts) + `mrid` The mRID of the required `Equipment` + Returns The `Equipment` with the specified `mrid` if it exists + Raises `KeyError` if `mrid` wasn't present. + """ + return get_by_mrid(self._equipment, mrid) - def get_contact(self, _id: str) -> ContactDetails: - """All End devices at this usage point.""" # TODO: again, lol, also jvmsdk - try: - return next((it for it in self.contacts if it.id == _id)) - except StopIteration: - raise KeyError(_id) + def add_equipment(self, equipment: Equipment) -> UsagePoint: + """ + Associate an `Equipment` with this `UsagePoint` - def add_contact(self, contact: ContactDetails) -> UsagePoint: - """Add a `ContactDetails` to this `UsagePoint`""" - if self._validate_reference(contact, self.get_contact, "A ContactDetails"): + `equipment` The `Equipment` to associate with this `UsagePoint`. + Returns A reference to this `UsagePoint` to allow fluent use. + Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `UsagePoint`. + """ + if self._validate_reference(equipment, self.get_equipment, "An Equipment"): return self - if self._contacts is None: - self._contacts = list() - self._contacts.append(contact) + self._equipment = list() if self._equipment is None else self._equipment + self._equipment.append(equipment) return self - def remove_contact(self, contact: ContactDetails) -> UsagePoint: - self._contacts = safe_remove(self._contacts, contact) + def remove_equipment(self, equipment: Equipment) -> UsagePoint: + """ + Disassociate an `Equipment` from this `UsagePoint` + + `equipment` The `Equipment` to disassociate with this `UsagePoint`. + Returns A reference to this `UsagePoint` to allow fluent use. + Raises `ValueError` if `equipment` was not associated with this `UsagePoint`. + """ + self._equipment = safe_remove(self._equipment, equipment) return self - def clear_contacts(self) -> UsagePoint: - self._contacts = None + def clear_equipment(self) -> UsagePoint: + """ + Clear all equipment. + Returns A reference to this `UsagePoint` to allow fluent use. + """ + self._equipment = None return self diff --git a/src/zepben/ewb/model/cim/iec61968/operations/operational_restriction.py b/src/zepben/ewb/model/cim/iec61968/operations/operational_restriction.py index 5c45cb2ad..ec66ae712 100644 --- a/src/zepben/ewb/model/cim/iec61968/operations/operational_restriction.py +++ b/src/zepben/ewb/model/cim/iec61968/operations/operational_restriction.py @@ -37,12 +37,6 @@ def __init__(self, *args, equipment: List[Equipment] = None, **kwargs): for eq in equipment: self.add_equipment(eq) - def num_equipment(self): - """ - Returns the number of `Equipment` associated with this `OperationalRestriction` - """ - return nlen(self._equipment) - @property def equipment(self) -> Generator[Equipment, None, None]: """ @@ -50,6 +44,12 @@ def equipment(self) -> Generator[Equipment, None, None]: """ return ngen(self._equipment) + def num_equipment(self): + """ + Returns the number of `Equipment` associated with this `OperationalRestriction` + """ + return nlen(self._equipment) + def get_equipment(self, mrid: str) -> Equipment: """ Get the `Equipment` for this `OperationalRestriction` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/conducting_equipment.py b/src/zepben/ewb/model/cim/iec61970/base/core/conducting_equipment.py index 2e83a3f6c..f93a0bf30 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/conducting_equipment.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/conducting_equipment.py @@ -78,6 +78,33 @@ def terminals(self) -> Generator[Terminal, None, None]: """ return ngen(self._terminals) + def __repr__(self): + return (f"{super(ConductingEquipment, self).__repr__()}, in_service={self.in_service}, " + f"normally_in_service={self.normally_in_service}, location={self.location}" + ) + + def _validate_terminal(self, terminal: Terminal) -> bool: + """ + Validate a terminal against this `ConductingEquipment`'s `Terminal`s. + + `terminal` The `Terminal` to validate. + Returns True if `Terminal`` is already associated with this `ConductingEquipment`, otherwise False. + Raises `ValueError` if `Terminal`s `conducting_equipment` is not this `ConductingEquipment`, + or if this `ConductingEquipment` has a different `Terminal` with the same mRID. + """ + if self._validate_reference(terminal, self.get_terminal_by_mrid, "A Terminal"): + return True + + if self._validate_reference_by_field(terminal, terminal.sequence_number, self.get_terminal_by_sn, "sequence_number"): + return True + + if not terminal.conducting_equipment: + terminal.conducting_equipment = self + + require(terminal.conducting_equipment is self, + lambda: f"Terminal {terminal} references another piece of conducting equipment {terminal.conducting_equipment}, expected {str(self)}.",) + return False + def num_terminals(self): """ Get the number of `Terminal`s for this `ConductingEquipment`. @@ -173,30 +200,3 @@ def clear_terminals(self) -> ConductingEquipment: """ self._terminals.clear() return self - - def __repr__(self): - return (f"{super(ConductingEquipment, self).__repr__()}, in_service={self.in_service}, " - f"normally_in_service={self.normally_in_service}, location={self.location}" - ) - - def _validate_terminal(self, terminal: Terminal) -> bool: - """ - Validate a terminal against this `ConductingEquipment`'s `Terminal`s. - - `terminal` The `Terminal` to validate. - Returns True if `Terminal`` is already associated with this `ConductingEquipment`, otherwise False. - Raises `ValueError` if `Terminal`s `conducting_equipment` is not this `ConductingEquipment`, - or if this `ConductingEquipment` has a different `Terminal` with the same mRID. - """ - if self._validate_reference(terminal, self.get_terminal_by_mrid, "A Terminal"): - return True - - if self._validate_reference_by_field(terminal, terminal.sequence_number, self.get_terminal_by_sn, "sequence_number"): - return True - - if not terminal.conducting_equipment: - terminal.conducting_equipment = self - - require(terminal.conducting_equipment is self, - lambda: f"Terminal {terminal} references another piece of conducting equipment {terminal.conducting_equipment}, expected {str(self)}.",) - return False diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/connectivity_node.py b/src/zepben/ewb/model/cim/iec61970/base/core/connectivity_node.py index f73a6d553..1251778e6 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/connectivity_node.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/connectivity_node.py @@ -39,12 +39,6 @@ def __init__(self, *args, terminals: List[Terminal] = None, **kwargs): def __iter__(self): return iter(self._terminals) - def num_terminals(self): - """ - Get the number of `Terminal`s for this `ConnectivityNode`. - """ - return len(self._terminals) - @property def terminals(self) -> Generator[Terminal, None, None]: """ @@ -52,6 +46,25 @@ def terminals(self) -> Generator[Terminal, None, None]: """ return ngen(self._terminals) + def is_switched(self): + return self.get_switch() is not None + + def get_switch(self): + for term in self._terminals: + try: + # All switches should implement is_open + _ = term.conducting_equipment.is_open() + return term.conducting_equipment + except AttributeError: + pass + return None + + def num_terminals(self): + """ + Get the number of `Terminal`s for this `ConnectivityNode`. + """ + return len(self._terminals) + def get_terminal(self, mrid: str) -> Terminal: """ Get the `Terminal` for this `ConnectivityNode` identified by `mrid` @@ -94,16 +107,3 @@ def clear_terminals(self) -> ConnectivityNode: """ self._terminals.clear() return self - - def is_switched(self): - return self.get_switch() is not None - - def get_switch(self): - for term in self._terminals: - try: - # All switches should implement is_open - _ = term.conducting_equipment.is_open() - return term.conducting_equipment - except AttributeError: - pass - return None diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/equipment.py b/src/zepben/ewb/model/cim/iec61970/base/core/equipment.py index 977c99d59..b5443e4bf 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/equipment.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/equipment.py @@ -136,47 +136,50 @@ def containers(self) -> Generator[EquipmentContainer, None, None]: """ return ngen(self._equipment_containers) - def num_containers(self) -> int: + def num_sites(self) -> int: """ - Returns The number of `EquipmentContainer`s associated with this `Equipment` + Returns The number of `Site`s associated with this `Equipment` """ - return nlen(self._equipment_containers) + return len(list(self.sites)) - def num_substations(self) -> int: + @property + def current_containers(self) -> Generator[EquipmentContainer, None, None]: """ - Returns The number of `zepben.ewb.model.cim.iec61970.base.core.substation.Substation`s associated with this `Equipment` + The `EquipmentContainer`s this equipment belongs to in the current state of the network. """ - return len(list(_of_type(self._equipment_containers, Substation))) + return ngen(self._current_containers) - def num_sites(self) -> int: + @property + def usage_points(self) -> Generator[UsagePoint, None, None]: """ - Returns The number of `Site`s associated with this `Equipment` + The `UsagePoint`s for this equipment. """ - return len(list(self.sites)) + return ngen(self._usage_points) - def num_normal_feeders(self) -> int: + @property + def operational_restrictions(self) -> Generator[OperationalRestriction, None, None]: """ - Returns The number of normal `Feeder`s associated with this `Equipment` + The `OperationalRestriction`s that this equipment is associated with. """ - return len(list(_of_type(self._equipment_containers, Feeder))) + return ngen(self._operational_restrictions) - def num_usage_points(self) -> int: + def num_containers(self) -> int: """ - Returns The number of `UsagePoint`s associated with this `Equipment` + Returns The number of `EquipmentContainer`s associated with this `Equipment` """ - return nlen(self._usage_points) + return nlen(self._equipment_containers) - def num_current_containers(self) -> int: + def num_substations(self) -> int: """ - Returns The number of `EquipmentContainer`s associated with this `Equipment` + Returns The number of `zepben.ewb.model.cim.iec61970.base.core.substation.Substation`s associated with this `Equipment` """ - return nlen(self._current_containers) + return len(list(_of_type(self._equipment_containers, Substation))) - def num_operational_restrictions(self) -> int: + def num_normal_feeders(self) -> int: """ - Returns The number of `OperationalRestriction`s associated with this `Equipment` + Returns The number of normal `Feeder`s associated with this `Equipment` """ - return nlen(self._operational_restrictions) + return len(list(_of_type(self._equipment_containers, Feeder))) def get_container(self, mrid: str) -> EquipmentContainer: """ @@ -221,12 +224,11 @@ def clear_containers(self) -> Equipment: self._equipment_containers = None return self - @property - def current_containers(self) -> Generator[EquipmentContainer, None, None]: + def num_current_containers(self) -> int: """ - The `EquipmentContainer`s this equipment belongs to in the current state of the network. + Returns The number of `EquipmentContainer`s associated with this `Equipment` """ - return ngen(self._current_containers) + return nlen(self._current_containers) def get_current_container(self, mrid: str) -> EquipmentContainer: """ @@ -271,12 +273,11 @@ def clear_current_containers(self) -> Equipment: self._current_containers = None return self - @property - def usage_points(self) -> Generator[UsagePoint, None, None]: + def num_usage_points(self) -> int: """ - The `UsagePoint`s for this equipment. + Returns The number of `UsagePoint`s associated with this `Equipment` """ - return ngen(self._usage_points) + return nlen(self._usage_points) def get_usage_point(self, mrid: str) -> UsagePoint: """ @@ -321,12 +322,11 @@ def clear_usage_points(self) -> Equipment: self._usage_points = None return self - @property - def operational_restrictions(self) -> Generator[OperationalRestriction, None, None]: + def num_operational_restrictions(self) -> int: """ - The `OperationalRestriction`s that this equipment is associated with. + Returns The number of `OperationalRestriction`s associated with this `Equipment` """ - return ngen(self._operational_restrictions) + return nlen(self._operational_restrictions) def get_operational_restriction(self, mrid: str) -> OperationalRestriction: """ diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/equipment_container.py b/src/zepben/ewb/model/cim/iec61970/base/core/equipment_container.py index 9b778e36e..44c2f5172 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/equipment_container.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/equipment_container.py @@ -41,12 +41,6 @@ def __init__(self, *args, equipment: List[Equipment] = None, **kwargs): for eq in equipment: self.add_equipment(eq) - def num_equipment(self): - """ - Returns The number of `Equipment` associated with this `EquipmentContainer` - """ - return nlen(self._equipment) - @property def equipment(self) -> Generator[Equipment, None, None]: """ @@ -54,55 +48,6 @@ def equipment(self) -> Generator[Equipment, None, None]: """ return ngen(self._equipment) - def get_equipment(self, mrid: str) -> Equipment: - """ - Get the `Equipment` for this `EquipmentContainer` identified by `mrid` - - `mrid` the mRID of the required `Equipment` - Returns The `Equipment` with the specified `mrid` if it exists - Raises `KeyError` if `mrid` wasn't present. - """ - if not self._equipment: - raise KeyError(mrid) - try: - return self._equipment[mrid] - except AttributeError: - raise KeyError(mrid) - - def add_equipment(self, equipment: Equipment) -> EquipmentContainer: - """ - Associate `equipment` with this `EquipmentContainer`. - - `equipment` The `Equipment` to associate with this `EquipmentContainer`. - Returns A reference to this `EquipmentContainer` to allow fluent use. - Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `EquipmentContainer`. - """ - if self._validate_reference(equipment, self.get_equipment, "An Equipment"): - return self - if self._equipment is None: - self._equipment = dict() - self._equipment[equipment.mrid] = equipment - return self - - def remove_equipment(self, equipment: Equipment) -> EquipmentContainer: - """ - Disassociate `equipment` from this `EquipmentContainer` - - `equipment` The `Equipment` to disassociate with this `EquipmentContainer`. - Returns A reference to this `EquipmentContainer` to allow fluent use. - Raises `KeyError` if `equipment` was not associated with this `EquipmentContainer`. - """ - self._equipment = safe_remove_by_id(self._equipment, equipment) - return self - - def clear_equipment(self) -> EquipmentContainer: - """ - Clear all equipment. - Returns A reference to this `EquipmentContainer` to allow fluent use. - """ - self._equipment = None - return self - @property def current_equipment(self) -> Generator[Equipment, None, None]: """ @@ -110,52 +55,6 @@ def current_equipment(self) -> Generator[Equipment, None, None]: """ return self.equipment - def num_current_equipment(self) -> int: - """ - Returns The number of `Equipment` contained in this `EquipmentContainer` in the current state of the network. - """ - return self.num_equipment() - - def get_current_equipment(self, mrid: str) -> Equipment: - """ - Get the `Equipment` contained in this `EquipmentContainer` in the current state of the network, identified by `mrid` - - `mrid` The mRID of the required `Equipment` - Returns The `Equipment` with the specified `mrid` if it exists - Raises `KeyError` if `mrid` wasn't present. - """ - return self.get_equipment(mrid) - - def add_current_equipment(self, equipment: Equipment) -> EquipmentContainer: - """ - Associate `equipment` with this `EquipmentContainer` in the current state of the network. - - `equipment` the `Equipment` to associate with this `EquipmentContainer` in the current state of the network. - Returns A reference to this `EquipmentContainer` to allow fluent use. - Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `EquipmentContainer`. - """ - self.add_equipment(equipment) - return self - - def remove_current_equipment(self, equipment: Equipment) -> EquipmentContainer: - """ - Disassociate `equipment` from this `EquipmentContainer` in the current state of the network. - - `equipment` The `Equipment` to disassociate from this `EquipmentContainer` in the current state of the network. - Returns A reference to this `EquipmentContainer` to allow fluent use. - Raises `KeyError` if `equipment` was not associated with this `EquipmentContainer`. - """ - self.remove_equipment(equipment) - return self - - def clear_current_equipment(self) -> EquipmentContainer: - """ - Clear all `Equipment` from this `EquipmentContainer` in the current state of the network. - Returns A reference to this `EquipmentContainer` to allow fluent use. - """ - self.clear_equipment() - return self - def current_feeders(self) -> Generator[Feeder, None, None]: """ Convenience function to find all of the current feeders of the equipment associated with this equipment container. @@ -246,3 +145,104 @@ def edge_terminals(self, state_operator: 'Type[NetworkStateOperators]' = None) - if t not in seen: seen.add(ct.from_terminal) yield ct.from_terminal + + def num_equipment(self): + """ + Returns The number of `Equipment` associated with this `EquipmentContainer` + """ + return nlen(self._equipment) + + def get_equipment(self, mrid: str) -> Equipment: + """ + Get the `Equipment` for this `EquipmentContainer` identified by `mrid` + + `mrid` the mRID of the required `Equipment` + Returns The `Equipment` with the specified `mrid` if it exists + Raises `KeyError` if `mrid` wasn't present. + """ + if not self._equipment: + raise KeyError(mrid) + try: + return self._equipment[mrid] + except AttributeError: + raise KeyError(mrid) + + def add_equipment(self, equipment: Equipment) -> EquipmentContainer: + """ + Associate `equipment` with this `EquipmentContainer`. + + `equipment` The `Equipment` to associate with this `EquipmentContainer`. + Returns A reference to this `EquipmentContainer` to allow fluent use. + Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `EquipmentContainer`. + """ + if self._validate_reference(equipment, self.get_equipment, "An Equipment"): + return self + if self._equipment is None: + self._equipment = dict() + self._equipment[equipment.mrid] = equipment + return self + + def remove_equipment(self, equipment: Equipment) -> EquipmentContainer: + """ + Disassociate `equipment` from this `EquipmentContainer` + + `equipment` The `Equipment` to disassociate with this `EquipmentContainer`. + Returns A reference to this `EquipmentContainer` to allow fluent use. + Raises `KeyError` if `equipment` was not associated with this `EquipmentContainer`. + """ + self._equipment = safe_remove_by_id(self._equipment, equipment) + return self + + def clear_equipment(self) -> EquipmentContainer: + """ + Clear all equipment. + Returns A reference to this `EquipmentContainer` to allow fluent use. + """ + self._equipment = None + return self + + def num_current_equipment(self) -> int: + """ + Returns The number of `Equipment` contained in this `EquipmentContainer` in the current state of the network. + """ + return self.num_equipment() + + def get_current_equipment(self, mrid: str) -> Equipment: + """ + Get the `Equipment` contained in this `EquipmentContainer` in the current state of the network, identified by `mrid` + + `mrid` The mRID of the required `Equipment` + Returns The `Equipment` with the specified `mrid` if it exists + Raises `KeyError` if `mrid` wasn't present. + """ + return self.get_equipment(mrid) + + def add_current_equipment(self, equipment: Equipment) -> EquipmentContainer: + """ + Associate `equipment` with this `EquipmentContainer` in the current state of the network. + + `equipment` the `Equipment` to associate with this `EquipmentContainer` in the current state of the network. + Returns A reference to this `EquipmentContainer` to allow fluent use. + Raises `ValueError` if another `Equipment` with the same `mrid` already exists for this `EquipmentContainer`. + """ + self.add_equipment(equipment) + return self + + def remove_current_equipment(self, equipment: Equipment) -> EquipmentContainer: + """ + Disassociate `equipment` from this `EquipmentContainer` in the current state of the network. + + `equipment` The `Equipment` to disassociate from this `EquipmentContainer` in the current state of the network. + Returns A reference to this `EquipmentContainer` to allow fluent use. + Raises `KeyError` if `equipment` was not associated with this `EquipmentContainer`. + """ + self.remove_equipment(equipment) + return self + + def clear_current_equipment(self) -> EquipmentContainer: + """ + Clear all `Equipment` from this `EquipmentContainer` in the current state of the network. + Returns A reference to this `EquipmentContainer` to allow fluent use. + """ + self.clear_equipment() + return self diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/feeder.py b/src/zepben/ewb/model/cim/iec61970/base/core/feeder.py index f703b4e77..8ca0e5aab 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/feeder.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/feeder.py @@ -111,6 +111,31 @@ def current_equipment(self) -> Generator[Equipment, None, None]: """ return ngen(self._current_equipment) + @property + def normal_energized_lv_feeders(self) -> Generator[LvFeeder, None, None]: + """ + The LV feeders that are normally energized by this feeder. + """ + return ngen(self._normal_energized_lv_feeders) + + @zbex + @property + def current_energized_lv_feeders(self) -> Generator[LvFeeder, None, None]: + """ + The LV feeders that are currently energized by this feeder. + """ + return ngen(self._current_energized_lv_feeders) + + @zbex + @property + def normal_energized_lv_substations(self) -> Generator['LvSubstation', None, None]: + return ngen(self._normal_energized_lv_substations) + + @zbex + @property + def current_energized_lv_substations(self) -> Generator['LvSubstation', None, None]: + return ngen(self._current_energized_lv_substations) + def num_current_equipment(self): """ :returns: The number of `Equipment` associated with this `Feeder` @@ -160,13 +185,6 @@ def clear_current_equipment(self) -> Feeder: self._current_equipment = None return self - @property - def normal_energized_lv_feeders(self) -> Generator[LvFeeder, None, None]: - """ - The LV feeders that are normally energized by this feeder. - """ - return ngen(self._normal_energized_lv_feeders) - def num_normal_energized_lv_feeders(self) -> int: """ Get the number of LV feeders that are normally energized by this feeder. @@ -216,14 +234,6 @@ def clear_normal_energized_lv_feeders(self) -> Feeder: self._normal_energized_lv_feeders = None return self - @zbex - @property - def current_energized_lv_feeders(self) -> Generator[LvFeeder, None, None]: - """ - The LV feeders that are currently energized by this feeder. - """ - return ngen(self._current_energized_lv_feeders) - def num_current_energized_lv_feeders(self) -> int: """ Get the number of LV feeders that are currently energized by this feeder. @@ -273,11 +283,6 @@ def clear_current_energized_lv_feeders(self) -> Feeder: self._current_energized_lv_feeders = None return self - @zbex - @property - def normal_energized_lv_substations(self) -> Generator['LvSubstation', None, None]: - return ngen(self._normal_energized_lv_substations) - def num_normal_energized_lv_substations(self) -> int: """ Get the number of entries in the normal [LvSubstation] collection. @@ -326,11 +331,6 @@ def clear_normal_energized_lv_substations(self) -> "Feeder": self._normal_energized_lv_substations = None return self - @zbex - @property - def current_energized_lv_substations(self) -> Generator['LvSubstation', None, None]: - return ngen(self._current_energized_lv_substations) - def num_current_energized_lv_substations(self) -> int: """ Get the number of entries in the current [LvSubstation] collection. diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/geographical_region.py b/src/zepben/ewb/model/cim/iec61970/base/core/geographical_region.py index 4f4be6be4..b0cf54b0a 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/geographical_region.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/geographical_region.py @@ -28,12 +28,6 @@ def __init__(self, *args, sub_geographical_regions: List[SubGeographicalRegion] for sgr in sub_geographical_regions: self.add_sub_geographical_region(sgr) - def num_sub_geographical_regions(self) -> int: - """ - Returns The number of `SubGeographicalRegion`s associated with this `GeographicalRegion` - """ - return nlen(self._sub_geographical_regions) - @property def sub_geographical_regions(self) -> Generator[SubGeographicalRegion, None, None]: """ @@ -41,6 +35,12 @@ def sub_geographical_regions(self) -> Generator[SubGeographicalRegion, None, Non """ return ngen(self._sub_geographical_regions) + def num_sub_geographical_regions(self) -> int: + """ + Returns The number of `SubGeographicalRegion`s associated with this `GeographicalRegion` + """ + return nlen(self._sub_geographical_regions) + def get_sub_geographical_region(self, mrid: str) -> SubGeographicalRegion: """ Get the `SubGeographicalRegion` for this `GeographicalRegion` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/power_system_resource.py b/src/zepben/ewb/model/cim/iec61970/base/core/power_system_resource.py index 967cee958..8d97f373e 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/power_system_resource.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/power_system_resource.py @@ -53,12 +53,6 @@ def has_controls(self) -> bool: """ return nlen(self.num_controls) > 0 - def num_assets(self) -> int: - """ - Get the number of `Asset`s associated with this `PowerSystemResource`. - """ - return nlen(self._assets) - @property def assets(self) -> Generator[Asset, None, None]: """ @@ -66,6 +60,12 @@ def assets(self) -> Generator[Asset, None, None]: """ return ngen(self._assets) + def num_assets(self) -> int: + """ + Get the number of `Asset`s associated with this `PowerSystemResource`. + """ + return nlen(self._assets) + def get_asset(self, mrid: str) -> Asset: """ Get the `Asset` associated with this `PowerSystemResource` identified by `mrid`. diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/sub_geographical_region.py b/src/zepben/ewb/model/cim/iec61970/base/core/sub_geographical_region.py index 12996f72f..5a567be73 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/sub_geographical_region.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/sub_geographical_region.py @@ -47,12 +47,6 @@ def geographical_region(self): def geographical_region(self, value): self._geographical_region = value - def num_substations(self) -> int: - """ - Returns The number of `Substation`s associated with this `SubGeographicalRegion` - """ - return nlen(self._substations) - @property def substations(self) -> Generator[Substation, None, None]: """ @@ -60,6 +54,12 @@ def substations(self) -> Generator[Substation, None, None]: """ return ngen(self._substations) + def num_substations(self) -> int: + """ + Returns The number of `Substation`s associated with this `SubGeographicalRegion` + """ + return nlen(self._substations) + def get_substation(self, mrid: str) -> Substation: """ Get the `Substation` for this `SubGeographicalRegion` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61970/base/core/substation.py b/src/zepben/ewb/model/cim/iec61970/base/core/substation.py index 8027c5382..7aaeead62 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/core/substation.py +++ b/src/zepben/ewb/model/cim/iec61970/base/core/substation.py @@ -93,60 +93,53 @@ def feeders(self) -> Generator[Feeder, None, None]: """ return ngen(self._normal_energized_feeders) - def num_feeders(self): + def num_circuits(self): """ - Returns The number of `Feeder`s associated with this `Substation` + Returns The number of `Circuit`s associated with this `Substation` """ - return nlen(self._normal_energized_feeders) + return nlen(self._circuits) - def get_feeder(self, mrid: str) -> Feeder: + def get_circuit(self, mrid: str) -> Circuit: """ - Get the `Feeder` for this `Substation` identified by `mrid` + Get the `Circuit` for this `Substation` identified by `mrid` - `mrid` The mRID of the required `Feeder` - Returns The `Feeder` with the specified `mrid` if it exists + `mrid` The mRID of the required `Circuit` + Returns The `Circuit` with the specified `mrid` if it exists Raises `KeyError` if `mrid` wasn't present. """ - return get_by_mrid(self._normal_energized_feeders, mrid) + return get_by_mrid(self._circuits, mrid) - def add_feeder(self, feeder: Feeder) -> Substation: + def add_circuit(self, circuit: Circuit) -> Substation: """ - Associate a `Feeder` with this `Substation` + Associate a `Circuit` with this `Substation` - `feeder` The `Feeder` to associate with this `Substation`. + `circuit` The `Circuit` to associate with this `Substation`. Returns A reference to this `Substation` to allow fluent use. - Raises `ValueError` if another `Feeder` with the same `mrid` already exists for this `Substation`, or if - `feeder.normal_energizing_substation` is not this `Substation`. + Raises `ValueError` if another `Circuit` with the same `mrid` already exists for this `Substation`. """ - if self._validate_reference(feeder, self.get_feeder, "A Feeder"): + if self._validate_reference(circuit, self.get_circuit, "A Circuit"): return self - - if feeder.normal_energizing_substation is None: - feeder.normal_energizing_substation = self - - require(feeder.normal_energizing_substation is self, lambda: f"{feeder} `normal_energizing_substation` property references {feeder.normal_energizing_substation}, expected {self}.") - - self._normal_energized_feeders = list() if self._normal_energized_feeders is None else self._normal_energized_feeders - self._normal_energized_feeders.append(feeder) + self._circuits = list() if self._circuits is None else self._circuits + self._circuits.append(circuit) return self - def remove_feeder(self, feeder: Feeder) -> Substation: + def remove_circuit(self, circuit: Circuit) -> Substation: """ - Disassociate `feeder` from this `Substation` + Disassociate `circuit` from this `Substation` - `feeder` The `Feeder` to disassociate from this `Substation`. + `circuit` The `Circuit` to disassociate from this `Substation`. Returns A reference to this `Substation` to allow fluent use. - Raises `ValueError` if `feeder` was not associated with this `Substation`. + Raises `ValueError` if `circuit` was not associated with this `Substation`. """ - self._normal_energized_feeders = safe_remove(self._normal_energized_feeders, feeder) + self._circuits = safe_remove(self._circuits, circuit) return self - def clear_feeders(self) -> Substation: + def clear_circuits(self) -> Substation: """ - Clear all current `Feeder`s. + Clear all current `Circuit`s. Returns A reference to this `Substation` to allow fluent use. """ - self._normal_energized_feeders = None + self._circuits = None return self def num_loops(self): @@ -247,51 +240,58 @@ def clear_energized_loops(self) -> Substation: self._energized_loops = None return self - def num_circuits(self): + def num_feeders(self): """ - Returns The number of `Circuit`s associated with this `Substation` + Returns The number of `Feeder`s associated with this `Substation` """ - return nlen(self._circuits) + return nlen(self._normal_energized_feeders) - def get_circuit(self, mrid: str) -> Circuit: + def get_feeder(self, mrid: str) -> Feeder: """ - Get the `Circuit` for this `Substation` identified by `mrid` + Get the `Feeder` for this `Substation` identified by `mrid` - `mrid` The mRID of the required `Circuit` - Returns The `Circuit` with the specified `mrid` if it exists + `mrid` The mRID of the required `Feeder` + Returns The `Feeder` with the specified `mrid` if it exists Raises `KeyError` if `mrid` wasn't present. """ - return get_by_mrid(self._circuits, mrid) + return get_by_mrid(self._normal_energized_feeders, mrid) - def add_circuit(self, circuit: Circuit) -> Substation: + def add_feeder(self, feeder: Feeder) -> Substation: """ - Associate a `Circuit` with this `Substation` + Associate a `Feeder` with this `Substation` - `circuit` The `Circuit` to associate with this `Substation`. + `feeder` The `Feeder` to associate with this `Substation`. Returns A reference to this `Substation` to allow fluent use. - Raises `ValueError` if another `Circuit` with the same `mrid` already exists for this `Substation`. + Raises `ValueError` if another `Feeder` with the same `mrid` already exists for this `Substation`, or if + `feeder.normal_energizing_substation` is not this `Substation`. """ - if self._validate_reference(circuit, self.get_circuit, "A Circuit"): + if self._validate_reference(feeder, self.get_feeder, "A Feeder"): return self - self._circuits = list() if self._circuits is None else self._circuits - self._circuits.append(circuit) + + if feeder.normal_energizing_substation is None: + feeder.normal_energizing_substation = self + + require(feeder.normal_energizing_substation is self, lambda: f"{feeder} `normal_energizing_substation` property references {feeder.normal_energizing_substation}, expected {self}.") + + self._normal_energized_feeders = list() if self._normal_energized_feeders is None else self._normal_energized_feeders + self._normal_energized_feeders.append(feeder) return self - def remove_circuit(self, circuit: Circuit) -> Substation: + def remove_feeder(self, feeder: Feeder) -> Substation: """ - Disassociate `circuit` from this `Substation` + Disassociate `feeder` from this `Substation` - `circuit` The `Circuit` to disassociate from this `Substation`. + `feeder` The `Feeder` to disassociate from this `Substation`. Returns A reference to this `Substation` to allow fluent use. - Raises `ValueError` if `circuit` was not associated with this `Substation`. + Raises `ValueError` if `feeder` was not associated with this `Substation`. """ - self._circuits = safe_remove(self._circuits, circuit) + self._normal_energized_feeders = safe_remove(self._normal_energized_feeders, feeder) return self - def clear_circuits(self) -> Substation: + def clear_feeders(self) -> Substation: """ - Clear all current `Circuit`s. + Clear all current `Feeder`s. Returns A reference to this `Substation` to allow fluent use. """ - self._circuits = None + self._normal_energized_feeders = None return self diff --git a/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram.py b/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram.py index e4098ecd3..7975de84e 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram.py +++ b/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram.py @@ -40,12 +40,6 @@ def __init__(self, *args, diagram_objects: List[DiagramObject] = None, **kwargs) for obj in diagram_objects: self.add_diagram_object(obj) - def num_diagram_objects(self): - """ - Returns The number of `DiagramObject`s associated with this `Diagram` - """ - return nlen(self._diagram_objects) - @property def diagram_objects(self) -> Generator[DiagramObject, None, None]: """ @@ -53,6 +47,12 @@ def diagram_objects(self) -> Generator[DiagramObject, None, None]: """ return ngen(self._diagram_objects) + def num_diagram_objects(self): + """ + Returns The number of `DiagramObject`s associated with this `Diagram` + """ + return nlen(self._diagram_objects) + def get_diagram_object(self, mrid: str) -> DiagramObject: """ Get the `DiagramObject` for this `Diagram` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object.py b/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object.py index 9bf75a7f0..55f4e0bba 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object.py +++ b/src/zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object.py @@ -61,12 +61,6 @@ def diagram(self, diag): else: raise ValueError(f"diagram for {str(self)} has already been set to {self._diagram}, cannot reset this field to {diag}") - def num_points(self): - """ - Returns the number of `DiagramObjectPoint`s associated with this `DiagramObject` - """ - return nlen(self._diagram_object_points) - @property def points(self) -> Generator[DiagramObjectPoint, None, None]: """ @@ -74,6 +68,21 @@ def points(self) -> Generator[DiagramObjectPoint, None, None]: """ return ngen(self._diagram_object_points) + def for_each_point(self, action: Callable[[int, DiagramObjectPoint], Any]): + """ + Call the `action` on each :class:`DiagramObjectPoint` in the `points` collection + + :param action: An action to apply to each :class:`DiagramObjectPoint` in the `points` collection, taking the index of the point, and the point itself. + """ + for index, point in enumerate(self.points): + action(index, point) + + def num_points(self): + """ + Returns the number of `DiagramObjectPoint`s associated with this `DiagramObject` + """ + return nlen(self._diagram_object_points) + def get_point(self, sequence_number: int) -> DiagramObjectPoint: """ Get the `DiagramObjectPoint` for this `DiagramObject` represented by `sequence_number` . @@ -92,15 +101,6 @@ def get_point(self, sequence_number: int) -> DiagramObjectPoint: def __getitem__(self, item: int) -> DiagramObjectPoint: return self.get_point(item) - def for_each_point(self, action: Callable[[int, DiagramObjectPoint], Any]): - """ - Call the `action` on each :class:`DiagramObjectPoint` in the `points` collection - - :param action: An action to apply to each :class:`DiagramObjectPoint` in the `points` collection, taking the index of the point, and the point itself. - """ - for index, point in enumerate(self.points): - action(index, point) - def add_point(self, point: DiagramObjectPoint) -> DiagramObject: """ Associate a `DiagramObjectPoint` with this `DiagramObject`, assigning it a sequence_number of `num_points`. diff --git a/src/zepben/ewb/model/cim/iec61970/base/generation/production/battery_unit.py b/src/zepben/ewb/model/cim/iec61970/base/generation/production/battery_unit.py index 2919d7ad8..a501e243c 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/generation/production/battery_unit.py +++ b/src/zepben/ewb/model/cim/iec61970/base/generation/production/battery_unit.py @@ -39,12 +39,6 @@ def __init__(self, *args, controls: List['BatteryControl'] = None, **kwargs): _controls: Optional[List['BatteryControl']] = None # NOTE: This is called `num_battery_controls` because `num_controls` is already used by `PowerSystemResource`. - def num_battery_controls(self): - """ - Returns The number of `BatteryControl`s associated with this `BatteryUnit` - """ - return nlen(self._controls) - @property def controls(self) -> Generator['BatteryControl', None, None]: """ @@ -52,6 +46,12 @@ def controls(self) -> Generator['BatteryControl', None, None]: """ return ngen(self._controls) + def num_battery_controls(self): + """ + Returns The number of `BatteryControl`s associated with this `BatteryUnit` + """ + return nlen(self._controls) + def get_control(self, mrid: str) -> 'BatteryControl': """ Get the `BatteryControl` for this `BatteryUnit` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py b/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py index b56861c49..c98ed592d 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py @@ -84,6 +84,72 @@ def cuts(self) -> Generator['Cut', None, None]: """The `Cut`s for this `AcLineSegment`.""" return ngen(self._cuts) + @property + def clamps(self) -> Generator['Clamp', None, None]: + """The `Clamp`s for this `AcLineSegment`.""" + return ngen(self._clamps) + + def _validate_cut(self, cut: 'Cut') -> bool: + """ + Validate a cut against this `AcLineSegment`'s `Cut`s. + + :param cut: The `Cut` to validate. + :return: True if `cut` is already associated with this `AcLineSegment`, otherwise False. + :raise ValueError: If `cut.ac_line_segment` is not this `AcLineSegment`, or if this `AcLineSegment` has a different `Cut` with the same mRID. + """ + if self._validate_reference(cut, self.get_cut, "A Cut"): + return True + + if not cut.ac_line_segment: + cut.ac_line_segment = self + + require( + cut.ac_line_segment is self, + lambda: f"{cut} `ac_line_segment` property references {cut.ac_line_segment}, expected {str(self)}.", + ) + return False + + def _validate_clamp(self, clamp: 'Clamp') -> bool: + """ + Validate a clamp against this `AcLineSegment`'s `Clamp`s. + + :param clamp: The `Clamp` to validate. + :return: True if `clamp` is already associated with this `AcLineSegment`, otherwise False. + :raise ValueError: If `clamp.ac_line_segment` is not this `AcLineSegment`, or if this `AcLineSegment` has a different `Clamp` with the same mRID. + """ + if self._validate_reference(clamp, self.get_clamp, "A Clamp"): + return True + + if not clamp.ac_line_segment: + clamp.ac_line_segment = self + + require( + clamp.ac_line_segment is self, + lambda: f"{clamp} `ac_line_segment` property references {clamp.ac_line_segment}, expected {str(self)}.", + ) + return False + + @property + def phases(self) -> Generator['AcLineSegmentPhase', None, None]: + """ + The individual phase models for this AcLineSegment. The returned collection is read only. + """ + return ngen(self._phases) + + def wire_info_for_phase(self, phase: SinglePhaseKind) -> 'WireInfo | None': + """ + Retrieve the WireInfo associated with the requested [phase]. If no specific [WireInfo] is available for the given [phase], [AcLineSegment.assetInfo] will be returned. + + :param phase: the phase to retrieve [WireInfo] for. + """ + if self._phases: + for it in self._phases: + if it.phase == phase: + return it.asset_info + return self.asset_info + else: + return self.asset_info + def num_cuts(self): """ Get the number of `Cut`s for this `AcLineSegment`. @@ -132,11 +198,6 @@ def clear_cuts(self) -> 'AcLineSegment': self._cuts.clear() return self - @property - def clamps(self) -> Generator['Clamp', None, None]: - """The `Clamp`s for this `AcLineSegment`.""" - return ngen(self._clamps) - def num_clamps(self): """ Get the number of `Clamp`s for this `AcLineSegment`. @@ -185,53 +246,6 @@ def clear_clamps(self) -> 'AcLineSegment': self._clamps.clear() return self - def _validate_cut(self, cut: 'Cut') -> bool: - """ - Validate a cut against this `AcLineSegment`'s `Cut`s. - - :param cut: The `Cut` to validate. - :return: True if `cut` is already associated with this `AcLineSegment`, otherwise False. - :raise ValueError: If `cut.ac_line_segment` is not this `AcLineSegment`, or if this `AcLineSegment` has a different `Cut` with the same mRID. - """ - if self._validate_reference(cut, self.get_cut, "A Cut"): - return True - - if not cut.ac_line_segment: - cut.ac_line_segment = self - - require( - cut.ac_line_segment is self, - lambda: f"{cut} `ac_line_segment` property references {cut.ac_line_segment}, expected {str(self)}.", - ) - return False - - def _validate_clamp(self, clamp: 'Clamp') -> bool: - """ - Validate a clamp against this `AcLineSegment`'s `Clamp`s. - - :param clamp: The `Clamp` to validate. - :return: True if `clamp` is already associated with this `AcLineSegment`, otherwise False. - :raise ValueError: If `clamp.ac_line_segment` is not this `AcLineSegment`, or if this `AcLineSegment` has a different `Clamp` with the same mRID. - """ - if self._validate_reference(clamp, self.get_clamp, "A Clamp"): - return True - - if not clamp.ac_line_segment: - clamp.ac_line_segment = self - - require( - clamp.ac_line_segment is self, - lambda: f"{clamp} `ac_line_segment` property references {clamp.ac_line_segment}, expected {str(self)}.", - ) - return False - - @property - def phases(self) -> Generator['AcLineSegmentPhase', None, None]: - """ - The individual phase models for this AcLineSegment. The returned collection is read only. - """ - return ngen(self._phases) - def num_phases(self) -> int: """ Get the number of entries in the [AcLineSegmentPhase] collection. @@ -295,17 +309,3 @@ def clear_phases(self) -> 'AcLineSegment': """ self._phases = None return self - - def wire_info_for_phase(self, phase: SinglePhaseKind) -> 'WireInfo | None': - """ - Retrieve the WireInfo associated with the requested [phase]. If no specific [WireInfo] is available for the given [phase], [AcLineSegment.assetInfo] will be returned. - - :param phase: the phase to retrieve [WireInfo] for. - """ - if self._phases: - for it in self._phases: - if it.phase == phase: - return it.asset_info - return self.asset_info - else: - return self.asset_info diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/energy_consumer.py b/src/zepben/ewb/model/cim/iec61970/base/wires/energy_consumer.py index 1852fb861..b016c64ad 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/energy_consumer.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/energy_consumer.py @@ -55,15 +55,15 @@ def __init__(self, *args, energy_consumer_phases: List[EnergyConsumerPhase] = No for phase in energy_consumer_phases: self.add_phase(phase) - def num_phases(self): - """Get the number of `EnergySourcePhase`s for this `EnergyConsumer`.""" - return nlen(self._energy_consumer_phases) - @property def phases(self) -> Generator[EnergyConsumerPhase, None, None]: """The individual phase models for this energy consumer.""" return ngen(self._energy_consumer_phases) + def num_phases(self): + """Get the number of `EnergySourcePhase`s for this `EnergyConsumer`.""" + return nlen(self._energy_consumer_phases) + def get_phase(self, mrid: str) -> EnergyConsumerPhase: """ Get the `EnergyConsumerPhase` for this `EnergyConsumer` identified by `mrid` diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py index 186ef01d9..1226c6bcb 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py @@ -94,12 +94,6 @@ def __init__(self, *args, power_transformer_ends: List[PowerTransformerEnd] = No end.power_transformer = self self.add_end(end) - def num_ends(self): - """ - Get the number of `PowerTransformerEnd`s for this `PowerTransformer`. - """ - return nlen(self._power_transformer_ends) - @property def ends(self) -> Generator[PowerTransformerEnd, None, None]: """The `PowerTransformerEnd`s for this `PowerTransformer`.""" @@ -129,6 +123,36 @@ def get_base_voltage(self, terminal: Terminal = None): else: return None + def _validate_end(self, end: PowerTransformerEnd) -> bool: + """ + Validate an end against this `PowerTransformer`'s `PowerTransformerEnd`s. + + `end` The `PowerTransformerEnd` to validate. + Returns True if `end` is already associated with this `PowerTransformer`, otherwise False. + Raises `ValueError` if `end.power_transformer` is not this `PowerTransformer`, or if this `PowerTransformer` has a different `PowerTransformerEnd` + with the same mRID. + """ + if self._validate_reference(end, self.get_end_by_mrid, "A PowerTransformerEnd"): + return True + + if self._validate_reference_by_field(end, end.end_number, self.get_end_by_num, "end_number"): + return True + + if not end.power_transformer: + end.power_transformer = self + + require( + end.power_transformer is self, + lambda: f"{end} `power_transformer` property references {end.power_transformer}, expected {str(self)}.", + ) + return False + + def num_ends(self): + """ + Get the number of `PowerTransformerEnd`s for this `PowerTransformer`. + """ + return nlen(self._power_transformer_ends) + def get_end_by_mrid(self, mrid: str) -> PowerTransformerEnd: """ Get the `PowerTransformerEnd` for this `PowerTransformer` identified by `mrid` @@ -203,27 +227,3 @@ def clear_ends(self) -> PowerTransformer: """ self._power_transformer_ends.clear() return self - - def _validate_end(self, end: PowerTransformerEnd) -> bool: - """ - Validate an end against this `PowerTransformer`'s `PowerTransformerEnd`s. - - `end` The `PowerTransformerEnd` to validate. - Returns True if `end` is already associated with this `PowerTransformer`, otherwise False. - Raises `ValueError` if `end.power_transformer` is not this `PowerTransformer`, or if this `PowerTransformer` has a different `PowerTransformerEnd` - with the same mRID. - """ - if self._validate_reference(end, self.get_end_by_mrid, "A PowerTransformerEnd"): - return True - - if self._validate_reference_by_field(end, end.end_number, self.get_end_by_num, "end_number"): - return True - - if not end.power_transformer: - end.power_transformer = self - - require( - end.power_transformer is self, - lambda: f"{end} `power_transformer` property references {end.power_transformer}, expected {str(self)}.", - ) - return False diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py index f26608ffb..4fa6b2a23 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py @@ -149,6 +149,23 @@ def rated_s(self, rated_s: Optional[int]): def s_ratings(self) -> Generator[TransformerEndRatedS, None, None]: return ngen(self._s_ratings) + def resistance_reactance(self): + """ + Get the `ResistanceReactance` for this `PowerTransformerEnd` from either: + 1. directly assigned values or + 2. the pre-calculated `starImpedance` or + 3. from the datasheet information of the associated `powerTransformer` + + If the data is not complete in any of the above it will merge in the missing values from the subsequent sources. + :return: + """ + ResistanceReactance(self.r, self.x, self.r0, self.x0).merge_if_incomplete( + lambda: self.star_impedance.resistance_reactance() if self.star_impedance is not None else None + ).merge_if_incomplete( + lambda: self.power_transformer.power_transformer_info.resistance_reactance(self.end_number) if self.power_transformer.asset_info is not None + else None + ) + def num_ratings(self) -> int: return nlen(self._s_ratings) @@ -194,20 +211,3 @@ def remove_rating_by_cooling_type(self, cooling_type: TransformerCoolingType) -> def clear_ratings(self) -> PowerTransformerEnd: self._s_ratings = None return self - - def resistance_reactance(self): - """ - Get the `ResistanceReactance` for this `PowerTransformerEnd` from either: - 1. directly assigned values or - 2. the pre-calculated `starImpedance` or - 3. from the datasheet information of the associated `powerTransformer` - - If the data is not complete in any of the above it will merge in the missing values from the subsequent sources. - :return: - """ - ResistanceReactance(self.r, self.x, self.r0, self.x0).merge_if_incomplete( - lambda: self.star_impedance.resistance_reactance() if self.star_impedance is not None else None - ).merge_if_incomplete( - lambda: self.power_transformer.power_transformer_info.resistance_reactance(self.end_number) if self.power_transformer.asset_info is not None - else None - )