tabs in a bokeh app

Hi,

Im trying to write an app that has multiple plots on different tabs below is an example of what I currently have, for some reason I get an empty plot of one of the figures before the layout of what I actually want, any help would be much appreciated?

from numpy import asarray, cumprod, convolve, exp, ones

from numpy.random import lognormal, gamma, uniform

from bokeh.models import ColumnDataSource, Slider, VBox, HBox, Select, GridPlot

from bokeh.models.widgets import Tabs, Panel

from bokeh.plotting import curdoc, Figure

from bokeh.driving import count

BUFSIZE = 200

MA12, MA26, EMA12, EMA26 = ‘12-tick Moving Avg’, ‘26-tick Moving Avg’, ‘12-tick EMA’, ‘26-tick EMA’

source = ColumnDataSource(dict(

time=[], average=[], low=[], high=[], open=[], close=[],

ma=[], macd=[], macd9=[], macdh=[], color=[]

))

p = Figure(plot_height=600, tools=“xpan,xwheel_zoom,xbox_zoom,reset”, x_axis_type=None)

p.x_range.follow = “end”

p.x_range.follow_interval = 100

p.line(x=‘time’, y=‘average’, alpha=0.2, line_width=3, color=‘navy’, source=source)

p.line(x=‘time’, y=‘ma’, alpha=0.8, line_width=2, color=‘orange’, source=source)

p.segment(x0=‘time’, y0=‘low’, x1=‘time’, y1=‘high’, line_width=2, color=‘black’, source=source)

p.segment(x0=‘time’, y0=‘open’, x1=‘time’, y1=‘close’, line_width=8, color=‘color’, source=source)

p2 = Figure(plot_height=250, x_range=p.x_range, tools=“xpan,xwheel_zoom,xbox_zoom,reset”)

p2.line(x=‘time’, y=‘macd’, color=‘red’, source=source)

p2.line(x=‘time’, y=‘macd9’, color=‘blue’, source=source)

p2.segment(x0=‘time’, y0=0, x1=‘time’, y1=‘macdh’, line_width=6, color=‘black’, alpha=0.5, source=source)

mean = Slider(title=“mean”, value=0, start=-0.01, end=0.01, step=0.001)

stddev = Slider(title=“stddev”, value=0.04, start=0.01, end=0.1, step=0.01)

mavg = Select(value=MA12, options=[MA12, MA26, EMA12, EMA26])

tab1 = Panel(child=p, title = “p”)

tab2 = Panel(child=p2, title = “p2”)

tabs = Tabs(tabs=[tab1,tab2])

curdoc().add_root(VBox(HBox(mean, stddev, mavg, width=800), VBox(p,tabs)))

def _create_prices(t):

last_average = 100 if t==0 else source.data['average'][-1]

returns = asarray(lognormal(mean.value, stddev.value, 1))

average =  last_average * cumprod(returns)

high = average * exp(abs(gamma(1, 0.03, size=1)))

low = average / exp(abs(gamma(1, 0.03, size=1)))

delta = high - low

open = low + delta * uniform(0.05, 0.95, size=1)

close = low + delta * uniform(0.05, 0.95, size=1)

return open[0], high[0], low[0], close[0], average[0]

def _moving_avg(prices, days=10):

if len(prices) < days: return [100]

return convolve(prices[-days:], ones(days, dtype=float), mode="valid") / days

def _ema(prices, days=10):

if len(prices) < days or days < 2: return [prices[-1]]

a = 2.0 / (days+1)

kernel = ones(days, dtype=float)

kernel[1:] = 1 - a

kernel = a * cumprod(kernel)

# The 0.8647 normalizes out that we stop the EMA after a finite number of terms

return convolve(prices[-days:], kernel, mode="valid") / (0.8647)

@count()

def update(t):

open, high, low, close, average = _create_prices(t)

color = "green" if open < close else "red"

new_data = dict(

    time=[t],

    open=[open],

    high=[high],

    low=[low],

    close=[close],

    average=[average],

    color=[color],

)

close = source.data['close'] + [close]

ma12 = _moving_avg(close[-12:], 12)[0]

ma26 = _moving_avg(close[-26:], 26)[0]

ema12 = _ema(close[-12:], 12)[0]

ema26 = _ema(close[-26:], 26)[0]

if   mavg.value == MA12:  new_data['ma'] = [ma12]

elif mavg.value == MA26:  new_data['ma'] = [ma26]

elif mavg.value == EMA12: new_data['ma'] = [ema12]

elif mavg.value == EMA26: new_data['ma'] = [ema26]

macd = ema12 - ema26

new_data['macd'] = [macd]

macd_series = source.data['macd'] + [macd]

macd9 = _ema(macd_series[-26:], 9)[0]

new_data['macd9'] = [macd9]

new_data['macdh'] = [macd - macd9]

source.stream(new_data, 300)

curdoc().add_periodic_callback(update, 50)

``

Thanks

Em

Hi Emma,

There is still an open issue with respect to Tabs and the server:

  https://github.com/bokeh/bokeh/issues/3138

It is blocked by some ongoing comprehensive layout (that should actually fix the problem as well), but that will take at least a few more weeks to complete.

However, what you can try in the mean time is to call

  curdoc().remove_root(p)

on the plots that you add as children to the Tab. I believe that should allow things to work for you in the short term. Please let us know if that works or not.

Bryan

···

On Apr 15, 2016, at 5:55 PM, Emma <[email protected]> wrote:

Hi,

Im trying to write an app that has multiple plots on different tabs below is an example of what I currently have, for some reason I get an empty plot of one of the figures before the layout of what I actually want, any help would be much appreciated?

from numpy import asarray, cumprod, convolve, exp, ones
from numpy.random import lognormal, gamma, uniform

from bokeh.models import ColumnDataSource, Slider, VBox, HBox, Select, GridPlot
from bokeh.models.widgets import Tabs, Panel
from bokeh.plotting import curdoc, Figure
from bokeh.driving import count

BUFSIZE = 200
MA12, MA26, EMA12, EMA26 = '12-tick Moving Avg', '26-tick Moving Avg', '12-tick EMA', '26-tick EMA'

source = ColumnDataSource(dict(
    time=, average=, low=, high=, open=, close=,
    ma=, macd=, macd9=, macdh=, color=
))

p = Figure(plot_height=600, tools="xpan,xwheel_zoom,xbox_zoom,reset", x_axis_type=None)
p.x_range.follow = "end"
p.x_range.follow_interval = 100

p.line(x='time', y='average', alpha=0.2, line_width=3, color='navy', source=source)
p.line(x='time', y='ma', alpha=0.8, line_width=2, color='orange', source=source)
p.segment(x0='time', y0='low', x1='time', y1='high', line_width=2, color='black', source=source)
p.segment(x0='time', y0='open', x1='time', y1='close', line_width=8, color='color', source=source)

p2 = Figure(plot_height=250, x_range=p.x_range, tools="xpan,xwheel_zoom,xbox_zoom,reset")
p2.line(x='time', y='macd', color='red', source=source)
p2.line(x='time', y='macd9', color='blue', source=source)
p2.segment(x0='time', y0=0, x1='time', y1='macdh', line_width=6, color='black', alpha=0.5, source=source)

mean = Slider(title="mean", value=0, start=-0.01, end=0.01, step=0.001)
stddev = Slider(title="stddev", value=0.04, start=0.01, end=0.1, step=0.01)
mavg = Select(value=MA12, options=[MA12, MA26, EMA12, EMA26])

tab1 = Panel(child=p, title = "p")
tab2 = Panel(child=p2, title = "p2")
tabs = Tabs(tabs=[tab1,tab2])

curdoc().add_root(VBox(HBox(mean, stddev, mavg, width=800), VBox(p,tabs)))

def _create_prices(t):
    last_average = 100 if t==0 else source.data['average'][-1]
    returns = asarray(lognormal(mean.value, stddev.value, 1))
    average = last_average * cumprod(returns)
    high = average * exp(abs(gamma(1, 0.03, size=1)))
    low = average / exp(abs(gamma(1, 0.03, size=1)))
    delta = high - low
    open = low + delta * uniform(0.05, 0.95, size=1)
    close = low + delta * uniform(0.05, 0.95, size=1)
    return open[0], high[0], low[0], close[0], average[0]

def _moving_avg(prices, days=10):
    if len(prices) < days: return [100]
    return convolve(prices[-days:], ones(days, dtype=float), mode="valid") / days

def _ema(prices, days=10):
    if len(prices) < days or days < 2: return [prices[-1]]
    a = 2.0 / (days+1)
    kernel = ones(days, dtype=float)
    kernel[1:] = 1 - a
    kernel = a * cumprod(kernel)
    # The 0.8647 normalizes out that we stop the EMA after a finite number of terms
    return convolve(prices[-days:], kernel, mode="valid") / (0.8647)

@count()
def update(t):
    open, high, low, close, average = _create_prices(t)
    color = "green" if open < close else "red"

    new_data = dict(
        time=[t],
        open=[open],
        high=[high],
        low=[low],
        close=[close],
        average=[average],
        color=[color],
    )

    close = source.data['close'] + [close]
    ma12 = _moving_avg(close[-12:], 12)[0]
    ma26 = _moving_avg(close[-26:], 26)[0]
    ema12 = _ema(close[-12:], 12)[0]
    ema26 = _ema(close[-26:], 26)[0]

    if mavg.value == MA12: new_data['ma'] = [ma12]
    elif mavg.value == MA26: new_data['ma'] = [ma26]
    elif mavg.value == EMA12: new_data['ma'] = [ema12]
    elif mavg.value == EMA26: new_data['ma'] = [ema26]

    macd = ema12 - ema26
    new_data['macd'] = [macd]

    macd_series = source.data['macd'] + [macd]
    macd9 = _ema(macd_series[-26:], 9)[0]
    new_data['macd9'] = [macd9]

    new_data['macdh'] = [macd - macd9]

    source.stream(new_data, 300)

curdoc().add_periodic_callback(update, 50)

Thanks
Em

--
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/d9012afa-5341-4786-94bc-128eb7dc0233%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Hi Bryan,

thanks for the quick reply. That seemed to do the job on my actual app so thanks…

Strangely that doesn’t seem to work on the example I posted.

Thanks

Em

···

On Saturday, 16 April 2016 09:46:45 UTC+10, Bryan Van de ven wrote:

Hi Emma,

There is still an open issue with respect to Tabs and the server:

    [https://github.com/bokeh/bokeh/issues/3138](https://github.com/bokeh/bokeh/issues/3138)

It is blocked by some ongoing comprehensive layout (that should actually fix the problem as well), but that will take at least a few more weeks to complete.

However, what you can try in the mean time is to call

    curdoc().remove_root(p)

on the plots that you add as children to the Tab. I believe that should allow things to work for you in the short term. Please let us know if that works or not.

Bryan

On Apr 15, 2016, at 5:55 PM, Emma [email protected] wrote:

Hi,

Im trying to write an app that has multiple plots on different tabs below is an example of what I currently have, for some reason I get an empty plot of one of the figures before the layout of what I actually want, any help would be much appreciated?

from numpy import asarray, cumprod, convolve, exp, ones

from numpy.random import lognormal, gamma, uniform

from bokeh.models import ColumnDataSource, Slider, VBox, HBox, Select, GridPlot

from bokeh.models.widgets import Tabs, Panel

from bokeh.plotting import curdoc, Figure

from bokeh.driving import count

BUFSIZE = 200

MA12, MA26, EMA12, EMA26 = ‘12-tick Moving Avg’, ‘26-tick Moving Avg’, ‘12-tick EMA’, ‘26-tick EMA’

source = ColumnDataSource(dict(

time=[], average=[], low=[], high=[], open=[], close=[],
ma=[], macd=[], macd9=[], macdh=[], color=[]

))

p = Figure(plot_height=600, tools=“xpan,xwheel_zoom,xbox_zoom,reset”, x_axis_type=None)

p.x_range.follow = “end”

p.x_range.follow_interval = 100

p.line(x=‘time’, y=‘average’, alpha=0.2, line_width=3, color=‘navy’, source=source)

p.line(x=‘time’, y=‘ma’, alpha=0.8, line_width=2, color=‘orange’, source=source)

p.segment(x0=‘time’, y0=‘low’, x1=‘time’, y1=‘high’, line_width=2, color=‘black’, source=source)

p.segment(x0=‘time’, y0=‘open’, x1=‘time’, y1=‘close’, line_width=8, color=‘color’, source=source)

p2 = Figure(plot_height=250, x_range=p.x_range, tools=“xpan,xwheel_zoom,xbox_zoom,reset”)

p2.line(x=‘time’, y=‘macd’, color=‘red’, source=source)

p2.line(x=‘time’, y=‘macd9’, color=‘blue’, source=source)

p2.segment(x0=‘time’, y0=0, x1=‘time’, y1=‘macdh’, line_width=6, color=‘black’, alpha=0.5, source=source)

mean = Slider(title=“mean”, value=0, start=-0.01, end=0.01, step=0.001)

stddev = Slider(title=“stddev”, value=0.04, start=0.01, end=0.1, step=0.01)

mavg = Select(value=MA12, options=[MA12, MA26, EMA12, EMA26])

tab1 = Panel(child=p, title = “p”)

tab2 = Panel(child=p2, title = “p2”)

tabs = Tabs(tabs=[tab1,tab2])

curdoc().add_root(VBox(HBox(mean, stddev, mavg, width=800), VBox(p,tabs)))

def _create_prices(t):

last_average = 100 if t==0 else source.data['average'][-1]
returns = asarray(lognormal(mean.value, stddev.value, 1))
average =  last_average * cumprod(returns)
high = average * exp(abs(gamma(1, 0.03, size=1)))
low = average / exp(abs(gamma(1, 0.03, size=1)))
delta = high - low
open = low + delta * uniform(0.05, 0.95, size=1)
close = low + delta * uniform(0.05, 0.95, size=1)
return open[0], high[0], low[0], close[0], average[0]

def _moving_avg(prices, days=10):

if len(prices) < days: return [100]
return convolve(prices[-days:], ones(days, dtype=float), mode="valid") / days

def _ema(prices, days=10):

if len(prices) < days or days < 2: return [prices[-1]]
a = 2.0 / (days+1)
kernel = ones(days, dtype=float)
kernel[1:] = 1 - a
kernel = a * cumprod(kernel)
# The 0.8647 normalizes out that we stop the EMA after a finite number of terms
return convolve(prices[-days:], kernel, mode="valid") / (0.8647)

@count()

def update(t):

open, high, low, close, average = _create_prices(t)
color = "green" if open < close else "red"
new_data = dict(
    time=[t],
    open=[open],
    high=[high],
    low=[low],
    close=[close],
    average=[average],
    color=[color],
)
close = source.data['close'] + [close]
ma12 = _moving_avg(close[-12:], 12)[0]
ma26 = _moving_avg(close[-26:], 26)[0]
ema12 = _ema(close[-12:], 12)[0]
ema26 = _ema(close[-26:], 26)[0]
if   mavg.value == MA12:  new_data['ma'] = [ma12]
elif mavg.value == MA26:  new_data['ma'] = [ma26]
elif mavg.value == EMA12: new_data['ma'] = [ema12]
elif mavg.value == EMA26: new_data['ma'] = [ema26]
macd = ema12 - ema26
new_data['macd'] = [macd]
macd_series = source.data['macd'] + [macd]
macd9 = _ema(macd_series[-26:], 9)[0]
new_data['macd9'] = [macd9]
new_data['macdh'] = [macd - macd9]
source.stream(new_data, 300)

curdoc().add_periodic_callback(update, 50)

Thanks

Em


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/d9012afa-5341-4786-94bc-128eb7dc0233%40continuum.io.

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