(self, links)
| 539 | push_to_stack(new_ind) |
| 540 | |
| 541 | def build_assemblies(self, links): |
| 542 | lookup = defaultdict(dict) |
| 543 | for link in links: |
| 544 | i, j = link.idx |
| 545 | lookup[i][j] = link |
| 546 | lookup[j][i] = link |
| 547 | |
| 548 | assemblies = [] |
| 549 | assembled = set() |
| 550 | |
| 551 | # Fill the subsets with unambiguous, complete individuals |
| 552 | G = nx.Graph([link.idx for link in links]) |
| 553 | for chain in nx.connected_components(G): |
| 554 | if len(chain) == self.n_multibodyparts: |
| 555 | edges = [tuple(sorted(edge)) for edge in G.edges(chain)] |
| 556 | assembly = Assembly(self.n_multibodyparts) |
| 557 | for link in links: |
| 558 | i, j = link.idx |
| 559 | if (i, j) in edges: |
| 560 | success = assembly.add_link(link) |
| 561 | if success: |
| 562 | lookup[i].pop(j) |
| 563 | lookup[j].pop(i) |
| 564 | assembled.update(assembly._idx) |
| 565 | assemblies.append(assembly) |
| 566 | |
| 567 | if len(assemblies) == self.max_n_individuals: |
| 568 | return assemblies, assembled |
| 569 | |
| 570 | for link in sorted(links, key=lambda x: x.affinity, reverse=True): |
| 571 | if any(i in assembled for i in link.idx): |
| 572 | continue |
| 573 | assembly = Assembly(self.n_multibodyparts) |
| 574 | assembly.add_link(link) |
| 575 | self._fill_assembly(assembly, lookup, assembled, self.safe_edge, self.nan_policy) |
| 576 | for link in assembly._links: |
| 577 | i, j = link.idx |
| 578 | lookup[i].pop(j) |
| 579 | lookup[j].pop(i) |
| 580 | assembled.update(assembly._idx) |
| 581 | assemblies.append(assembly) |
| 582 | |
| 583 | # Fuse superfluous assemblies |
| 584 | n_extra = len(assemblies) - self.max_n_individuals |
| 585 | if n_extra > 0: |
| 586 | if self.safe_edge: |
| 587 | ds_old = [self.calc_assembly_mahalanobis_dist(assembly) for assembly in assemblies] |
| 588 | while len(assemblies) > self.max_n_individuals: |
| 589 | ds = [] |
| 590 | for i, j in itertools.combinations(range(len(assemblies)), 2): |
| 591 | if assemblies[j] not in assemblies[i]: |
| 592 | temp = assemblies[i] + assemblies[j] |
| 593 | d = self.calc_assembly_mahalanobis_dist(temp) |
| 594 | delta = d - max(ds_old[i], ds_old[j]) |
| 595 | ds.append((i, j, delta, d, temp)) |
| 596 | if not ds: |
| 597 | break |
| 598 | min_ = sorted(ds, key=lambda x: x[2]) |
no test coverage detected