cdp 0.0.4 → 0.0.5
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/README.textile +1 -1
- data/gemspec +1 -1
- data/lib/cdp.rb +156 -23
- data/test/test_cdp.rb +43 -2
- metadata +2 -2
data/README.textile
CHANGED
data/gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
|
3
3
|
|
4
4
|
spec = Gem::Specification.new do |s|
|
5
5
|
s.name = "cdp"
|
6
|
-
s.version = '0.0.
|
6
|
+
s.version = '0.0.5'
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.files = ["lib/cdp.rb"] + ["gemspec"]
|
9
9
|
s.test_file = "test/test_cdp.rb"
|
data/lib/cdp.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'cdo'
|
2
2
|
require 'socket'
|
3
|
-
|
3
|
+
require "numru/netcdf"
|
4
|
+
require 'numru/netcdf_miss'
|
5
|
+
include NumRu
|
4
6
|
|
7
|
+
module Cdp
|
5
8
|
@@debug = false
|
6
9
|
|
7
|
-
|
8
10
|
# setup of CDO on different machines based on the hostname
|
9
11
|
def Cdp.setCDO
|
10
12
|
hostname = Socket.gethostname
|
@@ -60,40 +62,171 @@ module Cdp
|
|
60
62
|
|
61
63
|
# compute area weights from an area variable
|
62
64
|
def Cdp.areaWeights(areaVarname,areaFile,ofile=nil,force=false)
|
63
|
-
area = Cdo.selname(areaVarname,:in => areaFile)
|
64
|
-
areaSum = Cdo.enlarge(area,:in => "-fldsum #{area}")
|
65
65
|
if ofile.nil?
|
66
|
-
|
66
|
+
area = Cdo.selname(areaVarname,:input => areaFile)
|
67
|
+
Cdo.setname("area_weight",:input => " -div #{area} -enlarge,#{area} -fldsum #{area}")
|
67
68
|
else
|
68
|
-
unless force
|
69
|
-
|
70
|
-
|
71
|
-
else
|
72
|
-
puts "Resuse existing file #{ofile}" if @@debug
|
73
|
-
return ofile
|
74
|
-
end
|
69
|
+
unless File.exist?(ofile) and not force
|
70
|
+
puts "Resuse existing file #{ofile}" if @@debug
|
71
|
+
return ofile
|
75
72
|
else
|
76
|
-
Cdo.
|
73
|
+
area = Cdo.selname(areaVarname,:input => areaFile)
|
74
|
+
Cdo.setname("area_weight",:input => " -div #{area} -enlarge,#{area} -fldsum #{area}", :output => ofile)
|
77
75
|
end
|
78
76
|
end
|
79
77
|
end
|
80
78
|
|
81
79
|
# compute area weights from an area variable with a mask from another file
|
82
80
|
def Cdp.maskedAreaWeights(areaVarname,areaFile,maskVarname,maskFile,ofile=nil,force=false)
|
83
|
-
maskedArea = Cdo.div(:in => " -selname,#{areaVarname} #{areaFile} -selname,#{maskVarname} #{maskFile}")
|
84
81
|
if ofile.nil?
|
85
|
-
|
82
|
+
maskedArea = Cdo.div(:input => " -selname,#{areaVarname} #{areaFile} -selname,#{maskVarname} #{maskFile}")
|
83
|
+
Cdo.setname("area_weight", :input => " -div #{maskedArea} -enlarge,#{maskedArea} -fldsum #{maskedArea}")
|
86
84
|
else
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
else
|
91
|
-
puts "Resuse existing file #{ofile}" if @@debug
|
92
|
-
return ofile
|
93
|
-
end
|
85
|
+
if File.exist?(ofile) and not force
|
86
|
+
puts "Resuse existing file #{ofile}" if @@debug
|
87
|
+
return ofile
|
94
88
|
else
|
95
|
-
Cdo.
|
89
|
+
maskedArea = Cdo.div(:input => " -selname,#{areaVarname} #{areaFile} -selname,#{maskVarname} #{maskFile}")
|
90
|
+
Cdo.setname("area_weight", :input => " -div #{maskedArea} -enlarge,#{maskedArea} -fldsum #{maskedArea}", :output => ofile)
|
96
91
|
end
|
97
92
|
end
|
98
93
|
end
|
94
|
+
|
95
|
+
# split data file with global grid into 2 separate files with northern and
|
96
|
+
# southern hemisphere grid
|
97
|
+
# TODO: currently ICON cell variable are supported only
|
98
|
+
def Cdp.splitHemisphere(iFilename,varname,lon,lat,dim='2d')
|
99
|
+
iFile = NetCDF.open(iFilename)
|
100
|
+
unless iFile.var_names.include?(varname)
|
101
|
+
warn "Could not find #{varname} in #{iFilename}"
|
102
|
+
raise IOError
|
103
|
+
end
|
104
|
+
lats = iFile.var(lat).get
|
105
|
+
var = iFile.var(varname)
|
106
|
+
varDims = var.dim_names
|
107
|
+
varValues = var.get_with_miss
|
108
|
+
splittedDim = varDims[0]
|
109
|
+
|
110
|
+
# compute location indices and corresponding values
|
111
|
+
nhIndeces = (lats>0.0).where
|
112
|
+
shIndeces = (lats<0.0).where
|
113
|
+
|
114
|
+
case varValues.shape.size
|
115
|
+
when 3
|
116
|
+
varValuesNH = varValues[nhIndeces,true,true]
|
117
|
+
varValuesSH = varValues[shIndeces,true,true]
|
118
|
+
when 2
|
119
|
+
varValuesNH = varValues[nhIndeces,true]
|
120
|
+
varValuesSH = varValues[shIndeces,true]
|
121
|
+
when 1
|
122
|
+
varValuesNH = varValues[nhIndeces]
|
123
|
+
varValuesSH = varValues[shIndeces]
|
124
|
+
end
|
125
|
+
|
126
|
+
# create output
|
127
|
+
iBaseFilename = File.basename(iFilename)
|
128
|
+
nhFile,shFile = "nh_#{iBaseFilename}","sh_#{iBaseFilename}"
|
129
|
+
[nhFile,shFile].each_with_index {|file,i|
|
130
|
+
puts "Creating '#{file}' ...."
|
131
|
+
indeces = [nhIndeces,shIndeces][i]
|
132
|
+
oFile = NetCDF.create(file)
|
133
|
+
|
134
|
+
# create data definitions
|
135
|
+
iFile.each_dim {|dim|
|
136
|
+
pp dim.name
|
137
|
+
if splittedDim == dim.name
|
138
|
+
oFile.def_dim(dim.name,indeces.size)
|
139
|
+
else
|
140
|
+
oFile.def_dim(dim.name,dim.length)
|
141
|
+
end
|
142
|
+
}
|
143
|
+
|
144
|
+
# copy attributes
|
145
|
+
iFile.each_var {|var|
|
146
|
+
next unless ([varname] + varDims + [lon,lat] + [lon,lat].map {|c| c+"_vertices"}).flatten.include?(var.name)
|
147
|
+
newvar = oFile.def_var( var.name, var.ntype, var.dim_names )
|
148
|
+
var.each_att{|att| newvar.put_att( att.name, att.get )}
|
149
|
+
}
|
150
|
+
oFile.enddef
|
151
|
+
iFile.each_var {|var|
|
152
|
+
next unless ([varname] + varDims + [lon,lat] + [lon,lat].map {|c| c+"_vertices"}).flatten.include?(var.name)
|
153
|
+
case var.name
|
154
|
+
when varname
|
155
|
+
case varDims.size
|
156
|
+
when 3
|
157
|
+
oFile.var(var.name).put(var.get[indeces,true,true])
|
158
|
+
when 2
|
159
|
+
oFile.var(var.name).put(var.get[indeces,true])
|
160
|
+
end
|
161
|
+
when 'p_ice_concSum'
|
162
|
+
oFile.var(var.name).put(var.get[indeces,true])
|
163
|
+
when 'cell_area'
|
164
|
+
oFile.var(var.name).put(var.get[indeces])
|
165
|
+
when lon,lat
|
166
|
+
oFile.var(var.name).put(var.get[indeces])
|
167
|
+
when lon+'_vertices',lat+'_vertices'
|
168
|
+
oFile.var(var.name).put(var.get[true,indeces])
|
169
|
+
else
|
170
|
+
oFile.var(var.name).put(var.get)
|
171
|
+
end
|
172
|
+
}
|
173
|
+
oFile.close
|
174
|
+
}
|
175
|
+
|
176
|
+
[nhFile,shFile]
|
177
|
+
end
|
178
|
+
def Cdp.splitICONHemisphere(iFilename,varname,lon,lat)
|
179
|
+
iFile = NetCDF.open(iFilename)
|
180
|
+
lats = iFile.var(lat).get
|
181
|
+
iceValues = iFile.var(varname).get_with_miss
|
182
|
+
|
183
|
+
# compute location indices and corresponding values
|
184
|
+
nhIndeces = (lats>0.0).where
|
185
|
+
shIndeces = (lats<0.0).where
|
186
|
+
iceValuesNH = iceValues[nhIndeces,true,1..-1]
|
187
|
+
iceValuesSH = iceValues[shIndeces,true,1..-1]
|
188
|
+
|
189
|
+
|
190
|
+
# create output
|
191
|
+
nhFile,shFile = "nh_#{iFilename}","sh_#{iFilename}"
|
192
|
+
[nhFile,shFile].each_with_index {|file,i|
|
193
|
+
puts "Creating '#{file}' ...."
|
194
|
+
indeces = [nhIndeces,shIndeces][i]
|
195
|
+
f = NetCDF.create(file)
|
196
|
+
iFile.each_dim {|dim|
|
197
|
+
next if ['clon','clat','ncells'].include?(dim.name) or
|
198
|
+
f.def_dim(dim.name,dim.length)
|
199
|
+
}
|
200
|
+
["clon","clat","ncells"].each {|hdim|
|
201
|
+
f.def_dim(hdim,indeces.size)
|
202
|
+
}
|
203
|
+
|
204
|
+
iFile.each_var{|var|
|
205
|
+
a = {var.name => var.dim_names}
|
206
|
+
newvar = f.def_var( var.name, var.ntype, var.dim_names )
|
207
|
+
var.each_att{|att| newvar.put_att( att.name, att.get )}
|
208
|
+
}
|
209
|
+
f.enddef
|
210
|
+
iFile.each_var{|var|
|
211
|
+
#puts var.name
|
212
|
+
case var.name
|
213
|
+
when varname
|
214
|
+
f.var(var.name).put(var.get[indeces,true,true])
|
215
|
+
when 'p_ice_concSum'
|
216
|
+
f.var(var.name).put(var.get[indeces,true])
|
217
|
+
when 'cell_area'
|
218
|
+
f.var(var.name).put(var.get[indeces])
|
219
|
+
when lon,lat
|
220
|
+
f.var(var.name).put(var.get[indeces])
|
221
|
+
when lon+'_vertices',lat+'_vertices'
|
222
|
+
f.var(var.name).put(var.get[true,indeces])
|
223
|
+
else
|
224
|
+
f.var(var.name).put(var.get)
|
225
|
+
end
|
226
|
+
}
|
227
|
+
f.close
|
228
|
+
}
|
229
|
+
|
230
|
+
[nhFile,shFile]
|
231
|
+
end
|
99
232
|
end
|
data/test/test_cdp.rb
CHANGED
@@ -6,6 +6,9 @@ require 'pp'
|
|
6
6
|
DATADIR = ENV['HOME'] + "/data/icon"
|
7
7
|
ICONGRID = DATADIR + "/icon-R2B04-grid-etopo.nc"
|
8
8
|
ICONMASK = DATADIR + "/mask.nc"
|
9
|
+
ICONOCE = DATADIR + "/oce.nc"
|
10
|
+
ICONOCEL = DATADIR + "/oceLong.nc"
|
11
|
+
ICONICE = DATADIR + "/oce.nc"
|
9
12
|
WEIGHTS = File.dirname(__FILE__) + "/weights.nc"
|
10
13
|
|
11
14
|
class TestCdp < Test::Unit::TestCase
|
@@ -22,20 +25,30 @@ class TestCdp < Test::Unit::TestCase
|
|
22
25
|
Cdp.setDebug
|
23
26
|
weights = Cdp.areaWeights("cell_area",ICONGRID)
|
24
27
|
# global sum over all weights should be 1
|
25
|
-
assert_equal("1",Cdo.outputkey("value", :
|
28
|
+
assert_equal("1",Cdo.outputkey("value", :input => Cdo.fldsum(:input => weights)).first)
|
26
29
|
weights = Cdp.areaWeights("cell_area",ICONGRID,weights)
|
27
30
|
weights = Cdp.areaWeights("cell_area",ICONGRID,WEIGHTS)
|
28
31
|
assert_equal(WEIGHTS,weights)
|
29
32
|
weights = Cdp.areaWeights("cell_area",ICONGRID,WEIGHTS)
|
30
33
|
assert_equal(WEIGHTS,weights)
|
31
34
|
end
|
35
|
+
|
36
|
+
def test_splitFiles
|
37
|
+
files = []
|
38
|
+
files << '../A/a' << '../A/aa' << '../B/b' << '../B/bb' << 'gridfile'
|
39
|
+
grid, exp, exp4ana = Cdp.splitFilesIntoExperiments(files)
|
40
|
+
assert_equal('gridfile',grid)
|
41
|
+
assert_equal(exp['A'],['../A/a','../A/aa'])
|
42
|
+
assert_equal(exp['B'],['../B/b','../B/bb'])
|
43
|
+
end
|
32
44
|
def test_masked_area_weight
|
33
45
|
Cdo.debug = false
|
34
46
|
Cdp.setCDO
|
35
47
|
Cdp.setDebug
|
36
48
|
weights = Cdp.maskedAreaWeights("cell_area",ICONGRID,"wet_c",ICONMASK)
|
37
49
|
# global sum over all weights should be 1
|
38
|
-
|
50
|
+
pp Cdo.outputkey("value", :input => Cdo.fldsum(:input => weights))
|
51
|
+
assert_equal("1",Cdo.outputkey("value", :input => Cdo.fldsum(:input => weights)).uniq.first)
|
39
52
|
|
40
53
|
weights = Cdp.maskedAreaWeights("cell_area",ICONGRID,"wet_c",ICONMASK,WEIGHTS)
|
41
54
|
assert_equal(WEIGHTS,weights)
|
@@ -44,4 +57,32 @@ class TestCdp < Test::Unit::TestCase
|
|
44
57
|
weights = Cdp.maskedAreaWeights("cell_area",ICONGRID,"wet_c",ICONMASK,WEIGHTS,true)
|
45
58
|
assert_equal(WEIGHTS,weights)
|
46
59
|
end
|
60
|
+
def test_split_sphere
|
61
|
+
# one timesteps
|
62
|
+
Cdp.splitHemisphere(ICONOCE,"ELEV",'clon','clat')
|
63
|
+
return
|
64
|
+
# with missing values
|
65
|
+
Cdo.debug = true
|
66
|
+
maskedOce = Cdo.div(:input => "-selname,T #{ICONOCE} -selname,wet_c #{ICONOCE}")
|
67
|
+
Cdp.splitHemisphere(maskedOce,"T",'clon','clat')
|
68
|
+
maskedOce = Cdo.div(:input => "-selname,ELEV #{ICONOCE} -sellevidx,1 -selname,wet_c #{ICONOCE}")
|
69
|
+
Cdp.splitHemisphere(maskedOce,"ELEV",'clon','clat')
|
70
|
+
|
71
|
+
# 10 timesteps
|
72
|
+
Cdp.splitHemisphere(ICONOCEL,"ELEV",'clon','clat')
|
73
|
+
Cdp.splitHemisphere(ICONOCEL,"T",'clon','clat')
|
74
|
+
# with missing values
|
75
|
+
Cdo.debug = true
|
76
|
+
maskedOce = Cdo.div(:input => "-selname,T #{ICONOCEL} -selname,wet_c #{ICONOCEL}")
|
77
|
+
Cdp.splitHemisphere(maskedOce,"T",'clon','clat')
|
78
|
+
maskedOce = Cdo.div(:input => "-selname,ELEV #{ICONOCEL} -sellevidx,1 -selname,wet_c #{ICONOCEL}")
|
79
|
+
Cdp.splitHemisphere(maskedOce,"ELEV",'clon','clat')
|
80
|
+
end
|
81
|
+
def test_split_icon_sphere
|
82
|
+
|
83
|
+
# one timesteps
|
84
|
+
elev = Cdo.selname("ELEV",:input => ICONOCEL)
|
85
|
+
pp Cdo.infov(:input => elev)
|
86
|
+
Cdp.splitICONHemisphere(elev,"ELEV",'clon','clat')
|
87
|
+
end
|
47
88
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cdp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
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-
|
12
|
+
date: 2012-11-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cdo
|