ruby-netcdf 0.7.1 → 0.8.0
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.
- checksums.yaml +5 -13
- data/.ChangeLog.until20150117 +447 -0
- data/.gitignore +4 -6
- data/ChangeLog +392 -383
- data/LICENSE.txt +32 -57
- data/Rakefile +36 -1
- data/{extconf.rb → ext/numru/extconf.rb} +2 -2
- data/{netcdfraw.c → ext/numru/netcdfraw.c} +318 -320
- data/lib/numru/netcdf/version.rb +7 -0
- data/lib/numru/netcdf.rb +806 -0
- data/lib/{netcdf_miss.rb → numru/netcdf_miss.rb} +0 -0
- data/ruby-netcdf-bigmem.gemspec +29 -0
- data/ruby-netcdf.gemspec +8 -13
- data/test/aref_aset.rb +63 -33
- data/test/char_var.rb +32 -21
- data/test/clone.rb +46 -51
- data/test/create_tmp.rb +17 -13
- data/test/def_var_with_dim.rb +29 -11
- data/test/factor_offset.rb +77 -46
- data/test/putatt.rb +71 -49
- data/test/test.rb +197 -190
- data/test/type.rb +27 -11
- metadata +37 -24
- data/.rspec +0 -2
- data/.travis.yml +0 -3
- data/bin/console +0 -14
- data/bin/setup +0 -7
- data/lib/netcdf.rb +0 -808
- data/lib/version.rb +0 -5
data/lib/numru/netcdf.rb
ADDED
@@ -0,0 +1,806 @@
|
|
1
|
+
require 'narray'
|
2
|
+
require 'numru/netcdf/version'
|
3
|
+
require 'numru/netcdfraw'
|
4
|
+
|
5
|
+
if NArray.const_defined?(:SUPPORT_BIGMEM) && NArray::SUPPORT_BIGMEM
|
6
|
+
unless NumRu::NetCDF::SUPPORT_BIGMEM
|
7
|
+
raise "Ruby-NetCDF was compiled with NArray with big memory supoort " +
|
8
|
+
"(NArray-bigmem). However the NArray loaded is not NArray-bigmem."
|
9
|
+
end
|
10
|
+
else
|
11
|
+
if NumRu::NetCDF::SUPPORT_BIGMEM
|
12
|
+
raise "Ruby-NetCDF was compiled with NArray without big memory support. " +
|
13
|
+
"However the NArray loaded is with the support (NArray-bigmem)."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module NumRu
|
18
|
+
class NetCDF
|
19
|
+
|
20
|
+
Max_Try = 100
|
21
|
+
|
22
|
+
NCVERSION = NetCDF.libvers
|
23
|
+
|
24
|
+
if NCVERSION[0..0] >= "4"
|
25
|
+
@@nc4 = true
|
26
|
+
else
|
27
|
+
@@nc4 = false
|
28
|
+
end
|
29
|
+
def NetCDF.nc4?
|
30
|
+
@@nc4
|
31
|
+
end
|
32
|
+
|
33
|
+
@@cr_format = 0
|
34
|
+
|
35
|
+
def NetCDF.creation_format=(cmode)
|
36
|
+
raise("This method is available only for NetCDF >= 4") unless @@nc4
|
37
|
+
case cmode
|
38
|
+
when 0, nil, NC_CLASSIC_MODEL, /^CLASSIC$/i, NC_FORMAT_CLASSIC
|
39
|
+
# classic netcdf ver 3 fmt
|
40
|
+
@@cr_format = 0
|
41
|
+
when NC_64BIT_OFFSET, /^64BIT_OFFSET$/i, NC_FORMAT_64BIT
|
42
|
+
@@cr_format = NC_64BIT_OFFSET
|
43
|
+
when NC_NETCDF4, /^NETCDF4$/i, NC_FORMAT_NETCDF4
|
44
|
+
@@cr_format = NC_NETCDF4
|
45
|
+
when ( NC_NETCDF4 | NC_CLASSIC_MODEL), /^NETCDF4_CLASSIC$/i, NC_FORMAT_NETCDF4_CLASSIC
|
46
|
+
# NetCDF4 but disabling new data models
|
47
|
+
@@cr_format = NC_NETCDF4 | NC_CLASSIC_MODEL
|
48
|
+
else
|
49
|
+
raise ArgumentError, "Unsupported creation mode: #{cmod.to_s}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def NetCDF.creation_format
|
54
|
+
raise("This method is available only for NetCDF >= 4") unless @@nc4
|
55
|
+
case @@cr_format
|
56
|
+
when 0
|
57
|
+
"TRADITIONAL"
|
58
|
+
when NC_64BIT_OFFSET
|
59
|
+
"64BIT_OFFSET"
|
60
|
+
when NC_NETCDF4
|
61
|
+
"NETCDF4"
|
62
|
+
when (NC_NETCDF4 | NC_CLASSIC_MODEL)
|
63
|
+
"NETCDF4_CLASSIC"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def NetCDF.open(filename,mode="r",share=false)
|
68
|
+
call_create=false # false-> nc_open; true->nc_create
|
69
|
+
case(mode)
|
70
|
+
when "r","rb" # read only
|
71
|
+
mode=NC_NOWRITE
|
72
|
+
when "w","w+","wb","w+b" # overwrite if exits
|
73
|
+
call_create=true
|
74
|
+
mode=NC_CLOBBER
|
75
|
+
when "a","a+","r+","ab","a+b","r+b" # append if exits
|
76
|
+
if( File.exists?(filename) )
|
77
|
+
mode=NC_WRITE
|
78
|
+
else
|
79
|
+
call_create=true #(nonexsitent --> create)
|
80
|
+
mode=NC_CLOBBER
|
81
|
+
end
|
82
|
+
else
|
83
|
+
raise NetcdfError, "Mode #{mode} is not supported"
|
84
|
+
end
|
85
|
+
case(share)
|
86
|
+
when false
|
87
|
+
share=0
|
88
|
+
when true
|
89
|
+
share=NC_SHARE
|
90
|
+
else
|
91
|
+
raise NetcdfError, "We can't use the sharing mode you typed"
|
92
|
+
end
|
93
|
+
omode = mode | share
|
94
|
+
if(!call_create)
|
95
|
+
nc_open(filename,omode)
|
96
|
+
else
|
97
|
+
nc_create(filename,omode)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class << NetCDF
|
102
|
+
alias new open
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def NetCDF.create(filename,noclobber=false,share=false)
|
107
|
+
case(noclobber)
|
108
|
+
when false
|
109
|
+
noclobber=NC_CLOBBER
|
110
|
+
when true
|
111
|
+
noclobber=NC_NOCLOBBER
|
112
|
+
else
|
113
|
+
raise NetcdfError,"noclobber (2nd argument) must be true or false"
|
114
|
+
end
|
115
|
+
case(share)
|
116
|
+
when false
|
117
|
+
share=0
|
118
|
+
when true
|
119
|
+
share=NC_SHARE
|
120
|
+
else
|
121
|
+
raise NetcdfError,"share (3rd argument) must be true or false"
|
122
|
+
end
|
123
|
+
|
124
|
+
cmode=noclobber | share | @@cr_format
|
125
|
+
nc_create(filename,cmode)
|
126
|
+
end
|
127
|
+
|
128
|
+
class << NetCDF
|
129
|
+
def clean_tmpfile(path)
|
130
|
+
proc {
|
131
|
+
print "removing ", path, "..." if $DEBUG
|
132
|
+
if File.exist?(path)
|
133
|
+
File.unlink(path)
|
134
|
+
end
|
135
|
+
print "done\n" if $DEBUG
|
136
|
+
}
|
137
|
+
end
|
138
|
+
protected :clean_tmpfile
|
139
|
+
end
|
140
|
+
|
141
|
+
def NetCDF.create_tmp(tmpdir=ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'.',
|
142
|
+
share=false)
|
143
|
+
basename = 'temp'
|
144
|
+
n = 0
|
145
|
+
while true
|
146
|
+
begin
|
147
|
+
tmpname = sprintf('%s/%s%d_%d.nc', tmpdir, basename, $$, n)
|
148
|
+
unless File.exist?(tmpname)
|
149
|
+
netcdf = NetCDF.create(tmpname, true, share)
|
150
|
+
ObjectSpace.define_finalizer(netcdf,
|
151
|
+
NetCDF.clean_tmpfile(tmpname))
|
152
|
+
break
|
153
|
+
end
|
154
|
+
rescue
|
155
|
+
raise NetcdfError, "cannot generate tempfile `%s'" % tmpname if n >= Max_Try
|
156
|
+
end
|
157
|
+
n += 1
|
158
|
+
end
|
159
|
+
netcdf
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def put_att(attname,val,atttype=nil)
|
164
|
+
put_attraw(attname,val,atttype)
|
165
|
+
end
|
166
|
+
|
167
|
+
def def_var_with_dim(name, vartype, shape_ul0, dimnames)
|
168
|
+
# Same as def_var but defines dimensions first if needed.
|
169
|
+
# Use zero in shape to define an unlimited dimension.
|
170
|
+
if (shape_ul0.length != dimnames.length ) then
|
171
|
+
raise ArgumentError, 'lengths of shape and dimnames do not agree'
|
172
|
+
end
|
173
|
+
dims = []
|
174
|
+
dimnames.each_index{ |i|
|
175
|
+
dim = self.dim( dimnames[i] )
|
176
|
+
if ( dim != nil ) then
|
177
|
+
# dim exists --> check the length
|
178
|
+
if (shape_ul0[i] != dim.length_ul0 ) then
|
179
|
+
raise ArgumentError, "dimension length do not agree: #{i}th dim: "+\
|
180
|
+
"#{shape_ul0[i]} and #{dim.length_ul0}"
|
181
|
+
end
|
182
|
+
dims.push(dim)
|
183
|
+
else
|
184
|
+
# dim does not exist --> define it
|
185
|
+
dims.push( def_dim( dimnames[i], shape_ul0[i] ) )
|
186
|
+
end
|
187
|
+
}
|
188
|
+
def_var(name, vartype, dims)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Iterators:
|
192
|
+
def each_dim
|
193
|
+
num_dim=ndims()
|
194
|
+
for dimid in 0..num_dim-1
|
195
|
+
obj_Dim=id2dim(dimid)
|
196
|
+
yield(obj_Dim)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def each_var
|
201
|
+
num_var=nvars()
|
202
|
+
for varid in 0..num_var-1
|
203
|
+
obj_Var=id2var(varid)
|
204
|
+
yield(obj_Var)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def each_att
|
209
|
+
num_att=natts()
|
210
|
+
for attnum in 0..num_att-1
|
211
|
+
obj_Att=id2att(attnum)
|
212
|
+
yield(obj_Att)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def dims( names=nil ) # return all if names==nil
|
217
|
+
if names == nil
|
218
|
+
dims = (0..ndims()-1).collect{|dimid| id2dim(dimid)}
|
219
|
+
else
|
220
|
+
raise TypeError, "names is not an array" if ! names.is_a?(Array)
|
221
|
+
dims = names.collect{|name| dim(name)}
|
222
|
+
raise ArgumentError, "One or more dimensions do not exist" if dims.include?(nil)
|
223
|
+
end
|
224
|
+
dims
|
225
|
+
end
|
226
|
+
|
227
|
+
def vars( names=nil ) # return all if names==nil
|
228
|
+
if names == nil
|
229
|
+
vars = (0..nvars()-1).collect{ |varid| id2var(varid) }
|
230
|
+
else
|
231
|
+
raise TypeError, "names is not an array" if ! names.is_a?(Array)
|
232
|
+
vars = names.collect{|name| var(name)}
|
233
|
+
raise ArgumentError, "One or more variables do not exist" if vars.include?(nil)
|
234
|
+
end
|
235
|
+
vars
|
236
|
+
end
|
237
|
+
|
238
|
+
def dim_names
|
239
|
+
num_dim=ndims()
|
240
|
+
names=[]
|
241
|
+
for dimid in 0..num_dim-1
|
242
|
+
obj_Dim=id2dim(dimid)
|
243
|
+
names=names+[obj_Dim.name]
|
244
|
+
end
|
245
|
+
return names
|
246
|
+
end
|
247
|
+
|
248
|
+
def var_names
|
249
|
+
num_var=nvars()
|
250
|
+
names=[]
|
251
|
+
for varid in 0..num_var-1
|
252
|
+
obj_Var=id2var(varid)
|
253
|
+
names=names+[obj_Var.name]
|
254
|
+
end
|
255
|
+
return names
|
256
|
+
end
|
257
|
+
|
258
|
+
def att_names
|
259
|
+
num_att=natts()
|
260
|
+
names=[]
|
261
|
+
for attnum in 0..num_att-1
|
262
|
+
obj_Att=id2att(attnum)
|
263
|
+
names=names+[obj_Att.name]
|
264
|
+
end
|
265
|
+
return names
|
266
|
+
end
|
267
|
+
|
268
|
+
def inspect
|
269
|
+
"NetCDF:"+path
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
class NetCDFVar
|
275
|
+
|
276
|
+
class << NetCDFVar
|
277
|
+
def new(file,varname,mode="r",share=false)
|
278
|
+
if(file.is_a?(String))
|
279
|
+
file = NetCDF.open(file,mode,share)
|
280
|
+
elsif(!file.is_a?(NetCDF))
|
281
|
+
raise TypeError, "1st arg must be a NetCDF (file object) or a String (path)"
|
282
|
+
end
|
283
|
+
file.var(varname)
|
284
|
+
end
|
285
|
+
|
286
|
+
alias open new
|
287
|
+
end
|
288
|
+
|
289
|
+
alias :rank :ndims
|
290
|
+
|
291
|
+
def each_att
|
292
|
+
num_att=natts()
|
293
|
+
for attnum in 0..num_att-1
|
294
|
+
obj_Att=id2att(attnum)
|
295
|
+
yield(obj_Att)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def dim_names
|
300
|
+
ary = Array.new()
|
301
|
+
dims.each{|dim| ary.push(dim.name)}
|
302
|
+
ary
|
303
|
+
end
|
304
|
+
|
305
|
+
def att_names
|
306
|
+
num_att=natts()
|
307
|
+
names=[]
|
308
|
+
for attnum in 0..num_att-1
|
309
|
+
obj_Att=id2att(attnum)
|
310
|
+
names=names+[obj_Att.name]
|
311
|
+
end
|
312
|
+
return names
|
313
|
+
end
|
314
|
+
|
315
|
+
def put_att(attname,val,atttype=nil)
|
316
|
+
put_attraw(attname,val,atttype)
|
317
|
+
end
|
318
|
+
|
319
|
+
def shape_ul0
|
320
|
+
sh = []
|
321
|
+
dims.each{|d|
|
322
|
+
if d.unlimited? then
|
323
|
+
sh.push(0)
|
324
|
+
else
|
325
|
+
sh.push(d.length)
|
326
|
+
end
|
327
|
+
}
|
328
|
+
sh
|
329
|
+
end
|
330
|
+
|
331
|
+
def shape_current
|
332
|
+
sh = []
|
333
|
+
dims.each{|d|
|
334
|
+
sh.push(d.length)
|
335
|
+
}
|
336
|
+
sh
|
337
|
+
end
|
338
|
+
|
339
|
+
# The put and get methods in the NetCDFVar class
|
340
|
+
|
341
|
+
def pack(na)
|
342
|
+
sf = att('scale_factor')
|
343
|
+
ao = att('add_offset')
|
344
|
+
if ( sf == nil && ao == nil ) then
|
345
|
+
na
|
346
|
+
else
|
347
|
+
na = NArray.to_na(na) if na.is_a?(Array)
|
348
|
+
if sf
|
349
|
+
csf = sf.get
|
350
|
+
raise NetcdfError,"scale_factor is not a numeric" if csf.is_a?(String)
|
351
|
+
raise NetcdfError, "scale_factor is not unique" if csf.length != 1
|
352
|
+
raise NetcdfError, "zero scale_factor" if csf[0] == 0
|
353
|
+
else
|
354
|
+
csf = nil
|
355
|
+
end
|
356
|
+
if ao
|
357
|
+
cao = ao.get
|
358
|
+
raise NetcdfError, "add_offset is not a numeric" if cao.is_a?(String)
|
359
|
+
raise NetcdfError, "add_offset is not unique" if cao.length != 1
|
360
|
+
else
|
361
|
+
cao = nil
|
362
|
+
end
|
363
|
+
if csf and cao
|
364
|
+
packed = (na - cao) / csf
|
365
|
+
elsif csf
|
366
|
+
packed = na / csf
|
367
|
+
elsif cao
|
368
|
+
packed = na - cao
|
369
|
+
end
|
370
|
+
if self.typecode <= NArray::LINT
|
371
|
+
packed = packed.round
|
372
|
+
end
|
373
|
+
packed
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def scaled_put(var,hash=nil)
|
378
|
+
simple_put( pack(var), hash)
|
379
|
+
end
|
380
|
+
|
381
|
+
@@unpack_type = nil
|
382
|
+
class << NetCDFVar
|
383
|
+
def unpack_type
|
384
|
+
@@unpack_type
|
385
|
+
end
|
386
|
+
def unpack_type=(na_type)
|
387
|
+
if [NArray::BYTE, NArray::SINT, NArray::INT,
|
388
|
+
NArray::SFLOAT, NArray::FLOAT, nil].include?(na_type)
|
389
|
+
@@unpack_type = na_type
|
390
|
+
else
|
391
|
+
raise ArgumentError, "Arg must be one of NArray::BYTE, NArray::SINT, NArray::INT, NArray::SFLOAT, NArray::FLOAT"
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
|
397
|
+
def unpack(na)
|
398
|
+
sf = att('scale_factor')
|
399
|
+
ao = att('add_offset')
|
400
|
+
if ( sf == nil && ao == nil ) then
|
401
|
+
na
|
402
|
+
else
|
403
|
+
if sf
|
404
|
+
csf = sf.get
|
405
|
+
raise NetcdfError,"scale_factor is not a numeric" if csf.is_a?(String)
|
406
|
+
raise NetcdfError, "scale_factor is not unique" if csf.length != 1
|
407
|
+
raise NetcdfError, "zero scale_factor" if csf[0] == 0
|
408
|
+
else
|
409
|
+
csf =nil
|
410
|
+
end
|
411
|
+
if ao
|
412
|
+
cao = ao.get
|
413
|
+
raise NetcdfError, "add_offset is not a numeric" if cao.is_a?(String)
|
414
|
+
raise NetcdfError, "add_offset is not unique" if cao.length != 1
|
415
|
+
else
|
416
|
+
cao = nil
|
417
|
+
end
|
418
|
+
if csf and cao
|
419
|
+
una = na * csf + cao # csf & cao are NArray -> coerced to their types
|
420
|
+
elsif csf
|
421
|
+
una = na * csf
|
422
|
+
elsif cao
|
423
|
+
una = na + cao
|
424
|
+
end
|
425
|
+
una = una.to_type(@@unpack_type) if @@unpack_type
|
426
|
+
una
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def scaled_get(hash=nil)
|
431
|
+
unpack( simple_get(hash) )
|
432
|
+
end
|
433
|
+
|
434
|
+
def simple_put(var,hash=nil)
|
435
|
+
if hash==nil
|
436
|
+
if self.vartype == "char"
|
437
|
+
put_var_char(var)
|
438
|
+
elsif self.vartype == "byte"
|
439
|
+
put_var_byte(var)
|
440
|
+
elsif self.vartype == "sint"
|
441
|
+
put_var_sint(var)
|
442
|
+
elsif self.vartype == "int"
|
443
|
+
put_var_int(var)
|
444
|
+
elsif self.vartype == "sfloat"
|
445
|
+
put_var_sfloat(var)
|
446
|
+
elsif self.vartype == "float"
|
447
|
+
put_var_float(var)
|
448
|
+
else
|
449
|
+
raise NetcdfError,"variable type isn't supported in netCDF"
|
450
|
+
end
|
451
|
+
elsif hash.key?("index")==true
|
452
|
+
if self.vartype == "char"
|
453
|
+
put_var1_char(var,hash["index"])
|
454
|
+
elsif self.vartype=="byte"
|
455
|
+
put_var1_byte(var,hash["index"])
|
456
|
+
elsif self.vartype=="sint"
|
457
|
+
put_var1_sint(var,hash["index"])
|
458
|
+
elsif self.vartype == "int"
|
459
|
+
put_var1_int(var,hash["index"])
|
460
|
+
elsif self.vartype == "sfloat"
|
461
|
+
put_var1_sfloat(var,hash["index"])
|
462
|
+
elsif self.vartype == "float"
|
463
|
+
put_var1_float(var,hash["index"])
|
464
|
+
else
|
465
|
+
raise NetcdfError,"variable type isn't supported in netCDF"
|
466
|
+
end
|
467
|
+
elsif hash.key?("start")==true
|
468
|
+
if hash.key?("end")==false && hash.key?("stride")==false
|
469
|
+
if self.vartype == "char"
|
470
|
+
put_vars_char(var,hash["start"],nil,nil)
|
471
|
+
elsif self.vartype=="byte"
|
472
|
+
put_vars_byte(var,hash["start"],nil,nil)
|
473
|
+
elsif self.vartype=="sint"
|
474
|
+
put_vars_sint(var,hash["start"],nil,nil)
|
475
|
+
elsif self.vartype=="int"
|
476
|
+
put_vars_int(var,hash["start"],nil,nil)
|
477
|
+
elsif self.vartype=="sfloat"
|
478
|
+
put_vars_sfloat(var,hash["start"],nil,nil)
|
479
|
+
elsif self.vartype=="float"
|
480
|
+
put_vars_float(var,hash["start"],nil,nil)
|
481
|
+
else
|
482
|
+
raise NetcdfError, "variable type isn't supported in netCDF"
|
483
|
+
end
|
484
|
+
elsif hash.key?("end")==true && hash.key?("stride") == false
|
485
|
+
if self.vartype == "char"
|
486
|
+
put_vars_char(var,hash["start"],hash["end"],nil)
|
487
|
+
elsif self.vartype=="byte"
|
488
|
+
put_vars_byte(var,hash["start"],hash["end"],nil)
|
489
|
+
elsif self.vartype=="sint"
|
490
|
+
put_vars_sint(var,hash["start"],hash["end"],nil)
|
491
|
+
elsif self.vartype=="int"
|
492
|
+
put_vars_int(var,hash["start"],hash["end"],nil)
|
493
|
+
elsif self.vartype == "sfloat"
|
494
|
+
put_vars_sfloat(var,hash["start"],hash["end"],nil)
|
495
|
+
elsif self.vartype =="float"
|
496
|
+
put_vars_float(var,hash["start"],hash["end"],nil)
|
497
|
+
else
|
498
|
+
raise NetcdfError, "variable type isn't supported in netCDF"
|
499
|
+
end
|
500
|
+
elsif hash.key?("end")==false && hash.key?("stride")==true
|
501
|
+
if self.vartype == "char"
|
502
|
+
put_vars_char(var,hash["start"],nil,hash["stride"])
|
503
|
+
elsif self.vartype=="byte"
|
504
|
+
put_vars_byte(var,hash["start"],nil,hash["stride"])
|
505
|
+
elsif self.vartype=="sint"
|
506
|
+
put_vars_sint(var,hash["start"],nil,hash["stride"])
|
507
|
+
elsif self.vartype=="int"
|
508
|
+
put_vars_int(var,hash["start"],nil,hash["stride"])
|
509
|
+
elsif self.vartype=="sfloat"
|
510
|
+
put_vars_sfloat(var,hash["start"],nil,hash["stride"])
|
511
|
+
elsif self.vartype=="float"
|
512
|
+
put_vars_float(var,hash["start"],nil,hash["stride"])
|
513
|
+
else
|
514
|
+
raise NetcdfError, "variable type isn't supported in netCDF"
|
515
|
+
end
|
516
|
+
else hash.key?("end")==true && hash.key?("stride")==true
|
517
|
+
if self.vartype == "char"
|
518
|
+
put_vars_char(var,hash["start"],hash["end"],hash["stride"])
|
519
|
+
elsif self.vartype=="byte"
|
520
|
+
put_vars_byte(var,hash["start"],hash["end"],hash["stride"])
|
521
|
+
elsif self.vartype=="sint"
|
522
|
+
put_vars_sint(var,hash["start"],hash["end"],hash["stride"])
|
523
|
+
elsif self.vartype=="int"
|
524
|
+
put_vars_int(var,hash["start"],hash["end"],hash["stride"])
|
525
|
+
elsif self.vartype=="sfloat"
|
526
|
+
put_vars_sfloat(var,hash["start"],hash["end"],hash["stride"])
|
527
|
+
elsif self.vartype=="float"
|
528
|
+
put_vars_float(var,hash["start"],hash["end"],hash["stride"])
|
529
|
+
else
|
530
|
+
raise NetcdfError, "variable type isn't supported in netCDF"
|
531
|
+
end
|
532
|
+
end
|
533
|
+
else
|
534
|
+
raise ArgumentError,"{'start'}=>[ARRAY] or {'index'}=>[ARRAY] is needed"
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
alias put simple_put
|
539
|
+
|
540
|
+
def simple_get(hash=nil)
|
541
|
+
t_var = self.vartype
|
542
|
+
if hash == nil
|
543
|
+
if t_var == "char"
|
544
|
+
get_var_char
|
545
|
+
elsif t_var == "byte"
|
546
|
+
get_var_byte
|
547
|
+
elsif t_var == "sint"
|
548
|
+
get_var_sint
|
549
|
+
elsif t_var == "int"
|
550
|
+
get_var_int
|
551
|
+
elsif t_var == "sfloat"
|
552
|
+
get_var_sfloat
|
553
|
+
elsif t_var == "float"
|
554
|
+
get_var_float
|
555
|
+
else
|
556
|
+
raise NetcdfError, "variable type #{t_var} isn't supported in netCDF"
|
557
|
+
end
|
558
|
+
elsif hash.key?("index")==true
|
559
|
+
ind = hash["index"]
|
560
|
+
if t_var == "char"
|
561
|
+
get_var1_char(ind)
|
562
|
+
elsif t_var == "byte"
|
563
|
+
get_var1_byte(ind)
|
564
|
+
elsif t_var == "sint"
|
565
|
+
get_var1_sint(ind)
|
566
|
+
elsif t_var == "int"
|
567
|
+
get_var1_int(ind)
|
568
|
+
elsif t_var == "sfloat"
|
569
|
+
get_var1_sfloat(ind)
|
570
|
+
elsif t_var == "float"
|
571
|
+
get_var1_float(ind)
|
572
|
+
else
|
573
|
+
raise NetcdfError,"variable type #{t_var} isn't supported in netCDF"
|
574
|
+
end
|
575
|
+
elsif hash.key?("start")==true
|
576
|
+
h_sta = hash["start"]
|
577
|
+
h_end = hash["end"] # can be nill
|
578
|
+
h_str = hash["stride"] # can be nill
|
579
|
+
if NetCDF.nc4? && h_str && ((xstr=h_str[0]) != 1)
|
580
|
+
# Tentative treatment for the very slow netcdf-4 reading with step.
|
581
|
+
# Reading with step is generally slow with NetCDF 4, but it is
|
582
|
+
# particularly so for the first dimension.
|
583
|
+
# Ref: http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2013/msg00311.html
|
584
|
+
h_str[0] = 1
|
585
|
+
nc4remedy = true
|
586
|
+
else
|
587
|
+
nc4remedy = false
|
588
|
+
end
|
589
|
+
if t_var == "char"
|
590
|
+
v = get_vars_char(h_sta,h_end,h_str)
|
591
|
+
elsif t_var == "byte"
|
592
|
+
v = get_vars_byte(h_sta,h_end,h_str)
|
593
|
+
elsif t_var == "sint"
|
594
|
+
v = get_vars_sint(h_sta,h_end,h_str)
|
595
|
+
elsif t_var == "int"
|
596
|
+
v = get_vars_int(h_sta,h_end,h_str)
|
597
|
+
elsif t_var == "sfloat"
|
598
|
+
v = get_vars_sfloat(h_sta,h_end,h_str)
|
599
|
+
elsif t_var == "float"
|
600
|
+
v = get_vars_float(h_sta,h_end,h_str)
|
601
|
+
else
|
602
|
+
raise NetcdfError, "variable type #{t_var} isn't supported in netCDF"
|
603
|
+
end
|
604
|
+
if nc4remedy
|
605
|
+
idx = []
|
606
|
+
(0...v.shape[0]).step(xstr){|k| idx.push(k)}
|
607
|
+
v = v[idx,false]
|
608
|
+
end
|
609
|
+
v
|
610
|
+
else
|
611
|
+
raise ArgumentError,"{'start'}=>{ARRAY} or {'index'}=>{ARRAY} is needed"
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
alias get simple_get
|
616
|
+
|
617
|
+
def __rubber_expansion( args )
|
618
|
+
if (id = args.index(false)) # substitution into id
|
619
|
+
# false is incuded
|
620
|
+
alen = args.length
|
621
|
+
if args.rindex(false) != id
|
622
|
+
raise ArguemntError,"only one rubber dimension is permitted"
|
623
|
+
elsif alen > rank+1
|
624
|
+
raise ArgumentError, "too many args"
|
625
|
+
end
|
626
|
+
ar = ( id!=0 ? args[0..id-1] : [] )
|
627
|
+
args = ar + [true]*(rank-alen+1) + args[id+1..-1]
|
628
|
+
elsif args.length == 0 # to support empty [], []=
|
629
|
+
args = [true]*rank
|
630
|
+
end
|
631
|
+
args
|
632
|
+
end
|
633
|
+
private :__rubber_expansion
|
634
|
+
|
635
|
+
def [](*a)
|
636
|
+
if a.length == 0
|
637
|
+
return self.get
|
638
|
+
end
|
639
|
+
a = __rubber_expansion(a)
|
640
|
+
first = Array.new
|
641
|
+
last = Array.new
|
642
|
+
stride = Array.new
|
643
|
+
set_stride = false
|
644
|
+
a.each{|i|
|
645
|
+
if(i.is_a?(Integer))
|
646
|
+
first.push(i)
|
647
|
+
last.push(i)
|
648
|
+
stride.push(1)
|
649
|
+
elsif(i.is_a?(Range))
|
650
|
+
first.push(i.first)
|
651
|
+
last.push(i.exclude_end? ? i.last-1 : i.last)
|
652
|
+
stride.push(1)
|
653
|
+
elsif(i.is_a?(Hash))
|
654
|
+
r = (i.to_a[0])[0]
|
655
|
+
s = (i.to_a[0])[1]
|
656
|
+
if ( !( r.is_a?(Range) ) || ! ( s.is_a?(Integer) ) )
|
657
|
+
raise TypeError, "Hash argument must be {a_Range, step}"
|
658
|
+
end
|
659
|
+
first.push(r.first)
|
660
|
+
last.push(r.exclude_end? ? r.last-1 : r.last)
|
661
|
+
stride.push(s)
|
662
|
+
set_stride = true
|
663
|
+
elsif(i.is_a?(TrueClass))
|
664
|
+
first.push(0)
|
665
|
+
last.push(-1)
|
666
|
+
stride.push(1)
|
667
|
+
elsif( i.is_a?(Array) || i.is_a?(NArray))
|
668
|
+
a_new = a.dup
|
669
|
+
at = a.index(i)
|
670
|
+
i = NArray.to_na(i) if i.is_a?(Array)
|
671
|
+
for n in 0..i.length-1
|
672
|
+
a_new[at] = i[n]..i[n]
|
673
|
+
na_tmp = self[*a_new]
|
674
|
+
if n==0 then
|
675
|
+
k = at
|
676
|
+
if at > 0
|
677
|
+
a[0..at-1].each{|x| if x.is_a?(Integer) then k -= 1 end}
|
678
|
+
end
|
679
|
+
shape_tmp = na_tmp.shape
|
680
|
+
shape_tmp[k] = i.length
|
681
|
+
na = na_tmp.class.new(na_tmp.typecode,*shape_tmp)
|
682
|
+
index_tmp = Array.new(shape_tmp.length,true)
|
683
|
+
end
|
684
|
+
index_tmp[k] = n..n
|
685
|
+
na[*index_tmp] = na_tmp
|
686
|
+
end
|
687
|
+
return na
|
688
|
+
else
|
689
|
+
raise TypeError, "argument must be Integer, Range, Hash, TrueClass, Array, or NArray"
|
690
|
+
end
|
691
|
+
}
|
692
|
+
|
693
|
+
if(set_stride)
|
694
|
+
na = self.get({"start"=>first, "end"=>last, "stride"=>stride})
|
695
|
+
else
|
696
|
+
na = self.get({"start"=>first, "end"=>last})
|
697
|
+
end
|
698
|
+
shape = na.shape
|
699
|
+
(a.length-1).downto(0){ |i|
|
700
|
+
shape.delete_at(i) if a[i].is_a?(Integer)
|
701
|
+
}
|
702
|
+
na.reshape!( *shape )
|
703
|
+
na
|
704
|
+
end
|
705
|
+
|
706
|
+
def []=(*a)
|
707
|
+
val = a.pop
|
708
|
+
a = __rubber_expansion(a)
|
709
|
+
first = Array.new
|
710
|
+
last = Array.new
|
711
|
+
stride = Array.new
|
712
|
+
set_stride = false
|
713
|
+
a.each{|i|
|
714
|
+
if(i.is_a?(Integer))
|
715
|
+
first.push(i)
|
716
|
+
last.push(i)
|
717
|
+
stride.push(1)
|
718
|
+
elsif(i.is_a?(Range))
|
719
|
+
first.push(i.first)
|
720
|
+
last.push(i.exclude_end? ? i.last-1 : i.last)
|
721
|
+
stride.push(1)
|
722
|
+
elsif(i.is_a?(Hash))
|
723
|
+
r = (i.to_a[0])[0]
|
724
|
+
s = (i.to_a[0])[1]
|
725
|
+
if ( !( r.is_a?(Range) ) || ! ( s.is_a?(Integer) ) )
|
726
|
+
raise ArgumentError, "Hash argument must be {first..last, step}"
|
727
|
+
end
|
728
|
+
first.push(r.first)
|
729
|
+
last.push(r.exclude_end? ? r.last-1 : r.last)
|
730
|
+
stride.push(s)
|
731
|
+
set_stride = true
|
732
|
+
elsif(i.is_a?(TrueClass))
|
733
|
+
first.push(0)
|
734
|
+
last.push(-1)
|
735
|
+
stride.push(1)
|
736
|
+
elsif(i.is_a?(Array) || i.is_a?(NArray))
|
737
|
+
a_new = a.dup
|
738
|
+
at = a.index(i)
|
739
|
+
i = NArray.to_na(i) if i.is_a?(Array)
|
740
|
+
val = NArray.to_na(val) if val.is_a?(Array)
|
741
|
+
rank_of_subset = a.dup.delete_if{|v| v.is_a?(Integer)}.length
|
742
|
+
if val.rank != rank_of_subset
|
743
|
+
raise "rank of the rhs (#{val.rank}) is not equal to the rank "+
|
744
|
+
"of the subset specified by #{a.inspect} (#{rank_of_subset})"
|
745
|
+
end
|
746
|
+
k = at
|
747
|
+
a[0..at-1].each{|x| if x.is_a?(Integer) then k -= 1 end}
|
748
|
+
if i.length != val.shape[k]
|
749
|
+
raise "length of the #{k+1}-th dim of rhs is incorrect "+
|
750
|
+
"(#{i.length} for #{val.shape[k]})"
|
751
|
+
end
|
752
|
+
index_tmp = Array.new(val.rank,true) if !val.is_a?(Numeric) #==>Array-like
|
753
|
+
for n in 0..i.length-1
|
754
|
+
a_new[at] = i[n]..i[n]
|
755
|
+
if !val.is_a?(Numeric) then
|
756
|
+
index_tmp[k] = n..n
|
757
|
+
self[*a_new] = val[*index_tmp]
|
758
|
+
else
|
759
|
+
self[*a_new] = val
|
760
|
+
end
|
761
|
+
end
|
762
|
+
return self
|
763
|
+
else
|
764
|
+
raise TypeError, "argument must be Integer, Range, Hash, TrueClass, Array, or NArray"
|
765
|
+
end
|
766
|
+
}
|
767
|
+
|
768
|
+
if(set_stride)
|
769
|
+
self.put(val, {"start"=>first, "end"=>last, "stride"=>stride})
|
770
|
+
else
|
771
|
+
self.put(val, {"start"=>first, "end"=>last})
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
def inspect
|
776
|
+
'NetCDFVar:'+file.path+'?var='+name
|
777
|
+
end
|
778
|
+
|
779
|
+
end
|
780
|
+
|
781
|
+
class NetCDFAtt
|
782
|
+
|
783
|
+
def put(val,atttype=nil)
|
784
|
+
putraw(val,atttype)
|
785
|
+
end
|
786
|
+
|
787
|
+
def inspect
|
788
|
+
'NetCDFAtt:'+name
|
789
|
+
end
|
790
|
+
end
|
791
|
+
|
792
|
+
class NetCDFDim
|
793
|
+
def inspect
|
794
|
+
'NetCDFDim:'+name
|
795
|
+
end
|
796
|
+
|
797
|
+
def length_ul0
|
798
|
+
if unlimited?
|
799
|
+
0
|
800
|
+
else
|
801
|
+
length
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
end
|
806
|
+
end
|