☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

[Q] Make Histogram selectable and link to Data Column Source

Community Support
tniederm
tniederm

Hi,

I’m looking for a way to make the bars in a histogram selectable and link them to a data source.

What I want to do is the following:

I have a lot of different plots all on the same Data Source, so all are linked.

I also have a DataTable linked to the same source.

Inside that source there are a lot of columns with binary values which are not plotted.

Those collumns should be presented in a Histogram. If one bar of the Histogram is pressed all points that for example have value ‘1’ in that column should get selected in all plots as well as the Data Table.

And does anyone know a way to speed up opening the html?

I have about 90 plots, 300 points each and it takes about 2-4 minutes.

Here is some code which already does anythoing apart from linking the histograms and making them selectable.

Thanks, Tom

def init(self,xlsmPath):
#…
self.plotAll()

tabs =

p = layout.gridplot(self.__plots,ncols=4)

stat = layout.gridplot(self.__statPlots,ncols=4)

w = layout.WidgetBox(self.carSelect)

columns =

for i in range (1,self.__FirstColumn+self.__MaxNumParam):

columns.append(TableColumn(field=self.__desc[1,i], title=self.__desc[1,i]))

data_table = layout.WidgetBox(DataTable(source=self.view, columns=columns,width=5000, height=5000, sortable=True,scroll_to_selection=True))

tabs.append(Panel(child=p,title = ‘All’))

for i in range(0,self.__MaxNumParam):

collayout=layout.gridplot(self.__columnPlots[i],ncols=1)

tabs.append(Panel(child=collayout, title = (self.__desc[1,self.__FirstColumn+i])))

tabs.append(Panel(child=stat,title = ‘Statistics’))

tabs.append(Panel(child=data_table,title = ‘Result Table’))

tabs = Tabs(tabs=tabs,width=1000)

q=layout.layout([[w],[tabs]])

show(q)

def plotAll(self):

self.carRange = ColumnDataSource()

self.colNames = ColumnDataSource()

index=0

for elem in self.__carData:

self.rowArea(index) # now begin and end should be set

self.carRange.add([self.__begin,self.__end], name=str(elem[0]))

self.carmenu.append(elem[0])

index+=1

self.colNames.add([self.__MaxNumParam], name=‘length’)

index = 0

for i in range(0,self.__MaxNumParam):

self.colNames.add((self.__desc[1,self.__FirstColumn+i]), name=str(i))

index+=1

hover = HoverTool(

tooltips=[

(“index”, “$index”),

(“(x,y)”, “($x, $y)”),

])

TOOLS = “box_select,lasso_select,tap,wheel_zoom,reset,hover”

self.datadict = dict()

for i in range(1,self.__FirstColumn+self.__MaxNumParam):

self.datadict[(self.__desc[1,i])]=self.__data[:,i][0:self.__MaxNumRows]

self.source= ColumnDataSource(data=self.datadict)

self.view = ColumnDataSource(data=self.datadict)

index=0

for i in range(0,self.__MaxNumParam):

for j in range(i+1,self.__MaxNumParam):

self.__plots.append(figure(tools=TOOLS,plot_width=400, plot_height=400,

title=None, toolbar_location=“below”,webgl=True,name=‘circle’+str(i*j)))

self.__plots[index].scatter((self.__desc[1,self.__FirstColumn+i]),(self.__desc[1,self.__FirstColumn+j]),source=self.view)

self.__plots[index].xaxis.axis_label = (self.__desc[1,self.__FirstColumn+i])

self.__plots[index].yaxis.axis_label = (self.__desc[1,self.__FirstColumn+j])

hover = self.__plots[index].select(dict(type=HoverTool))

hover.tooltips = [

(“index”, “$index”),

(“(x,y)”, “($x, $y)”),

]

#select_tool = self.__plots[index].select(dict(type=BoxSelectTool))

p=self.__plots[index]

self.view.callback = CustomJS(args=dict(p=p,source=self.view), code=“”"

var inds = cb_obj.get(‘selected’)[‘1d’].indices;

var d1 = cb_obj.get(‘data’);

var text = ‘’;

var datatext = ‘’;

for (i = 0; i < inds.length; i++) {

text = text.concat(inds[i]+‘||’);

datatext = datatext.concat(‘Point ‘+inds[i]+’ ||’);

}

“”"

)

index+=1

self.__columnPlots.append()

colindex = 0

for k in range(0,self.__MaxNumParam):

if i != k:

self.__columnPlots[i].append(figure(tools=TOOLS,plot_width=900, plot_height=400,

title=None, toolbar_location=“below”,webgl=True,name=‘test’+str(i*k)))

self.__columnPlots[i][colindex].scatter((self.__desc[1,self.__FirstColumn+i]),(self.__desc[1,self.__FirstColumn+k]),source=self.view)

self.__columnPlots[i][colindex].xaxis.axis_label = (self.__desc[1,self.__FirstColumn+i])

self.__columnPlots[i][colindex].yaxis.axis_label = (self.__desc[1,self.__FirstColumn+k])

hover = self.__columnPlots[i][colindex].select(dict(type=HoverTool))

hover.tooltips = [

(“index”, “$index”),

(“(x,y)”, “($x, $y)”),

]

colindex += 1

#TODO statistics (now its time for some Barcharts)

for i in range(2,self.__FirstColumn):

self.__statPlots.append(Histogram(self.datadict[self.__desc[1,i]], title=self.__desc[1,i]))

self.__statPlots[i-2].xaxis.axis_label = (self.__desc[1,i])

self.__statPlots[i-2].add_tools(bokeh.models.TapTool())

self.carSelect = Select(title=“Choose Car:”, options=self.carmenu)

self.carSelect.callback = CustomJS(args=dict(rangeData=self.carRange,source=self.source,view=self.view,colNames=self.colNames), code=“”"

var select = cb_obj.get(‘value’);

var viewData = view.get(‘data’);

var sourceData = source.get(‘data’);

var colNameData = colNames.get(‘data’);

var range = rangeData.get(‘data’)[select];

var numCols = parseInt(colNameData[‘length’]);

for (i = 0; i < numCols; i++) {

viewData[colNameData[i.toString()]]=sourceData[colNameData[i.toString()]].slice(range[0],range[1]);

}

view.trigger(‘change’);

“”"

)

print 'Number of plots: ',

print index

``

⌁   Link to post
birdsarah_continuum
birdsarah_continuum

I’m guessing you’re going to
have the best luck by not using the high level Histogram feature, but b y using the plotting API
with HBar and VBar.

That means doing your own histo gram calculation which
is annoying, but the high level Charts interface is real ly designed for
quick exploration and not for more
custom ized
interactives.

Sincerely,

                                      Sarah

Bird

···

On 9/7/16 9:02 AM, wrote:

tniederm@gmail.com

Hi,

      I'm looking for a way to make the bars in a histogram

selectable and link them to a data source.

What I want to do is the following:

        I have a lot of different plots all on the same Data

Source, so all are linked.

I also have a DataTable linked to the same source.

        Inside that source there are a lot of columns with binary

values which are not plotted.

        Those collumns should be presented in a Histogram. If one

bar of the Histogram is pressed all points that for example
have value ‘1’ in that column should get selected in all
plots as well as the Data Table.

And does anyone know a way to speed up opening the html?

      I have about 90 plots, 300 points each and it takes about

2-4 minutes.

      Here is some code which already does anythoing apart from

linking the histograms and making them selectable.

Thanks, Tom

                def

init(self,xlsmPath):

                        #....

                        self.plotAll()

tabs =

                p =

layout.gridplot(self.__plots,ncols=4)

                stat =

layout.gridplot(self.__statPlots,ncols=4)

                w =

layout.WidgetBox(self.carSelect)

columns =

                for i in range

(1,self.__FirstColumn+self.__MaxNumParam):

                columns.append(TableColumn(field=self.__desc[1,i],

title=self.__desc[1,i]))

                data_table =

layout.WidgetBox(DataTable(source=self.view,
columns=columns,width=5000, height=5000,
sortable=True,scroll_to_selection=True))

tabs.append(Panel(child=p,title = ‘All’))

                for i in

range(0,self.__MaxNumParam):

collayout=layout.gridplot(self.__columnPlots[i],ncols=1)

                tabs.append(Panel(child=collayout, title =

(self.__desc[1,self.__FirstColumn+i])))

tabs.append(Panel(child=stat,title = ‘Statistics’))

                tabs.append(Panel(child=data_table,title = 'Result

Table’))

                tabs =

Tabs(tabs=tabs,width=1000)

q=layout.layout([[w],[tabs]])

show(q)

def plotAll(self):

                self.carRange =

ColumnDataSource()

                self.colNames =

ColumnDataSource()

index=0

                for elem in

self.__carData:

                self.rowArea(index) # now begin and end should be

set

                self.carRange.add([self.__begin,self.__end],

name=str(elem[0]))

self.carmenu.append(elem[0])

index+=1

                self.colNames.add([self.__MaxNumParam],

name=‘length’)

index = 0

                for i in

range(0,self.__MaxNumParam):

                self.colNames.add((self.__desc[1,self.__FirstColumn+i]),

name=str(i))

index+=1

hover = HoverTool(

tooltips=[

                ("index",

“$index”),

                ("(x,y)",

“($x, $y)”),

])

                TOOLS =

“box_select,lasso_select,tap,wheel_zoom,reset,hover”

                self.datadict =

dict()

                for i in

range(1,self.__FirstColumn+self.__MaxNumParam):

self.datadict[(self.__desc[1,i])]=self.__data[:,i][0:self.__MaxNumRows]

                self.source=

ColumnDataSource(data=self.datadict)

                self.view =

ColumnDataSource(data=self.datadict)

index=0

                for i in

range(0,self.__MaxNumParam):

                for j in

range(i+1,self.__MaxNumParam):

                self.__plots.append(figure(tools=TOOLS,plot_width=400,

plot_height=400,

                title=None,

toolbar_location=“below”,webgl=True,name=‘circle’+str(i*j)))

self.__plots[index].scatter((self.__desc[1,self.__FirstColumn+i]),(self.__desc[1,self.__FirstColumn+j]),source=self.view)

                self.__plots[index].xaxis.axis_label =

(self.__desc[1,self.__FirstColumn+i])

                self.__plots[index].yaxis.axis_label =

(self.__desc[1,self.__FirstColumn+j])

                hover =

self.__plots[index].select(dict(type=HoverTool))

hover.tooltips = [

(“index”, “$index”),

(“(x,y)”, “($x, $y)”),

]

                #select_tool =

self.__plots[index].select(dict(type=BoxSelectTool))

p=self.__plots[index]

                self.view.callback =

CustomJS(args=dict(p=p,source=self.view), code=“”"

var inds = cb_obj.get(‘selected’)[‘1d’].indices;

var d1 = cb_obj.get(‘data’);

var text = ‘’;

var datatext = ‘’;

for (i = 0; i < inds.length; i++) {

text = text.concat(inds[i]+‘||’);

                datatext = datatext.concat('Point '+inds[i]+'

||');

}

“”"

)

index+=1

self.__columnPlots.append()

colindex = 0

                for k in

range(0,self.__MaxNumParam):

if i != k:

                self.__columnPlots[i].append(figure(tools=TOOLS,plot_width=900,

plot_height=400,

                title=None,

toolbar_location=“below”,webgl=True,name=‘test’+str(i*k)))

self.__columnPlots[i][colindex].scatter((self.__desc[1,self.__FirstColumn+i]),(self.__desc[1,self.__FirstColumn+k]),source=self.view)

                self.__columnPlots[i][colindex].xaxis.axis_label =

(self.__desc[1,self.__FirstColumn+i])

                self.__columnPlots[i][colindex].yaxis.axis_label =

(self.__desc[1,self.__FirstColumn+k])

                hover

=
self.__columnPlots[i][colindex].select(dict(type=HoverTool))

hover.tooltips = [

(“index”, “$index”),

(“(x,y)”, “($x, $y)”),

]

colindex += 1

                #TODO statistics

(now its time for some Barcharts)

                for i in

range(2,self.__FirstColumn):

                self.__statPlots.append(Histogram(self.datadict[self.__desc[1,i]],

title=self.__desc[1,i]))

                self.__statPlots[i-2].xaxis.axis_label =

(self.__desc[1,i])

self.__statPlots[i-2].add_tools(bokeh.models.TapTool())

                self.carSelect =

Select(title=“Choose Car:”, options=self.carmenu)

                self.carSelect.callback =

CustomJS(args=dict(rangeData=self.carRange,source=self.source,view=self.view,colNames=self.colNames),
code=“”"

var select = cb_obj.get(‘value’);

var viewData = view.get(‘data’);

var sourceData = source.get(‘data’);

var colNameData = colNames.get(‘data’);

var range = rangeData.get(‘data’)[select];

var numCols = parseInt(colNameData[‘length’]);

for (i = 0; i < numCols; i++) {

viewData[colNameData[i.toString()]]=sourceData[colNameData[i.toString()]].slice(range[0],range[1]);

}

view.trigger(‘change’);

“”"

)

                print 'Number of

plots: ',

print index

``

–

  You received this message because you are subscribed to the Google

Groups “Bokeh Discussion - Public” group.

  To unsubscribe from this group and stop receiving emails from it,

send an email to bokeh+unsubscribe@continuum.io.

  To post to this group, send email to bokeh@continuum.io.

  To view this discussion on the web visit [https://groups.google.com/a/continuum.io/d/msgid/bokeh/38283eaf-9838-4b78-80e7-2ed1bcd8df43%40continuum.io](https://groups.google.com/a/continuum.io/d/msgid/bokeh/38283eaf-9838-4b78-80e7-2ed1bcd8df43%40continuum.io?utm_medium=email&utm_source=footer).

  For more options, visit [https://groups.google.com/a/continuum.io/d/optout](https://groups.google.com/a/continuum.io/d/optout).

–
Sarah Bird
Developer, Bokeh

    [
      ![Continuum Analytics](http://docs.continuum.io/_static/img/ContinuumWordmark.png)
    ](http://continuum.io)
⌁   Link to post
tniederm
tniederm

Thanks for the quick reply.
I’ll do it that way then.

Best,

Tom

···

Am Mittwoch, 7. September 2016 22:18:59 UTC+2 schrieb Sarah Bird:

I’m guessing you’re going to
have the best luck by not using the high level Histogram feature, but b y using the plotting API
with HBar and VBar.

That means doing your own histo gram calculation which
is annoying, but the high level Charts interface is real ly designed for
quick exploration and not for more
custom ized
interactives.

Sincerely,

                                      Sarah

Bird

On 9/7/16 9:02 AM, tnie...@gmail.com > wrote:

Hi,

      I'm looking for a way to make the bars in a histogram

selectable and link them to a data source.

What I want to do is the following:

        I have a lot of different plots all on the same Data

Source, so all are linked.

I also have a DataTable linked to the same source.

        Inside that source there are a lot of columns with binary

values which are not plotted.

        Those collumns should be presented in a Histogram. If one

bar of the Histogram is pressed all points that for example
have value ‘1’ in that column should get selected in all
plots as well as the Data Table.

And does anyone know a way to speed up opening the html?

      I have about 90 plots, 300 points each and it takes about

2-4 minutes.

      Here is some code which already does anythoing apart from

linking the histograms and making them selectable.

Thanks, Tom

                def

init(self,xlsmPath):

                        #....

                        self.plotAll()

tabs =

                p =

layout.gridplot(self.__plots,ncols=4)

                stat =

layout.gridplot(self.__statPlots,ncols=4)

                w =

layout.WidgetBox(self.carSelect)

columns =

                for i in range

(1,self.__FirstColumn+self.__MaxNumParam):

columns.append(TableColumn( field=self.__desc[1,i],
title=self.__desc[1,i]))

                data_table =

layout.WidgetBox(DataTable( source=self.view,
columns=columns,width=5000, height=5000,
sortable=True,scroll_to_selection=True))

tabs.append(Panel(child=p,title = ‘All’))

                for i in

range(0,self.__MaxNumParam):

collayout=layout.gridplot(self.__columnPlots[i],ncols=1)

tabs.append(Panel(child= collayout, title =
(self.__desc[1,self.__FirstColumn+i])))

tabs.append(Panel(child=stat, title = ‘Statistics’))

tabs.append(Panel(child=data_ table,title = ‘Result
Table’))

                tabs =

Tabs(tabs=tabs,width=1000)

q=layout.layout([[w],[tabs]])

show(q)

def plotAll(self):

                self.carRange =

ColumnDataSource()

                self.colNames =

ColumnDataSource()

index=0

                for elem in

self.__carData:

                self.rowArea(index) # now begin and end should be

set

self.carRange.add([self.__ begin,self.__end],
name=str(elem[0]))

self.carmenu.append(elem[0])

index+=1

self.colNames.add([self.__ MaxNumParam],
name=‘length’)

index = 0

                for i in

range(0,self.__MaxNumParam):

self.colNames.add((self.__ desc[1,self.__FirstColumn+i]),
name=str(i))

index+=1

hover = HoverTool(

tooltips=[

                ("index",

“$index”),

                ("(x,y)",

“($x, $y)”),

])

                TOOLS =

“box_select,lasso_select,tap,wheel_zoom,reset,hover”

                self.datadict =

dict()

                for i in

range(1,self.__FirstColumn+self.__MaxNumParam):

self.datadict[(self.__desc[1,i])]=self.__data[:,i][0:self.__MaxNumRows]

                self.source=

ColumnDataSource(data=self.datadict)

                self.view =

ColumnDataSource(data=self.datadict)

index=0

                for i in

range(0,self.__MaxNumParam):

                for j in

range(i+1,self.__MaxNumParam):

self.__plots.append(figure( tools=TOOLS,plot_width=400,
plot_height=400,

                title=None,

toolbar_location=“below”,webgl=True,name=‘circle’+str(i*j)))

self.__plots[index].scatter((self.__desc[1,self.__FirstColumn+i]),(self.__desc[1,self.__FirstColumn+j]),source=self.view)

self.__plots[index].xaxis. axis_label =
(self.desc[1,self. FirstColumn+i])

self.__plots[index].yaxis. axis_label =
(self.desc[1,self. FirstColumn+j])

                hover =

self.__plots[index].select(dict(type=HoverTool))

hover.tooltips = [

(“index”, “$index”),

(“(x,y)”, “($x, $y)”),

]

                #select_tool =

self.__plots[index].select(dict(type=BoxSelectTool))

p=self.__plots[index]

                self.view.callback =

CustomJS(args=dict(p=p,source=self.view), code=“”"

var inds = cb_obj.get(‘selected’)[‘1d’].indices;

var d1 = cb_obj.get(‘data’);

var text = ‘’;

var datatext = ‘’;

for (i = 0; i < inds.length; i++) {

text = text.concat(inds[i]+‘||’);

                datatext = datatext.concat('Point '+inds[i]+'

');

}

“”"

)

index+=1

self.__columnPlots.append()

colindex = 0

                for k in

range(0,self.__MaxNumParam):

if i != k:

self.__columnPlots[i].append(figure(tools=TOOLS,plot_width= 900,
plot_height=400,

                title=None,

toolbar_location=“below”,webgl=True,name=‘test’+str(i*k)))

self.__columnPlots[i][colindex].scatter((self.__desc[1,self.__FirstColumn+i]),(self.__desc[1,self.__FirstColumn+k]),source=self.view)

self.__columnPlots[i][ colindex].xaxis.axis_label =
(self.__desc[1,self.__FirstColumn+i])

self.__columnPlots[i][ colindex].yaxis.axis_label =
(self.__desc[1,self.__FirstColumn+k])

                hover

=
self.__columnPlots[i][colindex].select(dict(type=HoverTool))

hover.tooltips = [

(“index”, “$index”),

(“(x,y)”, “($x, $y)”),

]

colindex += 1

                #TODO statistics

(now its time for some Barcharts)

                for i in

range(2,self.__FirstColumn):

self._statPlots.append(Histogram(self.datadict[self. _desc[1,i]],
title=self.__desc[1,i]))

self.__statPlots[i-2].xaxis. axis_label =
(self.__desc[1,i])

self.__statPlots[i-2].add_tools(bokeh.models.TapTool())

                self.carSelect =

Select(title=“Choose Car:”, options=self.carmenu)

self.carSelect.callback =
CustomJS(args=dict(rangeData=self.carRange,source=self.source,view=self.view, colNames=self.colNames),
code=“”"

var select = cb_obj.get(‘value’);

var viewData = view.get(‘data’);

var sourceData = source.get(‘data’);

var colNameData = colNames.get(‘data’);

var range = rangeData.get(‘data’)[select];

var numCols = parseInt(colNameData[‘length’]);

for (i = 0; i < numCols; i++) {

viewData[colNameData[i.toString()]]=sourceData[colNameData[i.toString()]].slice(range[0],range[1]);

}

view.trigger(‘change’);

“”"

)

                print 'Number of

plots: ',

print index

``

–

  You received this message because you are subscribed to the Google

Groups “Bokeh Discussion - Public” group.

  To unsubscribe from this group and stop receiving emails from it,

send an email to bokeh+un...@continuum.io.

  To post to this group, send email to bo...@continuum.io.

  To view this discussion on the web visit [https://groups.google.com/a/continuum.io/d/msgid/bokeh/38283eaf-9838-4b78-80e7-2ed1bcd8df43%40continuum.io](https://groups.google.com/a/continuum.io/d/msgid/bokeh/38283eaf-9838-4b78-80e7-2ed1bcd8df43%40continuum.io?utm_medium=email&utm_source=footer).

  For more options, visit [https://groups.google.com/a/continuum.io/d/optout](https://groups.google.com/a/continuum.io/d/optout).

–
Sarah Bird
Developer, Bokeh

    [
      <img alt="Continuum Analytics" src="https://lh6.googleusercontent.com/proxy/VYgVjggTk1hCXSN9wFkffE3I6kxTvJ51tT4KvDXOuKbs1WyFG66k7kt2-vkDimbyxfWtP-d1paJmstMYhPPnDYSUF4rLPoYM2GM2QFM=w5000-h5000" style="width:150px;min-height:30px" height="30px" width="150px">
    ](http://continuum.io)
⌁   Link to post

End of archived discussion · Replies are disabled