diff --git a/epdb/models.py b/epdb/models.py index 52930ad3..9b8bd633 100644 --- a/epdb/models.py +++ b/epdb/models.py @@ -2179,18 +2179,20 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMix return Edge.create(self, start_nodes, end_nodes, rule, name=name, description=description) def update_depths(self): + # Collect number of in and out links per node in_count = defaultdict(lambda: 0) out_count = defaultdict(lambda: 0) for e in self.edges: - # TODO check if this will remain for react in e.start_nodes.all(): out_count[str(react.uuid)] += 1 for prod in e.end_nodes.all(): in_count[str(prod.uuid)] += 1 - root_nodes = [] + depth_map = {} + depth_map[0] = list() + for n in self.nodes: num_parents = in_count[str(n.uuid)] if num_parents == 0: @@ -2201,28 +2203,30 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMix # Only root node may have children if out_count[str(n.uuid)] > 0: - root_nodes.append(n) + depth_map[0].append(n) - levels = [root_nodes] - seen = set() - # Do a bfs to determine depths starting with level 0 a.k.a. root nodes - for i, level_nodes in enumerate(levels): - new_level = [] + # At most depth len(nodes) is possible + for i in range(self.nodes.count()): + level_nodes = depth_map.get(i, []) + + if len(level_nodes) == 0: + break + + unique_next_level = set() for n in level_nodes: - for e in n.out_edges.all(): - for prod in e.end_nodes.all(): - if str(prod.uuid) not in seen: - old_depth = prod.depth - if old_depth != i + 1: - prod.depth = i + 1 - prod.save() + for e in self.edges: + if n in e.start_nodes.all(): + for p in e.end_nodes.all(): + unique_next_level.add(p) - new_level.append(prod) + if len(unique_next_level) > 0: + depth_map[i + 1] = list(unique_next_level) - seen.add(str(n.uuid)) - - if new_level: - levels.append(new_level) + for depth, nodes in depth_map.items(): + for n in nodes: + if n.depth != depth: + n.depth = depth + n.save() class Node(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMixin):