2021年1月14日木曜日

PySimpleGUIとMatplotlibで高速グラフ描画





就活がいよいよ始まってきた中の人です.今回はPySimpleGUIに以前作成したMatplotlibの高速描画クラスを埋め込む話です. 

今回の話のコードはこちらから




1.PySimpleGUIについて


MatplotlibとGUIを組み合わせる場合,Tkinterとの組み合わせがよくあるパターンだと思います(Matplotlibの描画の問題で,多分これ一択).ただTkinterでGUIを組む場合,部品のレイアウトで苦労することがあるかと思います.そこで登場するのがPySimpleGUIです. 

売り文句は"Python GUI For Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces." 
どうやらPythonで使えるGUIライブラリをラップして,"人間"でも使えるようにしたライブラリと考えればよさそうです(はてさて読めるのだろうか).

参考:

2.Matplotlibを埋め込む


Tkinterもラップしてくれているので,Matplotlibも埋め込めそうって考えてたら公式cookbookに参考例がありました.どうやら動画として動かせ...ませんでした.どうやらサンプルコードが古いバージョンのようで,新しいものでは動作しないようです.

で,情報を探し回っていたら@bear_montblancさんの記事を見つけ,試してみたら動作しました.とりあえず普通の使い方であれば,Matplotlibのグラフを埋め込んで動作させることが可能なようです.

参考:
Be4rR,"PySimpleGUIにMatplotlibを埋め込みたい",https://qiita.com/bear_montblanc/items/cce4e8c58dfa236200f6

3.自作クラスを埋め込む


普通の使い方であればMatplotlibのグラフを埋め込めたので,今度は先日作成した自作クラスを埋め込みます.

といっても,2.で実装したコードを一部書き換える程度であっさり動作しました.



if __name__ == "__main__":

    try:
        make_dpi_aware()

        # Generate Layout
        layout = [[sg.Text('Fast_Render_Matplotlib Plot')],
                  [sg.Canvas(key='-CANVAS-')],
                  [sg.Button("Add"), sg.Button("Clear")]]

        # Generate Window (finalize=True is Required)
        window = sg.Window('Embedding Fast_Render_Matplotlib In PySimpleGUI',
                           layout,
                           finalize=True,
                           element_justification='center',
                           font='Monospace 18')

        # Generate Fig to Embedding Graph
        fig = plt.figure(figsize=(5, 4))
        line_ax = fig.add_subplot(2, 1, 1)
        pos_ax = fig.add_subplot(2, 1, 2)
        points_num = 500
        scatter_view = plotter.Scatter(fig, pos_ax, len_points=points_num, show_icon=True, PySimpleGUI=True)
        line_view = plotter.Line(fig, line_ax, plot_area=(points_num, 1000), len_points=points_num, PySimpleGUI=True)

        # Associate Fig and Canvas.
        fig_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig)

        while True:
            event, values = window.read()

            if event in (None, "Cancel"):
                break
            elif event == "Add":
                # Generate Random Data
                rand_array_x = np.random.randint(-1000, 1000, 1250).tolist()
                rand_array_y = np.random.randint(-1000, 1000, 1250).tolist()
                y = np.random.randint(-1000, 1000, points_num)

                # Plot Data
                line_view.plot(y)
                scatter_view.plot([rand_array_x, rand_array_y])

            elif event == "Clear":
                line_view.cla()
                scatter_view.cla()
                fig_agg.draw()

    except Exception as e:
        print(e, end="\n\n")
        import traceback
        traceback.print_exc()
        input("Press any key to continue...")
    else:
        print("Done")
    finally:
        window.close()



基本的には,ぼやけ防止の関数を走らせ,GUIのレイアウトを決定,ウィンドウを生成したのち,グラフの初期設定を行います.その後,グラフとレイアウトで設定したキャンバスを関連付けてあげることで準備は完了です.プロット類はボタンの入力をトリガとして走らせることで実行します.

参考:

3.実行速度





とりあえず50[fps]前半から60[fps]前半あたりが出ているようです.そこそこのフレームレートですね.

4.参考


コメント欄で教えてもらった,公式のデモコード集


©2021 shts All Right Reserved.

2 件のコメント:

  1. Many matplotlib example programs here:
    http://Demos.PySimpleGUI.org

    返信削除
    返信
    1. Thanks for the reply.
      I should certainly refer to this as well.
      I'll update this article later.

      削除