function [out]=rbd(sig,win,M1,M2)

%

% Recursive Bayesian Autoregressive Changepoint Detector

% Usage: [out] = rbd(sig,win,M1,M2)

%

% Input:  sig    ............ 1-D data vector

%         win           ..... length of sliding window

%                             (default 400), min~200, max~5000

%         M1, M2   .......... order of AR model (from left and right)

%                             (default 6)

% Output: out ................~(d_cep1).^2

%                             is proportional to the signal changes

%                            

% by Roman Cmejla, cmejla@fel.cvut.cz

% 2011Aug15, ver.3.00 

 

if (nargin == 0), disp('Usage: [out] = rbd(sig, win, M1, M2)'); return; end

if (nargin == 1), M1=6; M2=6; win=400; end;

if (nargin == 2), M1=6; M2=6; end;

if (nargin == 3), M1=M2; end;

 

% Initialization for m=length(window)/2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bay(length(sig))=0;

evid(length(sig))=0;

ME=round((M1+M2)/2);

sig=sig(:); sig=sig/max(abs(sig));

m=fix(win/2);

data=sig(1:win);

G(length(data-m),M1+M2)=0;

N=length(data);

 

% Initial matrix of basis function

for j=2:M1

    if j <= m, G(j,:)=[data(j-1:-1:1)' zeros(1,M1-j+1) zeros(1,M2)]; end;       

    if j > m, G(j,:)=[zeros(1,M1) data(j-1:-1:1)' zeros(1,M2-j+1)]; end;

end;

for j=(M1+1):N

    if j <= m, G(j,:)=[data(j-1:-1:j-M1)' zeros(1,M2)]; end;

    if j > m, G(j,:)=[zeros(1,M1) data(j-1:-1:j-M2)']; end;

end;

    D=data'*data;               % Signal energy

    CHI=data'*G;                % Correlation vector

    FI=inv(G'*G);               % Inverse correlation matrix

 

% Initial matrix of Bayesian evidence for estimate normalization

for j=2:ME

            G_E(j,:)=[data(j-1:-1:1)' zeros(1,ME-j+1)];

end;

for j=(ME+1):N

            G_E(j,:)=[data(j-1:-1:j-ME)'];

end;

    CHI_E  = data'*G_E;         % Correlation vector of BE

    FI_E   = inv(G_E'*G_E);     % Inverse correlation matrix of BE

 

for mm=m+1:length(sig)-m

% Recursive changepoint estimation for all next samples

    % Observe new sample

    d_last=sig(mm+m);   % new signal sample

    G2=[zeros(1,M1) sig(mm+m-1:-1:mm+m-M2)'];

    D=D+d_last*d_last;

    CHI=CHI+d_last*G2;

    W=FI*G2';

    LAMBDA=(1+G2*W);

    FI=FI-W*inv(LAMBDA)*W';

    % Removing old sample

    D=D-sig(mm-m)*sig(mm-m);

    if mm-m > M1, Z=[sig(mm-1-m:-1:mm-M1-m)' zeros(1,M2)]; else

        Z=[sig(mm-1-m:-1:1)' zeros(1,M2) zeros(1,M1-mm+m+1)]; end;

    CHI=CHI - sig(mm-m)*Z;

    W=FI*Z';

    LAMBDA=(1-Z*W);        

    FI=FI+(1/LAMBDA)*W*W';       

    % Position update

    R=[zeros(1,M1) sig(mm-1:-1:mm-M2)'];    % replacing with row of zeros

    CHI=CHI - sig(mm)*R;

    W=FI*R';

    LAMBDA=(1-R*W);         

    FI=FI+(1/LAMBDA)*W*W';        

    Q=[sig(mm-1:-1:mm-M1)' zeros(1,M2)];     % replacing with new data

    CHI=CHI + sig(mm)*Q;

    W=FI*Q';

    LAMBDA=(1+Q*W);        

    FI=FI-(1/LAMBDA)*W*W';  

    bay(mm)=log(D-CHI*FI*CHI');

 

% Bayesian evidence update

    % Adding new sample

    G2_E=[sig(mm+m-1:-1:mm+m-ME)'];

    CHI_E=CHI_E+d_last*G2_E;

    W_E=FI_E*G2_E';

    LAMBDA_E=(1+G2_E*W_E);

    FI_E=FI_E-W_E*inv(LAMBDA_E)*W_E';

    % Removing old sample

    if mm-m > ME, Z_E=[sig(mm-1-m:-1:mm-ME-m)']; else

        Z_E=[sig(mm-1-m:-1:1)' zeros(1,ME-mm+m+1)]; end;

    CHI_E=CHI_E - sig(mm-m)*Z_E;

    W_E=FI_E*Z_E';

    LAMBDA_E=(1-Z_E*W_E);        

    FI_E=FI_E+(1/LAMBDA_E)*W_E*W_E';        

    FTF=CHI_E*FI_E*CHI_E';

    evid(mm)=log(D-FTF);

% Return for position m+1

end;

 

% Calculate changepoint position probabilities

out=real(evid)-real(bay);

out=[zeros(1,m) 4*out(round(win/2)+1:end)];