Hi,
In the example below. Is it possible to tag the buttons somehow to know which ones are being pushed and only draw area under graph for the respective curve? Buttons can be named with the attribute “name”, is it possible to get the name in the drawArea function?
from bokeh.io import show
from bokeh.layouts import column, row
from bokeh.models import ColorPicker, Div, HTMLTemplateFormatter, ColumnDataSource, TableColumn, DataTable, TextInput, Button
from bokeh.io import curdoc
from bokeh.plotting import figure, output_file, show
import numpy as np
from numpy import trapz
import pandas as pd
output_file("dark_minimal.html")
#curdoc().theme = 'dark_minimal'
plot = figure(width=350, height=350)
d = {'systems': ['Zone-1', 'Zone-2', 'Zone-3'],
'colors': ['#18e7b9','#520084','#d2d200'],
'power': [1.25, 1.5, 1.75]
}
df = pd.DataFrame(data=d, index = [0, 1, 2])
template="""
<span class="bk bk-input-group">
<input class="bk bk-input" type="color" value = <%= value %>>
</span>
"""
formatter = HTMLTemplateFormatter(template=template)
def getData(val, tstart = 0, tend = 10):
x = np.arange(tstart, tend, 1)
y = val**x
return x, y
def plotter(fig, df):
plot_dict = {} #use this dictionary to store/organize stuff
#basically going for this kind of structure:
#name/system as keys, each key holding another dictionary pointing to 'fig':thefigureitsplottedon, 'rend':thelinerenderer, and 'picker':itscorrespondingcolorpicker
for name, color, val in zip(sorted(df.systems), df.colors, df.power):
print(name, color, val)
x, y = getData(val)
line = fig.line(x=x, y=y, color=color, line_width=4, legend_label = name)
picker = ColorPicker(title=name,color=color) #added color arg here to properly initialize
tstart = TextInput(value="0", title="Start time", width = 200)
tend = TextInput(value="10", title="End time", width = 200)
drawButton = Button(label="Calculate Area under graph", button_type="success")
picker.js_link('color', line.glyph, 'line_color')
plot_dict[name] = {}
plot_dict[name]['fig'] = fig
plot_dict[name]['rend'] = line
plot_dict[name]['picker'] = picker
plot_dict[name]['tstart'] = tstart
plot_dict[name]['tend'] = tend
plot_dict[name]['drawButton'] = drawButton
drawButton.on_click(drawArea)
return plot_dict
def fillColorUndercurve(x, y, plot, tstart, tend, Zone, color):
print(tstart.value, tend.value)
area = trapz(y, x, dx=5)
print("area =", area)
plot.circle_cross(x, y ,
size = 7,
legend_label = Zone + ', Area = ' + str(round(area, 2)) + ' mg',
color=color,
fill_alpha = 1)
plot.varea(x = x,
y1 = 0.000000000000000000001,
y2 = y,
legend_label = Zone + ', Area = ' + str(round(area, 2)) + ' mg',
fill_color = color)
plot.legend.click_policy = 'hide'
return plot
def drawArea(event):
Zone = 'Zone-1'
tstart = plot_dict[Zone]['tstart']
tend = plot_dict[Zone]['tend']
print(tstart, tend)
x, y = getData(val = df.power[0], tstart = float(tstart.value), tend = float(tend.value))
color = df.colors[0]
fillColorUndercurve(x, y, plot, tstart, tend, Zone, color)
plot_dict = plotter(plot,df)
plot_dict['Zone-1']['drawButton'].on_click(drawArea)
#now just use plot dict to organize a layout/column
lo = row(plot, column([column(plot_dict[k]['picker'], plot_dict[k]['tstart'], plot_dict[k]['tend'], plot_dict[k]['drawButton']) for k in plot_dict.keys()]))
curdoc().add_root(lo)