sgolay

Savitzky-Golay Filter Design

Syntax

```[B, C] = sgolay(k, nf)
[B, C] = sgolay(k, nf, w)```

Arguments

k

a positive scalar with integer value: the fitting polynomial degree.

nf

a positive scalar with integer value: the filter length, must be odd and greater than k+1.

w

a real vector of length nf with positive entries: the weights. If omitted no weights are applied.

B

a real n by n array: the set of filter coefficients: the early rows of B smooth based on future values and later rows smooth based on past values, with the middle row using half future and half past. In particular, you can use row i to estimate x(k) based on the i-1 preceding values and the n-i following values of x values as y(k) = B(i,:) * x(k-i+1:k+n-i).

C

a real n by k+1 array: the matrix of differentiation filters. Each column of C is a differentiation filter for derivatives of order P-1 where P is the column index. Given a signal X with length nf, an estimate of the P-th order derivative of its middle value can be found from:

(P) X ((nf+1)/2) = P!*C(:,P+1)'*X

Description

This function computes the smoothing FIR Savitzky-Golay Filter. This is achieved by fitting successive sub-sets of adjacent data points with a low-degree polynomial by the method of linear least squares.

This filter can also be used to approximate numerical derivatives.

Examples

The sgolay function can be used to construct FIR filter with no group delay. The following instructions explains what the sgolayfilt function does:

```dt = 0.01;
t = (0:0.01:4*%pi)';
x = sin(t)+0.05*rand(t,'normal');

nf = 61;
[B,C] = sgolay(3,nf);
nfs2 = floor(nf/2);

//compute the middle part of the filtered signal
xfm = filter(B(nfs2+1,:), 1, x);
xfm = xfm(nf:\$);
//compute the left part of the filtered signal
xfl = B(1:nfs2,:)*x(1:nf);
//compute the right part of the filtered signal
xfr = B(nfs2+2:nf,:)*x(\$-nf+1:\$);
clf
plot(t,x,'b',t,[xfl;xfm;xfr],'r');
gce().children(1).thickness = 2;
legend(["Raw","Filtered"]);```

The above script generate this graph:

It can also be used to obtain approximate derivatives:

```dt=0.01;
t = (0:0.01:4*%pi)';
x = sin(t)+0.03*rand(t,'normal');

nf = 61;
[B,C] = sgolay(3,nf);
nfs2 = floor(nf/2);

dx=-conv(x,C(:,2)',"valid");
d2x=2*conv(x,C(:,3)',"valid");

clf();
subplot(211)
plot(t(2:\$),diff(x)/dt,'g',t,cos(t),'b',t(nfs2+1:\$-nfs2),dx/dt,'r');
legend(["diff","theoretical","sgolay"]);
title("First order differentiation")
subplot(212)
plot(t,-sin(t),'b',t(nfs2+1:\$-nfs2),d2x/(dt^2),'r');
legend(["theoretical","sgolay"]);
title("Second order differentiation")```

Bibliography

Abraham Savitzky et Marcel J. E. Golay, « Smoothing and Differentiation of Data by Simplified Least Squares Procedures », Analytical Chemistry, vol. 8, no 36,‎ 1964, p. 1627–1639 (DOI 10.1021/ac60214a047)