from Adaptive-Degree Polynomial Filter (Savitzky-Golay Filter) by Jianwen Luo
Obtain the polynomial degree selected in the adaptive-degree polynomial filter.

polynomial_degree=adpf(data_frame)
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

Contact us at files@mathworks.com