(Tips) パワースペクトルの波数・周波数分布の作り方
作成者: 西本絵梨子
編集履歴
- 2014年2月14日: 新規作成。
- 2014年2月28日: GPhys::FFTのコマンドをさらに活用する方法について追記。
- 2014年3月17日: データの前処理(特定の周期を除去)についてのサンプルプログラムを追加。
- 2014年6月 3日: パワースペクトル密度の定義を一般的なものに変更。それに伴い、wavenum_freq.rbとwavenum_freq_2.rbを変更。
概要
熱帯OLRのパワースペクトルを計算して、波数・周波数空間でのパワースペクトル分布を描くサンプルプログラムです。 Wheeler and Kiladis (1999) JASの図1のようなものを描きます。
計算手順
1980年1月から2010年12月までのNOAA/OLR日平均データを使用。 データは次のサイトから入手できる:NOAA/OLR
- あらかじめ、365日、182.5日、122日の周期成分をデータから除去しておく。 (サンプルプログラム:remove_AC.rb)
赤道対称・反対称分離操作をほどこす。
赤道対称成分: OLRsym=(OLR(x,y,t)+OLR(x,-y,t))/2.0 赤道反対称成分: OLRasym=(OLR(x,y,t)-OLR(x,-y,t))/2.0
- GPhys::FFTをつかって、月ごとにフーリエ変換を経度・時間方向にほどこし、パワースペクトルを得る。このとき、その月のデータとして月開始の30日前から92日分のデータを使用する。

- 各月のパワースペクトルを足し合わして平均する。(平滑化)
- 東進成分と西進成分に分ける。k>0として、w>0が西進、w<0が東進。
- x(i) (i=0,1,..,N-1)のFFTの結果には、i=0,1,...,[N/2-1]まではx(i)のフーリエ変換X(i)が入っているが、残りi=N/2,..N-1にはX(N-i+1)が入っている。
- GPhys::FFTだと、時間方向のFFT成分の、前半分は西進成分が入っていて、後半分には東進成分が後ろから入っていると考えればよい。
ダウンロード
ソースコード
サンプル2
#
# draw the wavenumber-frequency diagram
# like Fig.1 of Wheeler and Kiladis [1999] JAS
# using GPhys::FFT
#
#-- create: 28 Feb. 2014 Eriko Nishimoto
#-- modified: 03 Jun. 2014 Eriko Nishimoto
#
require "numru/ggraph"
include NumRu
pi=Math::PI
type="sym"
type="antisym"
#-----------------------------settings
monlist=NArray.int(12).indgen(1,1)
#yrlist=NArray.int(30).indgen+1980
yrlist=NArray.int(5).indgen+1980
nperiod=92
#-----------------------------open data
#-- daily OLR data removed the cycles of 365days, 182.5days, 122days
dir="/raid/sup1/data/NOAAOLR/FFT/NetCDF/"
fname="daily_rmAC.nc"
var="olr_detrend"
slat, elat=-15, 15
dum=GPhys::IO.open(dir+fname,var).cut(true,slat..elat,true)
#-----------------------------make data
#-- components of antisymmetric and symmetric about the equator
nx,ny,nt=dum.shape
mask=NArray.int(ny).indgen(-1,-1)+ny
if type=="sym"
#-----------------------------symmetric component
#-- (a(x,y,t)+a(x,-y,t))/2
tmp=(dum+dum[true,mask,true])/2.0
figtitle="LOG10{ POWER(OLR S) }"
elsif type=="antisym"
#-----------------------------antisymmetric component
#-- (a(x,y,t)-a(x,-y,t))/2
tmp=(dum-dum[true,mask,true])/2.0
figtitle="LOG10{ POWER(OLR A) }"
end
#-----------------------------FFT
nx=tmp.shape[0]
nx_2,nt_2=nx/2,nperiod/2
ps=NArray.float(nx,nperiod).fill(0)
fc=[]
yrlist.each{|yr|
monlist.each{|mn|
#----------------------use data of nperiod
st=Date.parse("#{yr}-#{mn}-01")-30
et=st+nperiod-1
data=tmp.cut(false,st..et)
nx,ny,nt=data.shape
#----------------------foward FFT
GPhys::fft_ignore_missing(true)
fc=data.fft(false,0,2).mean(1)
#----------------------change axes
z0=fc.axis(0).pos
fc.axis(0).set_pos(-z0)
z1=fc.axis(-1).pos.convert_units("day-1")/(2.0*pi)
fc.axis(-1).set_pos(z1)
#----------------------power spectral
#-- |fc|^2
power=(fc.abs**2).val
ps+=power/monlist.length/yrlist.length
}
}
power=fc.copy.replace_val(ps).rawspect2powerspect(0,-1)\
.spect_zero_centering(0).spect_one_sided(-1)
p power.units
#====================================draw
#--settings
colormap = 8
psname = "Fig/"+$0.split('.')[0]+"_#{type}"
p psname
#--
DCL.sgscmn(colormap)
DCL.swcset 'fname',psname
iws = (ARGV[0]||(puts 'Workstation ID(I)?'; DCL.sgpwsn; gets)).to_i
DCL.gropn iws
DCLExt.sg_set_params 'lcntl'=>false
DCLExt.uz_set_params 'indext1'=>3,'indext2'=>5\
,'indexl1'=>5,'indexl2'=>5,'inner'=>-1
GGraph.set_fig "viewport"=>[0.08,0.92,0.2,0.8]
GGraph.set_axes "xunits"=>"","yunits"=>""\
,"xtitle"=>"wave number","ytitle"=>"frequency (1/day)"
GGraph.tone power.log10.cut(-15..15,0..0.5),true\
,"annot"=>false,"title"=>figtitle
GGraph.color_bar "landscape"=>true
DCL.grcls
参考文献
- Wheeler, M., and G. N. Kiladis, 1999: Convectively Coupled Equatorial Waves: Analysis of Clouds and Temperature in the Wavenumber--Frequency Domain. J. Atmos. Sci., 56, 374-399.
- 林良一, 1980: 最近の時空間スペクトル解析法の発展と大気大規模波動への応用. 天気, 27, 3-21.


キーワード:[FFT]
参照:[(Tips) パワースペクトルの波数・周波数分布(2)]