iconPlot 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|