Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
366cc7a
Added ConductingEquipment.max_terminals and check to enforce.
chestm007 Feb 12, 2025
226d6bc
removed TracedPhases from Terminal
chestm007 Feb 12, 2025
113ecf3
renamed src/zepben/evolve/services/network/tracing/traversals directo…
chestm007 Feb 12, 2025
45fba0b
implement network/tracing/networktrace/operators, not 100% happy with…
chestm007 Feb 12, 2025
278cf70
getting there with the traversal directory, a few conversation items …
chestm007 Feb 14, 2025
1e58361
Traversal directory done, a few others have been done
chestm007 Feb 26, 2025
83abb4e
Networktrace directory is done, aside from alot of bugs and some TODO's
chestm007 Feb 27, 2025
9166e22
Moved NominalPhasePath
chestm007 Mar 4, 2025
525ee53
Whole lotta changes, expect cyclic import errors at the least, just c…
chestm007 Mar 11, 2025
4d9e407
Still working on getting the codebase to import
chestm007 Mar 12, 2025
65e7670
NetworkTraceQueueNext is sending me insane, i think im now at the poi…
chestm007 Mar 13, 2025
a6a814a
SetPhases next.
chestm007 Mar 17, 2025
b83e4ca
SetPhases and a few files that touched it done
chestm007 Mar 18, 2025
14523d1
yes
chestm007 Mar 18, 2025
414fa0e
tests run, now for the fun bit
chestm007 Mar 19, 2025
ce68639
fun, fun, fun, Fun, FUn, FUN, FUUUUUUUN :+1:
chestm007 Mar 19, 2025
a402b84
now to get the NetworkStateOperators magic to work
chestm007 Mar 20, 2025
645e289
Massive changes
chestm007 Mar 25, 2025
e1cc787
174 fails
chestm007 Mar 25, 2025
b1360d0
173 fails
chestm007 Mar 25, 2025
3596f65
I'm not sure this approach to queue_condition magic is the right one
chestm007 Mar 26, 2025
708e670
167 fails
chestm007 Mar 26, 2025
0ecd332
83 fails
chestm007 Mar 27, 2025
4e4c623
95 fails (only because ive unskipped the busbranch tests)
chestm007 Mar 27, 2025
43a7896
test set direction
chestm007 Mar 28, 2025
177a404
test network database schema, and some type hinting
chestm007 Mar 28, 2025
66302fd
fix file formatting
chestm007 Mar 28, 2025
5713f2c
74 fails
chestm007 Mar 28, 2025
8b370e0
71 fails - Stuff has phases now
chestm007 Mar 31, 2025
c667caa
extra reporting for test failures in obscure places
chestm007 Mar 31, 2025
9584f3d
Tidy up doc strings and reformat
chestm007 Mar 31, 2025
aaa2da0
Output the file and line missing the await in tests
chestm007 Mar 31, 2025
033a79a
70 fails
chestm007 Mar 31, 2025
624d20d
a whole lotta changes... 67 fails - still wont trace properly :angry:
chestm007 Apr 2, 2025
3e5b8bc
traversal queue is building, and listening to queue conditions
chestm007 Apr 4, 2025
23093dd
the HARDEST 5 test passes i've ever had...
chestm007 Apr 11, 2025
b2a04b0
43 fails, assign to feeders is apparently solved
chestm007 Apr 15, 2025
2c9a82f
42 fails
chestm007 Apr 15, 2025
25b4641
Angry Panda Sounds
chestm007 Apr 16, 2025
559de0f
38 fails - branching is solved
chestm007 Apr 29, 2025
043452c
29 fails.
chestm007 May 1, 2025
820a954
set/remove phases is solved
chestm007 May 8, 2025
ce4efb9
26 fails (including busbranch - its now not being skipped)
chestm007 May 9, 2025
dcf34a9
find SWER equipment is solved
chestm007 May 12, 2025
cec472e
Set Phases is solved. 19 fails
chestm007 May 12, 2025
0d62b5f
EquipmentTreeBuilder is solved - 18 fails
chestm007 May 12, 2025
4b24f7d
Tests written for Traversal Class - Also made stuff async
chestm007 May 12, 2025
0d521e6
BusBranch hax, ill tidy it up when it works - 11 fails.
chestm007 May 12, 2025
566ca17
BusBranch is solved- need to modify the busbar creation code in the test
chestm007 May 13, 2025
8d25b18
TestDirectionCondition
chestm007 May 13, 2025
5db6768
Mostly a cleanup
chestm007 May 13, 2025
571bb84
a few more tests, and functions
chestm007 May 14, 2025
77c8a08
More tests, again
chestm007 May 14, 2025
3a43227
add missing license
chestm007 May 15, 2025
6b5bf28
rollback to <3.12 syntax
chestm007 May 15, 2025
12a6cd9
more of the same
chestm007 May 15, 2025
c5c7f83
tidying up imports, docstrings, and code
chestm007 May 15, 2025
ec7d335
deleted duplicate code in busbranch
chestm007 May 15, 2025
cf8559f
added code snippet to equipment_tree_builder __doc__
chestm007 May 15, 2025
b896aee
Got rid of ugly passing objects in from the top level into NetworkTrace
chestm007 May 15, 2025
8a3c582
Support 3.9
kgreav May 16, 2025
af8edc6
update types python 3.9 compat
chestm007 May 16, 2025
b6ac0d0
Update changelog
chestm007 May 16, 2025
ed8da23
Skip failing tests for merge
chestm007 May 16, 2025
50197e7
Skip test causing Maximum recursion error on py311
chestm007 May 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Zepben Python SDK
## [0.48.0] - UNRELEASED
### Breaking Changes
* None.
* Updated to new Tracing API. All old traces will need to be re-written with the new API.

### New Features
* None.
Expand Down
37 changes: 11 additions & 26 deletions src/zepben/evolve/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
# imported in a specific order to prevent unresolved dependency errors.
#
# @formatter:off
from __future__ import annotations

from zepben.evolve.util import *


# We need to import SinglePhaseKind before anything uses PhaseCode to prevent cyclic dependencies.
from zepben.evolve.model.cim.iec61970.base.wires.single_phase_kind import *

Expand Down Expand Up @@ -147,12 +149,8 @@
from zepben.evolve.model.phases import *
from zepben.evolve.model.resistance_reactance import *

from zepben.evolve.services.network.tracing.traversals.tracker import *
from zepben.evolve.services.network.tracing.traversals.basic_tracker import *
from zepben.evolve.services.network.tracing.traversals.traversal import *
from zepben.evolve.services.network.tracing.traversals.basic_traversal import *
from zepben.evolve.services.network.tracing.traversals.queue import *
from zepben.evolve.services.network.tracing.traversals.branch_recursive_tracing import *
from zepben.evolve.services.network.tracing.traversal.traversal import *
from zepben.evolve.services.network.tracing.traversal.queue import *

from zepben.evolve.services.network.tracing.feeder.feeder_direction import *
from zepben.evolve.services.network.tracing.util import *
Expand All @@ -161,13 +159,8 @@
from zepben.evolve.services.network.translator.network_cim2proto import *
from zepben.evolve.services.network.network_service import *

from zepben.evolve.services.network.tracing.connectivity.conducting_equipment_step import *
from zepben.evolve.services.network.tracing.connectivity.conducting_equipment_step_tracker import *
from zepben.evolve.services.network.tracing.connectivity.connected_equipment_trace import *
from zepben.evolve.services.network.tracing.connectivity.connectivity_result import *
from zepben.evolve.services.network.tracing.connectivity.connectivity_tracker import *
from zepben.evolve.services.network.tracing.connectivity.connectivity_trace import *
from zepben.evolve.services.network.tracing.connectivity.limited_connected_equipment_trace import *
from zepben.evolve.services.network.tracing.connectivity.nominal_phase_path import *
from zepben.evolve.services.network.tracing.connectivity.phase_paths import *
from zepben.evolve.services.network.tracing.connectivity.terminal_connectivity_connected import *
from zepben.evolve.services.network.tracing.connectivity.terminal_connectivity_internal import *
Expand All @@ -177,24 +170,14 @@
from zepben.evolve.services.network.tracing.feeder.direction_status import *
from zepben.evolve.services.network.tracing.feeder.assign_to_feeders import *
from zepben.evolve.services.network.tracing.feeder.assign_to_lv_feeders import *
from zepben.evolve.services.network.tracing.feeder.associated_terminal_trace import *
from zepben.evolve.services.network.tracing.feeder.associated_terminal_tracker import *
from zepben.evolve.services.network.tracing.feeder.set_direction import *
from zepben.evolve.services.network.tracing.feeder.remove_direction import *
from zepben.evolve.services.network.tracing.phases.phase_step import *
from zepben.evolve.services.network.tracing.phases.phase_status import *
from zepben.evolve.services.network.tracing.phases.phase_step_tracker import *
from zepben.evolve.services.network.tracing.phases.phase_trace import *
from zepben.evolve.services.network.tracing.phases.set_phases import *
from zepben.evolve.services.network.tracing.phases.phase_inferrer import *
from zepben.evolve.services.network.tracing.phases.remove_phases import *
from zepben.evolve.services.network.tracing.tree.downstream_tree import *
from zepben.evolve.services.network.tracing.tree.tree_node import *
from zepben.evolve.services.network.tracing.tree.tree_node_tracker import *
from zepben.evolve.services.network.tracing.find import *
from zepben.evolve.services.network.tracing.find_swer_equipment import *
from zepben.evolve.services.network.tracing.tracing import *
from zepben.evolve.services.network.tracing import tracing
from zepben.evolve.services.network.tracing.traversal.queue_condition import *
from zepben.evolve.services.network.tracing.traversal.context_value_computer import *
from zepben.evolve.services.network.tracing.traversal.step_action import StepAction
from zepben.evolve.services.network.tracing.feeder.set_direction import *

from zepben.evolve.services.common.meta.data_source import *
from zepben.evolve.services.common.meta.metadata_collection import *
Expand Down Expand Up @@ -440,6 +423,8 @@
from zepben.evolve.database.sqlite.network.network_database_reader import *
from zepben.evolve.database.sqlite.network.network_service_reader import *

from zepben.evolve.services.network.tracing.phases.set_phases import *

from zepben.evolve.testing.test_network_builder import *
from zepben.evolve.testing.test_traversal import *

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@
from zepben.evolve.services.network.tracing.feeder.assign_to_lv_feeders import AssignToLvFeeders

from zepben.evolve.services.network.tracing.feeder.set_direction import SetDirection
from zepben.evolve.services.network.tracing.networktrace.tracing import Tracing
from zepben.evolve.services.network.tracing.networktrace.operators.network_state_operators import NetworkStateOperators
from zepben.evolve.services.network.tracing.phases.phase_inferrer import PhaseInferrer
from zepben.evolve.services.network.tracing.phases.set_phases import SetPhases

from typing import List


class NetworkDatabaseReader(BaseDatabaseReader):
"""
Expand All @@ -44,26 +48,27 @@ def __init__(
connection: Connection,
service: NetworkService,
database_description: str,
tables: NetworkDatabaseTables = NetworkDatabaseTables(),
infer_phases: bool = None,
metadata_reader: MetadataCollectionReader = None,
service_reader: NetworkServiceReader = None,
table_version: TableVersion = TableVersion(),
set_direction: SetDirection = SetDirection(),
set_phases: SetPhases = SetPhases(),
phase_inferrer: PhaseInferrer = PhaseInferrer(),
assign_to_feeders: AssignToFeeders = AssignToFeeders(),
assign_to_lv_feeders: AssignToLvFeeders = AssignToLvFeeders()
set_feeder_direction: SetDirection = Tracing.set_direction(),
set_phases: SetPhases = Tracing.set_phases(),
phase_inferrer: PhaseInferrer = Tracing.phase_inferrer(),
assign_to_feeders: AssignToFeeders = Tracing.assign_equipment_to_feeders(),
assign_to_lv_feeders: AssignToLvFeeders = Tracing.assign_equipment_to_lv_feeders()
):
super().__init__(
connection,
metadata_reader if metadata_reader else MetadataCollectionReader(service, tables, connection),
service_reader if service_reader else NetworkServiceReader(service, tables, connection),
metadata_reader if metadata_reader else MetadataCollectionReader(service, NetworkDatabaseTables(), connection),
service_reader if service_reader else NetworkServiceReader(service, NetworkDatabaseTables(), connection),
service,
database_description,
table_version
)
self.service = service
self.set_direction = set_direction
self.infer_phases = infer_phases
self.set_feeder_direction = set_feeder_direction
self.set_phases = set_phases
self.phase_inferrer = phase_inferrer
self.assign_to_feeders = assign_to_feeders
Expand All @@ -73,20 +78,26 @@ async def _post_load(self) -> bool:
status = await super()._post_load()

self._logger.info("Applying feeder direction to network...")
await self.set_direction.run(self.service)
await self.set_feeder_direction.run(self.service, NetworkStateOperators.NORMAL)
await self.set_feeder_direction.run(self.service, NetworkStateOperators.CURRENT)
self._logger.info("Feeder direction applied to network.")

self._logger.info("Applying phases to network...")
await self.set_phases.run(self.service)
await self.phase_inferrer.run(self.service)
await self.set_phases.run(self.service, NetworkStateOperators.NORMAL)
await self.set_phases.run(self.service, NetworkStateOperators.CURRENT)
if self.infer_phases:
await self.phase_inferrer.run(self.service, NetworkStateOperators.NORMAL)
await self.phase_inferrer.run(self.service, NetworkStateOperators.CURRENT)
self._logger.info("Phasing applied to network.")

self._logger.info("Assigning equipment to feeders...")
await self.assign_to_feeders.run(self.service)
await self.assign_to_feeders.run(self.service, NetworkStateOperators.NORMAL)
await self.assign_to_feeders.run(self.service, NetworkStateOperators.CURRENT)
self._logger.info("Equipment assigned to feeders.")

self._logger.info("Assigning equipment to LV feeders...")
await self.assign_to_lv_feeders.run(self.service)
await self.assign_to_lv_feeders.run(self.service, NetworkStateOperators.NORMAL)
await self.assign_to_lv_feeders.run(self.service, NetworkStateOperators.CURRENT)
self._logger.info("Equipment assigned to LV feeders.")

self._logger.info("Validating that each equipment is assigned to a container...")
Expand All @@ -99,6 +110,17 @@ async def _post_load(self) -> bool:

return status

def _log_inferred_phases(self, normal_inferred_phases: List, current_inferred_phases: List): # FIXME: set list contents classes, this'll likely explode until then
# FIXME: im pretty sure this should be building a dict of lists, not just a simple KV store. if so, this logic is way too simple
inferred_phases = {item.conducting_equipment: item for item in normal_inferred_phases}

for it in current_inferred_phases:
ce = it.conducting_equipment
inferred_phases[ce] = (inferred_phases[ce] if inferred_phases[ce].suspect else it)

for phase in inferred_phases:
self._logger.warning(f"*** Action Required *** {phase.description()}")

def _validate_equipment_containers(self):
missing_containers = [it for it in self.service.objects(Equipment) if not it.containers]
count_by_class = Counter()
Expand Down
55 changes: 37 additions & 18 deletions src/zepben/evolve/model/busbranch/bus_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from functools import reduce
from typing import Set, Tuple, FrozenSet, Dict, Callable, Union, TypeVar, Any, List, Generic, Optional, Iterable

from zepben.evolve import BasicTraversal, Junction, BusbarSection, EquivalentBranch
from zepben.evolve import Junction, BusbarSection, EquivalentBranch, Traversal, StepContext
from zepben.evolve.model.cim.iec61970.base.core.conducting_equipment import ConductingEquipment
from zepben.evolve.model.cim.iec61970.base.core.terminal import Terminal
from zepben.evolve.model.cim.iec61970.base.wires.aclinesegment import AcLineSegment
Expand All @@ -18,6 +18,7 @@
from zepben.evolve.model.cim.iec61970.base.wires.power_transformer import PowerTransformer, PowerTransformerEnd
from zepben.evolve.model.cim.iec61970.base.wires.switch import Switch
from zepben.evolve.services.network.network_service import NetworkService
from zepben.evolve.services.network.tracing.busbranch_trace import BusBranchTrace, BusBranchTraceStep

__all__ = [
"BusBranchNetworkCreationValidator",
Expand All @@ -27,6 +28,7 @@
"TerminalGrouping"
]


BBN = TypeVar('BBN') # Bus-Branch Network
TN = TypeVar('TN') # Topological Node
TB = TypeVar('TB') # Topological Branch
Expand All @@ -36,6 +38,8 @@
EC = TypeVar('EC') # Energy Consumer
PEC = TypeVar('PEC') # Power Electronics Connection

D = TypeVar('D')


class BusBranchNetworkCreationValidator(Generic[BBN, TN, TB, EB, PT, ES, EC, PEC], metaclass=abc.ABCMeta):
"""
Expand Down Expand Up @@ -896,21 +900,26 @@ async def _group_negligible_impedance_terminals(
has_negligible_impedance: Callable[[ConductingEquipment], bool]
) -> TerminalGrouping[ConductingEquipment]:
tg = TerminalGrouping[ConductingEquipment]()
# noinspection PyArgumentList
trace = BasicTraversal(
start_item=terminal,
queue_next=_queue_terminals_across_negligible_impedance(has_negligible_impedance),
step_actions=[_process_terminal(tg, has_negligible_impedance)]

trace = (
BusBranchTrace(
queue_next=Traversal.QueueNext(_queue_terminals_across_negligible_impedance(has_negligible_impedance))
).add_start_item(terminal)
.add_step_action(_process_terminal(tg, has_negligible_impedance))
)

await trace.run()
return tg

def _create_traversal_step_object(next_item: Union[Terminal, AcLineSegment]) -> BusBranchTraceStep:
return BusBranchTraceStep(next_item)

def _process_terminal(
tg: TerminalGrouping[ConductingEquipment],
has_negligible_impedance: Callable[[ConductingEquipment], bool]
):
async def add_to_group(t: Terminal, _):
async def add_to_group(item: BusBranchTraceStep, _):
t = item.identified_object
if has_negligible_impedance(t.conducting_equipment):
tg.conducting_equipment_group.add(t.conducting_equipment)
tg.inner_terminals.add(t)
Expand All @@ -923,12 +932,17 @@ async def add_to_group(t: Terminal, _):
def _queue_terminals_across_negligible_impedance(
has_negligible_impedance: Callable[[ConductingEquipment], bool]
):
def queue_next(terminal: Terminal, traversal: BasicTraversal[Terminal]):
def queue_next(item: BusBranchTraceStep, context: StepContext, _queue_next: Callable[[BusBranchTraceStep], bool]):
terminal = item.identified_object
if terminal.connectivity_node is not None:
traversal.process_queue.extend(ot for ot in terminal.connectivity_node.terminals if ot != terminal)
for ot in terminal.connectivity_node.terminals:
if ot != terminal:
_queue_next(_create_traversal_step_object(ot))

if has_negligible_impedance(terminal.conducting_equipment):
traversal.process_queue.extend(ot for ot in terminal.conducting_equipment.terminals if ot != terminal)
for ot in terminal.conducting_equipment.terminals:
if ot != terminal:
_queue_next(_create_traversal_step_object(ot))

return queue_next

Expand All @@ -940,12 +954,13 @@ def has_common_impedance(line: AcLineSegment):
common_acls: TerminalGrouping[AcLineSegment] = TerminalGrouping()
connectivity_node_counter = Counter()

# noinspection PyArgumentList
trace = BasicTraversal(
start_item=acls,
queue_next=_queue_common_impedance_lines(common_acls, has_common_impedance),
step_actions=[_process_acls(common_acls, connectivity_node_counter)]
trace = (
BusBranchTrace(
queue_next=Traversal.QueueNext(_queue_common_impedance_lines(common_acls, has_common_impedance))
).add_start_item(acls)
.add_step_action(_process_acls(common_acls, connectivity_node_counter))
)

await trace.run()

for t in (t for line in common_acls.conducting_equipment_group for t in line.terminals):
Expand All @@ -966,7 +981,8 @@ def _process_acls(
common_acls: TerminalGrouping[AcLineSegment],
connectivity_node_counter: Counter
):
async def add_to_group(acls: AcLineSegment, _):
async def add_to_group(item: BusBranchTraceStep, _):
acls = item.identified_object
if acls in common_acls.conducting_equipment_group:
return

Expand All @@ -981,8 +997,11 @@ def _queue_common_impedance_lines(
common_acls: TerminalGrouping[AcLineSegment],
has_common_impedance: Callable[[AcLineSegment], bool]
):
def queue_next(acls: AcLineSegment, traversal: BasicTraversal[AcLineSegment]):
traversal.process_queue.extend(_next_common_acls(acls, has_common_impedance, common_acls))
def queue_next(item: BusBranchTraceStep, context: StepContext, _queue_next: Callable[[BusBranchTraceStep], bool]):
acls = item.identified_object

for it in _next_common_acls(acls, has_common_impedance, common_acls):
_queue_next(_create_traversal_step_object(it))

return queue_next

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

from __future__ import annotations

from typing import Optional
from typing import Optional, TYPE_CHECKING

from zepben.evolve.model.cim.iec61970.base.core.equipment import Equipment
from zepben.evolve.model.cim.iec61970.base.core.terminal import Terminal

if TYPE_CHECKING:
from zepben.evolve.model.cim.iec61970.base.core.terminal import Terminal

__all__ = ["AuxiliaryEquipment", "FaultIndicator"]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from __future__ import annotations

import sys
from typing import List, Optional, Generator, TYPE_CHECKING

from zepben.evolve.model.cim.iec61970.base.core.base_voltage import BaseVoltage
Expand Down Expand Up @@ -35,6 +36,7 @@ class ConductingEquipment(Equipment):
"""

_terminals: List[Terminal] = []
max_terminals = int(sys.maxsize)

def __init__(self, terminals: List[Terminal] = None, **kwargs):
super(ConductingEquipment, self).__init__(**kwargs)
Expand Down Expand Up @@ -112,10 +114,15 @@ def add_terminal(self, terminal: Terminal) -> ConductingEquipment:
`terminal` The `Terminal` to associate with this `ConductingEquipment`.
Returns A reference to this `ConductingEquipment` to allow fluent use.
Raises `ValueError` if another `Terminal` with the same `mrid` already exists for this `ConductingEquipment`.
Raises `ValueError` if `max_terminals` has already been reached.
"""
if self._validate_terminal(terminal):
return self

require (self.num_terminals() < self.max_terminals,
lambda: f"Unable to add {terminal} to {str(self)}. This conducting equipment already has the maximum number of terminals ({self.max_terminals}).")


if terminal.sequence_number == 0:
terminal.sequence_number = self.num_terminals() + 1

Expand Down
Loading