Pertanyaan Beberapa pertanyaan dengan Bokeh Berorientasi Objek


CATATAN: Pertanyaan ini menyangkut server Bokeh "generasi pertama", yang telah dihentikan dan dihapus selama beberapa tahun. Tidak ada dalam pertanyaan ini atau jawabannya relevan dengan versi Bokeh> = 0,11




Saya mencoba untuk mengerti Bokeh untuk aplikasi interaktif yang saya buat. Saya sedang melihat Contoh Bokeh, dan saya melihat bahwa sebagian besar contoh ditulis semuanya dalam ruang nama global, tetapi yang ada di subdirektori "aplikasi" ditulis dengan gaya yang bagus, berorientasi objek, di mana kelas utama ada di kelas Properti seperti HBox.

Ini akan menjadi pertanyaan bodoh karena saya tidak berpikir cara pemrograman Bokeh ini terdokumentasi dengan baik. Hal pertama yang saya temui adalah plot itu tidak menggambar kecuali saya termasuk extra_generated_classes.

  1. Apa yang dilakukan dengan extra_generated_classes?

    Kedua, sepertinya lingkaran acara setup_events dipanggil saat startup sebelumnya create dan kemudian setiap kali plot memicu suatu peristiwa.

  2. Mengapa setup_events perlu mendaftarkan callback setiap kali suatu peristiwa dipicu? Dan mengapa tidak menunggu pembuatan selesai sebelum mencoba mendaftarkannya pertama kali?

    Hal terakhir yang saya tidak yakin adalah bagaimana memaksa redraw dari Glyph di sini. Demo slider bekerja untuk saya, dan saya mencoba melakukan hal yang sama, kecuali dengan scatterplot bukan garis.

    Saya menetapkan jejak pdb di bagian paling akhir saya update_data, dan saya bisa menjamin itu self.source cocok self.plot.renderers[-1].data_source dan keduanya sudah di-tweak dari awal. Namun, self.plot itu sendiri tidak berubah.

  3. Apa pendekatan object-oriented yang setara dengan memanggil store_objects untuk memperbarui plot?

    Saya terutama bingung dengan yang ketiga ini, karena tidak terlihat seperti contoh sliders_app membutuhkan hal seperti itu. Untuk klarifikasi, saya mencoba untuk membuat sejumlah variabel widget / slider, jadi ini adalah apa kode saya terlihat seperti:

atribut kelas:

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)

menginisialisasi metode

@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

perbaharui 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()

Perhatikan bahwa saya yakin bahwa pengendali event mendapat pengaturan dan dipicu dengan benar. Saya hanya tidak tahu bagaimana membuat data sumber berubah mencerminkan di scatterplot.


32
2017-10-03 08:57


asal


Jawaban:


Saya mencari jawaban yang sama (kurangnya dokumentasi menyulitkan).

Sebagai jawaban, untuk pertanyaan # 1, apa kegunaan "extra_generated_classes":

tl; dr extra_generated_classes mendefinisikan nama modul, nama kelas, dan nama induk yang digunakan dalam pembuatan template kode js / html, dan memperluas kelas induk yang diteruskan ke kelas aplikasi (biasanya HBox atau VBox dalam contoh).

Jawaban yang lebih panjang. Lihatlah kode sumber di bokeh / server / utils / plugins.py, ini adalah kode yang dijalankan pada kode yang diteruskan ke bokeh-server menggunakan argumen baris perintah -script. Di akhir plugins.py, Anda dapat melihat bahwa extra_generated_classes diteruskan ke metode flask render_template, yang membuat a Jinja2template. Melihat ke dalam templat, oneobj.html, extra_generated_classes adalah larik array dari tiga hal: modulename, classname, dan parentname, yang diteruskan ke 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 adalah kode Python di bokeh / server / views / plugins.py, dan hanya memanggil render_template untuk aplikasi template.js, yang dapat Anda temukan di bokeh / server / templates. Template ini mengambil nama modul, nama kelas, dan nama pengguna, dan pada dasarnya membuat kode js yang memperluas nama induk (misalnya, HBox atau VBox) ke nama kelas (aplikasi Anda).


3
2017-08-04 20:56