Search code examples
python-3.xbokehheatmapcolorbar

Bokeh colorbar, assign a tick to each color


I'm trying to plot an heatmap of a matrix containing some counts (called mat in my code, then df after change the structure to use it with Bokeh). The structure is like this:

X element 1 element 2 element 3
category 1 0 6 4
category 2 1 7 3
category 3 5 2 10
category 4 0 1 4

Now with my code I'm using df.value.unique() both for the color mapper and the ticks, but in the heatmap the colorbar's ticks doesn't correspond to the colors:

enter image description here

How can I make the ticks coincide each one to one color? I'm quite sure I have to use the CategoricalColorMapper but with that I get only a white screen. Thank you for the help. Here's my code:

mat = pd.read_csv("tests/count_50.dat", sep="\t", index_col=0)

mat.index.name = 'MGI_id'
mat.columns.name = 'phen_sys'

#set data as float numbers
mat=mat.astype(float)

#Create a custom palette and add a specific mapper to map color with values
df = mat.stack(dropna=False).rename("value").reset_index()

pal=bokeh.palettes.brewer['YlGnBu'][len(df.value.unique())]
mapper = LinearColorMapper(palette=pal, low=df.value.min(), high=df.value.max(), nan_color = 'gray')

#Define a figure
p = figure(
    plot_width=1280,
    plot_height=800,
    title="Heatmap",
    x_range=list(df.MGI_id.drop_duplicates()),
    y_range=list(df.phen_sys.drop_duplicates()[::-1]),
    tooltips=[('Phenotype system','@phen_sys'),('Gene','@MGI_id'),('Phenotypes','@value')],
    x_axis_location="above",
    output_backend="webgl")

#Create rectangles for heatmap
p.rect(
    x="MGI_id",
    y="phen_sys",
    width=1,
    height=1,
    source=ColumnDataSource(df),
    fill_color=transform('value', mapper))
p.xaxis.major_label_orientation = 45
#Add legend
t = df.value.unique()
t.sort()
color_bar = ColorBar(
    color_mapper=mapper,
    ticker=FixedTicker(ticks=t, desired_num_ticks=len(df.value.unique())),
    label_standoff=6,
    border_line_color=None)
p.add_layout(color_bar, 'right')

show(p)

Solution

  • I found a solution: I create a factor list by ordering the values and then converting both the dataframe values and the factors. At that point I created a CategoricalColorMapper instead of the linear one and the plot now is correct:

    enter image description here