netcdf-nmatrix 0.8.0

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