Bokehコンテンツを埋め込む

Bokehは,HTML文書に描画やデータを埋め込む様々な方法を提供している.まず、独立文書とアプリケーションとの違いを注意してみましょう。

独立文書.

これらはBokehサーバにサポートされていないBokeh文書である.彼らは多くのツールやインタラクションを持っているかもしれません CustomJS コールバック)であるが,これらはHTML,JavaScript,CSSからなる.これらは、1つの大きな文書または1組の個別テンプレート化されたサブコンポーネントとして他のHTMLページに埋め込むことができる。

Bokehアプリケーション

これらはBokehサーバによってサポートされているBokeh文書である.独立文書のすべての機能に加えて、Bokehサーバで実行される真のPythonコールバックにイベントおよびツールを接続することができます。見 Bokehサーバの実行 Bokehアプリケーションの作成と実行に関するより多くの情報。

独立文書.

本節では,Bokeh独立文書(すなわち,Bokeh独立文書について述べる not Bokehサーバへのリンク)は,様々な方法で配布や埋め込みが可能である.

HTML文書.

Bokehはご利用いただけます file_html() 機能します。この関数は、それ自身の汎用テンプレートまたは提供されたテンプレートからHTMLを発行することができます。これらのファイルは、インライン描画されたデータを含み、対話型ツール(平行移動、ズームなど)を提供しながら、完全に転送可能である。あなたの陰謀のために。次は一例です

from bokeh.plotting import figure
from bokeh.resources import CDN
from bokeh.embed import file_html

plot = figure()
plot.circle([1,2], [3,4])

html = file_html(plot, CDN, "my plot")

標準的なPythonファイル操作を使用して、返されたHTMLテキストをファイルに保存することができます。また、自分のテンプレートを提供し、カスタムテンプレート変数または他のテンプレート変数を入力することができます。ご参照ください file_html() 文書はより詳細な情報を知るために使用される。

これはかなり低レベルで明示的なHTML文書生成方式であり,Webアプリケーション(たとえばFlaskアプリケーション)でそのファイルを使用することが有用である可能性がある.スクリプトやJupyterノートで|boke.ploting|インタフェースを使用する場合,ユーザは通常その関数を呼び出す. output_file() 結合する. show() あるいは…。 save() 代わりに。

JSONプロジェクト

Bokehはまた、指定されたdivにおいて独立したBokehコンテンツを提示するためにそれを容易に使用することができるJSONブロックを提供することができる。♪the json_item() 関数は、Bokehモデル(例えば、描画)を受け取り、レンダリングするdivを識別するオブジェクトID:を受け入れることもできる。

p = figure()
p.circle(x, y)

item_text = json.dumps(json_item(p, "myplot"))

この出力は Bokeh.embed.embed_item ウェブ上の機能:

item = JSON.parse(item_text);
Bokeh.embed.embed_item(item);

この場合、Bokeh描画はid付きdivに自分を提示します。 “私のエピソード” それがそうです。

呼び出し時にオブジェクトidを省略することもできる. json_item()

p = figure()
p.circle(x, y)

item_text = json.dumps(json_item(p)) # no target_id given

そして、JavaScript側でターゲットIDを制御することができます:

item = JSON.parse(item_text);
Bokeh.embed.embed_item(item, "myplot");

より完全な例として、Flaskサーバは、 /plot 端点:

@app.route('/plot')
def plot():
    p = make_plot('petal_width', 'petal_length')
    return json.dumps(json_item(p, "myplot"))

ページ上の対応するコードは以下のようになる場合があります。

<script>
fetch('/plot')
    .then(function(response) { return response.json() })
    .then(function(item) { return Bokeh.embed.embed_item(item) })
</script>

現代文法を使って

<script>
const response = await fetch('/plot')
const item = await response.json()
Bokeh.embed.embed_item(item)
</script>

完全な例は以下の位置で見つけることができる examples/embed/json_item.py それがそうです。

部品.部品

Bokehは、使用するために、独立文書の各コンポーネントを返すことを要求することもできる components() 機能します。この関数は1つに戻ります <script> あなたの図面データと付属のものが含まれています。 <div> 印刷ビューがロードされたマークを印刷します。これらのタグは、お好みでHTML文書で使用することができます:

from bokeh.plotting import figure
from bokeh.embed import components

plot = figure()
plot.circle([1,2], [3,4])

script, div = components(plot)

帰還者. <script> 似たように見えるでしょう

<script type="text/javascript">
    (function() {
  var fn = function() {
    Bokeh.safely(function() {
      var docs_json = { DOCUMENT DATA HERE };
      var render_items = [{
        "docid":"6833819f-9b5b-4904-821e-3f5eec77de9b",
        "elementid":"9574d123-9332-4b5f-96cc-6323bef37f40",
        "modelid":"7b328b27-9b14-4f7b-a5d8-0138bc7b0f59"
      }];

      Bokeh.embed.embed_items(docs_json, render_items);
    });
  };
  if (document.readyState != "loading") fn();
  else document.addEventListener("DOMContentLoaded", fn);
})();

</script>

Jupyterノートパソコンでは、ご利用いただけませんのでご注意ください components() そして show() 同じノートのセルにあります。

すべてのデータや描画や小さな部品オブジェクトは docs_json 変数(簡潔のため,ここでは内容を省略する).生まれたのは <div> 似たように見えるでしょう

<div class="bk-root" id="9574d123-9332-4b5f-96cc-6323bef37f40"></div>

この2つの要素はHTMLテキストに挿入またはテンプレート化することができ,スクリプトは実行時にdivを描画で置き換えることができる.

これらのコンポーネントを使用して、BokehJSは、例えば、文書テキストに内部接続されているか、またはCDNからロードされていると仮定する。CDNからBokehJSをロードするには、HTMLテキストまたはテンプレートに以下の行を追加し、対応するバージョンを置き換えてください x.y.z

<script src="https://cdn.bokeh.org/bokeh/release/bokeh-x.y.z.min.js"
        crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-x.y.z.min.js"
        crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-x.y.z.min.js"
        crossorigin="anonymous"></script>

♪the "-widgets" あなたの文書にBokeh小さな部品が含まれている場合にのみ、ファイルが必要です。同様に "-tables" 文書にBokehデータテーブルを使用する場合にのみ,ファイルが必要となる.

例えばバージョンを使うには 1.4.0 ウィジェットおよびフォームのサポートを含む:

<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"
        crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.js"
        crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.4.0.min.js"
        crossorigin="anonymous"></script>

注釈

あなたは解決の言葉を提供しなければならない </script> ラベル。これはすべてのブラウザに必要であり、それがなければ、ページは通常表示されません。あなたはまだずっと crossorigin="anonymous" 属性はスクリプトタグに追加する.

もしあなたが含めたいなら Subresource Integrity 明示的なスクリプトタグをハッシュする方法は integrity 属性は,呼び出すことで get_sri_hashes_for_version() 例:

In [1]: import bokeh.resources

In [2]: bokeh.resources.get_sri_hashes_for_version("2.0.0")
Out[2]:
{'bokeh-2.0.0.js': 'TQAjsk2/lDn1NHjYoe8HIascd3/Cw4EWdk6GNtYXVVyAiUkbEZiuP7fEgbSwM37Y',

...

'bokeh-widgets-2.0.0.min.js': '2ltAd1cQhavmLeBEZXGgnna8fjbw+FjvDq9m2dig4+8KVS8JcYFUQaALvLT//qHE'}

これらは赤裸々なハッシュです接頭辞を持たなければなりません sha384- 使っています例:

<script src="https://cdn.bokeh.org/bokeh/release/bokeh-2.0.0.min.js"
        integrity="sha384-5Y+xuMRAbgBj/2WKUiL8yzV4fBFic1HJPo2hT3pq2IsEzbsJjj8kT2i0b1lZ7C2N"
        crossorigin="anonymous"></script>

SRIハッシュは、完全なバージョンのためにのみ生成される(すなわち、開発バージョンまたは候補バージョンのために生成されない)。

単一のBokehモデル(例えば、ブロック)を除いて、 components() 関数はまた、モデルのリストまたはタプル、または鍵およびモデルの辞書を受け取る。それぞれは、スクリプトおよびdivの対応するデータ構造を含む1つのタプルを返す。

次に、異なる入力タイプと出力との関係について説明する。

components(plot)
#=> (script, plot_div)

components((plot_1, plot_2))
#=> (script, (plot_1_div, plot_2_div))

components({"Plot 1": plot_1, "Plot 2": plot_2})
#=> (script, {"Plot 1": plot_1_div, "Plot 2": plot_2_div})

以下は、マルチプリント生成器をどのように使用するかの例である。

# scatter.py

from bokeh.plotting import figure
from bokeh.models import Range1d
from bokeh.embed import components

# create some data
x1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y1 = [0, 8, 2, 4, 6, 9, 5, 6, 25, 28, 4, 7]
x2 = [2, 5, 7, 15, 18, 19, 25, 28, 9, 10, 4]
y2 = [2, 4, 6, 9, 15, 18, 0, 8, 2, 25, 28]
x3 = [0, 1, 0, 8, 2, 4, 6, 9, 7, 8, 9]
y3 = [0, 8, 4, 6, 9, 15, 18, 19, 19, 25, 28]

# select the tools we want
TOOLS="pan,wheel_zoom,box_zoom,reset,save"

# the red and blue graphs will share this data range
xr1 = Range1d(start=0, end=30)
yr1 = Range1d(start=0, end=30)

# only the green will use this data range
xr2 = Range1d(start=0, end=30)
yr2 = Range1d(start=0, end=30)

# build our figures
p1 = figure(x_range=xr1, y_range=yr1, tools=TOOLS, plot_width=300, plot_height=300)
p1.scatter(x1, y1, size=12, color="red", alpha=0.5)

p2 = figure(x_range=xr1, y_range=yr1, tools=TOOLS, plot_width=300, plot_height=300)
p2.scatter(x2, y2, size=12, color="blue", alpha=0.5)

p3 = figure(x_range=xr2, y_range=yr2, tools=TOOLS, plot_width=300, plot_height=300)
p3.scatter(x3, y3, size=12, color="green", alpha=0.5)

# plots can be a single Bokeh Model, a list/tuple, or even a dictionary
plots = {'Red': p1, 'Blue': p2, 'Green': p3}

script, div = components(plots)
print(script)
print(div)

運行 python scatter.py 印刷します

<script type="text/javascript">
    var docs_json = { DOCUMENT DATA HERE }
    var render_items = [{
      "docid":"33961aa6-fd96-4055-886f-b2afec7ff193",
      "elementid":"e89297cf-a2dc-4edd-8993-e16f0ca6af04",
      "modelid":"4eff3fdb-80f4-4b4c-a592-f99911e14398"
    },{
      "docid":"33961aa6-fd96-4055-886f-b2afec7ff193",
      "elementid":"eeb9a417-02a1-47e3-ab82-221abe8a1644",
      "modelid":"0e5ccbaf-62af-42cc-98de-7c597d83747a"
    },{
      "docid":"33961aa6-fd96-4055-886f-b2afec7ff193",
      "elementid":"c311f123-368f-43ba-88b6-4e3ecd9aed94",
      "modelid":"57f18497-9598-4c70-a251-6072baf223ff"
    }];

    Bokeh.embed.embed_items(docs_json, render_items);
</script>

    {
        'Green': '\n<div class="bk-root" id="e89297cf-a2dc-4edd-8993-e16f0ca6af04"></div>',
        'Blue': '\n<div class="bk-root" id="eeb9a417-02a1-47e3-ab82-221abe8a1644"></div>',
        'Red': '\n<div class="bk-root" id="c311f123-368f-43ba-88b6-4e3ecd9aed94"></div>'
    }

スクリプトとdiv要素をこのテンプレートに挿入します:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Bokeh Scatter Plots</title>

        <script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.1.0.min.js"></script>

        <!-- COPY/PASTE SCRIPT HERE -->

    </head>
    <body>
        <!-- INSERT DIVS HERE -->
    </body>
</html>

注意してください。上には含まれていません。 "-widgets" JSとCSSファイルは,文書はBokeh小部品を使用しないためである.必要に応じてCDNリソースをHTTPS URLの形で提供することも可能である.

以下のコマンドを実行することで例を見ることができます。

python /bokeh/examples/embed/embed_multiple.py

スクリプトを自動ロードする

独立文書を埋め込む最後の方法は autoload_static() 機能します。この関数は <script> タグは,タグがどこにあるかにかかわらず,自身をBokehグラフに置き換える.このスクリプトはまた,BokehJSをチェックし,必要に応じてロードする.この関数を用いて,文書中にこのスクリプトタグを単独で置くことで描画を埋め込むことができる.

この関数は、表示するBokehモデル(例えば、グラフ)を使用します。 Resources オブジェクトと,その中からスクリプトをロードするパス.それで? autoload_static() 独立したものに戻ります <script> タグとJavaScriptコードですJavaScriptコードは提供されたパスに保存されなければなりません。♪the <script> タグがページに含まれている場合には、保存されているJavaScriptをロードして実行し、ブラウザで描画を実現します。

次はどのようにご利用いただけますか autoload_static() 次は簡単な話です

from bokeh.resources import CDN
from bokeh.plotting import figure
from bokeh.embed import autoload_static

plot = figure()
plot.circle([1,2], [3,4])

js, tag = autoload_static(plot, CDN, "some/path")

生まれたのは <script> ラベルは以下のとおりである.

<script
    src="some/path"
    id="c5339dfd-a354-4e09-bba4-466f58a574f1"
    async="true"
    data-bokeh-modelid="7b226555-8e16-4c29-ba2a-df2d308588dc"
    data-bokeh-loglevel="info"
></script>

スクリプトタグは、描画をロードしたいHTMLページに含まれなければなりません。

個々のJavaScriptコードは、サーバ上の以下の位置でアクセス可能なファイルに保存されるべきである。 "some/path" 印刷が埋め込まれた文書から.

注釈

♪the <script> マークは1つ <div> 位置に着いて、そこに置かなければなりません <head> それがそうです。

Bokehアプリケーション

本節では,Bokehサーバアプリケーション全体をどのように埋め込むかについて述べる.Bokehアプリケーションは、ページロードのたびに新しいセッションおよび文書を作成して表示するか、または特定の既存のセッションをロードするように埋め込むことができる。

アプリケーション文書

アプリケーションがBokehサーバ上で実行され、あるURL上で利用可能な場合、通常、ページをいつアップロードしても、新しいセッションを作成してユーザに提示するために、アプリケーション全体をページに埋め込むことが望ましい。これは使用することで server_document() 関数であって、関数は、BokehサーバアプリケーションへのURLを受け取り、スクリプト実行のいつでもサーバからの新しいセッションを埋め込むスクリプトを返す。

以下は、以下のコマンドを用いて切り出した例である server_document()

from bokeh.embed import server_document
script = server_document("https://demo.bokeh.org/sliders")

返されたスクリプトタグは以下のとおりである.

<script
    src="https://demo.bokeh.org/sliders/autoload.js?bokeh-autoload-element=1000&bokeh-app-path=/sliders&bokeh-absolute-url=https://demo.bokeh.org/sliders"
    id="1000">
</script>

これは,HTMLページにテンプレート化し,その際にBokehアプリケーションを含むことができる.

アプリケーションセッション

時々、私たちは新しいセッションをロードするのではなく、新しいセッションをロードしたいかもしれません。 専一. 会議です。例えば、認証されたユーザのためのページを提示するFlaskアプリケーションは、特定のユーザのためのいくつかのカスタマイズされた新しいセッションを引き込むことを望むことができ、次いで、特定のBokehサーバセッションにサービスを提供することができる。これは使用することで server_session() 埋め込む特定のモデルを受け入れる関数(または None セッション文書全体)、セッションID、およびBokehアプリケーションのためのURL。

次はどうやって使うかです server_session() 首の瓶を持っています

from flask import Flask, render_template

from bokeh.client import pull_session
from bokeh.embed import server_session

app = Flask(__name__)

@app.route('/', methods=['GET'])
def bkapp_page():

    # pull a new session from a running Bokeh server
    with pull_session(url="http://localhost:5006/sliders") as session:

        # update or customize that session
        session.document.roots[0].children[1].title.text = "Special Sliders For A Specific User!"

        # generate a script to load the customized session
        script = server_session(session_id=session.id, url='http://localhost:5006/sliders')

        # use the script in the rendered page
        return render_template("embed.html", script=script, template="Flask")

if __name__ == '__main__':
    app.run(port=8080)

標準テンプレート.

Bokehはまた、“base”テンプレートを拡張することで、異なる文書ルートを柔軟に迅速に埋め込むことができる標準的なJJJAテンプレートを提供する。これは、Boehアプリケーションを非Boehレイアウト(例えば、Bootstrapなど)に埋め込む様々なコンポーネントに特に有用である。

以下に最小の例を示す.アプリケーションが2つのルートを作成し、Names属性を設定したと仮定します:

p1 = figure(..., name="scatter")

p2 = figure(..., name="line")

curdoc().add_root(p1)
curdoc().add_root(p2)

そして,テンプレートにこれらの根を名前順に引用し,それを渡すことができる. embed マクロはそれらを必要な位置に置きます

{% extends base %}

<!-- goes in head -->
{% block preamble %}
<link href="app/static/css/custom.min.css" rel="stylesheet">
{% endblock %}

<!-- goes in body -->
{% block contents %}
<div> {{ embed(roots.scatter) }} </div>
<div> {{ embed(roots.line) }} </div>
{% endblock %}

完全なテンプレート(すべてのカバー可能な部分を含む)は以下のようになる:

<!DOCTYPE html>
<html lang="en">
{% block head %}
<head>
    {% block inner_head %}
    <meta charset="utf-8">
    <title>{% block title %}{{ title | e if title else "Bokeh Plot" }}{% endblock %}</title>
    {% block preamble %}{% endblock %}
    {% block resources %}
        {% block css_resources %}
        {{ bokeh_css | indent(8) if bokeh_css }}
        {% endblock %}
        {% block js_resources %}
        {{ bokeh_js | indent(8) if bokeh_js }}
        {% endblock %}
    {% endblock %}
    {% block postamble %}{% endblock %}
    {% endblock %}
</head>
{% endblock %}
{% block body %}
<body>
    {% block inner_body %}
    {% block contents %}
        {% for doc in docs %}
        {{ embed(doc) if doc.elementid }}
        {% for root in doc.roots %}
            {{ embed(root) | indent(10) }}
        {% endfor %}
        {% endfor %}
    {% endblock %}
    {{ plot_script | indent(8) }}
    {% endblock %}
</body>
{% endblock %}
</html>