diagram - Hur får man tillgång till och ändrar redan existerande Bokeh-diagramobjekt direkt från JavaScript?


Jag utvecklar en applikation med Bokeh och Flask. Med hjälp av server-sidans Python-kod producerar den ett diagram inbäddat på en webbsida som innehåller en mängd användaringångselement som syftar till att konfigurera diagrammet.

Jag vet att från och med Bokeh v0.12.x finns det ett API som tillåter att skapa och manipulera diagram direkt från JavaScript.

Delen jag saknar här är, utifrån Bokeh-javascriptobjektet, hur kan jag lista och få åtkomst till de redan instanserade figurobjekten (figure, line, ColumnDataSource, ...)? Med BokehJS API skulle jag då kunna skriva javascriptkod som översätter webbsidans användarhändelser (checkbox, knapptryckning, textinmatning, ...) till åtgärder på diagrammet (ändra linjefärg, dölja linjer, uppdatera datapunktsvärden, ...).

Svar #1

Tänk på detta mycket grundläggande exempel. Jag hoppas att det kan få dig att komma igång.

Två reglage ändrar x- och y-koordinaterna för den mellersta punkten.

from bokeh.plotting import figure
from bokeh.resources import CDN
from bokeh.embed import file_html
from bokeh.models import ColumnDataSource
from jinja2 import Template

source = ColumnDataSource(data=dict(x=[1, 2, 3],
                                    y=[3, 2, 1]),
                          name='my-data-source')

p = figure()
l1 = p.line("x", "y", source=source)

copied and modified default file.html template used for e.g. `file_html`
html_template = Template("""
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>{{ title|e if title else "Bokeh Plot" }}</title>
        {{ bokeh_css }}
        {{ bokeh_js }}
        <style>
          html {
            width: 100%;
            height: 100%;
          }
          body {
            width: 90%;
            height: 100%;
            margin: auto;
          }
        </style>
        <script>
            function change_ds_value(name, idx, value) {
                var ds = Bokeh.documents[0].get_model_by_name('my-data-source');
                ds.data[name][idx] = value;
                ds.change.emit();
            }
        </script>
    </head>
    <body>
        <div>
            {{ plot_div|indent(8) }}
            {{ plot_script|indent(8) }}
            <input type='range' min='-5' max='5'
                   onchange='change_ds_value("x", 1, this.value)'/>
            <input type='range' min='-5' max='5'
                   onchange='change_ds_value("y", 1, this.value)'/>
        </div>
    </body>
</html>
""")

html = file_html(p, CDN, template=html_template)
with open('test.html', 'wt') as f:
    f.write(html)