iconPlot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/contrib/nclsh +276 -0
- data/gemspec +19 -0
- data/lib/iconPlot.rb +68 -0
- data/lib/icon_plot.ncl +653 -0
- data/lib/icon_plot_lib.ncl +1687 -0
- data/test/test_iconPlot.rb +33 -0
- metadata +52 -0
@@ -0,0 +1,1687 @@
|
|
1
|
+
;---------------------------------------------------------------
|
2
|
+
; ICON PLOT LIB
|
3
|
+
; This library aimes to provide an abstract way to access and plot ICON data
|
4
|
+
; fields from NetCDF files. It should obay some general requirements:
|
5
|
+
; * Don-Repeat-Yourself-principle: Every method has one responsebility, which no
|
6
|
+
; other method has. Or in other words: Don't just CopyAndPaste.
|
7
|
+
; * Use as much information from the input files as possible. If something is
|
8
|
+
; missing, create a better file or let the user input this peace of
|
9
|
+
; information. Examples are coordinates of data variabels and bounds of them.
|
10
|
+
; There are attributes for this.
|
11
|
+
; * naming conventions:
|
12
|
+
; # check* methods are procedure which can exit the whole program
|
13
|
+
; # get* methods are functions with return, what they descibe with their
|
14
|
+
; name. This is similar to NCL itself, e.g. getfilevardims()
|
15
|
+
; # set* methods are procedures
|
16
|
+
;---------------------------------------------------------------
|
17
|
+
; Authors : Ralf Mueller (ralf.mueller@zmaw.de)
|
18
|
+
; Stephan Lorenz (stephan.lorenz@zmaw.de)
|
19
|
+
;-------------------------------------------------------------------------------
|
20
|
+
; some global defaults
|
21
|
+
DEFAULTLON = "clon"
|
22
|
+
DEFAULTLAT = "clat"
|
23
|
+
RAD2DEG = 45./atan(1.)
|
24
|
+
ABORTMSG = "Abort Script."
|
25
|
+
NUMLEVS = 10
|
26
|
+
CDO = "cdo"
|
27
|
+
;-------------------------------------------------------------------------------
|
28
|
+
procedure setCDO(path)
|
29
|
+
begin
|
30
|
+
CDO=path
|
31
|
+
end
|
32
|
+
;-------------------------------------------------------------------------------
|
33
|
+
; signum function
|
34
|
+
undef("sign")
|
35
|
+
function sign(val)
|
36
|
+
begin
|
37
|
+
if (val.eq.0) then
|
38
|
+
return(1)
|
39
|
+
else
|
40
|
+
return(val/abs(val))
|
41
|
+
end if
|
42
|
+
end
|
43
|
+
;-------------------------------------------------------------------------------
|
44
|
+
; Is the 'time' variable a dimesions in the input dimensions array?
|
45
|
+
undef("has_time")
|
46
|
+
function has_time(dims)
|
47
|
+
begin
|
48
|
+
if (any(dims.eq."time")) then
|
49
|
+
return(True)
|
50
|
+
else
|
51
|
+
return(False)
|
52
|
+
end if
|
53
|
+
end
|
54
|
+
;-------------------------------------------------------------------------------
|
55
|
+
; Has the input variable the dimension 'time'?
|
56
|
+
undef("var_has_time")
|
57
|
+
function var_has_time(varname,filehandle)
|
58
|
+
begin
|
59
|
+
dims = getfilevardims(filehandle,varname)
|
60
|
+
if ( any(dims.eq."time") ) then
|
61
|
+
return(True)
|
62
|
+
else
|
63
|
+
return(False)
|
64
|
+
end if
|
65
|
+
end
|
66
|
+
;-------------------------------------------------------------------------------
|
67
|
+
; has a file a certain variable
|
68
|
+
undef("has_var")
|
69
|
+
function has_var(filehandle,varname)
|
70
|
+
begin
|
71
|
+
vNames = getfilevarnames(filehandle)
|
72
|
+
n = dimsizes (vNames)
|
73
|
+
do i=0,n-1 ; loop thru each variable
|
74
|
+
if (vNames(i).eq.varname) return True end if
|
75
|
+
end do
|
76
|
+
return False
|
77
|
+
end
|
78
|
+
;---------------------------------------------------------------
|
79
|
+
; get vertical dimension
|
80
|
+
undef("getVertDim")
|
81
|
+
function getVertDim(filehandle,var)
|
82
|
+
begin
|
83
|
+
dimNames = getvardims(var)
|
84
|
+
matches = (/"lev","depth","height","z"/)
|
85
|
+
do i=0,dimsizes(matches)-1
|
86
|
+
retval = str_match(dimNames,matches(i))
|
87
|
+
if (.not.ismissing(retval)) return retval end if
|
88
|
+
end do
|
89
|
+
return(str_match(dimNames,matches(0)))
|
90
|
+
end
|
91
|
+
;---------------------------------------------------------------
|
92
|
+
; procedure warper for array_append_record
|
93
|
+
undef("array_append_record_proc")
|
94
|
+
procedure array_append_record_proc(array,addition)
|
95
|
+
begin
|
96
|
+
arrayCopy = array_append_record(array,addition,0)
|
97
|
+
|
98
|
+
array = arrayCopy
|
99
|
+
end
|
100
|
+
;-------------------------------------------------------------------------------
|
101
|
+
; Read a horizontal field of the variable 'varname' from the given filehandle.
|
102
|
+
; If it is time dependend or has a vertival axis, use the given values for
|
103
|
+
; timstep and levelindex for selecting the field.
|
104
|
+
;
|
105
|
+
; Currently this limited to 3 dimensions, so that 4D tracer variables are ignored
|
106
|
+
undef("selIconField")
|
107
|
+
function selIconField(varname,filehandle,timestep,levelindex)
|
108
|
+
begin
|
109
|
+
dims = getfilevardims(filehandle,varname)
|
110
|
+
noOfDims = dimsizes(dims)
|
111
|
+
noOfDims = noOfDims(0)
|
112
|
+
usableVar = False
|
113
|
+
if ( has_time(dims) ) then
|
114
|
+
if (noOfDims .eq. 3) then ; dims: (time,lev,cell)
|
115
|
+
var = filehandle->$varname$(timestep,levelindex,:)
|
116
|
+
usableVar = True
|
117
|
+
end if
|
118
|
+
if (noOfDims .eq. 2) then ; dims: (time,cell)
|
119
|
+
var = filehandle->$varname$(timestep,:)
|
120
|
+
usableVar = True
|
121
|
+
end if
|
122
|
+
if (noOfDims .eq. 1) then ; dims: (time)
|
123
|
+
var = filehandle->$varname$(:)
|
124
|
+
usableVar = True
|
125
|
+
end if
|
126
|
+
else
|
127
|
+
; TODO: support for 4D tracer fields
|
128
|
+
; if (noOfDims .eq. 3) then ; dims: (lev,cell,tracerID)
|
129
|
+
; var = filehandle->$varname$(levIndex,:,tracer)
|
130
|
+
; usableVar = True
|
131
|
+
; end if
|
132
|
+
if (noOfDims .eq. 2) then ; dims: (lev,cell)
|
133
|
+
var = filehandle->$varname$(levelindex,:)
|
134
|
+
usableVar = True
|
135
|
+
end if
|
136
|
+
if (noOfDims .eq. 1) then ; dims: (cell)
|
137
|
+
var = filehandle->$varname$(:)
|
138
|
+
usableVar = True
|
139
|
+
end if
|
140
|
+
end if
|
141
|
+
if (.not. usableVar) then
|
142
|
+
print("Warning! Could not read " + varname + " from input file")
|
143
|
+
exit
|
144
|
+
end if
|
145
|
+
return var
|
146
|
+
end
|
147
|
+
;-------------------------------------------------------------------------------
|
148
|
+
; get full 3d ICON variable
|
149
|
+
undef("selIconVar")
|
150
|
+
function selIconVar(varname,filehandle,timestep)
|
151
|
+
begin
|
152
|
+
dims = getfilevardims(filehandle,varname)
|
153
|
+
noOfDims = dimsizes(dims)
|
154
|
+
noOfDims = noOfDims(0)
|
155
|
+
usableVar = False
|
156
|
+
if ( has_time(dims) ) then
|
157
|
+
if (noOfDims .eq. 3) then ; dims: (time,lev,cells)
|
158
|
+
var = filehandle->$varname$(timestep,:,:)
|
159
|
+
usableVar = True
|
160
|
+
end if
|
161
|
+
if (noOfDims .eq. 2) then ; dims: (time,cells)
|
162
|
+
var = filehandle->$varname$(timestep,:)
|
163
|
+
usableVar = True
|
164
|
+
end if
|
165
|
+
if (noOfDims .eq. 1) then ; dims: (cells)
|
166
|
+
var = filehandle->$varname$(:)
|
167
|
+
usableVar = True
|
168
|
+
end if
|
169
|
+
else
|
170
|
+
if (noOfDims .eq. 2) then ; dims: (lev,cells)
|
171
|
+
var = filehandle->$varname$(:,:)
|
172
|
+
usableVar = True
|
173
|
+
end if
|
174
|
+
if (noOfDims .eq. 1) then ; dims: (cells)
|
175
|
+
var = filehandle->$varname$(:)
|
176
|
+
usableVar = True
|
177
|
+
end if
|
178
|
+
end if
|
179
|
+
if (.not. usableVar) then
|
180
|
+
print("Warning! Could not read " + varname + " from input file")
|
181
|
+
exit
|
182
|
+
end if
|
183
|
+
return var
|
184
|
+
end
|
185
|
+
;-------------------------------------------------------------------------------
|
186
|
+
; see selIconField(), but for fields on a regular lonlat grid
|
187
|
+
undef("selRegularField")
|
188
|
+
function selRegularField(varname,filehandle,timestep,levelindex)
|
189
|
+
begin
|
190
|
+
dims = getfilevardims(filehandle,varname)
|
191
|
+
noOfDims = dimsizes(dims)
|
192
|
+
noOfDims = noOfDims(0)
|
193
|
+
usableVar = False
|
194
|
+
if ( has_time(dims) ) then
|
195
|
+
if (noOfDims .eq. 4) then ; dims: (time,lev,x,y)
|
196
|
+
var = filehandle->$varname$(timestep,levelindex,:,:)
|
197
|
+
usableVar = True
|
198
|
+
end if
|
199
|
+
if (noOfDims .eq. 3) then ; dims: (time,x,y)
|
200
|
+
var = filehandle->$varname$(timestep,:,:)
|
201
|
+
usableVar = True
|
202
|
+
end if
|
203
|
+
if (noOfDims .eq. 2) then ; dims: (x,y)
|
204
|
+
var = filehandle->$varname$(:,:)
|
205
|
+
usableVar = True
|
206
|
+
end if
|
207
|
+
if (noOfDims .eq. 1) then ; dims: (time)
|
208
|
+
var = filehandle->$varname$(:)
|
209
|
+
usableVar = True
|
210
|
+
end if
|
211
|
+
else
|
212
|
+
if (noOfDims .eq. 3) then ; dims: (lev,x,y)
|
213
|
+
var = filehandle->$varname$(levelindex,:,:)
|
214
|
+
usableVar = True
|
215
|
+
end if
|
216
|
+
if (noOfDims .eq. 2) then ; dims: (x,y)
|
217
|
+
var = filehandle->$varname$(:,:)
|
218
|
+
usableVar = True
|
219
|
+
end if
|
220
|
+
if (noOfDims .eq. 1) then ; dims: (x)
|
221
|
+
var = filehandle->$varname$(:)
|
222
|
+
usableVar = True
|
223
|
+
end if
|
224
|
+
end if
|
225
|
+
if (.not. usableVar) then
|
226
|
+
print("Warning! Could not read " + varname + " from input file")
|
227
|
+
exit
|
228
|
+
end if
|
229
|
+
return var
|
230
|
+
end
|
231
|
+
;-------------------------------------------------------------------------------
|
232
|
+
; see selRegularField(), but for 3d regular variable
|
233
|
+
undef("selRegularVar")
|
234
|
+
function selRegularVar(varname,filehandle,timestep)
|
235
|
+
begin
|
236
|
+
dims = getfilevardims(filehandle,varname)
|
237
|
+
noOfDims = dimsizes(dims)
|
238
|
+
noOfDims = noOfDims(0)
|
239
|
+
usableVar = False
|
240
|
+
if ( has_time(dims) ) then
|
241
|
+
if (noOfDims .eq. 4) then ; dims: (time,lev,x,y)
|
242
|
+
var = filehandle->$varname$(timestep,:,:,:)
|
243
|
+
usableVar = True
|
244
|
+
end if
|
245
|
+
if (noOfDims .eq. 3) then ; dims: (time,x,y)
|
246
|
+
var = filehandle->$varname$(timestep,:,:)
|
247
|
+
usableVar = True
|
248
|
+
end if
|
249
|
+
if (noOfDims .eq. 2) then ; dims: (x,y)
|
250
|
+
var = filehandle->$varname$(:,:)
|
251
|
+
usableVar = True
|
252
|
+
end if
|
253
|
+
if (noOfDims .eq. 1) then ; dims: (time)
|
254
|
+
var = filehandle->$varname$(:)
|
255
|
+
usableVar = False
|
256
|
+
end if
|
257
|
+
else
|
258
|
+
if (noOfDims .eq. 3) then ; dims: (lev,x,y)
|
259
|
+
var = filehandle->$varname$(:,:,:)
|
260
|
+
usableVar = True
|
261
|
+
end if
|
262
|
+
if (noOfDims .eq. 2) then ; dims: (x,y)
|
263
|
+
var = filehandle->$varname$(:,:)
|
264
|
+
usableVar = True
|
265
|
+
end if
|
266
|
+
if (noOfDims .eq. 1) then ; dims: (x)
|
267
|
+
var = filehandle->$varname$(:)
|
268
|
+
usableVar = True
|
269
|
+
end if
|
270
|
+
end if
|
271
|
+
if (.not. usableVar) then
|
272
|
+
print("Warning! Could not read " + varname + " from input file")
|
273
|
+
exit
|
274
|
+
end if
|
275
|
+
return var
|
276
|
+
end
|
277
|
+
;-------------------------------------------------------------------------------
|
278
|
+
; abstract Field selection
|
279
|
+
undef("selField")
|
280
|
+
function selField(varname,filehandle,timestep,levelindex,horizontalgridtype)
|
281
|
+
begin
|
282
|
+
if ( horizontalgridtype .eq. "unstructured") then
|
283
|
+
var = selIconField(varname,filehandle,timestep,levelindex)
|
284
|
+
else
|
285
|
+
var = selRegularField(varname,filehandle,timestep,levelindex)
|
286
|
+
end if
|
287
|
+
return var
|
288
|
+
end
|
289
|
+
;-------------------------------------------------------------------------------
|
290
|
+
; scale the given variable with the given factor, if it is NOT 1
|
291
|
+
undef("scaleVar")
|
292
|
+
procedure scaleVar(var,scalefactor)
|
293
|
+
local scalefactor
|
294
|
+
begin
|
295
|
+
if (scalefactor .ne. 1) then
|
296
|
+
var = var*scalefactor
|
297
|
+
end if
|
298
|
+
end
|
299
|
+
;-------------------------------------------------------------------------------
|
300
|
+
; Return the grid type of a given ICON variable (cell, vertex, or edge).
|
301
|
+
; This is based on the naming of the coordinates.
|
302
|
+
undef("getGridType")
|
303
|
+
function getGridType(variable)
|
304
|
+
begin
|
305
|
+
str = variable@coordinates
|
306
|
+
gtype = stringtocharacter(str)
|
307
|
+
if (gtype(0) .eq. "c") then
|
308
|
+
str = "cell"
|
309
|
+
end if
|
310
|
+
if (gtype(0) .eq. "e") then
|
311
|
+
str = "edge"
|
312
|
+
end if
|
313
|
+
if (gtype(0) .eq. "v") then
|
314
|
+
str = "vertex"
|
315
|
+
end if
|
316
|
+
return str
|
317
|
+
end
|
318
|
+
;-------------------------------------------------------------------------------
|
319
|
+
; Return the size of coordinates
|
320
|
+
undef("getCoordSizes")
|
321
|
+
function getCoordSizes(variable,filehandle)
|
322
|
+
begin
|
323
|
+
lonlat = str_split(variable@coordinates," ")
|
324
|
+
lon = lonlat(0)
|
325
|
+
lat = lonlat(1)
|
326
|
+
lonSize = dimsizes(filehandle->$lon$)
|
327
|
+
latSize = dimsizes(filehandle->$lat$)
|
328
|
+
|
329
|
+
return (/lonSize,latSize/)
|
330
|
+
end
|
331
|
+
;-------------------------------------------------------------------------------
|
332
|
+
; Return the coordinates of a given variable in radians
|
333
|
+
undef("getCoordinates")
|
334
|
+
function getCoordinates(variable,filehandle)
|
335
|
+
begin
|
336
|
+
lonlat = str_split(variable@coordinates," ")
|
337
|
+
lon = lonlat(0)
|
338
|
+
lat = lonlat(1)
|
339
|
+
x = filehandle->$lon$
|
340
|
+
y = filehandle->$lat$
|
341
|
+
|
342
|
+
return (/x,y/)
|
343
|
+
end
|
344
|
+
;-------------------------------------------------------------------------------
|
345
|
+
; Return the coordinates of a given variable in degrees
|
346
|
+
undef("getLonLats")
|
347
|
+
procedure getLonLats(variable,filehandle,x,y)
|
348
|
+
begin
|
349
|
+
lonlat = str_split(variable@coordinates," ")
|
350
|
+
lon = lonlat(0)
|
351
|
+
lat = lonlat(1)
|
352
|
+
x = filehandle->$lon$
|
353
|
+
y = filehandle->$lat$
|
354
|
+
x = x * RAD2DEG
|
355
|
+
y = y * RAD2DEG
|
356
|
+
end
|
357
|
+
;-------------------------------------------------------------------------------
|
358
|
+
; get variable from a certain file
|
359
|
+
undef("getVarFromFile")
|
360
|
+
function getVarFromFile(varname,filename)
|
361
|
+
begin
|
362
|
+
f = addfile(filename+".nc","r")
|
363
|
+
var = f->$varname$
|
364
|
+
return var
|
365
|
+
end
|
366
|
+
;-------------------------------------------------------------------------------
|
367
|
+
; read a coordinates variable from icon file and return its lonlat representation
|
368
|
+
undef("getCoordinateFromFile")
|
369
|
+
function getCoordinateFromFile(varname,filename)
|
370
|
+
begin
|
371
|
+
var = getVarFromFile(varname,filename)
|
372
|
+
return var*RAD2DEG
|
373
|
+
end
|
374
|
+
;-------------------------------------------------------------------------------
|
375
|
+
; Create an ascending array of numbers with a 'halflog' interval, i.e. for
|
376
|
+
; every decade the numbers 1, 2 and 5 are present.
|
377
|
+
; Examples:
|
378
|
+
; (/1,2,5,10,20,50,100,200,500/) or
|
379
|
+
; (/-1,-5e-1,-2e-1,-1e-1,-5e-2,-2e-2,-1e-2,0,1e-2,2e-2,5e-2,1e-1,2e-1,5e-1,1/)
|
380
|
+
; scaleLimit determines the numer of decades on the positive or negtive axis of the output array
|
381
|
+
undef("createLevels")
|
382
|
+
function createLevels(minVar, maxVar, scaleLimit)
|
383
|
+
begin
|
384
|
+
delimiter = "|"
|
385
|
+
tics4positive = (/1, 2, 5/)
|
386
|
+
tics4negative = (/5, 2, 1/)
|
387
|
+
|
388
|
+
signMin = sign(minVar)
|
389
|
+
signMax = sign(maxVar)
|
390
|
+
if (minVar.eq.0) then
|
391
|
+
logfirst = 0.0
|
392
|
+
first = 0.0
|
393
|
+
else
|
394
|
+
logfirst = ceil(log10(abs(minVar)))
|
395
|
+
first = signMin*10^logfirst
|
396
|
+
end if
|
397
|
+
if (maxVar.eq.0) then
|
398
|
+
loglast = 0.0
|
399
|
+
last = 0.0
|
400
|
+
else
|
401
|
+
loglast = ceil(log10(abs(maxVar)))
|
402
|
+
last = signMax*10^loglast
|
403
|
+
end if
|
404
|
+
|
405
|
+
|
406
|
+
retval = (/first, last, logfirst, loglast, signMin, signMax, logfirst*signMin - loglast*signMax/)
|
407
|
+
|
408
|
+
myScale = logfirst
|
409
|
+
levels = ""
|
410
|
+
;levels = new(1,float)
|
411
|
+
if (first .eq. 0) then
|
412
|
+
levels = str_concat((/levels,delimiter,"0"/))
|
413
|
+
;array_append_record_proc(levels,0.0)
|
414
|
+
print(levels)
|
415
|
+
end if
|
416
|
+
current = first
|
417
|
+
if (current .lt. 0) then
|
418
|
+
tics = tics4negative
|
419
|
+
do scaleChange=1,scaleLimit
|
420
|
+
do ticIndex=0,2
|
421
|
+
current = - tics(ticIndex)*10^(logfirst-scaleChange)
|
422
|
+
levels = str_concat((/levels,delimiter,flt2string(doubletofloat(current))/))
|
423
|
+
;array_append_record_proc(levels,doubletofloat(current))
|
424
|
+
end do
|
425
|
+
end do
|
426
|
+
end if
|
427
|
+
if (first.lt.0 .and. last.gt.0) then
|
428
|
+
levels = str_concat((/levels,delimiter,"0"/))
|
429
|
+
;array_append_record_proc(levels,0.0)
|
430
|
+
end if
|
431
|
+
if (last .gt. 0) then
|
432
|
+
tics = tics4positive
|
433
|
+
if (first.lt.0) then
|
434
|
+
startScale = min((/logfirst, loglast/)) - scaleLimit
|
435
|
+
else
|
436
|
+
startScale = min((/logfirst, loglast/))
|
437
|
+
end if
|
438
|
+
j = 0
|
439
|
+
do while (current.lt.(last/10))
|
440
|
+
myScale = startScale + j
|
441
|
+
do ticIndex=0,2
|
442
|
+
current = tics(ticIndex)*10^(myScale)
|
443
|
+
levels = str_concat((/levels,delimiter,flt2string(doubletofloat(current))/))
|
444
|
+
;array_append_record_proc(levels,current)
|
445
|
+
end do
|
446
|
+
j = j + 1
|
447
|
+
end do
|
448
|
+
levels = str_concat((/levels,delimiter,flt2string(doubletofloat(last))/))
|
449
|
+
;array_append_record_proc(levels,last)
|
450
|
+
end if
|
451
|
+
return(str_split(levels,"|"))
|
452
|
+
;print(levels)
|
453
|
+
;return(levels)
|
454
|
+
end
|
455
|
+
;---------------------------------------------------------------
|
456
|
+
; Print all variable names of a given file
|
457
|
+
undef("printVarNames")
|
458
|
+
procedure printVarNames(filehandle)
|
459
|
+
begin
|
460
|
+
filevarnames = getfilevarnames(filehandle)
|
461
|
+
print("# === variable names in file: "+filevarnames)
|
462
|
+
end
|
463
|
+
;---------------------------------------------------------------
|
464
|
+
; Print information about dimensions and attributes of a given varaiable
|
465
|
+
procedure printVar(varname, filehandle)
|
466
|
+
begin
|
467
|
+
dims = getfilevardims(filehandle,varname)
|
468
|
+
sizes = filevardimsizes(filehandle,varname)
|
469
|
+
var = filehandle->$varname$
|
470
|
+
; Print info about variable, its dimensions and attributes
|
471
|
+
print(dimsizes(sizes) + " Dimensions:")
|
472
|
+
if(.not.any(ismissing(dims))) then
|
473
|
+
do j = 0, dimsizes(dims) -1
|
474
|
+
print( j + ") " + dims(j) + ": " + sizes(j))
|
475
|
+
end do
|
476
|
+
end if
|
477
|
+
atts = getfilevaratts(filehandle,varname)
|
478
|
+
if(.not.any(ismissing(atts))) then
|
479
|
+
do k = 0, dimsizes(atts) -1
|
480
|
+
print(atts(k) + ": " +filehandle->$varname$@$atts(k)$)
|
481
|
+
if (atts(k) .eq. "coordinates") then
|
482
|
+
coordinates = var@$atts(k)$
|
483
|
+
else
|
484
|
+
coordinates = DEFAULTLON + " " + DEFAULTLAT
|
485
|
+
end if
|
486
|
+
end do
|
487
|
+
end if
|
488
|
+
end
|
489
|
+
;---------------------------------------------------------------
|
490
|
+
; Check, if a given variable name is present in a file
|
491
|
+
undef("checkVarname")
|
492
|
+
procedure checkVarname(varname, filehandle)
|
493
|
+
begin
|
494
|
+
filevarnames = getfilevarnames(filehandle)
|
495
|
+
if (.not. any(filevarnames.eq.varname)) then
|
496
|
+
print("Could not find variable "+varname+"!")
|
497
|
+
exit
|
498
|
+
end if
|
499
|
+
return True
|
500
|
+
end
|
501
|
+
;---------------------------------------------------------------
|
502
|
+
; Check, if the dimensions of to variables are equal
|
503
|
+
undef("checkDimsOfVars")
|
504
|
+
procedure checkDimsOfVars(varname0,varname1,filehandle)
|
505
|
+
begin
|
506
|
+
print(getfilevardims(filehandle,varname0))
|
507
|
+
print(getfilevardims(filehandle,varname1))
|
508
|
+
if (str_join(getfilevardims(filehandle,varname0),"") .ne. str_join(getfilevardims(filehandle,varname1),"")) then
|
509
|
+
print("Variables '"+varname0+"' and '"+varname1+"' must have the same dimensions!")
|
510
|
+
print("ABORT!")
|
511
|
+
exit
|
512
|
+
end if
|
513
|
+
end
|
514
|
+
;---------------------------------------------------------------
|
515
|
+
; Read a variable from the given or an optional file
|
516
|
+
undef("getMaskVar")
|
517
|
+
function getMaskVar(maskvarname,filehandle,hasOtherMaskfile,maskfilename,timestep,levelindex,plotmode,horizontalgridtype)
|
518
|
+
begin
|
519
|
+
if (hasOtherMaskfile) then
|
520
|
+
mfilehandle = addfile( maskfilename+".nc","r" )
|
521
|
+
else
|
522
|
+
mfilehandle = filehandle
|
523
|
+
end if
|
524
|
+
checkVarname(maskvarname, mfilehandle)
|
525
|
+
if (plotmode.eq."scalar" .or. plotmode.eq."overlay") then
|
526
|
+
if (horizontalgridtype.eq."unstructured") then
|
527
|
+
maskvar = selIconField(maskvarname,mfilehandle,timestep,levelindex)
|
528
|
+
else
|
529
|
+
maskvar = selRegularField(maskvarname,mfilehandle,timestep,levelindex)
|
530
|
+
end if
|
531
|
+
else
|
532
|
+
if (plotmode.eq."vector") then
|
533
|
+
maskvar = selRegularField(maskvarname,mfilehandle,timestep,levelindex)
|
534
|
+
else ; section
|
535
|
+
maskvar = selRegularVar(maskvarname,mfilehandle,timestep)
|
536
|
+
end if
|
537
|
+
end if
|
538
|
+
|
539
|
+
return maskvar
|
540
|
+
end
|
541
|
+
;---------------------------------------------------------------
|
542
|
+
; Read the dimensions of a variables from the given ot an optional file
|
543
|
+
;
|
544
|
+
; GLOBALS: maskFile
|
545
|
+
undef("getMaskDim")
|
546
|
+
function getMaskDim(maskvarname,filehandle,hasOtherMaskfile)
|
547
|
+
begin
|
548
|
+
if (hasOtherMaskfile) then
|
549
|
+
filehandle = addfile( maskFile+".nc","r" )
|
550
|
+
end if
|
551
|
+
checkVarname(maskvarname, filehandle)
|
552
|
+
maskdims = getfilevardims(filehandle,maskvarname)
|
553
|
+
|
554
|
+
return maskdims
|
555
|
+
end
|
556
|
+
;---------------------------------------------------------------
|
557
|
+
; set new filename bases on the input filename and intput type
|
558
|
+
undef("setNewFilename")
|
559
|
+
function setNewFilename(filename,tag,itype,atmlev)
|
560
|
+
begin
|
561
|
+
atmtag = ""
|
562
|
+
if (itype .eq. "atm") atmtag = "atmlev"+str_capital(atmlev)+"_" end if
|
563
|
+
newFilename = tag+"_"+atmtag+systemfunc("basename "+filename)
|
564
|
+
return newFilename
|
565
|
+
end
|
566
|
+
;---------------------------------------------------------------
|
567
|
+
; set filename for the automatically remapped file
|
568
|
+
undef("setRemapFilename")
|
569
|
+
function setRemapFilename(filename,itype,atmlev)
|
570
|
+
begin
|
571
|
+
return setNewFilename(filename,"remapnn",itype,atmlev)
|
572
|
+
end
|
573
|
+
undef("setZonmeanFilename")
|
574
|
+
function setZonmeanFilename(filename,itype,atmlev)
|
575
|
+
begin
|
576
|
+
return setNewFilename(filename,"zonmean",itype,atmlev)
|
577
|
+
end
|
578
|
+
;---------------------------------------------------------------
|
579
|
+
; Check, if two files have the same number of timestemps. Exit otherwise
|
580
|
+
undef("checkRemappedFile")
|
581
|
+
function checkRemappedFile(infilename,remapfilename,varname,itype,atmlev,atmplevs,atmhlevs)
|
582
|
+
begin
|
583
|
+
retval = True
|
584
|
+
|
585
|
+
if (.not. isfilepresent(remapfilename)) return False end if
|
586
|
+
|
587
|
+
orgFile = addfile (infilename+".nc" , "r")
|
588
|
+
orgTime = getfilevardimsizes(orgFile,"time")
|
589
|
+
|
590
|
+
if (.not. has_var(orgFile,varname)) then
|
591
|
+
print("Cannot find varname:"+varname)
|
592
|
+
exit
|
593
|
+
end if
|
594
|
+
|
595
|
+
orgvertdimname = getVertDim(orgFile,orgFile->$varname$)
|
596
|
+
if (.not. ismissing(orgvertdimname) ) then
|
597
|
+
orgvertdim = orgFile->$orgvertdimname$
|
598
|
+
end if
|
599
|
+
|
600
|
+
remapFile = addfile(remapfilename+".nc","r")
|
601
|
+
remapTime = getfilevardimsizes(remapFile,"time")
|
602
|
+
; test if the given variable can be found
|
603
|
+
if (.not. has_var(remapFile,varname)) then
|
604
|
+
print("Cannot find "+varname+" in remapped files:"+remapfilename)
|
605
|
+
retval = False
|
606
|
+
return retval
|
607
|
+
else
|
608
|
+
remappedvertdimname = getVertDim(remapFile,remapFile->$varname$)
|
609
|
+
if (.not. ismissing(remappedvertdimname)) then
|
610
|
+
remappedvertdim = remapFile->$remappedvertdimname$
|
611
|
+
end if
|
612
|
+
end if
|
613
|
+
|
614
|
+
|
615
|
+
if ( orgTime .eq. remapTime ) then
|
616
|
+
print("#=====================================================================================")
|
617
|
+
print("Remapped File '"+remapfilename+"' seems to have right time axes.")
|
618
|
+
else
|
619
|
+
print("#=====================================================================================")
|
620
|
+
print("Remapped File '"+remapfilename+"' seems to be wrong: Has different number of timesteps")
|
621
|
+
print("Original file has "+orgTime(0)+" timesteps")
|
622
|
+
print("Remapped File has "+remapTime(0)+" timesteps")
|
623
|
+
retval = False
|
624
|
+
end if
|
625
|
+
|
626
|
+
if (itype .eq. "atm") then
|
627
|
+
if (atmlev .eq. "p" .and. (str_join(atmplevs,",") .ne. str_join(remappedvertdim,",")) .and. (.not. ismissing(remappedvertdimname)))
|
628
|
+
print("Vertical pressure levels differ")
|
629
|
+
retval = False
|
630
|
+
else
|
631
|
+
print("Vertical pressure levels ok.")
|
632
|
+
end if
|
633
|
+
if (atmlev .eq. "h" .and. (str_join(atmhlevs,",") .ne. str_join(remappedvertdim,",")) .and. (.not. ismissing(remappedvertdimname)))
|
634
|
+
print("Vertical height levels differ")
|
635
|
+
retval = False
|
636
|
+
else
|
637
|
+
print("Vertical height levels ok.")
|
638
|
+
end if
|
639
|
+
end if
|
640
|
+
if (itype .eq. "oce") then
|
641
|
+
if ((.not. ismissing(orgvertdimname)) .and. (str_join(orgvertdim,",") .ne. str_join(remappedvertdim,",")) .and. (.not. ismissing(remappedvertdimname)))
|
642
|
+
print("Vertical depth levels differ")
|
643
|
+
retval = False
|
644
|
+
else
|
645
|
+
print("Vertical depth levels ok")
|
646
|
+
end if
|
647
|
+
end if
|
648
|
+
|
649
|
+
return retval
|
650
|
+
end
|
651
|
+
;---------------------------------------------------------------
|
652
|
+
; Perform a remapping (wich CDO) to a regular grid with a given resolution and return the
|
653
|
+
; filename of the remapped file. If the file is already present, the name is returned only
|
654
|
+
undef("remapForVecPlot")
|
655
|
+
procedure remapForVecPlot(iFile,remapFilename,resolution,useMask,plotMode,debug,addvars)
|
656
|
+
begin
|
657
|
+
if (plotMode.eq."section") then vecVars=(/varName/) end if
|
658
|
+
print("#=====================================================================================")
|
659
|
+
print("Looking for remapped file: "+remapFilename)
|
660
|
+
print("Use CDO to perform remapping: Create intermediate file: "+remapFilename)
|
661
|
+
print("Remove this intermediate file, if it was NOT automatically created from your inpur file "+iFile+"!")
|
662
|
+
variables = str_join(vecVars,",")
|
663
|
+
if ( addvars(0) .ne. "")
|
664
|
+
variables = str_concat((/variables,",",str_join(addvars,",")/))
|
665
|
+
print(str_join(addvars,","))
|
666
|
+
print("variables:"+variables)
|
667
|
+
end if
|
668
|
+
if ( useMask ) then
|
669
|
+
variables=variables +","+maskName
|
670
|
+
end if
|
671
|
+
if (plotMode.eq."overlay") variables = variables+","+varName end if
|
672
|
+
|
673
|
+
cmd = CDO+" -P 8 -remapnn,"+resolution+" -selname,"+variables+" "+iFile+" "+remapFilename
|
674
|
+
if debug then
|
675
|
+
print(cmd)
|
676
|
+
end if
|
677
|
+
system(cmd)
|
678
|
+
end
|
679
|
+
;---------------------------------------------------------------
|
680
|
+
; perform zonal mean for hoffmueller plot
|
681
|
+
undef("zonmean4HoffmuellerPlot")
|
682
|
+
procedure zonmean4HoffmuellerPlot(filename,varname,zonmeanfilename)
|
683
|
+
begin
|
684
|
+
cmd = CDO+" zonmean -selname,"+varname+" "+filename+" "+zonmeanfilename
|
685
|
+
if debug then
|
686
|
+
print(cmd)
|
687
|
+
end if
|
688
|
+
system(cmd)
|
689
|
+
end
|
690
|
+
;---------------------------------------------------------------
|
691
|
+
; Return the bounds of the coordinates of agiven variable
|
692
|
+
undef("getBoundsOfCoordinates")
|
693
|
+
function getBoundsOfCoordinates(variable,filehandle)
|
694
|
+
begin
|
695
|
+
lonlat = str_split(variable@coordinates," ")
|
696
|
+
lon = lonlat(0)
|
697
|
+
lat = lonlat(1)
|
698
|
+
|
699
|
+
|
700
|
+
boundslonName = filehandle->$lon$@bounds
|
701
|
+
boundslatName = filehandle->$lat$@bounds
|
702
|
+
boundslon = filehandle->$boundslonName$ * RAD2DEG
|
703
|
+
boundslat = filehandle->$boundslatName$ * RAD2DEG
|
704
|
+
|
705
|
+
return (/boundslon, boundslat/)
|
706
|
+
end
|
707
|
+
;---------------------------------------------------------------
|
708
|
+
; Return the bounds of the coordinates of agiven variable
|
709
|
+
undef("getBoundsFromFile")
|
710
|
+
function getBoundsFromFile(lonname,latname,filename)
|
711
|
+
begin
|
712
|
+
f = addfile(filename+".nc","r")
|
713
|
+
boundslonName = f->$lonname$@bounds
|
714
|
+
boundslatName = f->$latname$@bounds
|
715
|
+
boundslon = f->$boundslonName$ * RAD2DEG
|
716
|
+
boundslat = f->$boundslatName$ * RAD2DEG
|
717
|
+
|
718
|
+
return (/boundslon, boundslat/)
|
719
|
+
end
|
720
|
+
;---------------------------------------------------------------
|
721
|
+
; (Re)Set end of bounds. Required by the implementation of the grid plot
|
722
|
+
undef("setBoundsEnds")
|
723
|
+
procedure setBoundsEnds(blon,blat,lonmin,lonmax,latmin,latmax)
|
724
|
+
begin
|
725
|
+
latmax=max(blat)
|
726
|
+
latmin=min(blat)
|
727
|
+
lonmax=max(blon)
|
728
|
+
lonmin=min(blon)
|
729
|
+
|
730
|
+
if ( lonmin.lt.0 ) then
|
731
|
+
; longitudes are given in the range [-180,180]
|
732
|
+
lonmin = -180.
|
733
|
+
lonmax = 180.
|
734
|
+
else
|
735
|
+
; longitudes are given in the range [0,360]
|
736
|
+
lonmin = 0.
|
737
|
+
lonmax = 360.
|
738
|
+
end if
|
739
|
+
end
|
740
|
+
;---------------------------------------------------------------
|
741
|
+
; Bounds check for the grid plot
|
742
|
+
undef("checkLongitude")
|
743
|
+
procedure checkLongitude(x,boundslon,lonmin,lonmax,debug)
|
744
|
+
begin
|
745
|
+
dlon = 80.
|
746
|
+
ncell_tot = dimsizes(x) ; total # of cells
|
747
|
+
nfix = 0 ; count the # of problematic cells
|
748
|
+
|
749
|
+
do icell = 0, ncell_tot-1
|
750
|
+
if ( any(boundslon(icell,:).le.(lonmin+dlon)) .and. \
|
751
|
+
any(boundslon(icell,:).gt.(lonmax-dlon)) ) then
|
752
|
+
|
753
|
+
bl1=boundslon(icell,0)
|
754
|
+
bl2=boundslon(icell,1)
|
755
|
+
bl3=boundslon(icell,2)
|
756
|
+
|
757
|
+
boundslon(icell,:) = where(boundslon(icell,:).gt.(lonmax-dlon), \;
|
758
|
+
boundslon(icell,:)-360., \; where true
|
759
|
+
boundslon(icell,:) ) ; where false
|
760
|
+
|
761
|
+
bn1=boundslon(icell,0)
|
762
|
+
bn2=boundslon(icell,1)
|
763
|
+
bn3=boundslon(icell,2)
|
764
|
+
|
765
|
+
if (debug) then
|
766
|
+
print("cell="+icell+" lon="+bl1+", "+bl2+", "+bl3+" changed into " \
|
767
|
+
+" lon="+bn1+", "+bn2+", "+bn3)
|
768
|
+
end if
|
769
|
+
|
770
|
+
nfix = nfix +1
|
771
|
+
end if
|
772
|
+
end do
|
773
|
+
print("Longitude(s) of "+nfix+" cells corrected to avoid plotting problem.")
|
774
|
+
end
|
775
|
+
;---------------------------------------------------------------
|
776
|
+
; Set the Vertical Selection mode of the given NCL resource
|
777
|
+
undef("setLevels")
|
778
|
+
procedure setLevels(selmode,resource,minvar,maxvar,scalelimit,numlevs,debug)
|
779
|
+
begin
|
780
|
+
if (selmode .eq. "manual") then
|
781
|
+
resource@cnLevelSelectionMode = "ManualLevels"
|
782
|
+
resource@cnMinLevelValF = minvar
|
783
|
+
resource@cnMaxLevelValF = maxvar
|
784
|
+
; diffLog10 = log10(abs(maxVar-minVar))
|
785
|
+
;; if (diffLog10 .lt. 0) then
|
786
|
+
; resource@cnLevelSpacingF = 10^(floor(diffLog10))/numLevs
|
787
|
+
;; else
|
788
|
+
;; resource@cnLevelSpacingF = 10^(floor(diffLog10))/numLevs
|
789
|
+
;; end if
|
790
|
+
diffspacing = abs(maxvar-minvar)/(int2flt(numlevs))
|
791
|
+
resource@cnLevelSpacingF = diffspacing
|
792
|
+
end if
|
793
|
+
|
794
|
+
if (selmode .eq. "halflog") then
|
795
|
+
resource@cnLevelSelectionMode = "ExplicitLevels"
|
796
|
+
plotLevels = createLevels(minvar,maxvar,scalelimit)
|
797
|
+
if (debug) print("plotlevels = "+plotLevels) end if
|
798
|
+
resource@cnLevels = plotLevels
|
799
|
+
end if
|
800
|
+
if (debug) then
|
801
|
+
print("Manual Plotlevel setting......")
|
802
|
+
print(" selMode : " + selmode)
|
803
|
+
print(" minVal : " + minvar)
|
804
|
+
print(" maxVal : " + maxvar)
|
805
|
+
print(" numLevs: " + numlevs)
|
806
|
+
print(" scalelimit: " + scalelimit)
|
807
|
+
print(" plotLevels: " + resource@cnLevels)
|
808
|
+
end if
|
809
|
+
end
|
810
|
+
;---------------------------------------------------------------
|
811
|
+
; Create a default NCL resource
|
812
|
+
undef("setDefaultResource")
|
813
|
+
procedure setDefaultResource(resource,verticallabelbar)
|
814
|
+
begin
|
815
|
+
resource@gsnMaximize = False
|
816
|
+
; resource@gsnPaperOrientation = "landscape" ; turns plot on paper
|
817
|
+
; resource@wkPaperSize = "A4"
|
818
|
+
resource@gsnFrame = False
|
819
|
+
resource@gsnSpreadColors = True
|
820
|
+
|
821
|
+
resource@cnFillOn = True ; writes labelbar, no contour labels
|
822
|
+
resource@cnLinesOn = False
|
823
|
+
resource@cnInfoLabelOn = False
|
824
|
+
|
825
|
+
FontHeight0 = 0.012
|
826
|
+
FontHeight1 = 0.015
|
827
|
+
FontHeight2 = 0.017
|
828
|
+
FontHeight3 = 0.020
|
829
|
+
|
830
|
+
resource@tiXAxisFontHeightF = FontHeight0
|
831
|
+
resource@tiYAxisFontHeightF = FontHeight0
|
832
|
+
resource@tmXBLabelFontHeightF = FontHeight0
|
833
|
+
resource@tmYLLabelFontHeightF = FontHeight0
|
834
|
+
resource@tmXBLabelJust = "CenterCenter"
|
835
|
+
resource@gsnStringFontHeightF = FontHeight0
|
836
|
+
|
837
|
+
resource@mpFillOn = True
|
838
|
+
resource@cnFillOn = True
|
839
|
+
|
840
|
+
resource@lbLabelBarOn = True
|
841
|
+
if (verticallabelbar .eq. True) then
|
842
|
+
resource@lbOrientation = "vertical"
|
843
|
+
else
|
844
|
+
resource@pmLabelBarHeightF = 0.12
|
845
|
+
resource@pmLabelBarWidthF = 0.80
|
846
|
+
resource@pmLabelBarOrthogonalPosF = 0.15
|
847
|
+
end if
|
848
|
+
resource@lbLabelAutoStride = True
|
849
|
+
resource@lbLabelFontHeightF = FontHeight1 ; color bar labels
|
850
|
+
|
851
|
+
resource@cnFillMode = "RasterFill"
|
852
|
+
;resource@cnFillMode = "CellFill"
|
853
|
+
resource@cnRasterSmoothingOn = True
|
854
|
+
resource@mpGreatCircleLinesOn = True
|
855
|
+
resource@stMinArrowSpacingF = 0.001
|
856
|
+
end
|
857
|
+
;---------------------------------------------------------------
|
858
|
+
undef("setDefaultSectionResource")
|
859
|
+
function setDefaultSectionResource(points,secpoints,seclc,secrc)
|
860
|
+
begin
|
861
|
+
resource = True; plot mods desired
|
862
|
+
resource@gsnFrame = False; don't turn page yet
|
863
|
+
resource@gsnDraw = False; don't draw yet
|
864
|
+
resource@tmXBMode = "Explicit"; explicitly label x-axis
|
865
|
+
resource@tmXBValues = (/points(0),points(secpoints-1)/); points to label values
|
866
|
+
resource@tmXBLabels = (/ seclc(1) +"N, "+ seclc(0)+"E" , secrc(1)+"N, "+secrc(0)+"E" /)
|
867
|
+
|
868
|
+
resource@cnFillOn = True; turn on color
|
869
|
+
resource@lbLabelAutoStride = True; nice label bar label stride
|
870
|
+
resource@gsnSpreadColors = True; use full range of colormap
|
871
|
+
resource@cnLinesOn = False; turn off countour lines
|
872
|
+
resource@lbOrientation = "vertical"; vertical label bar
|
873
|
+
resource@pmLabelBarOrthogonalPosF = -0.05; move label bar closer to plot
|
874
|
+
resource@lbTitlePosition = "Bottom"
|
875
|
+
; resource@gsnYAxisIrregular2Log = True
|
876
|
+
|
877
|
+
delete(resource@cnMissingValFillPattern); no longer filling missing value areas
|
878
|
+
delete(resource@cnMissingValFillColor); no longer filling missing value areas
|
879
|
+
resource@cnMissingValFillColor = "gray30"
|
880
|
+
resource@cnMissingValPerimOn = True
|
881
|
+
|
882
|
+
resource@cnMissingValFillPattern = -1; set the missing value fill pattern to 5
|
883
|
+
resource@cnMissingValFillScaleF = 0.9; increase the density of the fill pattern (default = 1.0)
|
884
|
+
; resource@cnMissingValPerimOn = True; already turned on above
|
885
|
+
resource@cnMissingValPerimColor = "black"; change the missing value perimeter to black
|
886
|
+
resource@cnMissingValPerimDashPattern = 1; set the dash pattern of the missing value perimeter to 1
|
887
|
+
resource@cnMissingValPerimThicknessF = 3.0; increase the thickness of the missing value perimeter 3X
|
888
|
+
;resource@gsnYAxisIrregular2Log = True
|
889
|
+
return resource
|
890
|
+
end
|
891
|
+
undef("setDefaultOverlayResource")
|
892
|
+
procedure setDefaultOverlayResource(resource)
|
893
|
+
begin
|
894
|
+
resource@gsnDraw = False
|
895
|
+
resource@gsnFrame = False
|
896
|
+
resource@vcVectorDrawOrder = "Postdraw"
|
897
|
+
resource@vcFillArrowWidthF = 12.0
|
898
|
+
resource@lbOrientation = "Vertical"
|
899
|
+
resource@lbTitleString = "C"
|
900
|
+
resource@lbTitlePosition = "Left"
|
901
|
+
resource@cnInfoLabelOn = False
|
902
|
+
resource@lbTitleFontHeightF = 0.02
|
903
|
+
resource@lbLabelFontHeightF = 0.015
|
904
|
+
resource@lbLeftMarginF = 0.01
|
905
|
+
resource@lbLabelBarOn = False; switch of the vector label bar, because the speed is show as vector lenghts
|
906
|
+
end
|
907
|
+
;---------------------------------------------------------------
|
908
|
+
undef("shift4SecMap")
|
909
|
+
procedure shift4SecMap(resource)
|
910
|
+
begin
|
911
|
+
resource@vpWidthF = 0.6; set width of plot
|
912
|
+
resource@vpHeightF = 0.4; set height of plot
|
913
|
+
|
914
|
+
resource@vpXF = 0.2
|
915
|
+
resource@vpYF = 0.9
|
916
|
+
end
|
917
|
+
;---------------------------------------------------------------
|
918
|
+
; Compute the left shift for string with font hight 0.01, which should be
|
919
|
+
; displayed in the lower left corner of the plot with gsn_test_ndc()
|
920
|
+
undef("getLshiftForNDCString")
|
921
|
+
function getLshiftForNDCString(mystring)
|
922
|
+
begin
|
923
|
+
lshift = (strlen(mystring)/2 - 1)/100.0
|
924
|
+
if (strlen(mystring) .gt. 4)
|
925
|
+
lshift = lshift - lshift/5 + 0.1/strlen(mystring)
|
926
|
+
else
|
927
|
+
lshift = lshift + 0.01
|
928
|
+
end if
|
929
|
+
|
930
|
+
return lshift
|
931
|
+
end
|
932
|
+
;---------------------------------------------------------------
|
933
|
+
; Display a small string in the lower left corner of the plot
|
934
|
+
undef("setBaseString")
|
935
|
+
procedure setBaseString(workstation,plot,resource,basestring)
|
936
|
+
begin
|
937
|
+
resource@txFontHeightF = 0.01 ; if this is changed, please adjust the implementation of getLshiftForNDCString()
|
938
|
+
gsn_text_ndc(workstation,basestring,getLshiftForNDCString(basestring),.01,resource)
|
939
|
+
end
|
940
|
+
;---------------------------------------------------------------
|
941
|
+
; see setBaseString, but use an optional global argument
|
942
|
+
;
|
943
|
+
; GLOBALS: bStrg
|
944
|
+
undef("setAutomaticBaseString")
|
945
|
+
procedure setAutomaticBaseString(workstation,plotmode)
|
946
|
+
begin
|
947
|
+
if(isvar("bStrg")) then
|
948
|
+
BaseString = bStrg
|
949
|
+
else
|
950
|
+
BaseString = "Prgr icon_plot.ncl: " + systemfunc("date") + ","+getenv("USER")
|
951
|
+
end if
|
952
|
+
res = True
|
953
|
+
res@txFontHeightF = 0.011
|
954
|
+
if (plotmode.eq."section") res@txPosYF = 0.01 end if
|
955
|
+
gsn_text_ndc(workstation,BaseString,getLshiftForNDCString(BaseString),.12,res)
|
956
|
+
end
|
957
|
+
;---------------------------------------------------------------
|
958
|
+
; Set the Captions of a plot (left,right,center,title)
|
959
|
+
undef("setPlotCaptions")
|
960
|
+
procedure setPlotCaptions(resource,leftstring,rightstring,centerstring,titlestring)
|
961
|
+
begin
|
962
|
+
resource@gsnLeftString = leftstring
|
963
|
+
resource@gsnRightString = rightstring
|
964
|
+
resource@gsnCenterString = centerstring
|
965
|
+
resource@tiMainString = titlestring
|
966
|
+
end
|
967
|
+
;---------------------------------------------------------------
|
968
|
+
; Set the capitons of a plot automatically
|
969
|
+
;
|
970
|
+
; GLOBALS: lStrg, rStrg, tStrg
|
971
|
+
undef("setAutomaticPlotCaptions")
|
972
|
+
procedure setAutomaticPlotCaptions(resource,plotmode,varname,filehandle,filename,timestep,levelindex,itype,atmlev,k2c)
|
973
|
+
local varname
|
974
|
+
begin
|
975
|
+
; titles
|
976
|
+
if (plotmode.eq."vector") then
|
977
|
+
varname = vecVars(0)
|
978
|
+
left_str = "velocity"
|
979
|
+
else
|
980
|
+
left_str = varname
|
981
|
+
end if
|
982
|
+
if(.not. isvar("lStrg")) then
|
983
|
+
hastime = var_has_time(varname, filehandle)
|
984
|
+
if (hastime) then
|
985
|
+
timeval = filehandle->time(timestep)
|
986
|
+
dayfrag = timeval - floor(timeval)
|
987
|
+
day = doubletointeger(floor(timeval))
|
988
|
+
hour = doubletointeger(floor(86400*dayfrag/3600))
|
989
|
+
minute = doubletointeger(floor((86400*dayfrag - hour*3600)/60))
|
990
|
+
second = doubletointeger(86400*dayfrag - hour*3600 - minute*60)
|
991
|
+
timeStr = str_join((/day,hour,minute,second/),"|")
|
992
|
+
left_str = left_str + " (ts:"+timestep+"["+timeStr+"] "
|
993
|
+
else
|
994
|
+
left_str = "("
|
995
|
+
end if
|
996
|
+
if (plotmode .ne. "section")
|
997
|
+
if ( .not.ismissing(getVertDim(filehandle,filehandle->$varname$)) ) then
|
998
|
+
vertdimname = getVertDim(filehandle,filehandle->$varname$)
|
999
|
+
vertdim = filehandle->$vertdimname$
|
1000
|
+
vertval = vertdim(levelindex)
|
1001
|
+
left_str = left_str + "lev:"+vertval
|
1002
|
+
if (atmlev .ne. "m")
|
1003
|
+
left_str = left_str+vertdim@units+")"
|
1004
|
+
else
|
1005
|
+
left_str = left_str +")"
|
1006
|
+
end if
|
1007
|
+
end if
|
1008
|
+
end if
|
1009
|
+
else
|
1010
|
+
left_str = lStrg
|
1011
|
+
end if
|
1012
|
+
|
1013
|
+
if(.not. isvar("rStrg")) then
|
1014
|
+
rStrg = (/filename/)
|
1015
|
+
end if
|
1016
|
+
rightstring = str_join(rStrg," ")
|
1017
|
+
|
1018
|
+
if(.not. isvar("tStrg")) then
|
1019
|
+
tStrg = "ICON"
|
1020
|
+
end if
|
1021
|
+
titlestring = str_join(tStrg," ")
|
1022
|
+
centerstring = ""
|
1023
|
+
|
1024
|
+
resource@gsnLeftString = left_str
|
1025
|
+
resource@gsnRightString = rightstring
|
1026
|
+
resource@gsnCenterString = centerstring
|
1027
|
+
resource@tiMainString = titlestring
|
1028
|
+
v = filehandle->$varname$
|
1029
|
+
if ( isatt(v,"units") ) then
|
1030
|
+
resource@lbTitleString = "["+v@units+"]"
|
1031
|
+
else
|
1032
|
+
resource@lbTitleString = ""
|
1033
|
+
end if
|
1034
|
+
if (itype .eq. "atm" .and. varname .eq. "T" .and. k2c) resource@lbTitleString = "C" end if
|
1035
|
+
|
1036
|
+
resource@lbTitlePosition = "Bottom"
|
1037
|
+
resource@cnInfoLabelOn = False
|
1038
|
+
resource@lbTitleFontHeightF = 0.02
|
1039
|
+
resource@lbLabelFontHeightF = 0.015
|
1040
|
+
resource@lbLeftMarginF = 0.01
|
1041
|
+
end
|
1042
|
+
;---------------------------------------------------------------
|
1043
|
+
; vertical axes label for section plot
|
1044
|
+
undef("setSectionVertLabel")
|
1045
|
+
procedure setSectionVertLabel(resource,itype,atmlev)
|
1046
|
+
begin
|
1047
|
+
resource@lbTitleString = "[C]"
|
1048
|
+
label = ""
|
1049
|
+
reversYAxis = True
|
1050
|
+
if (itype .eq. "atm") then
|
1051
|
+
label = "Index"
|
1052
|
+
if (atmlev .eq. "p") label = "Pressure (Pa)" end if
|
1053
|
+
if (atmlev .eq. "h")
|
1054
|
+
label = "Height (m)"
|
1055
|
+
reversYAxis = False
|
1056
|
+
end if
|
1057
|
+
else
|
1058
|
+
label = "depth below sea (m)"
|
1059
|
+
end if
|
1060
|
+
resource@tiYAxisString = label
|
1061
|
+
resource@trYReverse = reversYAxis
|
1062
|
+
end
|
1063
|
+
;---------------------------------------------------------------
|
1064
|
+
; Determine the type of the map
|
1065
|
+
undef("setMapType")
|
1066
|
+
procedure setMapType(resource,maptype,centerlon,centerlat,satdist)
|
1067
|
+
begin
|
1068
|
+
if (maptype .eq. "ortho") then
|
1069
|
+
resource@mpProjection = "Orthographic"
|
1070
|
+
resource@mpPerimOn = False; turn off box around plot
|
1071
|
+
resource@mpGridAndLimbOn = True; draw grid lines and limb line
|
1072
|
+
resource@mpGridLineDashPattern = 2; choose pattern used to draw the grid
|
1073
|
+
resource@mpCenterLonF = centerlon
|
1074
|
+
resource@mpCenterLatF = centerlat
|
1075
|
+
resource@vcRefLengthF = 0.01
|
1076
|
+
resource@vcRefAnnoArrowLineColor = "black"; change ref vector color
|
1077
|
+
resource@vcRefAnnoArrowUseVecColor = False; do not use vec color for ref
|
1078
|
+
resource@vcRefAnnoOn = False; turns off ref vector annotation
|
1079
|
+
resource@vcGlyphStyle = "CurlyVector"; turn on curly vectors
|
1080
|
+
resource@vcMonoLineArrowColor = True; multiple colors desired
|
1081
|
+
resource@vcVectorDrawOrder = "PostDraw"; draw vectors last
|
1082
|
+
|
1083
|
+
|
1084
|
+
resource@mpGridAndLimbOn = True ; turn on lat/lon grid lines
|
1085
|
+
resource@mpGridMaskMode = "MaskNotOcean" ; don't draw over land or
|
1086
|
+
; inland water bodies
|
1087
|
+
|
1088
|
+
; resource@mpLandFillColor = "tan"
|
1089
|
+
; resource@mpOceanFillColor = "LightBlue"
|
1090
|
+
; resource@mpInlandWaterFillColor = "LightBlue"
|
1091
|
+
end if
|
1092
|
+
|
1093
|
+
if (maptype .eq. "lonlat")
|
1094
|
+
resource@mpProjection = "CylindricalEquidistant"
|
1095
|
+
resource@mpLimitMode = "LatLon"
|
1096
|
+
end if
|
1097
|
+
|
1098
|
+
if (maptype .eq. "NHps")
|
1099
|
+
resource@mpProjection = "Stereographic"
|
1100
|
+
resource@mpRelativeCenterLon = True
|
1101
|
+
resource@mpCenterLonF = 0
|
1102
|
+
resource@mpRelativeCenterLat = True
|
1103
|
+
resource@mpCenterLatF = 90.
|
1104
|
+
resource@mpLimitMode = "Corners"
|
1105
|
+
end if
|
1106
|
+
|
1107
|
+
if (maptype .eq. "SHps")
|
1108
|
+
resource@mpProjection = "Stereographic"
|
1109
|
+
resource@mpRelativeCenterLon = True
|
1110
|
+
resource@mpCenterLonF = 0
|
1111
|
+
resource@mpRelativeCenterLat = True
|
1112
|
+
resource@mpCenterLatF = -90.
|
1113
|
+
resource@mpLimitMode = "Corners"
|
1114
|
+
end if
|
1115
|
+
if (maptype .eq. "sat")
|
1116
|
+
resource@mpProjection = "Satellite"
|
1117
|
+
resource@mpMinLatF = resource@mpMinLatF + 10.
|
1118
|
+
resource@mpMaxLatF = resource@mpMaxLatF - 10.
|
1119
|
+
resource@mpMinLonF = resource@mpMinLonF + 10.
|
1120
|
+
resource@mpMaxLonF = resource@mpMaxLonF - 10.
|
1121
|
+
resource@mpCenterLonF = centerlon
|
1122
|
+
resource@mpCenterLatF = centerlat
|
1123
|
+
resource@mpSatelliteDistF = satdist
|
1124
|
+
end if
|
1125
|
+
if (maptype .eq. "lambert")
|
1126
|
+
resource@mpProjection = "LambertConformal"
|
1127
|
+
resource@mpProjection = "Hammer"
|
1128
|
+
resource@mpProjection = "Mollweide"
|
1129
|
+
resource@mpProjection = "Robinson"
|
1130
|
+
resource@mpProjection = "WinkelTripel"
|
1131
|
+
resource@mpProjection = "Gnomonic"
|
1132
|
+
resource@mpProjection = "Aitoff"
|
1133
|
+
; resource@gsnMaskLambertConformal = True
|
1134
|
+
end if
|
1135
|
+
end
|
1136
|
+
;---------------------------------------------------------------
|
1137
|
+
; Determine the corners of the map to plot
|
1138
|
+
; mapllc = map-lower-left-corner
|
1139
|
+
; mapurl = map-upper-right-corner
|
1140
|
+
; format: (/lon,lat/)
|
1141
|
+
undef("selMapCut")
|
1142
|
+
procedure selMapCut(resource,mapllc,mapurc)
|
1143
|
+
begin
|
1144
|
+
; bounds of plotting area (not used for Orthographic)
|
1145
|
+
resource@mpMinLatF = mapllc(1)
|
1146
|
+
resource@mpMaxLatF = mapurc(1)
|
1147
|
+
resource@mpMinLonF = mapllc(0)
|
1148
|
+
resource@mpMaxLonF = mapurc(0)
|
1149
|
+
|
1150
|
+
; center of view (for Orthographic and Sattelite only)
|
1151
|
+
; resource@mpCenterLonF = (resource@mpMaxLonF+resource@mpMinLonF)/2.0
|
1152
|
+
; resource@mpCenterLatF = (resource@mpMaxLatF+resource@mpMinLatF)/2.0
|
1153
|
+
|
1154
|
+
; bounds of plotting area for stereographic plots
|
1155
|
+
resource@mpLeftCornerLonF = mapllc(0)
|
1156
|
+
resource@mpLeftCornerLatF = mapllc(1)
|
1157
|
+
resource@mpRightCornerLonF = mapurc(0)
|
1158
|
+
resource@mpRightCornerLatF = mapurc(1)
|
1159
|
+
end
|
1160
|
+
;---------------------------------------------------------------
|
1161
|
+
; Set the visibility of the map
|
1162
|
+
undef("setMapVisibility")
|
1163
|
+
procedure setMapVisibility(resource,mapline)
|
1164
|
+
begin
|
1165
|
+
if (mapline) then
|
1166
|
+
resource@mpGeophysicalLineColor = "foreground"
|
1167
|
+
else
|
1168
|
+
resource@mpGeophysicalLineColor = "transparent"
|
1169
|
+
end if
|
1170
|
+
end
|
1171
|
+
;---------------------------------------------------------------
|
1172
|
+
; exit if minvar is larger than maxvar
|
1173
|
+
undef("checkMinMaxVar")
|
1174
|
+
procedure checkMinMaxVar(minvar,maxvar)
|
1175
|
+
begin
|
1176
|
+
if ( minvar .gt. maxvar ) then
|
1177
|
+
print("minVar has to be larger than maxVar")
|
1178
|
+
exit
|
1179
|
+
end if
|
1180
|
+
end
|
1181
|
+
;---------------------------------------------------------------
|
1182
|
+
; set the color of masked locations
|
1183
|
+
undef("setMaskColor")
|
1184
|
+
procedure setMaskColor(wks,resource)
|
1185
|
+
begin
|
1186
|
+
newcolor = NhlNewColor(wks,0.85,0.85,0.85) ; add gray to colormap
|
1187
|
+
;resource@gsnSpreadColorStart = 1
|
1188
|
+
resource@gsnSpreadColorEnd = 19 ; last color number not known?
|
1189
|
+
resource@cnMissingValFillColor = 20 ; last color is used for missing values
|
1190
|
+
end
|
1191
|
+
;---------------------------------------------------------------
|
1192
|
+
; set the coordinates for an ICON data field
|
1193
|
+
undef("setCoordinates")
|
1194
|
+
procedure setCoordinates(resource,lons,lats)
|
1195
|
+
begin
|
1196
|
+
resource@sfXArray = lons
|
1197
|
+
resource@sfYArray = lats
|
1198
|
+
end
|
1199
|
+
;---------------------------------------------------------------
|
1200
|
+
; set the coordinates bounds for an ICON data field
|
1201
|
+
undef("setBounds")
|
1202
|
+
procedure setBounds(resource,filehandle,x,y,debug)
|
1203
|
+
begin
|
1204
|
+
; add the bounds to the resource if bounds are present
|
1205
|
+
if (isatt(x,"bounds")) then
|
1206
|
+
xbounds = filehandle->$x@bounds$
|
1207
|
+
if (debug) print(""+x@bounds) end if
|
1208
|
+
resource@sfXCellBounds = xbounds
|
1209
|
+
end if
|
1210
|
+
if (isatt(y,"bounds")) then
|
1211
|
+
ybounds = filehandle->$y@bounds$
|
1212
|
+
if (debug) print(""+y@bounds) end if
|
1213
|
+
resource@sfYCellBounds = ybounds
|
1214
|
+
end if
|
1215
|
+
end
|
1216
|
+
;---------------------------------------------------------------
|
1217
|
+
; Print out some information about the used map
|
1218
|
+
undef("showMapInfo")
|
1219
|
+
procedure showMapInfo(resource,maptype,mapline)
|
1220
|
+
begin
|
1221
|
+
print("mapType: "+maptype)
|
1222
|
+
print("mapLine: "+mapline)
|
1223
|
+
print("CentLon/Lat="+resource@mpCenterLonF+"; "+resource@mpCenterLatF)
|
1224
|
+
print("Min/MaxLatF="+resource@mpMinLatF+"; "+resource@mpMaxLatF)
|
1225
|
+
print("Min/MaxLonF="+resource@mpMinLonF+"; "+resource@mpMaxLonF)
|
1226
|
+
end
|
1227
|
+
;---------------------------------------------------------------
|
1228
|
+
; preprocessing for atmosphere data, i.e. put variables on height
|
1229
|
+
; or pressure levels:
|
1230
|
+
; use ml2pl/ml2hl for vertical interpolation
|
1231
|
+
undef("preProc4Atm")
|
1232
|
+
function preProc4Atm(filename,atmlev,atmplevs,atmhlevs,debug)
|
1233
|
+
begin
|
1234
|
+
atmfilename = "atmPreProc_"+systemfunc("basename "+filename)
|
1235
|
+
if (atmlev .eq. "p") then
|
1236
|
+
operator = "ml2plx"
|
1237
|
+
levels = str_join(atmplevs,",")
|
1238
|
+
else
|
1239
|
+
operator = "ml2hlx"
|
1240
|
+
levels = str_join(atmhlevs,",")
|
1241
|
+
end if
|
1242
|
+
|
1243
|
+
cmd = CDO+" "+ operator +","+levels+" -selgrid,1 "+ filename +" "+ atmfilename
|
1244
|
+
if debug then
|
1245
|
+
print(cmd)
|
1246
|
+
end if
|
1247
|
+
system(cmd)
|
1248
|
+
|
1249
|
+
return atmfilename
|
1250
|
+
end
|
1251
|
+
;---------------------------------------------------------------
|
1252
|
+
; determine the leveltype: hybrid or non-hybrid
|
1253
|
+
undef("getVertDimType")
|
1254
|
+
function getVertDimType(dim)
|
1255
|
+
begin
|
1256
|
+
dtype = str_match(dim@long_name,"hybrid")
|
1257
|
+
if (ismissing(dtype)) then
|
1258
|
+
return "non-hybrid"
|
1259
|
+
else
|
1260
|
+
return "hybrid"
|
1261
|
+
end if
|
1262
|
+
end
|
1263
|
+
;---------------------------------------------------------------
|
1264
|
+
; determine the input type: oce OR atm
|
1265
|
+
; variables on hybrid layers are belong to atm input, everything
|
1266
|
+
; else is oce
|
1267
|
+
undef("getVarLevelType")
|
1268
|
+
function getVarLevelType(filename,varname)
|
1269
|
+
begin
|
1270
|
+
f = addfile(filename+".nc","r")
|
1271
|
+
vertdim = getVertDim(f,f->$varname$)
|
1272
|
+
if (ismissing(vertdim)) then
|
1273
|
+
delete(f)
|
1274
|
+
delete(vertdim)
|
1275
|
+
return "none"
|
1276
|
+
else
|
1277
|
+
retval = getVertDimType(f->$vertdim$)
|
1278
|
+
delete(f)
|
1279
|
+
delete(vertdim)
|
1280
|
+
|
1281
|
+
return retval
|
1282
|
+
end if
|
1283
|
+
end
|
1284
|
+
;---------------------------------------------------------------
|
1285
|
+
; determine the horizontal grid type (unstructured or lonlat)
|
1286
|
+
undef("getHorizGridType")
|
1287
|
+
function getHorizGridType(filename,varname,isIcon)
|
1288
|
+
begin
|
1289
|
+
if (isIcon) then
|
1290
|
+
print("DEBUG:"+isIcon)
|
1291
|
+
gridtype = "unstructured"
|
1292
|
+
else
|
1293
|
+
print("CDO:"+CDO)
|
1294
|
+
print("Call cdo griddes for determine the horizontal gridtype")
|
1295
|
+
gridtype = systemfunc(CDO+" -griddes -selname,"+varname+" -seltimestep,1 "+filename+" | grep gridtype | cut -d ' ' -f 4")
|
1296
|
+
end if
|
1297
|
+
print("Found horizontal grid of type: "+gridtype)
|
1298
|
+
return gridtype
|
1299
|
+
end
|
1300
|
+
;---------------------------------------------------------------
|
1301
|
+
; setting for vertical cross sections based on remapped icon data
|
1302
|
+
undef("setSection")
|
1303
|
+
function setSection(secLC,secRC,npoints,var)
|
1304
|
+
begin
|
1305
|
+
leftlat = secLC(1)
|
1306
|
+
rightlat = secRC(1)
|
1307
|
+
|
1308
|
+
leftlon = secLC(0)
|
1309
|
+
rightlon = secRC(0)
|
1310
|
+
|
1311
|
+
dist = gc_latlon(leftlat,leftlon,rightlat,rightlon,npoints,2)
|
1312
|
+
trans = linint2_points(var&lon,var&lat,var,True,dist@gclon,dist@gclat,2)
|
1313
|
+
|
1314
|
+
return trans
|
1315
|
+
end
|
1316
|
+
;---------------------------------------------------------------
|
1317
|
+
; setting for vertical cross sections based on remapped icon data
|
1318
|
+
undef("setSectionFromHybridPress")
|
1319
|
+
function setSectionFromHybridPress(secLC,secRC,npoints,var,filehandle,timestep)
|
1320
|
+
begin
|
1321
|
+
leftlat = secLC(1)
|
1322
|
+
rightlat = secRC(1)
|
1323
|
+
|
1324
|
+
leftlon = secLC(0)
|
1325
|
+
rightlon = secRC(0)
|
1326
|
+
|
1327
|
+
;config
|
1328
|
+
pressName = "PS"
|
1329
|
+
geopotName = "PHIS"
|
1330
|
+
hybCords = (/"hyam","hybm","hyai","hybi"/)
|
1331
|
+
hyamName = hybCords(0)
|
1332
|
+
hybmName = hybCords(1)
|
1333
|
+
hyaiName = hybCords(2)
|
1334
|
+
hybiName = hybCords(3)
|
1335
|
+
|
1336
|
+
nlevels = 47
|
1337
|
+
p00 = 1.e3; reference pressure in hPa
|
1338
|
+
|
1339
|
+
|
1340
|
+
|
1341
|
+
phis = filehandle->$pressName$(0,:,:) ; dims: (time,lon,lat)
|
1342
|
+
|
1343
|
+
psfc = filehandle->$pressName$(timestep,:,:) ; surface pressure, dims: (time,lon.lat)
|
1344
|
+
psfc = psfc*1.e-2 ; convert to hPa
|
1345
|
+
hyam = filehandle->$hyamName$*1.e-2 ; convert to hPa
|
1346
|
+
hybm = filehandle->$hybmName$
|
1347
|
+
hyai = filehandle->$hyaiName$*1.e-2 ; convert to hPa
|
1348
|
+
hybi = filehandle->$hybiName$
|
1349
|
+
klevi = dimsizes(hyai) ;
|
1350
|
+
klevm = dimsizes(hyam) ;
|
1351
|
+
|
1352
|
+
; compute 3d pressure
|
1353
|
+
dims = dimsizes(psfc)
|
1354
|
+
print("dims:"+str_join((/nlevels, dims(0), dims(1)/),"|"))
|
1355
|
+
pres3d = new ((/nlevels, dims(0), dims(1)/),double)
|
1356
|
+
pres3di = new ((/nlevels+1,dims(0), dims(1)/),double)
|
1357
|
+
theta3d = new ((/nlevels, dims(0), dims(1)/),double)
|
1358
|
+
do k = 0, nlevels-1
|
1359
|
+
pres3d(k,:,:) = psfc(:,:)*hybm(k) + hyam(k)
|
1360
|
+
end do
|
1361
|
+
do k = 0, nlevels
|
1362
|
+
pres3di(k,:,:) = psfc(:,:)*hybi(k) + hyai(k)
|
1363
|
+
end do
|
1364
|
+
|
1365
|
+
if (False) then ; potential temperature
|
1366
|
+
var = var*(p00/pres3d)^(2./7.)
|
1367
|
+
end if
|
1368
|
+
|
1369
|
+
; plot pressure levels
|
1370
|
+
plevs = (ispan(100,1000,25))*1.0
|
1371
|
+
|
1372
|
+
var_at_p = new ((/dimsizes(plevs),dimsizes(var&lat),dimsizes(var&lon)/),double)
|
1373
|
+
copy_VarMeta( theta3d, var_at_p)
|
1374
|
+
var_at_p@lon = var&lon
|
1375
|
+
var_at_p@lat = var&lat
|
1376
|
+
var_at_p@units = var@units
|
1377
|
+
var_at_p@long_name = var@long_name
|
1378
|
+
|
1379
|
+
extrapolate = True ; switch for doing extrapolation below the ground:
|
1380
|
+
intmethod = 1 ; 1: method for temperature, -1: method for geopotential, 0: other vars
|
1381
|
+
tlow = var(nlevels-1,:,:) ; temperature at lowest model level
|
1382
|
+
; (use ground temperature if available)
|
1383
|
+
|
1384
|
+
var_at_p = vinth2p_ecmwf(var,hyam,hybm,plevs,pres3di(nlevels,:,:)*100.,\
|
1385
|
+
intmethod,1.,1,extrapolate,1,tlow,phis)
|
1386
|
+
|
1387
|
+
dist = gc_latlon(leftlat,leftlon,rightlat,rightlon,npoints,2)
|
1388
|
+
trans = linint2_points_Wrap(var_at_p&lon,var_at_p&lat,var_at_p,True,dist@gclon,dist@gclat,2)
|
1389
|
+
|
1390
|
+
return trans
|
1391
|
+
end
|
1392
|
+
;---------------------------------------------------------------
|
1393
|
+
; setting for vertical cross sections based on pure icon input
|
1394
|
+
undef("setSectionFromHybridPressICON")
|
1395
|
+
function setSectionFromHybridPressICON(secLC,secRC,npoints,var,filehandle,timestep)
|
1396
|
+
begin
|
1397
|
+
leftlat = secLC(1)
|
1398
|
+
rightlat = secRC(1)
|
1399
|
+
|
1400
|
+
leftlon = secLC(0)
|
1401
|
+
rightlon = secRC(0)
|
1402
|
+
|
1403
|
+
;config
|
1404
|
+
pressName = "PS"
|
1405
|
+
geopotName = "PHIS"
|
1406
|
+
hybCords = (/"hyam","hybm","hyai","hybi"/)
|
1407
|
+
hyamName = hybCords(0)
|
1408
|
+
hybmName = hybCords(1)
|
1409
|
+
hyaiName = hybCords(2)
|
1410
|
+
hybiName = hybCords(3)
|
1411
|
+
|
1412
|
+
nlevels = 47
|
1413
|
+
plevels = 20
|
1414
|
+
p00 = 1.e3; reference pressure in hPa
|
1415
|
+
rad2deg = 45./atan(1.) ; radians to degrees
|
1416
|
+
|
1417
|
+
u3d = var
|
1418
|
+
phis = filehandle->$pressName$(0,:); dims: (time,cell)
|
1419
|
+
psfc = filehandle->$pressName$(timestep,:); surface pressure, dims: (time,lon.lat)
|
1420
|
+
psfc = psfc*1.e-2; convert to hPa
|
1421
|
+
hyam = filehandle->$hyamName$*1.e-2; convert to hPa
|
1422
|
+
hybm = filehandle->$hybmName$
|
1423
|
+
hyai = filehandle->$hyaiName$*1.e-2; convert to hPa
|
1424
|
+
hybi = filehandle->$hybiName$
|
1425
|
+
klevi = dimsizes(hyai);
|
1426
|
+
klevm = dimsizes(hyam);
|
1427
|
+
|
1428
|
+
; compute 3d pressure
|
1429
|
+
dims = dimsizes(psfc)
|
1430
|
+
print("dims:"+str_join((/nlevels, dims/),"|"))
|
1431
|
+
pres3d = new ((/nlevels, dims/),double)
|
1432
|
+
pres3di = new ((/nlevels+1,dims/),double)
|
1433
|
+
theta3d = new ((/nlevels, dims/),double)
|
1434
|
+
do k = 0, nlevels-1
|
1435
|
+
pres3d(k,:) = psfc(:)*hybm(k) + hyam(k)
|
1436
|
+
end do
|
1437
|
+
do k = 0, nlevels
|
1438
|
+
pres3di(k,:) = psfc(:)*hybi(k) + hyai(k)
|
1439
|
+
end do
|
1440
|
+
|
1441
|
+
theta3d = var
|
1442
|
+
theta3d@units="K"
|
1443
|
+
theta3d@long_name="Temperature"
|
1444
|
+
|
1445
|
+
; if (False) then ; potential temperature
|
1446
|
+
; var = var*(p00/pres3d)^(2./7.)
|
1447
|
+
; end if
|
1448
|
+
|
1449
|
+
x = filehandle->clon *rad2deg; cell center, lon
|
1450
|
+
y = filehandle->clat *rad2deg; cell center, lat
|
1451
|
+
|
1452
|
+
ylat = fspan(-90,90,91)
|
1453
|
+
ylat@units = "degrees_north"
|
1454
|
+
xlon = fspan(-180,180,181)
|
1455
|
+
xlon@units = "degrees_east"
|
1456
|
+
ylat!0 = "ylat"
|
1457
|
+
xlon!0 = "xlon"
|
1458
|
+
|
1459
|
+
u3dll = triple2grid(x,y,u3d,xlon,ylat,False)
|
1460
|
+
pres3dll = triple2grid(x,y,pres3d,xlon,ylat,False)
|
1461
|
+
pres3dill = triple2grid(x,y,pres3di,xlon,ylat,False)
|
1462
|
+
theta3dll = triple2grid(x,y,theta3d,xlon,ylat,False)
|
1463
|
+
phisll = triple2grid(x,y,phis,xlon,ylat,False)
|
1464
|
+
|
1465
|
+
u3dll!1 = "ylat"
|
1466
|
+
u3dll!2 = "xlon"
|
1467
|
+
u3dll&ylat = ylat
|
1468
|
+
u3dll&xlon = xlon
|
1469
|
+
|
1470
|
+
phisll!0 = "ylat"
|
1471
|
+
phisll!1 = "xlon"
|
1472
|
+
phisll&ylat = ylat
|
1473
|
+
phisll&xlon = xlon
|
1474
|
+
|
1475
|
+
copy_VarMeta( u3dll, pres3dill)
|
1476
|
+
copy_VarMeta( u3dll, pres3dll)
|
1477
|
+
copy_VarMeta( u3dll, theta3dll)
|
1478
|
+
|
1479
|
+
; now we try to interpolate from model levels to pressure levels
|
1480
|
+
plevs = (ispan(100,1000,25))*1.0
|
1481
|
+
|
1482
|
+
var_at_p = new ((/dimsizes(plevs),dimsizes(ylat),dimsizes(xlon)/),double)
|
1483
|
+
copy_VarMeta(u3dll, var_at_p)
|
1484
|
+
; var_at_p@ylat =ylat
|
1485
|
+
; var_at_p@xlon =xlon
|
1486
|
+
var_at_p@units = theta3d@units
|
1487
|
+
var_at_p@long_name = theta3d@long_name
|
1488
|
+
|
1489
|
+
extrapolate = True ; switch for doing extrapolation below the ground:
|
1490
|
+
intmethod = 1 ; 1: method for temperature, -1: method for geopotential, 0: other vars
|
1491
|
+
tlow = theta3dll(nlevels-1,:,:) ; temperature at lowest model level
|
1492
|
+
; (use ground temperature if available)
|
1493
|
+
|
1494
|
+
var_at_p = vinth2p_ecmwf(theta3dll, hyam, hybm, plevs, pres3dill(nlevels,:,:)*100.,\
|
1495
|
+
intmethod,1.,1,extrapolate,1,tlow,phisll)
|
1496
|
+
print(min(var_at_p))
|
1497
|
+
|
1498
|
+
dist = gc_latlon(leftlat,leftlon,rightlat,rightlon,npoints,2)
|
1499
|
+
trans = linint2_points_Wrap(xlon,ylat,var_at_p,True,dist@gclon,dist@gclat,2)
|
1500
|
+
|
1501
|
+
return trans
|
1502
|
+
end
|
1503
|
+
;---------------------------------------------------------------
|
1504
|
+
; Create flags array the the grid plot
|
1505
|
+
undef("getFlags")
|
1506
|
+
function getFlags(var,boundslon,boundslat,resource)
|
1507
|
+
begin
|
1508
|
+
flags = new(dimsizes(var),logical,"No_FillValue")
|
1509
|
+
do i = 0,dimsizes(var) - 1
|
1510
|
+
flags(i) = where(all(boundslon(i,:) .gt. resource@mpMaxLonF) .or. \
|
1511
|
+
all(boundslon(i,:) .lt. resource@mpMinLonF) .or. \
|
1512
|
+
all(boundslat(i,:) .gt. resource@mpMaxLatF) .or. \
|
1513
|
+
all(boundslat(i,:) .lt. resource@mpMinLatF), \
|
1514
|
+
False, True)
|
1515
|
+
end do
|
1516
|
+
return flags
|
1517
|
+
end
|
1518
|
+
;---------------------------------------------------------------
|
1519
|
+
; Set the default vector plot resource
|
1520
|
+
undef("setDefaultVectorPlot")
|
1521
|
+
procedure setDefaultVectorPlot(resource, refmagnitude, reflength, style, mindistance)
|
1522
|
+
begin
|
1523
|
+
resource@vcRefMagnitudeF = refmagnitude ; make vectors larger
|
1524
|
+
resource@vcRefLengthF = reflength ; reference vector length
|
1525
|
+
resource@vcGlyphStyle = style ; turn on curly vectors
|
1526
|
+
resource@vcMinDistanceF = mindistance ; thin out vectors
|
1527
|
+
end
|
1528
|
+
;---------------------------------------------------------------
|
1529
|
+
; Return the Colors of a given plot
|
1530
|
+
undef("getColorsFromPlot")
|
1531
|
+
function getColorsFromPlot(plot)
|
1532
|
+
begin
|
1533
|
+
getvalues plot@contour
|
1534
|
+
"cnFillColors" : colors
|
1535
|
+
end getvalues
|
1536
|
+
return colors
|
1537
|
+
end
|
1538
|
+
;---------------------------------------------------------------
|
1539
|
+
; Return the levels of a given plot
|
1540
|
+
undef("getLevelsFromPlot")
|
1541
|
+
function getLevelsFromPlot(plot)
|
1542
|
+
begin
|
1543
|
+
getvalues plot@contour
|
1544
|
+
"cnLevels" : levels
|
1545
|
+
end getvalues
|
1546
|
+
return levels
|
1547
|
+
end
|
1548
|
+
;---------------------------------------------------------------
|
1549
|
+
; Print out some information about the grid plot
|
1550
|
+
undef("printGridPlotInfo")
|
1551
|
+
procedure printGridPlotInfo(colors,levels,flags)
|
1552
|
+
begin
|
1553
|
+
print(colors)
|
1554
|
+
print(levels)
|
1555
|
+
print ("Outside the plot area: " + dimsizes(ind(flags .eq. False)) + \
|
1556
|
+
" triangles - not plotted")
|
1557
|
+
end
|
1558
|
+
;---------------------------------------------------------------
|
1559
|
+
; Create a resource for the grid plot
|
1560
|
+
undef("setupGridResource")
|
1561
|
+
function setupGridResource(var,levels,colors,boundslon,boundslat,wks,plot,debug)
|
1562
|
+
begin
|
1563
|
+
pres = True
|
1564
|
+
pres@gsEdgesOn = True ; Turn on edges
|
1565
|
+
pres@gsFillIndex = 0 ; Solid fill, the default
|
1566
|
+
|
1567
|
+
; First draw the triangles associated with the lowest level.
|
1568
|
+
i = 0
|
1569
|
+
vlow = ind(var .lt. levels(i))
|
1570
|
+
; if no index vlow is found with values less than levels(0), vlow is missing value:
|
1571
|
+
if (.not. ismissing(vlow(0))) then
|
1572
|
+
do j = 0, dimsizes(vlow)-1
|
1573
|
+
pres@gsFillColor = colors(i) ; first color
|
1574
|
+
gsn_polygon(wks,plot,boundslon(vlow(j),:),boundslat(vlow(j),:),pres)
|
1575
|
+
end do
|
1576
|
+
end if
|
1577
|
+
if (debug) then
|
1578
|
+
print("i=" + i + ", Values smaller than "+levels(i)+": " + dimsizes(vlow) + \
|
1579
|
+
" triangles considered, color= " + colors(i))
|
1580
|
+
end if
|
1581
|
+
delete(vlow)
|
1582
|
+
|
1583
|
+
; Now draw the triangles between the lowest and highest levels.
|
1584
|
+
do i = 0, dimsizes(levels) -2
|
1585
|
+
vind = ind(var .ge. levels(i) .and. var .lt. levels(i+1))
|
1586
|
+
; if no index is found, vind is missing value:
|
1587
|
+
if (.not. ismissing(vind(0))) then
|
1588
|
+
do j = 0, dimsizes(vind)-1
|
1589
|
+
pres@gsFillColor = colors(i+1)
|
1590
|
+
gsn_polygon( wks,plot, boundslon(vind(j),:),boundslat(vind(j),:),pres)
|
1591
|
+
end do
|
1592
|
+
end if
|
1593
|
+
if (debug) then
|
1594
|
+
print ("i=" + i + ", Values between " + levels(i) + " and " + levels(i+1) +": "\
|
1595
|
+
+dimsizes(vind) + " triangles considered, color= " + colors(i+1))
|
1596
|
+
end if
|
1597
|
+
delete(vind)
|
1598
|
+
end do
|
1599
|
+
|
1600
|
+
; Finally draw the triangles associated with the highest level.
|
1601
|
+
i = dimsizes(levels) -1
|
1602
|
+
vhig = ind(var .ge. levels(i) )
|
1603
|
+
|
1604
|
+
; if no index vhig is found with values larger levels(max-1), vhig is missing value:
|
1605
|
+
if (.not. ismissing(vhig(0))) then
|
1606
|
+
do j = 0, dimsizes(vhig) -1
|
1607
|
+
pres@gsFillColor = colors(i+1)
|
1608
|
+
gsn_polygon( wks,plot, boundslon(vhig(j),:),boundslat(vhig(j),:),pres)
|
1609
|
+
end do
|
1610
|
+
end if
|
1611
|
+
if (debug) then
|
1612
|
+
print ("i=" + i + ", Values larger than "+levels(i) +": " \
|
1613
|
+
+ dimsizes(vhig) + " triangles considered, color= " + colors(i+1))
|
1614
|
+
end if
|
1615
|
+
delete(vhig)
|
1616
|
+
|
1617
|
+
return pres
|
1618
|
+
end
|
1619
|
+
;---------------------------------------------------------------
|
1620
|
+
; Plot the ICON grid of a variable to the plot.
|
1621
|
+
undef("plotGrid")
|
1622
|
+
procedure plotGrid(workstation,plot,variable,x,bounds,filehandle,resource,debug)
|
1623
|
+
begin
|
1624
|
+
boundslon = bounds(0,:,:)
|
1625
|
+
boundslat = bounds(1,:,:)
|
1626
|
+
|
1627
|
+
latmax=flt2dble(0.0)
|
1628
|
+
latmin=flt2dble(0.0)
|
1629
|
+
lonmax=flt2dble(0.0)
|
1630
|
+
lonmin=flt2dble(0.0)
|
1631
|
+
setBoundsEnds(boundslon,boundslat,lonmin,lonmax,latmin,latmax)
|
1632
|
+
checkLongitude(x,boundslon,lonmin,lonmax,debug)
|
1633
|
+
|
1634
|
+
flags = getFlags(variable,boundslon,boundslat,resource)
|
1635
|
+
|
1636
|
+
colors = getColorsFromPlot(plot)
|
1637
|
+
levels = getLevelsFromPlot(plot)
|
1638
|
+
|
1639
|
+
if (debug) printGridPlotInfo(colors,levels,flags) end if
|
1640
|
+
|
1641
|
+
pres = setupGridResource(variable,levels,colors,boundslon,boundslat,workstation,plot,debug)
|
1642
|
+
end
|
1643
|
+
;---------------------------------------------------------------
|
1644
|
+
; read in mask variable
|
1645
|
+
undef("readMaskVar")
|
1646
|
+
function readMaskVar()
|
1647
|
+
begin
|
1648
|
+
end
|
1649
|
+
;---------------------------------------------------------------
|
1650
|
+
; plot vector/streamlines to resource
|
1651
|
+
undef("plotVecOrStream")
|
1652
|
+
function plotVecOrStream(useScalar,useStreamlines,uvar,vvar,scalarvar,resource,workstation,showMap)
|
1653
|
+
begin
|
1654
|
+
if (useScalar) then
|
1655
|
+
if (useStreamlines) then
|
1656
|
+
if (showMap)
|
1657
|
+
vc = gsn_csm_streamline_contour_map(workstation,uvar,vvar,scalarvar,resource)
|
1658
|
+
else
|
1659
|
+
vc = gsn_streamline_scalar(workstation,uvar,vvar,scalarvar,resource)
|
1660
|
+
end if
|
1661
|
+
else
|
1662
|
+
if (showMap)
|
1663
|
+
vc = gsn_csm_vector_scalar_map(workstation,uvar,vvar,scalarvar,resource)
|
1664
|
+
else
|
1665
|
+
vc = gsn_csm_vector_scalar(workstation,uvar,vvar,scalarvar,resource)
|
1666
|
+
end if
|
1667
|
+
end if
|
1668
|
+
else
|
1669
|
+
if (showMap)
|
1670
|
+
if (useStreamlines) then
|
1671
|
+
vc = gsn_csm_streamline_map(workstation,uvar,vvar,resource)
|
1672
|
+
else
|
1673
|
+
vc = gsn_csm_vector_map(workstation,uvar,vvar,resource)
|
1674
|
+
end if
|
1675
|
+
else
|
1676
|
+
if (useStreamlines) then
|
1677
|
+
vc = gsn_csm_streamline(workstation,uvar,vvar,resource)
|
1678
|
+
else
|
1679
|
+
vc = gsn_csm_vector(workstation,uvar,vvar,resource)
|
1680
|
+
end if
|
1681
|
+
end if
|
1682
|
+
end if
|
1683
|
+
return vc
|
1684
|
+
end
|
1685
|
+
|
1686
|
+
;
|
1687
|
+
; vim:list
|