Class: NumRu::VArray

Inherits:
Object
  • Object
show all
Defined in:
lib/numru/gphys/varray.rb,
lib/numru/gphys/interpolate.rb,
lib/numru/gphys/gphys_dim_op.rb,
ext/numru/gphys/dim_op.c

Overview

class Units

Constant Summary collapse

Math_funcs_nondim =
["exp","log","log10","log2","sin","cos","tan",
"sinh","cosh","tanh","asinh","acosh",
"atanh","csc","sec","cot","csch","sech","coth",
"acsch","asech","acoth"]
Math_funcs_radian =
["asin","acos","atan","atan2","acsc","asec","acot"]
Math_funcs =
Math_funcs_nondim + Math_funcs_radian + ["sqrt"]
Binary_operators_Uop =
["*","/","**", ".mul!",".div!"]
Binary_operators_Uconv =
["+","-",".add!",".sbt!"]
Binary_operators_Unone =
["%",".mod!",".imag="]
Binary_operators =
Binary_operators_Uop + 
Binary_operators_Uconv +
Binary_operators_Unone
Binary_operatorsL_comp =
[">",">=","<","<=",
".eq",".ne",".gt",".ge",".lt",".le"]
Binary_operatorsL_other =
["&","|","^",".and",".or",".xor",".not"]
Binary_operatorsL =
Binary_operatorsL_comp +
Binary_operatorsL_other
Unary_operators =
["-@","~"]
NArray_type1_methods =

type1 methods: returns a VArray with the same shape type2 methods: returns the result directly

["sort", "sort_index", 
"floor","ceil","round","to_f","to_i","to_type","abs",
"real","im","imag","angle","arg","conj","conjugate","cumsum",
"indgen","random"]
NArray_type2_methods1 =
["all?","any?","none?","where","where2",
"to_a", "to_string"]
NArray_type2_methods2 =
["rank", "shape", "total","length"]
NArray_type2_methods3 =
["typecode"]
NArray_type3_methods =
["mean","sum","stddev","min","max","median"]
NArray_type2_methods =

remaining: “transpose”

Array.new.push(*NArray_type2_methods1).
push(*NArray_type2_methods2).
push(*NArray_type2_methods3)
@@default_missval =

NC_FILL_DOUBLE/FLOAT ~15*2^119

9.9692099683868690e+36

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(narray = nil, attr = nil, name = nil) ⇒ VArray

< basic parts to be redefined in subclasses > ###



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/numru/gphys/varray.rb', line 315

def initialize(narray=nil, attr=nil, name=nil)
	 # initialize with an actual array --- initialization by subset
	 # mapping is made with VArray.new.initialize_mapping(...)
	 @name = ( name || "noname" )
	 @mapping = nil
	 @varray = nil
	 @ary = __check_ary_class(narray)
	 case attr
	 when Attribute
	    @attr = attr
	 when VArray
	    vary = attr
	    @attr = vary.attr_copy
	 when Hash
	    @attr = NumRu::Attribute.new
	    attr.each{|key,val| @attr[key]=val}
	 when nil
	    @attr = NumRu::Attribute.new
	 else
	   raise TypeError, "#{attr.class} is unsupported for the 2nd arg"
	 end
end

Class Method Details

.new2(ntype, shape, attr = nil, name = nil) ⇒ Object



349
350
351
352
# File 'lib/numru/gphys/varray.rb', line 349

def VArray.new2(ntype, shape, attr=nil, name=nil)
	 ary = NArray.new(ntype, *shape)
	 VArray.new(ary, attr, name)
end

Instance Method Details

#+@Object



917
918
919
# File 'lib/numru/gphys/varray.rb', line 917

def +@
	self
end

#[](*slicer) ⇒ Object



573
574
575
576
577
# File 'lib/numru/gphys/varray.rb', line 573

def [](*slicer)
	 slicer = __rubber_expansion( slicer )
	 mapping = SubsetMapping.new(self.shape_current, slicer)
	 VArray.new.initialize_mapping(mapping, self)
end

#[]=(*args) ⇒ Object



579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
# File 'lib/numru/gphys/varray.rb', line 579

def []=(*args)
	 val = args.pop
	 slicer = args
	 slicer = __rubber_expansion( slicer )
	 if val.is_a?(VArray)
	    val = val.val
	 else
	    val = __check_ary_class2(val)
	 end
	 if @mapping
	    sl= @mapping.composite(SubsetMapping.new(self.shape,slicer)).slicer
	    @varray[*sl]=val
	 else
	    @ary[*slicer]=val
	 end
	 val
end

#att_namesObject



516
517
518
# File 'lib/numru/gphys/varray.rb', line 516

def att_names
	attr.keys
end

#attr_copy(to = nil) ⇒ Object



512
513
514
# File 'lib/numru/gphys/varray.rb', line 512

def attr_copy(to=nil)
	attr.copy(to)
end

#axis_cyclic?Boolean

Returns:

  • (Boolean)


628
629
630
# File 'lib/numru/gphys/varray.rb', line 628

def axis_cyclic?
  axis_modulo != nil
end

#axis_cyclic_extendible?Boolean

Returns:

  • (Boolean)


658
659
660
661
662
663
664
665
666
667
668
# File 'lib/numru/gphys/varray.rb', line 658

def axis_cyclic_extendible?
  modulo = axis_modulo
  return false if !modulo
  v = val
  width = (v[-1] - v[0]).abs
	dx = width / (length-1)
	eps = 1e-4
	modulo = modulo.abs
	extendible = ( ((width+dx) - modulo).abs < eps*modulo )
  return extendible
end

#axis_draw_positiveObject



613
614
615
616
617
618
619
620
621
622
623
624
625
626
# File 'lib/numru/gphys/varray.rb', line 613

def axis_draw_positive
	# Default setting is taken from a widely used netcdf convention.
	# You can override it in a sub-class or using convention specific 
	# mixins.
	positive = attr['positive']
	case positive
	when /up/i
	  true
	when /down/i
	  false
	else
	  nil    # not defined, or if not 'up' or 'down'
	end  
end

#axis_moduloObject



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
# File 'lib/numru/gphys/varray.rb', line 632

def axis_modulo
	# Default setting is taken from a widely used netcdf convention.
	# You can override it in a sub-class or using convention specific 
	# mixins.
	if attval=attr['modulo']
	  if attval.is_a?(String)
	    attval.to_f
	  else
	    attval[0]
	  end
	elsif /degrees?_east/ =~ attr['units']
    360.0     # special treatment: a common convention for the earth
  elsif (tp = attr['topology']) and (/circular/i =~ tp)
    un = Units[attr['units']]
    if un == Units['degrees']
	    360.0
    elsif un == Units['radian']
      2*Math::PI
    else
      nil    # cannot guess --> nil
    end
  else
    nil      # not defined --> nil
	end
end

#bin_mean(dim, len, nminvalid = 1) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/numru/gphys/gphys_dim_op.rb', line 152

def bin_mean(dim, len, nminvalid=1)
  vi = self.val
  if vi.is_a?(NArrayMiss)
    vi, missval = nam2na_missval(vi)
    vo = c_bin_mean(vi,dim,len,missval,nminvalid)  # defined in dim_op.c
    vo = NArrayMiss.to_nam(vo, vo.ne(missval) )
  else
    vo = c_bin_mean(vi,dim,len)  # defined in dim_op.c
  end
  VArray.new( vo, self, self.name )  # Inherit name & attrs 
end

#bin_sum(dim, len, nminvalid = 1) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
# File 'lib/numru/gphys/gphys_dim_op.rb', line 164

def bin_sum(dim, len, nminvalid=1)
  vi = self.val
  if vi.is_a?(NArrayMiss)
    vi, missval = nam2na_missval(vi)
    vo = c_bin_sum(vi,dim,len,missval,nminvalid)  # defined in dim_op.c
    vo = NArrayMiss.to_nam(vo, vo.ne(missval) )
  else
    vo = c_bin_sum(vi,dim,len)  # defined in dim_op.c
  end
  VArray.new( vo, self, self.name )  # Inherit name & attrs 
end

#coerce(other) ⇒ Object

ToDo: implement units handling ToDo: coerce



675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
# File 'lib/numru/gphys/varray.rb', line 675

def coerce(other)
	case other
	when UNumeric
    oattr = self.attr_copy
	  oattr['units'] = other.units.to_s
	  na_other, = NArray.new(self.typecode, 1).coerce(other.val)   # scalar
	  c_other = VArray.new(na_other, oattr, self.name)
	else
	  case other
	  when Numeric, Array, NArrayMiss
	    c_other = UNumeric::Num2Coerce.new( other )
	  else
	    raise "Cannot coerse #{other.class}"
	  end
	end
	[c_other, self]
end

#convert_units(to) ⇒ Object



544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
# File 'lib/numru/gphys/varray.rb', line 544

def convert_units(to)
	if ! to.is_a?(Units)
	  to = Units.new(to)
	end
	myunits = self.units
	if myunits != to
	  if calendar = self.get_att("calendar")
	    date0 = UNumeric.new(0,myunits).to_datetime
	    un0 = UNumeric.from_date(date0,to,calendar)
	    offset = un0.to_f
	    gp = self + offset
	  else
	    gp = myunits.convert2(self, to)
	  end
	  gp.units = to
	  gp
	else
	  self   # returns self (no duplication)
	end
end

#copy(to = nil) ⇒ Object

< basic parts invariant in subclasses > ###



457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'lib/numru/gphys/varray.rb', line 457

def copy(to=nil)
	 attr = self.attr_copy( (to ? to.attr : to) )
	 val = self.val
	 if self.class==VArray && !self.mapped? && (to==nil || to.class==VArray)
	    val = val.dup
	 end
	 if to
	    to.val = val
	    to
	 else
	    VArray.new(val, attr, self.name)
	 end
end

#del_att(name) ⇒ Object



526
527
528
# File 'lib/numru/gphys/varray.rb', line 526

def del_att(name)
	attr.delete(name)
end

#fileObject



447
448
449
450
451
452
453
# File 'lib/numru/gphys/varray.rb', line 447

def file
	if @mapping
	  @varray.file
	else
	  return nil
	end
end

#get_att(name) ⇒ Object



519
520
521
# File 'lib/numru/gphys/varray.rb', line 519

def get_att(name)
	attr[name]
end

#inspectObject



341
342
343
344
345
346
347
# File 'lib/numru/gphys/varray.rb', line 341

def inspect
	 if !@mapping
      "<'#{name}' #{ntype}#{shape.inspect} val=[#{(0...(4<length ? 4 : length)).collect do |i| @ary[i].to_s+',' end}#{'...' if 4<length}]>"
	 else
	    "<'#{name}' shape=#{shape.inspect}  subset of a #{@varray.class}>"
	 end
end

#long_nameObject



565
566
567
# File 'lib/numru/gphys/varray.rb', line 565

def long_name
	attr['long_name']
end

#long_name=(nm) ⇒ Object



569
570
571
# File 'lib/numru/gphys/varray.rb', line 569

def long_name=(nm)
	attr['long_name'] = nm
end

#mapped?Boolean

def reshape( *shape )

# reshape method that returns a new entire copy (deep one).
# ToDo :: prepare another reshape method that does not make the
# entire copy (you could use NArray.refer, but be careful not 
# to make it public, because it's easily misused)
newobj = self.copy
newobj.ary.reshape!( *shape )
newobj

end

Returns:

  • (Boolean)


481
482
483
# File 'lib/numru/gphys/varray.rb', line 481

def mapped?
	 @mapping ? true : false
end

#marshal_dumpObject

< marshal dump/load >



976
977
978
# File 'lib/numru/gphys/varray.rb', line 976

def marshal_dump
  [@name, @mapping, @varray, @ary, @attr]
end

#marshal_load(ary) ⇒ Object



980
981
982
# File 'lib/numru/gphys/varray.rb', line 980

def marshal_load(ary)
  @name, @mapping, @varray, @ary, @attr = *ary
end

#nameObject



597
598
599
600
601
602
603
# File 'lib/numru/gphys/varray.rb', line 597

def name
	 if @mapping
	    @varray.name
	 else
	    @name.dup
	 end
end

#name=(nm) ⇒ Object

Raises:

  • (ArgumentError)


421
422
423
424
425
426
427
428
429
# File 'lib/numru/gphys/varray.rb', line 421

def name=(nm)
	 raise ArgumentError, "name should be a String" if ! nm.is_a?(String)
	 if @mapping
	    @varray.name = nm
	 else
	    @name = nm
	 end
	 nm
end

#ntypeObject



417
418
419
# File 'lib/numru/gphys/varray.rb', line 417

def ntype
  __ntype(typecode)
end

#rename(nm) ⇒ Object



434
435
436
# File 'lib/numru/gphys/varray.rb', line 434

def rename(nm)
	self.dup.rename!(nm)
end

#rename!(nm) ⇒ Object



430
431
432
433
# File 'lib/numru/gphys/varray.rb', line 430

def rename!(nm)
	 self.name=nm
	 self
end

#replace_val(narray) ⇒ Object



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/numru/gphys/varray.rb', line 398

def replace_val(narray)
	narray = __check_ary_class(narray)
	if self.class != VArray
	  raise "replace_val to #{self.class} is disabled. Use val= instead"
	end
	if narray.shape != shape 
	  raise "shape of the argument (#{narray.shape.inspect}) !="+
	    " self.shape (#{shape.inspect})"
	end
	@ary = narray
	if @mapping
	  # to non subset
	  @name = @varray.name
	  @attr = @varray.attr_copy
	  @mapping = @varray = nil
	end
	self
end

#reshape(*shape) ⇒ Object



609
610
611
# File 'lib/numru/gphys/varray.rb', line 609

def reshape(*shape)
	VArray.new( val.reshape(*shape), attr_copy, name )
end

#reshape!(*shape) ⇒ Object



438
439
440
441
442
443
444
445
# File 'lib/numru/gphys/varray.rb', line 438

def reshape!( *shape )
	if @mapping
	  raise "Cannot reshape an VArray mapped to another. Use copy first to make it independent"
	else
	  @ary.reshape!( *shape )
	end
	self
end

#set_att(name, val) ⇒ Object Also known as: put_att



522
523
524
525
# File 'lib/numru/gphys/varray.rb', line 522

def set_att(name, val)
	attr[name]=val
	self
end

#sqrtObject



768
769
770
771
772
# File 'lib/numru/gphys/varray.rb', line 768

def sqrt
	va = VArray.new( Misc::EMath.sqrt(self.val), self.attr_copy, self.name )
	va.units = units**Rational(1,2)
	va
end

#to_g1DObject



784
785
786
787
788
# File 'lib/numru/gphys/interpolate.rb', line 784

def to_g1D
  ax = Axis.new().set_pos(self)
  grid = Grid.new(ax)
  GPhys.new(grid,self)
end

#transpose(*dims) ⇒ Object



605
606
607
# File 'lib/numru/gphys/varray.rb', line 605

def transpose(*dims)
	VArray.new( val.transpose(*dims), attr_copy, name )
end

#unitsObject



531
532
533
534
535
536
537
# File 'lib/numru/gphys/varray.rb', line 531

def units
	str_units = attr['units']
	if !str_units || str_units==''
	  str_units = '1'              # represents non-dimension
	end
	Units.new( str_units )
end

#units=(units) ⇒ Object



539
540
541
542
# File 'lib/numru/gphys/varray.rb', line 539

def units=(units)
	attr['units'] = units.to_s
	units
end

#valObject



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
# File 'lib/numru/gphys/varray.rb', line 354

def val
	if @mapping
	  ary = @varray.ary
	  slicer = @mapping.slicer
	  if ary.is_a?(NArray) || ary.is_a?(NArrayMiss)
	    # interpret Hash slicers for NArray/NArrayMiss 
	    #   -- this part would not be needed if NArray supported it.
	    new_slicer = Array.new
	    for idx in 0...slicer.length
 sl = slicer[idx]
 if sl.is_a?(Hash)
		range, step = sl.to_a[0]
		dim_len = ary.shape[idx]
		first = range.first
		first += dim_len if first<0
		last = range.last
		last += dim_len if last<0
		if first<0 || first>=dim_len || last<0 || last>=dim_len || step==0
		  raise "slicer #{slicer.inspect} for dim #{idx} is invalid (dim_len=#{dim_len})"
		end
		step = -step if ( (last-first)*step < 0 )
		length = (last-first) / step + 1
		new_slicer[idx] = first + step * NArray.int(length).indgen!
 else
		new_slicer[idx] = sl
 end
	    end
	    slicer = new_slicer
	  end
	  ary[*slicer]
	else
	  @ary.dup
	end
end

#val=(narray) ⇒ Object



389
390
391
392
393
394
395
396
# File 'lib/numru/gphys/varray.rb', line 389

def val=(narray)
	 if @mapping
	    @varray.ary[*@mapping.slicer] = __check_ary_class2(narray)
	 else
	    @ary[] = __check_ary_class2(narray)
	 end
	 narray
end