cdo 1.2.7 → 1.3.0
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/gemspec +2 -2
- data/lib/cdo.rb +204 -279
- data/lib/cdo_lib.rb +415 -0
- data/test/test_cdo.rb +180 -181
- metadata +3 -3
- data/lib/cdo_oo.rb +0 -301
data/lib/cdo_lib.rb
ADDED
@@ -0,0 +1,415 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'open3'
|
3
|
+
require 'logger'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
# Copyright (C) 2011-2013 Ralf Mueller, ralf.mueller@zmaw.de
|
7
|
+
# See COPYING file for copying and redistribution conditions.
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation; version 2 of the License.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
|
18
|
+
# ==============================================================================
|
19
|
+
# CDO calling mechnism
|
20
|
+
module Cdo
|
21
|
+
|
22
|
+
VERSION = "1.2.5"
|
23
|
+
@@file = StringIO.new
|
24
|
+
|
25
|
+
State = {
|
26
|
+
:debug => false,
|
27
|
+
:returnCdf => false,
|
28
|
+
:operators => [],
|
29
|
+
:forceOutput => true,
|
30
|
+
:env => {},
|
31
|
+
:log => false,
|
32
|
+
:logger => Logger.new(@@file),
|
33
|
+
}
|
34
|
+
State[:debug] = ENV.has_key?('DEBUG')
|
35
|
+
State[:logger].formatter = proc do |serverity, time, progname, msg|
|
36
|
+
msg
|
37
|
+
end
|
38
|
+
|
39
|
+
@@CDO = ENV['CDO'].nil? ? 'cdo' : ENV['CDO']
|
40
|
+
|
41
|
+
# Since cdo-1.5.4 undocumented operators are given with the -h option. For
|
42
|
+
# earlier version, they have to be provided manually
|
43
|
+
@@undocumentedOperators = %w[anomaly beta boxavg change_e5lsm change_e5mask
|
44
|
+
change_e5slm chisquare chvar cloudlayer cmd com command complextorect
|
45
|
+
covar0 covar0r daycount daylogs del29feb delday delete deltap deltap_fl
|
46
|
+
delvar diffv divcoslat dumplogo dumplogs duplicate eca_r1mm enlargegrid
|
47
|
+
ensrkhistspace ensrkhisttime eof3d eof3dspatial eof3dtime export_e5ml
|
48
|
+
export_e5res fc2gp fc2sp fillmiss fisher fldcovar fldrms fourier fpressure
|
49
|
+
gather gengrid geopotheight ggstat ggstats globavg gp2fc gradsdes
|
50
|
+
gridverify harmonic hourcount hpressure import_e5ml import_e5res
|
51
|
+
import_obs imtocomplex infos infov interpolate intgrid intgridbil
|
52
|
+
intgridtraj intpoint isosurface lmavg lmean lmmean lmstd log lsmean
|
53
|
+
meandiff2test mergegrid mod moncount monlogs mrotuv mrotuvb mulcoslat ncode
|
54
|
+
ncopy nmltest normal nvar outputbounds outputboundscpt outputcenter
|
55
|
+
outputcenter2 outputcentercpt outputkey outputtri outputvector outputvrml
|
56
|
+
pardup parmul pinfo pinfov pressure_fl pressure_hl read_e5ml remapcon1
|
57
|
+
remapdis1 retocomplex scalllogo scatter seascount select selgridname
|
58
|
+
seloperator selvar selzaxisname setrcaname setvar showvar sinfov smemlogo
|
59
|
+
snamelogo sort sortcode sortlevel sortname sorttaxis sorttimestamp sortvar
|
60
|
+
sp2fc specinfo spectrum sperclogo splitvar stimelogo studentt template1
|
61
|
+
template2 test test2 testdata thinout timcount timcovar tinfo transxy trms
|
62
|
+
tstepcount vardes vardup varmul varquot2test varrms vertwind write_e5ml
|
63
|
+
writegrid writerandom yearcount]
|
64
|
+
|
65
|
+
@@outputOperatorsPattern = /(diff|info|output|griddes|zaxisdes|show|ncode|ndate|nlevel|nmon|nvar|nyear|ntime|npar|gradsdes|pardes)/
|
66
|
+
|
67
|
+
private
|
68
|
+
def Cdo.getOperators(force=false)
|
69
|
+
# Do NOT compute anything, if it is not required
|
70
|
+
return State[:operators] unless (State[:operators].empty? or force)
|
71
|
+
cmd = @@CDO + ' 2>&1'
|
72
|
+
help = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
|
73
|
+
if 5 >= help.size
|
74
|
+
warn "Operators could not get listed by running the CDO binary (#{@@CDO})"
|
75
|
+
pp help if Cdo.debug
|
76
|
+
exit
|
77
|
+
end
|
78
|
+
# in version 1.5.6 the output of '-h' has changed
|
79
|
+
State[:operators] = case
|
80
|
+
when Cdo.version < "1.5.6"
|
81
|
+
(help[help.index("Operators:")+1].split + @@undocumentedOperators).uniq
|
82
|
+
when Cdo.version <= "1.7.0"
|
83
|
+
help[(help.index("Operators:")+1)..help.index(help.find {|v| v =~ /CDO version/}) - 2].join(' ').split
|
84
|
+
else
|
85
|
+
IO.popen(@@CDO + ' --operators').readlines.map {|l| l.split(' ').first}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def Cdo.hasError(cmd,retvals)
|
90
|
+
if (State[:debug])
|
91
|
+
puts("RETURNCODE: #{retvals[:returncode]}")
|
92
|
+
end
|
93
|
+
if ( 0 != retvals[:returncode] )
|
94
|
+
puts("Error in calling:")
|
95
|
+
puts(">>> "+cmd+"<<<")
|
96
|
+
puts(retvals[:stderr])
|
97
|
+
return true
|
98
|
+
else
|
99
|
+
return false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def Cdo.env=(envHash)
|
104
|
+
State[:env] = envHash
|
105
|
+
end
|
106
|
+
def Cdo.env; State[:env]; end
|
107
|
+
|
108
|
+
def Cdo.call(cmd)
|
109
|
+
if (State[:debug])
|
110
|
+
puts '# DEBUG ====================================================================='
|
111
|
+
pp Cdo.env unless Cdo.env.empty?
|
112
|
+
puts 'CMD: '
|
113
|
+
puts cmd
|
114
|
+
puts '# DEBUG ====================================================================='
|
115
|
+
end
|
116
|
+
stdin, stdout, stderr, wait_thr = Open3.popen3(Cdo.env,cmd)
|
117
|
+
|
118
|
+
{
|
119
|
+
:stdout => stdout.read,
|
120
|
+
:stderr => stderr.read,
|
121
|
+
:returncode => wait_thr.value.exitstatus
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
def Cdo.run(cmd,ofile='',options='',returnCdf=false,force=nil,returnArray=nil,returnMaArray=nil)
|
126
|
+
cmd = "#{@@CDO} -O #{options} #{cmd} "
|
127
|
+
case ofile
|
128
|
+
when $stdout
|
129
|
+
retvals = Cdo.call(cmd)
|
130
|
+
State[:logger].info(cmd+"\n") if State[:log]
|
131
|
+
unless hasError(cmd,retvals)
|
132
|
+
return retvals[:stdout].split($/).map {|l| l.chomp.strip}
|
133
|
+
else
|
134
|
+
raise ArgumentError,"CDO did NOT run successfully!"
|
135
|
+
end
|
136
|
+
else
|
137
|
+
force = State[:forceOutput] if force.nil?
|
138
|
+
if force or not File.exists?(ofile.to_s)
|
139
|
+
ofile = MyTempfile.path if ofile.nil?
|
140
|
+
cmd << "#{ofile}"
|
141
|
+
retvals = call(cmd)
|
142
|
+
State[:logger].info(cmd+"\n") if State[:log]
|
143
|
+
if hasError(cmd,retvals)
|
144
|
+
raise ArgumentError,"CDO did NOT run successfully!"
|
145
|
+
end
|
146
|
+
else
|
147
|
+
warn "Use existing file '#{ofile}'" if Cdo.debug
|
148
|
+
end
|
149
|
+
end
|
150
|
+
if not returnArray.nil?
|
151
|
+
Cdo.readArray(ofile,returnArray)
|
152
|
+
elsif not returnMaArray.nil?
|
153
|
+
Cdo.readMaArray(ofile,returnMaArray)
|
154
|
+
elsif returnCdf or State[:returnCdf]
|
155
|
+
Cdo.readCdf(ofile)
|
156
|
+
else
|
157
|
+
return ofile
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def Cdo.parseArgs(args)
|
162
|
+
# splitinto hash-like args and the rest
|
163
|
+
operatorArgs = args.reject {|a| a.class == Hash}
|
164
|
+
opts = operatorArgs.empty? ? '' : ',' + operatorArgs.join(',')
|
165
|
+
io = args.find {|a| a.class == Hash}
|
166
|
+
io = {} if io.nil?
|
167
|
+
args.delete_if {|a| a.class == Hash}
|
168
|
+
# join input streams together if possible
|
169
|
+
io[:input] = io[:input].join(' ') if io[:input].respond_to?(:join)
|
170
|
+
return [io,opts]
|
171
|
+
end
|
172
|
+
|
173
|
+
def Cdo.method_missing(sym, *args, &block)
|
174
|
+
## args is expected to look like [opt1,...,optN,:input => iStream,:output => oStream] where
|
175
|
+
# iStream could be another CDO call (timmax(selname(Temp,U,V,ifile.nc))
|
176
|
+
puts "Operator #{sym.to_s} is called" if State[:debug]
|
177
|
+
if getOperators.include?(sym.to_s)
|
178
|
+
io, opts = Cdo.parseArgs(args)
|
179
|
+
if @@outputOperatorsPattern.match(sym)
|
180
|
+
run(" -#{sym.to_s}#{opts} #{io[:input]} ",$stdout)
|
181
|
+
else
|
182
|
+
run(" -#{sym.to_s}#{opts} #{io[:input]} ",io[:output],io[:options],io[:returnCdf],io[:force],io[:returnArray],io[:returnMaArray])
|
183
|
+
end
|
184
|
+
else
|
185
|
+
raise ArgumentError,"Operator #{sym.to_s} not found"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def Cdo.loadCdf
|
190
|
+
begin
|
191
|
+
require "numru/netcdf_miss"
|
192
|
+
include NumRu
|
193
|
+
rescue LoadError
|
194
|
+
warn "Could not load ruby's netcdf bindings. Please install it."
|
195
|
+
raise
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def Cdo.getSupportedLibs(force=false)
|
200
|
+
return unless (State[:libs].nil? or force)
|
201
|
+
_, _, stderr, _ = Open3.popen3(@@CDO + " -V")
|
202
|
+
supported = stderr.readlines.map(&:chomp)
|
203
|
+
with = supported.grep(/(with|Features)/)[0].split(':')[1].split.map(&:downcase)
|
204
|
+
libs = supported.grep(/library version/).map {|l|
|
205
|
+
l.strip.split(':').map {|l|
|
206
|
+
l.split.first.downcase
|
207
|
+
}[0,2]
|
208
|
+
}
|
209
|
+
State[:libs] = {}
|
210
|
+
with.flatten.each {|k| State[:libs][k]=true}
|
211
|
+
libs.each {|lib,version| State[:libs][lib] = version}
|
212
|
+
end
|
213
|
+
|
214
|
+
public
|
215
|
+
def Cdo.debug=(value)
|
216
|
+
State[:debug] = value
|
217
|
+
end
|
218
|
+
def Cdo.debug
|
219
|
+
State[:debug]
|
220
|
+
end
|
221
|
+
def Cdo.forceOutput=(value)
|
222
|
+
State[:forceOutput] = value
|
223
|
+
end
|
224
|
+
def Cdo.forceOutput
|
225
|
+
State[:forceOutput]
|
226
|
+
end
|
227
|
+
def Cdo.log=(value)
|
228
|
+
State[:log] = value
|
229
|
+
end
|
230
|
+
|
231
|
+
def Cdo.log
|
232
|
+
State[:log]
|
233
|
+
end
|
234
|
+
|
235
|
+
def Cdo.version
|
236
|
+
cmd = @@CDO + ' 2>&1'
|
237
|
+
help = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
|
238
|
+
regexp = %r{CDO version (\d.*), Copyright}
|
239
|
+
line = help.find {|v| v =~ regexp}
|
240
|
+
version = regexp.match(line)[1]
|
241
|
+
end
|
242
|
+
|
243
|
+
def Cdo.setReturnCdf(value=true)
|
244
|
+
if value
|
245
|
+
Cdo.loadCdf
|
246
|
+
end
|
247
|
+
State[:returnCdf] = value
|
248
|
+
end
|
249
|
+
|
250
|
+
def Cdo.unsetReturnCdf
|
251
|
+
setReturnCdf(false)
|
252
|
+
end
|
253
|
+
|
254
|
+
def Cdo.returnCdf
|
255
|
+
State[:returnCdf]
|
256
|
+
end
|
257
|
+
|
258
|
+
def Cdo.hasCdo?(bin=@@CDO)
|
259
|
+
return true if File.exists?(@@CDO) and File.executable?(@@CDO)
|
260
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each {|path|
|
261
|
+
return true if File.exists?([path,bin].join(File::SEPARATOR))
|
262
|
+
}
|
263
|
+
end
|
264
|
+
|
265
|
+
# test if @@CDO can be used
|
266
|
+
def Cdo.checkCdo
|
267
|
+
unless hasCdo?(@@CDO)
|
268
|
+
warn "Testing application #@@CDO is not available!"
|
269
|
+
exit 1
|
270
|
+
else
|
271
|
+
puts "Using CDO: #@@CDO"
|
272
|
+
puts IO.popen(@@CDO + " -V").readlines
|
273
|
+
end
|
274
|
+
return true
|
275
|
+
end
|
276
|
+
|
277
|
+
def Cdo.setCdo(cdo)
|
278
|
+
puts "Will use #{cdo} instead of #@@CDO" if Cdo.debug
|
279
|
+
@@CDO = cdo
|
280
|
+
Cdo.getOperators(true)
|
281
|
+
Cdo.getSupportedLibs(true)
|
282
|
+
end
|
283
|
+
|
284
|
+
def Cdo.getCdo
|
285
|
+
@@CDO
|
286
|
+
end
|
287
|
+
|
288
|
+
def Cdo.operators
|
289
|
+
Cdo.getOperators if State[:operators].empty?
|
290
|
+
State[:operators]
|
291
|
+
end
|
292
|
+
|
293
|
+
def Cdo.libs
|
294
|
+
getSupportedLibs
|
295
|
+
State[:libs]
|
296
|
+
end
|
297
|
+
|
298
|
+
def Cdo.hasLib?(lib)
|
299
|
+
return Cdo.libs.has_key?(lib)
|
300
|
+
return false
|
301
|
+
end
|
302
|
+
|
303
|
+
def Cdo.libsVersion(lib)
|
304
|
+
unless Cdo.hasLib?(lib)
|
305
|
+
raise ArgumentError, "Cdo does NOT have support for '#{lib}'"
|
306
|
+
else
|
307
|
+
if State[:libs][lib].kind_of? String
|
308
|
+
return State[:libs][lib]
|
309
|
+
else
|
310
|
+
warn "No version information available about '#{lib}'"
|
311
|
+
return false
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def Cdo.showlog
|
317
|
+
@@file.rewind
|
318
|
+
puts @@file.read
|
319
|
+
end
|
320
|
+
|
321
|
+
#==================================================================
|
322
|
+
# Addional operotors:
|
323
|
+
#------------------------------------------------------------------
|
324
|
+
def Cdo.boundaryLevels(args)
|
325
|
+
ilevels = Cdo.showlevel(:input => args[:input])[0].split.map(&:to_f)
|
326
|
+
bound_levels = Array.new(ilevels.size+1)
|
327
|
+
bound_levels[0] = 0
|
328
|
+
(1..ilevels.size).each {|i|
|
329
|
+
bound_levels[i] =bound_levels[i-1] + 2*(ilevels[i-1]-bound_levels[i-1])
|
330
|
+
}
|
331
|
+
bound_levels
|
332
|
+
end
|
333
|
+
|
334
|
+
def Cdo.thicknessOfLevels(args)
|
335
|
+
bound_levels = Cdo.boundaryLevels(args)
|
336
|
+
delta_levels = []
|
337
|
+
bound_levels.each_with_index {|v,i|
|
338
|
+
next if 0 == i
|
339
|
+
delta_levels << v - bound_levels[i-1]
|
340
|
+
}
|
341
|
+
delta_levels
|
342
|
+
end
|
343
|
+
|
344
|
+
def Cdo.readCdf(iFile)
|
345
|
+
Cdo.loadCdf unless State[:returnCdf]
|
346
|
+
NetCDF.open(iFile)
|
347
|
+
end
|
348
|
+
|
349
|
+
def Cdo.openCdf(iFile)
|
350
|
+
Cdo.loadCdf unless State[:returnCdf]
|
351
|
+
NetCDF.open(iFile,'r+')
|
352
|
+
end
|
353
|
+
|
354
|
+
def Cdo.readArray(iFile,varname)
|
355
|
+
filehandle = Cdo.readCdf(iFile)
|
356
|
+
if filehandle.var_names.include?(varname)
|
357
|
+
# return the data array
|
358
|
+
filehandle.var(varname).get
|
359
|
+
else
|
360
|
+
raise ArgumentError, "Cannot find variable '#{varname}'"
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def Cdo.readMaArray(iFile,varname)
|
365
|
+
filehandle = Cdo.readCdf(iFile)
|
366
|
+
if filehandle.var_names.include?(varname)
|
367
|
+
# return the data array
|
368
|
+
filehandle.var(varname).get_with_miss
|
369
|
+
else
|
370
|
+
raise ArgumentError,"Cannot find variable '#{varname}'"
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def Cdo.help(operator=nil)
|
375
|
+
if operator.nil?
|
376
|
+
puts Cdo.call([@@CDO,'-h'].join(' '))[:stderr]
|
377
|
+
else
|
378
|
+
operator = operator.to_s unless String == operator.class
|
379
|
+
if Cdo.operators.include?(operator)
|
380
|
+
puts Cdo.call([@@CDO,'-h',operator].join(' '))[:stdout]
|
381
|
+
else
|
382
|
+
puts "Unknown operator #{operator}"
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# Helper module for easy temp file handling
|
389
|
+
module MyTempfile
|
390
|
+
require 'tempfile'
|
391
|
+
@@_tempfiles = []
|
392
|
+
@@persistent_tempfiles = false
|
393
|
+
@@N = 10000000
|
394
|
+
|
395
|
+
def MyTempfile.setPersist(value)
|
396
|
+
@@persistent_tempfiles = value
|
397
|
+
end
|
398
|
+
|
399
|
+
def MyTempfile.path
|
400
|
+
unless @@persistent_tempfiles
|
401
|
+
t = Tempfile.new(self.class.to_s)
|
402
|
+
@@_tempfiles << t
|
403
|
+
@@_tempfiles << t.path
|
404
|
+
t.path
|
405
|
+
else
|
406
|
+
t = "_"+rand(@@N).to_s
|
407
|
+
@@_tempfiles << t
|
408
|
+
t
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def MyTempfile.showFiles
|
413
|
+
@@_tempfiles.each {|f| print(f+" ") if f.kind_of? String}
|
414
|
+
end
|
415
|
+
end
|
data/test/test_cdo.rb
CHANGED
@@ -9,91 +9,88 @@ require 'pp'
|
|
9
9
|
#===============================================================================
|
10
10
|
def rm(files); files.each {|f| FileUtils.rm(f) if File.exists?(f)};end
|
11
11
|
|
12
|
+
@show = ENV.has_key?('SHOW')
|
13
|
+
|
12
14
|
class TestCdo < Minitest::Test
|
13
15
|
|
14
16
|
DEFAULT_CDO_PATH = 'cdo'
|
15
17
|
|
18
|
+
def setup
|
19
|
+
@cdo = Cdo.new
|
20
|
+
end
|
21
|
+
|
16
22
|
def test_cdo
|
17
|
-
assert_equal(true
|
23
|
+
assert_equal(true,@cdo.check)
|
18
24
|
if ENV['CDO']
|
19
|
-
assert_equal(ENV['CDO']
|
25
|
+
assert_equal(ENV['CDO'],@cdo.cdo)
|
20
26
|
else
|
21
|
-
assert_equal(DEFAULT_CDO_PATH
|
27
|
+
assert_equal(DEFAULT_CDO_PATH,@cdo.cdo)
|
22
28
|
end
|
23
|
-
newCDO="#{ENV['HOME']}/local/bin/cdo"
|
29
|
+
newCDO="#{ENV['HOME']}/local/bin/cdo-dev"
|
24
30
|
if File.exist?(newCDO) then
|
25
|
-
Cdo.
|
26
|
-
assert_equal(true,
|
27
|
-
assert_equal(newCDO,
|
31
|
+
cdo = Cdo.new(:cdo => newCDO)
|
32
|
+
assert_equal(true,cdo.check)
|
33
|
+
assert_equal(newCDO,cdo.cdo)
|
28
34
|
end
|
29
35
|
end
|
30
36
|
def test_getOperators
|
31
37
|
%w[for random stdatm info showlevel sinfo remap geopotheight mask topo thicknessOfLevels].each {|op|
|
32
38
|
if ["thicknessOfLevels"].include?(op)
|
33
|
-
assert(
|
39
|
+
assert(@cdo.respond_to?(op),"Operator '#{op}' not found")
|
34
40
|
else
|
35
|
-
assert(
|
41
|
+
assert(@cdo.operators.include?(op),"Operator '#{op}' not found")
|
36
42
|
end
|
37
43
|
}
|
38
|
-
assert(
|
44
|
+
assert(@cdo.operators.include?('diff'),"Operator alias 'diff' is not callable")
|
39
45
|
end
|
40
46
|
def test_listAllOperators
|
41
|
-
|
47
|
+
assert(@cdo.operators.size > 700,"cound not find enough operators")
|
42
48
|
end
|
43
49
|
|
44
50
|
def test_outputOperators
|
45
|
-
|
46
|
-
levels =
|
51
|
+
@cdo.debug = true
|
52
|
+
levels = @cdo.showlevel(:input => "-stdatm,0")
|
47
53
|
assert_equal([0,0].map(&:to_s),levels)
|
48
54
|
|
49
|
-
info =
|
50
|
-
assert_equal("
|
55
|
+
info = @cdo.sinfo(:input => "-stdatm,0")
|
56
|
+
assert_equal("GRIB",info[0].split(':').last.strip)
|
51
57
|
|
52
|
-
values =
|
53
|
-
assert_equal(["1013.25", "288"],values)
|
54
|
-
values =
|
55
|
-
assert_equal(["1013.25", "271.913", "288", "240.591"],values)
|
56
|
-
values =
|
57
|
-
assert_equal(["0", "10000","0", "10000"],values)
|
58
|
+
values = @cdo.outputkey("value",:input => "-stdatm,0")
|
59
|
+
assert_equal(["1013.25", "288"],values[-2..-1])
|
60
|
+
values = @cdo.outputkey("value",:input => "-stdatm,0,10000")
|
61
|
+
assert_equal(["1013.25", "271.913", "288", "240.591"],values[-4..-1])
|
62
|
+
values = @cdo.outputkey("level",:input => "-stdatm,0,10000")
|
63
|
+
assert_equal(["0", "10000","0", "10000"],values[-4..-1])
|
58
64
|
end
|
59
65
|
def test_CDO_version
|
60
|
-
assert("1.4.3.1" <
|
66
|
+
assert("1.4.3.1" < @cdo.version,"Version too low: #{@cdo.version}")
|
67
|
+
assert("1.8.0" > @cdo.version,"Version too high: #{@cdo.version}")
|
61
68
|
end
|
62
69
|
def test_args
|
63
|
-
ofile0 =
|
64
|
-
ofile1 =
|
65
|
-
ofile2 =
|
66
|
-
ofile3 =
|
67
|
-
info =
|
70
|
+
ofile0 = @cdo.stdatm(0,20,40,80,200,230,400,600,1100)
|
71
|
+
ofile1 = @cdo.intlevel(0,10,50,100,500,1000, :input => ofile0)
|
72
|
+
ofile2 = @cdo.intlevel([0,10,50,100,500,1000],:input => ofile0)
|
73
|
+
ofile3 = @cdo.sub(:input => [ofile1,ofile2].join(' '))
|
74
|
+
info = @cdo.infon(:input => ofile3)
|
68
75
|
(1...info.size).each {|i| assert_equal(0.0,info[i].split[-1].to_f)}
|
69
76
|
end
|
70
77
|
def test_operator_options
|
71
|
-
|
78
|
+
@cdo.debug=true
|
72
79
|
targetLevels = [0,10,50,100,200,400,1000]
|
73
|
-
levels =
|
80
|
+
levels = @cdo.showlevel(:input => " -stdatm,#{targetLevels.join(',')}")
|
74
81
|
[0,1].each {|i| assert_equal(targetLevels.join(' '),levels[i])}
|
75
|
-
|
76
|
-
def test_CDO_options
|
77
|
-
names = Cdo.showname(:input => "-stdatm,0",:options => "-f nc")
|
82
|
+
names = @cdo.showname(:input => "-stdatm,0",:options => "-f nc")
|
78
83
|
assert_equal(["P T"],names)
|
79
|
-
|
80
|
-
if Cdo.hasLib?("sz")
|
81
|
-
ofile = Cdo.topo(:output => ofile,:options => "-z szip")
|
82
|
-
assert_equal(["GRIB SZIP"],Cdo.showformat(:input => ofile))
|
83
|
-
else
|
84
|
-
ofile = Cdo.topo
|
85
|
-
assert_equal(["GRIB"],Cdo.showformat(:input => ofile))
|
86
|
-
end
|
87
84
|
end
|
88
85
|
def test_chain
|
89
|
-
|
90
|
-
ofile =
|
91
|
-
assert_equal(["veloc"]
|
86
|
+
@cdo.debug = true
|
87
|
+
ofile = @cdo.setname('veloc',:input => " -copy -random,r1x1",:options => "-f nc")
|
88
|
+
assert_equal(["veloc"],@cdo.showname(:input => ofile))
|
92
89
|
end
|
93
90
|
|
94
91
|
def test_diff
|
95
|
-
diffv_ =
|
96
|
-
diff_ =
|
92
|
+
diffv_ = @cdo.diffn(:input => "-random,r1x1 -random,r1x1")
|
93
|
+
diff_ = @cdo.diffv(:input => "-random,r1x1 -random,r1x1")
|
97
94
|
return
|
98
95
|
|
99
96
|
assert_equal(diffv[1].split(' ')[-1],"random")
|
@@ -102,34 +99,29 @@ class TestCdo < Minitest::Test
|
|
102
99
|
assert_equal(diff[1].split(' ')[-3],"0.53060")
|
103
100
|
end
|
104
101
|
|
105
|
-
def test_operators
|
106
|
-
assert_includes(Cdo.operators,"infov")
|
107
|
-
assert_includes(Cdo.operators,"showlevel")
|
108
|
-
end
|
109
|
-
|
110
102
|
def test_bndLevels
|
111
|
-
ofile =
|
103
|
+
ofile = @cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:options => "-f nc")
|
112
104
|
assert_equal([0, 50.0, 150.0, 350.0, 650.0, 1100.0, 1700.0, 2500.0, 3500.0, 4500.0, 5500.0],
|
113
|
-
|
105
|
+
@cdo.boundaryLevels(:input => "-selname,T #{ofile}"))
|
114
106
|
assert_equal([50.0, 100.0, 200.0, 300.0, 450.0, 600.0, 800.0, 1000.0, 1000.0, 1000.0],
|
115
|
-
|
107
|
+
@cdo.thicknessOfLevels(:input => ofile))
|
116
108
|
end
|
117
109
|
|
118
110
|
def test_combine
|
119
111
|
ofile0, ofile1 = MyTempfile.path, MyTempfile.path
|
120
|
-
|
121
|
-
|
122
|
-
|
112
|
+
@cdo.fldsum(:input => @cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:options => "-f nc"),:output => ofile0)
|
113
|
+
@cdo.fldsum(:input => "-stdatm,25,100,250,500,875,1400,2100,3000,4000,5000",:options => "-f nc",:output => ofile1)
|
114
|
+
@cdo.returnCdf = true
|
123
115
|
MyTempfile.showFiles
|
124
|
-
diff =
|
116
|
+
diff = @cdo.sub(:input => [ofile0,ofile1].join(' ')).var('T').get
|
125
117
|
assert_equal(0.0,diff.min)
|
126
118
|
assert_equal(0.0,diff.max)
|
127
|
-
|
119
|
+
@cdo.returnCdf = false
|
128
120
|
end
|
129
121
|
|
130
122
|
def test_tempfile
|
131
123
|
ofile0, ofile1 = MyTempfile.path, MyTempfile.path
|
132
|
-
|
124
|
+
assert(ofile0 != ofile1, "Found equal tempfiles!")
|
133
125
|
# Tempfile should not disappeare even if the GC was started
|
134
126
|
puts ofile0
|
135
127
|
assert(File.exist?(ofile0))
|
@@ -139,49 +131,49 @@ class TestCdo < Minitest::Test
|
|
139
131
|
|
140
132
|
def test_returnCdf
|
141
133
|
ofile = rand(0xfffff).to_s + '_test_returnCdf.nc'
|
142
|
-
vals =
|
134
|
+
vals = @cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:output => ofile,:options => "-f nc")
|
143
135
|
assert_equal(ofile,vals)
|
144
|
-
|
145
|
-
vals =
|
136
|
+
@cdo.returnCdf = true
|
137
|
+
vals = @cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:output => ofile,:options => "-f nc")
|
146
138
|
assert_equal(["lon","lat","level","P","T"],vals.var_names)
|
147
139
|
assert_equal(276,vals.var("T").get.flatten.mean.floor)
|
148
|
-
|
149
|
-
vals =
|
140
|
+
@cdo.returnCdf = false
|
141
|
+
vals = @cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:output => ofile,:options => "-f nc")
|
150
142
|
assert_equal(ofile,vals)
|
151
143
|
FileUtils.rm(ofile)
|
152
144
|
end
|
153
145
|
def test_simple_returnCdf
|
154
146
|
ofile0, ofile1 = MyTempfile.path, MyTempfile.path
|
155
|
-
sum =
|
147
|
+
sum = @cdo.fldsum(:input => @cdo.stdatm(0,:options => "-f nc"),
|
156
148
|
:returnCdf => true).var("P").get
|
157
149
|
assert_equal(1013.25,sum.min)
|
158
|
-
sum =
|
150
|
+
sum = @cdo.fldsum(:input => @cdo.stdatm(0,:options => "-f nc"),:output => ofile0)
|
159
151
|
assert_equal(ofile0,sum)
|
160
152
|
test_returnCdf
|
161
153
|
end
|
162
154
|
def test_force
|
163
155
|
outs = []
|
164
156
|
# tempfiles
|
165
|
-
outs <<
|
166
|
-
outs <<
|
167
|
-
|
157
|
+
outs << @cdo.stdatm(0,10,20)
|
158
|
+
outs << @cdo.stdatm(0,10,20)
|
159
|
+
assert(outs[0] != outs[1])
|
168
160
|
|
169
161
|
# deticated output, force = true
|
170
162
|
outs.clear
|
171
|
-
outs <<
|
163
|
+
outs << @cdo.stdatm(0,10,20,:output => 'test_force')
|
172
164
|
mtime0 = File.stat(outs[-1]).mtime
|
173
|
-
outs <<
|
165
|
+
outs << @cdo.stdatm(0,10,20,:output => 'test_force')
|
174
166
|
mtime1 = File.stat(outs[-1]).mtime
|
175
|
-
|
167
|
+
assert(mtime0 != mtime1)
|
176
168
|
assert_equal(outs[0],outs[1])
|
177
169
|
FileUtils.rm('test_force')
|
178
170
|
outs.clear
|
179
171
|
|
180
172
|
# dedicated output, force = false
|
181
173
|
ofile = 'test_force_false'
|
182
|
-
outs <<
|
174
|
+
outs << @cdo.stdatm(0,10,20,:output => ofile,:force => false)
|
183
175
|
mtime0 = File.stat(outs[-1]).mtime
|
184
|
-
outs <<
|
176
|
+
outs << @cdo.stdatm(0,10,20,:output => ofile,:force => false)
|
185
177
|
mtime1 = File.stat(outs[-1]).mtime
|
186
178
|
assert_equal(mtime0,mtime1)
|
187
179
|
assert_equal(outs[0],outs[1])
|
@@ -190,10 +182,10 @@ class TestCdo < Minitest::Test
|
|
190
182
|
|
191
183
|
# dedicated output, global force setting
|
192
184
|
ofile = 'test_force_global'
|
193
|
-
|
194
|
-
outs <<
|
185
|
+
@cdo.forceOutput = false
|
186
|
+
outs << @cdo.stdatm(0,10,20,:output => ofile)
|
195
187
|
mtime0 = File.stat(outs[-1]).mtime
|
196
|
-
outs <<
|
188
|
+
outs << @cdo.stdatm(0,10,20,:output => ofile)
|
197
189
|
mtime1 = File.stat(outs[-1]).mtime
|
198
190
|
assert_equal(mtime0,mtime1)
|
199
191
|
assert_equal(outs[0],outs[1])
|
@@ -204,20 +196,20 @@ class TestCdo < Minitest::Test
|
|
204
196
|
def test_thickness
|
205
197
|
levels = "25 100 250 500 875 1400 2100 3000 4000 5000".split
|
206
198
|
targetThicknesses = [50.0, 100.0, 200.0, 300.0, 450.0, 600.0, 800.0, 1000.0, 1000.0, 1000.0]
|
207
|
-
assert_equal(targetThicknesses,
|
199
|
+
assert_equal(targetThicknesses, @cdo.thicknessOfLevels(:input => "-selname,T -stdatm,#{levels.join(',')}"))
|
208
200
|
end
|
209
201
|
|
210
202
|
def test_showlevels
|
211
203
|
sourceLevels = %W{25 100 250 500 875 1400 2100 3000 4000 5000}
|
212
204
|
assert_equal(sourceLevels,
|
213
|
-
|
205
|
+
@cdo.showlevel(:input => "-selname,T #{@cdo.stdatm(*sourceLevels,:options => '-f nc')}")[0].split)
|
214
206
|
end
|
215
207
|
|
216
208
|
def test_verticalLevels
|
217
|
-
|
209
|
+
@cdo.debug = true
|
218
210
|
targetThicknesses = [50.0, 100.0, 200.0, 300.0, 450.0, 600.0, 800.0, 1000.0, 1000.0, 1000.0]
|
219
211
|
sourceLevels = %W{25 100 250 500 875 1400 2100 3000 4000 5000}
|
220
|
-
thicknesses =
|
212
|
+
thicknesses = @cdo.thicknessOfLevels(:input => "-selname,T #{@cdo.stdatm(*sourceLevels,:options => '-f nc')}")
|
221
213
|
assert_equal(targetThicknesses,thicknesses)
|
222
214
|
end
|
223
215
|
|
@@ -231,31 +223,31 @@ class TestCdo < Minitest::Test
|
|
231
223
|
end
|
232
224
|
|
233
225
|
def test_returnArray
|
234
|
-
temperature =
|
235
|
-
|
236
|
-
|
226
|
+
temperature = @cdo.stdatm(0,:options => '-f nc',:returnCdf => true).var('T').get.flatten[0]
|
227
|
+
assert_raises ArgumentError do
|
228
|
+
@cdo.stdatm(0,:options => '-f nc',:returnArray => 'TT')
|
237
229
|
end
|
238
|
-
temperature =
|
230
|
+
temperature = @cdo.stdatm(0,:options => '-f nc',:returnArray => 'T')
|
239
231
|
assert_equal(288.0,temperature.flatten[0])
|
240
|
-
pressure =
|
232
|
+
pressure = @cdo.stdatm(0,1000,:options => '-f nc -b F64',:returnArray => 'P')
|
241
233
|
assert_equal("1013.25 898.543456035875",pressure.flatten.to_a.join(' '))
|
242
234
|
end
|
243
235
|
def test_returnMaArray
|
244
|
-
|
245
|
-
topo =
|
236
|
+
@cdo.debug = true
|
237
|
+
topo = @cdo.topo(:options => '-f nc',:returnMaArray => 'topo')
|
246
238
|
assert_equal(-1890.0,topo.mean.round)
|
247
|
-
bathy =
|
248
|
-
:input =>
|
239
|
+
bathy = @cdo.setrtomiss(0,10000,
|
240
|
+
:input => @cdo.topo(:options => '-f nc'),:returnMaArray => 'topo')
|
249
241
|
assert_equal(-3386.0,bathy.mean.round)
|
250
|
-
oro =
|
251
|
-
:input =>
|
242
|
+
oro = @cdo.setrtomiss(-10000,0,
|
243
|
+
:input => @cdo.topo(:options => '-f nc'),:returnMaArray => 'topo')
|
252
244
|
assert_equal(1142.0,oro.mean.round)
|
253
|
-
bathy =
|
245
|
+
bathy = @cdo.remapnn('r2x2',:input => @cdo.topo(:options => '-f nc'), :returnMaArray => 'topo')
|
254
246
|
assert_equal(-4298.0,bathy[0,0])
|
255
247
|
assert_equal(-2669.0,bathy[1,0])
|
256
|
-
ta =
|
257
|
-
tb =
|
258
|
-
withMask =
|
248
|
+
ta = @cdo.remapnn('r2x2',:input => @cdo.topo(:options => '-f nc'))
|
249
|
+
tb = @cdo.subc(-2669.0,:input => ta)
|
250
|
+
withMask = @cdo.div(:input => ta+" "+tb,:returnMaArray => 'topo')
|
259
251
|
assert(-8.0e+33 > withMask[1,0])
|
260
252
|
assert(0 < withMask[0,0])
|
261
253
|
assert(0 < withMask[0,1])
|
@@ -263,131 +255,123 @@ class TestCdo < Minitest::Test
|
|
263
255
|
end
|
264
256
|
|
265
257
|
def test_errorException
|
266
|
-
|
258
|
+
@cdo.debug = true
|
267
259
|
# stdout operators get get wrong input
|
268
|
-
|
269
|
-
|
260
|
+
assert_raises ArgumentError do
|
261
|
+
@cdo.showname(:input => '-for,d')
|
270
262
|
end
|
271
263
|
# non-existing operator
|
272
|
-
|
273
|
-
|
264
|
+
assert_raises ArgumentError do
|
265
|
+
@cdo.neverDefinedOperator()
|
274
266
|
end
|
275
267
|
# standard opertor get mis-spelled value
|
276
|
-
|
277
|
-
|
268
|
+
assert_raises ArgumentError do
|
269
|
+
@cdo.remapnn('r-10x10')
|
278
270
|
end
|
279
271
|
# standard operator get unexisting operator as input stream
|
280
|
-
|
281
|
-
|
272
|
+
assert_raises ArgumentError do
|
273
|
+
@cdo.remapnn('r10x10',:input => '-99topo')
|
282
274
|
end
|
283
275
|
# missing input stream
|
284
|
-
|
285
|
-
|
276
|
+
assert_raises ArgumentError do
|
277
|
+
@cdo.setname('setname')
|
286
278
|
end
|
287
279
|
# missing input stream for stdout-operator
|
288
|
-
|
289
|
-
|
280
|
+
assert_raises ArgumentError do
|
281
|
+
@cdo.showname
|
290
282
|
end
|
291
283
|
end
|
292
284
|
|
293
285
|
def test_inputArray
|
294
286
|
# check for file input
|
295
|
-
fileA =
|
296
|
-
fileB =
|
287
|
+
fileA = @cdo.stdatm(0)
|
288
|
+
fileB = @cdo.stdatm(0)
|
297
289
|
files = [fileA,fileB]
|
298
|
-
assert_equal(
|
299
|
-
|
300
|
-
assert_nil(
|
290
|
+
assert_equal(@cdo.diffv(:input => files.join(' ')),
|
291
|
+
@cdo.diffv(:input => files))
|
292
|
+
assert_nil(@cdo.diffv(:input => files).last)
|
301
293
|
# check for operator input
|
302
|
-
assert_nil(
|
294
|
+
assert_nil(@cdo.diffv(:input => ["-stdatm,0","-stdatm,0"]).last)
|
303
295
|
# check for operator input and files
|
304
|
-
assert_nil(
|
296
|
+
assert_nil(@cdo.diffv(:input => ["-stdatm,0",fileB]).last)
|
305
297
|
end
|
306
298
|
|
307
|
-
def
|
308
|
-
assert(
|
309
|
-
assert(
|
310
|
-
assert(
|
311
|
-
|
312
|
-
|
313
|
-
# assert_equal('1.10.0',Cdo.libsVersion("grib_api")) if Cdo.hasLib?("grib_api")
|
314
|
-
# Cdo.debug = true
|
315
|
-
# warn "Found magics support" if Cdo.libs.has_key?('magics')
|
316
|
-
# Cdo.setCdo('../../src/cdo')
|
317
|
-
# assert(Cdo.libs.has_key?('magics'),"Magics support is expected in the local development binary")
|
318
|
-
#end
|
319
|
-
assert_raise ArgumentError do
|
320
|
-
Cdo.libsVersion("foo")
|
299
|
+
def test_filetypes
|
300
|
+
assert(@cdo.filetypes.include?("grb"),"GRIB support missing")
|
301
|
+
assert(@cdo.filetypes.include?("nc4"),"NETCDF4 support missing")
|
302
|
+
assert(@cdo.filetypes.include?("ext"),"EXTRA support missing")
|
303
|
+
assert_raises ArgumentError do
|
304
|
+
@cdo.filetypes("foo")
|
321
305
|
end
|
322
306
|
end
|
323
307
|
|
324
308
|
def test_output_set_to_nil
|
325
|
-
assert_equal(String
|
326
|
-
assert_equal("File format: GRIB",
|
309
|
+
assert_equal(String,@cdo.topo(:output => nil).class)
|
310
|
+
assert_equal("File format: GRIB".tr(' ',''),@cdo.sinfov(:input => "-topo", :output => nil)[0].tr(' ',''))
|
327
311
|
end
|
328
312
|
|
329
|
-
if '
|
313
|
+
if 'luthien' == `hostname`.chomp then
|
330
314
|
def test_readCdf
|
331
315
|
input = "-settunits,days -setyear,2000 -for,1,4"
|
332
|
-
cdfFile =
|
333
|
-
cdf =
|
316
|
+
cdfFile = @cdo.copy(:options =>"-f nc",:input=>input)
|
317
|
+
cdf = @cdo.readCdf(cdfFile)
|
334
318
|
assert_equal(['lon','lat','time','for'],cdf.var_names)
|
335
319
|
end
|
336
320
|
def test_selIndexListFromIcon
|
337
321
|
input = "~/data/icon/oce.nc"
|
338
322
|
end
|
339
323
|
def test_readArray
|
340
|
-
|
341
|
-
assert_equal([
|
324
|
+
@cdo.debug = true
|
325
|
+
assert_equal([40,80],@cdo.readArray(@cdo.sellonlatbox(-10,10,-20,20,:input => '-topo',:options => '-f nc'), 'topo').shape)
|
342
326
|
end
|
343
327
|
def test_doc
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
328
|
+
@cdo.debug = true
|
329
|
+
@cdo.help(:remap)
|
330
|
+
@cdo.help(:infov)
|
331
|
+
@cdo.help(:topo)
|
332
|
+
@cdo.help(:notDefinedOP)
|
333
|
+
@cdo.help
|
350
334
|
end
|
351
335
|
def test_fillmiss
|
352
|
-
|
336
|
+
@cdo.debug = true
|
353
337
|
# check up-down replacement
|
354
|
-
rand =
|
355
|
-
cdf =
|
338
|
+
rand = @cdo.setname('v',:input => '-random,r1x10 ', :options => ' -f nc',:output => '/tmp/rand.nc')
|
339
|
+
cdf = @cdo.openCdf(rand)
|
356
340
|
vals = cdf.var('v').get
|
357
341
|
cdf.var('v').put(vals.sort)
|
358
342
|
cdf.sync
|
359
343
|
cdf.close
|
360
344
|
|
361
345
|
missRange = '0.3,0.8'
|
362
|
-
arOrg =
|
363
|
-
arFm =
|
364
|
-
arFm1s=
|
346
|
+
arOrg = @cdo.setrtomiss(missRange,:input => cdf.path,:returnMaArray => 'v')
|
347
|
+
arFm = @cdo.fillmiss(:input => "-setrtomiss,#{missRange} #{cdf.path}",:returnMaArray => 'v')
|
348
|
+
arFm1s= @cdo.fillmiss2(:input => "-setrtomiss,#{missRange} #{cdf.path}",:returnMaArray => 'v')
|
365
349
|
vOrg = arOrg[0,0..-1]
|
366
350
|
vFm = arFm[0,0..-1]
|
367
351
|
vFm1s = arFm1s[0,0..-1]
|
368
352
|
UnifiedPlot.linePlot([{:y => vOrg, :style => 'line',:title => 'org'},
|
369
353
|
{:y => vFm, :style => 'points',:title => 'fillmiss'},
|
370
354
|
{:y => vFm1s,:style => 'points',:title => 'fillmiss2'}],
|
371
|
-
plotConf: {:yrange => '[0:1]'},title: 'r1x10')
|
355
|
+
plotConf: {:yrange => '[0:1]'},title: 'r1x10') if @show
|
372
356
|
# check left-right replacement
|
373
|
-
rand =
|
374
|
-
cdf =
|
357
|
+
rand = @cdo.setname('v',:input => '-random,r10x1 ', :options => ' -f nc',:output => '/tmp/rand.nc')
|
358
|
+
cdf = @cdo.openCdf(rand)
|
375
359
|
vals = cdf.var('v').get
|
376
360
|
cdf.var('v').put(vals.sort)
|
377
361
|
cdf.sync
|
378
362
|
cdf.close
|
379
363
|
|
380
364
|
missRange = '0.3,0.8'
|
381
|
-
arOrg =
|
382
|
-
arFm =
|
383
|
-
arFm1s=
|
365
|
+
arOrg = @cdo.setrtomiss(missRange,:input => cdf.path,:returnMaArray => 'v')
|
366
|
+
arFm = @cdo.fillmiss(:input => "-setrtomiss,#{missRange} #{cdf.path}",:returnMaArray => 'v')
|
367
|
+
arFm1s= @cdo.fillmiss2(:input => "-setrtomiss,#{missRange} #{cdf.path}",:returnMaArray => 'v')
|
384
368
|
vOrg = arOrg[0..-1,0]
|
385
369
|
vFm = arFm[0..-1,0]
|
386
370
|
vFm1s = arFm1s[0..-1,0]
|
387
371
|
UnifiedPlot.linePlot([{:y => vOrg, :style => 'line',:title => 'org'},
|
388
372
|
{:y => vFm, :style => 'points',:title => 'fillmiss'},
|
389
373
|
{:y => vFm1s,:style => 'points',:title => 'fillmiss2'}],
|
390
|
-
plotConf: {:yrange => '[0:1]'},title: 'r10x1')
|
374
|
+
plotConf: {:yrange => '[0:1]'},title: 'r10x1') if @show
|
391
375
|
end
|
392
376
|
end
|
393
377
|
|
@@ -400,39 +384,54 @@ class TestCdo < Minitest::Test
|
|
400
384
|
|
401
385
|
# oType = grb (default)
|
402
386
|
ofiles = expected.map {|f| f += '.grb'}
|
403
|
-
|
387
|
+
@cdo.splitlevel(input: "-stdatm,0,10,100",output: oTag)
|
404
388
|
assert_equal(ofiles,Dir.glob(oTag+'*').sort)
|
405
389
|
rm(ofiles)
|
406
390
|
|
407
391
|
# oType = nc, from cdo options
|
408
392
|
ofiles = expected.map {|f| f += '.nc'}
|
409
|
-
|
393
|
+
@cdo.splitlevel(input: "-stdatm,0,10,100",output: oTag,options: '-f nc')
|
410
394
|
assert_equal(ofiles,Dir.glob(oTag+'*').sort)
|
411
395
|
rm(ofiles)
|
412
396
|
|
413
397
|
# oType = nc, from input type
|
414
398
|
ofiles = expected.map {|f| f += '.nc'}
|
415
|
-
|
399
|
+
@cdo.splitlevel(input: @cdo.stdatm(0,10,100,options: '-f nc'),output: oTag)
|
416
400
|
assert_equal(ofiles,Dir.glob(oTag+'*').sort)
|
417
401
|
rm(ofiles)
|
418
402
|
|
419
403
|
# oType = nc, from input ENV
|
420
404
|
ofiles = expected.map {|f| f += '.nc2'}
|
421
|
-
|
422
|
-
|
405
|
+
@cdo.env = {'CDO_FILE_SUFFIX' => '.nc2'}
|
406
|
+
@cdo.splitlevel(input: @cdo.stdatm(0,10,100,options: '-f nc'),output: oTag)
|
423
407
|
assert_equal(ofiles,Dir.glob(oTag+'*').sort)
|
424
408
|
rm(ofiles)
|
425
409
|
|
426
410
|
# oType = nc, from input ENV setting for each call
|
427
411
|
ofiles = expected.map {|f| f += '.nc2'}
|
428
|
-
|
412
|
+
@cdo.splitlevel(input: @cdo.stdatm(0,10,100,options: '-f nc'),output: oTag,env: {'CDO_FILE_SUFFIX' => '.nc2'})
|
429
413
|
assert_equal(ofiles,Dir.glob(oTag+'*').sort)
|
430
414
|
rm(ofiles)
|
431
415
|
end
|
432
416
|
def test_log
|
433
|
-
|
434
|
-
|
435
|
-
Cdo.
|
417
|
+
cmd = '-fldmean -mul -random,r20x20 -topo,r20x20'
|
418
|
+
# logging without a real file
|
419
|
+
@cdo = Cdo.new( returnNilOnError: true)
|
420
|
+
@cdo.debug = false
|
421
|
+
@cdo.logging = true
|
422
|
+
@cdo.topo
|
423
|
+
@cdo.temp
|
424
|
+
@cdo.sinfov(input: cmd)
|
425
|
+
puts @cdo.showLog
|
426
|
+
@cdo.sinfov(input: '-top')
|
427
|
+
@cdo.topo
|
428
|
+
puts @cdo.showLog
|
429
|
+
# use a use definded file for looging
|
430
|
+
@cdo = Cdo.new(logFile: 'test.log',logging: true, returnNilOnError: true)
|
431
|
+
@cdo.topo
|
432
|
+
@cdo.temp
|
433
|
+
@cdo.sinfov(input: cmd)
|
434
|
+
puts @cdo.showLog
|
436
435
|
end
|
437
436
|
end
|
438
437
|
|
@@ -440,30 +439,30 @@ end
|
|
440
439
|
# #
|
441
440
|
# # merge:
|
442
441
|
# # let files be an erray of valid filenames and ofile is a string
|
443
|
-
#
|
442
|
+
# @cdo.merge(:input => outvars.join(" "),:output => ofile)
|
444
443
|
# # or with multiple arrays:
|
445
|
-
#
|
444
|
+
# @cdo.merge(:input => [ifiles0,ifiles1].flatten.join(' '),:output => ofile)
|
446
445
|
# # selname:
|
447
446
|
# # lets grep out some variables from ifile:
|
448
447
|
# ["T","U","V"].each {|varname|
|
449
448
|
# varfile = varname+".nc"
|
450
|
-
#
|
449
|
+
# @cdo.selname(varname,:input => ifile,:output => varfile)
|
451
450
|
# }
|
452
451
|
# # a threaded version of this could look like:
|
453
452
|
# ths = []
|
454
453
|
# ["T","U","V"].each {|outvar|
|
455
454
|
# ths << Thread.new(outvar) {|ovar|
|
456
455
|
# varfile = varname+".nc"
|
457
|
-
#
|
456
|
+
# @cdo.selname(varname,:input => ifile,:output => varfile)
|
458
457
|
# }
|
459
458
|
# }
|
460
459
|
# ths.each {|th| th.join}
|
461
460
|
# # another example with sub:
|
462
|
-
#
|
461
|
+
# @cdo.sub(:input => [oldfile,newfile].join(' '), :output => diff)
|
463
462
|
#
|
464
463
|
# # It is possible too use the 'send' method
|
465
464
|
# operator = /grb/.match(File.extname(ifile)) ? :showcode : :showname
|
466
|
-
# inputVars =
|
465
|
+
# inputVars = @cdo.send(operator,:input => ifile)
|
467
466
|
# # show and info operators are writing to stdout. cdo.rb tries to collects this into arrays
|
468
467
|
# #
|
469
468
|
# # Same stuff with other operators:
|
@@ -473,15 +472,15 @@ end
|
|
473
472
|
# else
|
474
473
|
# warn "Wrong usage of variable identifier for '#{var}' (class #{var.class})!"
|
475
474
|
# end
|
476
|
-
#
|
475
|
+
# @cdo.send(operator,var,:input => @ifile, :output => varfile)
|
477
476
|
#
|
478
477
|
# # Pass an array for operators with multiple options:
|
479
478
|
# # Perform conservative remapping with pregenerated weights
|
480
|
-
#
|
479
|
+
# @cdo.remap([gridfile,weightfile],:input => copyfile,:output => outfile)
|
481
480
|
# # Create vertical height levels out of hybrid model levels
|
482
|
-
#
|
481
|
+
# @cdo.ml2hl([0,20,50,100,200,400,800,1200].join(','),:input => hybridlayerfile, :output => reallayerfile)
|
483
482
|
# # or use multiple arguments directly
|
484
|
-
#
|
483
|
+
# @cdo.remapeta(vctfile,orofile,:input => ifile,:output => hybridlayerfile)
|
485
484
|
#
|
486
485
|
# # the powerfull expr operator:
|
487
486
|
# # taken from the tutorial in https://code.zmaw.de/projects/cdo/wiki/Tutorial#The-_expr_-Operator
|
@@ -492,8 +491,8 @@ end
|
|
492
491
|
# TEMP_EXPR = lambda {|height| "213.0+75.0*exp(-#{height}/#{SCALEHEIGHT})"}
|
493
492
|
#
|
494
493
|
# # Create Pressure and Temperature out of a height field 'geopotheight' from ifile
|
495
|
-
#
|
496
|
-
#
|
494
|
+
# @cdo.expr("'p=#{PRES_EXPR['geopotheight']}'", :input => ifile, :output => presFile)
|
495
|
+
# @cdo.expr("'t=#{TEMP_EXPR['geopotheight']}'", :input => ifile, :output => tempFile)
|
497
496
|
#
|
498
497
|
#
|
499
498
|
# # TIPS: I often work with temporary files and for getting rid of handling them manually the MyTempfile module can be used:
|
@@ -503,11 +502,11 @@ end
|
|
503
502
|
# end
|
504
503
|
# # As an example, the computation of simple atmospherric density could look like
|
505
504
|
# presFile, tempFile = tfile, tfile
|
506
|
-
#
|
507
|
-
#
|
508
|
-
#
|
505
|
+
# @cdo.expr("'p=#{PRES_EXPR['geopotheight']}'", :input => ifile, :output => presFile)
|
506
|
+
# @cdo.expr("'t=#{TEMP_EXPR['geopotheight']}'", :input => ifile, :output => tempFile)
|
507
|
+
# @cdo.chainCall("setname,#{rho} -divc,#{C_R} -div",in: [presFile,tempFile].join(' '), out: densityFile)
|
509
508
|
#
|
510
509
|
# # For debugging, it is helpfull, to avoid the automatic cleanup at the end of the scripts:
|
511
510
|
# MyTempfile.setPersist(true)
|
512
511
|
# # creates randomly names files. Switch on debugging with
|
513
|
-
#
|
512
|
+
# @cdo.Debug = true
|