（続き）Bokeh をつかって行列演算を可視化する(with animation)

# 本日は

先日の　[Bokeh をつかって行列演算を可視化する](https://qiita.com/SatoshiTerasaki/items/96f1d53475cfa3912a50) に引き続いて Bokeh　の練習として回転行列

```math
R(\theta)=\begin{bmatrix}
\cos\theta& -\sin\theta\\
\sin\theta& \cos\theta
\end{bmatrix}
```

のパラメータ　$\theta$　を変えた時に像がどのように変化するのを見ていきましょう．
とはいえ，回転行列というぐらいですからぐるぐる回りますよね．
当たり前かもしれませんが，実際に実装して確かめて見ましょう．

# 実装例

ベタがきで書いています．
本当はクラス化した方が再利用性の観点から良いのですが，それは読者の演習問題とします．よくあるパターンですね．

```py3:anim_rot.py

"""
Reference:
https://github.com/bokeh/bokeh/blob/master/examples/plotting/server/animated.py
"""

import numpy as np
from bokeh.plotting import figure, output_file, show, curdoc
from bokeh.models import ColumnDataSource, Div
from bokeh.layouts import gridplot, column
from bokeh.client import push_session

init_degree = 30


def rot_mat(degree):
    theta = np.deg2rad(degree)
    mat = np.array([[np.cos(theta), -np.sin(theta)],
                    [np.sin(theta), np.cos(theta)]])
    return mat


def main():
    xs = np.linspace(-np.pi, np.pi, 11)
    ys = xs
    Xs, Ys = np.meshgrid(xs, ys)
    Xs, Ys = Xs.flatten(), Ys.flatten()

    mat = rot_mat(init_degree)

    transXs, transYs = mat @ np.array([Xs, Ys])

    output_file("lasso_selector.html")
    TOOLS = "pan,lasso_select,save,reset"
    source = ColumnDataSource(data=dict(Xs=Xs,
                                        Ys=Ys,
                                        transXs=transXs,
                                        transYs=transYs))

    f = figure(tools=TOOLS, title="target",
               x_range=(-np.pi*np.sqrt(2)-1, np.pi*np.sqrt(2)+1),
               y_range=(-np.pi*np.sqrt(2)-1, np.pi*np.sqrt(2)+1))
    f.circle('Xs', 'Ys', source=source)

    transf = figure(x_range=f.x_range,
                    y_range=f.y_range,
                    tools=TOOLS,
                    title="trans")
    transf.circle('transXs', 'transYs', source=source, size=6)

    degree = init_degree
    def update():
        nonlocal degree
        degree += 1
        new_mat = rot_mat(degree)
        transXs, transYs = new_mat @ np.array([Xs, Ys])
        source.data = dict(Xs=Xs,
                           Ys=Ys,
                           transXs=transXs,
                           transYs=transYs)
        transf.title.text = "theta={}".format(degree % 360)

    grid = gridplot([[f, transf]])
    plot = column(Div(text="<h2>Transform before and after</h2>"),
                  grid)
    document = curdoc()
    document.add_root(plot)
    document.add_periodic_callback(update, 60)


main()
```

`add_periodic_callback` に `update` 関数を突っ込むことで周期的に　`update`　を呼び出して $\theta$ を１度ずつずらしたときの像を描画します．

ここで注意なのは

```py3
if __name__ == '__main__':
      main() 
```

のようにせず， そのまま `main()` を書いておくことです．そうしておかないと実行しても空のページが出力されてしまいます． Referenceとして挙げている方法で session を用いるのも可能なのですが，なぜか起動に時間がかかるのでそのようにはしていません．

 https://github.com/bokeh/bokeh/blob/master/examples/plotting/server/animated.py

# 実行例

動かして見ましょう．bokeh パッケージをインストールすると `bokeh` コマンドが使えます．

```shell-session
$ bokeh serve --show anim_rot.py
```

そうするとブラウザが立ち上がり下画面のように動くはずです．
GIFでキャプチャーするツールで動画化しています．

![animrot.gif](https://qiita-image-store.s3.amazonaws.com/0/135978/a0f03bec-5a0e-efa3-0225-b53536dcde32.gif)

想像通り回転している様子がわかります．そして思っていたよりもカクカクせずに動いてくれますね．