Class: NumRu::VArray

Inherits:
Object
  • Object
show all
Defined in:
lib/numru/gphys/varray.rb

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)

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



932
933
934
# File 'lib/numru/gphys/varray.rb', line 932

def +@
	self
end

#[](*slicer) ⇒ Object



566
567
568
569
570
# File 'lib/numru/gphys/varray.rb', line 566

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

#[]=(*args) ⇒ Object



572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
# File 'lib/numru/gphys/varray.rb', line 572

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)


621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# File 'lib/numru/gphys/varray.rb', line 621

def axis_cyclic?
	# Default setting is taken from a widely used netcdf convention.
	# You can override it in a sub-class or using convention specific 
	# mixins.
	topology = attr['topology']
	case topology
	when /circular/i
	  true
	when nil     # 'topology' not defined
	  if /degrees?_east/ =~ attr['units']
	    true     # special treatment a common convention for the earth
	  else
	    nil      # not defined --> nil
	  end
	else
	  false
	end  
end

#axis_cyclic_extendible?Boolean

Returns:

  • (Boolean)


666
667
668
669
670
671
672
673
674
675
676
# File 'lib/numru/gphys/varray.rb', line 666

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



606
607
608
609
610
611
612
613
614
615
616
617
618
619
# File 'lib/numru/gphys/varray.rb', line 606

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



640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
# File 'lib/numru/gphys/varray.rb', line 640

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

#coerce(other) ⇒ Object

ToDo: implement units handling ToDo: coerce



683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
# File 'lib/numru/gphys/varray.rb', line 683

def coerce(other)
	oattr = self.attr_copy
	case other
	when UNumeric
	  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
	  oattr['units'] = self.get_att('units')     # Assume the same units
	  case other
	  when Numeric
	    na_other, = NArray.new(self.typecode, 1).coerce(other)   # scalar
	    c_other = VArray.new(na_other, oattr, self.name)
	  when Array
	    na = NArray.to_na(other)
	    c_other = VArray.new(na, oattr, self.name)
	  when NArray, NArrayMiss
	    c_other = VArray.new(other, oattr, self.name)
	  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
# 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
	  gp = myunits.convert2(self, to)
	  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



558
559
560
# File 'lib/numru/gphys/varray.rb', line 558

def long_name
	attr['long_name']
end

#long_name=(nm) ⇒ Object



562
563
564
# File 'lib/numru/gphys/varray.rb', line 562

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 >



991
992
993
# File 'lib/numru/gphys/varray.rb', line 991

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

#marshal_load(ary) ⇒ Object



995
996
997
# File 'lib/numru/gphys/varray.rb', line 995

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

#nameObject



590
591
592
593
594
595
596
# File 'lib/numru/gphys/varray.rb', line 590

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



602
603
604
# File 'lib/numru/gphys/varray.rb', line 602

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



783
784
785
786
787
# File 'lib/numru/gphys/varray.rb', line 783

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

#transpose(*dims) ⇒ Object



598
599
600
# File 'lib/numru/gphys/varray.rb', line 598

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