2017-11-26 3 views
2

Ich versuche, eine Bokeh-Anwendung zu generieren, die es dem Benutzer ermöglicht, die Glyphen eines Plots zu ändern. Leider ändern sich die Glyphen nach dem Aufruf der Methode on_change() der Dropdown-Schaltfläche nicht, obwohl ich die Achsenbeschriftung auf ähnliche Weise ändern kann. Das Ändern von plot.glyph außerhalb der aufgerufenen Funktion funktioniert jedoch einwandfrei.Ändern Sie interaktiv Glyphen in Bokeh-Plot

from bokeh.layouts import layout 
from bokeh.models import ColumnDataSource 
from bokeh.models.widgets import Dropdown 
from bokeh.plotting import figure 
from bokeh.io import curdoc 
from bokeh.models.markers import Cross, Circle 

source=ColumnDataSource(dict(x=[1,2,3],y=[4,5,6])) 

fig=figure() 
plot=fig.circle(x='x', y='y',source=source) 
fig.xaxis.axis_label='This is a label' 

#this changes the glyphs from circle to cross 
plot.glyph=Cross(x='x', y='y', size=20, line_color='firebrick', 
fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3) 

def update_plot(attr,old,new): 
    if dropdown.value=='cross': 
     #this changes the axis label but not the glyphs 
     fig.xaxis.axis_label='Label changed' 
     plot.glyph=Cross(x='x', y='y', size=20, line_color='firebrick', 
     fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3) 
    elif dropdown.value=='circle': 
     #this also only changes the axis label but not the glyphs 
     fig.xaxis.axis_label='Label changed again' 
     plot.glyph=Circle(x='x', y='y', size=20, line_color='firebrick', 
     fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3) 

menu=[('Circle','circle'),('Cross', 'cross')] 
dropdown=Dropdown(label="Select marker", menu=menu, value='circle') 
dropdown.on_change('value', update_plot) 

lay_out=layout([fig, dropdown]) 

curdoc().add_root(lay_out) 

Antwort

2

Ich bin nicht sicher über die genauen Gründe, warum Ihr Ansatz nicht funktioniert, aber diese funktioniert:

from bokeh.io import curdoc 
from bokeh.layouts import layout 
from bokeh.models import ColumnDataSource 
from bokeh.models.widgets import Dropdown 
from bokeh.plotting import figure 

source = ColumnDataSource(dict(x=[1, 2, 3], y=[4, 5, 6])) 

plot = figure() 

renderers = {rn: getattr(plot, rn)(x='x', y='y', source=source, 
            **extra, visible=False) 
      for rn, extra in [('circle', dict(size=10)), 
           ('line', dict()), 
           ('cross', dict(size=10)), 
           ('triangle', dict(size=15))]} 


def label_fn(item): 
    return 'Select marker ({})'.format(item) 


menu = [('No renderer', None)] 
menu.extend((rn.capitalize(), rn) for rn in renderers) 

dropdown = Dropdown(label=label_fn(None), menu=menu, value=None) 


def update_plot(attr, old, new): 
    dropdown.label = label_fn(new) 
    for renderer_name, renderer in renderers.items(): 
     renderer.visible = (renderer_name == new) 


dropdown.on_change('value', update_plot) 

lay_out = layout([plot, dropdown]) 

curdoc().add_root(lay_out) 

Grundsätzlich erstelle ich alle notwendigen Renderer vorher, und wechseln Sie dann nur visible Flagge von jedem.

Beachten Sie auch die korrekte Terminologie. Was Sie einen Plot nennen, ist eigentlich kein Plot, sondern ein Glyphen-Renderer. Und Handlung und Figur sind im Grunde dasselbe.

+0

Danke! Das macht, was ich vorhatte. Danke auch für die Korrektur meiner Terminologie. –

Verwandte Themen