lib/numru/gphys/gphys_netcdf_io.rb in gphys-1.2.2.1 vs lib/numru/gphys/gphys_netcdf_io.rb in gphys-1.4.3
- old
+ new
@@ -523,11 +523,11 @@
def __files2varray( files, varname, dim=nil )
if files.is_a?(NetCDF)
# Single file. Returns a VArrayNetCDF. dim is ignored.
file = files
var = file.var( varname )
- raise "variable '#{varname}' not found in #{file}" if !var
+ raise "variable '#{varname}' not found in #{file.inspect}" if !var
VArrayNetCDF.new( var )
elsif files.is_a?(NArray)
# Suppose that files is a NArray of NetCDF. Returns a VArrayCompsite.
if dim.is_a?(Integer) && dim>=0 && dim<files.rank
files = files[ *([0]*dim+[true]+[0]*(files.rank-dim-1)) ]
@@ -564,13 +564,34 @@
raise TypeError, "argument files: not a NetCDF, String, NArray, Array, or Regexp"
end
[files, ncvar0]
end
+ #--
+ # re-arrange the array of files and check some inconsistencies
+ #
+ # e.g.)
+ # files = NArray[ file0.nc, file1.nc, file2.nc, file3.nc ]
+ # The files have a variable, u(lat,lev,time),
+ # which is tiled to four parts as the followings:
+ # | lat | lev | time |
+ # file0.nc | -90...0 | 1000...500 | 0..1 |
+ # file1.nc | 0..90 | 1000...500 | 0..1 |
+ # file2.nc | -90...0 | 500..100 | 0..1 |
+ # file3.nc | 0..90 | 500..100 | 0..1 |
+ #
+ # Then the output is
+ # NArray[ [ [ file0.nc, file1.nc ],
+ # [ file2.nc, file3.nc ] ] ].
+ #
+ # The order of the elements of the input array is arbitrary.
+ #
def __files_dim_matching( files, varname )
# files: NArray of NetCDF
+ return files if files.length == 1
+
# < read the first file and check its rank >
file0 = files[0]
ncvar0 = file0.var(varname)
if files.rank > ncvar0.rank
@@ -579,47 +600,64 @@
convention = NetCDF_Conventions.find( ncvar0.file )
axposnames = convention::coord_var_names(ncvar0)
#< find correspoding dimensions >
- j2i = Array.new
+ rank = axposnames.length
+ cvals = Array.new(rank){ Array.new }
+ sign = Array.new(rank)
+ units = Array.new(rank)
+ files.each do |file|
+ axposnames.each_with_index do |axposname, i|
+ nvax = file.var(axposname)
+ raise "No coordinate variable: #{axposname}' not found" if !nvax
+ axpos = VArrayNetCDF.new( nvax )
+ axv0 = axpos.val[0]
+ if units[i]
+ un = axpos.units
+ axv0 = un.convert2(axv0,units[i]) unless un == units[i]
+ else # the first file
+ units[i] = axpos.units
+ sign[i] = (axpos.val[-1] >= axv0 ? 1 : -1)
+ end
+ cvals[i].push axv0
+ end
+ end
+ # For the above example,
+ # cvals = [ [ -90, 0, -90, 0 ],
+ # [ 1000, 1000, 500, 500 ],
+ # [ 0, 0, 0, 0 ] ]
+ # sign = [ 1, -1, 1 ]
- for ifl in 0...files.rank
- for jdt in 0...ncvar0.rank
- axpos_last = nil
- for kfl in 0...files.shape[ifl]
- nvax = files[*([0]*ifl+[kfl]+[0]*(files.rank-ifl-1))].var(axposnames[jdt])
- raise "No coordinate variable: #{axposname}' not found" if !nvax
- axpos = VArrayNetCDF.new( nvax )
- if kfl > 0
- if axpos.length != axpos_last.length
- # not equal ==> this is the dimension looking for
- j2i[jdt] = ifl
- break
- else
- axv0 = axpos.val[0]
- axv_last0 = axpos_last.val[0]
- if axv0 != axv_last0
- # not equal ==> this is the dimension looking for
- j2i[jdt] = ifl
- break
- end
- end
- end
- axpos_last = axpos
- end
- break if j2i.include?(ifl)
- end
- if files.shape[ifl]>1 && !j2i.include?(ifl)
- raise "No dimension correpodence found for #{ifl}th dim"
- end
- end
-
- for d in files.rank...ncvar0.rank
- j2i[ (j2i.index(nil) || files.rank) ] = d
- files.newdim!(d)
- end
- files = files.transpose(*j2i)
+ axs = Array.new(rank)
+ cvals.each_with_index do |cval, i|
+ axs[i] = cval.uniq
+ axs[i].sort!{|a,b| (a <=> b)*sign[i] }
+ end
+ # For the above example,
+ # axs = [ [ -90, 0 ], [ 1000, 500 ], [ 0 ] ]
+ files_new = NArray.object( *axs.map{|ax| ax.length} )
+ # For the above example,
+ # shape of the files_new is [2, 2, 1]
+ files.length.times do |n|
+ file = files[n]
+ idx = Array.new(rank)
+ rank.times do |i|
+ axv0 = cvals[i][n]
+ idx[i] = axs[i].index(axv0)
+ end
+ # For the above example,
+ # idx =
+ # [ 0, 0, 0 ] for n==0
+ # [ 1, 0, 0 ] for n==1
+ # [ 0, 1, 0 ] for n==2
+ # [ 1, 1, 0 ] for n==3
+ files_new[*idx] = file
+ end
+ if files_new.eq(nil).count_true > 0
+ raise "No dimension correspondence found"
+ end
+ files = files_new
files
end
def __to_na_of_netcdf( files )