lib/numru/gphys/varraycomposite.rb in gphys-1.2.2.1 vs lib/numru/gphys/varraycomposite.rb in gphys-1.4.3
- old
+ new
@@ -75,47 +75,64 @@
raise ArgumentError, "argument must be a NArray of VArray (or nil)"
end
nvas = varrays.shape
vrank = nvas.length
- rank=0
varrays.each{|va|
- if va.is_a?(VArray)
+ if !va.nil?
@first_vary = va
- @attr = @first_vary.attr
+ @attr = @first_vary.attr_copy
@name = @first_vary.name
- @rank = va.rank
+ @crank = va.rank # rank of the component VArrays
break
end
}
- if vrank > @rank
- raise ArgumentError, "rank of varrays > rank of the VArray"
- elsif vrank < @rank
- (@rank - vrank).times{
- varrays = varrays.newdim(vrank)
- nvas.push(1)
- }
- vrank = @rank
+ if vrank > @crank
+ @rank = vrank #=> @rank > @crank
+ else
+ @rank = @crank
+ if vrank < @crank
+ (@crank - vrank).times{
+ varrays = varrays.newdim(vrank)
+ nvas.push(1)
+ }
+ vrank = @crank # rank of varrays is increased to @crank (==@rank)
+ end
end
+ un0 = varrays[0].units
+ for i in 1...varrays.length
+ va = varrays[i]
+ varrays[i] = va.convert_units(un0) if va && va.units != un0
+ end
@bound_idx = Array.new # will be Array of Array
for dim in 0...vrank
@bound_idx[dim] = [0] # the frst element is always 0
for i in 0...nvas[dim]
idx = [true]*dim + [i..i,false]
set=false
len=0
varrays[*idx].each{|va|
if !set && va
- if !va.is_a?(VArray)
- raise ArgumentError,"Not a VArray: #{va.inspect}"
- end
- len = va.shape_current[dim]
+ ### commented out for the duck typing:
+ #if !va.is_a?(VArray)
+ # raise ArgumentError,"Not a VArray: #{va.inspect}"
+ #end
+ if dim < @crank
+ len = va.shape_current[dim]
+ else
+ len = 1
+ end
@bound_idx[dim][i+1] = @bound_idx[dim][i] + len
set=true
elsif va
- if va.shape_current[dim] != len
+ if dim < @crank
+ lc = va.shape_current[dim]
+ else
+ lc = 1
+ end
+ if lc != len
raise ArgumentError,"Non-uniformity in the #{i}th element"+
" of the #{dim}th dimension (#{va.shape_current[dim]} for #{len})"
end
end
}
@@ -163,23 +180,32 @@
def val
val = nil
loop_multi_dim_index( @varrays.shape ){|index|
vidx = Array.new
for d in 0...@rank
- vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1)
+ if d < @crank
+ vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1)
+ else
+ vidx[d] = @bound_idx[d][index[d]]
+ end
end
- v = @varrays[*index].val
+ units = @attr["units"]
+ if units
+ v = @varrays[*index].convert_units(units).val
+ else
+ v = @varrays[*index].val
+ end
if !val
if NArray===v
val = NArray.new(v.typecode,*@shape)
elsif NArrayMiss===v
val = NArrayMiss.new(v.typecode,*@shape)
else
raise TypeError, "Unexpected type #{v.class}"
end
end
- val[*vidx] = @varrays[*index].val
+ val[*vidx] = v
}
val
end
def val=(narray)
@@ -188,11 +214,15 @@
sub = narray
else
__check_ary_class(narray)
vidx = Array.new
for d in 0...@rank
- vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1)
+ if d < @crank
+ vidx[d] = (@bound_idx[d][index[d]])..(@bound_idx[d][index[d]+1]-1)
+ else
+ vidx[d] = @bound_idx[d][index[d]]
+ end
end
sub=narray[*vidx]
end
@varrays[*index].val = sub
}
@@ -284,16 +314,16 @@
imask = Array.new
isub = Array.new
idx.each_with_index{ |ix, dim|
size = @bound_idx[dim][-1]
imask[dim] = Array.new
- isub[dim] = Array.new
+ isub[dim] = Array.new if dim < @crank
for j in 0...(@bound_idx[dim].length)
match, isb = _imatch( size, ix, @bound_idx[dim][j..j+1] )
if match
imask[dim].push(j)
- isub[dim].push(isb)
+ isub[dim].push(isb) if dim < @crank
end
end
}
varrays = @varrays[ *imask ]
loop_multi_dim_index( varrays.shape ){ |index|
@@ -332,10 +362,15 @@
lst = index.exclude_end? ? index.last-1 : index.last
lst += size if lst < 0
stp = 1
else # Hash
range, stp = index.to_a[0]
+ if stp<=0
+ raise(ArgumentError,"Currently only positive step is supported")
+ # development note: current handling of fst and lst assumes a
+ # positive step
+ end
range = 0..-1 if range==true
fst = range.first
fst += size if fst < 0
lst = range.last
lst += size if lst < 0
@@ -347,15 +382,32 @@
a = ( (fst >= first) ? fst-first : (fst - first).modulo(stp) )
b = ( (lst <= last) ? lst-first : last-first )
if stp==1
return [true, a..b ]
else
- return [true, {(a..b) => stp} ]
+ len = last-first+1
+ if a<len
+ return [true, {(a..b) => stp} ]
+ else
+ return [false, nil]
+ end
end
else
return [false, nil]
end
+ when Array
+ match = false
+ isb = []
+ index.each{ |idx|
+ idx += size if idx < 0
+ if first <= idx && idx <= last
+ match = true
+ isb.push(idx-first)
+ end
+ }
+ isb = nil if isb == []
+ return [match, isb]
else
raise "Unsupported type for indexing: #{index.class}"
end
end
@@ -410,6 +462,37 @@
p va01.name
vac.set_att('long_name', 'test data')
p vac.get_att('long_name')
p va01.get_att('long_name')
p vac.typecode,vac.ntype
+
+ puts "testing rank extension.."
+ va0 = VArray.new( NArray.float(3,2).indgen!, {"units"=>"m/s"}, 'V' )
+ va1 = VArray.new( NArray.float(3,2).indgen!+100, {"units"=>"m/s"}, 'V' )
+ va2 = VArray.new( NArray.float(3,2).indgen!+200, {"units"=>"m/s"}, 'V' )
+ va3 = VArray.new( NArray.float(3,2).indgen!+300, {"units"=>"m/s"}, 'V' )
+ varrays = NArray.to_na([ [[va0]], [[va1]], [[va2]], [[va3]] ])
+ vac = VArrayComposite.new(varrays)
+ p vac, vac.val
+ if vac[1,1,1].val == 104.0
+ puts "test OK"
+ else
+ raise "test failed"
+ end
+
+ v = vac[0..1,0,{1..-1=>2}].val
+ ans = NArray.to_na( [ [100.0,101.0], [300.0, 301.0] ] )
+ if v==ans
+ puts "test OK"
+ else
+ raise "test failed"
+ end
+
+ vac[-1,true,1..2] = -999.0
+ if vac[-1,true,1..2].val.to_a.flatten.uniq == [-999.0 ]
+ puts "test OK"
+ else
+ raise "test failed"
+ end
+ #vac.val = NArray.float(3,2,4).random!
+ #p vac.val
end