利用NCL做FFT-頻譜分析#
Example 1: 菲律賓中部 (9˚-14˚N, 122˚-127˚E) 在DJF季節區域平均降雨的頻譜分析。
;*************************************************
; spec_3.ncl
;
; Concepts illustrated:
; - Calculating confidence intervals
;************************************************
;
; These files are loaded by default in NCL V6.2.0 and newer
; load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"
; load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl"
; load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/contributed.ncl"
;
; This file still has to be loaded manually
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/shea_util.ncl"
;************************************************
begin
;************************************************
; variable and file handling
;************************************************
fn = "./data/cmorph_sample.nc" ; define filename
in = addfile(fn,"r") ; open netcdf file
pcp = in->cmorph(:,{9:14},{122:127})
pcpm = dim_avg_n_Wrap(dim_avg_n_Wrap(pcp, 2), 1)
Cell In[1], line 1
*************************************************("")
^
SyntaxError: invalid syntax
NCL的時間格式必須是yyyymmdd,我們要先做一些轉換。
rtime = pcpm&time
delete(pcpm&time)
pcpm!0 = "time"
pcpm&time = cd_calendar(rtime,2)
接下來一年一年進行頻譜分析,然後再對年做平均。
;************************************************
; set function arguments
;************************************************
d = 0 ; detrending opt: 0=>remove mean 1=>remove mean + detrend
sm = 1 ; smooth: should be at least 3 and odd
pct = 0.10 ; percent taper: (0.0 <= pct <= 1.0) 0.10 common.
ys = 1998 ; Start year
ye = 2020 ; End year
ntim = 90 ; # of days in DJF
;************************************************
; calculate mean spectrum spectrum and lag1 auto cor
;************************************************
; loop over each segment of length ntim
spcavg = new ( ntim/2, typeof(pcpm))
spcavg = 0.0
r1zsum = 0.0
do yy = ys, ye
time1 = yy *10000 + 1201
time2 = (yy+1)*10000 + 228
pcp_5d_ave = runave_n_Wrap(pcpm({time1:time2}), 5, 1, 0)
dof = specx_anal(pcp_5d_ave,d,sm,pct) ; current segment spc
spcavg = spcavg + dof@spcx ; sum spc of each segment
r1 = dof@xlag1 ; extract segment lag-1
r1zsum = r1zsum + 0.5*(log((1+r1)/(1-r1))) ; sum the Fischer Z
end do
r1z = r1zsum/(ye-ys+1) ; average r1z
r1 = (exp(2*r1z)-1)/(exp(2*r1z)+1) ; transform back
; this is the mean r1
spcavg = spcavg/(ye-ys+1) ; average spectrum
;************************************************
; Assign mean spectrum to data object
;************************************************
df = 2.0*(ye-ys+1) ; deg of freedom
; all segments
df@spcx = spcavg ; assign the mean spc
df@frq = dof@frq
df@xlag1= r1 ; assign mean lag-1
接下來繪圖。
;************************************************
; plotting parameters
;************************************************
wks = gsn_open_wks("png","./images/spec") ; send graphics to PNG file
r = True ; plot mods desired
r@gsnDraw = False ; do not draw
r@gsnFrame = False ; do not advance frame
r@tiMainString = "DJF Precip. @ PHL-C" ; title
r@tiXAxisString = "Period (days)" ; xaxis
r@tiYAxisString = "Variance" ; yaxis
r@trXMaxF = 80.
r@trXMinF = 5.
;************************************************
; plot
;************************************************
r@xyLineThicknesses = (/2.,1.,1.,1./) ; Define line thicknesses
r@xyDashPatterns = (/0,0,1,1/) ; Dash patterns
;***********************************************
; Plot: Generate fancier plot showing
; "red noise" confidence bounds
; (a) solid for spectrum and Markov,
; (b) dash for bounds
;***********************************************
p = 1/df@frq ; *highly non-linear*
p!0 = "f"
p&f = df@frq
p@long_name = "period"
p@units = "day"
ip = ind(p.le.90 .and. p.ge.5) ; all indices for "short" periods
splt = specx_ci(df, 0.05, 0.95) ; calc confidence interval
plot = gsn_csm_xy(wks,p(ip), splt(:,ip),r)
draw(plot)
frame(wks)
end