ラベル signal processing の投稿を表示しています。 すべての投稿を表示
ラベル signal processing の投稿を表示しています。 すべての投稿を表示

2014年11月20日木曜日

Wavelet解析



Torrence and Compo [1998]  のwavelet解析手法と、そのツールは我々の分野でよく使われる。私もMiyama and Miyazawa [2014]をで使用している。その関連した発表をAOGS 2014でした時に、Torrence and Compo [1998] はスケールが大きいほうを過大評価するバイアスがあり、それに関する論文(Liu et al. 2007と関連するweb page)を教えていただいた。

下の図はLiu et al. 2007のFig.2に対応する、1,8,32,128,365日のsineカーブの単純な重ね合わせ(a)のシグナルにwavelet解析をかけたものである。Torrence and Compo [1998] の手法(b,c)ではスケールが大きい(長周期)のほうがシグナルが大きいと解析されてしまう。一方、Liu et al. [2007]はスペクトルをスケールで割ることを提案しており、これであれば(d,e)、各周期が同じくらいの強さであるという合理的な結果が出る。





上記の図を作るwavelet解析のツールをpythonに翻訳し、IPython Notebookにしたものはこちら。
http://nbviewer.jupyter.org/urls/dl.dropbox.com/s/u0wb931fs4qfrpn/wavelet_test_sine.ipynb

さらに、NINO SST3のwavelet解析した(Liu et al. 2007のFig 4に対応)物をIPython Notebookしたものはこちら。
http://nbviewer.jupyter.org/urls/dl.dropbox.com/s/400j051n0sustcy/wavelet_test_ElNino3_Liu.ipynb





2013年4月12日金曜日

Lanczos filter と Wakari




Lanczos filterによるlow-pass filterを理解するためにIPythonノートブックを作成した。
https://www.wakari.io/nb/tmiyama/Lanczos_test

結論は、少ない点でもadjustすれば低周波で応答関数が1に近づくようにできるが、基本は点数を大きくする必要があるということだ。

前回はIPython Viewerを使ってノートブックを公開したが、今回はWakariを使用してみた。

Wakariは端末がなくとも、クラウドでいろいろ計算できるので、なかなかおもしろい。

参考文献
Duchon, C. E., 1979: Lanczos Filtering in One and Two Dimensions. Journal of Applied Meteorology, 18, 1016–1022.

気象研究ノート 221号 気象学と海洋物理学で用いられるデータ解析法 伊藤 久徳・見延 庄士郎/著 日本気象学会/刊 A4判 253p

GFD電脳Ruby小物置き場 (Library) Lanczosフィルター
http://davis.gfd-dennou.org/rubygadgets/ja/?(Library)+Lanczos%A5%D5%A5%A3%A5%EB%A5%BF%A1%BC

2011年10月17日月曜日

フィルタの応答関数



フィルタの周波数応答関数をプロットしてみる。

以下の例は、京都大学の講義「MATLABで時系列解析」の線形システムの伝達関数を求めるを翻案したものである。

想定としては、1ヶ月ずつのデータがあり、シグナルとしては、48ヶ月周期と6ヶ月周期とホワイトノイズが重なったシグナルに対して13ヶ月の移動平均をかけている。

理論的な周波数応答関数を求める関数はscipyのfreqz関数である(matlabのfreqz関数に対応する)。応答関数は入力 x のパワースペクトル密度関数 Pxx と出力のクロススペクトル密度関数 Pyx の比としても推定できる。スペクトル密度関数を求める関数psdに関しては何度か紹介した。

#!/usr/bin/env python

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.pylab as plab
import matplotlib.mlab as mlab
from scipy.signal import freqz,lfilter

#--- Signal

Fs = 1   # frequency 
T = 1000.    # final time
t = np.arange(0.,T+1./Fs,1./Fs)  # time
x = np.sin(2.*np.pi*t/6.) + np.sin(2.*np.pi*t/48.)+np.random.normal(0,0.1,len(t)) # input signal

#---- power spectral by Welch's method 

plt.figure()
nfft = 256
window = np.hanning(256) 
noverlap = 128 
[Pxx,f] = mlab.psd(x,NFFT=nfft,Fs=Fs,window=window,noverlap=noverlap,detrend=plab.detrend_none) # Power spectral
plt.subplot(2,2,1) 
plt.plot(f,10*np.log10(Pxx)) # plot in decibel 
plt.legend(('Pxx',))
plt.plot([1./12.,1./12],[-70.,20.],'k--')
plt.plot([1./6.,1./6],[-70.,20.],'k--')
plt.plot([1./48.,1./48],[-70.,20.],'k--')
plt.ylim((-70,20))

#--- Moving average

h = np.ones(13)/13.

#--- Calculate theoritical response

fs,Res = freqz(h)
plt.subplot(2,2,2)
plt.plot(fs/2./np.pi,np.abs(Res))
plt.legend(('theoretical response',))
plt.plot([1./12.,1./12],[0.,1.],'k--')
plt.plot([1./6.,1./6],[0.,1.],'k--')
plt.plot([1./48.,1./48],[0.,1.],'k--')
plt.ylim((0,1.))


#--- Apply Filter

y = lfilter(h,1,x) # filter 

[Pxy,f] = mlab.csd(x,y,NFFT=nfft,Fs=Fs,window=window,noverlap=noverlap,detrend=plab.detrend_none) # cross scectral density

[Pyy,f] = mlab.psd(y,NFFT=nfft,Fs=Fs,window=window,noverlap=noverlap,detrend=plab.detrend_none)  # power spectral density 

plt.subplot(2,2,3)
plt.plot(f,10.*np.log10(abs(Pyy)))
plt.legend(('Pyy',))
plt.plot([1./12.,1./12],[-70.,20.],'k--')
plt.plot([1./6.,1./6],[-70.,20.],'k--')
plt.plot([1./48.,1./48],[-70.,20.],'k--')
plt.ylim((-70,20))


#--- Calculate estimated response

Resc = Pxy/Pxx 
plt.subplot(2,2,4)
plt.plot(f,abs(Resc)); 
plt.legend(('estimated response',)) 
plt.plot([1./12.,1./12],[0.,1.],'k--')
plt.plot([1./6.,1./6],[0.,1.],'k--')
plt.plot([1./48.,1./48],[0.,1.],'k--')
plt.ylim([0,1])

#--- Save fig
plt.savefig("test_response.png")
plt.show()


以下がフィルタを12ヶ月移動平均にした場合。
以下はシグナルからホワイトノイズを除いた場合。この時はスペクトルからの応答関数の推定はうまくいかない(移動平均はこの場合は13ヶ月)。



参考) Scipy Cookbook FIRFilter