def graph2geojson(c_id2info, c_id2outs, graph, n2xy=None, colorer=color, id2mask=None, onto=None):
    root = graph.getRoot()

    logging.info('generalized species/reactions -> metanodes')
    merge_ubs_for_similar_reactions(root)

    r2rs_ps = get_reaction2reactants_products(root)

    meta_graph = graph.inducedSubGraph([n for n in graph.getNodes()])

    logging.info('compartments -> metanodes')
    process_compartments(c_id2info, meta_graph, n2xy)

    calculate_related_compartments(root)

    colorer(root)
    color_edges(root)

    logging.info('tlp nodes -> geojson features')
    c_id2level2features, (n2lo, e2lo) = meta_graph2features(c_id2info, c_id2outs, meta_graph, r2rs_ps, n2xy,
                                                            id2mask=id2mask, onto=onto)

    geometry = geojson.Polygon([[0, DIMENSION], [0, 0], [DIMENSION, 0], [DIMENSION, DIMENSION]])

    hidden_c_ids, c_id_hidden_ubs = filter_features(c_id2level2features)
    rescale(c_id2level2features)
    get_l2fs = lambda l2fs: {lev: geojson.FeatureCollection(features, geometry=geometry) for (lev, features) in
                             l2fs.items()}
    return {c_id: get_l2fs(l2fs) for (c_id, l2fs) in c_id2level2features.items()}, (n2lo, e2lo), \
           hidden_c_ids, c_id_hidden_ubs
def graph2geojson(c_id2info,
                  c_id2outs,
                  graph,
                  n2xy=None,
                  colorer=color,
                  id2mask=None,
                  onto=None):
    root = graph.getRoot()

    logging.info('generalized species/reactions -> metanodes')
    merge_ubs_for_similar_reactions(root)

    r2rs_ps = get_reaction2reactants_products(root)

    meta_graph = graph.inducedSubGraph([n for n in graph.getNodes()])

    logging.info('compartments -> metanodes')
    process_compartments(c_id2info, meta_graph, n2xy)

    calculate_related_compartments(root)

    colorer(root)
    color_edges(root)

    logging.info('tlp nodes -> geojson features')
    c_id2level2features, (n2lo, e2lo) = meta_graph2features(c_id2info,
                                                            c_id2outs,
                                                            meta_graph,
                                                            r2rs_ps,
                                                            n2xy,
                                                            id2mask=id2mask,
                                                            onto=onto)

    geometry = geojson.Polygon([[0, DIMENSION], [0, 0], [DIMENSION, 0],
                                [DIMENSION, DIMENSION]])

    hidden_c_ids, c_id_hidden_ubs = filter_features(c_id2level2features)
    rescale(c_id2level2features)
    get_l2fs = lambda l2fs: {
        lev: geojson.FeatureCollection(features, geometry=geometry)
        for (lev, features) in l2fs.items()
    }
    return {c_id: get_l2fs(l2fs) for (c_id, l2fs) in c_id2level2features.items()}, (n2lo, e2lo), \
           hidden_c_ids, c_id_hidden_ubs
def meta_graph2features(c_id2info, c_id2outs, meta_graph, r2rs_ps, n2xy=None, id2mask=None, onto=None):
    root = meta_graph.getRoot()

    c_id2level2features = {}
    processed = set()
    c_id2c_borders = {}
    n2layout, e2layout = {}, {}

    all_c_id2c_borders = {}
    while True:
        for c_id, sizes in c_id2c_borders.items():
            layout_inner_elements(meta_graph, c_id, *sizes)

        if n2xy:
            apply_node_coordinates(meta_graph, n2xy)

        bend_edges(meta_graph)
        straighten_edges_inside_compartments(meta_graph, all_c_id2c_borders)
        # bend_edges_around_compartments(meta_graph, (e for e in meta_graph.getEdges() if not get_e_id(e) in processed))
        # bend_species_edges(meta_graph)
        color_edges(meta_graph)
        export_elements(c_id2info, c_id2outs, c_id2level2features, meta_graph, processed, r2rs_ps, n2layout, e2layout,
                        id2mask=id2mask, onto=onto)

        metas = [n for n in meta_graph.getNodes() if meta_graph.isMetaNode(n) and TYPE_COMPARTMENT == root[TYPE][n]]
        if not metas:
            c_id2c_borders = {}
            metas = [n for n in meta_graph.getNodes() if meta_graph.isMetaNode(n)]
            if not metas:
                break
            align_generalized_ns(meta_graph)
            rotate_generalized_ns(meta_graph)
            bend_ubiquitous_edges(meta_graph, metas)
        else:
            c_id2c_borders = {root[ID][c]: get_comp_borders(c, root) for c in metas}
            all_c_id2c_borders.update(c_id2c_borders)
        open_meta_ns(meta_graph, metas)

    for c_id in c_id2info.keys():
        (name, go, (l, out_c_id)) = c_id2info[c_id]
        comp_n = comp_to_meta_node(meta_graph, c_id, go, name, out_c_id, False, n2xy)
        if not comp_n:
            continue
        bend_edges(meta_graph)
        color_edges(meta_graph)
        export_edges(c_id2level2features, c_id2outs, meta_graph, processed, e2layout,
                 id2mask=id2mask)
        metas = factor_nodes(meta_graph)
        bend_ubiquitous_edges(meta_graph, metas)
        bend_edges(meta_graph)
        metas.append(comp_n)
        color_edges(meta_graph)
        export_edges(c_id2level2features, c_id2outs, meta_graph, processed, e2layout,
                 id2mask=id2mask)
        open_meta_ns(meta_graph, metas)

    return c_id2level2features, (n2layout, e2layout)
def meta_graph2features(c_id2info,
                        c_id2outs,
                        meta_graph,
                        r2rs_ps,
                        n2xy=None,
                        id2mask=None,
                        onto=None):
    root = meta_graph.getRoot()

    c_id2level2features = {}
    processed = set()
    c_id2c_borders = {}
    n2layout, e2layout = {}, {}

    all_c_id2c_borders = {}
    while True:
        for c_id, sizes in c_id2c_borders.items():
            layout_inner_elements(meta_graph, c_id, *sizes)

        if n2xy:
            apply_node_coordinates(meta_graph, n2xy)

        bend_edges(meta_graph)
        straighten_edges_inside_compartments(meta_graph, all_c_id2c_borders)
        # bend_edges_around_compartments(meta_graph, (e for e in meta_graph.getEdges() if not get_e_id(e) in processed))
        # bend_species_edges(meta_graph)
        color_edges(meta_graph)
        export_elements(c_id2info,
                        c_id2outs,
                        c_id2level2features,
                        meta_graph,
                        processed,
                        r2rs_ps,
                        n2layout,
                        e2layout,
                        id2mask=id2mask,
                        onto=onto)

        metas = [
            n for n in meta_graph.getNodes()
            if meta_graph.isMetaNode(n) and TYPE_COMPARTMENT == root[TYPE][n]
        ]
        if not metas:
            c_id2c_borders = {}
            metas = [
                n for n in meta_graph.getNodes() if meta_graph.isMetaNode(n)
            ]
            if not metas:
                break
            align_generalized_ns(meta_graph)
            rotate_generalized_ns(meta_graph)
            bend_ubiquitous_edges(meta_graph, metas)
        else:
            c_id2c_borders = {
                root[ID][c]: get_comp_borders(c, root)
                for c in metas
            }
            all_c_id2c_borders.update(c_id2c_borders)
        open_meta_ns(meta_graph, metas)

    for c_id in c_id2info.keys():
        (name, go, (l, out_c_id)) = c_id2info[c_id]
        comp_n = comp_to_meta_node(meta_graph, c_id, go, name, out_c_id, False,
                                   n2xy)
        if not comp_n:
            continue
        bend_edges(meta_graph)
        color_edges(meta_graph)
        export_edges(c_id2level2features,
                     c_id2outs,
                     meta_graph,
                     processed,
                     e2layout,
                     id2mask=id2mask)
        metas = factor_nodes(meta_graph)
        bend_ubiquitous_edges(meta_graph, metas)
        bend_edges(meta_graph)
        metas.append(comp_n)
        color_edges(meta_graph)
        export_edges(c_id2level2features,
                     c_id2outs,
                     meta_graph,
                     processed,
                     e2layout,
                     id2mask=id2mask)
        open_meta_ns(meta_graph, metas)

    return c_id2level2features, (n2layout, e2layout)