Updating Hovertools on change with Custom JS.

Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I’d love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I’d love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I’m trying to do. You can access it at the Stack Overflow post. I’ll also attached the code to this post, and I’ll past the text it at the very bottom.

Anyone have any ideas?

Here’s the code:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row
#Create a dataframe with x and y coordinates and 4 different statistics
df = pd.DataFrame({
            'x':[1,2,3],
            'y':[1,2,3],
            'stat1':[1,2,3],
            'stat2':[4,5,6],
            'stat3':[7,8,9],
            'stat4':[10,11,12],
            'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource
source=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats
option1=[('Stat1','@stat1'),
         ('Stat2','@stat2')]

option2=[('Stat3','@stat3'),
         ('Stat4','@stat4'),
         ('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips
hover=HoverTool(tooltips=option1)

#Create the figure
plot = figure(tools=[hover])
plot.circle('x', 'y', source=source)

#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover), code=    """
if (cb_obj.value='Stat Set 1') {
tt.tooltips=option1
} else {
tt.tooltips=option2
}
""")

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips
stat_select=Select(options=['Stat Set 1', 'Stat Set 2'],
                        value='Stat Set 1',
                         title='What stats set do you want to see when you hover?', callback=callback)

show(row(stat_select,plot))

Mapper.ipynb (13.8 KB)

1 Like

Maybe not exactly what you asked but displaying different values for the y-axis. The y-values change also as result of datasource swap.
If you want the range and values on the axis don’t change than you could try to add a new var e.g. “z” to your datasource and connect it to the displayed hover values like: tooltips = [(‘y’, ‘@z’)].

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row

df = pd.DataFrame({‘x’:[1, 2, 3],
‘y’:[1, 2, 3],
‘stat1’:[1, 2, 3],
‘stat2’:[4, 5, 6],
‘stat3’:[7, 8, 9],
‘stat4’:[10, 11, 12] })

source = ColumnDataSource(data = df)
hover = HoverTool(tooltips = [(‘x’, ‘@x’), (‘y’, ‘@y’)])
plot = figure(tools = [hover])
plot.circle(x = ‘x’, y = ‘y’, source = source)

callback = CustomJS (args = {‘source’: source}, code = “”"
var new_data = {‘x’: , ‘y’: , ‘stat1’: , ‘stat2’: , ‘stat3’: , ‘stat4’: };
var old_data = source.data;
new_data[‘x’] = source.data[‘x’];
new_data[‘stat1’] = source.data[‘stat1’];
new_data[‘stat2’] = source.data[‘stat2’];
new_data[‘stat3’] = source.data[‘stat3’];
new_data[‘stat4’] = source.data[‘stat4’];
new_data[‘y’] = old_data[cb_obj.value];
source.data = new_data; “”")

stat_select = Select(options = [‘stat1’, ‘stat2’, ‘stat3’, ‘stat4’], value = ‘stats1’, title = ‘Select stats set’, callback = callback)
show(row(stat_select, plot))

``

···

On Friday, November 16, 2018 at 5:15:04 PM UTC+1, Eric Larson wrote:

Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I’d love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I’d love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I’m trying to do. You can access it at the Stack Overflow post. I’ll also attached the code to this post, and I’ll past the text it at the very bottom.

Anyone have any ideas?

Here’s the code:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row
#Create a dataframe with x and y coordinates and 4 different statistics
df = pd.DataFrame({
            'x':[1,2,3],
            'y':[1,2,3],
            'stat1':[1,2,3],
            'stat2':[4,5,6],
            'stat3':[7,8,9],
            'stat4':[10,11,12],
            'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource
source=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats
option1=[('Stat1','@stat1'),
         ('Stat2','@stat2')]

option2=[('Stat3','@stat3'),
         ('Stat4','@stat4'),
         ('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips
hover=HoverTool(tooltips=option1)

#Create the figure
plot = figure(tools=[hover])
plot.circle('x', 'y', source=source)

#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover), code=    """
if (cb_obj.value='Stat Set 1') {
tt.tooltips=option1
} else {
tt.tooltips=option2
}
""")

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips
stat_select=Select(options=['Stat Set 1', 'Stat Set 2'],
                        value='Stat Set 1',
                         title='What stats set do you want to see when you hover?', callback=callback)

show(row(stat_select,plot))

And another version leaving the Y-axis values unchanged.

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row

df = pd.DataFrame({‘x’:[1, 2, 3],
‘y’:[1, 2, 3],
‘z’:[1, 2, 3],
‘stat1’:[1, 2, 3],
‘stat2’:[4, 5, 6],
‘stat3’:[7, 8, 9],
‘stat4’:[10, 11, 12] })

source = ColumnDataSource(data = df)
hover = HoverTool(tooltips = [(‘x’, ‘@x’), (‘y’, ‘@z’)])
plot = figure(tools = [hover])
plot.circle(x = ‘x’, y = ‘y’, source = source)

callback = CustomJS (args = {‘source’: source}, code = “”"
var new_data = {‘x’: , ‘y’: , ‘z’: , ‘stat1’: , ‘stat2’: , ‘stat3’: , ‘stat4’: };
var old_data = source.data;
new_data[‘x’] = source.data[‘x’];
new_data[‘y’] = source.data[‘y’];
new_data[‘stat1’] = source.data[‘stat1’];
new_data[‘stat2’] = source.data[‘stat2’];
new_data[‘stat3’] = source.data[‘stat3’];
new_data[‘stat4’] = source.data[‘stat4’];
new_data[‘z’] = old_data[cb_obj.value];
source.data = new_data; “”")

stat_select = Select(options = [‘stat1’, ‘stat2’, ‘stat3’, ‘stat4’], value = ‘stats1’, title = ‘Select stats set’, callback = callback)
show(row(stat_select, plot))

``

···

On Thursday, November 22, 2018 at 9:13:59 PM UTC+1, tony halik wrote:

Maybe not exactly what you asked but displaying different values for the y-axis. The y-values change also as result of datasource swap.
If you want the range and values on the axis don’t change than you could try to add a new var e.g. “z” to your datasource and connect it to the displayed hover values like: tooltips = [(‘y’, ‘@z’)].

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row

df = pd.DataFrame({‘x’:[1, 2, 3],
‘y’:[1, 2, 3],
‘stat1’:[1, 2, 3],
‘stat2’:[4, 5, 6],
‘stat3’:[7, 8, 9],
‘stat4’:[10, 11, 12] })

source = ColumnDataSource(data = df)
hover = HoverTool(tooltips = [(‘x’, ‘@x’), (‘y’, ‘@y’)])
plot = figure(tools = [hover])
plot.circle(x = ‘x’, y = ‘y’, source = source)

callback = CustomJS (args = {‘source’: source}, code = “”"
var new_data = {‘x’: , ‘y’: , ‘stat1’: , ‘stat2’: , ‘stat3’: , ‘stat4’: };
var old_data = source.data;
new_data[‘x’] = source.data[‘x’];
new_data[‘stat1’] = source.data[‘stat1’];
new_data[‘stat2’] = source.data[‘stat2’];
new_data[‘stat3’] = source.data[‘stat3’];
new_data[‘stat4’] = source.data[‘stat4’];
new_data[‘y’] = old_data[cb_obj.value];
source.data = new_data; “”")

stat_select = Select(options = [‘stat1’, ‘stat2’, ‘stat3’, ‘stat4’], value = ‘stats1’, title = ‘Select stats set’, callback = callback)
show(row(stat_select, plot))

``

On Friday, November 16, 2018 at 5:15:04 PM UTC+1, Eric Larson wrote:

Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I’d love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I’d love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I’m trying to do. You can access it at the Stack Overflow post. I’ll also attached the code to this post, and I’ll past the text it at the very bottom.

Anyone have any ideas?

Here’s the code:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row
#Create a dataframe with x and y coordinates and 4 different statistics
df = pd.DataFrame({
            'x':[1,2,3],
            'y':[1,2,3],
            'stat1':[1,2,3],
            'stat2':[4,5,6],
            'stat3':[7,8,9],
            'stat4':[10,11,12],
            'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource
source=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats
option1=[('Stat1','@stat1'),
         ('Stat2','@stat2')]

option2=[('Stat3','@stat3'),
         ('Stat4','@stat4'),
         ('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips
hover=HoverTool(tooltips=option1)

#Create the figure
plot = figure(tools=[hover])
plot.circle('x', 'y', source=source)

#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover), code=    """
if (cb_obj.value='Stat Set 1') {
tt.tooltips=option1
} else {
tt.tooltips=option2
}
""")

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips
stat_select=Select(options=['Stat Set 1', 'Stat Set 2'],
                        value='Stat Set 1',
                         title='What stats set do you want to see when you hover?', callback=callback)

show(row(stat_select,plot))

Thanks so much for your efforts, I appreciate it a great deal!

Unfortunately, I don’t think this will address what I’m trying to do (which I’m starting to believe is impossible). Ideally, my solution is going to have a variable number of items fed to the tooltips, which is why in my example I gave option1 2 items, and option2 3 items.

The real world application of this scatterplot stems from having a ton of statistics I’d like to show people about points on a scatterplot, like demographics. So, ideally, I’d like to have a dropdown where you can pick which demographics you want to show folks in the tooltips. For instance, you’d pick “income level,” and 5 buckets of income levels would show up in the tooltips. If you switch the dropdown to gender, it’d only have 2 values: Male/Female.

···

On Thursday, November 22, 2018 at 2:21:02 PM UTC-6, tony halik wrote:

And another version leaving the Y-axis values unchanged.

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row

df = pd.DataFrame({‘x’:[1, 2, 3],
‘y’:[1, 2, 3],
‘z’:[1, 2, 3],
‘stat1’:[1, 2, 3],
‘stat2’:[4, 5, 6],
‘stat3’:[7, 8, 9],
‘stat4’:[10, 11, 12] })

source = ColumnDataSource(data = df)
hover = HoverTool(tooltips = [(‘x’, ‘@x’), (‘y’, ‘@z’)])
plot = figure(tools = [hover])
plot.circle(x = ‘x’, y = ‘y’, source = source)

callback = CustomJS (args = {‘source’: source}, code = “”"
var new_data = {‘x’: , ‘y’: , ‘z’: , ‘stat1’: , ‘stat2’: , ‘stat3’: , ‘stat4’: };
var old_data = source.data;
new_data[‘x’] = source.data[‘x’];
new_data[‘y’] = source.data[‘y’];
new_data[‘stat1’] = source.data[‘stat1’];
new_data[‘stat2’] = source.data[‘stat2’];
new_data[‘stat3’] = source.data[‘stat3’];
new_data[‘stat4’] = source.data[‘stat4’];
new_data[‘z’] = old_data[cb_obj.value];
source.data = new_data; “”")

stat_select = Select(options = [‘stat1’, ‘stat2’, ‘stat3’, ‘stat4’], value = ‘stats1’, title = ‘Select stats set’, callback = callback)
show(row(stat_select, plot))

``

On Thursday, November 22, 2018 at 9:13:59 PM UTC+1, tony halik wrote:

Maybe not exactly what you asked but displaying different values for the y-axis. The y-values change also as result of datasource swap.
If you want the range and values on the axis don’t change than you could try to add a new var e.g. “z” to your datasource and connect it to the displayed hover values like: tooltips = [(‘y’, ‘@z’)].

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row

df = pd.DataFrame({‘x’:[1, 2, 3],
‘y’:[1, 2, 3],
‘stat1’:[1, 2, 3],
‘stat2’:[4, 5, 6],
‘stat3’:[7, 8, 9],
‘stat4’:[10, 11, 12] })

source = ColumnDataSource(data = df)
hover = HoverTool(tooltips = [(‘x’, ‘@x’), (‘y’, ‘@y’)])
plot = figure(tools = [hover])
plot.circle(x = ‘x’, y = ‘y’, source = source)

callback = CustomJS (args = {‘source’: source}, code = “”"
var new_data = {‘x’: , ‘y’: , ‘stat1’: , ‘stat2’: , ‘stat3’: , ‘stat4’: };
var old_data = source.data;
new_data[‘x’] = source.data[‘x’];
new_data[‘stat1’] = source.data[‘stat1’];
new_data[‘stat2’] = source.data[‘stat2’];
new_data[‘stat3’] = source.data[‘stat3’];
new_data[‘stat4’] = source.data[‘stat4’];
new_data[‘y’] = old_data[cb_obj.value];
source.data = new_data; “”")

stat_select = Select(options = [‘stat1’, ‘stat2’, ‘stat3’, ‘stat4’], value = ‘stats1’, title = ‘Select stats set’, callback = callback)
show(row(stat_select, plot))

``

On Friday, November 16, 2018 at 5:15:04 PM UTC+1, Eric Larson wrote:

Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I’d love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I’d love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I’m trying to do. You can access it at the Stack Overflow post. I’ll also attached the code to this post, and I’ll past the text it at the very bottom.

Anyone have any ideas?

Here’s the code:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row
#Create a dataframe with x and y coordinates and 4 different statistics
df = pd.DataFrame({
            'x':[1,2,3],
            'y':[1,2,3],
            'stat1':[1,2,3],
            'stat2':[4,5,6],
            'stat3':[7,8,9],
            'stat4':[10,11,12],
            'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource
source=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats
option1=[('Stat1','@stat1'),
         ('Stat2','@stat2')]

option2=[('Stat3','@stat3'),
         ('Stat4','@stat4'),
         ('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips
hover=HoverTool(tooltips=option1)

#Create the figure
plot = figure(tools=[hover])
plot.circle('x', 'y', source=source)

#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover), code=    """
if (cb_obj.value='Stat Set 1') {
tt.tooltips=option1
} else {
tt.tooltips=option2
}
""")

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips
stat_select=Select(options=['Stat Set 1', 'Stat Set 2'],
                        value='Stat Set 1',
                         title='What stats set do you want to see when you hover?', callback=callback)

show(row(stat_select,plot))

options = [option1, option2]

#Create the callback that will update the tooltips

callback = CustomJS (args=dict(tt=plot.hover, opts=options), code=“”"

if (cb_obj.value=='Stat Set 1') {

    tt[0].tooltips=opts[0]

} else {

    tt[0].tooltips=opts[1]

}

""")

``

This code should work

···

Le vendredi 16 novembre 2018 17:15:04 UTC+1, Eric Larson a écrit :

Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I’d love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I’d love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I’m trying to do. You can access it at the Stack Overflow post. I’ll also attached the code to this post, and I’ll past the text it at the very bottom.

Anyone have any ideas?

Here’s the code:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row
#Create a dataframe with x and y coordinates and 4 different statistics
df = pd.DataFrame({
            'x':[1,2,3],
            'y':[1,2,3],
            'stat1':[1,2,3],
            'stat2':[4,5,6],
            'stat3':[7,8,9],
            'stat4':[10,11,12],
            'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource
source=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats
option1=[('Stat1','@stat1'),
         ('Stat2','@stat2')]

option2=[('Stat3','@stat3'),
         ('Stat4','@stat4'),
         ('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips
hover=HoverTool(tooltips=option1)

#Create the figure
plot = figure(tools=[hover])
plot.circle('x', 'y', source=source)

#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover), code=    """
if (cb_obj.value='Stat Set 1') {
tt.tooltips=option1
} else {
tt.tooltips=option2
}
""")

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips
stat_select=Select(options=['Stat Set 1', 'Stat Set 2'],
                        value='Stat Set 1',
                         title='What stats set do you want to see when you hover?', callback=callback)

show(row(stat_select,plot))

Xavier’s done it!

That’s amazing. I’m a little curious about the logic behind adding the [0] after the tt. Do you have a quick explanation as to why that’s necessary? I’m also all ears on good sources for learning about CustomJs within Bokeh. That seems to be the major pitfall for me in the things I’m trying to do.

Thanks again for all of your help!!!

···

On Monday, November 26, 2018 at 1:53:32 PM UTC-6, Xavier Artusi wrote:

options = [option1, option2]

#Create the callback that will update the tooltips

callback = CustomJS (args=dict(tt=plot.hover, opts=options), code=“”"

if (cb_obj.value=='Stat Set 1') {
    tt[0].tooltips=opts[0]
} else {
    tt[0].tooltips=opts[1]
}
""")

``

This code should work

Le vendredi 16 novembre 2018 17:15:04 UTC+1, Eric Larson a écrit :

Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I’d love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I’d love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I’m trying to do. You can access it at the Stack Overflow post. I’ll also attached the code to this post, and I’ll past the text it at the very bottom.

Anyone have any ideas?

Here’s the code:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row
#Create a dataframe with x and y coordinates and 4 different statistics
df = pd.DataFrame({
            'x':[1,2,3],
            'y':[1,2,3],
            'stat1':[1,2,3],
            'stat2':[4,5,6],
            'stat3':[7,8,9],
            'stat4':[10,11,12],
            'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource
source=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats
option1=[('Stat1','@stat1'),
         ('Stat2','@stat2')]

option2=[('Stat3','@stat3'),
         ('Stat4','@stat4'),
         ('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips
hover=HoverTool(tooltips=option1)

#Create the figure
plot = figure(tools=[hover])
plot.circle('x', 'y', source=source)

#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover), code=    """
if (cb_obj.value='Stat Set 1') {
tt.tooltips=option1
} else {
tt.tooltips=option2
}
""")

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips
stat_select=Select(options=['Stat Set 1', 'Stat Set 2'],
                        value='Stat Set 1',
                         title='What stats set do you want to see when you hover?', callback=callback)

show(row(stat_select,plot))

actually I just added “debugger” to your code in CustomJS and used the chrome debugger to find out thats hover was holding an array.

···

Le lundi 26 novembre 2018 22:25:18 UTC+1, Eric Larson a écrit :

Xavier’s done it!

That’s amazing. I’m a little curious about the logic behind adding the [0] after the tt. Do you have a quick explanation as to why that’s necessary? I’m also all ears on good sources for learning about CustomJs within Bokeh. That seems to be the major pitfall for me in the things I’m trying to do.

Thanks again for all of your help!!!

On Monday, November 26, 2018 at 1:53:32 PM UTC-6, Xavier Artusi wrote:

options = [option1, option2]

#Create the callback that will update the tooltips

callback = CustomJS (args=dict(tt=plot.hover, opts=options), code=“”"

if (cb_obj.value=='Stat Set 1') {
    tt[0].tooltips=opts[0]
} else {
    tt[0].tooltips=opts[1]
}
""")

``

This code should work

Le vendredi 16 novembre 2018 17:15:04 UTC+1, Eric Larson a écrit :

Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I’d love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I’d love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I’m trying to do. You can access it at the Stack Overflow post. I’ll also attached the code to this post, and I’ll past the text it at the very bottom.

Anyone have any ideas?

Here’s the code:

import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import row
#Create a dataframe with x and y coordinates and 4 different statistics
df = pd.DataFrame({
            'x':[1,2,3],
            'y':[1,2,3],
            'stat1':[1,2,3],
            'stat2':[4,5,6],
            'stat3':[7,8,9],
            'stat4':[10,11,12],
            'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource
source=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats
option1=[('Stat1','@stat1'),
         ('Stat2','@stat2')]

option2=[('Stat3','@stat3'),
         ('Stat4','@stat4'),
         ('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips
hover=HoverTool(tooltips=option1)

#Create the figure
plot = figure(tools=[hover])
plot.circle('x', 'y', source=source)

#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover), code=    """
if (cb_obj.value='Stat Set 1') {
tt.tooltips=option1
} else {
tt.tooltips=option2
}
""")

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips
stat_select=Select(options=['Stat Set 1', 'Stat Set 2'],
                        value='Stat Set 1',
                         title='What stats set do you want to see when you hover?', callback=callback)

show(row(stat_select,plot))

Hi,

A plot can have multiple tooltips, so plot.hover returns a list, the subscript picks out the first hover tool from that list. You could alternatively make sure to just pass the one HoverTool as an argument to CustomJS, then you would not need to subscript in the JS code:

    callback = CustomJS (args=dict(tt=plot.hover[0], opts=options), code="""
        if (cb_obj.value=='Stat Set 1') {
            tt.tooltips=opts[0]
        } else {
            tt.tooltips=opts[1]
        }
    """)

Thanks,

Bryan

···

On Nov 26, 2018, at 14:16, [email protected] wrote:

actually I just added "debugger" to your code in CustomJS and used the chrome debugger to find out thats hover was holding an array.

Le lundi 26 novembre 2018 22:25:18 UTC+1, Eric Larson a écrit :
Xavier's done it!

That's amazing. I'm a little curious about the logic behind adding the [0] after the tt. Do you have a quick explanation as to why that's necessary? I'm also all ears on good sources for learning about CustomJs within Bokeh. That seems to be the major pitfall for me in the things I'm trying to do.

Thanks again for all of your help!!!

On Monday, November 26, 2018 at 1:53:32 PM UTC-6, Xavier Artusi wrote:
options = [option1, option2]
#Create the callback that will update the tooltips
callback = CustomJS (args=dict(tt=plot.hover, opts=options), code="""
    if (cb_obj.value=='Stat Set 1') {
        tt[0].tooltips=opts[0]
    } else {
        tt[0].tooltips=opts[1]
    }
    """)

This code should work

Le vendredi 16 novembre 2018 17:15:04 UTC+1, Eric Larson a écrit :
Hey everyone-

I posted this over at Stack Overflow as well here, but no luck yet.

I have a very similar problem to this post. It looked like the user came up with a clunky workaround, but it utilized bokeh server and I'd love to come up with a solution that would output the dynamic chart into a html file. So, my assumption is I need to figure something out via CustomJS callbacks.

Long story short, I'd love to have a plot and a dropdown. When you change the dropdown, everything stays the same, but there would be different stats fed to the tooltips. I wrote some sample code that should paint a pretty clear picture of what I'm trying to do. You can access it at the Stack Overflow post. I'll also attached the code to this post, and I'll past the text it at the very bottom.

Anyone have any ideas?

Here's the code:

import pandas as
pd

from bokeh.plotting import figure,
show

from bokeh.models import CustomJS, ColumnDataSource, HoverTool, ColumnDataSource, Select
from bokeh.layouts import
row

#Create a dataframe with x and y coordinates and 4 different statistics

df
= pd.DataFrame({

'x':[1,2,3],

'y':[1,2,3],

'stat1':[1,2,3],

'stat2':[4,5,6],

'stat3':[7,8,9],

'stat4':[10,11,12],

'stat5':[13,14,15]
})

#Create Bokeh's ColumnDataSource

source
=ColumnDataSource(data=df)

#Create the different options for the Hovertool tooltips. Note the dynamic number of stats

option1
=[('Stat1','@stat1'),

('Stat2','@stat2')]

option2
=[('Stat3','@stat3'),

('Stat4','@stat4'),

('Stat5','@stat5')]

#Set the default option for the Hovertool tooltips

hover
=HoverTool(tooltips=option1)

#Create the figure

plot
= figure(tools=[hover])

plot
.circle('x', 'y', source=source)

#Create the callback that will update the tooltips

callback
= CustomJS (args=dict(tt=plot.hover), code=
"""
    if (cb_obj.value='Stat Set 1') {
        tt.tooltips=option1
    } else {
        tt.tooltips=option2
    }
    """
)

#Create a dropdown menu that allows you to change which set of stats will populate the tooltips

stat_select
=Select(options=['Stat Set 1', 'Stat Set 2'],

                        value
='Stat Set 1',

                         title
='What stats set do you want to see when you hover?', callback=callback)

show
(row(stat_select,plot))

--
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/086eed01-681b-48ea-911c-388ab3277119%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

1 Like