Bokeh: updating widget after initial creation

Viewed 650

I'm trying to create a tool that will allow a user to select different parameters for plotting model data. I can generate the widgets initially, but I'd like to update one of the widgets based on a possible selection from the user.

Bokeh page

In this example, I've defaulted the value "Phase" to "Water" and "Effective Radius" to a list of values that correspond with water-only. If the user selects "Ice" from "Phase", I'd like the widget to update from a different list of values. Here is the relevant code:

from bokeh.models.widgets import (Slider, Button, CheckboxGroup, 
                             RadioButtonGroup, RadioGroup, Dropdown, Select)
# Selector for phase.
#--------------------
phs = [ "Water", "Ice", "Clear" ]
phs_select1 = Select( title="Cloud Phase", value=phs[0], options=phs, 
    width=150 )
phs_select2 = Select( title="Cloud Phase", value=phs[0], options=phs, 
    width=150 )

def update_phs( flag ):

    if flag == 0:
        fname[flag,3] = phs_select1.value.lower()
        update_de_list( )
        de_select1.update()
    if flag ==1:
        fname[flag,3] = phs_select2.value.lower()
        update_de_list( )
phs_select1.on_change( 'value', lambda attr, new, old: update_phs(0) )
phs_select2.on_change( 'value', lambda attr, new, old: update_phs(1) )

# Selector for effective diameter.
#----------------------------
de = [np.str(x) for x in (8, 20, 32, 50)]
def update_de_list():
# Add something here to update the widget?
    ?????????????????????????
    if phs_select1.value.lower() == "water":
        de = [np.str(x) for x in (8, 20, 32, 50)]
    elif phs_select1.value.lower() == "ice":
        de = [np.str(x) for x in (21.86, 46.34, 115.32)]
    ????????????????????????????????????
    ?
    ? Once user has selected a different phase, I need to update 
    ? "Effective Diameter field.
    ?
    ?????????????????????????

de_select1= Select( title="Effective Diameter", value=de[0], options=de, 
width=150 )
de_select2 = Select( title="Effective Diameter", value=de[0], options=de, 
width=150 )
def update_de( flag ):
    if flag == 0:
        fname[flag,5] = "de"+de_select1.value
    if flag == 1:
        fname[flag,5] = "de"+de_select2.value                                                                                                        

de_select1.on_change( 'value', lambda attr, new, old: update_de(0) )
de_select2.on_change( 'value', lambda attr, new, old: update_de(1) )

# Layout the widgets for the first file
lft_pnl = [srf_select1,igbp_select1,tau_select1,ws_select1,aod_select1]
rgt_pnl = [ prf_select1, phs_select1, de_select1, cld_select1 ]
lft_col = WidgetBox( *lft_pnl, sizing_mode="fixed", width=150)
rgt_col = WidgetBox( *rgt_pnl, sizing_mode="fixed", width=150)

# Layout the widgets for the first file
lft_pnl = [srf_select2,igbp_select2,tau_select2,ws_select2,aod_select2]
rgt_pnl = [ prf_select2, phs_select2, de_select2, cld_select2 ]
lft_col2 = WidgetBox( *lft_pnl, sizing_mode="fixed", width=150)
rgt_col2 = WidgetBox( *rgt_pnl, sizing_mode="fixed", width=150)

pnl_layout = layout([[lft_col, rgt_col],[lft_col2,rgt_col2],[plt_button]])

l = layout(children=[[grid,pnl_layout]])
curdoc().add_root( l )
1 Answers

Some bits of code are missing in your example, so I hope I understood your problem correctly :). As far as I can tell, you would like to change the options in the "Effective Diameter" field when the user changes the selection in the "Cloud Phase" field. I think to achieve what you would like to, you could just replace the following line inside the update_de_list() callback:

de = [np.str(x) for x in (21.86, 46.34, 115.32)]

with:

de_select1.options = [np.str(x) for x in (21.86, 46.34, 115.32)]
de_select2.options = [np.str(x) for x in (21.86, 46.34, 115.32)]
Related