function polynomial_degree=adpf(data_frame)
%
%Adaptive-Degree Polynomial Filter (Savitzky-Golay Filter)
%
%Commonly, the degree of the fitting polynomial for the Savitzky-Golay
%filter is fixed. However, the polynomial degree can vary according
%to the sum of squares of fitting residuals and the statistical testing
%to obtain the adaptive-degree polynomial filter.
%
%This function can be used to obtain the polynomial degree (output: polynomial_degree)
%selected in the adaptive-degree polynomial filter (Savitzky-Golay filter)
%for the data subset of length 2M+1 (intput: data_frame).
%
%Usage:
%Run Pkmi_Calculate first to obtain the numerical table of gram polynomials
%so as to accelerate the calculation.
%
%Examples:
%adpf_demo %A demo of data smoothing with the adaptive-degree polynomial filter
%Fig_1 %Obtain figure 1 of Ref. [1]
%Fig_2 %Obtain figure 2 of Ref. [1]
%
%Author:
% Jianwen Luo <luojw@bme.tsinghua.edu.cn, luojw@ieee.org> 2004-10-26
% Department of Biomedical Engineering, Department of Electrical Engineering
% Tsinghua University, Beijing 100084, P. R. China
%
%References:
% [1] P. Barak,
% "Smoothing and differentiation by an adaptive-degree polynomial filter,"
% Analytical Chemistry, vol. 67, pp. 2758-2762, 1995.
% [2] M. Jakubowska and W. W. Kubiak,
% "Adaptive-degree polynomial filter for voltammetric signals,"
% Analytica Chimica Acta, vol. 512, pp. 241-250, 2004.
% [3] A. Savitzky and M. J. E. Golay,
% "Smoothing and Differentiation of Data by Simplified Least Squares Procedures,"
% Analytical Chemistry, vol. 36, pp. 1627-1639, 1964.
% [4]P. A. Gorry,
% "General Least-Squares Smoothing and Differentiation by the Convolution (Savitzky-Golay) Method,"
% Analytical Chemistry, vol. 62, pp. 570-573, 1990.
% [5] J. W. Luo, K. Ying, P. He and J. Bai,
% Properties of Savitzky-Golay digital differentiators,
% Digital Signal Processing, in press,
% available at http://www.sciencedirect.com/science?_ob=IssueURL&_tockey=%23TOC%236768%239999%23999999999%2399999%23FLP%23Articles_in_Press&_auth=y&view=c&_acct=C000053663&_version=1&_urlVersion=0&_userid=1553430&md5=6a3653781dc7d2ec0b942b6efd816a32
% [6] http://www.mathworks.com/matlabcentral/fileexchange/loadFileList.do?objectType=search&criteria=savitzky+or+sgolayfilt&Search=Go
% [7] http://uk.cambridge.org/chemistry/resources/delevie/
global Pkmi_array
m=(length(data_frame)-1)/2;
N=length(data_frame);
x=-m:m;
y=data_frame;
x=x(:);
y=y(:);
alpha=0.1;
if N==3
polynomial_degree=1;%%%%%%%%%%%%revised from 2
else
k_start=1;% 0/1 for smoothing
k_end=N-2;%%%%%%%%%%%revised from N-1-2
k=k_start;
p_fit=polyfit(x,y,k);%polynomial degree = k_start
res_odd=sum((y-polyval(p_fit,x)).^2);
Fxs=[];
F_alphas=[];
while k<k_end%%%%%%%%%%%%%revised from k<=k_end
n1=k;
%polynomial degree = k
k=k+1;
value1=0;
value2=0;
for i=-m:m
value1=value1+Pkmi_array(k+2,m,i+m+1)*y(i+m+1);
value2=value2+(Pkmi_array(k+2,m,i+m+1))^2;
end
res_tmp=res_odd(end)-value1^2/value2;
%Note the typo in Equ. (6) of Ref. [1].
%polynomial degree = k+1
k=k+1;
value1=0;
value2=0;
for i=-m:m
value1=value1+Pkmi_array(k+2,m,i+m+1)*y(i+m+1);
value2=value2+(Pkmi_array(k+2,m,i+m+1))^2;
end
res_odd=[res_odd res_tmp-value1^2/value2];
n2=k;
v1=n2-n1;
v2=N-n2-1;
Fx=(res_odd(end-1)-res_odd(end))/(n2-n1)/res_odd(end)*(N-n2-1);
%In Ref. [1] and [2], the term '/(n2-n1)' is ignored.
%From my point of view, the consideration of this term would be more reasonable according to some textbooks on applied regression analysis.
F_alpha=finv(1-alpha,v1,v2);
Fxs=[Fxs Fx];
F_alphas=[F_alphas F_alpha];
if Fx<F_alpha
break;
end
end
if Fx<F_alpha
polynomial_degree=k-2;
else
polynomial_degree=k_end;
end
end