Livebook は Elixir版 Jupyter Notebook と言われているものです。私も Python や Julia で Jupyter Notebook を少しだけ使ったことがあり、ちょっとした利用には大変便利だと感じていたので、Livebook も試してみました。
すこし驚いたのが、Livebook は Phoenix LiveView のアプリケーションだということです。とても安定して動いているし、機能も結構豊富だということです。特にVegaLite や Kino を使って高度なグラフを描くことができるのは大変魅力的です。
関連記事
VegaLite で埼玉県を切る( Elixir, Livebook) - Qiita
Vega-Lite の View Composition (Elixir, Livebook) - Qiita
VegaLite の基礎 (Elixir, Livebook) -Qiita
Livebook 事始め (Elixir) - Qiita
この記事は 「東京電力電力供給状況監視 - Livebook」 というタイトルにすべきものでしたが、記事の趣旨が Livebook の使用感にあるため表記のタイトルとしました。
東京電力電力供給状況監視 - Phoenix LiveView
1. VegaLite と Kino について
Livebook
Livebook は Elixir版 Jupyter Notebook です
docker で動かす
docker run -p 8080:8080 -p 8081:8081 --pull always livebook/livebook
Livebook のインストール
git clone https://github.com/livebook-dev/livebook.git
cd livebook
mix deps.get --only prod
Windows コマンドプロンプトでの起動
set MIX_ENV=prod
mix phx.server
起動エラー時に試してみること
iex --sname foo
VegaLite
VegaLite は Vega-Lite の Elixir bindings です。
Vega-Lite is ハイレベルな、会話的グラフィックのための文法です。(D3.jsは低レベル)。それは宣言的な JSON 文法を使います。VegaLite でも JSON 文法を使うことができるようですが、主に Elixir の文法が使われます。
Kino
Kino は Livebook で使われるライブラリで、Elixir コードを使って直接リッチでインタラクティブな描画を可能とするものです。
Kino は単独でも使われますが、Kino.VegaLite という形で VegaLite とともに使われることが一般的です。
しかし Kino v0.5.2 までは Kino.VegaLite がドキュメントにあるのですが、Kino v0.6.0 以降は消えています。代わりに以下の別パッケージを使うみたいです。(名前にドットが入っていないだけなので勘違いしそうですが。)関数の説明などは Kino v0.5.2 の方を参照した方が良いです。
2. Livebook のコード
必要なパッケージをインストールします。
Mix.install([
{:vega_lite, "~> 0.1.6"},
{:kino_vega_lite, "~> 0.1.4"},
{:httpoison, "~> 1.8"}
])
alias VegaLite, as: Vl
VegaLite と Kino でグラフを描きます。グラフは5分おき(300000 ms)に自動更新されます。
chart =
Vl.new(width: 600, height: 300)
|> Vl.mark(:line)
|> Vl.encode_field(:x, "x", type: :quantitative )
|> Vl.encode_field(:y, "y", type: :quantitative, scale: [domain: [3100,3400]] )
|> Kino.VegaLite.new()
|> Kino.render()
Kino.VegaLite.periodically(chart, 300000, 0, fn i ->
denki =
case HTTPoison.get("http://tepco-usage-api.appspot.com/quick.txt") do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} -> body
{:ok, %HTTPoison.Response{status_code: 404}} -> "0,0,0"
{:error, %HTTPoison.Error{reason: _reason}} -> "0,0,0"
end
[_, y, _] = String.split(denki, ",")
point = %{x: i, y: String.to_integer(y)}
Kino.VegaLite.push(chart, point)
{:cont, i + 1}
end)
コードは以上なのですが、驚くほど短いです
2. 動作画像
コードとグラフが同時にキャプチャーできるなんて、Livebook っぽくてかっこいいですね。
3. Kino や VegaLite 関数の説明
new(opts \\ [])
VegaLite struct でラッピングされた新しい specification を返します。
Kino.VegaLite.new(vl)
引数の VegaLite 定義で widget process をスタートします。
Kino.render(term)
引数の term を render します。
encode_field(vl, channel, field, opts \\ [])
Adds field encoding を specification に追加します。
|> Vl.encode_field(:y, "y", type: :quantitative, scale: [domain: [3100,3400]] )
ここでは opts として type: オプションと scale: オプションを指定しています。
Kino.VegaLite.periodically(widget, interval_ms, acc, fun)
KinoVegaLite のドキュメントには明記されてませんが、Kino.VegaLite v0.5.2 のドキュメントには以下の関数があり、そのまま KinoVegaLite でも使えるみたいです。
- widget process を定期的に走らせるための callback を登録する関数
- callback は **interval_ms ** ミリ秒ごとに走る
- そして accumulated value を受け取る
-
callback 以下の2つのうちどれかをリターンしなければならない
* {:cont, acc} - 新しい accumulated value で callback を続ける
* :halt - もはや callback のスケジュールを停止する
今回は以上です。
コード自体は、本当に驚くほど短くて、素晴らしいプラットフォームだと感じました。しかし VegaLite の機能が豊富すぎるし、独特なので、少なからぬ試行錯誤を要しました。ドキュメントを読みこなす慣れが必要です。