def colorPalette(self, size=None): # https://bokeh.pydata.org/en/latest/docs/reference/palettes.html # https://bokeh.pydata.org/en/latest/docs/reference/colors.html color = list(d3['Category10'][10]) # [ 'orangered', 'cornflowerblue', ] # color = list(Spectral9).reverse() if size is None: return color elif size <= len(color): return color[0:size] elif size <= 256: return linear_palette(plasma(256), size) else: return linear_palette(plasma(256) + viridis(256) + magma(256), size)
def colorPalette(self, size=None): # https://bokeh.pydata.org/en/latest/docs/reference/palettes.html # https://bokeh.pydata.org/en/latest/docs/reference/colors.html color = list( d3['Category10'][10]) # [ 'orangered', 'cornflowerblue', ] # color = list(Spectral9).reverse() if size is None: return color elif size <= len(color): return color[0:size] elif size <= 256: return linear_palette(plasma(256), size) else: return linear_palette( plasma(256) + viridis(256) + magma(256), size)
def update_df(_df, _size, _color, _palette, _continuous, _discrete_sizeable, _discrete_colorable): """update the size and color columns of the given df based on widget selections and column classifications""" _df["size"] = 9 if _size != 'None' and _size in _discrete_sizeable: values = _df[_size][pd.notnull(_df[_size])].unique() if all([val.isnumeric() for val in values]): values = sorted(values, key=lambda x: float(x)) codes = dict(zip(values, range(len(values)))) groups = [codes[val] for val in _df[_size].values] _df["size"] = [SIZES[xx] for xx in groups] elif _size != 'None' and _size in _continuous: try: groups = pd.qcut(_df[_size].values, len(SIZES)) except ValueError: groups = pd.cut(_df[_size].values, len(SIZES)) _df["size"] = [SIZES[xx] for xx in groups.codes] _df["color"] = "#31AADE" if _color != 'None' and _color in _discrete_colorable: values = _df[_color][pd.notnull(_df[_color])].unique() colors = linear_palette(palettes[_palette], len(values)) if all([val.isnumeric() for val in values]): values = sorted(values, key=lambda x: float(x)) codes = dict(zip(values, range(len(values)))) groups = [codes[val] for val in _df[_color].values] _df["color"] = [colors[xx] for xx in groups] elif _color != 'None' and _color in _continuous: colors = palettes[_palette] groups = pd.cut(_df[_color].values, len(colors)) _df["color"] = [colors[xx] for xx in groups.codes]
def drawOnFigure(fig, source, heatdata, nodes, data_format, palette=Inferno256): data = parseRawData(heatdata, nodes, data_format, linear_palette(palette, constants.HEATMAP_CUTOFF + 1)) # Create holder for currently shown circles data[data_format['xs'] + '_shown'] = [] data[data_format['ys'] + '_shown'] = [] data[data_format['ss'] + '_shown'] = [] data[data_format['cs'] + '_shown'] = [] source.data = data fig.scatter(x=data_format['xs'] + '_shown', y=data_format['ys'] + '_shown', radius=data_format['ss'] + '_shown', fill_color=data_format['cs'] + '_shown', fill_alpha=0.8, source=source, angle=pi / 3, line_color=None)
def changeArea2(attr, old, new): scale1 = slider2.value[0] scale2 = slider2.value[1] dd = df.loc[df['death'].between(scale1, scale2), 'states'] d = len(dd) new_data = { 'states': df.loc[df['death'].between(scale1, scale2), 'states'], 'death': df.loc[df['death'].between(scale1, scale2), 'death'], 'colors': linear_palette(Viridis256, d) } source3.data = new_data
def changeArea(attr, old, new): scale1 = slider.value[0] scale2 = slider.value[1] dd = df.loc[df['cases'].between(scale1, scale2), 'states'] d = len(dd) new_data = { 'states': df.loc[df['cases'].between(scale1, scale2), 'states'], 'cases': df.loc[df['cases'].between(scale1, scale2), 'cases'], 'colors': linear_palette(Magma256, d) } source.data = new_data
def changeArea1(attr, old, new): scale1 = slider1.value[0] scale2 = slider1.value[1] dd = df.loc[df['cured'].between(scale1, scale2), 'states'] d = len(dd) new_data = { 'states': df.loc[df['cured'].between(scale1, scale2), 'states'], 'cured': df.loc[df['cured'].between(scale1, scale2), 'cured'], 'colors': linear_palette(Turbo256, d) } source2.data = new_data
def __init__(self, colorName, num=None, *args, **kwargs): if kwargs.get('loggingLevel') is not None: logger.setLevel(kwargs.get('loggingLevel')) debug('Creating palette for colorName: %s with %s colors.' % (colorName, num)) paletteFamilies = all_palettes.keys() self.callGroups = {} try: # See if the colorName self._Palette = [eval("bc.named." + colorName + ".to_hex()")] debug('Creating one color palette: %s' % self._Palette) return except: if colorName not in paletteFamilies: warning( '"%s" is neither a known color name nor a known color palette name; using Dark2[8].' % colorName) return pass _num = num if _num is None or _num < 1: _num = 8 pf = all_palettes[colorName] # if _num > max(pf.keys()): # debug('The number of lines in the graph exceeds the number of colors in the palette. Switch to a larger palette.') # pf = all_palettes['Viridis'] pfk = pf.keys() if _num in pfk: self._Palette = pf[_num] debug('Creating predefined palette: %s' % str(self._Palette)) return maxp = max(pfk) rptcnt = ((_num - 1) // maxp) + 1 if _num > maxp: minContainPalette = maxp else: minContainPalette = min( list(it.filterfalse(lambda x: x < _num, pfk))) if rptcnt == 1: debug('Generating pallette of %s colors from %s of %s.' % (_num, minContainPalette, pf[minContainPalette])) self._Palette = pf[minContainPalette][ 0:_num] # Take first _num colors from palette. # self._Palette = linear_palette(pf[minContainPalette], _num) # Take evenly spaced colors form palette. else: self._Palette = linear_palette(pf[maxp] * rptcnt, _num) debug('Creating palette: %s' % str(self._Palette))
def generate(data, title, width, height, x_range, units, font_size, items): """ Generate the chart """ p = plotarea(title, width, height, list(reversed(data)), units) p.yaxis.major_label_text_font_size = font_size p.title.text_font_size = ptmult(font_size, 1.2) # Add one to items that we retrieve in determining thresholds, since the final # slot is going to get swallowed by the summary line ca_threshold = sorted(d[2] for d in data.values() if d[2] > 0)[:(items + 1)][-1] ar_threshold = sorted(d[3] for d in data.values() if d[3] > 0)[-(items + 1):][0] rows = len(data) pal = linear_palette(palette, rows) # If a maximum value is specified, then push out how far the x axis will go # this helps with apples-to-apples comparison between before and after # charts if x_range is not None: p.rect(x=x_range, y=0, width=1, height=1, line_alpha=0, fill_alpha=0.0) index = rows - 1 offset = 0 for key, value in data.items(): mask = (key == OVERALL_LABEL) if mask: offset = 0 offset = offset + bar(p, index + 0.5, offset, value, pal[index], units, ca_threshold, ar_threshold, mask) index -= 1 legend(p) show(p)
def get_linear_cmap(cmap, n, fall_back="coolwarm"): """Produce n that differ linearly from a given colormap This function depends on pl.linear_palettes whose doc be found at: https: // docs.bokeh.org / en / latest / docs / reference / palettes.html cmap: : obj: `str` The colourmap chosen n: : obj: `int` Number of colours to generate Returns ------- colors: : obj: `list` A list of size n containing the linear colours """ colors = get_cmap(cmap, fall_back=fall_back) if len(colors) < n: logger.info("Requested {}, available: {}.".format(n, len(colors))) logger.info("Reverting back to default.") colors = get_cmap(fall_back) colors = pl.linear_palette(colors, n) return colors
def make_data(file, prob_thresh = 0.9): kwargs = {"sep": '\t', "names": ['lat', 'lon', 'time', 'cluster', 'prob', 'outlier'], "skiprows": 1} read_file = pd.read_csv("data/" + file, **kwargs) kwargs2 = {"sep": '\t', "names": ['lat', 'lon', 'time', 'cluster', 'prob', 'outlier'], "nrows": 1} tgf = pd.read_csv("data/"+file, **kwargs2) tgf_lat = [] tgf_lon = [] tgfpnt = transform(partial( pyproj.transform, pyproj.Proj(init='EPSG:4326'), pyproj.Proj(init='EPSG:3857')), Point(tgf['lon'], tgf['lat'])) tgf_lat.append(tgfpnt.x) tgf_lon.append(tgfpnt.y) tgf_time = tgf['time'] tgf_src = ColumnDataSource(data = {'cluster': tgf['cluster'], 'lats': tgf_lat, 'lons':tgf_lon, 'times': tgf_time}) cluster_colors = linear_palette(palette=Viridis256, n=len(set(read_file['cluster']))) read_file = read_file[read_file['prob']>=prob_thresh] cluster_lat = [] cluster_lon = [] colors = [] for _, row in read_file.iterrows(): pnt = transform(partial( pyproj.transform, pyproj.Proj(init='EPSG:4326'), pyproj.Proj(init='EPSG:3857')), Point(row['lon'], row['lat'])) cluster_lat.append(pnt.x) cluster_lon.append(pnt.y) colors.append(cluster_colors[int(row['cluster'])]) new_src = ColumnDataSource( data={'cluster': read_file['cluster'], 'lats': cluster_lat, 'lons': cluster_lon, 'colors': colors, 'times': read_file['time']}) return new_src, tgf_src, file
def chart(df): """ Builds a Bokeh plot for given stock betas :param df: Pandas DataFrame containing stock betas :return: Bokeh script, div components for rendering plot """ tooltips = [("Beta", "$y")] p = figure(width=800, height=400, x_axis_type='datetime', tools='wheel_zoom,pan,box_zoom,reset', tooltips=tooltips) col_len = len(df.columns) # Spectral palette is really nice, but only has 11 colors if col_len <= 11: palette = linear_palette(Spectral11, col_len) else: palette = inferno(col_len) for i in range(col_len): p.line(df.index, df[df.columns[i]], color=palette[i], line_width=2, legend=df.columns[i], alpha=0.8, muted_alpha=0.2, muted_color=palette[i]) p.legend.location = "top_left" p.legend.click_policy = "mute" return components(p)
'colors': linear_palette(Magma256, d) } source.data = new_data p = figure(y_range=a, plot_width=1300, plot_height=600, title="Confirmed Corona Cases in India Statewise ", x_axis_label="No of cases ", y_axis_label="States", tools="pan,wheel_zoom,box_zoom,reset") source = ColumnDataSource(data={ 'states': a, 'cases': b, 'colors': linear_palette(Magma256, d) }) slider = RangeSlider(title='Cases Range', start=0, end=100000, step=1, value=(0, 100000), bar_color="green") slider.on_change('value', changeArea) p.hbar(y='states', right='cases', left=0, height=0.6, fill_color='colors', fill_alpha=0.9, source=source)
from bokeh.io import curdoc import math from bokeh.io import curdoc from bokeh.plotting import figure, show, ColumnDataSource, output_notebook from bokeh.models import RangeSlider, HoverTool from bokeh.layouts import widgetbox, column, row from bokeh.palettes import Greys256, Inferno256, Magma256, Plasma256, Viridis256, Cividis256, Turbo256, linear_palette, Set2, Spectral6 from bokeh.models.widgets import Div df = df_j df1 = result c1 = list(df['Date'].values) d1 = df['ConfirmedCases'].tolist() #e=df1['Death_per_million_population'].tolist() l1 = len(c1) color2 = linear_palette(Turbo256, l1) p12 = figure(x_range=c1, plot_height=350, title="Daily New Cases in India", toolbar_location='right', tools="zoom_in,zoom_out,reset,save,pan,box_select,box_zoom", plot_width=650) a = p12.line(c1, d1, line_width=3, color='cornflowerblue') p12.annulus(x=c1, y=d1, inner_radius=0.1, outer_radius=0.25, color=color2, alpha=0.8) p12.segment(c1, -1000, c1, d1, line_width=3, line_color=color2, alpha=0.8) p12.y_range.start = -200
# to find the station after knowing which cluster its coordinate belongs to coord_to_station = {i.coord: i for i in risky_stations} X = np.array(list(coord_to_station.keys())) X_rad = np.radians(X) ms_per_radian = 6373000.0 eps = 15000 / ms_per_radian db = DBSCAN(eps=eps, min_samples=5, metric='haversine', n_jobs=-1).fit(X_rad) labels = db.labels_ unique_labels = set(labels) num_clusters = len(unique_labels) - (1 if -1 in labels else 0) logger.info('Number of clusters: {}'.format(num_clusters)) cluster_pallet = linear_palette(Turbo256, len(unique_labels)) label_to_stations = defaultdict(list) # to find the list of stations knowing the cluster label location_map3 = gmap(environ.get('API_KEY'), options2, title="Clusters", tools=tools, active_scroll="wheel_zoom") for i in unique_labels: if i != -1: # not noise for coord in X[labels == i]: location_map3.circle(x=coord[1], y=coord[0], size=10, color=cluster_pallet[i], fill_alpha=0.8) label_to_stations[i].append(coord_to_station[(coord[0], coord[1])]) # find the station from its coordinates and append it to the dictionary location_map3.plot_width = 700 location_map3.plot_height = 500 location_map3.sizing_mode = 'scale_width'
def create_graph_from_adj(adj, p, q, title="", subtitle="", size=500, remove_nodes=True): """Creates networkx graph from adjacency matrix and returns a bokeh plot of it. Arguments: adj {np.ndarray} -- Adjacency matrix of a grpah Keyword Arguments: title {str} -- Optional Title of the plot (default: {""}) """ assert (adj.shape[0] == adj.shape[1]) G = nx.from_numpy_matrix(adj) if (remove_nodes): G.remove_nodes_from(list(nx.isolates(G))) graph_renderer = from_networkx( G, nx.shell_layout, nlist=[list(range(p)), list(range(p, p + q))]) graph_renderer.node_renderer.data_source.add([(k < p) * max(k, 1) for k, v in G.degree()], 'is_p') graph_renderer.node_renderer.data_source.add( [min(10 + v, 20) for k, v in G.degree()], 'degree') # mapper = LinearColorMapper(palette=linear_palette(Spectral, p+1), low=0, high=p) mapper = LinearColorMapper(palette=linear_palette(Spectral4, 2), low=0, high=1) graph_renderer.node_renderer.glyph = Circle(size='degree', fill_color={ 'field': 'is_p', 'transform': mapper }) graph_renderer.node_renderer.selection_glyph = Circle( size='degree', fill_color=Spectral4[3]) graph_renderer.node_renderer.hover_glyph = Circle(size='degree', fill_color=Spectral4[3]) graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=1.0, line_width=3) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=3) graph_renderer.edge_renderer.hover_glyph = MultiLine( line_color=Spectral4[1], line_width=3) graph_renderer.selection_policy = NodesAndLinkedEdges() graph_renderer.inspection_policy = NodesAndLinkedEdges() neighbours = [] for i in list(G.nodes): neighbours.append(np.where(np.logical_or(adj[i, :], adj[:, i]))) graph_renderer.node_renderer.data_source.data['neighbours'] = neighbours bokeh_pl = Plot(plot_width=size, plot_height=size, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) # bokeh_pl.title.text = title bokeh_pl.add_layout(Title(text=subtitle, text_font_style="italic"), 'above') bokeh_pl.add_layout(Title(text=title, text_font_size="16pt"), 'above') # bokeh_pl.add_tools(HoverTool(tooltips=None), TapTool(), BoxSelectTool()) hover = HoverTool(tooltips=[("idx:", "@index"), ("Neighbours:", "@neighbours")]) bokeh_pl.add_tools(hover, TapTool(), BoxSelectTool()) bokeh_pl.renderers.append(graph_renderer) return (bokeh_pl)
def draw_clusters(cluster_data): available_clusters = list(set(cluster_data['cluster'])) available_clusters.sort() cluster_colors = linear_palette(palette=Viridis256, n=max(available_clusters) + 2) cluster_colors.sort() def make_dataset(cluster_list): cluster_list = np.asarray(cluster_list).astype(int) subset = cluster_data[cluster_data['cluster'].isin(cluster_list)] color_dict = { carrier: color for carrier, color in zip(available_clusters, cluster_colors) } cluster_lat = [] cluster_lon = [] colors = [] clusters = [] for cluster in cluster_list: sub_cluster = subset[subset['cluster'] == cluster] for _, row in sub_cluster.iterrows(): colors.append(color_dict[cluster]) clusters.append(cluster) pnt = transform( partial(pyproj.transform, pyproj.Proj(init='EPSG:4326'), pyproj.Proj(init='EPSG:3857')), Point(row['lon'], row['lat'])) cluster_lat.append(pnt.x) cluster_lon.append(pnt.y) new_src = ColumnDataSource( data={ 'cluster': clusters, 'lats': cluster_lat, 'lons': cluster_lon, 'color': colors }) return (new_src) def make_plot(src): p = figure(x_axis_type="mercator", y_axis_type="mercator", match_aspect=True) p.add_tile(CARTODBPOSITRON) p.legend.visible = False circles_glyph = p.circle('lats', 'lons', color='color', size=10, source=src, legend=False) # Add the glyphs to the plot using the renderers attribute p.renderers.append(circles_glyph) # Hover tooltip for flight lines, assign only the line renderer hover_circle = HoverTool(tooltips=[('Cluster ID', '@cluster'), ('lat', '@lats'), ('lon', '@lons')], line_policy='next', renderers=[circles_glyph]) # Add the hovertools to the figure p.add_tools(hover_circle) p = style(p) return p # Styling def style(p): # Title p.title.align = 'center' p.title.text_font_size = '20pt' p.title.text_font = 'serif' # Axis titles p.xaxis.axis_label_text_font_size = '14pt' p.xaxis.axis_label_text_font_style = 'bold' p.yaxis.axis_label_text_font_size = '14pt' p.yaxis.axis_label_text_font_style = 'bold' # Tick labels p.xaxis.major_label_text_font_size = '12pt' p.yaxis.major_label_text_font_size = '12pt' return p def update(attr, old, new): # Find list of carriers and make a new data set cluster_list = [ cluster_selection.labels[i] for i in cluster_selection.active ] new_src = make_dataset(cluster_list) src.data.update(new_src.data) # CheckboxGroup to select carriers for plotting cluster_selection = CheckboxGroup( labels=list(np.asarray(available_clusters).astype(str)), active=list(np.arange(-1, max(available_clusters) + 1, 1))) cluster_selection.on_change('active', update) # Initial carriers to plot initial_clusters = [ cluster_selection.labels[i] for i in cluster_selection.active ] # Initial source and plot src = make_dataset(initial_clusters) #print(src.data) p = make_plot(src) # Layout setup layout = row(cluster_selection, p) tab = Panel(child=layout, title='Cluster Map') return tab
def stackplot(shared, tax, rank='Phylum', output='barplot.html', min_abund=0.01, offset=50): x_sums = shared.sum(axis=1) tooltips = [('sample', '@sample'), (rank, '@' + rank), ('proportion', '@proportion{0.0%}'), ('total abundance', '@total_abundance')] if rank == 'Class': shared = shared.loc[:, tax.Phylum == 'Proteobacteria'] tax = tax.loc[shared.columns] tooltips += [('total_proteobacteria', '@total_proteobacteria')] prot_sums = shared.sum(axis=1) # Normalize to ratio to better visualize distribution shared = (shared.T / shared.sum(axis=1)).T # Group by rank shared = group_otus(shared, tax, rank, min_abund=min_abund) hue_order = shared.sum().sort_values(ascending=False).index filler = '_Others (< {:.0%})'.format(min_abund) if filler in hue_order: hue_order = hue_order.drop(filler).append(pd.Index([filler])) cmap = dict(zip(hue_order, linear_palette(Turbo256, len(hue_order)))) cmap[filler] = '#cccccc' # If it's the first plot to overlay p = figure(y_range=FactorRange(*sorted(shared.index, reverse=True)), plot_height=2 * offset + shared.shape[0] * 15, plot_width=2 * offset + 1000, title=Path(output).stem.replace('_', ' '), min_border=offset, y_axis_label='Sample', x_axis_label='Taxonomic composition', tooltips=tooltips) bar_data = pd.DataFrame({ 'left': shared[hue_order].shift(axis=1).cumsum(axis=1).fillna(0).stack(), 'right': shared[hue_order].cumsum(axis=1).stack(), 'proportion': shared[hue_order].stack() }).swaplevel(0, 1) samples = bar_data.index.get_level_values('sample') bar_data['color'] = [ cmap[otu] for otu in bar_data.index.get_level_values(rank) ] bar_data['total_abundance'] = x_sums.map( lambda x: f'{x:,}').loc[samples].to_numpy() if rank.lower() == 'class': bar_data['total_proteobacteria'] = prot_sums.map( lambda x: f'{x:,}').loc[samples].to_numpy() # plot each level one by one for i, level in enumerate(hue_order): data_i = bar_data.loc[level].assign(**{rank: level}) p.hbar(left='left', right='right', height=0.8, y='sample', color='color', line_color='black', line_width=1.2, source=data_i.reset_index(), legend_label=level, name=level) leg_items = p.legend.items.copy() p.legend.items.clear() legend = Legend(items=leg_items, padding=0, spacing=0, border_line_color=None) p.add_layout(legend, 'right') output_file(output) save(p)
# In[6]: n = 15 x = np.array([np.random.normal(0, 0.5, n), np.random.normal(1.25, 0.5, n)]).T y = np.matmul(x, np.array([1.56, -1.62]).T) w0, w1 = np.meshgrid(np.linspace(-75., 75., num=400), np.linspace(-75., 75., num=400)) w = np.array([w0.ravel(), w1.ravel()]) loss = np.sqrt(np.average(((y.reshape(n, 1) - np.matmul(x, w)) ** 2), axis=0)) p, v, m, pos, source = dict(), dict(), dict(), dict(), dict() color_mapper = LinearColorMapper(linear_palette(colorcet.bmy, 256), low=np.min(loss), high=np.max(loss)) color_bar = ColorBar(color_mapper=color_mapper, border_line_color=None, location=(0,0)) # In[7]: eta, gamma, epsilon, beta, beta2, num_epoch = 3, 0.3, 1, 0.9, 0.99, 100 x_init, y_init = -40., -40. epoch = 0 for method in ['Batch Gradient Descent', 'Stochastic Gradient Descent', 'Mini-batch Gradient Descent', 'Momemtum', 'Adaptive Gradient Descent', 'RMSprop', 'Adam', 'Nesterov Accelerate Gradient', 'Nadam']: p[method] = figure(title=f'{method} (η={eta:.1f}, epoch={epoch})', tooltips=[('w1', '$x'), ('w2', '$y'), ('loss', '@image')], tools=['pan', 'wheel_zoom', 'reset', 'save'], x_axis_label='w1', y_axis_label='w2') p[method].image(image=[loss.reshape(400, 400)], x=-75, y=-75, dw=150, dh=150, color_mapper=color_mapper) p[method].x_range.range_padding = p[method].y_range.range_padding = 0 p[method].add_layout(color_bar, 'right')
def create_graph_from_invcov(invcov, p, q, title="", subtitle="", size=500, remove_nodes=True, labels=None, show_weights=True): """Creates networkx graph from inverse covariance matrix and returns a bokeh plot of it. Arguments: invcov {np.ndarray} -- Inverse Covariance matrix of a grpah Keyword Arguments: title {str} -- Optional Title of the plot (default: {""}) """ assert (invcov.shape[0] == invcov.shape[1]) invcov = pd.DataFrame(invcov) G = nx.from_pandas_adjacency(invcov) if (remove_nodes): G.remove_nodes_from(list(nx.isolates(G))) graph_renderer = from_networkx( G, nx.shell_layout, nlist=[list(range(p)), list(range(p, p + q))]) graph_renderer.node_renderer.data_source.add([(k < p) * max(k, 1) for k, v in G.degree()], 'is_p') graph_renderer.node_renderer.data_source.add( [min(10 + v, 20) for k, v in G.degree()], 'degree') # mapper = LinearColorMapper(palette=linear_palette(Spectral, p+1), low=0, high=p) mapper = LinearColorMapper(palette=linear_palette(Spectral4, 2), low=0, high=1) graph_renderer.node_renderer.glyph = Circle(size='degree', fill_color={ 'field': 'is_p', 'transform': mapper }) graph_renderer.node_renderer.selection_glyph = Circle( size='degree', fill_color=Spectral4[3]) graph_renderer.node_renderer.hover_glyph = Circle(size='degree', fill_color=Spectral4[3]) edge_mapper = LinearColorMapper(palette=['pink', 'palegreen'], low=-1, high=1) edge_vals = [G.get_edge_data(u, v)["weight"] for u, v in G.edges] edge_weights = [ min(max(abs(G.get_edge_data(u, v)["weight"]), 0.5) * 4, 6) for u, v in G.edges ] graph_renderer.edge_renderer.data_source.add(edge_weights, 'weights') graph_renderer.edge_renderer.data_source.add(np.sign(edge_vals), 'signs') if (show_weights): graph_renderer.edge_renderer.glyph = MultiLine(line_color={ 'field': 'signs', 'transform': edge_mapper }, line_alpha=1.0, line_width='weights') else: graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=1.0, line_width=1) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color='black', line_width='weights') graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color="#CCCCCC", line_width='weights') graph_renderer.selection_policy = NodesAndLinkedEdges() graph_renderer.inspection_policy = NodesAndLinkedEdges() if (labels is not None): tmp = [labels[i] for i in G.nodes] graph_renderer.node_renderer.data_source.data['name'] = tmp neighbours = [] adj = np.array(np.abs(invcov) > 0) neighbours = [ labels[np.where(np.logical_or(adj[i, :], adj[:, i]))] for i in G.nodes ] graph_renderer.node_renderer.data_source.data[ 'neighbours'] = neighbours tooltips = [("idx:", "@index"), ("Name:", "@name"), ("Neighbours:", "@neighbours{safe}")] else: neighbours = [] adj = np.array(np.abs(invcov) > 0) for i in list(G.nodes): neighbours.append( list(map(str, np.where(np.logical_or(adj[i, :], adj[:, i]))[0]))) graph_renderer.node_renderer.data_source.data[ 'neighbours'] = neighbours tooltips = [("idx:", "@index"), ("Neighbours:", "@neighbours{safe}")] # add line breaks for n in neighbours: if len(n) > 3: for i in range(len(n)): if (i % 3 == 0): n[i] = "<br/>" + n[i] bokeh_pl = Plot(plot_width=size, plot_height=size, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) # bokeh_pl.title.text = title bokeh_pl.add_layout(Title(text=subtitle, text_font_style="italic"), 'above') bokeh_pl.add_layout(Title(text=title, text_font_size="16pt"), 'above') # bokeh_pl.add_tools(HoverTool(tooltips=None), TapTool(), BoxSelectTool()) hover = HoverTool(tooltips=tooltips) bokeh_pl.add_tools(hover, TapTool(), BoxSelectTool()) bokeh_pl.renderers.append(graph_renderer) return (bokeh_pl)