ruby-netcdf 0.7.2 → 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 -5
- data/.gitignore +0 -1
- data/ChangeLog +456 -0
- data/LICENSE.txt +32 -57
- data/ext/numru/netcdfraw.c +287 -321
- data/lib/numru/netcdf/version.rb +1 -1
- data/lib/numru/netcdf.rb +634 -638
- data/ruby-netcdf-bigmem.gemspec +1 -0
- data/ruby-netcdf.gemspec +1 -0
- 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 +18 -4
data/lib/numru/netcdf.rb
CHANGED
@@ -36,7 +36,7 @@ module NumRu
|
|
36
36
|
raise("This method is available only for NetCDF >= 4") unless @@nc4
|
37
37
|
case cmode
|
38
38
|
when 0, nil, NC_CLASSIC_MODEL, /^CLASSIC$/i, NC_FORMAT_CLASSIC
|
39
|
-
|
39
|
+
# classic netcdf ver 3 fmt
|
40
40
|
@@cr_format = 0
|
41
41
|
when NC_64BIT_OFFSET, /^64BIT_OFFSET$/i, NC_FORMAT_64BIT
|
42
42
|
@@cr_format = NC_64BIT_OFFSET
|
@@ -65,229 +65,225 @@ module NumRu
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def NetCDF.open(filename,mode="r",share=false)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
end
|
100
|
-
|
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
101
|
class << NetCDF
|
102
102
|
alias new open
|
103
103
|
end
|
104
|
-
|
105
|
-
|
104
|
+
|
105
|
+
|
106
106
|
def NetCDF.create(filename,noclobber=false,share=false)
|
107
107
|
case(noclobber)
|
108
108
|
when false
|
109
|
-
|
109
|
+
noclobber=NC_CLOBBER
|
110
110
|
when true
|
111
|
-
|
111
|
+
noclobber=NC_NOCLOBBER
|
112
112
|
else
|
113
|
-
|
113
|
+
raise NetcdfError,"noclobber (2nd argument) must be true or false"
|
114
114
|
end
|
115
115
|
case(share)
|
116
116
|
when false
|
117
|
-
|
117
|
+
share=0
|
118
118
|
when true
|
119
|
-
|
119
|
+
share=NC_SHARE
|
120
120
|
else
|
121
|
-
|
121
|
+
raise NetcdfError,"share (3rd argument) must be true or false"
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
cmode=noclobber | share | @@cr_format
|
125
125
|
nc_create(filename,cmode)
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
class << NetCDF
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
def NetCDF.create_tmp(tmpdir=ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'.',
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
161
|
-
n += 1
|
162
|
-
end
|
163
|
-
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
|
164
160
|
end
|
165
161
|
|
166
162
|
|
167
163
|
def put_att(attname,val,atttype=nil)
|
168
|
-
|
164
|
+
put_attraw(attname,val,atttype)
|
169
165
|
end
|
170
|
-
|
166
|
+
|
171
167
|
def def_var_with_dim(name, vartype, shape_ul0, dimnames)
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
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)
|
193
189
|
end
|
194
190
|
|
195
191
|
# Iterators:
|
196
192
|
def each_dim
|
197
|
-
num_dim=ndims()
|
193
|
+
num_dim=ndims()
|
198
194
|
for dimid in 0..num_dim-1
|
199
|
-
|
200
|
-
|
195
|
+
obj_Dim=id2dim(dimid)
|
196
|
+
yield(obj_Dim)
|
201
197
|
end
|
202
198
|
end
|
203
|
-
|
199
|
+
|
204
200
|
def each_var
|
205
201
|
num_var=nvars()
|
206
202
|
for varid in 0..num_var-1
|
207
|
-
|
208
|
-
|
203
|
+
obj_Var=id2var(varid)
|
204
|
+
yield(obj_Var)
|
209
205
|
end
|
210
206
|
end
|
211
|
-
|
207
|
+
|
212
208
|
def each_att
|
213
209
|
num_att=natts()
|
214
210
|
for attnum in 0..num_att-1
|
215
|
-
|
216
|
-
|
211
|
+
obj_Att=id2att(attnum)
|
212
|
+
yield(obj_Att)
|
217
213
|
end
|
218
214
|
end
|
219
|
-
|
215
|
+
|
220
216
|
def dims( names=nil ) # return all if names==nil
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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
|
229
225
|
end
|
230
226
|
|
231
227
|
def vars( names=nil ) # return all if names==nil
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
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
|
240
236
|
end
|
241
237
|
|
242
238
|
def dim_names
|
243
239
|
num_dim=ndims()
|
244
240
|
names=[]
|
245
241
|
for dimid in 0..num_dim-1
|
246
|
-
|
247
|
-
|
242
|
+
obj_Dim=id2dim(dimid)
|
243
|
+
names=names+[obj_Dim.name]
|
248
244
|
end
|
249
245
|
return names
|
250
|
-
end
|
251
|
-
|
246
|
+
end
|
247
|
+
|
252
248
|
def var_names
|
253
249
|
num_var=nvars()
|
254
250
|
names=[]
|
255
251
|
for varid in 0..num_var-1
|
256
|
-
|
257
|
-
|
252
|
+
obj_Var=id2var(varid)
|
253
|
+
names=names+[obj_Var.name]
|
258
254
|
end
|
259
255
|
return names
|
260
256
|
end
|
261
|
-
|
257
|
+
|
262
258
|
def att_names
|
263
259
|
num_att=natts()
|
264
260
|
names=[]
|
265
261
|
for attnum in 0..num_att-1
|
266
|
-
|
267
|
-
|
262
|
+
obj_Att=id2att(attnum)
|
263
|
+
names=names+[obj_Att.name]
|
268
264
|
end
|
269
265
|
return names
|
270
266
|
end
|
271
|
-
|
267
|
+
|
272
268
|
def inspect
|
273
269
|
"NetCDF:"+path
|
274
270
|
end
|
275
|
-
|
271
|
+
|
276
272
|
end
|
277
|
-
|
273
|
+
|
278
274
|
class NetCDFVar
|
279
|
-
|
275
|
+
|
280
276
|
class << NetCDFVar
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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
|
289
285
|
|
290
|
-
|
286
|
+
alias open new
|
291
287
|
end
|
292
288
|
|
293
289
|
alias :rank :ndims
|
@@ -295,516 +291,516 @@ module NumRu
|
|
295
291
|
def each_att
|
296
292
|
num_att=natts()
|
297
293
|
for attnum in 0..num_att-1
|
298
|
-
|
299
|
-
|
294
|
+
obj_Att=id2att(attnum)
|
295
|
+
yield(obj_Att)
|
300
296
|
end
|
301
297
|
end
|
302
|
-
|
298
|
+
|
303
299
|
def dim_names
|
304
300
|
ary = Array.new()
|
305
301
|
dims.each{|dim| ary.push(dim.name)}
|
306
302
|
ary
|
307
303
|
end
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
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)
|
320
316
|
put_attraw(attname,val,atttype)
|
321
|
-
|
317
|
+
end
|
322
318
|
|
323
|
-
|
319
|
+
def shape_ul0
|
324
320
|
sh = []
|
325
321
|
dims.each{|d|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
322
|
+
if d.unlimited? then
|
323
|
+
sh.push(0)
|
324
|
+
else
|
325
|
+
sh.push(d.length)
|
326
|
+
end
|
331
327
|
}
|
332
328
|
sh
|
333
|
-
|
334
|
-
|
335
|
-
|
329
|
+
end
|
330
|
+
|
331
|
+
def shape_current
|
336
332
|
sh = []
|
337
333
|
dims.each{|d|
|
338
|
-
|
334
|
+
sh.push(d.length)
|
339
335
|
}
|
340
336
|
sh
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
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)
|
705
701
|
}
|
706
702
|
na.reshape!( *shape )
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
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)
|
788
784
|
putraw(val,atttype)
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
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
|
802
798
|
if unlimited?
|
803
|
-
|
799
|
+
0
|
804
800
|
else
|
805
|
-
|
801
|
+
length
|
806
802
|
end
|
807
|
-
|
803
|
+
end
|
808
804
|
|
809
|
-
|
805
|
+
end
|
810
806
|
end
|