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