ECG-Kit 1.0
(10,855 bytes)
function [marksSLR,ind,messages]=SLR(marks,fa,QRSLIMIT,k,delta,messages)
% post processing rule for delineation
%
% [marksSLR,ind,messages]=SLR(marks,fa,QRSLIMIT,k,delta,messages)
%
% INPUT:
% marks: structure with a matrix of annotations in samples; in each field
% each matrix of annotations has one line per beat and 10 colunms
% corresponding respectively to P onset, P peak, P end, QRS onset, QRS
% main peak, QRS end, T onset, T peak, T prima, T end
% fa: sampling frequency of the recording.
% QRSLIMIT: admited diference between marks of the same beat in samples (optional)
% by default QRSLIMIT= 250 ms.
% k: number of neighbours to consider in SLR rule (optional)
% by default k=3
% delta: neighbourhood to consider in SLR rule in samples (optional)
% by default delta = [4 nan 4 12 nan 10 12 nan nan 12] ms for 10 marks
% or delta = [4 nan nan 4 nan 12 nan nan nan nan 10 12 nan nan 12] ms for 15 marks
% messages:- errors and warnings (optional)
%
% OUTPUT:
% marksSLR: multilead based on marks obtained by SLR rule
% ind: indexes of the initial column vectors for each set, corresponding to the sincronized beats
% each line of ind corresponds to a beat and each column to a set
% if a beat is absent of a set
% messages.errors: errors during the processing
% messages.errors_desc:errors description
% messages.status: sucess of the procesing (1) ou fail (0)
% messages.status: parameters considered
% Last update: DEZ2011
marksSLR=[];
ind=[];
if nargin<2
messages.errors= 'Fatal error in SLR.';
messages.errors_desc= 'Inputs marks and fa required';
messages.status=0;
return
else
if size(marks{1},2)~=10 && size(marks{1},2)~=15
messages.errors= 'Fatal error in SLR.';
messages.errors_desc= 'Input marks should include 10 or 15 marks.';
messages.status=0;
return
end
messages.status=1;
if ~isfield(messages,'errors')
messages.errors=[];
end
if ~isfield(messages,'errors_desc')
messages.errors_desc=[];
end
if ~isfield(messages,'warnings')
messages.warnings=[];
end
if ~isfield(messages,'status')
messages.status=1;
end
if ~isfield(messages,'setup')
messages.setup=[];
end
if ~isfield(messages.setup,'SLR')
messages.setup.SLR=[];
end
end
if nargin<5
if size(marks{1},2)==10
delta = [4 nan 4 12 nan 10 12 nan nan 12]*fa/1000;
elseif size(marks{1},2)==15
delta = [4 nan nan 4 nan 12 nan nan nan nan 10 12 nan nan 12]*fa/1000;
end
if nargin<4
k=min(3,size(marks{1},1)-1);
k=2;
if nargin<3
QRSLIMIT=250*fa/1000;
end
end
messages.setup.SLR.QRSlimit=QRSLIMIT;
messages.setup.SLR.delta=delta;
messages.setup.SLR.k=k;
if nargin<3
if isfield(messages,'setup') & isfield(messages.setup,'SLR')
if isfield(messages.setup.SLR,'QRSlimit')
QRSLIMIT=messages.setup.SLR.QRSlimit;
else
QRSLIMIT=[];
end
if isfield(messages.setup.SLR,'k')
k=messages.setup.SLR.k;
else
k=[];
end
if isfield(messages.setup.SLR,'delta')
if length(delta)==size(marks{1},2)
delta= messages.setup.SLR.delta;
else
delta=[];
end
end
else
QRSLIMIT=[];
k=[];
delta=[];
end
end
end
if isempty(QRSLIMIT) | ~isnumeric(QRSLIMIT) | isnan(QRSLIMIT)
QRSLIMIT=250*fa/1000;
messages.setup.SLR.QRSlimit=QRSLIMIT;
end
if isempty(k) | ~isnumeric(k) | isnan(k)
k=min(3,size(marks{1},1)-1);
messages.setup.SLR.k=k;
end
if isempty(delta) | size(delta)~=size(marks{1},2)
if size(marks{1},2)==10
delta = [4 nan 4 12 nan 10 12 nan nan 12]*fa/1000;
elseif size(marks{1},2)==15
delta = [4 nan nan 4 nan 12 nan nan nan nan 10 12 nan nan 12]*fa/1000;
end
messages.setup.SLR.delta=delta;
end
if ~isfield(messages.setup.SLR,'refrper')
if isfield(messages.setup,'wavedet') & isfield(messages.setup.wavedet,'refrper')
messages.setup.SLR.refrper=messages.setup.wavedet.refrper;
else
messages.setup.SLR.refrper=0.275;
end
end
if ~isfield(messages.setup.SLR,'tolerance')
messages.setup.SLR.tolerance=10*fa/1000; % 10 msec
end
if isstruct(marks)
leads = fieldnames(marks);
messages.setup.nleads=length(leads);
else
messages.setup.nleads = size(marks,2);
end
if length(delta)==10
messages.setup.marks_desc={'(','P',')','(','QRS',')','(','T','T''',')'};
% nmarks=10;
peaks=[2 5 8 9];
onsets=[1 4 6];
ends=[3 6 10];
refmark=5; %JB 27JUL2011
elseif length(delta)==15
messages.setup.marks_desc={'(','P','P''',')','QRS_first_peak','(','Q','R','S','R''',')','(','T','T''',')'};
% nmarks=15;
peaks=[2 3 8 13 14];
onsets=[1 6 12];
ends=[4 11 15];
% refmark=8; %JB 27JUL2011
refmark=[8 9 7 10];%RUTE %29JUL2011 porque la onda R puede ni existir en una derivacion especifica!
end
nmarks=length(delta);
beats=0;
% refmark=5; %JB 27JUL2011
refmark_n=refmark; %DEZ2011
for g=1:messages.setup.nleads
if isstruct(marks)
f = getfield(marks, char(leads(g))); %#ok<GFLD>
else
f = marks{g};
end
if length(f)> size(beats,1)
beats((size(beats,1)+1):length(f),1:g)=zeros(length((size(beats,1)+1):length(f)),g);
end
% beats(1:size(f,1),g)=f(:,refmark(1)); %19ABRIL2010
for n=1:size(f,1)%DEZ2011
refmark(n)=refmark_n(find(~isnan(f(n,refmark_n)),1,'first'));%DEZ2011
beats(n,g)=f(n,refmark(n)); %29JUL2011 %DEZ2011
end
%beats(1:size(f,1),g)=f(:,refmark); %29JUL2011
end
beats(beats==0)=NaN;
[ind,messages1]=sincronizabeats(beats,QRSLIMIT); %27JUL2011
ind(sum(~isnan(ind),2)<k+1,:) = [];
% nbeats=size(ind,1);
%JB 27JUL2011
beats=NaN*ones(size(ind));
for g=1:size(ind,2)
if isstruct(marks)
f = getfield(marks, char(leads(g))); %#ok<GFLD>
else
f = marks{g};
end
beats(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),5);
end
%ind(diff(nanmedian(beats,2)) < 200,:) = [];%JB 27JUL2011
ind(find(diff(nanmedian(beats,2)) < messages.setup.SLR.refrper*fa)+1,:) = [];%RUTE 10AGO 2011
nbeats=size(ind,1);
marksSLR=NaN.*ones(nbeats,nmarks);
for mark=peaks
beats=NaN*ones(size(ind));
for g=1:size(ind,2)
if isstruct(marks)
f = getfield(marks, char(leads(g))); %#ok<GFLD>
else
f = marks{g};
end
beats(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),mark);
end
marksSLR(:,mark)=nanmedian(beats,2);
end
if nmarks==15;
mark=7:10;
QRS{1}=NaN*ones(size(ind));
QRS{2}=QRS{1};
QRS{3}=QRS{1};
QRS{4}=QRS{1};
for g=1:size(ind,2)
if isstruct(marks)
f = getfield(marks, char(leads(g))); %#ok<GFLD>
else
f = marks{g};
end
QRS{1}(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),mark(1));
QRS{2}(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),mark(2));
QRS{3}(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),mark(3));
QRS{4}(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),mark(4));
end
for beat=1:nbeats
AA=[QRS{1}(beat,:);QRS{2}(beat,:);QRS{3}(beat,:);QRS{4}(beat,:)];
%look for small R waves that should go with Q waves
%RS that is an inverted QR or RSR' that is an inverted QRS
ii=find(AA(2,:)-nanmedian(AA(2,:))<-messages.setup.SLR.tolerance);
QRS{1}(beat,ii)=QRS{2}(beat,ii);
QRS{2}(beat,ii)=QRS{3}(beat,ii);
QRS{3}(beat,ii)=QRS{4}(beat,ii);
QRS{4}(beat,ii)=NaN;
AA=[QRS{1}(beat,:);QRS{2}(beat,:);QRS{3}(beat,:);QRS{4}(beat,:)];
%look for Q waves that should go with R waves
%QS complexes or QR that is an inverted RS
ii=find(AA(1,:)-nanmedian(AA(1,:))>messages.setup.SLR.tolerance);
QRS{4}(beat,ii)=QRS{3}(beat,ii);
QRS{3}(beat,ii)=QRS{2}(beat,ii);
QRS{2}(beat,ii)=QRS{1}(beat,ii);
QRS{1}(beat,ii)=NaN;
AA=[QRS{1}(beat,:);QRS{2}(beat,:);QRS{3}(beat,:);QRS{4}(beat,:)];
%look for R' waves that should go with S waves
ii=find(AA(4,:)-nanmedian(AA(4,:))<-messages.setup.SLR.tolerance);
QRS{1}(beat,ii)=QRS{2}(beat,ii);
QRS{2}(beat,ii)=QRS{3}(beat,ii);
QRS{3}(beat,ii)=QRS{4}(beat,ii);
QRS{4}(beat,ii)=NaN;
AA=[QRS{1}(beat,:);QRS{2}(beat,:);QRS{3}(beat,:);QRS{4}(beat,:)];
marksSLR(beat,mark)=nanmedian(AA');
end
end
for mark=onsets, %onsets
beats=NaN.*ones(nbeats,nmarks);
for g=1:size(ind,2)
if isstruct(marks)
f = getfield(marks, char(leads(g))); %#ok<GFLD>
else
f = marks{g};
end
beats(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),mark);
end
aux= sum(~isnan(beats),2);
for beat=1:nbeats
if aux(beat)>k, % if the mark was found in more than k of the leads
kk = beats(beat,:);
kk(isnan(kk))=[];
kk =sort(kk); % sorted the mark found in the leads in beat
while (length(kk)>k && kk(k+1)>(kk(1)+delta(mark))), %eliminate the first mark until kk satisfy the rule or length(kk)<k
kk(1)=[];
end
%if length(kk)<k there is not a multilead mark
if length(kk)==k
marksSLR(beat,mark)=nan;
else
marksSLR(beat,mark)=kk(1);
end
else
marksSLR(beat,mark)=nan;
end
end
end
for mark=ends, % ends
beats=NaN.*ones(nbeats,nmarks);
for g=1:size(ind,2)
if isstruct(marks)
f = getfield(marks, char(leads(g))); %#ok<GFLD>
else
f = marks{g};
end
beats(~isnan(ind(:,g)),g)=f(ind(~isnan(ind(:,g)),g),mark);
end
aux= sum(~isnan(beats),2);
for beat=1:nbeats
if aux(beat)>k, %
kk = beats(beat,:);
kk(isnan(kk))=[];
kk =flipud(sort(kk)')'; %Rute 19AB2010
while (length(kk)>k && kk(k+1)<(kk(1)-delta(mark))),
kk(1)=[];
end
if length(kk)==k
marksSLR(beat,mark)=nan;
else
marksSLR(beat,mark)=kk(1);
end
else
marksSLR(beat,mark)=nan;
end
end
end