JupyterLab上でmatplotlibのアニメーションを出力する

JupyterLabを使っているとmatplotlibで作成したアニメーションをnotebook上で再生できず困っていたのですが、
解決方法が分かったので共有します。

## 環境

```sh
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G65
$ python -V
Python 3.6.8 :: Anaconda, Inc.
$ jupyter lab --version
0.35.3
$ python -c "import matplotlib; print(matplotlib.__version__)"
3.0.0
```


## 解決方法

### 方法1: IPython.display.HTMLを使う

後の方法2よりもこちらのほうが簡単で良いと思います。

以下は確認用のコードです。jupyter labを起動させて下のコードを貼り付けてアニメーションが表示されるか試すことができます。

```python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML

fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')

def init():
    ax.set_xlim(0, 2 * np.pi)
    ax.set_ylim(-1, 1)
    return ln,

def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,

ani = FuncAnimation(fig, update, frames=np.linspace(0, 2 * np.pi, 128),
                    init_func=init, blit=True, interval=50)

HTML(ani.to_jshtml())
# HTML(ani.to_html5_video())  # またはこちら
```

出力結果：

![sin_animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133841/d15ba1da-4bae-3ffa-25b0-216d816be31c.gif)


[to_jshtml()](https://matplotlib.org/api/_as_gen/matplotlib.animation.Animation.html#matplotlib.animation.Animation.to_jshtml)によりアニメーションをHTML表現に変換したものを[HTML()](https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.HTML)で表示させています。ボタンによるインタラクティブな操作ができていい感じです。
[to_html5_video()](https://matplotlib.org/api/_as_gen/matplotlib.animation.Animation.html#matplotlib.animation.Animation.to_html5_video)でHTML5 video tagを作成することもできます。


### 方法2: jupyter-matplotlibを使う

参考までに、別の方法も載せておきます。

[jupyter-matplotlib](https://github.com/matplotlib/jupyter-matplotlib)をインストールし、`%matplotlib widget`のmagic commandを実行することでも解決できました。
自分がインストールしたバージョンは**v0.3.0**です。

実行したコマンド：

```sh
conda install -c conda-forge ipympl
# conda install nodejs  # 必要なら
jupyter labextension install @jupyter-widgets/jupyterlab-manager
jupyter labextension install jupyter-matplotlib
```

コード：

```python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

%matplotlib widget

fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')

def init():
    ax.set_xlim(0, 2 * np.pi)
    ax.set_ylim(-1, 1)
    return ln,

def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,

ani = FuncAnimation(fig, update, frames=np.linspace(0, 2 * np.pi, 128),
                    init_func=init, blit=True, interval=50)
```

notebookに以下のようなアニメーションが出力されていれば成功です。

![anim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133841/5518f479-48bf-d094-2659-934a482f4cdc.gif)



## 補足

作成したアニメーションを保存するときは、例えばこんな感じで。下のコードを実行するには事前に[imagemagick](https://www.imagemagick.org/)をインストールしておく必要があります。

```python
ani.save('anim.gif', writer='imagemagick', fps=10)
```

## 参考

- [Interactivity does not work in Jupyter Lab · Issue #66 · matplotlib/jupyter-matplotlib](https://github.com/matplotlib/jupyter-matplotlib/issues/66)
- [This matplotlib animation example works in notebook but not in lab · Issue #4492 · jupyterlab/jupyterlab](https://github.com/jupyterlab/jupyterlab/issues/4492)
- [Javascript Error: IPython is not defined in JupyterLab - Stack Overflow](https://stackoverflow.com/questions/51922480/javascript-error-ipython-is-not-defined-in-jupyterlab)
- [Jupyterでmatplotlibのjavascriptアニメーションを動かす - QiitaQiita](https://qiita.com/yoku_/items/11ac4ad1df349095655c)