Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

PythonでOctave (MATLAB) の関数を使える oct2py 【インストール方法・利用例】

はじめに

数値計算用のプログラミング言語としては Pythonの利用が増えています.

一方で,MATLABや,MATLABに似たオープンソース数値計算ツールである Octave も選択肢としてあります.

Python が使われている一方で,Octaveにしかない関数や,Octave (MATLAB) で書いた関数を利用したいという場面があります.

そこで,今回はPythonOctaveの関数を呼び出せる便利なライブラリ「oct2py」を紹介します.

本記事では,PythonからOctaveの関数を簡単に使う方法,特に「oct2py」のインストール方法と利用例を詳しく説明します.

インストール方法

検証環境

  • OS: Windows 11 Home (23H2)
  • Pythonバージョン: 3.10.6
  • Octaveバージョン: 9.2.0
  • Oct2pyバージョン: 5.7.2

Octave, oct2pyの概要

oct2py は,Python数値計算ツール Octaveを統合し,PythonからOctaveの関数を呼び出せるツールです.MATLABが有償であるのに対し,Octaveオープンソースであり,手軽に数値計算が可能です.このライブラリを使うと,Pythonコードの中でMATLABライクな数値処理が簡単に行えます.

octave.org

pypi.org

github.com

oct2py.readthedocs.io

octaveのインストール方法

まずは Octaveをインストールします.インストーラの指示に沿って進めれば大丈夫です.

https://octave.org/download

インストール後,システム環境変数octaveのパスを設定する必要があります.

ここで重要なのが,octave-cli.exe (コマンドラインインターフェイス版) が存在するフォルダのパスを登録する必要があります.

私の環境だと,"C:\Program Files\GNU Octave\Octave-9.2.0\mingw64\bin"でした.

ここで,"C:\Program Files\GNU Octave\Octave-9.2.0"を環境変数に設定してしまうと,oct2pyの呼び出し時に以下のようなエラーが出てしまいました.

>>> import oct2py
[WinError 193] %1 は有効な Win32 アプリケーションではありません.

oct2pyの導入

次に,Pythonの環境にoct2pyを導入します.以下のpipコマンドを使って簡単にインストールできます.

pip install oct2py

また,condaも利用できます.下記を参考にしてください. blink1073.github.io

パッケージの導入

ここまでの操作だと,Octaveの基本的な機能しか利用できません.

そこで,例えば信号処理や制御システム向けのパッケージを導入したい場合は,Octave上で以下のコマンドを実行します.

pkg install -forge signal

この時,Octaveは管理者権限で実行することを推奨します.

また,上記のコマンドでうまくいかなかった場合,手動でダウンロードしてインストールすることを試してみてください.私の環境では,以下のように解凍せずにインストールできました.なお,インストールには少し時間がかかりました.

pkg install signal-1.4.6.tar.gz

参考: sanyo-jyuku.blogspot.com

動作確認

以上の導入作業終了後,例えばpythonインタプリタを起動して,以下の文を入力し,エラーなく実行できれば導入は無事完了です.

>python
>>> import oct2py
>>> oc = oct2py.Oct2Py()

利用例

基本操作

oct2pyを使った最も基本的な操作は,Octaveの関数をPython内で呼び出すことです.

例えば,octave.sin(1)のように呼び出して計算を行います.

import numpy as np
import oct2py
oc = oct2py.Oct2Py()
ans = oc.sin(np.pi/2)
print(f"{ans}") # => 1.0

パッケージの利用

追加のパッケージを利用する際は,以下のように呼び出す必要がありました.以下の例では,signal を利用しています.

import numpy as np
import oct2py
oc = oct2py.Oct2Py()
oc.eval('pkg load signal')

関数の返り値の数の指定:nout

Octaveの関数には複数の値を返すものがあります.しかし,特にnoutを指定せずに利用した場合は,1つ目の返り値のみとなるようです.

そこで,複数の値を返す関数ではnoutパラメータを指定することで,それぞれの出力を取得できます.基本的に,octaveの関数を使うときはnoctを指定する方がよさそうです.

以下は,Butterworth filterの関数 butter の利用例です.

nout を指定しない場合:

import numpy as np
import oct2py
oc = oct2py.Oct2Py()
oc.eval('pkg load signal')

ret = oc.butter(4, 0.2)
print(ret)
# => [[0.00482434 0.01929737 0.02894606 0.01929737 0.00482434]]

Function File: [b, a] = butter (n, wc) の bのみが返ってきています.

nout=2:

ret = oc.butter(4, 0.2, nout=2)
print(len(ret)) # => 2
print(ret)
# => [array([[0.00482434, 0.01929737, 0.02894606, 0.01929737, 0.00482434]]), array([[ 1.        , -2.36951301,  2.31398841, -1.05466541,  0.18737949]])]

Function File: [b, a] = butter (n, wc) の b, aが返ってきています.

nout=3:

ret = oc.butter(4, 0.2, nout=3)
print(len(ret)) # => 3
print(ret)
# => [array([[0.00482434, 0.01929737, 0.02894606, 0.01929737, 0.00482434]]), array([[ 1.        , -2.36951301,  2.31398841, -1.05466541,  0.18737949]])]

Function File: [z, p, g] = butter (…) になるため,返り値は分子・分母多項式の係数ではなく,零,極,ゲインになることに気を付ける必要があります.

Octave独自の関数を使う例:invfreqz

実は,OctaveにはPython (Scipyなど) には実装されておらず,MATLAB独自の関数が多くあります.

例えば,invfreqz 関数は周波数応答データからフィルタ係数 b, a を推定する便利な関数です.しかし,2024年9月現在では Scipyなどには実装されていません.

しかし,oct2pyを使えば,Pythonからinvfreqzを呼び出してフィルタ設計を行うことができます.

以下は,低域通過フィルタ(バターワースフィルタ)の周波数応答 H(f)から,フィルタ係数 b, a を

Octaveでの invfreqz() の利用

octave:3> pkg load signal
octave:4> n = 128;
octave:5> [b, a] = butter(4, 0.2); % 低域通過フィルタの設計 (バターワースフィルタ)
octave:6> [H, w] = freqz(b, a, n); % フィルタの周波数応答を計算
octave:7> p = 4; % 分子の次数
octave:8> q = 4; % 分母の次数
octave:9> [bb, aa] = invfreqz(H, w, p, q); % invfreqzを使ってフィルタ係数を推定
octave:10> bb
bb =

   4.8243e-03   1.9297e-02   2.8946e-02   1.9297e-02   4.8243e-03

octave:11> aa
aa =

   1.0000  -2.3695   2.3140  -1.0547   0.1874

octave:12> b
b =

   4.8243e-03   1.9297e-02   2.8946e-02   1.9297e-02   4.8243e-03

octave:13> a
a =

   1.0000  -2.3695   2.3140  -1.0547   0.1874

Python (oct2py) で Octaveのinvfreqz() の呼び出し

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import oct2py
>>>
>>> oc = oct2py.Oct2Py()
>>> oc.eval('pkg load signal')
>>>
>>> n = 128
>>> b, a = oc.butter(4, 0.2, nout=2) # オリジナルのフィルタ設計 (バターワース低域通過フィルタ)
>>> H, w = oc.freqz(b, a, n, nout=2) # 周波数応答を取得
>>> p = 4  # 分子の次数
>>> q = 4  # 分母の次数
>>> bb, aa = oc.invfreqz(H, w, p, q, nout=2) # invfreqzを使用してフィルタ係数を推定
>>>
>>> print(bb)
[[0.00482434 0.01929737 0.02894606 0.01929737 0.00482434]]
>>> print(aa)
[[ 1.         -2.36951301  2.31398841 -1.05466541  0.18737949]]
>>> print(b)
[[0.00482434 0.01929737 0.02894606 0.01929737 0.00482434]]
>>> print(a)
[[ 1.         -2.36951301  2.31398841 -1.05466541  0.18737949]]
>>>

同じ結果になっていることが確認できました。

まとめ

oct2pyを使用することで,Pythonの環境から簡単にOctaveの豊富な関数やライブラリを活用することができます.

Python の NumPyやSciPyなどを合わせて使いながら,高度・高精度な数値計算や信号処理を実施したり,OctaveMATLABスクリプト・関数等の資源を有効活用するのにオススメです.