The main granular assembling function, that IDENTIFIES assembly points, but does not perform the assembly on its own
    It DOES NOT change the supplied breakpoint graph in any way!!!

def identify_assembly_points(graph, bgtree, target_multicolor, exclude=None, verbose=False, verbose_destination=None):
    """
    The main granular assembling function, that IDENTIFIES assembly points, but does not perform the assembly on its own
    It DOES NOT change the supplied breakpoint graph in any way!!!
    """
    if verbose:
        print(">>Identifying assemblies for target multicolor:",
              [e.name for e in target_multicolor.multicolors.elements()], file=verbose_destination)
    guidance = bgtree.consistent_multicolors[:]
    offset = len(Multicolor.split_colors(target_multicolor, guidance=guidance,
                                         account_for_color_multiplicity_in_guidance=False)) - 1
    assemblies = []  # the overall result
    if exclude is None:
        exclude = []  # a container with single colors of genomes, that are to be considered fully assembled
    multicolor_scores = {}
    surroundings = {}
    full_irregular_multicolors = {}
    for i, cc in enumerate(graph.connected_components_subgraphs(copy=True)):
        subnets, possible_assemblies, h_support, t_support, repeats = get_irregular_subnets(cc, target_multicolor, exclude)
        for subnet in subnets:
            vertices = [vertex for vertex in subnet.nodes() if not vertex.is_irregular_vertex]
            repeats_h = {repeat for vertex in vertices for repeat in h_support[vertex]}
            repeats_t = {repeat for vertex in vertices for repeat in t_support[vertex]}
            repeats = repeats_h.intersection(repeats_t)
            for repeat in repeats:
                g = nx.Graph()
                for edge in filter(lambda edge: not edge.is_irregular_edge, subnet.edges()):
                    v1, v2 = sorted((edge.vertex1, edge.vertex2), key=lambda vertex: vertex.name)
                    if v1 in h_support and repeat in h_support[v1] and v2 in t_support and repeat in t_support[v2]:
                        before, after = get_assembly_score(graph, v1, v2, target_multicolor, bgtree,
                                                           multicolor_scores, surroundings, full_irregular_multicolors)
                        if before - after - offset > 1:
                            g.add_edge((v1, "h"), (v2, "t"), weight=before - after - offset)
                    if v1 in t_support and repeat in t_support[v1] and v2 in h_support and repeat in h_support[v2]:
                        before, after = get_assembly_score(graph, v1, v2, target_multicolor, bgtree,
                                                           multicolor_scores, surroundings, full_irregular_multicolors)
                        if before - after - offset > 1:
                            g.add_edge((v1, "t"), (v2, "h"), weight=before - after - offset)
                edges = g.edges(data=True)
                if len(edges) == 0:
                    continue
                new_edges = []
                for edge in edges:
                    first, second = edge[0], edge[1]
                    v1, v2 = sorted((first, second), key=lambda item: item[0].name)
                    new_edges.append((v1, v2, edge[2]))
                edges = sorted(new_edges, reverse=True, key=lambda e: (e[2]["weight"], e[0][0].name, e[0][1], e[1][0].name, e[0][1]))
                visited = set()
                for v1, v2, data in edges:
                    weight = data["weight"]
                    if v1 not in visited and v2 not in visited:
                        visited.add(v1)
                        visited.add(v2)
                        v1, dir1 = v1
                        v2, dir2 = v2
                        assert (dir1 == "h" and dir2 == "t") or (dir1 == "t" and dir2 == "h")
                        if dir1 == "h":
                            assemblies.append((v2, v1, weight, repeat))
                        else:
                            assemblies.append((v1, v2, weight, repeat))
    return assemblies