示例#1
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
示例#2
0
 def _interval_view(self):
     import panel as pn
     import holoviews as hv
     hv.extension("bokeh")
     df = self.tree.to_df(self.label)
     self.keys = list(self.tree.keys())
     # self.values = list(self.tree.values())
     plot = hv.Segments(df, kdims=["begin", "parameter",  "end", "parameter"], vdims="data", )
     
     defaults = dict(color="data", 
                     line_width=30, alpha=0.5,
                     responsive=True,
                     height=120,
                     colorbar=True,
                     toolbar="above",
                     tools=["hover", "tap"],
                     xlabel="index",
                     nonselection_alpha=0.2,
                     nonselection_color="grey",
                     title=self.label)
     # defaults.update(opts)
     self.segments = segments = plot.opts(**defaults)
     labels = hv.Labels(df, kdims=["mid", "parameter"], vdims="label")
     plot = labels*segments
     self.selector = hv.streams.Selection1D(source=plot)
     self.selector.param.watch(self.make_tree_view, ['index'], onlychanged=True)
     self.make_tree_view()
     return pn.Column(plot, sizing_mode="stretch_width", width=700)
示例#3
0
def __size_legend(size_min, size_max, dot_min, dot_max,
                  size_tick_labels_format, size_ticks):
    size_ticks_pixels = np.interp(size_ticks, (size_min, size_max),
                                  (dot_min, dot_max))
    size_tick_labels = [size_tick_labels_format.format(x) for x in size_ticks]
    points = hv.Points(
        {
            'x': np.repeat(0.15, len(size_ticks)),
            'y': np.arange(len(size_ticks), 0, -1),
            'size': size_ticks_pixels
        },
        vdims='size').opts(xaxis=None,
                           color='black',
                           yaxis=None,
                           size=dim('size'))
    labels = hv.Labels(
        {
            'x': np.repeat(0.3, len(size_ticks)),
            'y': np.arange(len(size_ticks), 0, -1),
            'text': size_tick_labels
        }, ['x', 'y'], 'text').opts(text_align='left', text_font_size='9pt')
    overlay = (points * labels)
    overlay.opts(width=dot_max + 100,
                 height=int(len(size_ticks) * (dot_max + 12)),
                 xlim=(0, 1),
                 ylim=(0, len(size_ticks) + 1),
                 invert_yaxis=True,
                 shared_axes=False,
                 show_frame=False)
    return overlay
示例#4
0
def dictionary_pair_overlap(alpha, beta):
    overlap_dim = hv.Dimension("Overlap Count", value_format=lambda x: f"{x}")

    data = [(f"{ak}: {len(av)}", f"{bk}: {len(bv)}", len(set.intersection(set(av), set(bv))))
            for (ak, av), (bk, bv) in itertools.product(alpha.items(), beta.items())]

    heatmap = hv.HeatMap(data, vdims=overlap_dim).opts(labelled=[], colorbar=True)
    return heatmap * hv.Labels(heatmap)
示例#5
0
def gen_labels(df):

    labels = hv.Labels({
        ('x', 'y'): df[['x', 'y']],
        'text': list(df['labels'])
    }, ['x', 'y'], 'text').options(xoffset=0.2,
                                   yoffset=0.05)  #, apply_ranges=False)

    return labels
示例#6
0
def plot_surface(obj, **args):
    region = args.get('region', None)
    idx = obj.tag2idx(region)
    tags = args.get('tags', False)
    coord = args.get('coord', None)
    locator = args.get('locator', False)
    fill = args.get('fill', None)

    amin = np.min(obj.bbox_min[idx], axis=0)
    amax = np.max(obj.bbox_max[idx], axis=0)
    wh = amax - amin
    if np.min(wh) < 250:
        wh = wh / np.min(wh) * 250
    hvobj = hv.Path([obj.boundary[i]
                     for i in idx]).opts(style=dict(color='k'),
                                         plot=dict(yaxis=None,
                                                   xaxis=None,
                                                   aspect='equal',
                                                   width=int(ceil(wh[0])),
                                                   height=int(ceil(wh[1]))))

    if fill is not None:
        vals = np.nan * np.zeros((obj.num, ))
        for k in fill.keys():
            _idx = obj.tag2idx(k)
            for i in _idx:
                vals[i] = fill[k]

        imin = np.min(obj.bbox_min[idx], axis=0).astype(int)
        imax = np.max(obj.bbox_max[idx], axis=0).astype(int)
        im = np.nan * np.zeros(tuple((imax - imin + 1)[::-1].tolist()))
        for i in idx:
            im[obj._coords[i][:, 1] - imin[1],
               obj._coords[i][:, 0] - imin[0]] = vals[i]
        hvobj = hv.Image(np.flipud(im),
                         bounds=(imin[0], imin[1], imax[0], imax[1])).opts(
                             plot=dict(yaxis=None, xaxis=None))

    if coord is not None:
        hvobj *= hv.Curve([obj.hand2pixel((0,0)),obj.hand2pixel((coord,0))]) *\
            hv.Curve([obj.hand2pixel((0,0)),obj.hand2pixel((0,coord))])
    if tags:
        hvobj *= hv.Labels({
            'x': [obj._centers[i][0] for i in idx],
            'y': [obj._centers[i][1] for i in idx],
            'Label': [str(i) + ' ' + ''.join(obj.tags[i]) for i in idx]
        })

    # show cursor position in hand coordinates (works only in bokeh)
    if locator:
        pointer = hv.streams.PointerXY(x=0, y=0)
        dm = hv.DynamicMap(lambda x, y: hvobj * hv.Text(
            x, y + 5, '(%d,%d)' % tuple(obj.pixel2hand(np.array([x, y])))),
                           streams=[pointer])
        return dm

    return hvobj
 def centers(data):
     try:
         x_ls, y_ls = data['xs'], data['ys']
     except TypeError:
         x_ls, y_ls = [], []
     xs = [np.mean(x) for x in x_ls]
     ys = [np.mean(y) for y in y_ls]
     rois = region_names[:len(xs)]
     return hv.Labels((xs, ys, rois))
示例#8
0
def square_left(a=1):
    # we set a + b = 100 then convert to a + b = 1
    a = a / 100.0
    b = 1.0 - a
    poly_1 = Polygons([rectangle(a, b, b, a),
                       rectangle(0, 0, a, b)]).options(color=col_rect)
    poly_2 = Polygons([rectangle(0, b, a, a),
                       rectangle(a, 0, b, b)]).options(color=col_sq_1)
    poly_3 = Polygons([line(0, 0, a, b), line(a, b, b, a)])
    text_1 = [(a / 2, -0.05, 'a'), (-0.05, b / 2, 'b'), (a / 2, 1.05, 'a'),
              (1.05, b / 2, 'b'), (a + b / 2, -0.05, 'b'),
              (-0.05, b + a / 2, 'a'), (a + b / 2, 1.05, 'b'),
              (1.05, b + a / 2, 'a'), (a / 2.5, (b + 0.1 / a) / 2.5, 'c'),
              (a + (b - 0.082 / a) / 2, b + a / 2, 'c')]
    text_2 = [(a / 2, b + a / 2, 'a\u00b2'), (a + b / 2, b / 2, 'b\u00b2')]
    output = (poly_1 * poly_2 * poly_3 * hv.Labels(text_1) *
              hv.Labels(text_2).options(text_color='white')).options(opts)
    output = output.relabel("a\u00b2: {}".format(np.round((a) * 100)**2),
                            "b\u00b2: {}".format(np.round((1 - a) * 100)**2))
    return output
示例#9
0
    def ShowTree(self, lib='HV'):
        import networkx as nx
        import inspect
        G = self.__G__

        # reverse graph used to calculate depth of node
        H = nx.MultiDiGraph()
        H.add_nodes_from(G)
        H.add_edges_from([(e[1], e[0]) for e in G.edges])
        for n in H.nodes():
            lev = set(
                [val[1] for val in dict(nx.bfs_predecessors(H, n)).items()])
            lev = len(lev)
            G.nodes[n]['depth'] = lev

        h = {i: 0 for i in range(100)}
        for n in G.nodes():
            G.nodes[n]['height'] = h[G.nodes[n]['depth']] * 1.5
            G.nodes[n]['pos'] = (float(G.nodes[n]['depth']),
                                 float(G.nodes[n]['height']))
            h[G.nodes[n]['depth']] = h[G.nodes[n]['depth']] + 1

        if lib.lower() == 'matplotlib':
            import matplotlib.pyplot as plt
            plt.figure(figsize=(6, 6))
            #pos= [key for key in nx.get_node_attributes(G,'pos').keys()] #  nx.spring_layout(G,scale=2)
            pos = nx.get_node_attributes(G,
                                         'pos')  #  nx.spring_layout(G,scale=2)

            color_map = [G.nodes[g]['color'] for g in G.nodes]
            nx.draw(G,
                    pos,
                    node_color=color_map,
                    with_labels=True,
                    node_size=1000,
                    connectionstyle='arc3, rad = 0.1')
        if lib.lower() == 'hv':
            import holoviews as hv
            hv.extension('bokeh')
            graph = hv.Graph.from_networkx(
                G, nx.layout.fruchterman_reingold_layout).opts(
                    width=800,
                    height=400,
                    xaxis=None,
                    yaxis=None,
                    legend_position='top_left',
                    directed=True,
                    node_size=50,
                    inspection_policy='edges',
                    arrowhead_length=0.01,
                    node_color='color')
            labels = hv.Labels(graph.nodes, ['x', 'y'], 'name')
            return graph * labels
示例#10
0
    def interactive_map(self):

        maps = []

        for key, value in self.data.items():

            if key != 'background':
                line_plot = None
                for unique_type in value['gdf'].geometry.type.unique():
                    gdf = value['gdf'].loc[value['gdf'].geometry.type.isin(
                        [unique_type])]
                    if unique_type == 'MultiPolygon' or unique_type == 'Polygon':
                        zone_plot = gdf.hvplot(hover_cols=['id'],
                                               colorbar=False,
                                               legend=False,
                                               label='id',
                                               grid=True,
                                               width=600,
                                               height=450,
                                               project=True,
                                               alpha=0.6,
                                               tiles='EsriUSATopo')
                        data = list(
                            zip(
                                zone_plot.Polygons.values()
                                [0].data.geometry.centroid.x,
                                zone_plot.Polygons.values()
                                [0].data.geometry.centroid.y))

                        labels = hv.Labels({('x', 'y'): data,
                                            'text': [i for i in gdf['id']]},
                                           ['x', 'y'], 'text') \
                            .opts(opts.Labels(text_font_size='16pt'))

                    elif unique_type == 'MultiLineString':
                        line_plot = gdf.hvplot(project=True)
                if line_plot is not None:

                    interactive_map = (gf.ocean * gf.land * gf.ocean * gf.borders) *\
                                      zone_plot *\
                                      labels *\
                                      self.data['background']['gdf'].hvplot(project=True, alpha=0.1) * \
                                      line_plot
                else:
                    interactive_map = (gf.ocean * gf.land * gf.ocean * gf.borders) * \
                                      zone_plot * \
                                      labels * \
                                      self.data['background']['gdf'].hvplot(project=True, alpha=0.1)

                maps.append(interactive_map)

        return hv.Layout(maps).cols(2).opts(shared_axes=False)
示例#11
0
def add_point(target_data, label):
    target = hv.Points(target_data)
    target.opts(color='r')
    label = hv.Labels({
        ('x', 'y'): target_data,
        'text': label
    }, ['x', 'y'], 'text')
    label.opts(
        opts.Labels(text_font_size='10pt',
                    yoffset=0.05,
                    xoffset=0.1,
                    text_color='r'), )
    target.redim(x=hv.Dimension('x', soft_range=(-2, 5)))
    return target * label
示例#12
0
def square_right(a=1):
    a = a / 100.0
    b = 1.0 - a

    poly_5 = Polygons([rectangle(0, 0, a + b, b + a)]).options(color=col_rect)
    poly_6 = Polygons(
        [array([[a, 0], [a + b, a], [b, b + a], [0, b],
                [a, 0]])]).options(color=col_sq_3)
    text_1 = [(a / 2, -0.05, 'a'), (-0.05, b / 2, 'b'), (b / 2, 1.05, 'b'),
              (1.05, a / 2, 'a'), (a + b / 2, -0.05, 'b'),
              (-0.05, b + a / 2, 'a'), (b + a / 2, 1.05, 'a'),
              (1.05, a + b / 2, 'b')]
    text_2 = Text((b + a) / 2, (b + a) / 2, 'c\u00b2').options(color='white')
    output = (poly_5 * poly_6 * hv.Labels(text_1) * text_2).options(opts)
    output = output.relabel("c\u00b2: {}".format(
        np.round((a) * 100)**2 + np.round((1 - a) * 100)**2))
    return output
def heatmap_for_metric(df,
                       metric,
                       region,
                       vartype,
                       title,
                       base_column=None,
                       base_diff_type='abs-diff'):
    """
    heatmap by selecting the column metric (for multi indexed data frame this could result in multiple columns)
    if base_column is specified, uses that to do an absolute or percent diff calculation
    if base_diff_type is abs then subtract absolute value otherwise calculate percent diffs
    """
    df = df[metric]
    if base_column is not None:
        if base_diff_type == 'abs':
            df = df.sub(df[base_column], axis=0)
        elif base_diff_type == 'abs-diff':
            df = abs(df).sub(abs(df[base_column]), axis=0)
        else:
            df = df.sub(df[base_column], axis=0).div(df[base_column],
                                                     axis=0) * 100
    else:
        print(
            'calib_heatmap.heatmap_for_metric: base_column not specified, not subtracting.'
        )

    mm = max(abs(df.max().max()), abs(df.min().min()))
    if base_column is not None and base_diff_type != 'abs':
        mm = min(mm,
                 50)  # for percent more than 50% difference is too much ...

    # drop columns we don't want to display
    drop_col_list = ['v8_2_0', 'v8_2_1']
    df.drop(drop_col_list, inplace=True, axis=1)

    heatmap = df.hvplot.heatmap(
        title=title + ' Metric: ' + metric,
        cmap='RdBu',
        #cnorm='eq_hist',
        grid=True,
        xaxis='top',
        clim=(mm, -mm),
        rot=0).opts(margin=10)
    return heatmap * (hv.Labels(heatmap).opts(text_color='black',
                                              text_font_size='8pt'))
def genesetcollection_overlap_heatmap(alpha: dict, beta: dict):
    """
    View the overlap (as a heatmap) of two GeneSetCollection dictionaries,
    as provided by gsc.as_dict().

    :param alpha:
    :param beta:
    :return:
    """
    overlap_dim = hv.Dimension("Overlap Count", value_format=lambda x: f"{x}")

    data = [(f"{ak}: {len(av)}", f"{bk}: {len(bv)}",
             len(set.intersection(set(av), set(bv))))
            for (ak,
                 av), (bk,
                       bv) in itertools.product(alpha.items(), beta.items())]

    heatmap = hv.HeatMap(data, vdims=overlap_dim)
    return heatmap * hv.Labels(heatmap)
def makeHoverHeatMap(df, labelcol, hovercols, vmin=25, vmax=45):
    """
    this makes a holoviews heatmap from the dataframe
    x and y and z (column and row and Ct) columns should be the first two columns
    labelcol values are shown on the heatmap
    hovercols values will be shown on hover
    """
    hv.extension('bokeh', width=90)
    heatmap = hv.HeatMap(df)
    #tooltips=[('Row','@Row'),('Col','@Column'),('JCT','@JCT'),('CT','@CT'),('JCategory','@JCategory'),('Category','@Category'),('Sample','@Sample')]
    tooltips = [(hovercols[i], '@' + hovercols[i])
                for i in range(len(hovercols))]
    hover = HoverTool(tooltips=tooltips)
    heatmap.opts(tools=[hover],
                 colorbar=True,
                 invert_yaxis=True,
                 width=1500,
                 height=800,
                 clim=(vmin, vmax),
                 xlim=(0.5, 24.5))
    return heatmap * hv.Labels(heatmap, vdims=[labelcol])
示例#16
0
 def _make_progress(self):
     import holoviews as hv
     import holoviews.plotting.bokeh  # noqa
     stages = len(self._stages)
     line = hv.Path([[(0, 0), (stages - 1, 0)]]).options(line_width=10,
                                                         color='black',
                                                         backend='bokeh')
     vals = np.arange(stages)
     active = [1 if v == self._stage else 0 for v in vals]
     points = hv.Points((vals, np.zeros(stages), active),
                        vdims=['active']).options(color_index='active',
                                                  line_color='black',
                                                  cmap={
                                                      0: 'white',
                                                      1: 'gray'
                                                  },
                                                  show_legend=False,
                                                  size=20,
                                                  default_tools=[],
                                                  tools=['tap'],
                                                  nonselection_alpha=1,
                                                  backend='bokeh')
     point_labels = points.add_dimension('text',
                                         0, [n for n, _ in self._stages],
                                         vdim=True)
     labels = hv.Labels(point_labels).options(yoffset=-2.5, backend='bokeh')
     self._progress_sel.source = points
     hv_plot = (line * points * labels).options(xaxis=None,
                                                yaxis=None,
                                                width=800,
                                                show_frame=False,
                                                toolbar=None,
                                                height=80,
                                                xlim=(-0.5, stages - 0.5),
                                                ylim=(-4, 1.5),
                                                clone=False,
                                                backend='bokeh')
     return HoloViews(hv_plot, backend='bokeh')
示例#17
0
    def display(self,
                trackqc: TrackQC,
                tracks: List[str] = None,
                normalize=True) -> hv.Layout:
        """
        Outputs a heatmap. Columns are types of Error and rows are tracks. Each
        cell presents the percentage of appearance of the specific error at the
        specific track.
        """
        disc = self.dataframe(trackqc, tracks, normalize)
        value = self.value(normalize)
        nbeads = len(trackqc.status.index)
        hmap = (hv.HeatMap(disc[~disc['error'].isna()],
                           kdims=['error', 'track'],
                           vdims=[value, 'beads']).redim.range(**{
                               value: (-100, 100) if normalize else (-nbeads,
                                                                     nbeads)
                           }).redim.label(error=" ").options(**self.styleopts))

        fmt = (lambda x: f'{abs(x):.01f}') if normalize else (
            lambda x: f'{abs(x):.1f}')
        return ((hmap *
                 hv.Labels(hmap).redim.value_format(**{value: fmt})).clone(
                     label=self.title))
示例#18
0
def geneset_overlap_heatmap(lineament_collection, keys=None, mode="overlap"):
    lineament_dict = lineament_collection.as_dict(keys)

    if mode == "overlap":
        overlap_dim = hv.Dimension("Overlap Count", value_format=lambda x: f"{x}")
        data = [(ak, bk, len(set.intersection(set(av), set(bv))))
                for (ak, av), (bk, bv) in itertools.permutations(lineament_dict.items(), 2)
                if ak != bk]

    elif mode == "percent":
        overlap_dim = hv.Dimension("Overlap Percent", value_format=lambda x: f"{x:.0%}")

        zero_filtered_dict = {k: v for k, v in lineament_dict.items()
                              if len(v) > 0}
        data = [(ak, bk, len(set.intersection(set(av), set(bv))) / len(set(av)))
                for (ak, av), (bk, bv) in itertools.permutations(zero_filtered_dict.items(), 2)
                if ak != bk]

    else:
        raise ValueError(f"{mode} is not a valid mode. Select from 'overlap' or 'percent'.)")

    heatmap = hv.HeatMap(data, vdims=overlap_dim)  # .options(xrotation=45, width=450, height=450, labelled=[],
    #         colorbar=True)
    return heatmap * hv.Labels(heatmap)
示例#19
0
def embedding(adata: AnnData, basis: Union[str, List[str], Tuple[str]],
              keys: Union[None, str, List[str], Tuple[str]] = None,
              cmap: Union[str, List[str], Tuple[str]] = None, palette: Union[str, List[str], Tuple[str]] = None,
              alpha: float = 1, size: float = None, width: int = 400, height: int = 400, sort: bool = True,
              cols: int = None, brush_categorical: bool = False,
              use_raw: bool = None, nbins: int = -1, reduce_function: Callable[[np.array], float] = np.max,
              legend: str = 'right', tooltips: Union[str, List[str], Tuple[str]] = None,
              legend_font_size: Union[int, str] = None, **kwds) -> hv.core.element.Element:
    """
    Generate an embedding plot.

    Args:
        adata: Annotated data matrix.
        keys: Key for accessing variables of adata.var_names or a field of adata.obs used to color the plot. Can also use `count` to plot cell count when binning.
        basis: String in adata.obsm containing coordinates.
        alpha: Points alpha value.
        size: Point pixel size.
        sort: Plot higher values on top of lower values. Disable for linked brushing.
        brush_categorical: Enable linked brushing on categorical variables (disables categorical legend).
        cmap: Color map for continous variables.
        palette: Color map for categorical variables.
        nbins: Number of bins used to summarize plot on a grid. Useful for large datasets. Negative one means automatically bin the plot.
        reduce_function: Function used to summarize overlapping cells if nbins is specified.
        cols: Number of columns for laying out multiple plots
        width: Plot width.
        height: Plot height.
        tooltips: List of additional fields to show on hover.
        legend: `top', 'bottom', 'left', 'right', or 'data' to draw labels for categorical features on the plot.
        legend_font_size: Font size for `labels_on_data`
        use_raw: Use `raw` attribute of `adata` if present.
    """

    if keys is None:
        keys = []
    basis = __to_list(basis)
    adata_raw = __get_raw(adata, use_raw)
    keys = __to_list(keys)
    if tooltips is None:
        tooltips = []
    tooltips = __to_list(tooltips)
    if legend_font_size is None:
        legend_font_size = '12pt'
    labels_on_data = legend == 'data'
    keywords = dict(fontsize=dict(title=9, legend=legend_font_size), padding=0.02 if not labels_on_data else 0.05,
        xaxis=False, yaxis=False,
        nonselection_alpha=0.1,
        tools=['box_select'], legend=not legend == 'data')
    plots = []
    numeric_plots = []
    keywords.update(kwds)
    data_df = __get_df(adata, adata_raw, keys + tooltips, is_obs=True)
    density = len(keys) == 0
    if density:
        keys = ['count']

    for b in basis:
        df = data_df.copy()
        coordinate_columns = ['X_' + b + c for c in ['1', '2']]
        df = pd.concat((df, pd.DataFrame(adata.obsm['X_' + b][:, 0:2], columns=coordinate_columns)), axis=1)
        nbins = __auto_bin(df, nbins, width, height)
        df_with_coords = df
        bin_data = nbins is not None and nbins > 0

        if bin_data or density:
            df['count'] = 1.0
        if bin_data:
            df, df_with_coords = __bin(df, nbins=nbins, coordinate_columns=coordinate_columns,
                reduce_function=reduce_function)

        if size is None:
            size = __get_marker_size(df.shape[0])

        for key in keys:
            is_color_by_numeric = pd.api.types.is_numeric_dtype(df[key])
            if not is_color_by_numeric:
                __fix_color_by_data_type(df, key)
            df_to_plot = df
            if sort and is_color_by_numeric:
                df_to_plot = df.sort_values(by=key)
            __create_hover_tool(df, keywords, exclude=coordinate_columns, current=key)
            color_keyword_keep = 'cmap'
            color_keyword_delete = 'color'
            if is_color_by_numeric:
                color = 'viridis' if cmap is None else cmap
            else:
                if not brush_categorical:
                    color_keyword_keep = 'color'
                    color_keyword_delete = 'cmap'
                color = colorcet.b_glasbey_category10 if palette is None else palette
            keywords[color_keyword_keep] = color
            if color_keyword_delete in keywords:
                del keywords['color']
            if not is_color_by_numeric and brush_categorical:
                if not pd.api.types.is_categorical_dtype(df[key]):
                    df[key] = df[key].astype('category')
                df[key] = df[key].astype(int)
            use_c = is_color_by_numeric or brush_categorical
            p = df_to_plot.hvplot.scatter(
                x=coordinate_columns[0],
                y=coordinate_columns[1],
                title=str(key),
                c=key if use_c else None,
                by=key if not use_c else None,
                size=size,
                alpha=alpha,
                colorbar=is_color_by_numeric,
                width=width, height=height, **keywords)
            bounds_stream = __create_bounds_stream(p)
            if use_c and not sort and not bin_data:
                numeric_plots.append(p)
            if not is_color_by_numeric and labels_on_data:
                labels_df = df_to_plot[[coordinate_columns[0], coordinate_columns[1], key]].groupby(key).aggregate(
                    np.median)
                labels = hv.Labels({('x', 'y'): labels_df, 'text': labels_df.index.values}, ['x', 'y'], 'text').opts(
                    text_font_size=legend_font_size)
                p = p * labels
            p.bounds_stream = bounds_stream
            plots.append(p)
    for i in range(len(numeric_plots)):
        for j in range(i):
            __BrushLinkRange(numeric_plots[i], numeric_plots[j])
            __BrushLinkRange(numeric_plots[j], numeric_plots[i])
    if cols is None:
        cols = 1 if width > 500 else 2
    layout = hv.Layout(plots).cols(cols)
    layout.df = df_with_coords
    return layout
示例#20
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
示例#21
0
#plot = figure(title="Networkx Integration Demonstration", x_range=(-1.1,1.1), y_range=(-1.1,1.1),
              #tools="", toolbar_location=None)
#graph = hv.Graph.from_networkx(B, nx.bipartite_layout(B, nodes=l)).opts(tools=['hover'], directed=True,
                                                                           # node_size=25, inspection_policy='edges',
                                                                            #arrowhead_length=0.1)
                                                                           # , vdims='weight')
#plot.hv.render(graph)

#output_file("networkx_graph.html")
#show(plot)


renderer = hv.renderer('bokeh')
# actually drawing the graph with holoviews
flowchart = hv.Graph.from_networkx(B, nx.bipartite_layout(B, nodes=l), vdims='weight').opts(tools=['hover'], directed=True,
                                                                            node_size=25, inspection_policy='edges',
                                                                            arrowhead_length=0.1)
                                                                            #edge_line_width=B.nodes('weight'))
                                                                            #, vdims='weight')

labels = hv.Labels(flowchart.nodes, ['x', 'y'], 'index')
#layout = flowchart * labels.opts(text_font_size='8pt', text_color='red', bgcolor='white')

#doc = renderer.server_doc(layout)
show(hv.render(flowchart.opts(edge_line_width=hv.dim('weight')*3) * labels.opts(text_font_size='8pt', text_color='red',
                                                                                 bgcolor='white')))
#from bokeh.server.server import Server

#server = Server({'/': app}, port=0)
示例#22
0
def embedding(adata: AnnData, basis: str, keys: Union[None, str, List[str], Tuple[str]] = None,
              cmap: Union[str, List[str], Tuple[str]] = 'viridis',
              alpha: float = 1, size: int = 12,
              width: int = 400, height: int = 400,
              sort: bool = True, cols: int = 2,
              use_raw: bool = None, nbins: int = None, reduce_function: Callable[[np.array], float] = np.mean,
              labels_on_data: bool = False, tooltips: Union[str, List[str], Tuple[str]] = None,
              **kwds):
    """
    Generate an embedding plot.

    Parameters:
    adata: Annotated data matrix.
    keys: Key for accessing variables of adata.var_names or a field of adata.obs used to color the plot. Can also use `count` to plot cell count when binning.
    basis: String in adata.obsm containing coordinates.
    alpha: Points alpha value.
    size: Point pixel size.
    sort: Plot higher values on top of lower values.
    cmap: Color map name (hv.plotting.list_cmaps()) or a list of hex colors. See http://holoviews.org/user_guide/Styling_Plots.html for more information.
    nbins: Number of bins used to summarize plot on a grid. Useful for large datasets.
    reduce_function: Function used to summarize overlapping cells if nbins is specified.
    cols: Number of columns for laying out multiple plots
    width: Plot width.
    height: Plot height.
    tooltips: List of additional fields to show on hover.
    labels_on_data: Whether to draw labels for categorical features on the plot.
    use_raw: Use `raw` attribute of `adata` if present.
    """

    if keys is None:
        keys = []

    adata_raw = __get_raw(adata, use_raw)
    keys = __to_list(keys)
    if tooltips is None:
        tooltips = []
    tooltips = __to_list(tooltips)
    keywords = dict(fontsize=dict(title=9), padding=0.02, xaxis=False, yaxis=False, nonselection_alpha=0.1,
        tools=['box_select'], cmap=cmap)
    keywords.update(kwds)
    coordinate_columns = ['X_' + basis + c for c in ['1', '2']]
    df = __get_df(adata, adata_raw, keys + tooltips,
        pd.DataFrame(adata.obsm['X_' + basis][:, 0:2], columns=coordinate_columns),
        is_obs=True)
    df_with_coords = df
    if len(keys) == 0:
        keys = ['count']
    plots = []

    if nbins is not None:
        df['count'] = 1.0
        df, df_with_coords = __bin(df, nbins=nbins, coordinate_columns=coordinate_columns,
            reduce_function=reduce_function)

    for key in keys:
        is_color_by_numeric = pd.api.types.is_numeric_dtype(df[key])
        df_to_plot = df
        if sort and is_color_by_numeric:
            df_to_plot = df.sort_values(by=key)
        __create_hover_tool(df, keywords, exclude=coordinate_columns, current=key)
        p = df_to_plot.hvplot.scatter(
            x=coordinate_columns[0],
            y=coordinate_columns[1],
            title=str(key),
            c=key if is_color_by_numeric else None,
            by=key if not is_color_by_numeric else None,
            size=size,
            alpha=alpha,
            colorbar=is_color_by_numeric,
            width=width, height=height, **keywords)
        bounds_stream = __create_bounds_stream(p)
        if not is_color_by_numeric and labels_on_data:
            labels_df = df_to_plot[[coordinate_columns[0], coordinate_columns[1], key]].groupby(key).aggregate(
                np.median)
            labels = hv.Labels({('x', 'y'): labels_df, 'text': labels_df.index.values}, ['x', 'y'], 'text')
            p = p * labels
        p.bounds_stream = bounds_stream
        plots.append(p)

    layout = hv.Layout(plots).cols(cols)
    layout.df = df_with_coords
    return layout
示例#23
0
def draw_heatmap(dft, conti, verbose,chart_format,datevars=[], dep=None,
                                    modeltype='Regression',classes=None):
    #####
    ### Test if this is a time series data set, then differene the continuous vars to find
    ###  if they have true correlation to Dependent Var. Otherwise, leave them as is
    width_size = 600
    height_size = 400
    if len(conti) <= 1:
        return
    elif len(conti) <= 10:
        height_size = 500
        width_size = 600
    else:
        height_size = 800
        width_size = 1200
    if isinstance(dft.index, pd.DatetimeIndex) :
        dft = dft[:]
        timeseries_flag = True
        pass
    else:
        dft = dft[:]
        try:
            dft.index = pd.to_datetime(dft.pop(datevars[0]),infer_datetime_format=True)
            timeseries_flag = True
        except:
            if verbose == 1 and len(datevars) > 0:
                print('No date vars could be found or %s could not be indexed.' %datevars)
            elif verbose == 1 and len(datevars) == 0:
                print('No date vars could be found in data set')
            timeseries_flag = False
    # Add a column: the color depends on target variable but you can use whatever function
    imgdata_list = list()
    if modeltype != 'Regression':
        ########## This is for Classification problems only ###########
        if dft[dep].dtype == object or dft[dep].dtype == np.int64:
            dft[dep] = dft[dep].factorize()[0]
        image_count = 0
        N = len(conti)
        target_vars = dft[dep].unique()
        plotc = 1
        #rows = len(target_vars)
        rows = 1
        cols = 1
        if timeseries_flag:
            dft_target = dft[[dep]+conti].diff()
        else:
            dft_target = dft[:]
        dft_target[dep] = dft[dep].values
        corre = dft_target.corr()
        if timeseries_flag:
            heatmap = corre.hvplot.heatmap(height=height_size, width=width_size, colorbar=True,
                    cmap=["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"],
                                           rot=70,
            title='Time Series: Heatmap of all Differenced Continuous vars for target = %s' %dep)
        else:
            heatmap = corre.hvplot.heatmap(height=height_size, width=width_size,
                    colorbar=True,
                    cmap=["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"],
                    rot=70,
            title='Heatmap of all Continuous Variables including target = %s' %dep);
        hv_panel = heatmap * hv.Labels(heatmap)
        if verbose == 2:
            imgdata_list = append_panels(hv_panel, imgdata_list, chart_format)
            image_count += 1
    else:
        ### This is for Regression and None Dep variable problems only ##
        image_count = 0
        if dep is None or dep == '':
            pass
        else:
            conti += [dep]
        dft_target = dft[conti]
        if timeseries_flag:
            dft_target = dft_target.diff().dropna()
        else:
            dft_target = dft_target[:]
        N = len(conti)
        corre = dft_target.corr()
        if timeseries_flag:
            heatmap = corre.hvplot.heatmap(height=height_size, width=width_size, colorbar=True,
                    cmap=["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"],
                                           rot=70,
                title='Time Series Data: Heatmap of Differenced Continuous vars including target = %s' %dep)
        else:
            heatmap = corre.hvplot.heatmap(height=height_size, width=width_size,
                    cmap=["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"],
                                           rot=70,
            title='Heatmap of all Continuous Variables including target = %s' %dep);
        hv_panel = heatmap * hv.Labels(heatmap)
        if verbose == 2:
            imgdata_list = append_panels(hv_panel, imgdata_list, chart_format)
            image_count += 1
    return hv_panel
def plot_scatter(df,
                 x,
                 y,
                 x_round_val=1,
                 y_round_val=1,
                 x_tooltip='',
                 y_tooltip=''):
    '''
    
    Returns a HoloViews plot layout.
        Arguments:
        df - Dataframe to process, must have the column 'Country' adn the columns x and y within.
        x - Column in Dataframe where values are evaluated for the x-axis
        y - Column in Dataframe where values are evaluated for the y-axis
        x_round_val (optional) - single numeric value to set the x axis limits on max found within x
        y_round_val (optional) - single numeric value to set the y axis limits on max found within y
        x_tooltip (optional) - tooltip to be set in the plots for the x values
        y_tooltip (optional) - tooltip to be set in the plots for the y values
    '''
    max_y = np.ceil(np.nanmax(df[y].values))
    max_y = max_y - max_y % y_round_val + 2 * y_round_val
    max_x = np.ceil(np.nanmax(df[x].values))
    max_x = max_x - max_x % x_round_val + 2 * x_round_val
    '''
    if max_x > max_y:
        max_y = max_x
    else:
        max_x=max_y
    '''
    if x_tooltip == '':
        x_tooltip = '@{' + x + '}{0,0.0}'
    if y_tooltip == '':
        y_tooltip = '@{' + y + '}{0,0.0}'

    # Plot settings and parameters
    hover = HoverTool(tooltips=[('Country',
                                 '@Country'), (x, x_tooltip), (y, y_tooltip)])
    padding = dict(x=(-1.2, 1.2), y=(-1.2, 1.2))

    options_shared = dict(width=700,
                          height=700,
                          xlim=(0, max_x),
                          ylim=(0, max_y),
                          hooks=[axis_not_scientific],
                          active_tools=['wheel_zoom'],
                          padding=(0.1, 0.1),
                          show_grid=True,
                          show_legend=True,
                          legend_position='bottom',
                          legend_cols=3)
    options = [
        opts.Scatter(marker='o',
                     size=10,
                     fill_alpha=0.6,
                     tools=[hover],
                     color=hv.Palette('Set2'),
                     **options_shared),
        opts.Points(color='Country',
                    cmap=cc.cm.fire,
                    size=8,
                    tools=[hover],
                    **options_shared),
        opts.Labels(text_font_size='8pt', yoffset=y_round_val / 5),
        opts.Overlay(**options_shared)
    ]

    ds = hv.Table(df)
    # Create the plot
    layout = (  #hv.Scatter(df, kdims=[x], vdims=[y, 'Country'])*
        ds.to(hv.Scatter, x, y, 'Country').overlay() *
        hv.Labels(ds, kdims=[x, y], vdims=['Country'])).opts(options)
    return layout
示例#25
0
                     vdims=['Lat', 'avg_PM2_5', 'Location'])
scatter.opts(color='avg_PM2_5',
             size=10,
             padding=.1,
             tools=['hover'],
             colorbar=True,
             cmap='magma',
             width=500,
             height=400,
             clim=(0, 60))

points = gv.Points(df.dropna(), ['Lon', 'Lat'], ['avg_PM2_5', 'Location'])
points.opts(size=10,
            color='avg_PM2_5',
            cmap='magma',
            tools=['hover'],
            colorbar=True,
            width=500,
            height=400,
            padding=.1,
            clim=(0, 60))

labels = hv.Labels(df1, kdims=['Lon', 'Lat'], vdims=['Location'])

test = gvts.EsriImagery * points * labels
hv.save(test.options(toolbar=None),
        '/Users/matthew/Desktop/IDW_new_test.png',
        fmt='png',
        backend='bokeh')  # works
#show(hv.render(test))
while begin < end:
     
    #mask = (new_df['time'] == begin)
    #info = new_df.loc[mask]
    
    df = new_df.loc[begin]
    df1 = new_df1.loc[begin]
    
    latlngbox = "47.612,-117.472,47.728,-117.348" 
    
    points = gv.Points(df.dropna(), ['Lon', 'Lat'], ['PM2_5', 'Location'])
    print((points))
    
    levels = 10#[0,10,20,30,40,50,60]
    labels = hv.Labels(df1, kdims = ['Lon', 'Lat'], vdims =['Location'])
    labels.opts(text_color = 'white')
    #levels = np.arange(0,100,6)
    points.opts(size=10, color='PM2_5', cmap='magma', clim=(0,70),
                color_levels = levels,
                colorbar_opts={
        'major_label_overrides': {
            0:'0',
            10:'10',
            20:'20',
            30:'30',
            35:'ug/m^3',
            40:'40',
            50:'50',
            60:'60',
            70:'70',
示例#27
0
def plot_confussion_matrix(
    y_test,
    y_pred,
    target_names: list = None,
    cmap: str = "YlGnBu",
    width=500,
    height: int = 400,
    title: str = "Confusion matrix",
    normalize: bool = False,
):
    value_label = "examples"
    target_label = "true_label"
    pred_label = "predicted_label"
    label_color = "color"

    def melt_distances_to_heatmap(distances: pd.DataFrame) -> pd.DataFrame:
        dist_melt = pd.melt(distances.reset_index(),
                            value_name=value_label,
                            id_vars="index")
        dist_melt = dist_melt.rename(columns={
            "index": target_label,
            "variable": pred_label
        })
        dist_melt[target_label] = pd.Categorical(dist_melt[target_label])
        dist_melt[pred_label] = pd.Categorical(dist_melt[pred_label])
        coords = dist_melt.copy()
        coords[target_label] = dist_melt[target_label].values.codes
        coords[pred_label] = dist_melt[pred_label].values.codes
        return coords[[pred_label, target_label, value_label]]

    conf_matrix = confusion_matrix(y_test, y_pred)
    if normalize:
        conf_matrix = np.round(
            conf_matrix.astype("float") /
            conf_matrix.sum(axis=1)[:, np.newaxis], 3)
    # Adjust label color to make them readable when displayed on top of any colormap
    df = melt_distances_to_heatmap(pd.DataFrame(conf_matrix))
    mean = df[value_label].mean()
    df[label_color] = -df[value_label].apply(lambda x: int(x > mean))
    if target_names is not None:
        df[target_label] = df[target_label].apply(lambda x: target_names[x])
        df[pred_label] = df[pred_label].apply(lambda x: target_names[x])
    true_label_name = "Actual label"
    pred_label_name = "Predicted label"

    tooltip = [
        (true_label_name, "@{%s}" % target_label),
        (pred_label_name, "@{%s}" % pred_label),
        ("Examples", "@{%s}" % value_label),
    ]
    hover = HoverTool(tooltips=tooltip)
    heatmap = hv.HeatMap(df, kdims=[pred_label, target_label])
    heatmap.opts(title=title,
                 colorbar=True,
                 cmap=cmap,
                 width=width,
                 height=height,
                 tools=[hover])
    labeled = heatmap * hv.Labels(heatmap).opts(text_color=label_color,
                                                cmap=cmap)
    return labeled.options(xlabel=pred_label_name,
                           ylabel=true_label_name,
                           invert_yaxis=True)
# %%
data = X
# pivot on person-category
observed = pd.crosstab(data.acc, data.PID)
ca = CA(2, observed.columns, observed.index).fit(observed.to_numpy())

rows = pd.DataFrame(ca.row_coord_,
                    index=observed.index,
                    columns=["PID_component_1", "PID_component_2"])
columns = pd.DataFrame(ca.col_coord_,
                       index=observed.columns,
                       columns=["acc_component_1", "acc_component_2"])

#%%
plot = (
    hv.Labels(columns.reset_index(), ["PID_component_1", "PID_component_2"],
              "PID").opts(text_font_size="5pt", text_color="blue") *
    hv.Labels(rows.reset_index().assign(acc=lambda df: df.acc.astype(str)),
              ["acc_component_1", "acc_component_2"], "acc").opts(
                  text_font_size="5pt", text_color="red")).opts(
                      width=800, height=500, title="Correspondance Analysis")

plot

#%%
data = pd.concat([
    context.io.load('xente_sample_submission_wide').assign(test=True),
    context.io.load('xente_train').assign(test=False)
],
                 axis=0)

#%%
示例#29
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)
示例#30
0
def bipartite_food_continent(impex):
    # make the nodes: continents on the left, food groups on the right
    continents = impex.index.get_level_values(0).unique().array
    meta_food_groups = impex.columns.levels[0].array
    bi = nx.Graph()
    bi.add_nodes_from(continents, bipartite=1)
    bi.add_nodes_from(meta_food_groups, bipartite=0)

    # make an edge between each continent and each food group
    edges = []
    for continent in continents:
        for food in meta_food_groups:
            edges.append((continent, food))

    bi.add_edges_from(edges, weight=3)

    # calculate the initial raw weights, which is the total amount of food for each continent-food pair
    weights = []
    for continent in continents:
        for food in meta_food_groups:
            total_food_amount = impex.xs(continent)[food].xs(
                'imports', level=1, axis=1).to_numpy().sum()
            weights.append(total_food_amount)

    # incorporate these weights into the data for each edge
    for num, name in enumerate(bi.edges(data=True)):
        name[2]['weight'] = weights[num]

    # make a list of all the weights so can edit them
    all_weights = []
    for (node1, node2, data) in bi.edges(data=True):
        all_weights.append(data['weight'])

    # normalize the weights so they are appropriate for the graph
    for num, wt in enumerate(all_weights):
        all_weights[num] = wt * len(continents) * 5 / sum(weights)

    # incorporate the normalized weights into the edge data for use in the graph
    for num, name in enumerate(bi.edges(data=True)):
        name[2]['weight'] = all_weights[num]

    top = nx.bipartite.sets(bi)[0]
    pos = nx.bipartite_layout(bi, top)

    # make an interactive bipartite graph with Holoviews and Bokeh
    bipartite = hv.Graph.from_networkx(bi, pos, width=all_weights)

    # create text labels for each of the nodes
    labs = [
        'Africa', 'America', 'Asia', 'Europe', 'Oceania', 'animal products',
        'cereals', 'fruits', 'meat', 'seafood', 'vegetables'
    ]
    labels = hv.Labels(
        {
            ('x', 'y'): bipartite.nodes.array([0, 1]),
            'text': labs
        }, ['x', 'y'], 'text')

    # plot the graph with labels
    hv.extension('bokeh')

    (bipartite * labels).relabel("Food Type Imports by Continent").opts(
        opts.Labels(text_color='text',
                    cmap='Category20',
                    yoffset=0.13,
                    fontsize=14,
                    padding=0.2),
        opts.Graph(node_size=30,
                   inspection_policy='edges',
                   fontsize={'title': 20},
                   node_hover_fill_color='red',
                   edge_line_width='weight',
                   xaxis=None,
                   yaxis=None,
                   node_fill_color='lightgray',
                   edge_hover_fill_color='red',
                   frame_height=400,
                   frame_width=600,
                   padding=((0.1, 0.15), (0.1, 0.2))))

    # plotting and saving the Sankey diagram to html
    labels = [
        'Africa', 'America', 'Asia', 'Europe', 'Oceania', 'animal_products',
        'cereals', 'fruits', 'meat', 'seafood', 'vegetables'
    ]
    colors = [
        'skyblue', 'yellow', 'orange', 'violet', 'green', 'maroon', 'darkblue',
        'seashell', 'lavenderblush', 'lightpink', 'turquoise'
    ]

    sources = []
    targets = []
    weights = []
    link_colors = []
    for (left_node, right_node, data) in bi.edges(data=True):
        weight = data['weight']
        sources.append(labels.index(left_node))
        targets.append(labels.index(right_node))
        weights.append(weight)
    #    link_colors.append(colors[labels.index(left_node)])

    import plotly.graph_objects as go

    fig = go.Figure(data=[
        go.Sankey(node=dict(pad=10,
                            thickness=10,
                            line=dict(color="black", width=0.5),
                            label=labels,
                            color=colors),
                  link=dict(
                      source=sources,
                      target=targets,
                      value=weights,
                  ))
    ])

    fig.update_layout(title_text="Food Type Imports by Continent",
                      font_size=12)
    fig.show()