Class: Runarray::NArray

Inherits:
Array
  • Object
show all
Defined in:
lib/runarray/narray.rb

Constant Summary collapse

TYPECODES =
['float', 'int']
@@zero =
0.0

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ NArray

Returns a new instance of NArray.



51
52
53
54
55
56
57
# File 'lib/runarray/narray.rb', line 51

def initialize(*args)
  if TYPECODES.include?(args[0])
    self.class.build(*args)
  else
    super(*args)
  end
end

Class Method Details

.[](*ar) ⇒ Object



14
15
# File 'lib/runarray/narray.rb', line 14

def [](*args)
end

.build(typecode, *dims) ⇒ Object

Raises:

  • (NotImplementedError)


17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/runarray/narray.rb', line 17

def build(typecode, *dims)
  zero = 
    case typecode
    when 'float' then 0.0
    when 'int' then 0
    end
  raise NotImplementedError, "dims <= 1 right now" if dims.size > 2
  case dims.size
  when  1
    self.new(dims.first, zero)
  end
end

.float(*dims) ⇒ Object



10
11
12
# File 'lib/runarray/narray.rb', line 10

def float(*dims)
  build('float', *dims)
end

.max(first, second) ⇒ Object



32
33
34
35
36
# File 'lib/runarray/narray.rb', line 32

def self.max(first, second)
  if first >= second ; first
  else ; second
  end
end

.min(first, second) ⇒ Object



38
39
40
41
42
# File 'lib/runarray/narray.rb', line 38

def self.min(first, second)
  if first <= second ; first
  else ; second
  end
end

.prep(input) ⇒ Object

Accepts an Array, Vector, or list Returns a new Object Basically just does a to_rep on each element



140
141
142
143
144
145
146
# File 'lib/runarray/narray.rb', line 140

def self.prep(input)
  obj = self.new
  (0...input.size).each do |i|
    obj[i] = obj.to_rep(input[i])
  end
  obj
end

Instance Method Details

#*(other) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/runarray/narray.rb', line 200

def *(other)
  nw = self.class.new
  if other.kind_of?(Runarray::NArray)
    self.each_with_index do |val,i|
      nw << val * other[i]
    end
  else
    self.each do |val|
      nw << val * other
    end 
  end
  nw
end

#**(other) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/runarray/narray.rb', line 186

def **(other)
  nw = self.class.new
  if other.kind_of?(Runarray::NArray)
    self.each_with_index do |val,i|
      nw << (val ** other[i])
    end
  else
    self.each do |val|
      nw << val ** other
    end 
  end
  nw
end

#+(other) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/runarray/narray.rb', line 214

def +(other)
  nw = self.class.new
  if other.kind_of?(Runarray::NArray)
    self.each_with_index do |val,i|
      nw << val + other[i]
    end
  else
    self.each do |val|
      nw << val + other
    end 
  end
  nw
end

#-(other) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/runarray/narray.rb', line 228

def -(other)
  nw = self.class.new
  if other.kind_of?(Runarray::NArray)
    self.each_with_index do |val,i|
      nw << val - other[i]
    end
  else
    self.each do |val|
      nw << val - other
    end 
  end
  nw
end

#/(other) ⇒ Object

def /(other); send(‘/’.to_sym, other) end def (other); send(‘’.to_sym, other) end def -(other); send(‘-’.to_sym, other) end def *(other); send(‘*’.to_sym, other) end



172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/runarray/narray.rb', line 172

def /(other)
  nw = self.class.new
  if other.kind_of?(Runarray::NArray)
    self.each_with_index do |val,i|
      nw << val / other[i]
    end
  else
    self.each do |val|
      nw << val / other
    end 
  end
  nw
end

#_correct_indices(indices) ⇒ Object

given indices that were deleted in sequential order, reconstruct the original indices e.g. ( ‘*’ indicates that the index was deleted in that round )

[ 0][  ][ 2][ 3][  ][*5][ 6][  ][ 8]
  |       |   |         /        / 
[*0][  ][ 2][*3][  ][ 5][  ][ 7][  ]
        /      _____/  _____/            
[  ][ 1][  ][*3][  ][ 5][  ][  ][  ]
      |             /
[  ][*1][  ][  ][*4][  ][  ][  ][  ]
### -> ANSWER: [0,2,3,5,6,8]


585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
# File 'lib/runarray/narray.rb', line 585

def _correct_indices(indices)
  ## need to correct the indices based on what was deleted before
  indices_new = indices.reverse.inject do |final,ind_ar|
    new_final = final.collect do |fi|
      rtn = fi
      ind_ar.each do |ind|
        if ind <= fi
          rtn += 1 
        end
      end
      rtn
    end
    new_final.push(*ind_ar)
    new_final
  end
  indices_new.sort
end

#absObject



242
243
244
245
246
247
248
# File 'lib/runarray/narray.rb', line 242

def abs
  nw = self.class.new
  self.each do |val|
    nw << val.abs
  end
  nw
end

#avgObject

returns a float



267
268
269
# File 'lib/runarray/narray.rb', line 267

def avg
  sum.to_f/self.size
end

#chim(y = nil) ⇒ Object

Class functions: THIS MUST BE FOR FLOAT AND DOUBLE ONLY!!! This is a fairly precise Fortran->C translation of the SLATEC chim code Evaluate the deriv at each x point return 1 if less than 2 data points return 0 if no errors ASSUMES monotonicity of the X data points !!!!! ASSUMES that this->length() >= 2 If length == 1 then derivs is set to 0 If length == 0 then raises an ArgumentError returns a new array of derivatives Assumes that y values are Floats if y is not given, then values are assumed to be evenly spaced.



937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
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
1006
1007
1008
1009
1010
1011
1012
1013
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
1046
# File 'lib/runarray/narray.rb', line 937

def chim(y=nil)
  y = self.class.new((0...(self.size)).to_a) if y.nil?

  #void VecABR::chim(VecABR &x, VecABR &y, VecABR &out_derivs) {
  x = self
  derivs = Runarray::NArray.new(x.size)

  length = x.size
  three = 3.0

  ierr = 0
  lengthLess1 = length - 1

  if length < 2 
    if length == 1
      derivs[0] = 0
      return derivs
    else 
      raise ArgumentError, "trying to chim with 0 data points!"
    end
  end

  h1 = x[1] - x[0]
  del1 = (y[1] - y[0]) / h1
  dsave = del1

  # special case length=2 --use linear interpolation
  if lengthLess1 < 2
    derivs[0] = del1
    derivs[1] = del1
    return derivs
  end 

  # Normal case (length >= 3)

  h2 = x[2] - x[1]
  del2 = (y[2] - y[1]) / h2

  # SET D(1) VIA NON-CENTERED THREE-POINT FORMULA, ADJUSTED TO BE
  #     SHAPE-PRESERVING.

  hsum = h1 + h2
  w1 = (h1 + hsum)/hsum
  w2 = (h1*-1.0)/hsum
  derivs[0] = (w1*del1) + (w2*del2)
  if (( pchst(derivs[0], del1) ) <= 0)
    derivs[0] = @@zero
  elsif ( pchst(del1, del2) < 0 )
    # need to do this check only if monotonicity switches
    dmax = del1 * three
    if (derivs[0].abs > dmax.abs) 
      derivs[0] = dmax
    end 
  end

  (1...lengthLess1).to_a.each do |ind|
    if (ind != 1)
      h1 = h2
      h2 = x[ind+1] - x[ind]
      hsum = h1 + h2
      del1 = del2
      del2 = (y[ind+1] - y[ind])/h2
    end 

    derivs[ind] = @@zero

    pchstval = pchst(del1, del2)

    klass = self.class

    if (pchstval > 0) 
      hsumt3 = hsum+hsum+hsum
      w1 = (hsum + h1)/hsumt3
      w2 = (hsum + h2)/hsumt3
      dmax = klass.max( del1.abs, del2.abs )
      dmin = klass.min( del1.abs, del2.abs )
      drat1 = del1/dmax
      drat2 = del2/dmax
      derivs[ind] = dmin/(w1*drat1 + w2*drat2)
    elsif (pchstval < 0 )
      ierr = ierr + 1
      dsave = del2
      next
    else   # equal to zero
      if (del2 == @@zero) 
        next
      end
      if (pchst(dsave,del2) < 0) 
        ierr = ierr + 1 
      end
      dsave = del2
      next
    end 
  end


  w1 = (h2*-1.0)/hsum
  w2 = (h2 + hsum)/hsum
  derivs[lengthLess1] = (w1*del1) + (w2*del2)
  if ( pchst(derivs[lengthLess1], del2) <= 0 ) 
    derivs[lengthLess1] = @@zero;
  elsif ( pchst(del1, del2) < 0)
    # NEED DO THIS CHECK ONLY IF MONOTONICITY SWITCHES.
    dmax = three*del2
    if (derivs[lengthLess1].abs > dmax.abs) 
      derivs[lengthLess1] = dmax
    end 
  end 
  derivs
end

#clip(min, max, output = nil) ⇒ Object

these are given in inclusive terms output is the array used for placing the data in (expects same size). If nil it will be in-place.



745
746
747
748
749
750
751
752
753
754
# File 'lib/runarray/narray.rb', line 745

def clip(min, max, output=nil)
  output ||= self
  self.each_with_index do |v,i|
    n = v
    n = min if v < min 
    n = max if v > max
    output[i] = n
  end
  output
end

#delete_outliers(deviations, y = nil) ⇒ Object

Returns (x, y) where any data points in cartesion coords(self,y) that are > ‘deviations’ from the least squares regression line are deleted (deviations will be converted to float) In the future this may be for multiple vecs…



629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
# File 'lib/runarray/narray.rb', line 629

def delete_outliers(deviations, y=nil)
  nx = self.class.new
  ny = self.class.new if y
  distribution = 
    if y
      self.residuals_from_least_squares(y)
    else
      self
    end
  mean, std_dev = distribution.sample_stats
  cutoff = deviations.to_f * std_dev
  #puts "CUTOFF: #{cutoff}"
  distribution.each_with_index do |res,i|
    #puts "RES: #{res}"
    unless (res - mean).abs > cutoff
      #puts "ADDING"
      nx << self[i] 
      (ny << y[i]) if y
    end
  end
  if y
    [nx,ny]
  else
    #puts "GIVING BACK"
    nx
  end
end

#delete_outliers_iteratively(deviations, y = nil) ⇒ Object

Returns (x, y) where any data points in cartesion coords(self,y) that are > ‘deviations’ from the least squares regression line are deleted. The least squares line is recalculated and outliers tossed out iteratively until no further points are tossed. In the future this may be for multiple vecs…



527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
# File 'lib/runarray/narray.rb', line 527

def delete_outliers_iteratively(deviations, y=nil)
  x = self
  ln = x.size
  nx = nil
  ny = nil
  loop do
    answ = x.delete_outliers(deviations, y)
    if y
      (nx, ny) = answ
    else
      nx = answ
    end
    if nx.size == ln
      break
    else
      ln = nx.size
      x = nx
      y = ny ## still nil if only x
    end
  end
  if y
    [nx, ny]
  else
    nx
  end
end

#floorObject



250
251
252
253
254
255
256
# File 'lib/runarray/narray.rb', line 250

def floor
  nw = self.class.new
  self.each do |val|
    nw << val.floor
  end
  nw
end

#histogram(*arg) ⇒ Object



127
128
129
# File 'lib/runarray/narray.rb', line 127

def histogram(*arg)
  require 'histogram'
end

#inc_x(yvec, start = 0, endp = 2047, increment = 1.0, baseline = 0.0, behavior = "sum") ⇒ Object

returns (new_x_coords, new_y_coords) of the same type as self Where:

self = the current x coordinates
yvec = the parallel y coords 
start = the initial x point
endp = the final point
increment = the x coordinate increment
baseline = the default value if no values lie in a bin
behavior = response when multiple values fall to the same bin
  sum => sums all values
  avg => avgs the values
  high => takes the value at the highest x coordinate
  max => takes the value of the highest y value [need to finalize]
  maxb => ?? [need to finalize]


289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/runarray/narray.rb', line 289

def inc_x(yvec, start=0, endp=2047, increment=1.0, baseline=0.0, behavior="sum")
  xvec = self


  scale_factor = 1.0/increment
  end_scaled = ((endp * (scale_factor)) + 0.5).to_int 
  start_scaled = ((start* (scale_factor)) + 0.5).to_int 


  # the size of the yvec will be: [start_scaled..end_scaled] = end_scaled - start_scaled + 1
  ## the x values of the incremented vector: 
  xvec_new_size = (end_scaled - start_scaled + 1)
  xvec_new = self.class.new(xvec_new_size)
  # We can't just use the start and endp that are given, because we might
  # have needed to do some rounding on them
  end_unscaled = end_scaled / scale_factor
  start_unscaled = start_scaled / scale_factor
  xval_new = start_unscaled
  xvec_new_size.times do |i|
    xvec_new[i] = start_unscaled
    start_unscaled += increment
  end

  # special case: no data
  if xvec.size == 0
    yvec_new = self.class.new(xvec_new.size, baseline)
    return [xvec_new, yvec_new]
  end

  ## SCALE the mz_scaled vector
  xvec_scaled = xvec.collect do |val|
    (val * scale_factor).round
  end

  ## FIND greatest index
  _max = xvec_scaled.last

  ## DETERMINE maximum value
  max_ind = end_scaled
  if _max > end_scaled; max_ind = _max ## this is because we'll need the room
  else; max_ind = end_scaled
  end

  ## CREATE array to hold mapped values and write in the baseline
  arr = self.class.new(max_ind+1, baseline)
  nobl = self.class.new(max_ind+1, 0)

  case behavior
  when "sum"
    xvec_scaled.each_with_index do |ind,i|
      val = yvec[i]
      arr[ind] = nobl[ind] + val
      nobl[ind] += val
    end
  when "high"  ## FASTEST BEHAVIOR
    xvec_scaled.each_with_index do |ind,i|
      arr[ind] = yvec[i]
    end
  when "avg"
    count = Hash.new {|s,key| s[key] = 0 }
    xvec_scaled.each_with_index do |ind,i|
      val = yvec[i]
      arr[ind] = nobl[ind] + val
      nobl[ind] += val
      count[ind] += 1
    end
    count.each do |k,co|
      if co > 1;  arr[k] /= co end
    end
  when "max" # @TODO: finalize behavior of max and maxb
    xvec_scaled.each_with_index do |ind,i|
      val = yvec[i]
      if val > nobl[ind];  arr[ind] = val; nobl[ind] = val end
    end
  when "maxb"
    xvec_scaled.each_with_index do |ind,i|
      val = yvec[i]
      if val > arr[ind];  arr[ind] = val end
    end
  else 
    warn "Not a valid behavior: #{behavior}, in one_dim\n"
  end

  trimmed = arr[start_scaled..end_scaled]
  if xvec_new.size != trimmed.size
    abort "xvec_new.size(#{xvec_new.size}) != trimmed.size(#{trimmed.size})"
  end
  [xvec_new, trimmed]
end

#indices_equal(val) ⇒ Object

returns an Array of indices where val == member



727
728
729
730
731
732
733
734
735
# File 'lib/runarray/narray.rb', line 727

def indices_equal(val)
  indices = []
  self.each_with_index do |v,i|
    if val == v
      indices << i
    end
  end
  indices
end

#inspectObject



67
68
69
# File 'lib/runarray/narray.rb', line 67

def inspect
  "[ #{self.join(", ")} ]" 
end

#log_space(&block) ⇒ Object

BASIC METHODS:



61
62
63
64
65
# File 'lib/runarray/narray.rb', line 61

def log_space(&block)
  logged = self.map{|v| Math.log(v) }
  new_ar = block.call(logged)
  self.class.new( new_ar.map{|v| Math.exp(v) } )
end

#lowess(y, f = 2.0/3.0, iter = 3) ⇒ Object Also known as: loess

originally taken from a pastebin posting (2009-08-26) which is considered public domain. (en.pastebin.ca/1255734) self is considered the x values. Returns y values at the x values given

Raises:

  • (NotImplementedError)


770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
# File 'lib/runarray/narray.rb', line 770

def lowess(y, f=2.0/3.0, iter=3) 
  x = self
  n = x.size
  r = (f*n).ceil.to_i
  # h = [numpy.sort(numpy.abs(x-x[i]))[r] for i in range(n)]
  (0...n).each { |i| (x-x[i]).abs.sort[r] }
  raise NotImplementedError, "not finished!"

  #w = numpy.clip(numpy.abs(([x]-numpy.transpose([x]))/h),0.0,1.0)
  #w = 1-w*w*w
  #w = w*w*w
  #yest = numpy.zeros(n)
  #delta = numpy.ones(n)
  #for iteration in range(iter):
  #  for i in range(n):
  #    weights = delta * w[:,i]
  #  theta = weights*x
  #  b_top = sum(weights*y)
  #  b_bot = sum(theta*y)
  #  a = sum(weights)
  #  b = sum(theta)
  #  d = sum(theta*x)
  #  yest[i] = (d*b_top-b*b_bot+(a*b_bot-b*b_top)*x[i])/(a*d-b**2)
  #  residuals = y-yest
  #  s = numpy.median(abs(residuals))
  #  delta = numpy.clip(residuals/(6*s),-1,1)
  #  delta = 1-delta*delta
  #  delta = delta*delta
  #  return yest

end

#map(&block) ⇒ Object



75
76
77
# File 'lib/runarray/narray.rb', line 75

def map(&block)
  self.class.new(old_map(&block))
end

#maxObject



682
683
684
685
686
687
688
# File 'lib/runarray/narray.rb', line 682

def max
  mx = self.first
  self.each do |val|
    if val > mx ; mx = val end
  end
  mx
end

#max_indicesObject

returns an array of indices



708
709
710
# File 'lib/runarray/narray.rb', line 708

def max_indices
  indices_equal(self.max)
end

#minObject



674
675
676
677
678
679
680
# File 'lib/runarray/narray.rb', line 674

def min
  mn = self.first
  self.each do |val|
    if val < mn then mn = val end
  end
  mn
end

#min_indicesObject

returns an array of indices



738
739
740
# File 'lib/runarray/narray.rb', line 738

def min_indices
  indices_equal(self.min)
end

#min_maxObject

Returns (min, max)



757
758
759
760
761
762
763
764
765
# File 'lib/runarray/narray.rb', line 757

def min_max
  mn = self.first
  mx = self.first
  self.each do |val|
    if val < mn then mn = val end
    if val > mx then mx = val end
  end
  return mn, mx
end

#moving_avg(pre = 1, post = 1) ⇒ Object

moving average (slow, simple implementation)



465
466
467
468
469
470
471
472
473
474
475
476
# File 'lib/runarray/narray.rb', line 465

def moving_avg(pre=1, post=1)
  last_index = self.size - 1
  ma = self.class.new(self.size)
  self.each_with_index do |center,index|
    start_i = index - pre
    start_i >= 0 or start_i = 0
    end_i = index + post
    end_i < self.size or end_i = last_index
    ma[index] = self[start_i..end_i].avg
  end
  ma
end

#nil?Boolean

Returns:

  • (Boolean)


920
921
922
# File 'lib/runarray/narray.rb', line 920

def nil?
  false
end

#noisify!(fraction, precision = 1000000) ⇒ Object

for each value in mat, take a certain fraction and make it random random fraction can be from 0 to 2X the original fraction.



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/runarray/narray.rb', line 113

def noisify!(fraction, precision=1000000)
  self.collect! do |val| 
    part = fraction * val
    rnum = rand((2*part*precision).to_i)
    random = rnum.to_f/precision
    answ = val - part
    if val > 0
      answ + random
    else
      answ - random
    end
  end
end

#old_mapObject



5
# File 'lib/runarray/narray.rb', line 5

alias_method :old_map, :map

#old_selectObject



6
# File 'lib/runarray/narray.rb', line 6

alias_method :old_select, :select

#orderObject

returns the indices as VecI object which indicate the ascending order of the values tie goes to the value closest to the front of the list



714
715
716
717
718
719
720
721
722
723
724
# File 'lib/runarray/narray.rb', line 714

def order
  sorted = self.sort
  hash = Hash.new {|h,k| h[k] = [] }
  self.each_with_index do |sortd,i|
    hash[sortd] << i
  end
  ord = sorted.map do |val|
    hash[val].shift
  end
  Runarray::NArray.new('int').replace(ord)
end

#outliers(deviations, y = nil) ⇒ Object

returns an ary of indices to outliers if y is given, the residuals from the least squares between self and y are calculated before finding outliers



606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
# File 'lib/runarray/narray.rb', line 606

def outliers(deviations, y=nil)
  indices = []
  distribution = 
    if y 
      self.residuals_from_least_squares(y)
    else
      self
    end
  mean, std_dev = distribution.sample_stats
  cutoff = deviations.to_f * std_dev
  distribution.each_with_index do |res,i|
    if (res - mean).abs > cutoff
      indices << i 
    end
  end
  indices
end

#outliers_iteratively(deviations, y = nil) ⇒ Object



554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
# File 'lib/runarray/narray.rb', line 554

def outliers_iteratively(deviations, y=nil)
  xdup = self.dup
  ydup = y.dup if y
  indices = nil
  all_indices = []
  loop do
    indices = xdup.outliers(deviations, ydup)
    all_indices << indices.dup
    if indices.size == 0
      break
    else
      indices.reverse.each do |i|
        xdup.delete_at(i)
        ydup.delete_at(i) if y
      end
    end
  end
  _correct_indices(all_indices)
end

#pearsons_r(y) ⇒ Object



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/runarray/narray.rb', line 379

def pearsons_r(y)
  x = self
  sum_xy = @@zero
  sum_x = @@zero
  sum_y = @@zero
  sum_x2 = @@zero
  sum_y2 = @@zero
  n = x.size

  x.each_with_index do |xval,i|
    yval = y[i]
    sum_xy += xval * yval
    sum_x += xval
    sum_y += yval
    sum_x2 += xval**2
    sum_y2 += yval**2 
  end

  ## Here it is:
  # 'E' is Capital Sigma 
  # r = EXY - (EXEY/N) 
  #    -----------------
  #    sqrt( (EX^2 - (EX)^2/N) * (EY^2 - (EY)^2/N) )

  top = sum_xy.to_f - ((sum_x * sum_y).to_f/n)
  fbot = sum_x2.to_f - ((sum_x**2).to_f/n)
  sbot = sum_y2.to_f - ((sum_y**2).to_f/n)
  top / Math.sqrt(fbot * sbot)
end

#residuals_from_least_squares(y) ⇒ Object

Returns a NArray object (of doubles)



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
# File 'lib/runarray/narray.rb', line 658

def residuals_from_least_squares(y)
  rsq, slope, intercept = rsq_slope_intercept(y)
  residuals = Runarray::NArray.float
  self.each_with_index do |val,i|
    expected_y = (slope*val) + intercept 
    ydiff = y[i].to_f - expected_y
    if ydiff == 0.0
      residuals << 0.0
    else
      run = ydiff/slope
      residuals << run/( Math.sin(Math.atan(ydiff/run)) )
    end
  end
  residuals
end

#rsq_slope_intercept(y) ⇒ Object

Returns (rsq, slope, y_intercept)



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/runarray/narray.rb', line 410

def rsq_slope_intercept(y)
  x = self
  if y.size != x.size then raise ArgumentError, "y must have same size as self!" end
  if x.size < 2
    raise ArgumentError, "vectors must have 2 or more data points!"
  elsif x.size == 2
    l = x[1]; fl = y[1]; s = x[0]; fs = y[0]
    if x[0] > x[1] ; l,s=s,l; fl,fs=fs,fl end
    if l-s == 0 then raise ArgumentError, "two points same x" end
    slope = (fl-fs)/(l-s)
    # y = mx + b
    # b = y - mx
    y_intercept = fl - (slope*l)
    rsq = 1.0   
    return rsq, slope, y_intercept
  else
    x = self
    mean_x = x.avg
    mean_y = y.avg
    sum_sq_res_xx = @@zero
    sum_sq_res_yy = @@zero
    sum_sq_res_xy = @@zero
    x.each_with_index do |val,i|
      x_minus_mean_i = x[i].to_f - mean_x
      y_minus_mean_i = y[i].to_f - mean_y
      sum_sq_res_xx += x_minus_mean_i*x_minus_mean_i
      sum_sq_res_yy += y_minus_mean_i*y_minus_mean_i
      sum_sq_res_xy += x_minus_mean_i*y_minus_mean_i
    end
    slope = sum_sq_res_xy/sum_sq_res_xx
    y_intercept = mean_y - (slope * mean_x) 
    rsq = (sum_sq_res_xy*sum_sq_res_xy)/(sum_sq_res_xx*sum_sq_res_yy)
    return rsq, slope, y_intercept
  end
end

#sample_statsObject

Returns (mean, standard_dev) if size == 0 returns [nil, nil]



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# File 'lib/runarray/narray.rb', line 448

def sample_stats
  _len = size
  return [nil, nil] if _len == 0
  _sum = 0.0
  _sum_sq = 0.0
  self.each do |val|
    _sum += val
    _sum_sq += val * val
  end
  std_dev = _sum_sq - ((_sum * _sum)/_len)
  std_dev /= ( _len > 1 ? _len-1 : 1 )
  std_dev = Math.sqrt(std_dev)
  mean = _sum.to_f/_len
  return mean, std_dev
end

#select(&block) ⇒ Object



71
72
73
# File 'lib/runarray/narray.rb', line 71

def select(&block)
  self.class.new(old_select(&block))
end

#shuffleObject



703
704
705
# File 'lib/runarray/narray.rb', line 703

def shuffle
  self.dup.shuffle!
end

#shuffle!Object



690
691
692
693
694
695
696
697
698
699
700
701
# File 'lib/runarray/narray.rb', line 690

def shuffle!
  ##################################
  ## this is actually slightly faster, but I don't know how stable
  #size.downto(1) { |n| push delete_at(rand(n)) }
  #self
  ##################################
  (size - 1) .downto 1 do |i|
    j = rand(i + 1)
    self[i], self[j] = self[j], self[i]
  end
  self
end

#spreadObject

difference between max and min



916
917
918
# File 'lib/runarray/narray.rb', line 916

def spread
  (max - min).abs
end

#sumObject



258
259
260
261
262
263
264
# File 'lib/runarray/narray.rb', line 258

def sum
  sum = @@zero
  self.each do |val|
    sum += val 
  end
  sum
end

#to_aObject

def ==(other)

if other == nil
  return false
end
self.each_index do |i|
  if self[i] != other[i]
    return false
  end
end
true

end



103
104
105
106
107
108
109
# File 'lib/runarray/narray.rb', line 103

def to_a
  x = []
  self.each do |it|
    x << it
  end
  x
end

#to_rep(val) ⇒ Object

Takes input and converts to whatever internal representation SUBCLASS THIS GUY!



133
134
135
# File 'lib/runarray/narray.rb', line 133

def to_rep(val)
  val.to_f
end

#to_sObject



83
84
85
# File 'lib/runarray/narray.rb', line 83

def to_s
  self.join(" ")
end

#transform(*args, &block) ⇒ Object

called as (points, &block) or (pre, post, &block) points e.g. 3, means one before, current, and one after) pre = 1 and post = 1 is 3 points pre = 2 and post = 2 is 5 points yields a Vec object with the objects to be acted on and sets the value to the return value of the block.



1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
# File 'lib/runarray/narray.rb', line 1056

def transform(*args, &block)
  (pre, post) = 
    if args.size == 1
      pre = (args[0] - 1) / 2
      post = pre
      [pre, post]
    elsif args.size == 2
      args
    else 
      raise(ArgumentError, "accepts (pre, post, &block), or (points, &block)")
    end
  trans = self.class.new(size)
  last_i = self.size - 1
  # TODO: could implement with rolling yielded array and be much faster...
  self.each_with_index do |x,i|
    start = i - pre
    stop = i + post
    start = 0 if start < 0
    stop = last_i if stop > last_i
    trans[i] = block.call(self[start..stop])
  end
  trans
end