cdo 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +3 -0
- data/README.rdoc +1 -1
- data/gemspec +2 -2
- data/lib/cdo.rb +88 -45
- data/test/test_cdo.rb +61 -1
- metadata +3 -2
data/ChangeLog
ADDED
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.
|
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
|
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.
|
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:
|
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:
|