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.
- 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
|