Skip to content

Commit e2e0803

Browse files
authored
Merge pull request #2024 from UV-CDAT/issue_1776_vert_interp_accept_axis_Arg
fix #1776
2 parents 1ccc830 + 9b4ce01 commit e2e0803

1 file changed

Lines changed: 164 additions & 128 deletions

File tree

Lib/vertical.py

Lines changed: 164 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44
import cdms2
55
import numpy
66
import cdat_info
7-
def reconstructPressureFromHybrid(ps,A,B,Po):
7+
8+
9+
def reconstructPressureFromHybrid(ps, A, B, Po):
810
"""
911
Reconstruct the Pressure field on sigma levels, from the surface pressure
10-
12+
1113
Input
1214
Ps : Surface pressure
1315
A,B,Po: Hybrid Convertion Coefficients, such as: p=B.ps+A.Po
1416
Ps: surface pressure
1517
B,A are 1D : sigma levels
1618
Po and Ps must have same units
17-
19+
1820
Output
1921
Pressure field
2022
Such as P=B*Ps+A*Po
@@ -23,200 +25,234 @@ def reconstructPressureFromHybrid(ps,A,B,Po):
2325
P=reconstructPressureFromHybrid(ps,A,B,Po)
2426
"""
2527
# Compute the pressure for the sigma levels
26-
cdat_info.pingPCMDIdb("cdat","cdutil.vertical.reconstructPressureFromHybrid")
27-
ps,B=genutil.grower(ps,B)
28-
ps,A=genutil.grower(ps,A)
29-
p=ps*B
30-
p=p+A*Po
28+
cdat_info.pingPCMDIdb(
29+
"cdat",
30+
"cdutil.vertical.reconstructPressureFromHybrid")
31+
ps, B = genutil.grower(ps, B)
32+
ps, A = genutil.grower(ps, A)
33+
p = ps * B
34+
p = p + A * Po
3135
p.setAxisList(ps.getAxisList())
32-
p.id='P'
36+
p.id = 'P'
3337
try:
34-
p.units=ps.units
38+
p.units = ps.units
3539
except:
36-
pass
37-
t=p.getTime()
40+
pass
41+
t = p.getTime()
3842
if not t is None:
39-
p=p(order='tz...')
43+
p = p(order='tz...')
4044
else:
41-
p=p(order='z...')
45+
p = p(order='z...')
4246
return p
43-
44-
def linearInterpolation(A,I,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000], status=None):
47+
48+
49+
def linearInterpolation(
50+
A, I, levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000,
51+
30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000], status=None, axis='z'):
4552
"""
4653
Linear interpolation
4754
to interpolate a field from some levels to another set of levels
4855
Value below "surface" are masked
49-
56+
5057
Input
5158
A : array to interpolate
5259
I : interpolation field (usually Pressure or depth) from TOP (level 0) to BOTTOM (last level), i.e P value going up with each level
5360
levels : levels to interplate to (same units as I), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]
61+
axis: axis over which to do the linear interpolation, default is 'z', accepted: '1' '(myaxis)'
5462
5563
I and levels must have same units
5664
5765
Output
5866
array on new levels (levels)
59-
67+
6068
Examples:
6169
A=interpolate(A,I,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000])
6270
"""
63-
64-
cdat_info.pingPCMDIdb("cdat","cdutil.vertical.linearInterpolation")
71+
72+
cdat_info.pingPCMDIdb("cdat", "cdutil.vertical.linearInterpolation")
6573
try:
66-
nlev=len(levels) # Number of pressure levels
74+
nlev = len(levels) # Number of pressure levels
6775
except:
68-
nlev=1 # if only one level len(levels) would breaks
69-
levels=[levels,]
70-
order=A.getOrder()
71-
A=A(order='z...')
72-
I=I(order='z...')
73-
sh=list(I.shape)
74-
nsigma=sh[0] #number of sigma levels
75-
sh[0]=nlev
76-
t=MV2.zeros(sh,typecode=MV2.float32)
77-
sh2=I[0].shape
78-
prev=-1
79-
for ilev in range(nlev): # loop through pressure levels
76+
nlev = 1 # if only one level len(levels) would breaks
77+
levels = [levels, ]
78+
order = A.getOrder()
79+
A = A(order='%s...' % axis)
80+
I = I(order='%s...' % axis)
81+
sh = list(I.shape)
82+
nsigma = sh[0] # number of sigma levels
83+
sh[0] = nlev
84+
t = MV2.zeros(sh, typecode=MV2.float32)
85+
sh2 = I[0].shape
86+
prev = -1
87+
for ilev in range(nlev): # loop through pressure levels
8088
if status is not None:
81-
prev=genutil.statusbar(ilev,nlev-1.,prev)
82-
lev=levels[ilev] # get value for the level
83-
Iabv=MV2.ones(sh2,MV2.float)
84-
Aabv=-1*Iabv # Array on sigma level Above
85-
Abel=-1*Iabv # Array on sigma level Below
86-
Ibel=-1*Iabv # Pressure on sigma level Below
87-
Iabv=-1*Iabv # Pressure on sigma level Above
88-
Ieq=MV2.masked_equal(Iabv,-1) # Area where Pressure == levels
89-
for i in range(1,nsigma): # loop from second sigma level to last one
90-
a = MV2.greater_equal(I[i], lev) # Where is the pressure greater than lev
91-
b = MV2.less_equal(I[i-1],lev) # Where is the pressure less than lev
89+
prev = genutil.statusbar(ilev, nlev - 1., prev)
90+
lev = levels[ilev] # get value for the level
91+
Iabv = MV2.ones(sh2, MV2.float)
92+
Aabv = -1 * Iabv # Array on sigma level Above
93+
Abel = -1 * Iabv # Array on sigma level Below
94+
Ibel = -1 * Iabv # Pressure on sigma level Below
95+
Iabv = -1 * Iabv # Pressure on sigma level Above
96+
Ieq = MV2.masked_equal(Iabv, -1) # Area where Pressure == levels
97+
for i in range(1, nsigma): # loop from second sigma level to last one
98+
a = MV2.greater_equal(
99+
I[i],
100+
lev) # Where is the pressure greater than lev
101+
b = MV2.less_equal(
102+
I[i - 1],
103+
lev) # Where is the pressure less than lev
92104
# Now looks if the pressure level is in between the 2 sigma levels
93105
# If yes, sets Iabv, Ibel and Aabv, Abel
94-
a=MV2.logical_and(a,b)
95-
Iabv=MV2.where(a,I[i],Iabv) # Pressure on sigma level Above
96-
Aabv=MV2.where(a,A[i],Aabv) # Array on sigma level Above
97-
Ibel=MV2.where(a,I[i-1],Ibel) # Pressure on sigma level Below
98-
Abel=MV2.where(a,A[i-1],Abel) # Array on sigma level Below
99-
Ieq= MV2.where(MV2.equal(I[i],lev),A[i],Ieq)
100-
101-
val=MV2.masked_where(MV2.equal(Ibel,-1.),numpy.ones(Ibel.shape)*lev) # set to missing value if no data below lev if there is
102-
103-
tl=(val-Ibel)/(Iabv-Ibel)*(Aabv-Abel)+Abel # Interpolation
106+
a = MV2.logical_and(a, b)
107+
Iabv = MV2.where(a, I[i], Iabv) # Pressure on sigma level Above
108+
Aabv = MV2.where(a, A[i], Aabv) # Array on sigma level Above
109+
Ibel = MV2.where(
110+
a,
111+
I[i - 1],
112+
Ibel) # Pressure on sigma level Below
113+
Abel = MV2.where(a, A[i - 1], Abel) # Array on sigma level Below
114+
Ieq = MV2.where(MV2.equal(I[i], lev), A[i], Ieq)
115+
116+
val = MV2.masked_where(
117+
MV2.equal(Ibel, -1.), numpy.ones(Ibel.shape) * lev)
118+
# set to missing value if no data below lev if
119+
# there is
120+
121+
tl = (val - Ibel) / (Iabv - Ibel) * \
122+
(Aabv - Abel) + Abel # Interpolation
104123
if ((Ieq.mask is None) or (Ieq.mask is MV2.nomask)):
105-
tl=Ieq
124+
tl = Ieq
106125
else:
107-
tl=MV2.where(1-Ieq.mask,Ieq,tl)
108-
t[ilev]=tl.astype(MV2.float32)
126+
tl = MV2.where(1 - Ieq.mask, Ieq, tl)
127+
t[ilev] = tl.astype(MV2.float32)
109128

110-
ax=A.getAxisList()
111-
autobnds=cdms2.getAutoBounds()
129+
ax = A.getAxisList()
130+
autobnds = cdms2.getAutoBounds()
112131
cdms2.setAutoBounds('off')
113-
lvl=cdms2.createAxis(MV2.array(levels).filled())
132+
lvl = cdms2.createAxis(MV2.array(levels).filled())
114133
cdms2.setAutoBounds(autobnds)
115134
try:
116-
lvl.units=I.units
135+
lvl.units = I.units
117136
except:
118137
pass
119-
lvl.id='plev'
120-
138+
lvl.id = 'plev'
139+
121140
try:
122-
t.units=I.units
141+
t.units = I.units
123142
except:
124-
pass
125-
126-
ax[0]=lvl
143+
pass
144+
145+
ax[0] = lvl
127146
t.setAxisList(ax)
128-
t.id=A.id
147+
t.id = A.id
129148
for att in A.listattributes():
130-
setattr(t,att,getattr(A,att))
149+
setattr(t, att, getattr(A, att))
131150
return t(order=order)
132151

133-
def logLinearInterpolation(A,P,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000],status=None):
152+
153+
def logLinearInterpolation(
154+
A, P, levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000,
155+
30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000], status=None, axis='z'):
134156
"""
135157
Log-linear interpolation
136158
to convert a field from sigma levels to pressure levels
137159
Value below surface are masked
138-
160+
139161
Input
140-
A : array on sigma levels
141-
P : pressure field from TOP (level 0) to BOTTOM (last level)
162+
A : array on sigma levels
163+
P : pressure field from TOP (level 0) to BOTTOM (last level)
142164
levels : pressure levels to interplate to (same units as P), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]
165+
axis: axis over which to do the linear interpolation, default is 'z', accepted: '1' '(myaxis)'
143166
144167
P and levels must have same units
145168
146169
Output
147170
array on pressure levels (levels)
148-
171+
149172
Examples:
150173
A=logLinearInterpolation(A,P),levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000])
151174
"""
152-
153-
cdat_info.pingPCMDIdb("cdat","cdutil.vertical.logLinearInterpolation")
175+
176+
cdat_info.pingPCMDIdb("cdat", "cdutil.vertical.logLinearInterpolation")
154177
try:
155-
nlev=len(levels) # Number of pressure levels
178+
nlev = len(levels) # Number of pressure levels
156179
except:
157-
nlev=1 # if only one level len(levels) would breaks
158-
levels=[levels,]
159-
order=A.getOrder()
160-
A=A(order='z...')
161-
P=P(order='z...')
162-
sh=list(P.shape)
163-
nsigma=sh[0] #number of sigma levels
164-
sh[0]=nlev
165-
t=MV2.zeros(sh,typecode=MV2.float32)
166-
sh2=P[0].shape
167-
prev=-1
168-
for ilev in range(nlev): # loop through pressure levels
180+
nlev = 1 # if only one level len(levels) would breaks
181+
levels = [levels, ]
182+
order = A.getOrder()
183+
A = A(order='%s...' % axis)
184+
P = P(order='%s...' % axis)
185+
sh = list(P.shape)
186+
nsigma = sh[0] # number of sigma levels
187+
sh[0] = nlev
188+
t = MV2.zeros(sh, typecode=MV2.float32)
189+
sh2 = P[0].shape
190+
prev = -1
191+
for ilev in range(nlev): # loop through pressure levels
169192
if status is not None:
170-
prev=genutil.statusbar(ilev,nlev-1.,prev)
171-
lev=levels[ilev] # get value for the level
172-
Pabv=MV2.ones(sh2,MV2.float)
173-
Aabv=-1*Pabv # Array on sigma level Above
174-
Abel=-1*Pabv # Array on sigma level Below
175-
Pbel=-1*Pabv # Pressure on sigma level Below
176-
Pabv=-1*Pabv # Pressure on sigma level Above
177-
Peq=MV2.masked_equal(Pabv,-1) # Area where Pressure == levels
178-
for i in range(1,nsigma): # loop from second sigma level to last one
179-
a=MV2.greater_equal(P[i], lev) # Where is the pressure greater than lev
180-
b= MV2.less_equal(P[i-1],lev) # Where is the pressure less than lev
193+
prev = genutil.statusbar(ilev, nlev - 1., prev)
194+
lev = levels[ilev] # get value for the level
195+
Pabv = MV2.ones(sh2, MV2.float)
196+
Aabv = -1 * Pabv # Array on sigma level Above
197+
Abel = -1 * Pabv # Array on sigma level Below
198+
Pbel = -1 * Pabv # Pressure on sigma level Below
199+
Pabv = -1 * Pabv # Pressure on sigma level Above
200+
Peq = MV2.masked_equal(Pabv, -1) # Area where Pressure == levels
201+
for i in range(1, nsigma): # loop from second sigma level to last one
202+
a = MV2.greater_equal(
203+
P[i],
204+
lev) # Where is the pressure greater than lev
205+
b = MV2.less_equal(
206+
P[i - 1],
207+
lev) # Where is the pressure less than lev
181208
# Now looks if the pressure level is in between the 2 sigma levels
182209
# If yes, sets Pabv, Pbel and Aabv, Abel
183-
a=MV2.logical_and(a,b)
184-
Pabv=MV2.where(a,P[i],Pabv) # Pressure on sigma level Above
185-
Aabv=MV2.where(a,A[i],Aabv) # Array on sigma level Above
186-
Pbel=MV2.where(a,P[i-1],Pbel) # Pressure on sigma level Below
187-
Abel=MV2.where(a,A[i-1],Abel) # Array on sigma level Below
188-
Peq= MV2.where(MV2.equal(P[i],lev),A[i],Peq)
189-
190-
val=MV2.masked_where(MV2.equal(Pbel,-1),numpy.ones(Pbel.shape)*lev) # set to missing value if no data below lev if there is
191-
192-
tl=MV2.log(val/Pbel)/MV2.log(Pabv/Pbel)*(Aabv-Abel)+Abel # Interpolation
210+
a = MV2.logical_and(a, b)
211+
Pabv = MV2.where(a, P[i], Pabv) # Pressure on sigma level Above
212+
Aabv = MV2.where(a, A[i], Aabv) # Array on sigma level Above
213+
Pbel = MV2.where(
214+
a,
215+
P[i - 1],
216+
Pbel) # Pressure on sigma level Below
217+
Abel = MV2.where(a, A[i - 1], Abel) # Array on sigma level Below
218+
Peq = MV2.where(MV2.equal(P[i], lev), A[i], Peq)
219+
220+
val = MV2.masked_where(
221+
MV2.equal(Pbel, -1), numpy.ones(Pbel.shape) * lev)
222+
# set to missing value if no data below lev if
223+
# there is
224+
225+
tl = MV2.log(
226+
val / Pbel) / MV2.log(
227+
Pabv / Pbel) * (
228+
Aabv - Abel) + Abel # Interpolation
193229
if ((Peq.mask is None) or (Peq.mask is MV2.nomask)):
194-
tl=Peq
230+
tl = Peq
195231
else:
196-
tl=MV2.where(1-Peq.mask,Peq,tl)
197-
t[ilev]=tl.astype(MV2.float32)
198-
199-
ax=A.getAxisList()
200-
autobnds=cdms2.getAutoBounds()
232+
tl = MV2.where(1 - Peq.mask, Peq, tl)
233+
t[ilev] = tl.astype(MV2.float32)
234+
235+
ax = A.getAxisList()
236+
autobnds = cdms2.getAutoBounds()
201237
cdms2.setAutoBounds('off')
202-
lvl=cdms2.createAxis(MV2.array(levels).filled())
238+
lvl = cdms2.createAxis(MV2.array(levels).filled())
203239
cdms2.setAutoBounds(autobnds)
204240
try:
205-
lvl.units=P.units
241+
lvl.units = P.units
206242
except:
207243
pass
208-
lvl.id='plev'
209-
244+
lvl.id = 'plev'
245+
210246
try:
211-
t.units=P.units
247+
t.units = P.units
212248
except:
213-
pass
214-
215-
ax[0]=lvl
249+
pass
250+
251+
ax[0] = lvl
216252
t.setAxisList(ax)
217-
t.id=A.id
253+
t.id = A.id
218254
for att in A.listattributes():
219-
setattr(t,att,getattr(A,att))
255+
setattr(t, att, getattr(A, att))
220256
return t(order=order)
221-
222-
sigma2Pressure=logLinearInterpolation
257+
258+
sigma2Pressure = logLinearInterpolation

0 commit comments

Comments
 (0)