Module: Savgol
- Included in:
- Array
- Defined in:
- lib/savgol.rb,
lib/savgol/array.rb,
lib/savgol/version.rb
Constant Summary collapse
- VERSION =
"0.2.1"
Instance Method Summary collapse
- #savgol(window_size, order, deriv = 0, check_args = false) ⇒ Object
- #sg_convolve(data, weights, mode = :valid) ⇒ Object
-
#sg_pad_ends(half_window) ⇒ Object
pads the ends with the reverse, geometric inverse sequence.
-
#sg_weights(half_window, order, deriv = 0) ⇒ Object
returns an object that will convolve with the padded array.
Instance Method Details
#savgol(window_size, order, deriv = 0, check_args = false) ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/savgol/array.rb', line 5 def savgol(window_size, order, deriv=0, check_args=false) # check arguments if !window_size.is_a?(Integer) || window_size.abs != window_size || window_size % 2 != 1 || window_size < 1 raise ArgumentError, "window_size size must be a positive odd integer" end if !order.is_a?(Integer) || order < 0 raise ArgumentError, "order must be an integer >= 0" end if window_size < order + 2 raise ArgumentError, "window_size is too small for the polynomials order" end half_window = (window_size -1) / 2 weights = sg_weights(half_window, order, deriv) ar = sg_pad_ends(half_window) sg_convolve(ar, weights) end |
#sg_convolve(data, weights, mode = :valid) ⇒ Object
24 25 26 27 28 |
# File 'lib/savgol/array.rb', line 24 def sg_convolve(data, weights, mode=:valid) data.each_cons(weights.size).map do |ar| ar.zip(weights).map {|pair| pair[0] * pair[1] }.reduce(:+) end end |
#sg_pad_ends(half_window) ⇒ Object
pads the ends with the reverse, geometric inverse sequence
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/savgol/array.rb', line 31 def sg_pad_ends(half_window) start = self[1..half_window] start.reverse! start.map! {|v| self[0] - (v - self[0]).abs } fin = self[(-half_window-1)...-1] fin.reverse! fin.map! {|v| self[-1] + (v - self[-1]).abs } start.push(*self, *fin) end |
#sg_weights(half_window, order, deriv = 0) ⇒ Object
returns an object that will convolve with the padded array
43 44 45 46 47 48 49 50 51 |
# File 'lib/savgol/array.rb', line 43 def sg_weights(half_window, order, deriv=0) # byebug mat = Matrix[ *(-half_window..half_window).map {|k| (0..order).map {|i| k**i }} ] # Moore-Penrose psuedo-inverse without SVD (not so precize) # A' = (A.t * A)^-1 * A.t pinv_matrix = Matrix[*(mat.transpose*mat).to_a].inverse * Matrix[*mat.to_a].transpose pinv = Matrix[*pinv_matrix.to_a] pinv.row(deriv).to_a end |