cdo 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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