(Library) Lanczosフィルター
作成者: 西本絵梨子
概要
Lanczosフィルターに関するライブラリです。 時空間領域に対応した重み関数、周波数空間に対応した応答関数、を返します。
ダウンロード
Lanczos.rb ライブラリ(2013/11/08版)。
依存ライブラリ
NArray, NMath (電脳Rubyホームページを参照のこと)
使用方法
上記ファイルを同一ディレクトリもしくは、パスの通っているディレクトリに格納し、
require 'Lanczos'
でモジュールを読み込んで下さい。
Tips
データに時空間フィルターをかけるには、 時空間領域でのフィルタリング と 周波数空間でのフィルタリング の二通りがある。 詳細は、Duchon(1979)、伊藤・見延(2010)などを参照してください。
- 時空間領域でのフィルタリングの仕方
重み関数(Lanczos::weight_fなど)を計算し、時空間データに対して加重移動平均 (GPhys加重移動平均メソッド)を施す。
- 周波数空間でのフィルタリングの仕方
まず、フーリエ変換(GPhysのFFTメソッド)などによって、時空間データを周波数領域データに変換する。次にその周波数領域データに、応答関数(Lanczos::ref_fなど)をかけてフィルターをかける。最後にフーリエ逆変換などによって、時空間データに戻す。
関数
主な関数は次のようになっています。
Lanczos::weight_f( fc , n ) =>(ローパスの)重み関数を返します
- fc : カットオフ周波数
- n : 重み
Lanczos::weight_f_bp( fc1, fc2 , n ) => バンドパスの重み関数を返します
- fc1: カットイン周波数
- fc2: カットオフ周波数
- n : 重み
Lanczos::res_f( wgt, f ) => 周波数空間での応答関数を返します
- wgt: 重み関数
- f : 連続した周波数
Lanczos::bp_filter( f, fc1, fc2, n )
Lanczos::low_filter( f, fc2, n )
Lanczos::high_filter( f, fc1, n )
それぞれ、周波数空間での応答関数を返します。 中で、Lanczos::weight_f と Lanczos::res_f を呼んでいます。
ソースファイル
# -*- coding: utf-8 -*-
require 'narray'
include NMath
module Lanczos
#############
# NArray版 虚数単位 i (長さ1の配列)
I = NArray.complex(1).fill( Complex(0.0,1.0) )
module_function
# sinc function
#
# 入力
# - x (NArray)
# 出力
# - sinc (NArray)
def sinc(x)
n = x.length
n_2 = (n-1)/2
sinc=NMath::sin(PI*x)/(PI*x)
sinc[n_2]=1 if x[n_2]==0
return sinc
end
# Lanczos weight function
#
# 入力
# - fc (Float) : cut-off(or cut-in) frequency
# - n (Integer) : number of weights
# 出力
# - w (NArray) : weight function
def weight_f(fc,n)
n = n.to_i
if n%2 == 0
raise "weights number need to be odd number!\n"
end
n_2 = (n-1)/2
k = NArray.float(n).indgen!-n_2
sigma = sinc(k/n_2)
w = 2.0 * fc * sinc(2.0*fc*k) * sigma
return w
end
# Lanczos band-pass weight function
#
# 入力
# - fc1 (Float) : cut-in frequency
# - fc2 (Float) : cut-off frequency
# - n (Integer) : number of weights
# 出力
# - w (NArray) : weight function
def weight_f_bp(fc1,fc2,n)
n = n.to_i
if n%2 == 0
raise "weights number need to be odd number!\n"
end
n_2 = (n-1)/2
if n_2 < (1.3/(fc2-fc1)).ceil
raise "weights number need to be more than 2*1.3/(fc2-fc1)+1\n"
end
k = NArray.float(n).indgen!-n_2
sigma = sinc(k/n_2)
w = 2.0 * ( fc2*sinc(2.0*fc2*k) - fc1*sinc(2.0*fc1*k) ) * sigma
return w
end
# Lanczos Response function
#
# 入力
# - w (NArray) : weight function
# - f (NArray) : sequence of frequencies
# 出力
# - r (NArray) : response function
def res_f(w,f)
n = w.length
n_2 = (n-1)/2
k = NArray.complex(1,n).indgen!-n_2
w = w.reshape(1,n).to_type(NArray::COMPLEX)
r = (w*NMath::exp(I*2*PI*f*k)).sum(-1)
#p "r"
#p r
return r
end
#########
# Lanczos Band-Pass Response Function
#
# 入力
# - f (NArray) : sequence of frequencies
# - fc1 (Float) : cut-in frequency
# - fc2 (Float) : cut-off frequency
# - n (Integer) : number of weights
# 出力
# - r (NArray) : band-pass response function
def bp_filter( f, fc1, fc2, n )
w = Lanczos::weight_f_bp( fc1, fc2, n )
r = Lanczos::res_f( w, f )
return r
end
# Lanczos Low-Pass Response Function
#
# 入力
# - f (NArray) : sequence of frequencies
# - fc2 (Float) : cut-off frequency
# - n (Integer) : number of weights
# 出力
# - r (NArray) : low-pass response function
def low_filter( f, fc2, n )
w = Lanczos::weight_f( fc2, n )
r = Lanczos::res_f( w, f )
return r
end
# Lanczos High-Pass Response Function
#
# 入力
# - f (NArray) : sequence of frequencies
# - fc1 (Float) : cut-in frequency
# - n (Integer) : number of weights
# 出力
# - r (NArray) : high-pass response function
def high_filter( f, fc1, n )
w = Lanczos::weight_f( fc1, n )
r = 1-Lanczos::res_f( w, f )
return r
end
#########
end
##########################################################
# メイン
if $0 == __FILE__
require 'numru/dcl'
include NumRu
#< 引数解釈 >
fc1 = ARGV[0] ? ARGV[0].to_f : 0.2
fc2 = ARGV[1] ? ARGV[1].to_f : 0.3
n = ARGV[2] ? ARGV[2].to_i : 43
#< f >
m = 365*2
f = NArray.sfloat(m).indgen/m.to_f
fN = 1.0/2.0 # Nyquist frequency
DCL.gropn 1
DCL.grfrm
DCL.grsvpt 0.2,0.8,0.2,0.8
DCL.grswnd 0.0,1.0,-0.2,1.1
DCL.grstrn 1
DCL.grstrf
DCL.usdaxs
# idealized filter response
DCL.uulinz [0.0,fc1],[0.0,0.0],1,23
DCL.uulinz [fc1,fc2],[1.0,1.0],1,23
DCL.uulinz [fc2,fN],[0.0,0.0],1,23
DCL.uulinz [fc1,fc1],[0.0,1.0],3,21
DCL.uulinz [fc2,fc2],[0.0,1.0],3,21
r = Lanczos::bp_filter( f, fc1, fc2, n )
r_low = Lanczos::low_filter( f, fc2, n )
r_high = Lanczos::high_filter( f, fc1, n )
# Lanczos filter
DCL.uulinz f,r,1,3
DCL.uxsttl 't',"n=#{n}",-1
#}
DCL.grcls
end
参考文献
Duchon, C. E. (1979). Lanczos filtering in one and two dimensions. Journal of Applied Meteorology, 18, 1016-1022.
伊藤久徳、見延庄士郎. (2010). 気象学と海洋物理学で用いられるデータ解析法, 気象研究ノート第221号. 日本気象学会.
キーワード:[解析] [時系列フィルター]
参照:[(Library) Butterworthローパスフィルター]