PyQtGraphとmatplotlibを真面目に比較する（Axes.plot相当）

# 環境
- Mac mini(M1) Big Sur
- Python 3.9.6(arm64)
- numpy 1.21.1
- matplotlib 3.4.3
- PyQtGraph 0.12.2

# 目標
　matplotlibで描いてるグラフをPyQtGraphで描けるようになる．

# 実習
　matplotlibのコードをコメントに書いた直後にPyQtGraphのコードを記述するという方式で進めます．matplotlibはオブジェクト指向で扱います．また以下のインポート文を前提とします．

```import.py
import numpy as np
from matplotlib import pyplot as pet
import pyqtgraph as pg

np.random.seed(765)
x = np.linspace(0, 10, 100)
y = np.cos(x)
s = np.random.randn(100)/30
```

## Artists
　[公式](https://pyqtgraph.readthedocs.io/en/latest/plotting.html)から拾ってきたmatplotlibでいうところのArtistsの図です．これを念頭に置いておくと理解しやすいはずです．
![IMG_3148.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403698/2d13394e-f679-eed3-a722-25d46afd76ea.png)

## Axes.plot()
```plot01.py
#fig, ax = plt.subplots()
win = pg.plot()

#ax.plot(x, y)
win.plot(x, y)

#fig.show()
win.exec()
```
これを実行すると新規ウィンドウでグラフが表示されます．
![plot01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403698/b9396b74-301f-0fe8-d138-15ca6b018f83.png)
　そして右クリックすると保存（Export）の他にスペクトル表示や対数変換，微分，グリッド線の表示が後から変更できます．
![スクリーンショット 2021-08-12 22.09.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403698/815d285b-ac5f-6e6d-3f6a-93c93c51d885.png)
　なおグラフ1つだけであればmatplotlibの`Axes`のインスタンス化に相当する操作はなくても描けます．

```plot02.py
win = pg.plot(x, y, title='cos curve')
pg.exec()
```
![スクリーンショット 2021-08-12 22.16.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403698/f5bce623-6005-b984-a44d-bde435c639a3.png)
　しれっと指定されてる`title`はウィンドウの名前です．ただし右クリックからの保存ではウィンドウ名は残らないため，グラフタイトルとは別です．

## fig.savefig()
```plot03.py
#fig.savefig('plot03.png')
import pyqtgraph.exporters
win = pg.plot(x, y, title='cos curve')
exporter = pg.exporters.ImageExporter(win.plotItem)
exporter.parameters()['width'] = 100
exporter.export('plot03.png')
```
　スクリプトでの保存は少し手間でした．まず`pyqtgraph.exporter`を明示的に読み込む必要があります．ただしインタラクティブシェルでGUIウィンドウにグラフを表示して右クリックから保存した後は不要になりました．次に`exporter`に`Axes`ならぬ`PlotItem`を渡します．その次は幅を指定していますがなくても保存はできました．なおこの状態だと縦横比は固定のようで，幅を変えると縦も自動的に調整されました．最後は普通にファイル名の指定です．
　`PlotItem`を指定するということはあるウィンドウ中のグラフを全部保存したい時は個別なのか？と不安になりますが，ちゃんと一括保存する方法があります．後述する方法で複数のグラフをウィンドウに放り込んだ場合，`exporter = pg.exporters.ImageExporter(win.scene())`とすれば後は同じ様にして保存できました．

## plt.subplots()
　複数のグラフを並べる方法です．

```plot04.py
#fig, axes = plt.subplots(2, 2)
win = pg.GraphicsLayoutWidget(show=True)

#axes[0][0].plot(x, y)
p1 = win.addPlot(x=x, y=y)

#axes[0][1].plot(x, y)
p2 = win.addPlot(x=x, y=y)

#axes[1][0].plot(x, y)
win.nextRow()
p3 = win.addPlot(x=x, y=y)

#axes[1][1].plot(x, y)
p4 = win.addPlot(x=x, y=y)
```
　matplotlibと異なりデータは`x=x`などと指定しないとエラーになりました．また`show=True`は指定しないとグラフが表示できませんでした．`parent`パラメータが存在してそこに`QWidget`というものを指定できるらしいですが，それをしない場合は`show=True`が必要になるようです．行と列を明示したければ，

```plot05.py
win = pg.GraphicsLayoutWidget(show=True)
for i in [0,1]:
    for j in [0,1]:
        win.addPlot(
                x=x, y=y,
                row=i, col=j
            )
```
![plot05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403698/b4c5eb14-5084-8a17-0d36-bb13e79ad658.png)

　上のグラフはデータは全て$y=\cos x$ですが，右クリックしてスペクトル表示や微分（$y'$），$y$ vs $y'$の表示に変更してあります．

# 結論
　とりあえず描いて保存はできる．保存は少し手間．

# 予定
1. 散布図
1. データ分析的な使い方ができるか  
（ヒストグラムとかカーネル密度分布とか）
1. アニメーション表示と保存

などなど

# 追記
[続編書きました.](https://qiita.com/Yukiho_P/items/29ef5d17cd6a7f06564f)
データ分析用途は難しそうなのでplotlyでも使うのが良さそう．

# 追記2
[アニメーション描画まで書きました．](https://qiita.com/Yukiho_P/items/68fb44192bf596460a50)
保存まで試すのは時間かかりそうです．