Flaskを使ってみる

bokehを使ったグラフ表示


最近、bokehというライブラリの存在を知りました。
matplotlibやseabornはグラフイメージを作成しますが、bokehではグラフ表示用のJavaスクリプトを作成します。

Flaskと組み合わせることで、グラフ表示用のJavaスクリプトを含んでいるHTMLファイルを作成する事ができます。
グラフ表示はJavaスクリプト(クライアント側)で行われ、マウススクロールによるズーミングや移動を行うことができます。
インストールは以下の通りです。
$ sudo apt update

$ sudo apt install python-dev python-setuptools libjpeg-dev zlib1g-dev libfreetype6-dev

$ pip install bokeh



pythonコードは以下の通りです。
matplotlibやseabornとよく似ています。
#!/usr/bin/python
#-*- encoding: utf-8 -*-
import numpy as np
from bokeh.plotting import figure, output_file, show
from bokeh.embed import components
from bokeh.resources import INLINE
from bokeh.util.string import encode_utf8
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/bokeh')
def bokeh():
   flip=1
   x = np.linspace(0, 14, 100)

   fig = figure(plot_width=600, plot_height=600)
   colors=['blue','orange','green','red','violet','brown']
   for i in range(1, 7):
      #fig.line(x, np.sin(x + i * .5) * (7 - i) * flip, line_color="#a4225f")
      fig.line(x, np.sin(x + i * .5) * (7 - i) * flip, line_color=colors[i-1])

   # grab the static resources
   js_resources = INLINE.render_js()
   css_resources = INLINE.render_css()

   # render template
   script, div = components(fig)
   html = render_template(
       'bokeh.html',
       title='flask + bokeh',
       plot_script=script,
       plot_div=div,
       js_resources=js_resources,
       css_resources=css_resources,
   )
   return encode_utf8(html)

if __name__ == "__main__":
   app.run(host='0.0.0.0', port=8080, debug=True)

テンプレートファイル(bokeh.html)は以下の様になります。
ページのほとんどの要素がFlaskにより埋め込まれます。
画像がキャッシュされないようにしています。
<!doctype html>
<html lang="en">
  <head>
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta charset="utf-8">
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>bokeh with flask</title>
    {{ js_resources|indent(4)|safe }}
    {{ css_resources|indent(4)|safe }}
    {{ plot_script|indent(4)|safe }}
  </head>
  <body>
    <h1>{{ title }}</h1>
    {{ plot_div|indent(4)|safe }}
  </body>
</html>


実行すると以下のグラフを表示します。
グラフ右側のtoolbarでPan、Box Zoom、Wheel Zome、Save、Resetを行うことができます。
これらの動作はHTMLに埋め込まれたJavaスクリプトで実現しています。


こちらはtoolbarでZoomを行った時の表示です。




こ ちらこ ちらにBokehのサンプルコードが公開されていますが、いずれもstylesheetリソースと、
javascriptリソースをテンプレートにハードコードしています。
stylesheetとjavascriptのリソースは、インストールしたbokehのバージョンに依存するので、テンプレートにハードコード すると、
特定のバージョン以外では正 しく動きません。

こちら
にFlaskでbokehを使うサンプルコードが公開されていますが、stylesheetとjavascriptのリソース を、 実行時に取り出して
テンプレートに埋め込んでいるので、どのバージョンをインストールしても正しく動きます。



以下の様にすると複数のグラフを表示することができます。
#!/usr/bin/python
#-*- encoding: utf-8 -*-
from bokeh.plotting import figure, output_file, show
from bokeh.embed import components
from bokeh.resources import INLINE
from bokeh.util.string import encode_utf8
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/bokeh2')
def bokeh2():

   #First Plot
   fig1 = figure(plot_width=600, plot_height=200)
   fig1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)

   #Second Plot
   fig2 = figure(plot_width=600, plot_height=200)
   fig2.square([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="olive", alpha=0.5)

   # grab the static resources
   js_resources = INLINE.render_js()
   css_resources = INLINE.render_css()

   # render template
   script1, div1 = components(fig1)
   script2, div2 = components(fig2)

   html = render_template(
       'multi.html',
       title='flask + bokeh',
       plot_script1=script1,
       plot_div1=div1,
       plot_script2=script2,
       plot_div2=div2,
       js_resources=js_resources,
       css_resources=css_resources,
   )
   return encode_utf8(html)

if __name__ == "__main__":
   app.run(host='0.0.0.0', port=8080, debug=True)

テンプレートファイル(multi.html)では2組のscriptとdivを埋め込んでいます。
<!doctype html>
<html lang="en">
  <head>
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta charset="utf-8">
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>bokeh with flask</title>
    {{ js_resources|indent(4)|safe }}
    {{ css_resources|indent(4)|safe }}
    {{ plot_script1|indent(4)|safe }}
    {{ plot_script2|indent(4)|safe }}
  </head>
  <body>
    <h1>{{ title }}</h1>
    {{ plot_div1|indent(4)|safe }}
    {{ plot_div2|indent(4)|safe }}
  </body>
</html>

グラフ右側のtoolbarはそれぞれのグラフに付くので、それぞれのグラフを独立して操作することができます。


上のグラフと下のグラフで拡大率を変えています。


bokehのサンプル・コードはこ ちらに公開されています。

続く...