Noninvasive Fetal ECG: The PhysioNet/Computing in Cardiology Challenge 2013 1.0.0

File: <base>/sources/mhaghpanahi_at_gmail.com/ekf_df_dw.m (1,906 bytes)
function df = ekf_df_dw(X,params)

    % X: state vector
    % params: a cell containing all parameters required:
        % W: process noise vector
        % nk: a vector indicating the number of Gaussian Kernels used for modeling
        % each independent component
        % fs:sampling frequency

    L=size(X,1); % number of states in the state vector X
    
    W= params{1};
    nk= params{2};
    fs= params{3};
    
    Lind = length(nk); % number of independent components used for MECG cancellation
    nParam = length(W); % number of process noise parameters
    w=W(1); % average heart-rate in rads
    df= zeros(L, nParam); % Note that L=Lind+1
    
    dt= 1/fs;
    df(1,1)=dt;
    ptr=1; % pointer to the current parameter extracted from the W vector
    for i=1:Lind
        kernelParam = reshape(W(ptr+1:ptr+nk(i)*3),3,[]); % kernel parameters for the current independent component
        dfi= feval(@df_dW, X, kernelParam, w, fs);
        df(i+1,1)= dfi(1);
        df(i+1,ptr+1:ptr+nk(i)*3)=dfi(2:end);
        df(i+1,end-Lind+i)=1;
        ptr=ptr+nk(i)*3;
    end

end

function y = df_dW(X, kp, w, fs)
    % X: state vector
    % kp: kernel parameters
    % w:  average heart-rate in rads
    % fs: sampling frequency
    % np: number of process noise parameters
    dt= 1/fs;
    alpha= kp(1,:);
    theta= kp(2,:);
    b=kp(3,:);
    
    dtheta=  rem(X(1) - theta,2*pi);
    np= numel(kp);
    partDeriv= zeros(size(kp));
    
    y=zeros(1,np+1);
    y(1)= -sum(dt*alpha.*dtheta./(b.^2).*exp(-dtheta.^2./(2*b.^2)));
    partDeriv(1,:)= -dt*w./(b.^2).*dtheta .* exp(-dtheta.^2./(2*b.^2));
    partDeriv(2,:)= 2*dt.*alpha.*w.*dtheta./b.^3.*(1 - dtheta.^2./(2*b.^2)).*exp(-dtheta.^2./(2*b.^2));
    partDeriv(3,:)= dt*w*alpha./(b.^2).*exp(-dtheta.^2./(2*b.^2)) .* (1 - dtheta.^2./b.^2);
    y(2:end)= partDeriv(:)';
    
end