Esempio n. 1
0
 def changed_layout(self, change):
     self.selected_nodes = []
     if self.graph is None:
         self.output_graph = None
         self.display_datashader_vis(self.output_graph)
     elif len(self.graph) == 0:
         self.output_graph = None
         self.display_datashader_vis("Cannot display blank graph.")
     elif isinstance(self.graph, nx.classes.graph.Graph):
         original = hv.Graph.from_networkx(
             self.graph, self._nx_layout, **self.graph_layout_params
         )
         self.output_graph = bundle_graph(original)
         self.tap_selection_stream = streams.Tap(source=self.output_graph)
         self.tap_selection_stream.add_subscriber(self.tap_stream_subscriber)
         self.box_selection_stream = streams.BoundsXY(source=self.output_graph)
         self.box_selection_stream.add_subscriber(self.box_stream_subscriber)
         self.final_graph = self.set_options(self.output_graph)
         self.display_datashader_vis(self.final_graph)
     else:
         self.output_graph = self.strip_and_produce_rdf_graph(self.graph)
         self.tap_selection_stream = streams.Tap(source=self.output_graph)
         self.tap_selection_stream.add_subscriber(self.tap_stream_subscriber)
         self.box_selection_stream = streams.BoundsXY(source=self.output_graph)
         self.box_selection_stream.add_subscriber(self.box_stream_subscriber)
         self.final_graph = self.set_options(self.output_graph)
         self.display_datashader_vis(self.final_graph)
Esempio n. 2
0
def node_bundle_tab(filename):
    G = scripts.MakeNetworkxGraph.__makegraph__(sep_type='semicolon',
                                                nodes_df_link=filename)
    """ Make HV network """
    hv_graph = hv.Graph.from_networkx(G, nx.spring_layout,
                                      k=1).relabel('Force-Directed Spring')

    hv_graph.opts(width=650,
                  height=650,
                  xaxis=None,
                  yaxis=None,
                  padding=0.1,
                  node_size=hv.dim('size'),
                  node_color=hv.dim('node_type'),
                  cmap='YlOrBr',
                  edge_color=hv.dim('weight'),
                  edge_cmap='YlGnBu',
                  edge_line_width=hv.dim('weight'))

    bundle_graph_plot = bundle_graph(hv_graph)
    """ END HERE """

    # Output files to Flask
    renderer = hv.renderer('bokeh')
    # plot = renderer.get_plot(hv_graph, show=True).state
    bundle_plot = renderer.get_plot(bundle_graph_plot, show=True).state
    return bundle_plot
Esempio n. 3
0
def get_net(layout, bundled, shade):
    if (layout.lower() == 'circle'):
        net = hv.Graph.from_networkx(
            G, nx.layout.circular_layout).relabel('Circular Layout').opts(
                width=650, height=650, xaxis=None, yaxis=None, padding=0.1)
    elif layout.lower() == 'spring':
        net = hv.Graph.from_networkx(
            G, nx.layout.spring_layout, k=0.8, iterations=100).relabel(
                'Force-Directed Fruchterman-Reingold').opts(width=650,
                                                            height=650,
                                                            xaxis=None,
                                                            yaxis=None,
                                                            padding=0.1)
    #             , node_size=node_dict[i] for i in node_dict.keys())
    else:
        net = "Error 1: layout type must be: 'circle', 'spring'"
    net.opts(width=650,
             height=650,
             xaxis=None,
             yaxis=None,
             padding=0.1,
             edge_color_index='weight',
             edge_cmap='jet')
    if bundled:
        net = bundle_graph(net)
    if B_edge_select:
        net.opts(inspection_policy='edges')
    if shade:
        net = hd.datashade(net).opts(plot=dict(height=650, width=650))
    return net
Esempio n. 4
0
    def view_network(self):
        if self.mapdf is None:
            return pn.indicators.LoadingSpinner(value=True,
                                                width=100,
                                                height=100)
        G = get_graph(self.model_path)
        if G.order == 0:
            return pn.pane.Alert(
                f'## No network file found on {self.model_path}')
        nodeloc = list(
            filter(lambda n: n[1]['name'] == self.localities,
                   G.nodes(data=True)))
        # print(nodeloc, self.localities)
        if nodeloc == []:
            return pn.pane.Alert(f'## Please select a locality.')
        H = get_subgraph(G, nodeloc[0][0])
        partial_map = self.mapdf[self.mapdf.geocode.isin(H.nodes)]
        partial_map = partial_map.set_crs(4326)
        partial_map = partial_map.to_crs(3857)  # Converting to web mercator
        centroids = [(c.x, c.y) for c in partial_map.centroid]
        # Draw the graph using Altair
        gcs = [int(gc) for gc in partial_map.geocode]
        pos = dict(zip(gcs, centroids))

        # viz = nxa.draw_networkx(
        #     G, pos=pos,
        #     node_color='weight',
        #     cmap='viridis',
        #     width='weight',
        #     edge_color='black',
        # )

        kwargs = dict(width=800, height=800, xaxis=None, yaxis=None)
        hv.opts.defaults(opts.Nodes(**kwargs), opts.Graph(**kwargs))
        colors = ['#000000'] + hv.Cycle('Category20').values
        epi_graph = hv.Graph.from_networkx(H, positions=pos)

        epi_graph.opts(cmap=colors,
                       node_size=10,
                       edge_line_width=1,
                       directed=True,
                       node_line_color='gray',
                       edge_color='gray',
                       node_color='circle')
        tiles = gv.tile_sources.Wikipedia

        f = bundle_graph(epi_graph) * tiles
        source = epi_graph.nodes.clone()
        # print(epi_graph.nodes.data.iloc[0])
        source.data = epi_graph.nodes.data[epi_graph.nodes.data.name ==
                                           self.localities]

        return f * source.opts(color='red')
Esempio n. 5
0
    def strip_and_produce_rdf_graph(self, rdf_graph: Graph):
        """
        A function that takes in an rdflib.graph.Graph object
        and transforms it into a datashader holoviews graph.
        Also performs the sparql query on the graph that can be set
        via the 'sparql' parameter
        """

        sparql = self.sparql
        qres = rdf_graph.query(sparql)
        uri_graph = Graph()
        for row in qres:
            uri_graph.add(row)

        new_netx = rdflib_to_networkx_graph(uri_graph)
        original = hv.Graph.from_networkx(new_netx, self._nx_layout,
                                          **self.graph_layout_params)
        output_graph = bundle_graph(original)
        return output_graph
    # make sure there aren't any edges that go to a nonexistant node
    edf = edf[((edf['start'].isin(ndf['user index'])) &
               (edf['stop'].isin(ndf['user index'])))]

    # create graph and save
    #----------------------------------------------------------------------------#

    # initialize default args for Holoviews
    kwargs = dict(width=600, height=600, xaxis=None, yaxis=None)
    opts.defaults(opts.Nodes(**kwargs), opts.Graph(**kwargs))

    # construct Holoviews graph with Bokeh backend
    hv_nodes = hv.Nodes(ndf).sort()
    hv_graph = hv.Graph((edf, hv_nodes))
    hv_graph.opts(node_color='log degree',
                  node_size=10,
                  edge_line_width=1,
                  node_line_color='gray',
                  edge_hover_line_color='#DF0000')

    # bundle edges for aestheticss
    bundled = bundle_graph(hv_graph)

    # save html of interactive visualizations
    renderer.save(bundled, 'ff_reaction_graph_bundled')
    renderer.save(hv_graph, 'ff_reaction_graph')

    #----------------------------------------------------------------------------#

#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
Esempio n. 7
0
            graph = hv.Graph.from_networkx(NetworkX_Graph, nx.spectral_layout).relabel('Spectral Layout')
        else:
            graph = hv.Graph.from_networkx(NetworkX_Graph, nx.circular_layout).relabel('Circular Layout')
            layout = 'circular'
        PickleMe.pickelize(graph, new_name)
    return graph


hv_graph = makeHVGraph(layout='spring', filename='Wikipedia', NetworkX_Graph=G)

hv_graph.opts(width=650, height=650, xaxis=None, yaxis=None,
              padding=0.1, node_size=hv.dim('size'),
              node_color=hv.dim('node_type'), cmap='viridis',
              edge_color=hv.dim('weight'), edge_cmap='viridis', edge_line_width=hv.dim('weight'))

bundle_graph = bundle_graph(hv_graph)

""" END HERE """

# TO DO (Ani): add HoloMap here, on attribute iterations between 0 and 1000? play with it
frequencies = [0, 50, 100, 250, 500, 750, 1000]
hmap=hv.HoloMap(hv_graph, kdims='frequencies')
hmap

# Save files
# TO DO (Asaf):
# Output file, TO DO: add naming system based on CSV name and graph properties
hv.save(hv_graph, 'pickledtest.html', backend='bokeh')
hv.save(bundle_graph, 'pickledtestbundled.html', backend='bokeh')

# Output files to Flask
Esempio n. 8
0
def get_similarity_graphs(csv_template,
                          metadata,
                          figure_folder,
                          groupby='species',
                          ksizes=KSIZES,
                          log2sketchsizes=LOG2SKETCHSIZES,
                          molecules=MOLECULES,
                          sketch_id_template=SKETCH_ID_TEMPLATE,
                          n_neighbors=N_NEIGHBORS,
                          plaidplot=False,
                          palettes=PALETTES,
                          color_cols=COLOR_COLS,
                          verbose=False,
                          make_within_groupby_graphs=False):
    """Read similarity csvs and create holoviews graphs

    Parameters
    ----------
    csv_template : str
        format-string to insert molecule, ksize, and log2sketchsize values
        into to get csv. e.g.:
        'similarities_molecule-{molecule}_ksize-{ksize}_log2sketchsize-{log2sketchsize}.csv'
    metadata : pandas.DataFrame
        Sample-by-feature metadata encoding additional information about
        samples, such as species, cell type label, or tissue
    groupby : str
        Which column of the metadata to groupby to get sub-graphs for
    ksizes : tuple of int
        Which k-mer sizes to look for similarity files for,
        default (9, 12, 15, 21)
    log2sketchsizes : tuple of int
        Which log2 sketch sizes to look for similarity files for,
        default (10, 12, 14, 16)
    molecules : tuple of str
        Which molecules to use, default both 'dna' and 'protein'
    sketch_id_template : str
        String to use as a unique identifier for the sketch, e.g.
        'molecule-{molecule}_ksize-{ksize}_log2sketchsize-{log2sketchsize}'
    plaidplot : bool
        If true, make a clustered heatmap with the sides labeled with the
        color_cols
    palettes : dict
        Column name (must be in 'metadata') to palette name mapping
    color_cols : list
        Column names in 'metadata' to color by

    Returns
    -------
    graph_dict : dict of holoviews.Graph
        (molecule, ksize, log2sketchsize) : holoviews.Graph mapping for all
        similarity matrices found. To be used by 'draw_holoviews_graphs'

    """
    # Strip the final slash because it makes s3 stuff weird
    figure_folder = figure_folder.rstrip('/')

    iterable = itertools.product(molecules, ksizes, log2sketchsizes)
    graph_dict = {}

    categories = metadata[color_cols]

    for molecule, ksize, log2sketchsize in iterable:
        template_kwargs = dict(molecule=molecule,
                               ksize=ksize,
                               log2sketchsize=log2sketchsize)
        sketch_id = sketch_id_template.format(**template_kwargs)
        if verbose:
            print(sketch_id.replace('-', ": ").replace("_", ", "))
        csv = csv_template.format(**template_kwargs)
        try:
            similarities = pd.read_csv(csv)
        except FileNotFoundError:
            warnings.warn(f"file {csv} not found")
            # File doesn't exist yet
            continue
        similarities.index = similarities.columns
        if verbose:
            print(f"\tsimilarities.shape: {similarities.shape}")

        title = f"molecule: {molecule}, ksize: {ksize}, " \
                f"log2sketchsize: {log2sketchsize}"

        if plaidplot:
            try:
                g = sourmash_utils.plaidplot(similarities,
                                             metric='cosine',
                                             row_categories=categories,
                                             col_categories=categories,
                                             row_palette=palettes,
                                             col_palette=palettes)
                g.fig.suptitle(title)
                png = f'{figure_folder}/{sketch_id}_plaidplot.png'
                savefig(g, png, dpi=150)
            except FloatingPointError:
                warnings.warn("\tCouldn't compute linkage -- no plaidplot " \
                              "generated")

        graph, pos = build_graph_and_plot(similarities, metadata, n_neighbors,
                                          color_cols, palettes, figure_folder,
                                          sketch_id, title)

        # hv.extension('matplotlib')

        graph_hv = hv.Graph.from_networkx(graph, pos)

        graph_hv = graph_hv.opts(node_size=10,
                                 edge_line_width=1,
                                 cmap='Set2',
                                 node_color=dim(groupby),
                                 node_line_color='gray')
        bundled = bundle_graph(graph_hv)
        # hv.save(bundled, '.pdf', backend='matplotlib')
        graph_dict[(molecule, ksize, log2sketchsize)] = bundled

        if make_within_groupby_graphs:
            # make within-group (e.g. within-species) graphs
            for species, df in metadata.groupby(groupby):
                data = similarities.loc[df.index, df.index]
                figure_prefix = f"{sketch_id}_{species}"
                graph_title = f"{title} ({species})"
                build_graph_and_plot(data, df, n_neighbors, color_cols,
                                     palettes, figure_folder, figure_prefix,
                                     graph_title)

    return graph_dict
Esempio n. 9
0
graph.opts(cmap='Category20',
           edge_cmap='Category20',
           node_size=10,
           edge_line_width=1,
           node_color=dim('Id').str(),
           edge_color=dim('Source').str())

hv.save(graph, 'coloured_chord.html')

# Facebook data as graph with predifined coordinate system
kwargs = dict(width=300, height=300, xaxis=None, yaxis=None)
opts.defaults(opts.Nodes(**kwargs), opts.Graph(**kwargs))

colors = ['#000000'] + hv.Cycle('Category20').values
edges_df = pd.read_csv('data/fb_edges.csv')
fb_nodes = hv.Nodes(pd.read_csv('data/fb_nodes.csv')).sort()
fb_graph = hv.Graph((edges_df, fb_nodes), label='Facebook Circles')

fb_graph.opts(cmap=colors,
              node_size=10,
              edge_line_width=1,
              node_line_color='gray',
              node_color='circle')

hv.save(fb_graph, 'fb_graph.html')

# Bundled graph of facebook data
from holoviews.operation.datashader import datashade, bundle_graph
bundled = bundle_graph(fb_graph)
hv.save(bundled, 'fb_bundled.html')
Esempio n. 10
0
        def make_plot(self):
            from graphion.session.handler import get_directed  # dependency cycle fix

            if get_directed(self.sid):
                G = from_pandas_adjacency(df, create_using=DiGraph)
            else:
                G = from_pandas_adjacency(df, create_using=Graph)
            self.nodeCount = number_of_nodes(G)
            """
            Create NetworkX graph layout manager
            """
            if diagramType == "FORCE":
                layout = spring_layout(G,
                                       k=10.42 / sqrt(self.nodeCount),
                                       seed=server.config['SEED'])
            elif diagramType == "HIERARCHICAL":
                if self.nodeCount > 1:
                    layout = graphviz_layout(Graph([
                        (u, v, d) for u, v, d in G.edges(data=True)
                    ]),
                                             prog='dot')
                else:
                    layout = circular_layout(
                        G
                    )  # graphviz_layout does not work with one node, just display a "circular_layout"
            elif diagramType == "RADIAL":
                layout = circular_layout(G)
            else:
                pass

            # get node and edge information from graph
            nodes, nodes_coordinates = zip(*sorted(layout.items()))
            nodes_x, nodes_y = list(zip(*nodes_coordinates))

            # calculate centrality
            centrality = degree_centrality(G)
            _, nodeCentralities = zip(*sorted(centrality.items()))

            if self.nodeCount > 1:
                # get degree information
                if is_directed(G):
                    inDegreeSize = dict(G.in_degree)
                    inDegree = inDegreeSize.copy()
                    outDegreeSize = dict(G.out_degree)
                    outDegree = outDegreeSize.copy()
                    totalDegreeSize = {}
                    for n in nodes:
                        totalDegreeSize[n] = inDegreeSize[n] + outDegreeSize[n]
                    totalDegree = totalDegreeSize.copy()
                else:
                    inDegreeSize = dict(G.degree)
                    inDegree = inDegreeSize.copy()
                    outDegreeSize = inDegreeSize.copy()
                    outDegree = inDegreeSize.copy()
                    totalDegreeSize = inDegreeSize.copy()
                    totalDegree = inDegreeSize.copy()

                # get weight information
                if is_directed(G):
                    inWeightSize = dict(G.in_degree(weight='weight'))
                    inWeight = inWeightSize.copy()
                    outWeightSize = dict(G.out_degree(weight='weight'))
                    outWeight = outWeightSize.copy()
                    totalWeightSize = {}
                    for n in nodes:
                        totalWeightSize[n] = inWeightSize[n] + outWeightSize[n]
                    totalWeight = totalWeightSize.copy()
                else:
                    inWeightSize = dict(G.degree(weight='weight'))
                    inWeight = inWeightSize.copy()
                    outWeightSize = inWeightSize.copy()
                    outWeight = inWeightSize.copy()
                    totalWeightSize = inWeightSize.copy()
                    totalWeight = inWeightSize.copy()

                # Creating a scale to ensure that the node sizes don't go bananas
                minNodeSize = 0.1  # minNodeSize * maxNodeSize = minimum node size
                maxIn = -maxsize - 1
                minIn = maxsize
                maxOut = -maxsize - 1
                minOut = maxsize
                maxTot = -maxsize - 1
                minTot = maxsize
                maxInw = -maxsize - 1
                minInw = maxsize
                maxOutw = -maxsize - 1
                minOutw = maxsize
                maxTotw = -maxsize - 1
                minTotw = maxsize
                for n in nodes:
                    ind = inDegreeSize[n]
                    outd = outDegreeSize[n]
                    totd = totalDegreeSize[n]
                    inw = inWeightSize[n]
                    outw = outWeightSize[n]
                    totw = totalWeightSize[n]
                    if ind > maxIn:
                        maxIn = ind
                    elif ind < minIn:
                        minIn = ind
                    if outd > maxOut:
                        maxOut = outd
                    elif outd < minOut:
                        minOut = outd
                    if totd > maxTot:
                        maxTot = totd
                    elif totd < minTot:
                        minTot = totd
                    if inw > maxInw:
                        maxInw = inw
                    elif inw < minInw:
                        minInw = inw
                    if outw > maxOutw:
                        maxOutw = outw
                    elif outw < minOutw:
                        minOutw = outw
                    if totw > maxTotw:
                        maxTotw = totw
                    elif totw < minTotw:
                        minTotw = totw

                if maxIn == minIn:
                    sameInDegree = True
                else:
                    sameInDegree = False
                    for n in nodes:
                        result = (inDegreeSize[n] - minIn) / maxIn
                        if result < minNodeSize:
                            inDegreeSize[n] = minNodeSize
                        else:
                            inDegreeSize[n] = result
                if maxOut == minOut:
                    sameOutDegree = True
                else:
                    sameOutDegree = False
                    for n in nodes:
                        result = (outDegreeSize[n] - minOut) / maxOut
                        if result < minNodeSize:
                            outDegreeSize[n] = minNodeSize
                        else:
                            outDegreeSize[n] = result
                if maxTot == minTot:
                    sameTotalDegree = True
                else:
                    sameTotalDegree = False
                    for n in nodes:
                        result = (totalDegreeSize[n] - minTot) / maxTot
                        if result < minNodeSize:
                            totalDegreeSize[n] = minNodeSize
                        else:
                            totalDegreeSize[n] = result
                if maxInw == minInw:
                    sameInWeight = True
                else:
                    sameInWeight = False
                    for n in nodes:
                        result = (inWeightSize[n] - minInw) / maxInw
                        if result < minNodeSize:
                            inWeightSize[n] = minNodeSize
                        else:
                            inWeightSize[n] = result
                if maxOutw == minOutw:
                    sameOutWeight = True
                else:
                    sameOutWeight = False
                    for n in nodes:
                        result = (outWeightSize[n] - minOutw) / maxOutw
                        if result < minNodeSize:
                            outWeightSize[n] = minNodeSize
                        else:
                            outWeightSize[n] = result
                if maxTotw == minTotw:
                    sameTotalWeight = True
                else:
                    sameTotalWeight = False
                    for n in nodes:
                        result = (totalWeightSize[n] - minTotw) / maxTotw
                        if result < minNodeSize:
                            totalWeightSize[n] = minNodeSize
                        else:
                            totalWeightSize[n] = result

                # Making a dictionary for all attributes, and ensuring none of the values go crazy.
                attributes = {}
                maxNodeSize = 30
                for n in nodes:
                    outd = outDegreeSize[n]
                    totd = totalDegreeSize[n]
                    inw = inWeightSize[n]
                    outw = outWeightSize[n]
                    totw = totalWeightSize[n]

                    if sameInDegree:
                        ind = 1
                    else:
                        ind = inDegreeSize[n]
                    if sameOutDegree:
                        outd = 1
                    else:
                        outd = outDegreeSize[n]
                    if sameTotalDegree:
                        totd = 1
                    else:
                        totd = totalDegreeSize[n]
                    if sameInWeight:
                        inw = 1
                    else:
                        inw = inWeightSize[n]
                    if sameOutWeight:
                        outw = 1
                    else:
                        outw = outWeightSize[n]
                    if sameTotalWeight:
                        totw = 1
                    else:
                        totw = totalWeightSize[n]

                    attributes[n] = {
                        'indegreesize': ind * maxNodeSize,
                        'outdegreesize': outd * maxNodeSize,
                        'totaldegreesize': totd * maxNodeSize,
                        'inweightsize': inw * maxNodeSize,
                        'outweightsize': outw * maxNodeSize,
                        'totalweightsize': totw * maxNodeSize,
                        'indegree': inDegree[n],
                        'outdegree': outDegree[n],
                        'totaldegree': totalDegree[n],
                        'inweight': inWeight[n],
                        'outweight': outWeight[n],
                        'totalweight': totalWeight[n],
                        'count': 0
                    }

                set_node_attributes(G, attributes)
                plot = HVGraph.from_networkx(G, layout).opts(
                    directed=get_directed(self.sid), arrowhead_length=0.01)

                # disabling displaying all node info on hovering over the node
                tooltips = [('Index', '@index'), ('In-Degree', '@indegree'),
                            ('Out-Degree', '@outdegree'),
                            ('Total Degree', '@totaldegree'),
                            ('In Edge Weight', '@inweight'),
                            ('Out Edge-Weight', '@outweight'),
                            ('Total Edge-Weight', '@totalweight')]
                hover = HoverTool(tooltips=tooltips)
            else:
                attributes = {}
                for n in nodes:
                    attributes[n] = {
                        'indegreesize': 1,
                        'outdegreesize': 1,
                        'totaldegreesize': 1,
                        'inweightsize': 1,
                        'outweightsize': 1,
                        'totalweightsize': 1,
                        'indegree': 0,
                        'outdegree': 0,
                        'totaldegree': 0,
                        'inweight': 0,
                        'outweight': 0,
                        'totalweight': 0,
                        'count': 0
                    }

                set_node_attributes(G, attributes)
                plot = HVGraph.from_networkx(G, layout).opts(
                    directed=get_directed(self.sid), arrowhead_length=0.01)
                tooltips = [('Index', '@index'), ('In-Degree', '@indegree'),
                            ('Out-Degree', '@outdegree'),
                            ('Total Degree', '@totaldegree'),
                            ('In Edge Weight', '@inweight'),
                            ('Out Edge-Weight', '@outweight'),
                            ('Total Edge-Weight', '@totalweight')]
                hover = HoverTool(tooltips=tooltips)

            # Make custom dictionary with color palettes
            for c in self.colorList:
                if c == 'cividis':
                    self.colorMap[c] = Cividis256
                elif c == 'viridis':
                    self.colorMap[c] = Viridis256
                elif c == 'inferno':
                    self.colorMap[c] = Inferno256
                else:
                    self.colorMap[c] = palette[c]

            if max(nodeCentralities) > 0:
                if datashaded and self.nodeCount > 1:
                    plot = bundle_graph(plot)
            points = plot.nodes
            points.opts(cmap=self.colorMap[self.color_palette],
                        color=self.node_color,
                        size=self.node_size,
                        tools=['box_select', 'lasso_select', 'tap', hover],
                        active_tools=['wheel_zoom'],
                        toolbar='above',
                        show_legend=False,
                        width=self.size,
                        height=self.size)

            plot.opts(node_size=0,
                      node_color=None,
                      node_line_width=0,
                      node_hover_fill_color='green')
            return plot, points
Esempio n. 11
0
    labels_no_labels = labels.clone()
    labels_no_labels[:] = -1

    labels = {
        i: {
            'labels_all': labels[i],
            'labels_no_test': labels_no_test[i],
            'labels_only_train': labels_only_train[i],
            'labels_no_labels': labels_no_labels[i]
        }
        for i in range(len(labels))
    }

    print('Setting attributes')
    nx.set_node_attributes(G, labels)

    print('Bundling')
    G = bundle_graph(
        hv.Graph.from_networkx(G,
                               nx.layout.spring_layout).opts(tools=['hover']))

    cmap = [
        '#0000ff', '#8888ff', '#ffffff', '#ff8888', '#ff0000', '#00ffff',
        '#ffff00'
    ]
    draw_graph(G, 'labels_all', cmap)
    draw_graph(G, 'labels_no_test', ['#222222'] + cmap)
    draw_graph(G, 'labels_only_train', ['#222222'] + cmap)
    draw_graph(G, 'labels_no_labels', ['#222222'])