2016-07-20 16 views
0

Ich versuche einen interaktiven Bokeh-Schieberegler zu verwenden, um den Inhalt eines Diagramms zu ändern, ähnlich dem Beispiel here. Ich habe zwei verschachtelte Listen x und y.Interaktiver Slider mit Bokeh

Ich möchte einfach den Schieberegler den Index der Listen zu plotten ändern. dh wenn der Schieber index = 0, plotten dann x[0] vs y[0], wenn der Schieber Index 1, Grundstück x[1] vs y[1], etc ...

Die Dokumentation Beispiel berechnet die neuen Daten im laufenden Betrieb, die für nicht durchführbar ist die Daten, mit denen ich arbeiten muss.

Wenn ich den Code unten ausführen, zeigt sich nichts in der Handlung ... Ich weiß nicht, Javascript, also ich vermute, das ist, wo ich falsch liege.

Ich führe Python 3.5 und Bokeh 0.12. Dies alles läuft in einem Jupiter-Notizbuch.

import numpy as np 
from bokeh.layouts import row 
from bokeh.models import CustomJS, ColumnDataSource, Slider 
from bokeh.plotting import Figure, show 
from bokeh.io import output_notebook 
from bokeh.resources import INLINE 
output_notebook(INLINE) 

x = [[x*0.05 for x in range(0, 500)], 
    [x*0.05 for x in range(0, 500)]] 

y = [np.sin(x[0]), 
    np.cos(x[1])] 

source = ColumnDataSource(data=dict(x=x, y=y)) 

plot = Figure(plot_width=400, plot_height=400) 
plot.line('x'[0], 'y'[0], source=source, line_width=3, line_alpha=0.6) 

callback = CustomJS(args=dict(source=source), code=""" 
     var data = source.get('data'); 
     var f = cb_obj.get('value'); 
     x = data['x'][f]; 
     y = data['y'][f]; 
     source.trigger('change'); 
    """) 

slider = Slider(start=0, end=1, value=0, step=1, title="index", callback=callback) 
layout = row(plot, slider) 
show(layout) 
+0

Können Sie ein Beispiel Ihrer Daten hinzufügen? –

+0

@ conner.xyz Die Daten stammen von einem Physik-Simulationscode, der zu groß ist, um ihn einzuschließen. Die einfachen x- und y-Arrays im Code haben hier die gleiche Struktur. Jedes verschachtelte Array in x und y entspricht einer anderen Zeit. Die Daten, die ich habe, ändern sich mit der Zeit, also möchte ich in der Lage sein, die Daten innerhalb von x gegen y zu plotten und den Schieberegler zu haben, der den Index steuert, der der Zeit entspricht. Im Wesentlichen möchte ich nur den Index des geschachtelten Arrays ändern und seinen Inhalt grafisch darstellen. Wenn der Slider-Index 0 ist, plotten Sie x [0] gegen y [0] und ändern Sie den Schieberegler auf 1, um x [1] gegen y [1] zu zeichnen. – smillerc

+0

Das Datenattribut 'ColumnDataSource' sollte eDict sein, das String-Spaltennamen 1d-Sequenzen (den Daten für die Zeile) zuordnet. Das heißt, die Übergabe einer verschachtelten Liste ist in diesem Fall nicht sinnvoll. Verschachtelte Listen würden für "mult_line" sinnvoll sein, und dann könnten Sie die Sichtbarkeit jeder Zeile steuern, indem Sie eine Spalte für die Zeilen-Alphas verwenden, die der Slider aktualisiert. – bigreddot

Antwort

3

Statt einen Schieber mit dem Index der Daten zu ändern aufgetragen werden, könnten Sie zwei ColumnDataSource s definieren: source_visible und source_available, wo der erste, der die Daten enthält, die derzeit wird in der Grafik angezeigt und die zweite fungiert als Datenrepository von wo aus wir Daten in CustomJS Rückruf basierend auf Benutzerauswahl auf der Webseite:

import numpy as np 
from bokeh.layouts import row 
from bokeh.models import ColumnDataSource, Slider, CustomJS 
from bokeh.plotting import Figure, show 

# Define data 
x = [x*0.05 for x in range(0, 500)] 
trigonometric_functions = { 
    '0': np.sin(x), 
    '1': np.cos(x), 
    '2': np.tan(x), 
    '3': np.arcsin(x), 
    '4': np.arccos(x), 
    '5': np.arctan(x)} 
initial_function = '0' 

# Wrap the data in two ColumnDataSources 
source_visible = ColumnDataSource(data=dict(
    x=x, y=trigonometric_functions[initial_function])) 
source_available = ColumnDataSource(data=trigonometric_functions) 

# Define plot elements 
plot = Figure(plot_width=400, plot_height=400) 
plot.line('x', 'y', source=source_visible, line_width=3, line_alpha=0.6) 
slider = Slider(title='Trigonometric function', 
       value=int(initial_function), 
       start=np.min([int(i) for i in trigonometric_functions.keys()]), 
       end=np.max([int(i) for i in trigonometric_functions.keys()]), 
       step=1) 

# Define CustomJS callback, which updates the plot based on selected function 
# by updating the source_visible ColumnDataSource. 
slider.callback = CustomJS(
    args=dict(source_visible=source_visible, 
       source_available=source_available), code=""" 
     var selected_function = cb_obj.get('value'); 
     // Get the data from the data sources 
     var data_visible = source_visible.get('data'); 
     var data_available = source_available.get('data'); 
     // Change y-axis data according to the selected value 
     data_visible.y = data_available[selected_function]; 
     // Update the plot 
     source_visible.trigger('change'); 
    """) 

layout = row(plot, slider) 
show(layout) 

Beachten Sie, dass es bei umfangreichen Daten eine Weile dauern kann, bis alle Daten auf einmal an den Browser des Clients gesendet werden.