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
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)
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
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)
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
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))
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
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
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)
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
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])
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')
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))
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)
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
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
#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)
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
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
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',
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) #%%
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)
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()