フレーム構築編:wxPythonで信号処理のGUIアプリをつくろう①

  • このエントリーをはてなブックマークに追加
Advertisements

やっぱりGUIアプリを作ってみたいと思い、当ブログの信号処理関連コードの中で需要が高いフィルタ処理をソフト化してみます。ここでは初めてGUIアプリを作る人を対象に手順を追って作り方を説明します。是非みんなでGUIアプリを作れるようになりましょう。

こんにちは。wat(@watlablog)です。GUIアプリ作成挑戦記としてシリーズ化します!まずは構想とフレーム構成を作ります

本記事の対象読者

この記事はこれまでGUIアプリを作りたかったけど敷居の高さを感じていた人を対象としています。

Advertisements

筆者自身もwxPythonでGUIアプリを作るのは初めてであり、さらにこの記事はアプリ開発と同時に執筆しています。

Advertisements

初心者が書く記事をシリーズの最初から読むことで、読者も構想からGUI設計コード記述デバッグexe化まで一通りこなせるようになることを目標とします。
筆者が途中で挫折しなければ…

開発環境

PC環境

今回筆者は以下のMacbook Proで開発していますが、おそらくWindowsも同じ操作で動くと思います。

Mac OS macOS Catalina 10.15.7
CPU 1.4[GHz]
メモリ 8[GB]

Python環境

Python環境はこちら。Anacondaを使わずにインストールしたPythonとpip installした各種ライブラリ、IDEはPyCharmを使っています。シリーズが進むにつれてライブラリは追加予定ですが、フレーム構築編としてはwxPythonとmatplotlib、numpyが入っていれば十分でしょう。

Python Python 3.9.6
PyCharm (IDE) PyCharm CE 2020.1
Numpy 1.21.1
matplotlib 3.4.3
wxPython 4.1.1

GUIコード自動生成ツール

wxPythonでGUIを作っていきますが、最初はwxPythonのGUIコードを自動生成してくれるwxFormBuilderを使います。

wxFormBuilderについては「wxFormBuilderでwxPythonのGUIコード自動生成」にまとめましたので、是非内容をご確認ください。

信号処理GUIアプリの構想(フレームのイメージで説明)

まずはシンプルにGUIアプリを学ぶことを目的とする

初めて作るGUIプログラミングでいきなり凝ったアプリを作ろうとすると挫折しそうです。そのため、このシリーズでは「学び」を主目的に置き、できるだけシンプルな構成で完結するアプリにしたいと思います。

基本情報技術者試験でUMLUnified Modeling Language)を少し勉強した身としては、かっこよくクラス図等のソフトウェア設計図を描いてから手を動かしたいところですが、今回は省略します。

UMLは対ソフトウェア開発者にとっては曖昧な表現が少なく効果的だと思いますが、本記事の読者はおそらくプログラミング初心者が多いため、逆にわかりにくくなることが懸念されます。

そのためアプリの全体構想はブログ記事の文章や絵で解説するレベルを目指します。

信号処理の内容としては、このブログでも昔から人気のあるフィルタ処理を扱います。それでは以下にアプリに求める要件を設定し、構想を練っていきます。

時間波形読み出し機能

ここからは実際にwxPythonで作成したGUIのフレームを使って説明をします。

信号処理プログラムは、はじめに時間波形を読み込む機能が必要です。以下の図がソフトを起動して最初に目にする画面ですが、最上部に読み込みボタンや保存ボタンを設置し、タブの中に種類毎のプロット表示や設定をまとめるようなスタイルにしてみました。

ファイル保存もここに記載しています。

時間波形読み込み部分のタブ

図の左側にはwxFormBuilderのオブジェクトツリーを示しています。まだ無駄があるような気もしますが、トレースすれば同じフレーム構造が作れるはずです(記事後半にプロジェクトファイルをダウンロードできるようにしておきます)。

ちなみに、「時間波形情報」部分は背景色bgを変更し、enableのチェックを外すことでユーザが値を入力できなくしています。

表示器の設定

wavとcsvに対応させる

フィルタ処理の元波形はwavファイルcsvファイルの2種類から読み込めるようにします。

wavファイルは音声ファイルとしてメジャーであり、csvファイルは計測器からのデータ形式で頻出したり、Excel使いに人気があります。

PyAudioが使えるので録音して波形にするといったことも既にできますが、まずはシンプルにファイルのみを扱います!

単一チャンネル波形のみを扱い、キャリブレーションは行わない

wavファイルやcsvファイルには多チャンネル記録が可能ですが、ここでは単一チャンネルのみを扱います。そして、通常の商用計測ソフトで行われるキャリブレーション等も行いません。

多チャンネル信号を扱う時は、それぞれのチャンネルに対応する校正係数をかけたり、プロットの見せ方をチャンネル毎に変えたりと、ユーザに配慮したい項目が多彩になります。

ここでは上記最初の目的により、まずはそれらを排除した最もシンプルな構成でアプリを作成します。

特にwavファイルはビットのフルレンジに対する処理を入れたりしないと実用的な使用は難しいと思いますが、細かいことは後で!

ちなみにソフトタイトルのwlwatlabの略です。。

フィルタ設定機能

フィルタ設定は別タブにしてみました。行列方向両方で位置を揃えたかったため、GridSizerを使っています。

ここでは各種フィルタ(ローパス、ハイパス、バンドパス、バンドストップ)の実行ボタンを左側に配置させ、必要なカットオフ周波数設定をすぐ隣に置いています。

右側には減衰量に関する共通設定を置きました。初期値等はコードの方で入れておくようにする方針です。

フィルタ設定部分のタブ

通常市販のソフトは設定画面を別ウィンドウで用意して、適用やキャンセル処理を実装するものが多いと思います。余裕が出たら別のバリエーションに挑戦しても良いかも知れません。

フーリエ変換機能

信号を読み込んだ時フィルタをかけた時再計算ボタンが押された時…の3パターンでフーリエ変換による周波数軸プロットを実装する予定です。

ここでは平均化フーリエ変換を想定し、オーバーラップを考慮して時間波形が何回平均化されたかを示す「平均化回数」を情報として表示させておく方針です。

フーリエ変換のタブ

フーリエ変換の結果は上のボタンからcsvファイルに保存可能にしようと思います。

スペクトログラム表示機能

フーリエ変換と同じタイミングかつ同じ設定でスペクトログラム表示(STFT計算)を行います。こちらは本当に確認だけのおまけ機能という用途です。

スペクトログラム表示機能のタブ

プロット軸設定の修正機能

PythonのCUIコードだけでプログラミングしていると、一番面倒なのが軸設定の変更だと思います。

データによりますが、オートスケールにすると広すぎる場合はxlimylimを修正する度にコードを実行する必要があります。インタラクティブに操作できるライブラリもありますが、matplotlibをそのまま使いたい時が多いです。

せっかくGUIプログラミングをするので、軸の上下限値を変更したらmatplotlibのプロットに反映されるイベントも作りたいと思いました(記事執筆時現在はまだやっていませんが、作れるはず…)。

Fixと書いてあるオブジェクトはcheckboxです。

以下の図はレイアウト図ですが、ちょっと無駄なスペースが多い?
wxFormBuilderを使っても微調整はなかなか難しいですね。

プロット軸修正機能のタブ

wxFormBuilderの作業

レイアウトの作成【ダウンロード可】

wxFormBuilderは感覚的な操作でwxPython用のGUIレイアウトを作ることが可能です。

作り方自体は「wxFormBuilderでwxPythonのGUIコード自動生成」をご覧いただければわかると思いますが、以下に今回の作った.fbpというプロジェクトファイルをダウンロードできるようにしてみました。

.zipに圧縮していますので、解凍することで中身のツリー構造の詳細を確認可能と思います。

イベントトリガーの設定

コードを自動生成する前に、イベントのトリガーを設定しておく必要があります。

方法は先ほどの記事に記載していますが、今回はwxButtonOnButtonClickイベント、wxTextCtrl(入力欄)にOnTextイベント、wxCheckBoxOnCheckBoxイベントを設定しました。

親フレームと子フレームの.pyファイル生成

こちらも先ほどの記事に記載しましたが、wxFormBuilderでレイアウトを決めた後は、Generate CodeGenerate Inherited Classを実行して親フレームと子フレームのPythonファイルを自動生成します。

Pythonコードを追記してフレームのみのアプリ動作を確認する

ファイル構成とクラスイメージ

今回は下の図に示す4つのファイル構成を想定しました。

ファイル構成の図

main.pyはメインの実行ループを管理したり、メインフレームのインスタンス化を担当する短いコードです。

MainFrame.pyはwxFormBuilderで自動生成され通常は編集しないファイルですが、matplotlib部分は自分で書く必要があります。

またwlFrontPanel.pyも自動生成されるコードですが、このファイルにはイベントに対する動作をプログラミングします。ここがメインのGUIプログラミングといった所でしょう。

dspToolkit.pyの内容はwlFrontPanel.pyに書いても問題はないと思いますが、計算に使うclassとフレームやイベントのclassは分けた方が可読性良しと判断したので分ける予定です(これから作る!)。

main.pyのコード

Main.pyのコードを以下に示します。
これは先ほどまでの記事で紹介していた内容と同じです。

MainFrame.pyのコード

MainFrame.pyは700行ほどのコードが自動生成されました!

ここでは「# matplotlib for 〜」とコメントが入っている3箇所(時間波形、周波数波形、スペクトログラム)にプロットを追記しています。

このコードについての詳細は「wxPythonでGUIレイアウトを作り込む時に参照するページ」に記載しましたので、こちらをご覧ください。

長い!

wlFrontPanel.pyのコード

wlFrontPanel.pyにはイベントの動作を記述しますが、この記事ではまずフレーム動作関係のみ追記します。

こちらも「wxPythonでGUIレイアウトを作り込む時に参照するページ」に記載していますが、ウィンドウを閉じるというメソッドを追記しただけとなりました。

フレーム部分の動作確認(動画)

上記3つのファイルを同じディレクトリに置いて、main.pyを実行するとGUIが画面に現れます。

静止画で説明すべきでないと思いましたので、こちらのYouTube動画で動作を確認できるようにしてみました。

それっぽい動きをしている…かも??

まだ4つ目の計算コードをまとめたファイルは作っていませんが、入れ物がとりあえずできました!

まとめ

この記事では信号処理のGUIプログラミング学習を目的に、第1弾としてアプリ構想やフレーム構築を行いました。
はたしてGUIプログラミング初心者(クラスで書くプログラミングも初心者)の筆者が完成まで辿り着けるのか…!

ということでシリーズ化します。
筆者が途中で挫折しなければ…

一応入れ物はできた段階ですが、完成をやさしく見守っていただけると幸いです。

コード自動生成ツールを使うことで、意外にも簡単に入れ物は作れました!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*