cdo 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/ChangeLog +3 -0
  2. data/README.rdoc +1 -1
  3. data/gemspec +2 -2
  4. data/lib/cdo.rb +88 -45
  5. data/test/test_cdo.rb +61 -1
  6. metadata +3 -2
data/ChangeLog ADDED
@@ -0,0 +1,3 @@
1
+ 1.0.0 2011-12-14: initial version
2
+ 1.0.1 2011-12-15: bugix release
3
+ 1.0.2 2012-01-11: return NetCDF/NArray (optional)
data/README.rdoc CHANGED
@@ -59,6 +59,6 @@ Cdo.rb makes use of the GPLv2D License, see COPYING
59
59
 
60
60
  Author:: Ralf Mueller <stark.dreamdetective@gmail.com>
61
61
  Requires:: CDO version 1.5.x
62
- License:: Copyright 2011 by Ralf Mueller
62
+ License:: Copyright 2011-2012 by Ralf Mueller
63
63
  Released under GPLv2 license. See the COPYING
64
64
  file included in the distribution.
data/gemspec CHANGED
@@ -2,9 +2,9 @@ require 'rubygems'
2
2
 
3
3
  spec = Gem::Specification.new do |s|
4
4
  s.name = "cdo"
5
- s.version = '1.0.1'
5
+ s.version = '1.0.2'
6
6
  s.platform = Gem::Platform::RUBY
7
- s.files = ["lib/cdo.rb"] + ["gemspec","COPYING","README.rdoc"]
7
+ s.files = ["lib/cdo.rb"] + ["gemspec","COPYING","README.rdoc","ChangeLog"]
8
8
  s.test_file = "test/test_cdo.rb"
9
9
  s.description = "Easy access to the Climate Data operators"
10
10
  s.summary = "Easy access to the Climate Data operators"
data/lib/cdo.rb CHANGED
@@ -1,9 +1,24 @@
1
1
  require 'pp'
2
2
 
3
+ # Copyright (C) 2011-2012 Ralf Mueller, ralf.mueller@zmaw.de
4
+ # See COPYING file for copying and redistribution conditions.
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; version 2 of the License.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
3
15
  # ==============================================================================
4
16
  # CDO calling mechnism
5
17
  module Cdo
6
- State = {}
18
+ State = {
19
+ :debug => false,
20
+ :returnArray => false
21
+ }
7
22
  @@CDO = ENV['CDO'].nil? ? '/usr/bin/cdo' : ENV['CDO']
8
23
 
9
24
  # Only operators with documentation are accessible vie the build-in help.
@@ -11,12 +26,60 @@ module Cdo
11
26
  @@undocumentedOperators = %w[geopotheight pressure_fl pressure_hl]
12
27
  @@addOperators = %w[boundaryLevels thicknessOfLevels]
13
28
 
29
+ private
30
+ def Cdo.call(cmd)
31
+ if (State[:debug])
32
+ puts '# DEBUG ====================================================================='
33
+ puts cmd
34
+ puts '# DEBUG ====================================================================='
35
+ puts IO.popen(cmd).read
36
+ else
37
+ system(cmd + ' 1>/dev/null 2>&1 ')
38
+ end
39
+ end
40
+ def Cdo.run(cmd,ofile=nil,options='',returnArray=false)
41
+ cmd = "#{@@CDO} -O #{options} #{cmd} "
42
+ case ofile
43
+ when $stdout
44
+ cmd << " 2>/dev/null"
45
+ return IO.popen(cmd).readlines.map {|l| l.chomp.strip}
46
+ when nil
47
+ ofile = Tempfile.new("Cdo.rb").path
48
+ end
49
+ cmd << "#{ofile}"
50
+ call(cmd)
51
+ if State[:returnArray] or returnArray
52
+ return NetCDF.open(ofile)
53
+ else
54
+ return ofile
55
+ end
56
+ end
57
+
58
+ public
14
59
  def Cdo.Debug=(value)
15
60
  State[:debug] = value
16
61
  end
17
62
  def Cdo.Debug
18
63
  State[:debug]
19
64
  end
65
+ def Cdo.returnArray=(value)
66
+ 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
78
+ end
79
+ end
80
+ def Cdo.returnArray
81
+ State[:returnArray]
82
+ end
20
83
 
21
84
  # test if @@CDO can be used
22
85
  def Cdo.checkCdo
@@ -28,13 +91,11 @@ module Cdo
28
91
  puts IO.popen(@@CDO + " -V").readlines
29
92
  end
30
93
  end
31
-
32
94
  def Cdo.setCdo(cdo)
33
95
  puts "Will use #{cdo} instead of #@@CDO" if Cdo.Debug
34
96
  @@CDO = cdo
35
97
  end
36
98
 
37
-
38
99
  def Cdo.getOperators
39
100
  cmd = @@CDO + ' 2>&1'
40
101
  help = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
@@ -46,29 +107,6 @@ module Cdo
46
107
  help[help.index("Operators:")+1].split
47
108
  end
48
109
  end
49
- def Cdo.call(cmd)
50
- if (State[:debug])
51
- puts '# DEBUG ====================================================================='
52
- puts cmd
53
- puts '# DEBUG ====================================================================='
54
- puts IO.popen(cmd).read
55
- else
56
- system(cmd + ' 1>/dev/null 2>&1 ')
57
- end
58
- end
59
- def Cdo.run(cmd,ofile=nil,options='')
60
- cmd = "#{@@CDO} -O #{options} #{cmd} "
61
- case ofile
62
- when $stdout
63
- cmd << " 2>/dev/null"
64
- return IO.popen(cmd).readlines.map {|l| l.chomp.strip}
65
- when nil
66
- ofile = Tempfile.new("Cdo.rb").path
67
- end
68
- cmd << "#{ofile}"
69
- call(cmd)
70
- return ofile
71
- end
72
110
 
73
111
  # Call an operator chain without checking opeartors
74
112
  def Cdo.chainCall(chain,*args)
@@ -87,8 +125,29 @@ module Cdo
87
125
  end
88
126
  end
89
127
 
128
+ def Cdo.method_missing(sym, *args, &block)
129
+ # args is expected to look like [opt1,...,optN,:in => iStream,:out => oStream] where
130
+ # iStream could be another CDO call (timmax(selname(Temp,U,V,ifile.nc))
131
+ puts "Operator #{sym.to_s} is called" if State[:debug]
132
+ if getOperators.include?(sym.to_s) or @@undocumentedOperators.include?(sym.to_s)
133
+ io = args.find {|a| a.class == Hash}
134
+ args.delete_if {|a| a.class == Hash}
135
+ if /(diff|info|show|griddes)/.match(sym)
136
+ run(" -#{sym.to_s} #{io[:in]} ",$stdout)
137
+ else
138
+ opts = args.empty? ? '' : ',' + args.reject {|a| a.class == Hash}.join(',')
139
+ run(" -#{sym.to_s}#{opts} #{io[:in]} ",io[:out],io[:options],io[:returnArray])
140
+ end
141
+ else
142
+ warn "Operator #{sym.to_s} not found"
143
+ end
144
+ end
145
+
146
+ #==================================================================
147
+ # Addional operotors:
148
+ #------------------------------------------------------------------
90
149
  def Cdo.boundaryLevels(args)
91
- ilevels = Cdo.showlevel(:in => args[:in]).map(&:to_f)
150
+ ilevels = Cdo.showlevel(:in => args[:in])[0].split.map(&:to_f)
92
151
  bound_levels = Array.new(ilevels.size+1)
93
152
  bound_levels[0] = 0
94
153
  (1..ilevels.size).each {|i|
@@ -106,25 +165,9 @@ module Cdo
106
165
  }
107
166
  delta_levels
108
167
  end
109
-
110
- def Cdo.method_missing(sym, *args, &block)
111
- # args is expected to look like [opt1,...,optN,:in => iStream,:out => oStream] where
112
- # iStream could be another CDO call (timmax(selname(Temp,U,V,ifile.nc))
113
- puts "Operator #{sym.to_s} is called" if State[:debug]
114
- if getOperators.include?(sym.to_s) or @@undocumentedOperators.include?(sym.to_s)
115
- io = args.find {|a| a.class == Hash}
116
- args.delete_if {|a| a.class == Hash}
117
- if /(info|show|griddes)/.match(sym)
118
- run(" -#{sym.to_s} #{io[:in]} ",$stdout)
119
- else
120
- opts = args.empty? ? '' : ',' + args.reject {|a| a.class == Hash}.join(',')
121
- run(" -#{sym.to_s}#{opts} #{io[:in]} ",io[:out],io[:options])
122
- end
123
- else
124
- warn "Operator #{sym.to_s} not found"
125
- end
126
- end
127
168
  end
169
+
170
+ # Helper module for easy temp file handling
128
171
  module MyTempfile
129
172
  require 'tempfile'
130
173
  @@_tempfiles = []
data/test/test_cdo.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
2
  require 'test/unit'
3
3
  require 'cdo'
4
+ require 'pp'
4
5
 
5
- class TestJobQueue < Test::Unit::TestCase
6
+ class TestCdo < Test::Unit::TestCase
6
7
 
7
8
  DEFAULT_CDO_PATH = '/usr/bin/cdo'
8
9
  def setup
@@ -40,6 +41,20 @@ class TestJobQueue < Test::Unit::TestCase
40
41
  assert_equal("File format: GRIB",info[0])
41
42
 
42
43
  end
44
+ def test_args
45
+ #Cdo.Debug = true
46
+ #MyTempfile.setPersist(true)
47
+ ofile0 = MyTempfile.path
48
+ ofile1 = MyTempfile.path
49
+ ofile2 = MyTempfile.path
50
+ ofile3 = MyTempfile.path
51
+ Cdo.stdatm(0,20,40,80,200,230,400,600,1100,:out => ofile0)
52
+ Cdo.intlevel(0,10,50,100,500,1000, :in => ofile0,:out => ofile1)
53
+ Cdo.intlevel([0,10,50,100,500,1000],:in => ofile0,:out => ofile2)
54
+ Cdo.sub(:in => [ofile1,ofile2].join(' '),:out => ofile3)
55
+ info = Cdo.infon(:in => ofile3)
56
+ (1...info.size).each {|i| assert_equal(0.0,info[i].split[-1].to_f)}
57
+ end
43
58
  def test_operator_options
44
59
  ofile = MyTempfile.path
45
60
  targetLevels = [0,10,50,100,200,400,1000]
@@ -61,6 +76,51 @@ class TestJobQueue < Test::Unit::TestCase
61
76
  Cdo.chainCall("-setname,veloc -copy",:in => "-random,r1x1",:out => ofile,:options => "-f nc")
62
77
  assert_equal(["veloc"],Cdo.showname(:in => ofile))
63
78
  end
79
+
80
+ def test_diff
81
+ diffv = Cdo.diffn(:in => "-random,r1x1 -random,r1x1")
82
+ assert_equal(diffv[1].split(' ')[4],"random")
83
+ assert_equal(diffv[1].split(' ')[-1],"0.53060")
84
+ diff = Cdo.diff(:in => "-random,r1x1 -random,r1x1")
85
+ assert_equal(diff[1].split(' ')[-1],"0.53060")
86
+ end
87
+
88
+ def test_bndLevels
89
+ ofile = MyTempfile.path
90
+ Cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:out => ofile,:options => "-f nc")
91
+ assert_equal([0, 50.0, 150.0, 350.0, 650.0, 1100.0, 1700.0, 2500.0, 3500.0, 4500.0, 5500.0],
92
+ Cdo.boundaryLevels(:in => "-selname,T #{ofile}"))
93
+ assert_equal([50.0, 100.0, 200.0, 300.0, 450.0, 600.0, 800.0, 1000.0, 1000.0, 1000.0],
94
+ Cdo.thicknessOfLevels(:in => ofile))
95
+ end
96
+
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
+ def test_combine
108
+ ofile0, ofile1 = MyTempfile.path, MyTempfile.path
109
+ Cdo.fldsum(:in => Cdo.stdatm(25,100,250,500,875,1400,2100,3000,4000,5000,:options => "-f nc"),:out => ofile0)
110
+ ofile1 = Cdo.fldsum(:in => "-stdatm,25,100,250,500,875,1400,2100,3000,4000,5000",:options => "-f nc")
111
+ Cdo.returnArray = true
112
+ diff = Cdo.sub(:in => [ofile0,ofile1].join(' '),:out => MyTempfile.path).var('T').get
113
+ assert_equal(0.0,diff.min)
114
+ assert_equal(0.0,diff.max)
115
+ Cdo.returnArray = false
116
+ end
117
+ def test_simple_returnArray
118
+ ofile0, ofile1 = MyTempfile.path, MyTempfile.path
119
+ sum = Cdo.fldsum(:in => Cdo.stdatm(0,:options => "-f nc"),
120
+ :returnArray => true).var("P").get
121
+ assert_equal(1013.25,sum.min)
122
+ test_returnArray
123
+ end
64
124
  end
65
125
 
66
126
  # # Calling simple operators
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.1
4
+ version: 1.0.2
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: 2011-12-15 00:00:00.000000000 Z
12
+ date: 2012-01-11 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
@@ -23,6 +23,7 @@ files:
23
23
  - gemspec
24
24
  - COPYING
25
25
  - README.rdoc
26
+ - ChangeLog
26
27
  - test/test_cdo.rb
27
28
  homepage: http://code.zmaw.de/projects/cdo
28
29
  licenses: