cdo 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +4 -0
- data/gemspec +1 -1
- data/lib/cdo.rb +57 -46
- data/test/test_cdo.rb +40 -23
- 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
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
|
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
|
-
#
|
25
|
-
#
|
26
|
-
@@undocumentedOperators = %w[
|
27
|
-
|
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]
|
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.
|
89
|
+
def Cdo.debug=(value)
|
60
90
|
State[:debug] = value
|
61
91
|
end
|
62
|
-
def Cdo.
|
92
|
+
def Cdo.debug
|
63
93
|
State[:debug]
|
64
94
|
end
|
65
|
-
def Cdo.
|
95
|
+
def Cdo.setReturnArray(value=true)
|
66
96
|
if value
|
67
|
-
|
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.
|
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.
|
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)
|
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
|
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(
|
195
|
+
t = "_"+rand(@@N).to_s
|
185
196
|
@@_tempfiles << t
|
186
197
|
t
|
187
198
|
end
|
data/test/test_cdo.rb
CHANGED
@@ -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
|
-
|
33
|
-
|
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.
|
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.
|
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.
|
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.
|
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-
|
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
|