cdo 1.0.2 → 1.0.3

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 (5) hide show
  1. data/ChangeLog +4 -0
  2. data/gemspec +1 -1
  3. data/lib/cdo.rb +57 -46
  4. data/test/test_cdo.rb +40 -23
  5. metadata +2 -2
data/ChangeLog CHANGED
@@ -1,3 +1,7 @@
1
1
  1.0.0 2011-12-14: initial version
2
2
  1.0.1 2011-12-15: bugix release
3
3
  1.0.2 2012-01-11: return NetCDF/NArray (optional)
4
+ 1.0.3 2012-01-17: bugfix for NArray return values
5
+ remove chainCall method - can be replaced by setting :in
6
+ speed up by reuse operator list instead of computing it
7
+ every time
data/gemspec CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  spec = Gem::Specification.new do |s|
4
4
  s.name = "cdo"
5
- s.version = '1.0.2'
5
+ s.version = '1.0.3'
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.files = ["lib/cdo.rb"] + ["gemspec","COPYING","README.rdoc","ChangeLog"]
8
8
  s.test_file = "test/test_cdo.rb"
data/lib/cdo.rb CHANGED
@@ -16,15 +16,35 @@ require 'pp'
16
16
  # CDO calling mechnism
17
17
  module Cdo
18
18
  State = {
19
- :debug => false,
20
- :returnArray => false
19
+ :debug => false,
20
+ :returnArray => false,
21
+ :operators => []
21
22
  }
22
23
  @@CDO = ENV['CDO'].nil? ? '/usr/bin/cdo' : ENV['CDO']
23
24
 
24
- # Only operators with documentation are accessible vie the build-in help.
25
- # Other have to be added manually
26
- @@undocumentedOperators = %w[geopotheight pressure_fl pressure_hl]
27
- @@addOperators = %w[boundaryLevels thicknessOfLevels]
25
+ # Since cdo-1.5.4 undocumented operators are given with the -h option. For
26
+ # earlier version, they have to be provided manually
27
+ @@undocumentedOperators = %w[anomaly beta boxavg change_e5lsm change_e5mask
28
+ change_e5slm chisquare chvar cloudlayer cmd com command complextorect
29
+ covar0 covar0r daycount daylogs del29feb delday delete deltap deltap_fl
30
+ delvar diffv divcoslat dumplogo dumplogs duplicate eca_r1mm enlargegrid
31
+ ensrkhistspace ensrkhisttime eof3d eof3dspatial eof3dtime export_e5ml
32
+ export_e5res fc2gp fc2sp fillmiss fisher fldcovar fldrms fourier fpressure
33
+ gather gengrid geopotheight ggstat ggstats globavg gp2fc gradsdes
34
+ gridverify harmonic hourcount hpressure ifs2icon import_e5ml import_e5res
35
+ import_obs imtocomplex infos infov interpolate intgrid intgridbil
36
+ intgridtraj intpoint isosurface lmavg lmean lmmean lmstd log lsmean
37
+ meandiff2test mergegrid mod moncount monlogs mrotuv mrotuvb mulcoslat ncode
38
+ ncopy nmltest normal nvar outputbounds outputboundscpt outputcenter
39
+ outputcenter2 outputcentercpt outputkey outputtri outputvector outputvrml
40
+ pardup parmul pinfo pinfov pressure_fl pressure_hl read_e5ml remapcon1
41
+ remapdis1 retocomplex scalllogo scatter seascount select selgridname
42
+ seloperator selvar selzaxisname setrcaname setvar showvar sinfov smemlogo
43
+ snamelogo sort sortcode sortlevel sortname sorttaxis sorttimestamp sortvar
44
+ sp2fc specinfo spectrum sperclogo splitvar stimelogo studentt template1
45
+ template2 test test2 testdata thinout timcount timcovar tinfo transxy trms
46
+ tstepcount vardes vardup varmul varquot2test varrms vertwind write_e5ml
47
+ writegrid writerandom yearcount]
28
48
 
29
49
  private
30
50
  def Cdo.call(cmd)
@@ -48,34 +68,38 @@ module Cdo
48
68
  end
49
69
  cmd << "#{ofile}"
50
70
  call(cmd)
51
- if State[:returnArray] or returnArray
71
+ if returnArray or State[:returnArray]
72
+ Cdo.loadCdf unless State[:returnArray]
52
73
  return NetCDF.open(ofile)
53
74
  else
54
75
  return ofile
55
76
  end
56
77
  end
78
+ def Cdo.loadCdf
79
+ begin
80
+ require "numru/netcdf"
81
+ include NumRu
82
+ rescue LoadError
83
+ warn "Could not load ruby's netcdf bindings. Please install it."
84
+ raise
85
+ end
86
+ end
57
87
 
58
88
  public
59
- def Cdo.Debug=(value)
89
+ def Cdo.debug=(value)
60
90
  State[:debug] = value
61
91
  end
62
- def Cdo.Debug
92
+ def Cdo.debug
63
93
  State[:debug]
64
94
  end
65
- def Cdo.returnArray=(value)
95
+ def Cdo.setReturnArray(value=true)
66
96
  if value
67
- begin
68
- require "numru/netcdf"
69
- include NumRu
70
- State[:returnArray] = true
71
-
72
- rescue LoadError
73
- warn "Could not load ruby's netcdf bindings. Please install it."
74
- raise
75
- end
76
- else
77
- State[:returnArray] = value
97
+ Cdo.loadCdf
78
98
  end
99
+ State[:returnArray] = value
100
+ end
101
+ def Cdo.unsetReturnArray
102
+ setReturnArray(false)
79
103
  end
80
104
  def Cdo.returnArray
81
105
  State[:returnArray]
@@ -92,44 +116,30 @@ module Cdo
92
116
  end
93
117
  end
94
118
  def Cdo.setCdo(cdo)
95
- puts "Will use #{cdo} instead of #@@CDO" if Cdo.Debug
119
+ puts "Will use #{cdo} instead of #@@CDO" if Cdo.debug
96
120
  @@CDO = cdo
121
+ Cdo.getOperators(true)
97
122
  end
98
123
 
99
- def Cdo.getOperators
124
+ def Cdo.getOperators(force=false)
125
+ # Do NOT compute anything, if it is not required
126
+ return State[:operators] unless (State[:operators].empty? or force)
127
+
100
128
  cmd = @@CDO + ' 2>&1'
101
129
  help = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
102
130
  if 5 >= help.size
103
131
  warn "Operators could not get listed by running the CDO binary (#{@@CDO})"
104
- pp help if Cdo.Debug
132
+ pp help if Cdo.debug
105
133
  exit
106
- else
107
- help[help.index("Operators:")+1].split
108
- end
109
- end
110
-
111
- # Call an operator chain without checking opeartors
112
- def Cdo.chainCall(chain,*args)
113
- io = args.find {|a| a.class == Hash}
114
- args.delete_if {|a| a.class == Hash}
115
-
116
- chain = chain.strip
117
- firstOp = chain
118
- firstOp = chain[0...[chain.index(','),chain.index(' ')].min] unless chain.index(',').nil?
119
- firstOp = firstOp[1..-1] if firstOp[0] == '-'
120
- if /(info|show|griddes)/.match(firstOp)
121
- Cdo.run(" #{chain} #{io[:in]} ",$stdout)
122
- else
123
- opts = args.empty? ? '' : ',' + args.reject {|a| a.class == Hash}.join(',')
124
- Cdo.run(" #{chain}#{opts} #{io[:in]} ",io[:out],io[:options])
125
134
  end
135
+ State[:operators] = (help[help.index("Operators:")+1].split + @@undocumentedOperators).uniq
126
136
  end
127
137
 
128
138
  def Cdo.method_missing(sym, *args, &block)
129
139
  # args is expected to look like [opt1,...,optN,:in => iStream,:out => oStream] where
130
140
  # iStream could be another CDO call (timmax(selname(Temp,U,V,ifile.nc))
131
141
  puts "Operator #{sym.to_s} is called" if State[:debug]
132
- if getOperators.include?(sym.to_s) or @@undocumentedOperators.include?(sym.to_s)
142
+ if getOperators.include?(sym.to_s)
133
143
  io = args.find {|a| a.class == Hash}
134
144
  args.delete_if {|a| a.class == Hash}
135
145
  if /(diff|info|show|griddes)/.match(sym)
@@ -160,7 +170,7 @@ module Cdo
160
170
  bound_levels = Cdo.boundaryLevels(args)
161
171
  delta_levels = []
162
172
  bound_levels.each_with_index {|v,i|
163
- next if i == 0
173
+ next if 0 == i
164
174
  delta_levels << v - bound_levels[i-1]
165
175
  }
166
176
  delta_levels
@@ -172,6 +182,7 @@ module MyTempfile
172
182
  require 'tempfile'
173
183
  @@_tempfiles = []
174
184
  @@persistent_tempfiles = false
185
+ @@N = 10000000
175
186
  def MyTempfile.setPersist(value)
176
187
  @@persistent_tempfiles = value
177
188
  end
@@ -181,7 +192,7 @@ module MyTempfile
181
192
  @@_tempfiles << t
182
193
  t.path
183
194
  else
184
- t = "_"+rand(10000000).to_s
195
+ t = "_"+rand(@@N).to_s
185
196
  @@_tempfiles << t
186
197
  t
187
198
  end
@@ -28,9 +28,12 @@ class TestCdo < Test::Unit::TestCase
28
28
  end
29
29
 
30
30
  def test_getOperators
31
- %w[for random stdatm info showlevel sinfo remap mask topo thicknessOfLevels].each {|op|
32
- assert(Cdo.getOperators.include?(op),"Operator '#{op}' not found") unless op == "thicknessOfLevels"
33
- assert(Cdo.respond_to?(op),"Operator '#{op}' not found") if op == "thicknessOfLevels"
31
+ %w[for random stdatm info showlevel sinfo remap geopotheight mask topo thicknessOfLevels].each {|op|
32
+ if ["thicknessOfLevels"].include?(op)
33
+ assert(Cdo.respond_to?(op),"Operator '#{op}' not found")
34
+ else
35
+ assert(Cdo.getOperators.include?(op))
36
+ end
34
37
  }
35
38
  end
36
39
  def test_info
@@ -39,7 +42,6 @@ class TestCdo < Test::Unit::TestCase
39
42
 
40
43
  info = Cdo.sinfo(:in => "-stdatm,0")
41
44
  assert_equal("File format: GRIB",info[0])
42
-
43
45
  end
44
46
  def test_args
45
47
  #Cdo.Debug = true
@@ -73,7 +75,7 @@ class TestCdo < Test::Unit::TestCase
73
75
  def test_chain
74
76
  ofile = MyTempfile.path
75
77
  #Cdo.Debug = true
76
- Cdo.chainCall("-setname,veloc -copy",:in => "-random,r1x1",:out => ofile,:options => "-f nc")
78
+ Cdo.setname('veloc',:in => " -copy -random,r1x1",:out => ofile,:options => "-f nc")
77
79
  assert_equal(["veloc"],Cdo.showname(:in => ofile))
78
80
  end
79
81
 
@@ -94,25 +96,26 @@ class TestCdo < Test::Unit::TestCase
94
96
  Cdo.thicknessOfLevels(:in => ofile))
95
97
  end
96
98
 
97
- def test_returnArray
98
- ofile = MyTempfile.path
99
- vals = Cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:out => ofile,:options => "-f nc")
100
- assert_equal(ofile,vals)
101
- Cdo.returnArray = true
102
- vals = Cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:out => ofile,:options => "-f nc")
103
- assert_equal(["lon","lat","level","P","T"],vals.var_names)
104
- assert_equal(276,vals.var("T").get.flatten.mean.floor)
105
- Cdo.returnArray = false
106
- end
107
99
  def test_combine
108
100
  ofile0, ofile1 = MyTempfile.path, MyTempfile.path
109
101
  Cdo.fldsum(:in => Cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:options => "-f nc"),:out => ofile0)
110
102
  ofile1 = Cdo.fldsum(:in => "-stdatm,25,100,250,500,875,1400,2100,3000,4000,5000",:options => "-f nc")
111
- Cdo.returnArray = true
103
+ Cdo.setReturnArray(true)
112
104
  diff = Cdo.sub(:in => [ofile0,ofile1].join(' '),:out => MyTempfile.path).var('T').get
113
105
  assert_equal(0.0,diff.min)
114
106
  assert_equal(0.0,diff.max)
115
- Cdo.returnArray = false
107
+ Cdo.setReturnArray(false)
108
+ end
109
+
110
+ def test_returnArray
111
+ ofile = MyTempfile.path
112
+ vals = Cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:out => ofile,:options => "-f nc")
113
+ assert_equal(ofile,vals)
114
+ Cdo.setReturnArray
115
+ vals = Cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:out => ofile,:options => "-f nc")
116
+ assert_equal(["lon","lat","level","P","T"],vals.var_names)
117
+ assert_equal(276,vals.var("T").get.flatten.mean.floor)
118
+ Cdo.unsetReturnArray
116
119
  end
117
120
  def test_simple_returnArray
118
121
  ofile0, ofile1 = MyTempfile.path, MyTempfile.path
@@ -121,6 +124,26 @@ class TestCdo < Test::Unit::TestCase
121
124
  assert_equal(1013.25,sum.min)
122
125
  test_returnArray
123
126
  end
127
+
128
+ def test_thickness
129
+ levels = "25 100 250 500 875 1400 2100 3000 4000 5000".split
130
+ targetThicknesses = [50.0, 100.0, 200.0, 300.0, 450.0, 600.0, 800.0, 1000.0, 1000.0, 1000.0]
131
+ assert_equal(targetThicknesses, Cdo.thicknessOfLevels(:in => "-selname,T -stdatm,#{levels.join(',')}"))
132
+ end
133
+
134
+ if 'thingol' == `hostname`.chomp then
135
+ def test_verticalLevels
136
+ iconpath = "/home/ram/src/git/icon/grids"
137
+ # check, if a given input files has vertival layers of a given thickness array
138
+ targetThicknesses = [50.0, 100.0, 200.0, 300.0, 450.0, 600.0, 800.0, 1000.0, 1000.0, 1000.0]
139
+ ifile = [iconpath,"ts_phc_annual-iconR2B04-L10_50-1000m.nc"].join('/')
140
+ assert_equal(["25 100 250 500 875 1400 2100 3000 4000 5000",
141
+ "25 100 250 500 875 1400 2100 3000 4000 5000"],Cdo.showlevel(:in => ifile))
142
+ thicknesses = Cdo.thicknessOfLevels(:in => ifile)
143
+ assert_equal(targetThicknesses,thicknesses)
144
+ end
145
+ end
146
+
124
147
  end
125
148
 
126
149
  # # Calling simple operators
@@ -162,12 +185,6 @@ end
162
185
  # end
163
186
  # Cdo.send(operator,var,:in => @ifile, :out => varfile)
164
187
  #
165
- # # For chaining operators, there is a special method:
166
- # Cdo.chainCall("-setname,veloc -copy",:in => ifile,:out => ofile,:options => "-f nc")
167
- # # another example with 3 operators and a different hash syntax
168
- # C_R = 287.05
169
- # Cdo.chainCall("setname,#{rho} -divc,#{C_R} -div",in: [pressureFile,temperatureFile].join(' '), out: densityFile)
170
- #
171
188
  # # Pass an array for operators with multiple options:
172
189
  # # Perform conservative remapping with pregenerated weights
173
190
  # Cdo.remap([gridfile,weightfile],:in => copyfile,:out => outfile)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cdo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-11 00:00:00.000000000 Z
12
+ date: 2012-01-17 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Easy access to the Climate Data operators
15
15
  email: stark.dreamdetective@gmail.com