Class: Array

Inherits:
Object show all
Defined in:
lib/multiarray.rb,
lib/multiarray/operations.rb

Overview

The Array class is extended with a few methods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.gauss_blur_filter(sigma, max_error = 1.0 / 0x100) ⇒ Array

Compute Gauss blur filter

Compute a filter for approximating a Gaussian blur. The size of the filter is determined by the given error bound.

Parameters:

  • sigma (Float)

    Spread of blur filter.

  • max_error (Float) (defaults to: 1.0 / 0x100)

    Upper bound for filter error.

Returns:

  • (Array)

    An array with the filter elements.



615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
# File 'lib/multiarray.rb', line 615

def gauss_blur_filter( sigma, max_error = 1.0 / 0x100 )
  # Error function
  #
  # @param [Float] x Function argument
  # @param [Float] sigma Function parameter
  #
  # @private
  def erf(x, sigma)
    0.5 * Math.erf( x / ( Math.sqrt( 2.0 ) * sigma.abs ) )
  end
  raise 'Sigma must be greater than zero.' if sigma <= 0
  # Integral of Gauss-bell from -0.5 to +0.5.
  integral = erf( +0.5, sigma ) - erf( -0.5, sigma )
  retVal = [ integral ]
  while 1.0 - integral > max_error
    # Integral of Gauss-bell from -size2 to +size2.
    size2 = 0.5 * ( retVal.size + 2 )
    nIntegral = erf( +size2, sigma ) - erf( -size2, sigma )
    value = 0.5 * ( nIntegral - integral )
    retVal.unshift value
    retVal.push value
    integral = nIntegral
  end
  # Normalise result.
  retVal.collect { |element| element / integral }
end

.gauss_gradient_filter(sigma, max_error = 1.0 / 0x100) ⇒ Array

Compute Gauss gradient filter

Compute a filter for approximating a Gaussian gradient. The size of the filter is determined by the given error bound.

Parameters:

  • sigma (Float)

    Spread of blur filter.

  • max_error (Float) (defaults to: 1.0 / 0x100)

    Upper bound for filter error.

Returns:

  • (Array)

    An array with the filter elements.



651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
# File 'lib/multiarray.rb', line 651

def gauss_gradient_filter( sigma, max_error = 1.0 / 0x100 )
  # Gaussian function
  #
  # @param [Float] x Function argument
  # @param [Float] sigma Function parameter
  #
  # @private
  def gauss(x, sigma)
    1.0 / ( Math.sqrt( 2.0 * Math::PI ) * sigma.abs ) *
      Math.exp( -x**2 / ( 2.0 * sigma**2 ) )
  end
  raise 'Sigma must be greater than zero.' if sigma <= 0
  # Integral of Gauss-gradient from -0.5 to +0.5.
  retVal = [ gauss( +0.5, sigma ) - gauss( -0.5, sigma ) ]
  # Absolute integral of Gauss-gradient from 0.5 to infinity.
  integral = gauss( 0.5, sigma )
  sumX = 0
  while 2.0 * integral > max_error
    size2 = 0.5 * ( retVal.size + 2 )
    nIntegral = gauss( size2, sigma )
    value = integral - nIntegral
    retVal.unshift +value
    retVal.push -value
    sumX += value * ( retVal.size - 1 )
    integral = nIntegral
  end
  retVal.collect { |element| element / sumX }
end

Instance Method Details

#collect_with_index(&action) ⇒ Array<Object>

Element-wise operation based on element and its index

Same as Array#collect but with index.

Parameters:

  • &action

    Closure accepting an element and an index.

Returns:



689
690
691
# File 'lib/multiarray.rb', line 689

def collect_with_index( &action )
  zip( ( 0 ... size ).to_a ).collect &action
end

#erf(x, sigma) ⇒ Object

Error function

Parameters:

  • x (Float)

    Function argument

  • sigma (Float)

    Function parameter



622
623
624
# File 'lib/multiarray.rb', line 622

def erf(x, sigma)
  0.5 * Math.erf( x / ( Math.sqrt( 2.0 ) * sigma.abs ) )
end

#gauss(x, sigma) ⇒ Object

Gaussian function

Parameters:

  • x (Float)

    Function argument

  • sigma (Float)

    Function parameter



658
659
660
661
# File 'lib/multiarray.rb', line 658

def gauss(x, sigma)
  1.0 / ( Math.sqrt( 2.0 * Math::PI ) * sigma.abs ) *
    Math.exp( -x**2 / ( 2.0 * sigma**2 ) )
end

#histogram(*ret_shape, options = {}) ⇒ Node

Compute histogram of this array

Parameters:

  • ret_shape (Array<Integer>)

    Dimensions of resulting histogram.

Options Hash (options):

  • :weight (Node) — default: Hornetseye::UINT(1)

    Weights for computing the histogram.

  • :safe (Boolean) — default: true

    Do a boundary check before creating the histogram.

Returns:

  • (Node)

    The histogram.



968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
# File 'lib/multiarray/operations.rb', line 968

def histogram( *ret_shape )
  options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
  options = { :weight => Hornetseye::UINT. new( 1 ), :safe => true }.merge options
  unless options[:weight].matched?
    options[:weight] =
      Hornetseye::Node.match( options[ :weight ] ).maxint.new options[ :weight ]
  end
  weight = options[ :weight ]
  if options[ :safe ]
    if size != ret_shape.size
      raise "Number of arrays for histogram (#{size}) differs from number of " +
            "dimensions of histogram (#{ret_shape.size})"
    end
    source_type = inject { |a,b| a.dimension > b.dimension ? a : b }
    source_type.check_shape *self
    source_type.check_shape options[ :weight ]
    for i in 0 ... size
      range = self[ i ].range 0 ... ret_shape[ i ]
      if range.begin < 0
        raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
              "(but was #{range.begin})"
      end
      if range.end >= ret_shape[ i ]
        raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
              "(but was #{range.end})"
      end
    end
  end
  left = Hornetseye::MultiArray(weight.typecode, ret_shape.size).new *ret_shape
  left[] = 0
  block = Hornetseye::Histogram.new left, weight, *self
  if block.compilable?
    Hornetseye::GCCFunction.run block
  else
    block.demand
  end
  left
end

#lut(table, options = {}) ⇒ Node

Perform element-wise lookup

Parameters:

  • table (Node)

    The lookup table (LUT).

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :safe (Boolean) — default: true

    Do a boundary check before creating the element-wise lookup.

Returns:

  • (Node)

    The result of the lookup operation.



1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
# File 'lib/multiarray/operations.rb', line 1014

def lut( table, options = {} )
  options = { :safe => true }.merge options
  if options[ :safe ]
    if size > table.dimension
      raise "Number of arrays for lookup (#{size}) is greater than the " +
            "number of dimensions of LUT (#{table.dimension})"
    end
    source_type = inject { |a,b| a.dimension > b.dimension ? a : b }
    source_type.check_shape *self
    for i in 0 ... size
      offset = table.dimension - size
      range = self[ i ].range 0 ... table.shape[ i + offset ]
      if range.begin < 0
        raise "#{i+1}th index must be in 0 ... #{table.shape[i]} " +
              "(but was #{range.begin})"
      end
      if range.end >= table.shape[ i + offset ]
        raise "#{i+1}th index must be in 0 ... " +
              "#{table.shape[ i + offset ]} (but was #{range.end})"
      end
    end
  end
  if all? { |source| source.dimension == 0 and source.variables.empty? }
    result = table
    ( table.dimension - 1 ).downto( 0 ) do |i|
      result = result.element( self[ i ].demand ).demand
    end
    result
  else
    Hornetseye::Lut.new( *( self + [ table ] ) ).force
  end
end

#stripObject



693
694
695
696
697
# File 'lib/multiarray.rb', line 693

def strip
  collect { |arg| arg.strip }.inject [[], [], []] do |retval,s|
    [retval[0] + s[0], retval[1] + s[1], retval[2] + [s[2]]]
  end
end