cdo 1.3.4 → 1.3.6

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.
Files changed (6) hide show
  1. checksums.yaml +5 -5
  2. data/gemspec +4 -2
  3. data/lib/cdo.rb +27 -6
  4. data/test/test_cdo.rb +29 -13
  5. metadata +31 -4
  6. data/lib/cdo_lib.rb +0 -415
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 839669f481246fb63e5ad6b7871127ef6b1c710d
4
- data.tar.gz: fae0e2fa60efa590697c9cf73f0e1fc3db103cd8
2
+ SHA256:
3
+ metadata.gz: ae07b4039ff9ecbaea1bdea8a4d50c83b63bdd5d65c6b87f5d0c8f67632dc937
4
+ data.tar.gz: 23d76998b8cd25d1b0ba6619651c255c33920e104181912ccdbe588bfb580e08
5
5
  SHA512:
6
- metadata.gz: 12c44ad5bb29e96457a623d07060a87557f79b2ee9246faf1b0e477865ff5603219118260fa2db0623a149dda45f133db132980ddd18c41c44949dfb86c06fa0
7
- data.tar.gz: '02851b39cb5c9fd19941e0e85c594d01fdcd51349bf0df6255477fb92ae1ede816a42d438fe19ba077ed7dc1958bcfc38d789031186faf09361b76c43c97ddd3'
6
+ metadata.gz: d870e95cb67677c2f00aa707ce458ee314c7767c857c9085c65a7e838eba6b5e00e40c2c529b1c603b9444562de3e85f2cae812386516261460ff842660aa50e
7
+ data.tar.gz: 70d7277e46d3c12175fe9168a86aa60e60f0d8837a3d36a94906ce9c3ac725d7c2f8428fc8e841f8d5fbba1c92f7fd4f5bf2e2ba6bbbcda6935815507ac21f42
data/gemspec CHANGED
@@ -3,9 +3,9 @@ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
3
3
 
4
4
  spec = Gem::Specification.new do |s|
5
5
  s.name = "cdo"
6
- s.version = '1.3.4'
6
+ s.version = '1.3.6'
7
7
  s.platform = Gem::Platform::RUBY
8
- s.files = ["lib/cdo.rb","lib/cdo_lib.rb"] + ["gemspec","LICENSE"]
8
+ s.files = ["lib/cdo.rb","gemspec","LICENSE"]
9
9
  s.test_file = "test/test_cdo.rb"
10
10
  s.description = "Easy access to the Climate Data operators"
11
11
  s.summary = "Easy access to the Climate Data operators"
@@ -16,6 +16,8 @@ spec = Gem::Specification.new do |s|
16
16
  s.required_ruby_version = ">= 1.9"
17
17
  s.add_development_dependency('unifiedPlot')
18
18
  s.add_development_dependency('minitest')
19
+ s.add_development_dependency('facets')
20
+ s.add_development_dependency('colorize')
19
21
  s.add_development_dependency('rake')
20
22
  end
21
23
 
data/lib/cdo.rb CHANGED
@@ -3,6 +3,11 @@ require 'open3'
3
3
  require 'logger'
4
4
  require 'stringio'
5
5
 
6
+ class Hash
7
+ alias :include? :has_key?
8
+ end
9
+
10
+
6
11
  class Cdo
7
12
 
8
13
  # hardcoded fallback list of output operators - from 1.8.0 there is an
@@ -69,7 +74,8 @@ class Cdo
69
74
 
70
75
  # collect the complete list of possible operators
71
76
  def getOperators(path2cdo)
72
- if version <= '1.7.0' then
77
+ case
78
+ when version <= '1.7.0' then
73
79
  cmd = path2cdo + ' 2>&1'
74
80
  help = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
75
81
  if 5 >= help.size
@@ -78,12 +84,21 @@ class Cdo
78
84
  exit
79
85
  end
80
86
 
81
- @operators = help[(help.index("Operators:")+1)..help.index(help.find {|v| v =~ /CDO version/ }) - 2].join(' ').split
87
+ operators = help[(help.index("Operators:")+1)..help.index(help.find {|v| v =~ /CDO version/ }) - 2].join(' ').split
88
+ when version <= '1.9.1' then
89
+ cmd = "#{path2cdo} --operators"
90
+ operators = IO.popen(cmd).readlines.map {|l| l.split(' ').first }
82
91
  else
83
- cmd = "#{path2cdo} --operators"
84
-
85
- @operators = IO.popen(cmd).readlines.map {|l| l.split(' ').first }
92
+ cmd = "#{path2cdo} --operators"
93
+ operators = {}
94
+ IO.popen(cmd).readlines.map {|line|
95
+ lineContent = line.chomp.split(' ')
96
+ name = lineContent[0]
97
+ iCounter, oCounter = lineContent[-1].tr(')','').tr('(','').split('|')
98
+ operators[name] = { iStreams: iCounter.to_i, oStreams: oCounter.to_i }
99
+ }
86
100
  end
101
+ return operators
87
102
  end
88
103
 
89
104
  def getNoOuputOperators(path2cdo)
@@ -285,9 +300,15 @@ class Cdo
285
300
  puts collectLogs
286
301
  end
287
302
 
303
+ def hasCdo(path=@cdo)
304
+ executable = system("#{path} -V >/dev/null 2>&1")
305
+ fullpath = File.exists?(path) and File.executable?(path)
306
+
307
+ return (executable or fullpath)
308
+ end
288
309
  # check if cdo backend is working
289
310
  def check
290
- return false unless system("#@cdo -h 1>/dev/null 2>&1")
311
+ return false unless hasCdo
291
312
 
292
313
  retval = _call("#{@cdo} -V")
293
314
  pp retval if @debug
@@ -1,8 +1,7 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+ require 'cdo'
2
3
 
3
4
  require 'minitest/autorun'
4
- require 'cdo'
5
- require 'pp'
6
5
 
7
6
 
8
7
  #===============================================================================
@@ -15,6 +14,7 @@ class TestCdo < Minitest::Test
15
14
 
16
15
  @@show = ENV.has_key?('SHOW')
17
16
  @@maintainermode = ENV.has_key?('MAINTAINERMODE')
17
+ @@debug = ENV.has_key?('DEBUG')
18
18
 
19
19
  def setup
20
20
  @cdo = Cdo.new
@@ -25,6 +25,8 @@ class TestCdo < Minitest::Test
25
25
  if ENV['CDO']
26
26
  assert_equal(ENV['CDO'],@cdo.cdo)
27
27
  else
28
+ pp DEFAULT_CDO_PATH
29
+ pp @cdo.cdo
28
30
  assert_equal(DEFAULT_CDO_PATH,@cdo.cdo)
29
31
  end
30
32
  newCDO="#{ENV['HOME']}/local/bin/cdo-dev"
@@ -41,6 +43,14 @@ class TestCdo < Minitest::Test
41
43
  def test_V
42
44
  puts @cdo.version(verbose=true)
43
45
  end
46
+ def test_hasCdo
47
+ assert(@cdo.hasCdo)
48
+ @cdo.cdo = 'cccccccc'
49
+ assert_equal( false, @cdo.hasCdo)
50
+
51
+ @cdo.cdo='/bin/cdo'
52
+ assert(@cdo.hasCdo) if File.exist?(@cdo.cdo)
53
+ end
44
54
  def test_getOperators
45
55
  %w[for random stdatm info showlevel sinfo remap geopotheight mask topo thicknessOfLevels].each {|op|
46
56
  if ["thicknessOfLevels"].include?(op)
@@ -56,7 +66,7 @@ class TestCdo < Minitest::Test
56
66
  end
57
67
 
58
68
  def test_outputOperators
59
- @cdo.debug = true
69
+ @cdo.debug = @@debug
60
70
  levels = @cdo.showlevel(:input => "-stdatm,0")
61
71
  assert_equal([0,0].map(&:to_s),levels)
62
72
 
@@ -72,7 +82,7 @@ class TestCdo < Minitest::Test
72
82
  end
73
83
  def test_CDO_version
74
84
  assert("1.4.3.1" < @cdo.version,"Version too low: #{@cdo.version}")
75
- assert("1.8.1" < @cdo.version,"Version too low: #{@cdo.version}")
85
+ assert("1.7.1" < @cdo.version,"Version too low: #{@cdo.version}")
76
86
  assert("3.0" > @cdo.version,"Version too high: #{@cdo.version}")
77
87
  end
78
88
  def test_args
@@ -84,7 +94,7 @@ class TestCdo < Minitest::Test
84
94
  (1...info.size).each {|i| assert_equal(0.0,info[i].split[-1].to_f)}
85
95
  end
86
96
  def test_operator_options
87
- @cdo.debug=true
97
+ @cdo.debug=@@debug
88
98
  targetLevels = [0,10,50,100,200,400,1000]
89
99
  levels = @cdo.showlevel(:input => " -stdatm,#{targetLevels.join(',')}")
90
100
  [0,1].each {|i| assert_equal(targetLevels.join(' '),levels[i])}
@@ -92,7 +102,7 @@ class TestCdo < Minitest::Test
92
102
  assert_equal(["P T"],names)
93
103
  end
94
104
  def test_chain
95
- @cdo.debug = true
105
+ @cdo.debug = @@debug
96
106
  ofile = @cdo.setname('veloc',:input => " -copy -random,r1x1",:options => "-f nc")
97
107
  assert_equal(["veloc"],@cdo.showname(:input => ofile))
98
108
  end
@@ -127,6 +137,7 @@ class TestCdo < Minitest::Test
127
137
  outs.clear
128
138
  outs << @cdo.stdatm(0,10,20,:output => 'test_force')
129
139
  mtime0 = File.stat(outs[-1]).mtime
140
+ sleep(1)
130
141
  outs << @cdo.stdatm(0,10,20,:output => 'test_force')
131
142
  mtime1 = File.stat(outs[-1]).mtime
132
143
  assert(mtime0 != mtime1)
@@ -194,7 +205,7 @@ class TestCdo < Minitest::Test
194
205
  end
195
206
 
196
207
  def test_verticalLevels
197
- @cdo.debug = true
208
+ @cdo.debug = @@debug
198
209
  targetThicknesses = [50.0, 100.0, 200.0, 300.0, 450.0, 600.0, 800.0, 1000.0, 1000.0, 1000.0]
199
210
  sourceLevels = %W{25 100 250 500 875 1400 2100 3000 4000 5000}
200
211
  thicknesses = @cdo.thicknessOfLevels(:input => "-selname,T #{@cdo.stdatm(*sourceLevels,:options => '-f nc')}")
@@ -212,7 +223,7 @@ class TestCdo < Minitest::Test
212
223
  end
213
224
 
214
225
  def test_errorException
215
- @cdo.debug = true
226
+ @cdo.debug = @@debug
216
227
  # stdout operators get get wrong input
217
228
  assert_raises ArgumentError do
218
229
  @cdo.showname(:input => '-for,d')
@@ -303,6 +314,11 @@ class TestCdo < Minitest::Test
303
314
  if @@maintainermode then
304
315
  require 'unifiedPlot'
305
316
 
317
+ def test_longChain
318
+ ifile = "-enlarge,global_0.3 -settaxis,2000-01-01 -expr,'t=sin(for*3.141529/180.0)' -for,1,10"
319
+ t = @cdo.fldmax(input: "-div -sub -timmean -seltimestep,2,3 #{ifile} -seltimestep,1 #{ifile} -gridarea #{ifile}",returnArray: "t")
320
+ assert_equal(8.981299259858133e-09,t[0])
321
+ end
306
322
  def test_returnArray
307
323
  temperature = @cdo.stdatm(0,:options => '-f nc',:returnCdf => true).var('T').get.flatten[0]
308
324
  assert_raises ArgumentError do
@@ -314,7 +330,7 @@ class TestCdo < Minitest::Test
314
330
  assert_equal("1013.25 898.543456035875",pressure.flatten.to_a.join(' '))
315
331
  end
316
332
  def test_returnMaArray
317
- @cdo.debug = true
333
+ @cdo.debug = @@debug
318
334
  topo = @cdo.topo(:options => '-f nc',:returnMaArray => 'topo')
319
335
  assert_equal(-1890.0,topo.mean.round)
320
336
  bathy = @cdo.setrtomiss(0,10000,
@@ -382,17 +398,17 @@ class TestCdo < Minitest::Test
382
398
  input = "-settunits,days -setyear,2000 -for,1,4"
383
399
  cdfFile = @cdo.copy(:options =>"-f nc",:input=>input)
384
400
  cdf = @cdo.readCdf(cdfFile)
385
- assert_equal(['lon','lat','time','for'],cdf.var_names)
401
+ assert_empty(['lon','lat','for','time'] - cdf.var_names)
386
402
  end
387
403
  def test_selIndexListFromIcon
388
404
  input = "~/data/icon/oce.nc"
389
405
  end
390
406
  def test_readArray
391
- @cdo.debug = true
407
+ @cdo.debug = @@debug
392
408
  assert_equal([40,80],@cdo.readArray(@cdo.sellonlatbox(-10,10,-20,20,:input => '-topo',:options => '-f nc'), 'topo').shape)
393
409
  end
394
410
  def test_doc
395
- @cdo.debug = true
411
+ @cdo.debug = @@debug
396
412
  @cdo.help(:remap)
397
413
  @cdo.help(:infov)
398
414
  @cdo.help(:topo)
@@ -400,7 +416,7 @@ class TestCdo < Minitest::Test
400
416
  @cdo.help
401
417
  end
402
418
  def test_fillmiss
403
- @cdo.debug = true
419
+ @cdo.debug = @@debug
404
420
  # check up-down replacement
405
421
  rand = @cdo.setname('v',:input => '-random,r1x10 ', :options => ' -f nc',:output => '/tmp/rand.nc')
406
422
  cdf = @cdo.openCdf(rand)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cdo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.4
4
+ version: 1.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ralf Mueller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-06 00:00:00.000000000 Z
11
+ date: 2018-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: unifiedPlot
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: facets
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -61,7 +89,6 @@ files:
61
89
  - LICENSE
62
90
  - gemspec
63
91
  - lib/cdo.rb
64
- - lib/cdo_lib.rb
65
92
  - test/test_cdo.rb
66
93
  homepage: https://code.zmaw.de/projects/cdo/wiki/Cdo%7Brbpy%7D
67
94
  licenses:
@@ -83,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
110
  version: '0'
84
111
  requirements: []
85
112
  rubyforge_project:
86
- rubygems_version: 2.6.11
113
+ rubygems_version: 2.7.4
87
114
  signing_key:
88
115
  specification_version: 4
89
116
  summary: Easy access to the Climate Data operators
@@ -1,415 +0,0 @@
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