【matplotlib】specgramを使って時間周波数解析をする方法[Python]

  • URLをコピーしました!

matplotlib

前回、NumPyでヒストグラムのビンを任意に作成する方法(np.ditigize)を紹介しました。

今回はmatplotlibのspecgramを使って時間周波数解析をする方法を紹介します。

時間周波数解析に関してはSciPyを使って行う方法を前に紹介していますので、良かったらどうぞ。

それでは始めていきましょう。

specgramの使い方

specgramを使い、時間周波数解析の結果をグラフ化するには「plt.specgram(波データ, サンプリングレート)」とします。

簡単なsin 波を使って試してみましょう。

import matplotlib.pyplot as plt
import numpy as np

fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time)

fig = plt.figure()
plt.clf()

plt.specgram(y, Fs=fs)

plt.xlabel("Time")
plt.ylabel("Frequency")

plt.show()

実行結果

20 Hzと100 Hzのsin波を合成した場合はこの様になります。

import matplotlib.pyplot as plt
import numpy as np

fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)

fig = plt.figure()
plt.clf()

plt.specgram(y, Fs=fs)

plt.xlabel("Time")
plt.ylabel("Frequency")

plt.show()

実行結果

カラーマップの変更方法

plt.specgramのオプション引数はいくつかあるのですが、特によく使うものとしてカラーマップのオプション引数があります。

カラーマップを変更するには「cmap=カラーマップ」を追加します。

import matplotlib.pyplot as plt
import numpy as np

fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)

fig = plt.figure()
plt.clf()

plt.specgram(y, Fs=fs, cmap="plasma")

plt.xlabel("Time")
plt.ylabel("Frequency")

plt.show()

実行結果

分解能の変更方法

出力する画像の分解能を変更するには「NFFT」と「noverlap」のオプション引数を変更します。

デフォルトはそれぞれ256と128です。

それぞれ値を小さくするとこんな感じになります。

import matplotlib.pyplot as plt
import numpy as np

fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)

fig = plt.figure()
plt.clf()

plt.specgram(y, Fs=fs, NFFT=64, noverlap=16)

plt.xlabel("Time")
plt.ylabel("Frequency")

plt.show()

実行結果

逆に値を大きくするとこんな感じです。

import matplotlib.pyplot as plt
import numpy as np

fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)

fig = plt.figure()
plt.clf()

plt.specgram(y, Fs=fs, NFFT=512, noverlap=256)

plt.xlabel("Time")
plt.ylabel("Frequency")

plt.show()

実行結果

さらに値を大きくしてNFFTがデータ数よりも大きくなった場合、警告が出ます。

import matplotlib.pyplot as plt
import numpy as np

fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)

fig = plt.figure()
plt.clf()

plt.specgram(y, Fs=fs, NFFT=1024, noverlap=512)

plt.xlabel("Time")
plt.ylabel("Frequency")

plt.show()

実行結果
/var/folders/sp/hg7p80kx22s7vct7yb0zl5cm0000gn/T/ipykernel_3389/
3366260405.py:11: UserWarning: Only one segment is calculated since 
parameter NFFT (=1024) >= signal length (=1000).
  plt.specgram(y, Fs=fs, NFFT=1024, noverlap=512)

またNFFTはnoverlapより必ず大きい値である必要があります。

noverlapがNFFTと同じ値、もしくはNFFTより大きな値になった場合はエラーとなります。

import matplotlib.pyplot as plt
import numpy as np

fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)

fig = plt.figure()
plt.clf()

plt.specgram(y, Fs=fs, NFFT=64, noverlap=64)

plt.xlabel("Time")
plt.ylabel("Frequency")

plt.show()

実行結果
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[60], line 11
      8 fig = plt.figure()
      9 plt.clf()
---> 11 plt.specgram(y, Fs=fs, NFFT=64, noverlap=64)
     13 plt.xlabel("Time")
     14 plt.ylabel("Frequency")

(中略)

ValueError: noverlap must be less than NFFT

次回はmatplotlibで積み上げの折れ線グラフを作成する方法(plt.stackplot)を紹介します。

それでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする