一般情况下NCL自带的month_to_season可以将月数据计算为季节数据
近期需要计算每两个月的月数据,故在month_to_season的基础上修改代码,以计算每两个月的月数据
首先建立一个新的“season”
season = (/"DJ","JF","FM","MA","AM","MJ","JJ" \
,"JA","AS","SO","ON","ND" /)
其中month_to_season原代码中主要是采用滑动平均的方法来计算每三个月的平均
因此主要改动地方在第一个量和最后一个变量的计算
例如
if (NMO.eq.0) then
n = 0
xSea(0) = xMon(n)
end if
if (NMO.eq.nmos-1) then
n = (nyrs-1)*nmos + NMO
xSea(nyrs-1) = (xMon(n) + xMon(n-1))*0.5
end if
其余则主要将1/3改成1/2
非常简单
全部代码如下:
month_to_season2.ncl
计算2个月的平均,采用滑动
undef ("month_to_season2")
function month_to_season2 (xMon:numeric, SEASON:string)
local season,NMO,dimx,rank,ntim,nlat,mlon,nmos,nyrs,con \
, nyrStrt,nyrLast,nyr,n,xSea, klev, dName,cv,xSea
begin
season = (/"DJ","JF","FM","MA","AM","MJ","JJ" \
,"JA","AS","SO","ON","ND" /)
;找到对应的season
NMO = ind(season.eq.SEASON) ; index corresponding to season
if (ismissing(NMO)) then
print ("contributed: month_to_season2: bad season: SEASON="+SEASON)
exit
end if
;每一维的数量以及包含几维
dimx = dimsizes(xMon)
rank = dimsizes(dimx)
if (rank.eq.2 .or. rank.ge.5) then
print ("contributed: month_to_season: rank="+rank)
print ("----- rank currently not handled -----")
end if
nmos = 12
ntim = dimx(0)
modCheck ("month_to_season2", ntim, nmos)
;lat和lon的数量
if (rank.ge.3) then
nlat = dimx(rank-2)
mlon = dimx(rank-1)
end if
;有多少年
nyrs = ntim/nmos
con = 1./2.
nyrStrt = 0
nyrLast = nyrs-1
if (NMO.eq.0) then
nyrStrt = 1
end if
if (NMO.eq.nmos-1) then
nyrLast = nyrs-2
end if
if (rank.eq.1) then
xSea = new ( nyrs, typeof(xMon), getFillValue(xMon))
do nyr=nyrStrt,nyrLast
n = nyr*nmos + NMO
xSea(nyr) = (xMon(n-1) + xMon(n))*con
end do
; special for beginning/end points
if (NMO.eq.0) then
n = 0
xSea(0) = xMon(n)
end if
if (NMO.eq.nmos-1) then
n = (nyrs-1)*nmos + NMO
xSea(nyrs-1) = (xMon(n) + xMon(n-1))*0.5
end if
end if
if (rank.eq.3) then
xSea = new ( (/nyrs,nlat,mlon/), typeof(xMon), getFillValue(xMon))
do nyr=nyrStrt,nyrLast
n = nyr*nmos + NMO
xSea(nyr,:,:) = (xMon(n-1,:,:) + xMon(n,:,:))*con
end do
; special for beginning/end points
if (NMO.eq.0) then
n = 0
xSea(0,:,:) = xMon(n,:,:)
end if
if (NMO.eq.nmos-1) then
n = (nyrs-1)*nmos + NMO
xSea(nyrs-1,:,:) = (xMon(n,:,:) + xMon(n-1,:,:))*0.5
end if
end if
if (rank.eq.4) then
klev = dimx(1)
xSea = new ( (/nyrs,klev,nlat,mlon/), typeof(xMon), getFillValue(xMon))
do nyr=nyrStrt,nyrLast
n = nyr*nmos + NMO
xSea(nyr,:,:,:) = (xMon(n-1,:,:,:) + xMon( n ,:,:,:))*0.5
end do
if (NMO.eq.0) then
n = 0
xSea(0,:,:,:) = xMon(n,:,:,:)
end if
if (NMO.eq.nmos-1) then
n = (nyrs-1)*nmos + NMO
xSea(nyrs-1,:,:,:) = (xMon(n,:,:,:) + xMon(n-1,:,:,:))*0.5
end if
end if
copy_VarAtts (xMon, xSea)
if (isatt(xMon,"long_name") .or. isatt(xMon,"description") .or. \
isatt(xMon,"standard_name") ) then
xSea@long_name = SEASON+": "+getLongName(xMon)
end if
do n=1,rank-1 ; copy spatial coordinates
if (.not.ismissing(xMon!n)) then
xSea!n = xMon!n
if(iscoord(xMon,xMon!n))
xSea&$xSea!n$ = xMon&$xMon!n$
end if
end if
end do
;n = 0 ; special coordinate for time
;xSea!n = "year"
;if (iscoord(xMon,xMon!n))
; xSea&$xSea!n$ = xMon&$xMon!n$(NMO:ntim-1:nmos)
;end if
dName = xMon!0
xSea!0 = dName
if(iscoord(xMon,dName)) then
cv = xMon&$dName$(NMO:ntim-1:nmos)
; possibly override
;if (isatt(cv,"units") .and. \
; (cv@units.eq."YYYYMM" .or. cv@units.eq."YYMM")) then
; cv = cv/100
; cv@units = "YYYY"
;end if
;if (isatt(cv,"units") .and. cv@units.eq."YYYYMMDD") then
; cv = cv/10000
; cv@units = "YYYY"
;end if
xSea&$dName$ = cv
end if
xSea@NMO = NMO ; for possible use in subscripting
; eg: nStrt= xSea@NMO ; time(nStrt:ntim-1,12)
return (xSea)
end