How add interactions to bokeh spider-chart (radar-chart)

233 Views Asked by At

I'm trying to make an interactive spider chart using Bokeh. The chart it's almost done, there are only a couple of things missing that even with the documentation I'm not able to get. In particular I would like to have a label that come out when I pass the mouse over a zone (eg: for the "yellow area" I would like to see its count values for each vertex with the vertex name). Finally the last problem is that my chart polygon is missing the edge connecting the first and last vertex. I leave here my code with a sample of the data I'm using, thank you for the help.

import numpy as np
import pandas as pd
import math
from bokeh.io import output_file, show
from bokeh.models import BasicTicker, ColorBar, LinearColorMapper, ColumnDataSource, PrintfTickFormatter, LabelSet, Legend, HoverTool
from bokeh.plotting import figure
from bokeh.transform import transform
from bokeh.palettes import viridis

mod_cat_ID = pd.DataFrame(columns=['ID','Name'])
mod_cat_ID['ID'] = [1,2,3,4,5,6,7,8,9,10,'X','?']
mod_cat_ID['Name'] = ['Carbohydrate metabolism','Energy metabolism','Lipid metabolism','Nucleotide metabolism','Amino acid metabolism','Glycan metabolism','Metabolism of cofactors and vitamins','Biosynthesis of terpenoids and polyketides','Biosynthesis of other secondary metabolites','Xenobiotics biodegradation','Signature Modules','Unknown']

df=pd.DataFrame(columns=['Pheno_ID','Genes_count','Norm_count'])
df['Pheno_ID'] = ['MP:0000218','MP:0000321','MP:0010093','MP:0001985','MP:0011094']
df['Genes_count'] = [[689, 248, 476, 97, 0, 800, 0, 0, 0, 0],[0, 0, 180, 0, 0, 0, 236, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[120, 0, 0, 0, 88, 0, 0, 0, 0, 0],[367, 600, 347, 240, 361, 404, 236, 0, 0, 0]]
df['Norm_count'] = [[0.86125, 0.31, 0.595, 0.12125, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],[0.0, 0.0, 0.225, 0.0, 0.0, 0.0, 0.295, 0.0, 0.0, 0.0],[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],[0.15, 0.0, 0.0, 0.0, 0.11, 0.0, 0.0, 0.0, 0.0, 0.0],[0.45875, 0.75, 0.43375, 0.3, 0.45125, 0.505, 0.295, 0.0, 0.0, 0.0]]

#The last 2 categories are not counted and showed
n_vertex = len(mod_cat_ID) - 2
theta = np.linspace(0, 2 * np.pi, n_vertex, endpoint=False)

# rotate theta such that the first axis is at the top
theta += np.pi / 2

centre = 1

def unit_poly_verts(theta, centre):
    """Return vertices of polygon for subplot axes.
    This polygon is circumscribed by a unit circle centered at (centre, centre)
    """
    x0, y0, r = [centre] * 3
    verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
    return verts

def radar_patch(r, theta, centre):
    """ Returns the x and y coordinates corresponding to the magnitudes of
    each variable displayed in the radar plot
    """
    # offset from centre of circle
    offset = 0
    yt = (r * centre + offset) * np.sin(theta) + centre
    xt = (r * centre + offset) * np.cos(theta) + centre
    return xt, yt

verts = unit_poly_verts(theta, centre)
x = [v[0] for v in verts]
y = [v[1] for v in verts]

fig = figure(title="Phenotype/Pathway module - Radar plot")
#Here I need only the first 10 categories, the last 2 are not counted and showed
text = mod_cat_ID['Name'][0:10]
source = ColumnDataSource({'x': x , 'y': y , 'text': text})

fig.line(x="x", y="y", source=source)

labels = LabelSet(x="x", y="y", text="text", source=source)

fig.add_layout(labels)

cols = viridis(len(df))

for i in range(len(df)):
    xt, yt = radar_patch(np.asarray(df['Norm_count'][i]), theta, centre)
    fig.patch(x=xt, y=yt, fill_alpha=0.15, fill_color=cols[i], line_color=cols[i], legend_label=str(df['Pheno_ID'][i]))

fig.circle([centre],[centre], color = 'black')
fig.axis.visible = False
fig.xgrid.grid_line_color = None
fig.ygrid.grid_line_color = None
fig.legend.location = 'top_left'
fig.legend.click_policy = 'hide'
show(fig)
0

There are 0 best solutions below