0

I already have a slider code from here where it's just static, it has to be slided manually , but I want something which has a play button on it and can be played by clicking on it.

Here is what I tried doing to have a play and pause button, here is the source from where I got this code

def animate_update():
    year = slider.value + 1
    if year > years[-1]:
        year = years[0]
    slider.value = year


def slider_update(attrname, old, new):
    year = slider.value
    label.text = str(year)
    source.data = data[year]

slider = Slider(start=years[0], end=years[-1], value=years[0], step=1, title="Year")
slider.on_change('value', slider_update)


def animate():
    if button.label == '► Play':
        button.label = '❚❚ Pause'
        curdoc().add_periodic_callback(animate_update, 200)
    else:
        button.label = '► Play'
        curdoc().remove_periodic_callback(animate_update)

button = Button(label='► Play', width=60)
button.on_click(animate)

But when using this it gives me error

NameError                                 Traceback (most recent call last)
<ipython-input-15-f62f961b8000> in <module>()
     32         curdoc().remove_periodic_callback(animate_update)
     33 
---> 34 button = Button(label='► Play', width=60)
     35 button.on_click(animate)

NameError: name 'Button' is not defined

P.S - I'm using jupyter notebook.

What is there that I'm doing it wrong.

Any help would be much appreciated.

Thanks

Domnick

3
  • It seems that you did not import "Button" from bokeh.models Commented Jan 23, 2018 at 14:46
  • @Seb, the github link you provided in one of your answered post, has the code for automatic slider ,but how do I save it or how do I run it ,sorry for a silly question. Commented Jan 24, 2018 at 7:13
  • The github code runs with a bokeh server from the commandline with "bokeh serve --show scriptname.py" Commented Jan 24, 2018 at 13:21

1 Answer 1

1

Here is an example of play button for slider with a local Bokeh Server (by combining these two links : here and here).

Before, you need to install bokeh.

Then, you write and run this script :

 from bokeh.server.server import Server
 from bokeh.application import Application
 from bokeh.application.handlers.function import FunctionHandler
 from bokeh.plotting import figure, ColumnDataSource
 from bokeh.core.properties import field
 from bokeh.models import (HoverTool, SingleIntervalTicker,
                           Slider, Button, Label, CategoricalColorMapper)
 from bokeh.palettes import Spectral6 
 import numpy as np
 import pandas as pd

def process_data():
    from bokeh.sampledata.gapminder import fertility, life_expectancy, population, regions

    # Make the column names ints not strings for handling
    columns = list(fertility.columns)
    years = list(range(int(columns[0]), int(columns[-1])))
    rename_dict = dict(zip(columns, years))

    fertility = fertility.rename(columns=rename_dict)
    life_expectancy = life_expectancy.rename(columns=rename_dict)
    population = population.rename(columns=rename_dict)
    regions = regions.rename(columns=rename_dict)

    regions_list = list(regions.Group.unique())

    # Turn population into bubble sizes. Use min_size and factor to tweak.
    scale_factor = 200
    population_size = np.sqrt(population / np.pi) / scale_factor
    min_size = 3
    population_size = population_size.where(population_size >= min_size).fillna(min_size)

    return fertility, life_expectancy, population_size, regions, years, regions_list


def make_document(doc):

    fertility_df, life_expectancy_df, population_df_size, regions_df, years, regions_list = process_data()

    df = pd.concat({'fertility': fertility_df,
                'life': life_expectancy_df,
                'population': population_df_size},
               axis=1)    
    data = {}

    regions_df.rename({'Group':'region'}, axis='columns', inplace=True)
    for year in years:
        df_year = df.iloc[:,df.columns.get_level_values(1)==year]
        df_year.columns = df_year.columns.droplevel(1)
        data[year] = df_year.join(regions_df.region).reset_index().to_dict('series')

    source = ColumnDataSource(data=data[years[0]])

    plot = figure(x_range=(1, 9), y_range=(20, 100), title='Gapminder Data', plot_height=300)
    plot.xaxis.ticker = SingleIntervalTicker(interval=1)
    plot.xaxis.axis_label = "Children per woman (total fertility)"
    plot.yaxis.ticker = SingleIntervalTicker(interval=20)
    plot.yaxis.axis_label = "Life expectancy at birth (years)"

    label = Label(x=1.1, y=18, text=str(years[0]), text_font_size='70pt', text_color='#eeeeee')
    plot.add_layout(label)

    color_mapper = CategoricalColorMapper(palette=Spectral6, factors=regions_list)
    plot.circle(
      x='fertility',
      y='life',
      size='population',
      source=source,
      fill_color={'field': 'region', 'transform': color_mapper},
      fill_alpha=0.8,
      line_color='#7c7e71',
      line_width=0.5,
      line_alpha=0.5,
      legend=field('region'),
    )
    plot.add_tools(HoverTool(tooltips="@Country", show_arrow=False,  point_policy='follow_mouse'))

    def animate_update():
        year = slider.value + 1
        if year > years[-1]:
            year = years[0]
        slider.value = year    

    def slider_update(attrname, old, new):
        year = slider.value
        label.text = str(year)
        source.data = data[year]

    slider = Slider(start=years[0], end=years[-1], value=years[0], step=1, title="Year")
    slider.on_change('value', slider_update)

    callback_id = None

    def animate():
        global callback_id
        if button.label == '► Play':
            button.label = '❚❚ Pause'
            callback_id = doc.add_periodic_callback(animate_update, 200)
        else:
            button.label = '► Play'
            doc.remove_periodic_callback(callback_id)

    button = Button(label='► Play', width=60)
    button.on_click(animate)    

    doc.add_root(button)
    doc.add_root(slider)
    doc.add_root(plot)

apps = {'/': Application(FunctionHandler(make_document))}

server = Server(apps, port=5000)
server.start()

And after, write in a navigator : http://localhost:5000/

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.