広く使われているPythonを活用して,フーリエ解析を学ぶ一冊。Pythonで数学的な処理をした経験がなくても問題ありません。科学技術計算で必須のライブラリNumPyとmatplotlibについて,基本から解説しています。

アプリ完成編:wxPythonで信号処理のGUIアプリをつくろう⑥

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

Pythonによる信号処理のGUIアプリ作成挑戦記第6弾は「アプリ完成編」です。前回までで時間波形や周波数波形に関する一連の機能実装は完成しているため、細かい「軸設定機能」、「処理結果保存機能」を実装してアプリを完成させる方法を紹介します。

こんにちは。wat(@watlablog)です。シリーズ第6弾はいよいよアプリを完成させます!全コードを公開していますので、是非最後まで読んでみてください!

バックナンバー

この記事は以下の記事の内容を前提とした続きものです。
是非こちらの記事も読んでみてください。

①アプリ構想とフレーム構築編

Advertisements

フレーム構築編:wxPythonで信号処理のGUIアプリをつくろう①」の記事で信号処理のGUIアプリを作り始めました。

Advertisements

この記事はどんなコンセプトでアプリを作るのか、各GUIをどうやって作っていくのか、開発環境や実際に作ったGUIコードを紹介しています。

②波形読み込み編

波形読み込み編:wxPythonで信号処理のGUIアプリをつくろう②」の記事ではファイル読み込み部分を実装しました。ボタンによるファイル選択、拡張子制限、matplotlibへのデータ渡しといったコードを紹介しています。

③周波数波形編

周波数波形編:wxPythonで信号処理のGUIアプリをつくろう③」の記事は平均化フーリエ変換を扱いました。平均化フーリエ変換はフレームサイズの条件次第で計算がかからない(オーバーラップ処理ができない)ため、関連の例外処理を施す必要がありました。

④スペクトログラム編

スペクトログラム編:wxPythonで信号処理のGUIアプリをつくろう④」ではフーリエ変換を拡張させ、信号の周波数変化や時間変化を可視化できるようにしました。

ここまで来ると読み込んだ波形の特徴が一目瞭然となり、これだけでもいっぱしのアプリケーションと呼べるものになったと思います。

⑤フィルタ処理編

フィルタ処理編:wxPythonで信号処理のGUIアプリをつくろう⑤」ではデジタルフィルタ処理を実装しました。

先にフーリエ変換やスペクトログラム表示機能を実装しておくことで、フィルタ機能の検証に使うという構想で進めています。

このアプリの目的は波形を読み込んで周波数分析しフィルタをかけて波形の変化を分析する部分にあるため、この時点でメイン機能は実装できたと言えます。

この記事でやること

軸設定機能の実装

ここまでの制作過程で「波形読み込み」や「周波数分析」、「スペクトログラム表示」をmatplotlibで可視化させてきました。

しかしプロットの各横軸、縦軸は波形の最大値や最小値から求められたオートスケールしか使えるようにしていませんでした。

プロット画面はユーザーが任意に拡大縮小して分析したいものです。そのためこの記事で軸設定機能の実装を行います。

軸設定機能のイメージ

これから実装する軸設定のイメージを図を使って見てみましょう。

本アプリは「Plot setup」タブで軸の設定を行います。軸の設定を有効化するためには「Fix」にチェックを付けます。チェックを付けないと各プロットはオートスケールでデータを表示します。

軸設定は時間波形、周波数波形と個別に設定し、スペクトログラムは時間波形のx軸設定と周波数波形の軸設定を使って調整します。

設定の適用は「Re:Calculation」ボタンで行います。このボタンは周波数計算の設定変更で実装した再計算ボタンですが、これを再利用してプロット設定も再計算で使用します。

軸設定の方法

時間波形の設定適用例を下図に示します。
ここでは四角で囲った部分を拡大してみましたが、軸に大きな値を設定することで縮小表示することも可能です。

時間波形の軸設定

次は周波数波形の設定適用例です。ここでは振幅成分である縦軸に大きな値を設定してみました。周波数波形はdB変換の有無で値が大きく変わるので注意してください。

周波数軸設定

スペクトログラム表示は時間/周波数/振幅の3成分を持っています。そのため時間軸はTime axesから、周波数軸と振幅軸はFrequency axesを流用します。

スペクトログラム表示の軸設定

ファイル保存機能の実装

次に実装するのはファイル保存機能です。
このアプリでは時間波形と周波数波形を保存可能としますが、以下の用途を想定しています。

  • 時間波形にフィルタをかけた後、wavファイルに保存して聴感上の変化を確認する。
  • csvファイルを読み込みwavファイルに変換する。
  • wavファイルを読み込みcsvファイルに変換する。
  • フーリエ変換結果をcsvファイルに保存して後の処理を自分で行う。
  • フィルタ処理後のフーリエ変換結果をcsvファイルに保存して後の処理を自分で行う。

時間波形のwav保存

Save wavボタン

wav波形の保存は「Pythonでモノラルとステレオのwavファイルを保存する方法」で行った方法を使います。PySoundFileを使うと1行で書けてしまうのでおすすめです。

時間波形を保存する際、プロットが空の場合はメッセージを表示させて処理をスキップするような例外処理をいれます。

def save_as()を作っていわゆる「名前を付けて保存」ダイアログによる処理を実現させます。

ちなみに、名前を付けて保存ダイアログの事例は日本語のサイトで見当たらなかったのですが、wxPython公式サイトにサンプルがありました(最初から見れば良かった)。

wxPython公式ドキュメント:https://docs.wxpython.org/wx.FileDialog.html

時間波形のcsv保存

Save csvボタン

wavファイルが音を再生する目的でよく用いられるのに対し、csvファイルは多くの計測機やソフトに対応しているためこちらも需要があります。

機能自体はwav保存と同じであるため、def save_as()を共通で使います。

周波数波形のcsv保存

Save csvボタン(FFT)

周波数波形(横軸周波数/縦軸振幅)の波形ももちろん保存したくなります。
周波数波形はwavファイルにする必要性がないため、csv保存のみ実装します。
手法は時間波形のcsv保存と全く同じ方法です。

dB変換のチェックボックスの状態でヘッダを「Amplitude[Lin]」にするか「Amplitude[dB]」にするか判断しています。

保存の直前にチェックボックスの状態を変更し、再計算しないまま保存してしまうと間違うことになるのですが、今回はそこまでケアをしていません(周波数計算時にフラグを立てておく等すれば良いかも?)。

ちなみに、csvのフォーマットや作り方は「ただPythonでcsvから離散フーリエ変換をするだけのコード」等の「ただだけシリーズ」でお馴染みのPandas記法です。もし本アプリを多チャンネル仕様に拡張したい方はこちらの記事をご覧頂けると参考になるかも知れません。

Pythonによる信号処理のGUIアプリコード

今回はアプリ完成編であるため、全てのコードをここに記録します。
今後修正があった場合もこの記事のコードを修正します(GitHubにもアップするかもですが)。

ファイル構成図を再度眺めてみましょう。本アプリは4つのファイルで構成されています。一応この通り作れたはず…です。

ファイル構成図

Python環境

改めてPython環境を示します。ライブラリはpip installしておく必要があります。

Python Python 3.9.6
PyCharm (IDE) PyCharm CE 2020.1
Numpy 1.21.1
Scipy 1.4.1
Pandas 1.0.5
matplotlib 3.4.3
wxPython 4.1.1
PySoundFile 0.9.0.post1

PCはMacbookで検証しています。

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

main.py

main.py」ファイルに記載するコードがこちらです。このコードはシリーズ初回から一切変更していません。

MainFrame.py

MainFrame.py」はwxFormBuilderで自動生成されたコードを、matplotlibのプロット表示対応とするために編集したものです。こちらもシリーズ初回に説明があります。

GUIのレイアウト定義はここで設定しています。

長い…。

wlFrontPanel.py

wlFrontPanel.py」は「MainFrame.py」で設定したボタンや制御器にイベントを設定するメソッドをまとめたファイルです。

今回の実装もこの部分を編集しています。

シリーズを重ねることで特に解説等なくても微修正をしていますので、この記事のコードが最新であることにご注意ください。

ちょっと長い…。

dspToolkit.py

「dspToolkit.py」は信号処理のクラスとしてのメソッドをまとめたファイルです。

このファイルでフィルタ処理、フーリエ変換関連の主要なコードを書いています。

これは長くない。

まとめ

アプリ完成🎉

とは言え、まだバグ潰しが完璧なわけではありません
詳細まで潰し込もうとするとGUIプログラミングはちょっと面倒…いや、かなり面倒!ということがわかりました。専業でプログラマをしている方はすごいと思いました…。

今回は普段メカ系エンジニアの筆者が果たしてGUIアプリを最後までプログラミングできるのか、というようなノリから始めました。

今年は本業も忙しくなりコーディングに時間がとれない感じでしたが、当初の予定通りつまずくことなく進めることができました。

迷わず進めた理由はなんといっても最初の一歩であるGUIレイアウトの設定を自動コーディングしてくれるwxFormBuilderのおかげでした。

イベント設定はwxPythonの公式ページに多くが載っているのとGoogle検索で乗り切ることができるので、主要な計算部分さえ構想が固まればGUIプログラミングもある程度できそうです。

是非皆さんもこの記事のシリーズ第1回からお読み頂き、GUIプログラミングをやってみてください!

このシリーズは最後におまけで実行ファイル化をしようと思います(エラーで筆者が挫折しなければ…。)

乞うご期待!

信号処理プログラムを完成させることができました
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

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

SNSでもご購読できます。

コメントを残す

*