예제 #1
0
def _nodes(node_positions, info_df=None):
    """Returns a Nodes object from a networkx graph or a list of node positions."""
    if isinstance(node_positions, dict):
        indices = sorted(np.array(list(node_positions.keys())))
        node_positions = np.array(list(node_positions.values()))[indices]

    info = _node_info(node_positions, info_df)
    kdims = ["x", "y", "index"]
    vdims = list(info.columns.drop(kdims))
    return hv.Nodes(info, kdims=kdims, vdims=vdims)
예제 #2
0
def get_graph_from_data(node_and_edges_data):
    
    node_data    = node_and_edges_data['node_data']
    source_edges = node_and_edges_data['source_edges']
    target_edges = node_and_edges_data['target_edges']

    node_data['minus_mean_deviation'] = -node_data['mean_deviation']

    nodes = hv.Nodes(data=node_data)
    
    tooltips = [('Samples', '@samples'), 
                ('Mean Deviation', '@mean_deviation'), 
                ('Index', '@index'),
                ('Partition', '@partition')]

    hover = HoverTool(tooltips = tooltips)
   
    # add labels to nodes 
    labels = hv.Labels(nodes, ['x', 'y'], 'index')

    graph = hv.Graph(((source_edges, target_edges), nodes)).opts(
                        node_color='mean_deviation', cmap='viridis',
                        node_size = 'node_sizes',
                        tools=[hover], 
                        hooks=[hook_graph],
                        height = 600,
                        responsive = True,
                        xaxis = None, yaxis=None)
    
    # add text to the right of the graph indicating the quartiles
    xpos = np.max(node_data['x'])
    ypos = list(set(node_data['y']))
    ypos.sort()
    quartile_texts = ['All', 'Lower Quartile', 
                      '2nd Quartile', '3rd Quartile', 
                      'Higher Quartile ']
    labels_quartiles = hv.Labels({'x' : xpos, 
                                  'y' : ypos, 
                               'text' : quartile_texts
                                 }, 
                                 ['x','y'], 
                                 'text')
    
    labels_quartiles.opts(xoffset = 1, align='start')

    # TODO: append the quartile texts to the plot
       
    final_graph = graph * labels    

    #final_graph.opts(
    #        opts.Labels(text_color='y', cmap='BrBG', color_levels=5))
 
    return final_graph
예제 #3
0
    def _make_progress(self):
        import holoviews as hv
        import holoviews.plotting.bokeh  # noqa

        if self._graph:
            root = get_root(self._graph)
            depth = get_depth(root, self._graph)
            breadths = get_breadths(root, self._graph)
            max_breadth = max(len(v) for v in breadths.values())
        else:
            root = None
            max_breadth, depth = 0, 0
            breadths = {}

        height = 80 + (max_breadth - 1) * 20

        edges = []
        for src, tgts in self._graph.items():
            for t in tgts:
                edges.append((src, t))

        nodes = []
        for depth, subnodes in breadths.items():
            breadth = len(subnodes)
            step = 1. / breadth
            for i, n in enumerate(subnodes[::-1]):
                if n == self._stage:
                    state = 'active'
                elif n == self._error:
                    state = 'error'
                elif n == self._next_stage:
                    state = 'next'
                else:
                    state = 'inactive'
                nodes.append((depth, step / 2. + i * step, n, state))

        cmap = {
            'inactive': 'white',
            'active': '#5cb85c',
            'error': 'red',
            'next': 'yellow'
        }

        def tap_renderer(plot, element):
            from bokeh.models import TapTool
            gr = plot.handles['glyph_renderer']
            tap = plot.state.select_one(TapTool)
            tap.renderers = [gr]

        nodes = hv.Nodes(nodes, ['x', 'y', 'Stage'],
                         'State').opts(alpha=0,
                                       default_tools=['tap'],
                                       hooks=[tap_renderer],
                                       hover_alpha=0,
                                       selection_alpha=0,
                                       nonselection_alpha=0,
                                       axiswise=True,
                                       size=10,
                                       backend='bokeh')
        self._progress_sel.source = nodes
        graph = hv.Graph((edges, nodes)).opts(edge_hover_line_color='black',
                                              node_color='State',
                                              cmap=cmap,
                                              tools=[],
                                              default_tools=['hover'],
                                              selection_policy=None,
                                              node_hover_fill_color='gray',
                                              axiswise=True,
                                              backend='bokeh')
        labels = hv.Labels(nodes, ['x', 'y'], 'Stage').opts(yoffset=-.30,
                                                            default_tools=[],
                                                            axiswise=True,
                                                            backend='bokeh')
        plot = (graph * labels * nodes) if self._linear else (graph * nodes)
        plot.opts(xaxis=None,
                  yaxis=None,
                  min_width=400,
                  responsive=True,
                  show_frame=False,
                  height=height,
                  xlim=(-0.25, depth + 0.25),
                  ylim=(0, 1),
                  default_tools=['hover'],
                  toolbar=None,
                  backend='bokeh')
        return plot
예제 #4
0
def tag_relation_net(tag_df,
                     name=None,
                     kind='coocc',
                     layout=nx.spring_layout,
                     layout_kws=None,
                     padding=None,
                     **node_adj_kws):
    """
    Explore tag relationships by create a Holoviews Graph Element. Nodes are tags
    (colored by classification), and edges occur only when those tags happen together.

    Parameters
    ----------
    tag_df :  pandas.DataFrame
        standard Nestor tag occurrence matrix. Multi-column with top-level containing
        tag classifications (named-entity NE) and 2nd level containing tags. Each row
        corresponds to a single event (MWO), with binary indicators (1-occurs, 0-does not).
    name : str
        what to name this tag relation element. Creates a Holoviews group "name".
    kind : str
        coocc :
            co-occurrence graph, where tags are connected if they occur in the same MWO,
            above the value calculated for pct_thres. Connects all types together.
        sankey :
            Directed "flow" graph, currently implemented with a (P) -> (I) -> (S) structure.
            Will require ``dag=True``. Alters default to ``similarity=count``
    layout : object (function), optional
        must take a graph object as input and output 2D coordinates for node locations
        (e.g. all networkx.layout functions). Defaults to ``networkx.spring_layout``
    layout_kws : dict, optional
        options to pass to networkx layout functions
    padding : dict, optional
        contains "x" and "y" specifications for boundaries. Defaults:
            ``{'x':(-0.05, 1.05), 'y':(-0.05, 1.05)}``
        Only valid if ``kind`` is 'coocc'.

    node_adj_kws :
        keyword arguments for ``nestor.tagtrees.tag_df_network``. Valid options are
            similarity : 'cosine' (default) or 'count'
            dag : bool, default='False', (True if ``kind='sankey'``)
            pct_thres : : int or None
                If int, between [0,100]. The lower percentile at which to
                threshold edges/adjacency.

    Returns
    -------
    graph: holoviews.Holomap or holoviews.Graph element, pending sankey or cooccurrence input.
    """
    try:
        import nestor.tagtrees
    except ImportError:
        print(
            'The tag-relation network requires the use of our trees module! Import failed!'
        )
        raise
    if name is None:
        name = 'Tag Net'
    adj_params = {
        'similarity': 'cosine',
    }

    graph_types = {
        'coocc': hv.Graph,
        'sankey': hv.Sankey,
    }

    if kind is 'sankey':
        if node_adj_kws.get('dag', True) is False:
            import warnings
            warnings.warn(
                'Sankey cannot be plotted with a co-occurrence net! Changing to DAG...'
            )
        adj_params['similarity'] = 'count'
        adj_params.update(node_adj_kws)
        adj_params['dag'] = True
    else:
        assert kind is 'coocc', 'You have passed an invalid graph type!'
        adj_params.update(node_adj_kws)

    G, node_info, edge_info = nestor.tagtrees.tag_df_network(
        tag_df[['I', 'P', 'S']], **adj_params)
    pos = pd.DataFrame(layout(G)).T.rename(columns={0: 'x', 1: 'y'})
    node_info = node_info.join(pos).reset_index().rename(
        columns={'index': 'tag'})

    nodes = hv.Nodes(node_info, kdims=['x', 'y', 'tag'], vdims=['NE', 'count'])

    # nodes = nodes.sort('NE').options(color_index='NE', cmap=opts, size='size')

    graph = graph_types[kind]((edge_info, nodes), group=name, vdims='weight')
    ops = {
        'color_index': 'NE',
        'cmap': color_opts,
        'edge_color_index': 'weight',
        'edge_cmap': 'blues',
        #     'node_size' : 'count',  # wait for HoloViews `op()` functionality!
    }

    graph = graph.options(**ops)

    if kind is 'sankey':
        return graph
    else:
        text = hv.Labels(node_info, ['x', 'y'], 'tag',
                         group=name).options(text_font_size='8pt',
                                             xoffset=0.015,
                                             yoffset=-0.015,
                                             text_align='left')
        if padding is None:
            padding = dict(x=(-1.05, 1.05), y=(-1.05, 1.05))
        return (graph * text).redim.range(**padding)
# Read in edge data
edges_df = pd.read_pickle(INPUT_EDGES_DF)

# Convert corporation ID to node index
edges_df['source'] = edges_df['source'].map(unique_to_idx)
edges_df['target'] = edges_df['target'].map(unique_to_idx)

# Color each edge according to its nodes
edges_df['color'] = edges_df.apply(get_edge_color, axis=1)

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
# Convert edge and node DataFrames into Holoviews graph, define tooltips
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

# Convert node DataFrame to HoloViews object
hv_nodes = hv.Nodes(nodes_df)

# Create HoloViews Graph object from nodes and edges, with x and y limits
# bounded by `GRAPH_EXTENTS`
hv_graph = hv.Graph((edges_df, hv_nodes), )

# Define custom hover tooltip
hover = HoverTool(tooltips=[
    ('Officer Name', '@FullName'),
    ('ID', '@IdNumber'),
    ('Company 1', '@Company1'),
    ('Company 2', '@Company2'),
    ('Company 3', '@Company3'),
])

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
    edf = pd.DataFrame(el)

    # 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')

    #----------------------------------------------------------------------------#
예제 #7
0
    # convert `source` and `target` columns to str datatype
    edges_df['source'] = edges_df['source'].astype(str)
    edges_df['target'] = edges_df['target'].astype(str)

    # use natural logarithm of edge weight, for visualization purposes
    edges_df['weight'] = np.log(edges_df['weight'].astype(float))

    # scale edge weight for visualization purposes
    edges_df['weight'] /= EDGE_SCALING

    # 4. generate visualization using HoloViews package
    #############################################################################

    # convert node DataFrame to HoloViews object
    hv_nodes = hv.Nodes(nodes_df).sort()

    # create HoloViews Graph object from nodes and edges, with x and y limits
    # bounded by `GRAPH_EXTENTS`
    hv_graph = hv.Graph((edges_df, hv_nodes), extents=GRAPH_EXTENTS)

    # define custom hover tooltip
    hover = HoverTool(tooltips=[
        ("member id", "@member_id"),
        ("name", "@name"),
        ("posts", "@posts"),
        ("messages", "@messages"),
    ])

    # specify parameters for visualization
    hv_graph.opts(node_radius='size',
예제 #8
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')
예제 #9
0
def plot_subgraph(csv_path, rel_name):
    global edges_plot
    global nodes_plot
    global node_type_size_dict
    global labels

    with open(csv_path, 'r') as w:
        data = pd.read_csv(w)

    if not (os.path.exists(f'./{rel_name}')):
        os.mkdir(f'./{rel_name}')
    
    if not (os.path.exists(f'./{rel_name}/subgraphs')):
        os.mkdir(f'./{rel_name}/subgraphs')
    
    #this is since I have CSV that does not explicitly specify node types
    data["left"] = data.Edge.apply(lambda a: a.split("-->")[0])
    data["right"] = data.Edge.apply(lambda a: a.split("-->")[1])

    #get all unique nodes
    nodes = pd.concat([data.left,data.right],ignore_index=True).drop_duplicates().reset_index(drop=True).to_frame("name").reset_index()
    data["left_index"] = nodes.set_index("name").loc[data.left,"index"].values
    data["right_index"] = nodes.set_index("name").loc[data.right,"index"].values

    #also temporary type should be in the csv
    nodes["type"] = nodes.name.apply(lambda a: "Chem/Gene" if a in data.left.values else "Disease")


    # ### Create NetworkX Graph
    # Make a directed graph from a list of edges.  
    # Also let's compute node layout as well... layout is just position of every node on the canvas

    graph = nx.DiGraph()
    graph.add_edges_from(data.loc[:,["left_index","right_index"]].values)
    layout = nx.layout.fruchterman_reingold_layout(graph.to_undirected(),.5)
    layout = pd.DataFrame(layout,index=["x","y"]).T.sort_index()
    nodes = pd.concat([nodes,layout],axis=1)


    # ## Let's Plot Some Graphs
    paths = make_paths(nodes,data)

    hv.extension("bokeh")


    nodes_plot = hv.Nodes(nodes,kdims=["x","y","index"],vdims=["name","type"]).opts(show_legend=True)
    edges_plot = hv.Graph((data,nodes_plot,paths),kdims=["left_index","right_index"],vdims=["Original_Weight","Boltzmann_Citation_Weight","Publication_Year_Weight","Publication_Year_and_Citation_Weight", "H_Index_Weight"])
    # edges_plot = bundle_graph(edges_plot)


    labels = hv.Labels(nodes,kdims=["x","y"],vdims=["name"]).opts(text_align="left", text_font_size="8pt",xoffset=.05,text_alpha = .5, text_color="white")

    weight_field = "Boltzmann_Citation_Weight"

    weights = ["Original_Weight","Boltzmann_Citation_Weight","Publication_Year_Weight","Publication_Year_and_Citation_Weight", "H_Index_Weight"]

    # need to change this
    node_type_size_dict = {"Chem/Gene":15,"Disease":30}

    out = hv.HoloMap({w: make_plot(w) for w in weights},kdims = "weight_type")


    print('Saving Subgraphs to file...')

    hv.save(out,f"./{rel_name}/subgraphs/{rel_name}_subgraph.html")

    hv.save(out,f"./{rel_name}/subgraphs/{rel_name}_img1.gif")


    # ![Subgraph](imgs/img1.gif)

    # We can also see all of them side by side


    out2 = out.opts(width=600,height=600).layout("weight_type").cols(2)

    hv.save(out2,f"./{rel_name}/subgraphs/{rel_name}_img2.png")
    hv.save(out2,f"./{rel_name}/subgraphs/{rel_name}_subgraph_side_by_side.html")
fuzzy_df.shape

label_df = pd.read_csv("PRJNA301554.hydroponic.sample_annotations.txt",
                       index_col=0,
                       sep='\t')
labels = label_df.astype('object').reset_index()

fuzzy_edges = pd.DataFrame(fuzzy_df.stack()).reset_index()
fuzzy_edges.columns = ['source', 'target', 'weight']
fuzzy_edges.head(2)

cutoff = fuzzy_edges['weight'].quantile(.95)
filtered = fuzzy_edges[fuzzy_edges['weight'] > cutoff]
print(f'Cutoff: {cutoff:.3}')
print(f'Remaining shape: {filtered.shape}')

atlas_layout = forceatlas2_layout(labels, fuzzy_edges, iterations=100)

hv_opts = {}
hv_opts['padding'] = 0.1
hv_opts['width'] = 600
hv_opts['height'] = 400
hv_opts['cmap'] = 'Set1'
hv_opts['xaxis'] = None
hv_opts['yaxis'] = None
hv_opts['size'] = 5

vdims = ['Sample', 'Treatment', 'Genotype', 'Subspecies', 'Time']
hv_nodes = hv.Nodes(atlas_layout, kdims=['x', 'y', 'index'], vdims=vdims)
hv_nodes.opts(**hv_opts)