sablib
Loading...
Searching...
No Matches
savitzky_golay.cpp
Go to the documentation of this file.
1
6
7#include <cmath>
8
9#include "../misc/convolve.h"
10
11#include "savitzky_golay.h"
12
13namespace sablib {
14
15//
16// Implementation of SavitzkyGolayCoefficients() function
17//
18const std::vector<double> SavitzkyGolayCoefficients(
19 const unsigned int n, const unsigned int polyorder, const unsigned derive, const double delta
20)
21{
22 unsigned int window = 2 * n + 1;
23 double p = 1;
24
25 if(n == 0) {
26 throw std::invalid_argument("SavitzkyGolayCoefficients(): n is zero.");
27 }
28
29 if(polyorder == 0) {
30 throw std::invalid_argument("SavitzkyGolayCoefficients(): polyorder is zero.");
31 }
32
33 if(window <= polyorder) {
34 throw std::invalid_argument("SavitzkyGolayCoefficients(): window size (2 * n + 1) must be greater than polyorder.");
35 }
36
37 if(window <= derive) {
38 throw std::invalid_argument("SavitzkyGolayCoefficients(): window size (2 * n + 1) must be greater than derive.");
39 }
40
41 if(polyorder <= derive) {
42 throw std::invalid_argument("SavitzkyGolayCoefficients(): polyorder must be greater than derive.");
43 }
44
45 Eigen::VectorXd v = Eigen::VectorXd::LinSpaced(window, (int)-n, n);
46 Eigen::MatrixXd x = Eigen::MatrixXd::Ones(window, polyorder + 1);
47
48 for(unsigned int i = 1; i <= polyorder; i++){
49 x.col(i) = (x.col(i - 1).array() * v.array()).matrix();
50 }
51
52 Eigen::MatrixXd coeff_mat = (x.transpose() * x).inverse() * x.transpose();
53
54 if(derive > 0){
55 for(unsigned int i = 1; i <= derive; i++){
56 p *= i;
57 }
58 p /= std::pow(delta, derive);
59 }
60
61 Eigen::VectorXd coeff = coeff_mat.row(derive) * p;
62 std::vector<double> result(coeff.size());
63
64 Eigen::VectorXd::Map(result.data(), result.size()) = coeff;
65
66 return result;
67}
68
69//
70// Implementation of SavitzkyGolay() function
71//
72const std::vector<double> SavitzkyGolay(
73 const std::vector<double> & y,
74 const unsigned int n, const unsigned int polyorder, const unsigned derive, const double delta
75)
76{
77 if(y.size() == 0) {
78 throw std::invalid_argument("SavitzkyGolay(): the length of y is zero.");
79 }
80
81 std::vector<double> coeff = SavitzkyGolayCoefficients(n, polyorder, derive, delta);
82 Eigen::VectorXd w = Eigen::VectorXd::Map(coeff.data(), coeff.size());
83 Eigen::VectorXd yy = Eigen::VectorXd::Map(y.data(), y.size());
84
85 Eigen::VectorXd z = Convolve(yy, w, ConvolveMode::Same);
86
87 std::vector<double> result(z.size());
88
89 Eigen::VectorXd::Map(result.data(), result.size()) = z;
90
91 return result;
92}
93
94}; // namespace sablib
Python's NumPy-like convolve() function.
const Derived1::PlainObject Convolve(const Eigen::MatrixBase< Derived1 > &v1, const Eigen::MatrixBase< Derived2 > &v2, const ConvolveMode mode=ConvolveMode::Full)
Returns the discrete, linear convolution of two one-dimensional sequences.
Definition convolve.h:35
const std::vector< double > SavitzkyGolay(const std::vector< double > &y, const unsigned int n, const unsigned int polyorder, const unsigned derive, const double delta)
Performs smoothing (and differentiation) using a Savitzky-Golay filter.
const std::vector< double > SavitzkyGolayCoefficients(const unsigned int n, const unsigned int polyorder, const unsigned derive, const double delta)
Calculates the coefficients for a Savitzky-Golay filter.
Smoothing using Savitzky-Golay filter.