ruby-netcdf 0.7.1 → 0.8.0

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