2014-10-03 18 views
32

NOTA: questa domanda riguarda il server Bokeh di "prima generazione", che è stato deprecato e rimosso per diversi anni. Nessuna disposizione della presente domanda o sue risposte è rilevante per qualsiasi versione di Bokeh> = 0,11Domande multiple con Bokeh orientato agli oggetti




sto cercando di capire Bokeh per un app interattiva che sto costruendo. Sto guardando il Bokeh examples, e vedo che la maggior parte degli esempi sono scritti tutti nello spazio dei nomi globale, ma quelli nella sottodirectory "app" sono scritti in uno stile piacevole, orientato agli oggetti, in cui la classe principale è rimossa da una classe di proprietà come HBox.

Questo sarà un miscuglio di domande perché non penso che questo modo di programmare Bokeh sia stato ben documentato. La prima cosa che ho riscontrato è che la trama non è stata disegnata a meno che non includessi lo extra_generated_classes.

  1. cosa fa extra_generated_classes fanno?

    In secondo luogo, sembra che il ciclo degli eventi setup_events viene chiamato all'avvio prima create e successivamente ogni volta che la trama attiva un evento.

  2. Perché setup_events deve registrare i callback ogni volta che viene attivato un evento? E perché non aspetta che la creazione finisca prima di tentare di registrarli la prima volta?

    L'ultima cosa di cui non sono sicuro è come forzare un ridisegno di un glifo qui. La demo del dispositivo di scorrimento funziona per me, e sto cercando di fare praticamente la stessa cosa, tranne che con uno scatterplot invece di una linea.

    ho impostato una traccia PPB alla fine del mio update_data, e posso garantire che self.source corrisponde self.plot.renderers[-1].data_source e che entrambi sono stati ottimizzati fin dall'inizio. Tuttavia, lo stesso self.plot non cambia.

  3. Qual è l'equivalente del approccio orientato agli oggetti a chiamare store_objects per aggiornare la trama?

    Sono particolarmente confuso da questo terzo, perché non sembra che l'esempio sliders_app abbia bisogno di qualcosa del genere.Per chiarimenti, sto cercando di fare un numero variabile di widgets/cursori, quindi questo è ciò che il mio codice è simile:

attributi di classe:

extra_generated_classes = [['ScatterBias', 'ScatterBias', 'HBox']] 
maxval = 100.0 

inputs = Instance(bkw.VBoxForm) 
outputs = Instance(bkw.VBoxForm) 
plots = Dict(String, Instance(Plot)) 
source = Instance(ColumnDataSource) 


cols = Dict(String, String) 
widgets = Dict(String, Instance(bkw.Slider)) 
# unmodified source 
df0 = Instance(ColumnDataSource) 

metodo initialize

@classmethod 
def create(cls): 
    obj = cls() 

    ############################## 
    ## load DataFrame 
    ############################## 
    df = pd.read_csv('data/crime2013_tagged_clean.csv', index_col='full_name') 
    obj.cols = {'x': 'Robbery', 
      'y': 'Violent crime total', 
      'pop': 'Population' 
      } 

    cols = obj.cols 

    # only keep interested values 
    df2= df.ix[:, cols.values()] 

    # drop empty rows 
    df2.dropna(axis=0, inplace=True) 

    df0 = df2.copy() 
    df0.reset_index(inplace=True) 
    # keep copy of original data 
    obj.source = ColumnDataSource(df2) 
    obj.df0 = ColumnDataSource(df0) 

    ############################## 
    ## draw scatterplot 
    ############################## 

    obj.plots = { 
      'robbery': scatter(x=cols['x'], 
       y=cols['y'], 
       source=obj.source, 
       x_axis_label=cols['x'], 
       y_axis_label=cols['y']), 
      'pop': scatter(x=cols['pop'], 
       y=cols['y'], 
       source=obj.source, 
       x_axis_label=cols['pop'], 
       y_axis_label=cols['y'], 
       title='%s by %s, Adjusted by by %s'%(cols['y'], 
        cols['pop'], cols['pop'])), 
     } 

    obj.update_data() 
    ############################## 
    ## draw inputs 
    ############################## 
    # bokeh.plotting.scatter 
    ## TODO: refactor so that any number of control variables are created 
    # automatically. This involves subsuming c['pop'] into c['ctrls'], which 
    # would be a dictionary mapping column names to their widget titles 
    pop_slider = obj.make_widget(bkw.Slider, dict(
      start=-obj.maxval, 
      end=obj.maxval, 
      value=0, 
      step=1, 
      title='Population'), 
     cols['pop']) 

    ############################## 
    ## make layout 
    ############################## 
    obj.inputs = bkw.VBoxForm(
      children=[pop_slider] 
      ) 

    obj.outputs = bkw.VBoxForm(
      children=[obj.plots['robbery']] 
     ) 

    obj.children.append(obj.inputs) 
    obj.children.append(obj.outputs) 

    return obj 

update_data

def update_data(self): 
    """Update y by the amount designated by each slider""" 
    logging.debug('update_data') 
    c = self.cols 
    ## TODO:: make this check for bad input; especially with text boxes 
    betas = { 
      varname: getattr(widget, 'value')/self.maxval 
      for varname, widget in self.widgets.iteritems() 
      } 

    df0 = pd.DataFrame(self.df0.data) 
    adj_y = [] 
    for ix, row in df0.iterrows(): 
     ## perform calculations and generate new y's 
     adj_y.append(self.debias(row)) 

    self.source.data[c['y']] = adj_y 
    assert len(adj_y) == len(self.source.data[c['x']]) 
    logging.debug('self.source["y"] now contains debiased data') 

    import pdb; pdb.set_trace() 

Nota che sono sicuro che il gestore eventi viene configurato e attivato correttamente. Semplicemente non so come far riflettere i dati sorgente modificati nel grafico a dispersione.

+0

Hai trovato una soluzione a questo problema, in particolare per il re-rendering di dispersione? Sto indagando su Bokeh per qualcosa di simile. –

+10

Prova a dividere le tue domande in blocchi più piccoli se vuoi delle risposte. – sorin

risposta

3

Sto cercando le stesse risposte (la mancanza di documentazione lo rende difficile).

In risposta, alla domanda 1 #, qual è l'utilità di "extra_generated_classes":

tl; dr extra_generated_classes definisce un modulename, classname, e ParentName utilizzato in modello di generazione di codice js/html, e si estende la classe genitore passò nella classe dell'app (solitamente HBox o VBox negli esempi).

Risposta più lunga. Guarda il codice sorgente in bokeh/server/utils/plugins.py, questo è il codice che viene eseguito sul codice passato a bokeh-server usando l'argomento della riga di comando --script. Alla fine di plugins.py, puoi vedere che extra_generated_classes è passato al metodo pallone render_template, che esegue il rendering di un modello Jinja2. Guardando dentro il modello, oneobj.html, extra_generated_classes è un array di array di tre cose: modulename, nomeclasse e ParentName, che vengono passati in bokeh.server.generatejs:

{% block extra_scripts %} 
    {% for modulename, classname, parentname in extra_generated_classes %} 
    <script 
    src="{{ url_for('bokeh.server.generatejs', modulename=modulename, classname=classname, parentname=parentname) }}" 
    ></script> 
    {% endfor %} 
{% endblock %} 

bokeh.server.generatejs è un Codice Python in bokeh/server/views/plugins.py, e chiama solo render_template per un template app.js, che puoi trovare in bokeh/server/templates. Questo modello prende il modulename, classname e parentname e fondamentalmente crea il codice js che estende il nome genitore (ad esempio HBox o VBox) al nome della classe (la tua app).

Problemi correlati