Noninvasive Fetal ECG: The PhysioNet/Computing in Cardiology Challenge 2013 1.0.0
(193,207 bytes)
% function% [A,FilteredECG,chann,Rmaterni,delay,MQRS,FQRS,fetal_QRSAnn_est,QT_Interval] = physionet2013(tm,ECG)
function [fetal_QRSAnn_est,QT_Interval] = physionet2013(tm,ECG)
% fetal_QRSAnn_est=ones(1,50);
QT_Interval = 0;
%%c'è correttore periodicità picchi fetali e correttore posizione sul picco
%% SOLO DUE TEMPLATE, LAVORO A 1000HZ, allineo sulla massima correlazione,
%% nuovo correttore periodicità
%%CORRETTA CORREZIONE PERIODICITà
%facciamo riferimento a occorrenze_finali (quelle effettive post fusione)
%invece che a quelle immaginate come somma dei due template fusi
%rispetto alla prima sottomissione variazione del metodo di identificazione
%del picco nell'intorno trovato. Al posto della semplice QRS detection
%nuovo tentativo di wavelet come per la rimozione della madre: per il feto
%si potrebbe provare ad abbassare la soglia di correlazione di fusione dei
%template?
% Template algorithm for Physionet/CinC competition 2013. This function can
% be used for events 1 and 2. Participants are free to modify any
% components of the code. However the function prototype must stay the
% same:
%
% [fetal_QRSAnn_est,QT_Interval] = physionet2013(tm,ECG) where the inputs and outputs are specified
% below.
%
% inputs:
% ECG: 4x60000 (4 channels and 1min of signal at 1000Hz) matrix of
% abdominal ECG channels.
% tm : Nx1 vector of time in milliseconds
% output:
% FQRS: FQRS markers in seconds. Each marker indicates the position of one
% of the FQRS detected by the algorithm.
% QT_Interval: 1x1 estimated fetal QT duration (enter NaN or 0 if you do wish to calculate)
%
%
% Author: Joachim Behar - IPMG Oxford (joachim.behar@eng.ox.ac.uk)
% Last updated: March 3, 2013 Ikaro Silva
% ---- check size of ECG ----
if size(ECG,1)>size(ECG,2)
ECG = ECG';
end
fs = 1000; % sampling frequency
N = size(ECG,2); % number of abdominal channels
debug = 0; % enter debug mode?
% ---- preprocessing ----
[FilteredECG, original_d] = preprocessing(ECG,fs);
% save(['ECG250_' num2str(segnale)],'FilteredECG')
%ALGORITMO DI QRS DETECTION SU TUTTI I CANALI
start_delay=1;
numero_intervalli=3; %numero che dia intero dividendo 60000
dim_intervallo=floor(length(FilteredECG(1,:))/numero_intervalli);
MQRS1=[];
MQRS2=[];
MQRS3=[];
MQRS4=[];
Apost1=zeros(2*numero_intervalli, 50*4);
Apost2=zeros(2*numero_intervalli, 50*4);
Apost3=zeros(2*numero_intervalli, 50*4);
Apost4=zeros(2*numero_intervalli, 50*4);
occorrenze_finali1=zeros(2,1);
occorrenze_finali2=zeros(2,1);
occorrenze_finali3=zeros(2,1);
occorrenze_finali4=zeros(2,1);
noise=[0,0,0,0];
% soglia_incl=(dim_intervallo/250)/2;
% soglia_incl=round(soglia_incl);
for di=1:numero_intervalli
[Ttotpost1,Ttot1,MQRS,Apost,Nt1,occorrenze_finali]=PeakDetection...
(FilteredECG(1,(di-1)*dim_intervallo+1:di*dim_intervallo), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(1,:)), 100, 50*4, 0,0.85,0.8,0.8,original_d(1,4*((di-1)*dim_intervallo)+1:4*(di*dim_intervallo)));
if(occorrenze_finali(1)==0)
noise(1)=1;
end
if(noise(1)==0)
dimx=0;
if(length(occorrenze_finali)==1)
dimx=1;
else
r=pearsoncoeff(Apost(1,:),Apost(2,:));
if(r>0.7) %sono due template della stessa classe
occorrenze_finali(2)=0;
MQRS(2,:)=zeros(1,length(MQRS(1,:)));
Apost(2,:)=zeros(1,length(Apost(1,:)));
end
end
if(di==1)
if(dimx==1)
occorrenze_finali=[occorrenze_finali; 0];
MQRS=[MQRS; zeros(1,length(MQRS))];
end
MQRS1=MQRS;
Apost1=Apost;
occorrenze_finali1=occorrenze_finali;
else
if(dimx==1)
% if(sum(Apost(1,:))==0)
% Apost(1,:)=Apost(2,:);
% Apost(2,:)=zeros(1,length(Apost(1,:)));
% end
r1=pearsoncoeff(Apost(1,:),Apost1(end-1,:));
r2=pearsoncoeff(Apost(1,:),Apost1(end,:));
if(isnan(r1))
r1=-2;
end
if(isnan(r2))
r2=-2;
end
if(r1>r2)
MQRS1=[MQRS1, [(MQRS+(di-1)*4*dim_intervallo); zeros(1,length(MQRS))]];
Apost1=[Apost1; Apost];
occorrenze_finali1=[occorrenze_finali1, [occorrenze_finali; 0]];
else
MQRS1=[MQRS1, [zeros(1,length(MQRS)); (MQRS+(di-1)*4*dim_intervallo)]];
Apost1=[Apost1; Apost(2,:);Apost(1,:)];
occorrenze_finali1=[occorrenze_finali1, [0; occorrenze_finali]];
end
else
%correlazione template 1 con il precedente 1 e con il
%precedente 2
r(1)=pearsoncoeff(Apost(1,:),Apost1(end-1,:));
r(2)=pearsoncoeff(Apost(1,:),Apost1(end,:));
%correlazione del template 2 con il precedente 1 e con il
%precedente 2
r(3)=pearsoncoeff(Apost(2,:),Apost1(end-1,:));
r(4)=pearsoncoeff(Apost(2,:),Apost1(end,:));
for uh=1:4
if(isnan(r(uh)))
r(uh)=-2;
end
end
[masr,indr]=max(r);
if((indr==2)||(indr==3))
tempo=MQRS(1,:);
MQRS(1,:)=MQRS(2,:);
MQRS(2,:)=tempo;
tempo=Apost(1,:);
Apost(1,:)=Apost(2,:);
Apost(2,:)=tempo;
tempo=occorrenze_finali(1);
occorrenze_finali(1)=occorrenze_finali(2);
occorrenze_finali(2)=tempo;
end
MQRS1=[MQRS1, (MQRS+(di-1)*4*dim_intervallo)];
Apost1=[Apost1; Apost];
occorrenze_finali1=[occorrenze_finali1, occorrenze_finali];
end
end
end
% figure
% plot(Apost(1,:))
% if(length(occorrenze_finali)>1)
% hold on
% plot(Apost(2,:),'r')
% title(['1 template 1 blu, occ: ' num2str(occorrenze_finali1(1)) 'battiti media: ' num2str(Ttotpost1(1)) 'template 2 rosso,occ:' num2str(occorrenze_finali1(2)) 'battiti media: ' num2str(Ttotpost1(2))])
% end
%
[Ttotpost2,Ttot2,MQRS,Apost,Nt2,occorrenze_finali]=PeakDetection...
(FilteredECG(2,(di-1)*dim_intervallo+1:di*dim_intervallo), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(2,:)), 100, 50*4, 0,0.85,0.8,0.8,original_d(2,4*((di-1)*dim_intervallo)+1:4*(di*dim_intervallo)));
if(occorrenze_finali(1)==0)
noise(2)=1;
end
if(noise(2)==0)
dimx=0;
if(length(occorrenze_finali)==1)
dimx=1;
else
r=pearsoncoeff(Apost(1,:),Apost(2,:));
if(r>0.7) %sono due template della stessa classe
occorrenze_finali(2)=0;
MQRS(2,:)=zeros(1,length(MQRS(1,:)));
Apost(2,:)=zeros(1,length(Apost(1,:)));
end
end
if(di==1)
if(dimx==1)
occorrenze_finali=[occorrenze_finali; 0];
MQRS=[MQRS; zeros(1,length(MQRS))];
end
MQRS2=MQRS;
Apost2=Apost;
occorrenze_finali2=occorrenze_finali;
else
if(dimx==1)
% if(sum(Apost(1,:))==0)
% Apost(1,:)=Apost(2,:);
% Apost(2,:)=zeros(1,length(Apost(1,:)));
% end
r1=pearsoncoeff(Apost(1,:),Apost2(end-1,:));
r2=pearsoncoeff(Apost(1,:),Apost2(end,:));
if(isnan(r1))
r1=-2;
end
if(isnan(r2))
r2=-2;
end
if(r1>r2)
MQRS2=[MQRS2, [(MQRS+(di-1)*4*dim_intervallo); zeros(1,length(MQRS))]];
Apost2=[Apost2; Apost];
occorrenze_finali2=[occorrenze_finali2, [occorrenze_finali; 0]];
else
MQRS2=[MQRS2, [zeros(1,length(MQRS)); (MQRS+(di-1)*4*dim_intervallo)]];
Apost2=[Apost2; Apost(2,:);Apost(1,:)];
occorrenze_finali2=[occorrenze_finali2, [0; occorrenze_finali]];
end
else
%correlazione template 1 con il precedente 1 e con il
%precedente 2
r(1)=pearsoncoeff(Apost(1,:),Apost2(end-1,:));
r(2)=pearsoncoeff(Apost(1,:),Apost2(end,:));
%correlazione del template 2 con il precedente 1 e con il
%precedente 2
r(3)=pearsoncoeff(Apost(2,:),Apost2(end-1,:));
r(4)=pearsoncoeff(Apost(2,:),Apost2(end,:));
for uh=1:4
if(isnan(r(uh)))
r(uh)=-2;
end
end
[masr,indr]=max(r);
if((indr==2)||(indr==3))
tempo=MQRS(1,:);
MQRS(1,:)=MQRS(2,:);
MQRS(2,:)=tempo;
tempo=Apost(1,:);
Apost(1,:)=Apost(2,:);
Apost(2,:)=tempo;
tempo=occorrenze_finali(1);
occorrenze_finali(1)=occorrenze_finali(2);
occorrenze_finali(2)=tempo;
end
MQRS2=[MQRS2, (MQRS+(di-1)*4*dim_intervallo)];
Apost2=[Apost2; Apost];
occorrenze_finali2=[occorrenze_finali2, occorrenze_finali];
end
end
end
% figure
% plot(Apost(1,:))
% if(length(occorrenze_finali)>1)
% hold on
% plot(Apost(2,:),'r')
% title(['2 template 1 blu, occ: ' num2str(occorrenze_finali2(1)) 'battiti media: ' num2str(Ttotpost2(1)) 'template 2 rosso,occ:' num2str(occorrenze_finali2(2)) 'battiti media: ' num2str(Ttotpost2(2))])
% end
[Ttotpost3,Ttot3,MQRS,Apost,Nt3,occorrenze_finali]=PeakDetection...
(FilteredECG(3,(di-1)*dim_intervallo+1:di*dim_intervallo), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(3,:)), 100, 50*4, 0,0.85,0.8,0.8,original_d(3,4*((di-1)*dim_intervallo)+1:4*(di*dim_intervallo)));
if(occorrenze_finali(1)==0)
noise(3)=1;
end
if(noise(3)==0)
dimx=0;
if(length(occorrenze_finali)==1)
dimx=1;
else
r=pearsoncoeff(Apost(1,:),Apost(2,:));
if(r>0.7) %sono due template della stessa classe
occorrenze_finali(2)=0;
MQRS(2,:)=zeros(1,length(MQRS(1,:)));
Apost(2,:)=zeros(1,length(Apost(1,:)));
end
end
if(di==1)
if(dimx==1)
occorrenze_finali=[occorrenze_finali; 0];
MQRS=[MQRS; zeros(1,length(MQRS))];
end
MQRS3=MQRS;
Apost3=Apost;
occorrenze_finali3=occorrenze_finali;
else
if(dimx==1)
% if(sum(Apost(1,:))==0)
% Apost(1,:)=Apost(2,:);
% Apost(2,:)=zeros(1,length(Apost(1,:)));
% end
r1=pearsoncoeff(Apost(1,:),Apost3(end-1,:));
r2=pearsoncoeff(Apost(1,:),Apost3(end,:));
if(isnan(r1))
r1=-2;
end
if(isnan(r2))
r2=-2;
end
if(r1>r2)
MQRS3=[MQRS3, [(MQRS+(di-1)*4*dim_intervallo); zeros(1,length(MQRS))]];
Apost3=[Apost3; Apost];
occorrenze_finali3=[occorrenze_finali3, [occorrenze_finali; 0]];
else
MQRS3=[MQRS3, [zeros(1,length(MQRS)); (MQRS+(di-1)*4*dim_intervallo)]];
Apost3=[Apost3; Apost(2,:);Apost(1,:)];
occorrenze_finali3=[occorrenze_finali3, [0; occorrenze_finali]];
end
else
%correlazione template 1 con il precedente 1 e con il
%precedente 2
r(1)=pearsoncoeff(Apost(1,:),Apost3(end-1,:));
r(2)=pearsoncoeff(Apost(1,:),Apost3(end,:));
%correlazione del template 2 con il precedente 1 e con il
%precedente 2
r(3)=pearsoncoeff(Apost(2,:),Apost3(end-1,:));
r(4)=pearsoncoeff(Apost(2,:),Apost3(end,:));
for uh=1:4
if(isnan(r(uh)))
r(uh)=-2;
end
end
[masr,indr]=max(r);
if((indr==2)||(indr==3))
tempo=MQRS(1,:);
MQRS(1,:)=MQRS(2,:);
MQRS(2,:)=tempo;
tempo=Apost(1,:);
Apost(1,:)=Apost(2,:);
Apost(2,:)=tempo;
tempo=occorrenze_finali(1);
occorrenze_finali(1)=occorrenze_finali(2);
occorrenze_finali(2)=tempo;
end
MQRS3=[MQRS3, (MQRS+(di-1)*4*dim_intervallo)];
Apost3=[Apost3; Apost];
occorrenze_finali3=[occorrenze_finali3, occorrenze_finali];
end
end
end
% figure
% plot(Apost(1,:))
% if(length(occorrenze_finali)>1)
% hold on
% plot(Apost(2,:),'r')
% title(['3 template 1 blu, occ: ' num2str(occorrenze_finali3(1)) 'battiti media: ' num2str(Ttotpost3(1)) 'template 2 rosso,occ:' num2str(occorrenze_finali3(2)) 'battiti media: ' num2str(Ttotpost3(2))])
%
% end
[Ttotpost4,Ttot4,MQRS,Apost,Nt4,occorrenze_finali]=PeakDetection...
(FilteredECG(4,(di-1)*dim_intervallo+1:di*dim_intervallo), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(4,:)), 100, 50*4, 0,0.85,0.8,0.8,original_d(4,4*((di-1)*dim_intervallo)+1:4*(di*dim_intervallo)));
if(occorrenze_finali(1)==0)
noise(4)=1;
end
if(noise(4)==0)
dimx=0;
if(length(occorrenze_finali)==1)
dimx=1;
else
r=pearsoncoeff(Apost(1,:),Apost(2,:));
if(r>0.7) %sono due template della stessa classe
occorrenze_finali(2)=0;
MQRS(2,:)=zeros(1,length(MQRS(1,:)));
Apost(2,:)=zeros(1,length(Apost(1,:)));
end
end
if(di==1)
if(dimx==1)
occorrenze_finali=[occorrenze_finali; 0];
MQRS=[MQRS; zeros(1,length(MQRS))];
end
MQRS4=MQRS;
Apost4=Apost;
occorrenze_finali4=occorrenze_finali;
else
if(dimx==1)
% if(sum(Apost(1,:))==0)
% Apost(1,:)=Apost(2,:);
% Apost(2,:)=zeros(1,length(Apost(1,:)));
% end
r1=pearsoncoeff(Apost(1,:),Apost4(end-1,:));
r2=pearsoncoeff(Apost(1,:),Apost4(end,:));
if(isnan(r1))
r1=-2;
end
if(isnan(r2))
r2=-2;
end
if(r1>r2)
MQRS4=[MQRS4, [(MQRS+(di-1)*4*dim_intervallo); zeros(1,length(MQRS))]];
Apost4=[Apost4; Apost];
occorrenze_finali4=[occorrenze_finali4, [occorrenze_finali; 0]];
else
MQRS4=[MQRS4, [zeros(1,length(MQRS)); (MQRS+(di-1)*4*dim_intervallo)]];
Apost4=[Apost4; Apost(2,:);Apost(1,:)];
occorrenze_finali4=[occorrenze_finali4, [0; occorrenze_finali]];
end
else
%correlazione template 1 con il precedente 1 e con il
%precedente 2
r(1)=pearsoncoeff(Apost(1,:),Apost4(end-1,:));
r(2)=pearsoncoeff(Apost(1,:),Apost4(end,:));
%correlazione del template 2 con il precedente 1 e con il
%precedente 2
r(3)=pearsoncoeff(Apost(2,:),Apost4(end-1,:));
r(4)=pearsoncoeff(Apost(2,:),Apost4(end,:));
for uh=1:4
if(isnan(r(uh)))
r(uh)=-2;
end
end
[masr,indr]=max(r);
if((indr==2)||(indr==3))
tempo=MQRS(1,:);
MQRS(1,:)=MQRS(2,:);
MQRS(2,:)=tempo;
tempo=Apost(1,:);
Apost(1,:)=Apost(2,:);
Apost(2,:)=tempo;
tempo=occorrenze_finali(1);
occorrenze_finali(1)=occorrenze_finali(2);
occorrenze_finali(2)=tempo;
end
MQRS4=[MQRS4, (MQRS+(di-1)*4*dim_intervallo)];
Apost4=[Apost4; Apost];
occorrenze_finali4=[occorrenze_finali4, occorrenze_finali];
end
end
end
% figure
% plot(Apost(1,:))
% if(length(occorrenze_finali)>1)
% hold on
% plot(Apost(2,:),'r')
% title(['4 template 1 blu, occ: ' num2str(occorrenze_finali4(1)) 'battiti media: ' num2str(Ttotpost4(1)) 'template 2 rosso,occ:' num2str(occorrenze_finali4(2)) 'battiti media: ' num2str(Ttotpost4(2))])
% end
end
occorrenze_finali1=sum(occorrenze_finali1,2);
occorrenze_finali2=sum(occorrenze_finali2,2);
occorrenze_finali3=sum(occorrenze_finali3,2);
occorrenze_finali4=sum(occorrenze_finali4,2);
% figure
% h=original_d(1,:);
% plot(original_d(1,:))
% hold on
% plot(MQRS1(1,:),h(MQRS1(1,:)),'*r')
%%
%%%valutazione canali rumorosi
th_rum=20; %soglia per individuare canali troppo rumorosi con il template matching
fin_occ=[max(occorrenze_finali1), max(occorrenze_finali2), max(occorrenze_finali3), max(occorrenze_finali4)];
% for ly=1:4
% if fin_occ(ly)<th_rum;
% fin_occ(ly)=0;
% end
% end
canali_no_rumore=find(fin_occ>0);
canali_rumore=find(fin_occ==0);
if(isempty(canali_rumore))
canali_rumore=[0];
end
if(noise(1)==0)
temp1=[Apost1(1,:);Apost1(3,:); Apost1(5,:)];
temp2=[Apost1(2,:);Apost1(4,:); Apost1(6,:)];
Apost1(1:3,:)=temp1;
Apost1(4:6,:)=temp2;
end
if(noise(2)==0)
temp1=[Apost2(1,:);Apost2(3,:); Apost2(5,:)];
temp2=[Apost2(2,:);Apost2(4,:); Apost2(6,:)];
Apost2(1:3,:)=temp1;
Apost2(4:6,:)=temp2;
end
if(noise(3)==0)
temp1=[Apost3(1,:);Apost3(3,:); Apost3(5,:)];
temp2=[Apost3(2,:);Apost3(4,:); Apost3(6,:)];
Apost3(1:3,:)=temp1;
Apost3(4:6,:)=temp2;
end
if(noise(4)==0)
temp1=[Apost4(1,:);Apost4(3,:); Apost4(5,:)];
temp2=[Apost4(2,:);Apost4(4,:); Apost4(6,:)];
Apost4(1:3,:)=temp1;
Apost4(4:6,:)=temp2;
end
% figure
% plot(Apost4(1,:))
% hold on
% plot(Apost4(2,:))
% plot(Apost4(3,:))
% figure
% plot(Apost4(4,:))
% hold on
% plot(Apost4(5,:))
% plot(Apost4(6,:))
%% QRS DETECTOR PER TROVARE POSIZIONE BATTITI MATERNI %250Hz
% [qrs1]= balda(FilteredECG(1,:),1);
[qrs1]= balda(FilteredECG(1,:),0);
[qrs2]= balda(FilteredECG(2,:),0);
[qrs3]= balda(FilteredECG(3,:),0);
[qrs4]= balda(FilteredECG(4,:),0);
y=FilteredECG(1,:);
%% creazione sequenze di classi
[mark1] = match(qrs1*4, MQRS1, 15*4);
[mark2] = match(qrs2*4, MQRS2, 15*4);
[mark3] = match(qrs3*4, MQRS3, 15*4);
[mark4] = match(qrs4*4, MQRS4, 15*4);
%% ANALISI DELLA PERIODICITà PER SCEGLIERE IL CANALE MATERNO
th_periodicity=40;
forget=1/4;
delay=0;
% [occtmp1,occchk1,RRm1,count_removed1,count_added1,noise1]=periodicity_correction_v2(qrs1,length(y),th_periodicity,forget, delay);
% [occtmp2,occchk2,RRm2,count_removed2,count_added2,noise2]=periodicity_correction_v2(qrs2,length(y),th_periodicity,forget, delay);
% [occtmp3,occchk3,RRm3,count_removed3,count_added3,noise3]=periodicity_correction_v2(qrs3,length(y),th_periodicity,forget, delay);
% [occtmp4,occchk4,RRm4,count_removed4,count_added4,noise4]=periodicity_correction_v2(qrs4,length(y),th_periodicity,forget, delay);
[occtmp1,occchk1,RRm1,count_removed1,count_added1,noise1]=periodicity_cor_caller...
(FilteredECG(1,:),mark1,qrs1,length(y),th_periodicity,forget, delay);
[occtmp2,occchk2,RRm2,count_removed2,count_added2,noise2]=periodicity_cor_caller...
(FilteredECG(2,:),mark2,qrs2,length(y),th_periodicity,forget, delay);
[occtmp3,occchk3,RRm3,count_removed3,count_added3,noise3]=periodicity_cor_caller...
(FilteredECG(3,:),mark3,qrs3,length(y),th_periodicity,forget, delay);
[occtmp4,occchk4,RRm4,count_removed4,count_added4,noise4]=periodicity_cor_caller...
(FilteredECG(4,:),mark4,qrs4,length(y),th_periodicity,forget, delay);
RRm=[RRm1, RRm2, RRm3, RRm4];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%
% NOTA
% per la scelta del canale io farei così: per quelli che non sono noise,
% cercherei quelli con RRm simile e alto (madre), poi sceglierei sulla base
% del numero di correzioni fatte. Le soglie che metti sotto sono troppo
% basse. Inoltre metterei un miglior QRS detector (magari con un matched
% filtro un po' più largo, perché il balda che fai mi pare un po' una
% porcheria (gli piace molto più il feto che la mamma. Il problema del
% template sul segnale 3 io non riesco a vederlo proprio. Inoltre ho notato
% che su un segnale i due template sono entrambi materni e anche molto
% simili. Potremmo provare ad abbassare un po' la soglia di correlazione
% (non molto) perché è strano che non si fondano. Inoltre per quello che
% vedo io non dovrebbe essere molto difficile capire chi è feto e chi
% madre...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%
%% SCELTA CANALE MATERNO
cont_tot=zeros(4,1);
cont_tot(1)=count_removed1+1.5*count_added1; %peso di più gli aggiunti
cont_tot(2)=count_removed2+1.5*count_added2;
cont_tot(3)=count_removed3+1.5*count_added3;
cont_tot(4)=count_removed4+1.5*count_added4;
numero_picchi=[length(occtmp1);length(occtmp2);length(occtmp3);length(occtmp4)];
etichetta_picchi=[1,2,3,4];
u=1;
while u<4
if((numero_picchi(u)<45)||cont_tot(u)>50)
numero_picchi(u)=[];
etichetta_picchi(u)=[];
cont_tot(u)=[];
else
u=u+1;
end
if(u>length(numero_picchi))
break;
end
end
if(isempty(numero_picchi))
madre=1;
elseif(length(numero_picchi)==1)
madre=etichetta_picchi(1);
else
media_picchi=mean(numero_picchi);
test=abs(numero_picchi-media_picchi*ones(length(numero_picchi),1));
massimo_picchi=max(test);
due_classi=0;
if(massimo_picchi>5)
due_classi=1;
end
if(due_classi==0)
[minimo,ind_min]=min(cont_tot);
madre=etichetta_picchi(ind_min);
else
classe1=etichetta_picchi(1);
num_classe1=numero_picchi(1);
classe2=[];
num_classe2=[];
for zj=2:length(numero_picchi)
if(abs(num_classe1(1)-numero_picchi(zj))<5)
classe1=[classe1, etichetta_picchi(zj)];
num_classe1=[num_classe1, numero_picchi(zj)];
else
classe2=[classe2, etichetta_picchi(zj)];
num_classe2=[num_classe2, numero_picchi(zj)];
end
end
media1=mean(num_classe1);
media2=mean(num_classe2);
if(media1<media2)
errori_classe1=[];
for lk=1:length(classe1)
errori_classe1=[errori_classe1, cont_tot(classe1(lk))];
[min_err, ind_min_err]=min(errori_classe1);
madre=classe1(ind_min_err);
end
else
errori_classe2=[];
for lk=1:length(classe2)
errori_classe2=[errori_classe2, cont_tot(classe2(lk))];
[min_err, ind_min_err]=min(errori_classe2);
madre=classe2(ind_min_err);
end
end
end
end
RRmM=RRm(madre);
% % cont_tot
% minimo=100000;
% for u=1:4
% if cont_tot(u)<10
% if((numero_picchi(u)<=minimo)&&(numero_picchi(u)>45))
% madre=u;
% minimo=numero_picchi(u);
% end
% end
% end
% [val,madre]=min(cont_tot);
switch(madre)
case 1
battiti_materni=occtmp1;
case 2
battiti_materni=occtmp2;
case 3
battiti_materni=occtmp3;
case 4
battiti_materni=occtmp4;
end
% figure
% subplot(4,1,1)
% y=FilteredECG(1,:);
% plot(y)
% hold on
% plot(battiti_materni,y(battiti_materni),'*r')
% title(['canale scelto ' num2str(madre)])
% subplot(4,1,2)
% y=FilteredECG(2,:);
% plot(y)
% hold on
% plot(battiti_materni,y(battiti_materni),'*r')
% subplot(4,1,3)
% y=FilteredECG(3,:);
% plot(y)
% hold on
% plot(battiti_materni,y(battiti_materni),'*r')
% subplot(4,1,4)
% y=FilteredECG(4,:);
% plot(y)
% hold on
% plot(battiti_materni,y(battiti_materni),'*r')
%%inserisci formula per pesare meno count_removed rispetto a count_added?
%% SOTTRAZIONE DEL CANALE MATERNO
%% FASE 1. SCELTA DEL TEMPLATE MATERNO IN OGNI CANALE
battiti_materni=4*battiti_materni; %riferiti a 1000Hz
[r,c]=size(MQRS1);
if (r>1)
[template1]=scelta_template(battiti_materni, MQRS1);
else
template1=1;
end
[r,c]=size(MQRS2);
if (r>1)
[template2]=scelta_template(battiti_materni, MQRS2);
else
template2=1;
end
[r,c]=size(MQRS3);
if (r>1)
[template3]=scelta_template(battiti_materni, MQRS3);
else
template3=1;
end
[r,c]=size(MQRS4);
if (r>1)
[template4]=scelta_template(battiti_materni, MQRS4);
else
template4=1;
end
%% FASE 3.SOTTRAZIONE TEMPLATE MEDIO DI OGNI CANALE
% ---- channel selection or combination prior FQRS detection ----
% [chann] = ChannelSelectionOrCombination(occorrenze_finali1,occorrenze_finali2, occorrenze_finali3,occorrenze_finali4); %non dovrebbe usare num_occ ma occorrenze_finali che sono quelle VERE dopo la fusione e la riduzione dei template. Attenzione che Apost è ordinato secondo num_occ
% ---- MECG cancellation ----
% for i=1:N % run algorithm for each channel
% FECG(:,i) = MECGcancellation(MQRS,FilteredECG(:,i)',fs,20);
% end
if(noise(1)==0)
[FECG1]=MECGcancellation(original_d(1,:),battiti_materni, Apost1, template1);
else
FECG1=(original_d(1,:));
end
if(noise(2)==0)
[FECG2]=MECGcancellation(original_d(2,:),battiti_materni, Apost2, template2);
else
FECG2=(original_d(2,:));
end
if(noise(3)==0)
[FECG3]=MECGcancellation(original_d(3,:),battiti_materni, Apost3, template3);
else
FECG3=(original_d(3,:));
end
if(noise(4)==0)
[FECG4]=MECGcancellation(original_d(4,:),battiti_materni, Apost4, template4);
else
FECG4=(original_d(4,:));
end
FECG=[FECG1; FECG2; FECG3; FECG4];
for tk=1:4
temp=resample(FECG(tk,:)',250,1000);
FECG_down(tk,:)=temp';
end
% save FECG.mat
% save(['FECG' num2str(segnale)],'FECG')
% finestra_feto=24;
FECG1_down=resample(FECG1',250,1000);
FECG1_down=FECG1_down';
if(noise(1)==0)
[Ttotpost1,Ttot1,MQRS1,Apost1,Nt1,occorrenze_finali1]=PeakDetection...
(FECG_down(1,:), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(1,:)), 100, 200, 0,0.8,0.8,0.75,FECG1);
end
if(noise(2)==0)
[Ttotpost2,Ttot2,MQRS2,Apost2,Nt2,occorrenze_finali2]=PeakDetection...
(FECG_down(2,:), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(2,:)), 100, 200, 0,0.8,0.8,0.75,FECG2);
end
if(noise(3)==0)
[Ttotpost3,Ttot3,MQRS3,Apost3,Nt3,occorrenze_finali3]=PeakDetection...
(FECG_down(3,:), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(3,:)), 100, 200, 0,0.8,0.8,0.75,FECG3);
end
if(noise(4)==0)
[Ttotpost4,Ttot4,MQRS4,Apost4,Nt41,occorrenze_finali4]=PeakDetection...
(FECG_down(4,:), 'bior6.8', 3, 1, 2500, 1, 'h', 1, 0, 0, 0, 1, [], 10*length(FilteredECG(4,:)), 100, 200, 0,0.8,0.8,0.75,FECG4);
end
[qrs1]=balda(FECG_down(1,:),1);
[qrs2]=balda(FECG_down(2,:),1);
[qrs3]=balda(FECG_down(3,:),1);
[qrs4]=balda(FECG_down(4,:),1);
%% periodicity_cor_callerFETUS;
%% creazione sequenze di classi
[mark1] = match(qrs1*4, MQRS1, 15*4);
[mark2] = match(qrs2*4, MQRS2, 15*4);
[mark3] = match(qrs3*4, MQRS3, 15*4);
[mark4] = match(qrs4*4, MQRS4, 15*4);
%% ANALISI DELLA PERIODICITà PER SCEGLIERE IL CANALE MATERNO
th_periodicity=60;
forget=1/4;
delay=0;
% [occtmp1,occchk1,RRm1,count_removed1,count_added1,noise1]=periodicity_correction_v2(qrs1,length(y),th_periodicity,forget, delay);
% [occtmp2,occchk2,RRm2,count_removed2,count_added2,noise2]=periodicity_correction_v2(qrs2,length(y),th_periodicity,forget, delay);
% [occtmp3,occchk3,RRm3,count_removed3,count_added3,noise3]=periodicity_correction_v2(qrs3,length(y),th_periodicity,forget, delay);
% [occtmp4,occchk4,RRm4,count_removed4,count_added4,noise4]=periodicity_correction_v2(qrs4,length(y),th_periodicity,forget, delay);
[occtmpf1,occchk1,RRmf1,count_removed1,count_added1,noise1]=periodicity_cor_callerFETUS...
(FECG_down(1,:),mark1,qrs1,length(y),th_periodicity,forget, delay);
[occtmpf2,occchk2,RRmf2,count_removed2,count_added2,noise2]=periodicity_cor_callerFETUS...
(FECG_down(2,:),mark2,qrs2,length(y),th_periodicity,forget, delay);
[occtmpf3,occchk3,RRmf3,count_removed3,count_added3,noise3]=periodicity_cor_callerFETUS...
(FECG_down(3,:),mark3,qrs3,length(y),th_periodicity,forget, delay);
[occtmpf4,occchk4,RRmf4,count_removed4,count_added4,noise4]=periodicity_cor_callerFETUS...
(FECG_down(4,:),mark4,qrs4,length(y),th_periodicity,forget, delay);
RRmf=[RRmf1, RRmf2, RRmf3, RRmf4];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cont_tot=zeros(4,1);
cont_tot(1)=count_removed1+1.5*count_added1; %peso di più gli aggiunti
cont_tot(2)=count_removed2+1.5*count_added2;
cont_tot(3)=count_removed3+1.5*count_added3;
cont_tot(4)=count_removed4+1.5*count_added4;
minimo=cont_tot(1);
feto=1;
fh=1;
scelgo=cont_tot;
while(fh>0)
[minimo,feto]=min(cont_tot);
if(abs(RRmf(feto)-RRmM)<5)
canale_materno=0;
switch (feto)
case 1
[canale_materno]=controlla_scelta(battiti_materni,occtmpf1);
case 2
[canale_materno]=controlla_scelta(battiti_materni,occtmpf2);
case 3
[canale_materno]=controlla_scelta(battiti_materni,occtmpf3);
case 4
[canale_materno]=controlla_scelta(battiti_materni,occtmpf4);
end
%becca residuo materno periodico
if(canale_materno==1)
cont_tot(feto)=10000;
else
fh=0;
end
else
fh=0;
end
if(minimo==10000)
[minimo, feto]=min(scelgo);
fh=0;
end
end
switch(feto)
case 1
battiti_fetali=occtmpf1;
battito_medio=Apost1(1,:);
case 2
battiti_fetali=occtmpf2;
battito_medio=Apost2(1,:);
case 3
battiti_fetali=occtmpf3;
battito_medio=Apost3(1,:);
case 4
battiti_fetali=occtmpf4;
battito_medio=Apost4(1,:);
end
%%
if(debug==0)
%% CONTROLLO FREQUENZA MATERNA E FETALE PER EVENTUALE SCAMBIO
% total_delay=delay;
% FQRS=pic_f;
% FQRS=MQRSf(1,:);
FQRS=4*battiti_fetali;
% total_delay=0; %ritardo balda
%% CORREZIONE FETI
% FQRS=FQRS-total_delay;
% FQRS=4*FQRS;
% upsam=resample(FilteredECG(1,:)',1000,250);
% upsam=upsam';
if(max(battito_medio(1,:))==max(abs(battito_medio(1,:))))
%morfologia positiva
morf=1;
else
morf=0;
end
[FQRS]=correggi(FQRS,FECG(feto,:),morf);
% FQRS=corretti;
% pre_FQRS=FQRS;
% pre_FQRS=pre_FQRS;
% FQRS=find(FQRS>1);
% pre_FQRS=pre_FQRS(frs(1):end);
% [FQRS]=correction(upsam,FQRS); %NEL CORREGGERE PROVARE A USARE IL SEGNALE ORIGINALE, NON QUELLO PULITO PER VEDERE SE MIGLIORA
% FQRS=FQRS; %@1000Hz
z=find(FQRS>1);
FQRS=FQRS(z(1):end);
fetal_QRSAnn_est= round(1000*FQRS'/fs);
QT_Interval = 0;
end
end
function[canale_materno]=controlla_scelta(battiti_materni, feto)
qrs_1=feto;
canale_materno=0;
soglia_val=20;
zi=1;
contatore_1=0;
while (zi<length(battiti_materni))
zj=1;
while(zj<length(qrs_1))
if(abs(qrs_1(zj)- battiti_materni(zi))<=soglia_val)
contatore_1= contatore_1 + 1;
qrs_1(zj)=[];
break;
end
zj=zj+1;
end
zi=zi+1;
end
if(contatore_1>=0.8*length(battiti_materni))
canale_materno=1;
end
end
function [corretti]=correggi(pic_f,YA,morf)
corretti=pic_f;
stimato=0;
indice_stimato=0;
incrementa=1;
for zm=1:length(pic_f)
stimato=0;
indice_stimato=0;
incrementa=1;
if(morf==1)
id=0;
start=pic_f(zm)-25;
if((start-8>0)&&(start+51+8<length(YA)))
while(id<50)
contat=0;
for lt=1:8
if((YA(start+id)>=YA(start+id-lt))&&(YA(start+id)>=YA(start+id+lt)))
contat=contat+1;
end
end
if(contat==8)
stimato(incrementa)=YA(start+id);
indice_stimato(incrementa)=start+id;
incrementa=incrementa+1;
end
id=id+1;
end
else
id=0;
start=pic_f(zm)-25;
if((start-8>0)&&(start+51+8<length(YA)))
while(id<200)
contat=0;
for lt=1:8
if((YA(start+id)<=YA(start+id-lt))&&(YA(start+id)<=YA(start+id+lt)))
contat=contat+1;
end
end
if(contat==8)
stimato(incrementa)=YA(start+id);
indice_stimato(incrementa)=start+id;
incrementa=incrementa+1;
end
id=id+1;
end
end
end
end
if(incrementa>1)
[tr,fr]=max(abs(stimato));
corretti(zm)=indice_stimato(fr);
end
end
end
%% confronto con la madre per escludere se troppo simile
function[residui_materni]=escludi(qrs1,qrs2,qrs3,qrs4, mqrs)
soglia_val=20;
zi=1;
l1=length(qrs1);
l2=length(qrs2);
l3=length(qrs3);
l4=length(qrs4);
contatore_1=0;
contatore_2=0;
contatore_3=0;
contatore_4=0;
residui_materni=[];
while (zi<length(qrs1))
zj=1;
incremento=1;
while(zj<length(mqrs))
if(abs(qrs1(zi)- mqrs(zj))<=soglia_val)
contatore_1= contatore_1 + 1;
qrs1(zi)=[];
incremento=0;
break;
end
zj=zj+1;
end
zi=zi+incremento;
end
if(contatore_1>0.5*l1)
residui_materni=[residui_materni 1];
end
zi=1;
while (zi<length(qrs2))
zj=1;
incremento=1;
while(zj<length(mqrs))
if(abs(qrs2(zi)- mqrs(zj))<=soglia_val)
contatore_2= contatore_2 + 1;
qrs2(zi)=[];
incremento=0;
break;
end
zj=zj+1;
end
zi=zi+incremento;
end
if(contatore_2>0.5*l2)
residui_materni=[residui_materni 2];
end
zi=1;
while (zi<length(qrs3))
zj=1;
incremento=1;
while(zj<length(mqrs))
if(abs(qrs3(zi)- mqrs(zj))<=soglia_val)
contatore_3= contatore_3 + 1;
qrs3(zi)=[];
incremento=0;
break;
end
zj=zj+1;
end
zi=zi+incremento;
end
if(contatore_3>0.5*l3)
residui_materni=[residui_materni 3];
end
zi=1;
while (zi<length(qrs4))
zj=1;
incremento=1;
while(zj<length(mqrs))
if(abs(qrs4(zi)- mqrs(zj))<=soglia_val)
contatore_4= contatore_4 + 1;
qrs4(zi)=[];
incremento=0;
break;
end
zj=zj+1;
end
zi=zi+incremento;
end
if(contatore_4>0.5*l4)
residui_materni=[residui_materni 4];
end
if(length(residui_materni)==4)
[fg,ni]=min([contatore_1, contatore_2, contatore_3, contatore_4]);
residui_materni(ni)=[];
end
end
%% periodicity correction con tolleranza molto alta, scelgo il migliore
function[qrs,qrs1,qrs2,qrs3,qrs4]=balda_feto(x,delay,fat)
[righe,colonne]=size(x);
qrs=0;
qrs1=0;
qrs2=0;
qrs3=0;
qrs4=0;
b0 = [1 0 -1];
a0 = 1;
b1 = [1 0 -2 0 1];
a1 = 1;
bs = 1/8*ones(1,8);
as = 1;
for jn=1:righe
y0(jn,:)=filter(b0,a0,x(jn,:));
y0(jn,:)=abs(y0(jn,:));
y1(jn,:)=filter(b1,a1,x(jn,:));
y1(jn,:)=abs(y1(jn,:));
y0(jn,:) = [0,y0(jn,1:end-1)]; % vedere dispense a pag. 60
% y2(jn,:) = 1.3*y0(jn,:) + 1.1*y1(jn,:);
y2(jn,:) = 1.1*y0(jn,:) + 1.9*y1(jn,:);
y3(jn,:)=filter(bs,as,y2(jn,:));
end
if(righe>1)
yt=sum(y2(:,:));
else
yt=y2;
end
ys = filter(bs,as,yt);
% Introduco un ritardo 4, che si accumula al ritardo 2 precedente
% vedere dispense a pag. 61
% ritardo finale = 6.
% Esempio di blanking per evitare rilevazioni multiple
% M = max(ys);
nu=floor(length(ys)/250);
soglia=zeros(1,length(ys));
soglias=zeros(righe,length(ys));
for t=1:nu-3
soglia((t-1)*250 +1 : t*250) = 0.5* max(ys((t-1)*250 +1 : ((t+3)*250))); % la soglia è il 60% del massimo del segnale
for jk=1:righe
soglias(jk,(t-1)*250 +1 : t*250) = 0.5* max(y3(jk,(t-1)*250 +1 : ((t+3)*250))); % la soglia è il 60% del massimo del segnale
end
end
soglia((nu-3)*250+1:end)=soglia((nu-3)*250);
if(righe==4)
soglias(1,(nu-3)*250+1:end)=soglias(1,(nu-3)*250);
soglias(2,(nu-3)*250+1:end)=soglias(2,(nu-3)*250);
soglias(3,(nu-3)*250+1:end)=soglias(3,(nu-3)*250);
soglias(4,(nu-3)*250+1:end)=soglias(4,(nu-3)*250);
end
% tm=tm+delay; %delay a 1000 Hz
% tm=round(tm./fat);
j = 1;
qrs = zeros(size(ys)); %vettore dove metterò gli indici di occorrenza di un QRS
blanking = 0;
for i=1:length(ys)-1
if (blanking == 0)
if (ys(i) > soglia(i)) && (ys(i+1) < ys(i)) % esempio di sogliatura.
qrs(j) = i-6;
j = j + 1;
blanking = 30;
end
else
blanking = blanking -1;
end
end
qrs(j:end) = []; % Elimino la parte inutilizzata del vettore.
if(righe==4)
j = 1;
qrs1 = zeros(size(ys)); %vettore dove metterò gli indici di occorrenza di un QRS
ys=y3(1,:);
soglia=soglias(1,:);
blanking = 0;
for i=1:length(ys)-1
if (blanking == 0)
if (ys(i) > soglia(i)) && (ys(i+1) < ys(i)) % esempio di sogliatura.
qrs1(j) = i-6;
j = j + 1;
blanking = 30;
end
else
blanking = blanking -1;
end
end
qrs1(j:end) = []; % Elimino la parte inutilizzata del vettore.
j = 1;
qrs2 = zeros(size(ys)); %vettore dove metterò gli indici di occorrenza di un QRS
ys=y3(2,:);
soglia=soglias(2,:);
blanking = 0;
for i=1:length(ys)-1
if (blanking == 0)
if (ys(i) > soglia(i)) && (ys(i+1) < ys(i)) % esempio di sogliatura.
qrs2(j) = i-6;
j = j + 1;
blanking = 30;
end
else
blanking = blanking -1;
end
end
qrs2(j:end) = []; % Elimino la parte inutilizzata del vettore.
j = 1;
qrs3 = zeros(size(ys)); %vettore dove metterò gli indici di occorrenza di un QRS
ys=y3(3,:);
soglia=soglias(3,:);
blanking = 0;
for i=1:length(ys)-1
if (blanking == 0)
if (ys(i) > soglia(i)) && (ys(i+1) < ys(i)) % esempio di sogliatura.
qrs3(j) = i-6;
j = j + 1;
blanking = 30;
end
else
blanking = blanking -1;
end
end
qrs3(j:end) = []; % Elimino la parte inutilizzata del vettore.
j = 1;
qrs4 = zeros(size(ys)); %vettore dove metterò gli indici di occorrenza di un QRS
ys=y3(4,:);
soglia=soglias(4,:);
blanking = 0;
for i=1:length(ys)-1
if (blanking == 0)
if (ys(i) > soglia(i)) && (ys(i+1) < ys(i)) % esempio di sogliatura.
qrs4(j) = i-6;
j = j + 1;
blanking = 30;
end
else
blanking = blanking -1;
end
end
qrs4(j:end) = []; % Elimino la parte inutilizzata del vettore.
end
end
function [Y, proiezioni, D_ord, V_ord,W]=PCA(X)
[M, N]=size (X);
u=mean(X');
% %Calcolo della media per ogni variabile
%CENTRATI
h=ones(1,N);
B =X - u'*h;
%matrice di covarianza
C=cov(B');
% C_prova=(B*B')/N;
%Calcolo degli autovalori e degli autovettori
[V,D]=eig(C);
%Riordiniamo gli autovalori e i rispettivi autovettori
[val, ind]=sort(diag(D));
D_ord=zeros(M,M);
V_ord=zeros(M,M);
for m=1:M
t=ind(M+1-m);
D_ord(m,m)=D(t,t);
V_ord(:,m)=V(:,t);
end
%Scelta delle prime L colonne (vogliamo ridurre la dimensionalità a L=1)
L=1;
W(:,L)=V_ord(:,L);
% % %Si possono convertire i dati in Z-scores
% % s=zeros(M,1);
% % s(:,1)=sqrt(diag(C));
% % z=B ./(s*h);
%Proiezione dei dati nella nuova base (prima componene principale)
Y=W'*B;
%Proiezione di tutti i basi sulle M basi
proiezioni=V_ord'*B;
end
function [picchi]=scegli(pic_f, feti, battiti_materni)
feti=feti+12;
soglia_val=20;
qrs_1=pic_f;
qrs_2=feti;
contatore_1=0;
contatore_2=0;
zi=1;
while (zi<length(battiti_materni))
zj=1;
while(zj<length(qrs_1))
if(abs(qrs_1(zj)- battiti_materni(zi))<=soglia_val)
contatore_1= contatore_1 + 1;
qrs_1(zj)=[];
break;
end
zj=zj+1;
end
zj=1;
while(zj<length(qrs_2))
if(abs(qrs_2(zj)- battiti_materni(zi))<=soglia_val)
contatore_2= contatore_2 + 1;
qrs_2(zj)=[];
break;
end
zj=zj+1;
end
zi=zi+1;
end
if(contatore_1<contatore_2)
picchi=qrs_1;
else
picchi=qrs_2;
end
end
function[template]=scelta_template(battiti_materni, mqrs)
qrs_1=mqrs(1, mqrs(1,:)>0);
qrs_1=qrs_1+25*4-1;
qrs_2=mqrs(2, mqrs(2,:)>0);
qrs_2=qrs_2+25*4-1;
soglia_val=20*4;
zi=1;
contatore_1=0;
contatore_2=0;
while (zi<length(battiti_materni))
zj=1;
while(zj<length(qrs_1))
if(abs(qrs_1(zj)- battiti_materni(zi))<=soglia_val)
contatore_1= contatore_1 + 1;
qrs_1(zj)=[];
break;
end
zj=zj+1;
end
zj=1;
while(zj<length(qrs_2))
if(abs(qrs_2(zj)- battiti_materni(zi))<=soglia_val)
contatore_2= contatore_2 + 1;
qrs_2(zj)=[];
break;
end
zj=zj+1;
end
zi=zi+1;
end
if(contatore_1>=contatore_2)
template=1;
elseif(contatore_2>contatore_1)
template=2;
end
end
function[qrs]=balda(x,tipo)
% if(tipo==0)
b0 = [1 0 -1];
a0 = 1;
b1 = [1 0 -2 0 1];
a1 = 1;
y0 = filter(b0,a0,x);
y0 = abs(y0);
y1 = filter(b1,a1,x);
y1 = abs(y1);
y0 = [0,y0(1:end-1)]; % vedere dispense a pag. 60
y2 = 1.3*y0 + 1.1*y1;
% accumulo un ritardo 2
bs = 1/8*ones(1,8);
as = 1;
ys = filter(bs,as,y2);
% Introduco un ritardo 4, che si accumula al ritardo 2 precedente
% vedere dispense a pag. 61
% ritardo finale = 6.
% Esempio di blanking per evitare rilevazioni multiple
% M = max(ys);
nu=floor(length(ys)/250);
soglia=zeros(1,length(ys));
for t=1:nu-3
soglia((t-1)*250 +1 : t*250) = 0.6* max(ys((t-1)*250 +1 : ((t+3)*250))); % la soglia è il 60% del massimo del segnale
end
soglia((nu-3)*250+1:end)=soglia((nu-3)*250);
j = 1;
qrs = zeros(size(ys)); %vettore dove metterò gli indici di occorrenza di un QRS
blanking = 0;
if(tipo==0)
for i=1:length(ys)-1
if (blanking == 0)
if (ys(i) > soglia(i)) && (ys(i+1) < ys(i)) % esempio di sogliatura.
sta=i;
avan=1;
tempo=0;
while(ys(sta)>soglia(sta))
tempo(avan)=ys(sta);
avan=avan+1;
sta=sta-1;
if(sta==0)
break;
end
end
[mj,ij]=max(tempo);
ij=ij-1;
qrs(j) = i-6-ij;
j = j + 1;
blanking = 30;
end
else
blanking = blanking -1;
end
end
qrs(j:end) = []; % Elimino la parte inutilizzata del vettore.
else
blanking = 0;
for i=1:length(ys)-1
if (blanking == 0)
if (ys(i) > soglia(i)) && (ys(i+1) < ys(i)) % esempio di sogliatura.
qrs(j) = i-6;
j = j + 1;
blanking = 30;
end
else
blanking = blanking -1;
end
end
qrs(j:end) = [];
end
% figure
% plot(x)
% hold on
% plot(qrs,x(qrs),'*r')
% else
%
% b0 = 1/2*[1 0 -1]; %ritardo di 1
% a0 = 1;
% delay0=1;
%
% b1 = 1/4*[1 0 -2 0 1]; %ritardo di 2
% a1 = 1;
% delay1=2;
%
% b2 = 1/44*[2 4 8 16 8 4 2];
% delay2=3;
% a2=1;
% %ritardo di 3
%
% y0 = filter(b0,a0,x);
% y0 = abs(y0);
%
% y1 = filter(b1,a1,x);
% y1 = abs(y1);
%
% y2=filter(b2,a2,y0);
% y2=filter(b2,a2,x);
%
% for f=2:length(y2)
% y3(f)=y2(f)*y2(f-1); %ritardo di 1
% end
% delay3=1;
% % y3=y2;
% % delay3=0;
%
%
% %ritardi
% dl=delay0+delay2+delay3-delay1;
% y1=[zeros(1,dl),y1(1:end-dl)];
% y4=y3+0.5*y1;
%
%
%
% bs = 1/8*ones(1,8);
% as = 1;
% ys = filter(bs,as,y4);
% delays=4;
% total_delay=delay0+delay1+delay2+delay3+delays;
%
% figure
% del=total_delay-delay0;
% plot([zeros(1,del) y0(1:300-del)])
% hold on
% plot([zeros(1,total_delay) x(1:300-total_delay)],'m')
% del2=total_delay-delay1;
% plot([zeros(1,del2) y1(1:300-del2)],'r')
% del=del-delay2;
% plot([zeros(1,del) y2(1:300-del)],'c')
% del=del-delay3;
% plot([zeros(1,del) y3(1:300-del)],'g')
% plot([zeros(1,del) y4(1:300-del)],'k')
% plot(ys(1:300),'y')
% title('blu der prima, rosso der sec, ciano shaped filter, verde amplificato,nero comb lin, giallo finale, magenta ingresso')
% %
% % Introduco un ritardo 4, che si accumula al ritardo 5 precedente
% % ritardo finale = 9.
%
% % Esempio di blanking per evitare rilevazioni multiple
% % M = max(ys);
% nu=floor(length(ys)/250);
% soglia=zeros(1,length(ys));
% for t=1:nu-3
% soglia((t-1)*250 +1 : t*250) = 0.5* max(ys((t-1)*250 +1 : ((t+3)*250))); % la soglia è il 60% del massimo del segnale
% end
% soglia((nu-3)*250+1:end)=soglia((nu-3)*250);
% j = 1;
% qrs = zeros(size(ys)); %vettore dove metterò gli indici di occorrenza di un QRS
% blanking = 0;
%
% for i=1:length(ys)-1
% if (blanking == 0)
% if (ys(i) > soglia(i)) && (ys(i+1) < ys(i))
%
% qrs(j) = i;
% j = j + 1;
% blanking = 30;
%
% end
% else
% blanking = blanking -1;
% end
% end
%
% qrs(j:end) = []; % Elimino la parte inutilizzata del vettore.
% figure
% plot(x)
% hold on
% plot(qrs,x(qrs),'*r')
% end
end
function [FilteredECG, original_d] = preprocessing(ECG,F_acq)
% ---- preprocess the data ----
%controllo che non ci siano NaN
for mk=1:4
seg=ECG(mk,:);
l=isnan(seg); %mette 1 logico dove ci sono NaN
z=find(l==1); %trovo gli 1
z=[z,0];
c=1;
while c<length(z)
if(z(c)>0)
start=z(c);
stop=z(c);
if(z(c)==length(seg))
else
while(z(c+1)-z(c)==1)
c=c+1;
stop=z(c);
end
end
end
c=c+1;
delta=stop-start;
if(delta==0) %ho solo un campione
delta=3;
end
if(((start-delta)>0)&&((stop+delta)<length(seg)+1))
%interp sline
a=[start-delta:start-1, stop+1:stop+delta];
elseif((start-delta)<1)
%spline da inizio segnale
if(start>1)
a=[1:start-1, stop+1:stop+delta];
else
a=[start,stop+1: stop + delta];
end
elseif((stop+delta)>length(seg))
%spline fino alla fine del segnale
if(stop<length(z))
a=[start-delta:start-1, stop+1:length(seg)];
else
a=[start-delta:start-1, stop];
end
end
b=seg(a);
d=(start:stop);
tt=spline(a,b,d);
seg(start:stop)=tt;
end
ECG(mk,:)=seg;
end
F_elab=250;
ECG=ECG-mean(ECG,2)*ones(1,length(ECG));
for z=1:4
data(z,:)=DERIVATORE(ECG(z,:),F_acq,1);
end
s=zeros(1,4);
for z=1:4
s(z)=std(data(z,:));
end
a=10;
soglie=a*s;
for l=1:4
ECG(l,:)=taglia_outlier2(ECG(l,:),data(l,:),soglie(l));
end
% % load coeff_FIR_46_50_1000.mat
% Hd = prova_filtro;
% Num=Hd.Numerator;
% for l=1:4
% ECG_lp(l,:)=filter(Num,1,ECG(l,:));
% end
% delay1=floor(length(Num)/2);
ingresso=ECG;
Hd = prova_iir_lp;
Num=Hd.Numerator;
Den=Hd.Denominator;
% delay1=length(Num)-1;
for l=1:4
ECG(l,:)=filtfilt(Num,Den,ECG(l,:));
end
%@1000Hz
% dawn(:,1)=resample(ECG(1,:)',F_elab,F_acq);
% dawn(:,2)=resample(ECG(2,:)',F_elab,F_acq);
% dawn(:,3)=resample(ECG(3,:)',F_elab,F_acq);
% dawn(:,4)=resample(ECG(4,:)',F_elab,F_acq);
% ECG=dawn';
% % load coeff_FIR_1_2.mat
% Hd_2 = prova_filtro2;
% Num=Hd_2.Numerator;
% for l=1:4
% ECG_fir(l,:)=filter(Num,1,ECG(l,:));
% end
% delay2=floor(length(Num)/2); %@250Hz
% Hd=prova_iir_hp;
% Hd = filtro_iir_4_8_250;
Hd = hp_4_8_1000;
Num=Hd.Numerator;
Den=Hd.Denominator;
% delay2=length(Num)-1;
for l=1:4
ECG(l,:)=filtfilt(Num,Den,ECG(l,:));
end
% delay2=4*delay2;
original_d= ECG;
% delay=delay1+delay2;
delay=0;
prova=original_d(1,:);
% prova=resample(prova',F_acq,F_elab);
% figure
% plot(prova')
% hold on
% plot(ingresso(1,1:end-delay),'r')
% title('filtraggio')
dawn(:,1)=resample(ECG(1,:)',F_elab,F_acq);
dawn(:,2)=resample(ECG(2,:)',F_elab,F_acq);
dawn(:,3)=resample(ECG(3,:)',F_elab,F_acq);
dawn(:,4)=resample(ECG(4,:)',F_elab,F_acq);
FilteredECG=dawn';
end
function Hd = hp_4_8_1000 %filtro iir passa alto a 1000Hz
%HP_4_8_1000 Returns a discrete-time filter object.
%
% M-File generated by MATLAB(R) 7.5 and the Signal Processing Toolbox 6.8.
%
% Generated on: 28-Aug-2013 11:15:05
%
% Butterworth Highpass filter designed using FDESIGN.HIGHPASS.
% All frequency values are in Hz.
Fs = 1000; % Sampling Frequency
Fstop = 4; % Stopband Frequency
Fpass = 8; % Passband Frequency
Astop = 40; % Stopband Attenuation (dB)
Apass = 1; % Passband Ripple (dB)
match = 'stopband'; % Band to match exactly
% Construct an FDESIGN object and call its BUTTER method.
h = fdesign.highpass(Fstop, Fpass, Astop, Apass, Fs);
Hd = design(h, 'butter', 'MatchExactly', match);
% Get the transfer function values.
[b, a] = tf(Hd);
% Convert to a singleton filter.
Hd = dfilt.df2(b, a);
end
function Hd = filtro_iir_4_8_250
%FILTRO_IIR_4_8_250 Returns a discrete-time filter object.
%
% M-File generated by MATLAB(R) 7.5 and the Signal Processing Toolbox 6.8.
%
% Generated on: 23-Aug-2013 19:19:44
%
% Butterworth Highpass filter designed using FDESIGN.HIGHPASS.
% All frequency values are in Hz.
Fs = 250; % Sampling Frequency
Fstop = 4; % Stopband Frequency
Fpass = 8; % Passband Frequency
Astop = 40; % Stopband Attenuation (dB)
Apass = 1; % Passband Ripple (dB)
match = 'stopband'; % Band to match exactly
% Construct an FDESIGN object and call its BUTTER method.
h = fdesign.highpass(Fstop, Fpass, Astop, Apass, Fs);
Hd = design(h, 'butter', 'MatchExactly', match);
% Get the transfer function values.
[b, a] = tf(Hd);
% Convert to a singleton filter.
Hd = dfilt.df2(b, a);
% [EOF]
end
function Hd = prova_iir_lp
%PROVA_IIR_LP Returns a discrete-time filter object.
%
% M-File generated by MATLAB(R) 7.5 and the Signal Processing Toolbox 6.8.
%
% Generated on: 22-Aug-2013 10:13:58
%
% Chebyshev Type II Lowpass filter designed using FDESIGN.LOWPASS.
% All frequency values are in Hz.
Fs = 1000; % Sampling Frequency
Fpass = 46; % Passband Frequency
Fstop = 50; % Stopband Frequency
Apass = 1; % Passband Ripple (dB)
Astop = 40; % Stopband Attenuation (dB)
match = 'stopband'; % Band to match exactly
% Construct an FDESIGN object and call its CHEBY2 method.
h = fdesign.lowpass(Fpass, Fstop, Apass, Astop, Fs);
Hd = design(h, 'cheby2', 'MatchExactly', match);
% Get the transfer function values.
[b, a] = tf(Hd);
% Convert to a singleton filter.
Hd = dfilt.df2(b, a);
% [EOF]
end
function Hd = prova_iir_hp
%PROVA_IIR_HP Returns a discrete-time filter object.
%
% M-File generated by MATLAB(R) 7.5 and the Signal Processing Toolbox 6.8.
%
% Generated on: 21-Aug-2013 16:09:04
%
% Butterworth Highpass filter designed using FDESIGN.HIGHPASS.
% All frequency values are in Hz.
Fs = 250; % Sampling Frequency
Fstop = 1; % Stopband Frequency
Fpass = 2; % Passband Frequency
Astop = 40; % Stopband Attenuation (dB)
Apass = 1; % Passband Ripple (dB)
match = 'stopband'; % Band to match exactly
% Construct an FDESIGN object and call its BUTTER method.
h = fdesign.highpass(Fstop, Fpass, Astop, Apass, Fs);
Hd = design(h, 'butter', 'MatchExactly', match);
% Get the transfer function values.
[b, a] = tf(Hd);
% Convert to a singleton filter.
Hd = dfilt.df2(b, a);
% [EOF]
% % % % Fs = 250; % Sampling Frequency
% % % %
% % % % Fstop = 1; % Stopband Frequency
% % % % Fpass = 3; % Passband Frequency
% % % % Astop = 40; % Stopband Attenuation (dB)
% % % % Apass = 1; % Passband Ripple (dB)
% % % % match = 'stopband'; % Band to match exactly
% % % %
% % % % % Construct an FDESIGN object and call its BUTTER method.
% % % % h = fdesign.highpass(Fstop, Fpass, Astop, Apass, Fs);
% % % % Hd = design(h, 'butter', 'MatchExactly', match);
% % % % % Get the transfer function values.
% % % % [b, a] = tf(Hd);
% % % %
% % % % % Convert to a singleton filter.
% % % % Hd = dfilt.df2(b, a);
% % % %
% % % % % [EOF]
end
function Hd = prova_filtro
%PROVA_FILTRO Returns a discrete-time filter object.
%
% M-File generated by MATLAB(R) 7.5 and the Signal Processing Toolbox 6.8.
%
% Generated on: 19-Aug-2013 16:46:53
%
% FIR Window Lowpass filter designed using the FIR1 function.
% All frequency values are in Hz.
Fs = 1000; % Sampling Frequency
Fpass = 46; % Passband Frequency
Fstop = 50; % Stopband Frequency
Dpass = 0.057501127785; % Passband Ripple
Dstop = 0.001; % Stopband Attenuation
flag = 'scale'; % Sampling Flag
% Calculate the order from the parameters using KAISERORD.
[N,Wn,BETA,TYPE] = kaiserord([Fpass Fstop]/(Fs/2), [1 0], [Dstop Dpass]);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, Wn, TYPE, kaiser(N+1, BETA), flag);
Hd = dfilt.dffir(b);
end
function Hd = prova_filtro2
%PROVA_FILTRO2 Returns a discrete-time filter object.
%
% M-File generated by MATLAB(R) 7.5 and the Signal Processing Toolbox 6.8.
%
% Generated on: 19-Aug-2013 17:36:08
%
% FIR Window Highpass filter designed using the FIR1 function.
% All frequency values are in Hz.
Fs = 250; % Sampling Frequency
Fstop = 1; % Stopband Frequency
Fpass = 2; % Passband Frequency
Dstop = 0.01; % Stopband Attenuation
Dpass = 0.057501127785; % Passband Ripple
flag = 'scale'; % Sampling Flag
% Calculate the order from the parameters using KAISERORD.
[N,Wn,BETA,TYPE] = kaiserord([Fstop Fpass]/(Fs/2), [0 1], [Dpass Dstop]);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, Wn, TYPE, kaiser(N+1, BETA), flag);
Hd = dfilt.dffir(b);
% [EOF]
end
function [uscita]=taglia_outlier2(original,ingresso,soglia)
t=find(abs(ingresso)>soglia);
uscita=original;
if(isempty(t))
else
j=t;
for v=(length(t)):-1:2
if(abs(t(v)-t(v-1))==1)
j(v)=0;
end
end
for z=1:length(j)
indice=j(z);
if(indice==0)
else
if((indice-5)<1)
delta=original(1:(indice+10) );
th=abs(median(delta));
fb=indice+10;
while(abs(original(fb)-original(fb-1))<3*th)
fb=fb-1; %estremo destro
if(fb==1)
fb=indice+10;
break;
end
end
estremo_dx=fb;
uscita(1,1:estremo_dx)=original(estremo_dx);
elseif((indice+10)>length(original)-1)
delta=original((indice-5):end );
th=abs(median(delta));
fb=indice-5;
while(abs(original(fb)-original(fb+1))<3*th)
fb=fb+1; %estremo sinistro
if(fb==length(original))
fb=indice-5;
break;
end
end
estremo_sx=fb;
uscita(1,estremo_sx:end)=original(estremo_sx);
else
delta=original((indice-5):(indice+10) );
th=abs(median(delta));
fb=indice-5;
while(abs(original(fb)-original(fb+1))<3*th)
fb=fb+1; %estremo sinistro
if(fb>=indice+10)
fb=indice+10;
break;
end
end
estremo_sx=fb;
fb=indice+10;
while(abs(original(fb)-original(fb-1))<3*th)
fb=fb-1; %estremo destro
if(fb<=indice-5)
fb=indice-5;
break;
end
end
estremo_dx=fb;
c=(estremo_dx - estremo_sx)-1;
if(c>1)
a=[(estremo_sx-c-1):estremo_sx, estremo_dx: (estremo_dx+c+1)];
b=original(a);
d=(estremo_sx+1 : estremo_dx - 1);
tt=spline(a,b,d);
uscita(estremo_sx+1 : estremo_dx - 1)=tt;
elseif c==1
a=[(estremo_sx-1):estremo_sx, estremo_dx: (estremo_dx+1)];
b=original(a);
d=estremo_sx+1;
tt=spline(a,b,d);
uscita(estremo_sx+1 : estremo_dx - 1)=tt;
end
end
end
end
end
end
function y=DERIVATORE(x,fs,parametro)
switch(parametro)
case 0
b=(1/2)*[1 -1];
a=1;
y=filter(b,a,x);
case 1
b=(1.99/2)*[1 -1];
a=[1 -0.99];
y=filter(b,a,x);
end
end
function [pulito]=MECGcancellation(segnale,mqrs,Apost ,template)
if(template==1)
temp_sottr(1,:)=Apost(1,:);
temp_sottr(2,:)=Apost(2,:);
temp_sottr(3,:)=Apost(3,:);
else
temp_sottr(1,:)=Apost(4,:);
temp_sottr(2,:)=Apost(5,:);
temp_sottr(3,:)=Apost(6,:);
end
dim=length(temp_sottr);
for tm=1:3
temp_sottr(tm,:)=temp_sottr(tm,:).*(tukeywin(dim, 0.2))';
end
% temp_sottr=Apost(template,:);
pulito=segnale;
delta_stop=0;
% indice_debug=1;
for lt=1:length(mqrs)
inds=mqrs(lt);
if((inds+dim)>length(segnale))
ui=length(segnale);
delta_stop=inds+dim-ui;
% segnale=[segnale,zeros(1,delta)];
tempn=[segnale(inds-dim:end), zeros(1,delta_stop)];
inizio=dim-1;
% tempn=segnale(length(segnale)-101:length(segnale));
elseif((inds-dim)<1)
% tempn=segnale(1:dim+1);
tempn=[zeros(1,-inds+dim+1) segnale(1:inds+dim)];
% inizio=dim-1+(inds-dim)-1;
inizio=dim-1;
else
tempn=segnale(inds-dim:inds+dim);
inizio=dim-1;
end
r1 = pearsoncoeff(tempn,temp_sottr(1,:));
r2 = pearsoncoeff(tempn,temp_sottr(2,:));
r3 = pearsoncoeff(tempn,temp_sottr(3,:));
[mar(1),inr(1)]=max(r1);
[mar(2),inr(2)]=max(r2);
[mar(3),inr(3)]=max(r3);
[ma,in]=max(mar);
% start=inds-inizio-2+in;
start=inds-inizio-2+inr(in);
delta_start=0;
if(start<1)
start=1;
delta_start=-inds+dim;
end
if(delta_stop>1)
delta_stop=start+dim-length(segnale)-1;
end
if(delta_stop<0)
delta_stop=0;
end
if(delta_stop<0)
delta_stop=0;
end
% if(start>length(segnale))
%
% end
% G=max(abs(segnale(start+delta_start:start+dim-1-delta_stop)))/max(abs(temp_sottr(in,delta_start+1:end-delta_stop)));
% deb2=(temp_sottr*G);
% deb1=segnale(start:start+dim-1);
deb1=segnale(start:start+dim-1-delta_stop-delta_start);
% delta_pos=abs(max((segnale(start:start+49))))-abs(max((temp_sottr)));
% delta_neg=abs(min((segnale(start:start+49))))-abs(min((temp_sottr)));
Gpos=max((segnale(start:start+dim-1-delta_stop-delta_start)))/max((temp_sottr(in,delta_start+1:end-delta_stop)));
Gneg=min((segnale(start:start+dim-1-delta_stop-delta_start)))/min((temp_sottr(in,delta_start+1:end-delta_stop)));
deb2=0;
for kl=1:length(deb1)
if(temp_sottr(in,kl)>0)
deb2(kl)=temp_sottr(in,delta_start+kl)*Gpos;
else
deb2(kl)=temp_sottr(in,delta_start+kl)*Gneg;
end
end
% if(delta_pos>delta_neg)
% deb2=(temp_sottr*Gpos);
% else
% deb2=(temp_sottr*Gneg);
% end
% grt=0;
% if(delta>0)
% grt=start+dim-1-length(pulito);
% end
% if(grt<0)
% grt=0;
% end
% if(grt==0)
% matrice_debug(indice_debug,:)=segnale(start:start+dim-1-grt);
%
% indice_debug=indice_debug+1;
% end
% deb1=segnale(start+delta_start:start+dim-1-delta_stop);
pulito(start:start+dim-1-delta_start-delta_stop)=segnale(start:start+dim-1-delta_start-delta_stop)-(deb2(1:end));
% figure
% plot(segnale(start:start+dim-1-grt))
% hold on
% plot((deb2(1:end-grt)),'r')
% title('in rosso template')
end
end
function [qrs_f, DEL] =PeakDetectionFetali(FECG,Rmaterni)
AM=8;
DEL=floor((AM)/2)+1;
% a=derivatore_elementare(FECG);
% b=a.^2;
% d=b;
b0 = [1 0 -1];
a0 = 1;
b1 = [1 0 -2 0 1];
a1 = 1;
y0 = filter(b0,a0,FECG);
y0 = abs(y0);
y1 = filter(b1,a1,FECG);
y1 = abs(y1);
y0 = [0,y0(1:end-1)]; % vedere dispense a pag. 60
y2 = 1.3*y0 + 1.1*y1;
% accumulo un ritardo 2
bs = 1/8*ones(1,8);
as = 1;
ys = filter(bs,as,y2);
DEL=DEL+1;
% for lt=1:4
% a(lt,:)=derivatore_elementare(FECG(lt,:));
% b(lt,:)=a(lt,:).^2;
% end
% d=sum(b);
% c=media_mobile(d,AM);
[so]=sogliatrovapiccoR_offline(ys,0.8);
% ys=c;
j=1;
t=0;
qrs_f=[];
REFRATT=15; %bpm max 300
for i=1:length(ys)-1
if(i>t)
if(ys(i)>so(i))
r=ys(i);
ri=i;
k=i;
while((ys(k)>so(k))&&(k<(length(ys))))
if(ys(k)>r)
r=ys(k);
ri=k;
end
k=k+1;
end
qrs_f(j)=ri;
if(j>1)
if(abs(qrs_f(j)-qrs_f(j-1))<=REFRATT)
% if(ys(qrs_f(j))>ys(qrs_f(j-1)))
pea=qrs_f(j)*ones(1,length(Rmaterni));
p=min(abs(Rmaterni - pea));
qea=qrs_f(j-1)*ones(1,length(Rmaterni));
q=min(abs(Rmaterni - qea));
if((p>q)&&(q<REFRATT))
qrs_f(j-1)=qrs_f(j);
qrs_f(j)=[];
elseif((q>p)&&(p<REFRATT))
qrs_f(j)=[];
elseif(ys(qrs_f(j))>ys(qrs_f(j-1)))
qrs_f(j-1)=qrs_f(j);
qrs_f(j)=[];
elseif(ys(qrs_f(j))<ys(qrs_f(j-1)))
qrs_f(j)=[];
end
else
j=j+1;
end
else
j=j+1;
end
t=k;
end
end
end
end
function [Ttotpost,Ttot,occ, Apost,Nt,occorrenze_finali]=PeakDetection(signal, wavname, levels, clearapprox, buffer_len, ...
threshold, hard_soft, deepth_th, level_independent, single_level_th_dep, level_th, scaling_type, ...
rms_sc, N, th_base_type, LEN, par_detection,Thcross,Thc,Thfusione, original_d)
mid = LEN;
occorrenze_finali=[];
occ=0;
mid_mezzi = LEN/2;
% Thc = 0.9; % soglia di correlazione (0.9)
% Thfusione=0.9; % soglia di correlazione per fusione template
Kin = 0; % indice iniziale QRS
Kfn = 0; % indice finale QRS
Ttotdisc = 0; % conteggio QRS trovati ma non classificati
NumTempl=2; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Thcross=0.85;
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% INIZIO CREAZIONE VARIABILI
NTM = 10; % numero massimo di template ammessi
Nt = 0; % numero di template presenti in quel momento
A = zeros(NTM,LEN); % matrice dei template
Templ_overwritten = 0;
Ttot = zeros(NTM,1); % vettore delle occorrenze totali
tmp = zeros(1,LEN); % buffer temporaneo per uno spike
cc = zeros(NTM,LEN);% matrice contenente le crosscorrelazioni fra template e spike trovato
Ld = cell(levels,1);
Hd = cell(levels,1);
Lr = cell(levels,1);
Hr = cell(levels,1);
% disp('creazione filtri wavelet...')
[Ld{1},Hd{1},Lr{1},Hr{1}]=wfilters(wavname); % predisposizione wavelet 'bior6.8'
for i=2:levels % creazione filtri a trous di Mallat
Ld{i}= upsampling(Ld{i-1});
Hd{i}= upsampling(Hd{i-1});
Lr{i}= upsampling(Lr{i-1});
Hr{i}= upsampling(Hr{i-1});
end
for i=2:levels % eliminazione code di zeri filtri
t=(2^(i-1))-1;
Ld{i}(end-t+1:end)=[];
Hd{i}(end-t+1:end)=[];
Lr{i}(end-t+1:end)=[];
Hr{i}(end-t+1:end)=[];
end
% disp('definizione ritardi...')
delay=cell(levels-1,1);
delayIT = 0;
for i = levels:-1:2
if rem(length(Ld{i}),2)==0 % filtro lunghezza pari (Ld e Hd sono della stessa lunghezza)
delayIT=delayIT+length(Ld{i});
else % filtro lunghezza dispari (Ld e Hd sono della stessa lunghezza)
delayIT=delayIT+length(Ld{i})-1;
end
delay{i-1}=delayIT;
end
if rem(length(Hd{1}),2)==0 % filtro lunghezza pari (Ld e Hd sono della stessa lunghezza)
total_delay=delayIT+length(Hd{1});
else % filtro lunghezza dispari (Ld e Hd sono della stessa lunghezza)
total_delay=delayIT+length(Hd{1})-1;
end
% disp('creazione buffer dei filtri in decomposizione...')
input_buffer = zeros(buffer_len + length(Ld{1}) - 1,1);
dec_buffer_L = cell(levels,1);
dec_buffer_H = cell(levels,1);
for i = 1:levels - 1
dec_buffer_L{i} = zeros(buffer_len + length(Ld{i+1}) - 1,1);
dec_buffer_H{i} = zeros(buffer_len + delay{i} + length(Hr{i}) - 1,1);
end
dec_buffer_L{levels} = zeros(buffer_len + length(Ld{levels}) - 1,1);
dec_buffer_H{levels} = zeros(buffer_len + length(Hd{levels}) - 1,1);
% disp('creazione buffer dei filtri in ricomposizione...')
tmpbuffer1rec = zeros(buffer_len,1);
tmpbuffer2rec = zeros(buffer_len,1);
rec_buffer_sum = cell(levels,1);
for i = 1:levels
rec_buffer_sum{i} = zeros(buffer_len + length(Lr{i}) - 1,1);
end
denoised = zeros(size(signal));
% disp('creazione variabili per soglia...')
buffer_for_th = zeros(deepth_th * buffer_len, levels);
th = zeros(levels, 1);
update_th = 1;
scaling = zeros(levels, 1);
switch th_base_type
case 100
th_base = 0.3936 + 0.1829*(log2(N));
case 200
th_base = sqrt(2*log(N));
otherwise
th_base = th_base_type;
end
if scaling_type == 5
th_base = 1;
end
% fprintf('Processing...');
numblocks = length(signal)/buffer_len;
% s = strcat('Processing (', num2str(length(signal)/buffer_len));
% s = strcat(s, ' blocks)...');
% hwait = waitbar(0,'Processing block -0- of -20-','name',s,'visible','off');
% hwaitpos = get(hwait,'position'); % [left bottom width height]
% hwaitpos(1,1) = hwaitpos(1,1) - hwaitpos(1,3)/2 - 2;
% set(hwait, 'position', hwaitpos);
% s = strcat('Templates created (', num2str(NTM));
% s = strcat(s, ' max)...');
% hwait2 = waitbar(0,'Number of templates at now: -0-','name',s,'visible','off');
% hwaitpos = get(hwait2,'position'); % [left bottom width height]
% hwaitpos(1,1) = hwaitpos(1,1) + hwaitpos(1,3)/2 + 2;
% set(hwait2, 'position', hwaitpos);
% set(hwait2, 'visible', 'on');
% set(hwait, 'visible', 'on');
for i=1:numblocks
input_buffer(1:end - buffer_len)=input_buffer(buffer_len + 1:end);
% s = strcat('Processing block -', num2str(i));
% s = strcat(s,'- of -20-');
% waitbar(i/numblocks, hwait, s);
input_buffer(length(Ld{1}):end)=signal((i-1)*buffer_len+1:(i)*buffer_len);
tmpl = filter(Ld{1},1,input_buffer);
tmph = filter(Hd{1},1,input_buffer);
for lev = 1:levels - 1
dec_buffer_L{lev}(1:end - buffer_len) = dec_buffer_L{lev}(buffer_len + 1:end);
dec_buffer_H{lev}(1:end - buffer_len) = dec_buffer_H{lev}(buffer_len + 1:end);
dec_buffer_L{lev}(end - buffer_len + 1:end) = tmpl(length(Ld{lev}):end);
dec_buffer_H{lev}(end - buffer_len + 1:end) = tmph(length(Hd{lev}):end);
tmpl = filter(Ld{lev+1},1,dec_buffer_L{lev});
tmph = filter(Hd{lev+1},1,dec_buffer_L{lev});
end
dec_buffer_L{levels}(1:end - buffer_len) = dec_buffer_L{levels}(buffer_len + 1:end);
dec_buffer_H{levels}(1:end - buffer_len) = dec_buffer_H{levels}(buffer_len + 1:end);
dec_buffer_L{levels}(end - buffer_len + 1:end) = tmpl(length(Lr{levels}):end);
dec_buffer_H{levels}(end - buffer_len + 1:end) = tmph(length(Hr{levels}):end);
if i == 1
for lev = 1:levels
for j = 1:deepth_th
buffer_for_th((j-1)*buffer_len+1:j*buffer_len, lev) = dec_buffer_H{lev}(end-buffer_len+1:end);
end
end
if threshold ~= 0 % se è previsto di sogliare
if level_independent ~= 0 % se la soglia non dipende dal segnale alle varie scale
for lev = 1:levels
scaling(lev) = 1; % nessuno scalamento alla soglia th di base
end
else
if single_level_th_dep ~= 0
scaling(1) = scal_th(scaling_type, level_th, buffer_for_th, rms_sc);
for lev = 2:levels
scaling(lev) = scaling(lev-1); % propago lo stesso scalamento su tutte le scale
end
else
for lev = 1:levels
scaling(lev) = scal_th(scaling_type, lev, buffer_for_th, rms_sc);
end
end
end
for lev = 1:levels
th(lev) = th_base * scaling(lev);
end
end
end
if clearapprox ~= 0
dec_buffer_L{levels} = zeros(buffer_len + length(Ld{levels}) - 1,1);
end
% applica soglia
if (hard_soft == 's') || (hard_soft == 'S' ) % se specificato soft (s oppure S) fa soft
for lev=1:levels
dec_th = (abs(dec_buffer_H{lev}(end-buffer_len+1:end)) - th(lev));
dec_th = (dec_th+abs(dec_th))/2;
dec_buffer_H{lev}(end-buffer_len+1:end) = ...
sign(dec_buffer_H{lev}(end-buffer_len+1:end)).*dec_th;
end
else % altrimenti hard
for lev=1:levels
dec_buffer_H{lev}(end-buffer_len+1:end) = ...
dec_buffer_H{lev}(end-buffer_len+1:end).*(abs(dec_buffer_H{lev}(end-buffer_len+1:end)) > th(lev));
end
end
% ricomposizione
rec_buffer_sum{levels} = dec_buffer_L{levels};
for lev = levels-1:-1:1
% filtra Lr su tmpl e lo copia su tmp1 (256)
tmpl = filter(Lr{lev+1},1,rec_buffer_sum{lev+1});
tmpbuffer1rec = tmpl(end-buffer_len+1:end);
% filtra Hr su tmpr e lo copia su tmp2 (256)
tmph = filter(Hr{lev+1},1,dec_buffer_H{lev+1}(1:length(Hr{lev+1})-1+buffer_len));
tmpbuffer2rec = tmph(end-buffer_len+1:end);
% aggiorna il rec_buffer_sum del livello sottostante
rec_buffer_sum{lev}(1:end - buffer_len) = rec_buffer_sum{lev}(buffer_len + 1:end);
% somma tmp1 e tmp2 in rec_buffer_sum (posizione opportuna)
rec_buffer_sum{lev}(end - buffer_len + 1:end)=0.5*(tmpbuffer1rec + tmpbuffer2rec);
end
% filtra Lr su tmpl e lo copia su tmp1 (256)
tmpl = filter(Lr{1},1,rec_buffer_sum{1});
tmpbuffer1rec = tmpl(end-buffer_len+1:end);
% filtra Hr su tmpr e lo copia su tmp2 (256)
tmph = filter(Hr{1},1,dec_buffer_H{1}(1:length(Hr{1})-1+buffer_len));
tmpbuffer2rec = tmph(end-buffer_len+1:end);
% somma tmp1 e tmp2 in rec_buffer_sum (posizione opportuna)
denoised((i-1)*buffer_len+1:(i)*buffer_len) = 0.5*(tmpbuffer1rec + tmpbuffer2rec);
end
% QRS DETECTOR
if(par_detection~=1)
[ys, so]=qrs_detector_wd(denoised);
delay_stadi_QRSdet = 7; %2 della der seconda + 5 media mobile
else
a=derivatore_elementare(denoised);
b=a.^2;
ys=media_mobile(b,8);
[so]=sogliatrovapiccoR_offline(ys,0.9); %AUMENTATA SOGLIA A 0.9
delay_stadi_QRSdet = 5; %1 della der prima + 4 media mobile
end
j=1;
t=0;
QRSs=[];
for i=1:length(ys)-1
if(i>t)
if(ys(i)>so(i))
r=ys(i);
ri=i;
k=i;
while((ys(k)>so(k))&&(k<(length(ys))))
if(ys(k)>r)
r=ys(k);
ri=k;
end
k=k+1;
end
QRSs(j)=ri;
j=j+1;
t=k;
end
end
end
% figure
% plot(ys)
% hold on
% plot(so,'g')
% if tmatch_on_den~=0
% %% Template matching sul segnale denoised
% BUFF = denoised;
% QRSs=QRSs-delay_stadi_QRSdet;
% else
% %% Template matching sul segnale originale
% BUFF = signal;
% QRSs=QRSs-delay_stadi_QRSdet-total_delay; %+ eventuale centratura
% end
% leggere posizioni picchi QRS detector
BUFF =original_d;
QRSs=QRSs-delay_stadi_QRSdet-total_delay;
QRSs=QRSs*4;
indice_debug=1;
cb=1;
if(length(QRSs)>5)
while(QRSs(cb)<1000)
cb=cb+1;
end
for idx_QRSs=cb:length(QRSs)
if QRSs(idx_QRSs)-LEN/2<1
Kin=1;
else
Kin=QRSs(idx_QRSs)-LEN/2;
end
if QRSs(idx_QRSs)+LEN/2-1>length(BUFF)
Kfn=length(BUFF);
else
Kfn=QRSs(idx_QRSs)+LEN/2-1;
end
if(Kin==1)
% Kfn=QRSs(idx_QRSs)+LEN-1;
Kfn=LEN;
end
if(Kfn==length(BUFF));
% Kin=QRSs(idx_QRSs)-LEN+1;
Kin=length(BUFF)-LEN+1;
end
delta=Kfn-Kin;
prova1=0;
prova2=1000000;
for tb=Kin+round(mid/4):Kfn-round(mid/4)
if(BUFF(tb)>prova1)
prova1=BUFF(tb);
m_pos=tb;
end
if(BUFF(tb)<prova2)
prova2=BUFF(tb);
m_neg=tb;
end
end
prova2=abs(prova2);
% if(prova2>1.2*prova1)
if(prova2>1.4*prova1)
m=m_neg;
else
m=m_pos;
end
%
% prova1=max([zeros(1,0.1*LEN) BUFF(Kin+0.1*LEN:Kfn-0.1*LEN) zeros(1,0.1*LEN)]);
% prova2=min([zeros(1,0.1*LEN) BUFF(Kin+0.1*LEN:Kfn-0.1*LEN) zeros(1,0.1*LEN)]);
% prova2=abs(prova2);
% if(prova2>1.2*prova1)
% [c,m] = (min([zeros(1,0.1*LEN) BUFF(Kin+0.1*LEN:Kfn-0.1*LEN) zeros(1,0.1*LEN)]));
% else
% [c,m] = (max([zeros(1,0.1*LEN) BUFF(Kin+0.1*LEN:Kfn-0.1*LEN) zeros(1,0.1*LEN)]));
% end
% [c,m] = max(abs([zeros(1,5) BUFF(Kin+5:Kfn-5) zeros(1,5)]));
tmp = zeros(size(tmp));
ampt=floor((5/8)*mid);
sts=floor(mid/8);
if((m-ampt+2>0)&&(m+ampt+1<=length(BUFF)))
tmp(1:2*ampt)=BUFF(m-ampt+2:m+ampt+1);
end
invld=0;
%%analizzo se tmp è centrato male
if(1.2*max(abs(tmp(ampt-0.1*mid:ampt+0.1*mid)))<(max(abs(tmp))))
%%template non valido
invld=1;
end
if(invld==0)
% tmp(mid-m:mid-m+delta)=BUFF(Kin:Kfn);
maxcorr=zeros(NTM,1);
indexmaxcorr=zeros(NTM,1);
if Nt == 0; % nessuna classe prima
A(1,:)=tmp(sts:sts+mid-1);
Ttot(1,1)=1;
Nt = 1;
% s = strcat('Number of templates at now: -', num2str(Nt));
% s = strcat(s,'-');
% waitbar(Nt/NTM,hwait2,s);
% occurrences(i)=Nt;
else
% ho almeno un template quindi faccio la cross-correlazione fra tmp e tutti
for k=1:Nt
% tmp2=[zeros(1,50) tmp(51:end-50) zeros(1,50)];
cctemp = pearsoncoeff(tmp,A(k,:));
cc(k,1:length(cctemp)) = cctemp; %% serve solo per debug
[maxcorr(k),indexmaxcorr(k)]=max(cctemp);
end
[mm,im]= max(maxcorr);
if mm < Thc
if Nt < NTM % numero di classi minore di quello massimo: aggiungo una classe
A(Nt+1,:)=tmp(sts:sts+LEN-1);
Ttot(Nt+1,1)=1;
Nt=Nt+1;
% s = strcat('Number of templates at now: -', num2str(Nt));
% s = strcat(s,'-');
% waitbar(Nt/NTM,hwait2,s);
% occurrences(i)=Nt;
else % numero di classi pari o maggiore di quello massimo: devo togliere il template con occorrenza minore
[mmin, mminidx] = min(Ttot);
% s=strcat('Removing template with number of occurrences = ', num2str(mmin));
% disp(s);
Templ_overwritten = Templ_overwritten + 1;
% e aggiungere il nuovo
A(mminidx,:)=tmp(sts:sts+LEN-1);
Ttot(mminidx,1)=1;
% occurrences(i)=mminidx+100;
end
else
% tiro via la parte centrale del segnale, allineata sulla correlazione 'estrattoy'
estrattoy = tmp(indexmaxcorr(im):indexmaxcorr(im)+LEN-1);
% estrattoy = tmp(mid_mezzi:mid_mezzi+LEN-1);
% eseguo la media sincronizzata
A(im,:) = synchronizedAVG(A(im,:),estrattoy,Ttot(im,1));
debug_t(indice_debug,:)=estrattoy;
vettore_debug(indice_debug)=im; %numero classe
indice_debug=indice_debug+1;
% aggiorno occorrenze di quella classe
Ttot(im,1) = Ttot(im,1)+1;
% occurrences(i)=im;
end
end
end
end
% close(hwait);
% fprintf('-----------------------------------------------------------\n');
% fprintf('AVVIO PROCESSO DI FUSIONE TEMPLATE SIMILI CON SOGLIA %d\n',Thfusione);
indexA = 1;
while indexA < Nt
tmp(sts:sts+LEN-1) = A(indexA,:);
maxcorr=zeros(NTM,1);
indexmaxcorr=zeros(NTM,1);
for k=indexA+1:Nt
%plot(A(indexA,:)); hold on; plot(A(k,:),'r');
cctemp = pearsoncoeff(tmp,A(k,:));
cc(k,1:length(cctemp)) = cctemp; %% serve solo per debug
%%permetto solo piccoli spostamenti per allineare
[maxcorr(k),indexmaxcorr(k)]=max(cctemp);
%close
end
[mm,im]= max(maxcorr);
if mm > Thfusione
% fprintf('Fuso il template %d (occ. %d) con quello %d (occ. %d)\n',indexA,Ttot(indexA,1),im,Ttot(im,1));
% fprintf(' - Risultato fusione in pos. %d (occ. %d)\n',indexA,Ttot(indexA,1)+Ttot(im,1));
estrattoy = tmp(indexmaxcorr(im):indexmaxcorr(im)+LEN-1);
%figure; plot(estrattoy); hold on; plot(A(im,:),'r')
A(indexA,:) = synchronizedWAVG(estrattoy,A(im,:),Ttot(indexA,1),Ttot(im,1));
%plot(A(indexA,:),'g');
Ttot(indexA,1) = Ttot(indexA,1)+Ttot(im,1);
A(im,:)=A(Nt,:);
Ttot(im,1)=Ttot(Nt,1);
A(Nt,:)=0;
Ttot(Nt,1)=0;
Nt=Nt-1;
indexA=1;
else
indexA=indexA+1;
end
end
% fprintf('Numero di template finali: %d\n', Nt);
% fprintf('Occorrenze per template finali:\n');
% for i=1:Nt
% fprintf('Template %d: %d\n',i,Ttot(i,1));
% end
Apost = zeros(NumTempl,LEN);
Atemp=A;
Ttottemp = Ttot;
Ttotpost = zeros(NumTempl,1);
% applica riduzione numero di classi
for i = 1 : NumTempl
[m,idx] = max(Ttottemp);
Ttotpost(i) = m;
Apost(i,:)=Atemp(idx,:);
Ttottemp(idx) = [];
Atemp(idx,:) = [];
end
clear Atemp
clear Ttottemp
% fprintf('-----------------------------------------------------------\n');
% fprintf('Riduzione numero di template.\n');
% fprintf('Numero finale di template: %d\n', length(Ttotpost));
% fprintf('Numero finale di occorrenze totali: %d\n', sum(Ttotpost));
% fprintf('Occorrenze per template:\n');
for i=1:length(Ttotpost)
% fprintf('Template %d: %d\n',i,Ttotpost(i,1));
end
% fprintf('-----------------------------------------------------------\n\n\n\n\n');
% close(hwait2);
% Template matching continuo
% if tmatch_on_den~=0
% %% Template matching sul segnale denoised
% BUFF = denoised;
% else
% %% Template matching sul segnale originale senza contare il WD
% BUFF = signal;
% end
BUFF=original_d;
for k=1:NumTempl %numtempl è 2
cctemp=[];
[mA,iA]=max(Apost(k,:));
cctemp = pearsoncoeff(BUFF,Apost(k,:));
cctemp=cctemp.*(abs(cctemp) > Thcross); %hard thresholding della crosscorrelazione
j=1;
h=1;
while j<length(cctemp)
if cctemp(j)>0
start_m=j;
while cctemp(j)>0 && j<length(cctemp)
end_m=j;
j = j+1;
end
[mp,ip]=max(cctemp(start_m:end_m));
occ(k,h)=ip+start_m-1;
occorrenze_finali(k,1)=h;
h=h+1;
end
j=j+1;
end
end
else
Ttotpost=0;
Ttot=0;
occ=0;
Apost=0;
Nt=0;
occorrenze_finali=0;
end
end
function [r] = pearsoncoeff(x,y)
sx = size(x);
sy = size(y);
if min(size(x)) > 1
error('Impossibile usare la funzione su dati matriciali!')
return
end
if min(size(y)) > 1
error('Impossibile usare la funzione su dati matriciali!')
return
end
if sx(1) > sx(2)
x=x';
end
if sy(1) > sy(2)
y=y';
end
if length(x) < length(y) % il vettore x deve essere il più lungo
tmp=y;
y=x;
x=tmp;
end
ly =length(y);
lr = length(x)-ly+1;
r = zeros(1,lr);
stdy = std(y);
meany = mean(y);
yc = y - meany;
for i=1:lr
stdx = std(x(i:i+length(y)-1));
meanx = mean(x(i:i+length(y)-1));
xc = x(i:i+length(y)-1) - meanx;
num = sum((1/(ly-1))*xc.*yc);
r(i)=num/(stdy*stdx);
end
end
function scaling = scal_th(scaling_type, level, buffer_for_threshold, rms_sc)
switch scaling_type
case 1
scaling = median(abs(buffer_for_threshold(:,level))) / 0.6745;
case 2
scaling = 1.4826 * quantile(buffer_for_threshold(:,level),.75);
case 3
scaling = std(buffer_for_threshold(:,level));
case 4
scaling = 1.4826 * median(abs(buffer_for_threshold(:,level)-median(buffer_for_threshold(:,level))));
case 5
scaling = rms_sc(level) * norm(buffer_for_threshold(:,level))/sqrt(length(buffer_for_threshold(:,level)));
otherwise scaling = 1;
end
end
function res = standardize(x)
res = (x-mean(x))/std(x);
end
function u = synchronizedAVG(oldu,y,n)
loldu = length(oldu);
ly = length(y);
if loldu ~= ly
error('Arrays must have the same length');
end
if (min(size(oldu)) ~= 1) || (min(size(y)) ~= 1)
error('Only arrays, not matrices!');
end
% u=((oldu*n)+y)/(n+1);
if(n>60)
u=y;
else
u=((oldu*n)+y)/(n+1);
end
end
function u = synchronizedWAVG(firstsig,secondsig,wfirst,wsecond)
N=wfirst+wsecond;
u=(firstsig*wfirst/N)+(secondsig*wsecond/N);
end
function [y]=upsampling(x)
l=length(x);
n=2*l;
y=zeros(1,n);
for u=1:l
y(2*u-1)=x(u);
end
end
function [soglia]=sogliatrovapiccoR_offline(segnale,G)
soglia=[];
i=1;
while(i+1024)<length(segnale)
if((i-1024)>0)
% B=sort(segnale(i-1023:i+1024));
% r=G*rms(B(10:end-10));
r=G*mean(segnale(i-1023:i+1024));
else
% B=sort(segnale(i:i+2*1024-1));
% r=G*rms(B(10:end-10));
r=G*mean(segnale(i:i+2*1024-1));
end
if r<0.02;
r=0.02;
end
soglia(i:i+1024)=r;
i=i+256;
end
soglia(i:length(segnale))=r;
end
function [yf]=media_mobile(x,N)
b=(1/N)* ones(1,N);
a=1;
yf=filter(b,a,x);
end
function [chann] = ChannelSelectionOrCombination(num_occ1,num_occ2, num_occ3,num_occ4)
A=[num_occ1(2);num_occ2(2); num_occ3(2); num_occ4(2)];
% A=[num_occ1(1);num_occ2(1); num_occ3(1); num_occ4(1)];
[k,chann]=max(A);
end
function r=rms(x)
r=norm(x)/sqrt(length(x));
end
function [FQRS]=correction(SelectedResidual,FQRS)
%@1000Hz
R=10*2; %numero pari
for r=1:length(FQRS)
in=FQRS(r);
max_loc=[];
ind_max=[];
min_loc=[];
ind_min=[];
mx=1;
mi=1;
if(((in+R)<length(SelectedResidual))&&((in-R)>0))
for hn=0:(2*R-4) %2*R+1 elementi
%ricerca massimi locali
if((SelectedResidual(in-R+hn)<=SelectedResidual(in-R+hn+1))&&(SelectedResidual(in-R+hn+1)<=SelectedResidual(in-R+hn+2))...
&&(SelectedResidual(in-R+hn+3)<=SelectedResidual(in-R+hn+2))&&(SelectedResidual(in-R+hn+4)<=SelectedResidual(in-R+hn+3)))
max_loc(mx)=SelectedResidual(in-R+hn+2);
ind_max(mx)=in-R+hn+2;
mx=mx+1;
end
if((SelectedResidual(in-R+hn)>=SelectedResidual(in-R+hn+1))&&(SelectedResidual(in-R+hn+1)>=SelectedResidual(in-R+hn+2))...
&&(SelectedResidual(in-R+hn+3)>=SelectedResidual(in-R+hn+2))&&(SelectedResidual(in-R+hn+4)>=SelectedResidual(in-R+hn+3)))
min_loc(mx)=SelectedResidual(in-R+hn+2);
ind_min(mx)=in-R+hn+2;
mi=mi+1;
end
end
end
%condizione vettore vuoto (analizzare morfologia picco qrs fetale
%rispetto a picco di rumore: dovrebbe essere più ampio! quindi analisi
%su più campioni invece che solo 2 a dx e 2 a sx?
MM=0;
MI=0;
if(isempty(max_loc))
else
[MM,MI]=max(abs(max_loc));
end
mm=0;
mi=0;
if(isempty(min_loc))
else
[mm,mi]=max(abs(min_loc));
end
if((MM>mm)&&(MM>0))
FQRS(r)=ind_max(MI);
elseif((mm>MM)&&(mm>0))
FQRS(r)=ind_min(mi);
end
end
end
function [c, vett_soglia]=qrs_detector_wd(x)
[c]=estrazioneFS(x);
[vett_soglia]=sogliatrovapiccoR_offline(c,0.8);
end
function [c]=estrazioneFS(x)
y0=derivatore_elementare(x);
y0=abs(y0);
b1 = [1 0 -2 0 1];
a1 = 1;
y1 = filter(b1,a1,x);
y1 = abs(y1);
y0 = [0,y0(1:end-1)];
y2 = 1.3*y0 + 1.1*y1;
c=media_mobile(y2,10);
end
function [yf]=derivatore_elementare(x)
yf=filter([.5 -.5],1,x);
end
%
% function[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_v2(occ,stop_cond,thRR,gamma,starting_delay )
% occtmp=0;
% occchk=0;
% RRm=0;
% count_removed=0;
% count_added=0;
% if nargin<4
% thRR=20;
% gamma=1/4;
% end
% noise=0;
% if size(occ,1)>size(occ,2)
% occ=occ';
% end
% occtmp=occ(1,occ>0); %taglio la coda di eventuali zeri
% RRist=occtmp(2:end)-occtmp(1:end-1); %trovo gli RR istantanei
% RRm=round(median(RRist)); %mediana RR starting value per autoregressivo
% %RRm=100;%%%%%%%%%%%%%%%%%%%%%%%%%Solo per test.
% delta=abs(RRist-RRm); %identifico lo scostamento di ogni distanza RR dal valore mediano
% occchk=zeros(size(delta)); %creo vettore di check su tale scostamento(0=fuori tolleranza)
% occchk(delta<=thRR)=1; %come sopra (1=ok)
% start=find(occchk, 1, 'first'); %prendo il primo elemento ok e parto dalì
% if start+2 < length(occchk)
% while occchk(start)+occchk(start+1)+occchk(start+2) ~= 3
% start = start+1;
% if start+2 >= length(occchk)
% noise = 1;
% break;
% end
% end
% end
% start = start + 1;
%
%
% %prima ragioniamo in avanti (da start in poi), poi, se necessario,andremo
% %ai punti che precedono start.
% if noise == 0
% count_removed = 0;
% count_added = 0;
% i=start;
% RRm = occtmp(i+1)-occtmp(i);
% while i<length(occtmp)-2 %fino alla fine del vettore
%
% % stem(occtmp(1:end-1),occchk,'r')
% if occchk(i) ~= 0 %se la distanza fra l'i+1 e l'i è ok per qualche motivo...
% %non può essercene uno migliore intorno solo all'inizio, ma a
% %regime sì. Quindi...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi la prossima occorrenza
% nextR = occtmp(i) + RRm;
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i+1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j+1;
% if j>length(occtmp)
% break
% end
% end
% %cancello tutti i picchi nell'intorno del migliore (uno almeno
% %lo trovo, sennò non ci sarebbe stato un occchk=1
% for aux=i+1:j-1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% %sistemo i vettori occchk e occtmp
% if(i<length(occtmp)-2)
% break;
% end
% if j-1>=i+2 %se ne ho trovato solo uno lo lascio indicato com'è
% if abs(occtmp(i+2)-occtmp(i+1)-RRm) < thRR
% occchk(i+1)=1;
% else
% occchk(i+1)=0;
% end
% end
%
% %aggiorno l'autoregressivo
% RRm=round(RRm*(1-gamma)+(occtmp(i+1)-occtmp(i))*gamma);
% else %se la distanza fra l'i+1 e l'i è fuori tolleranza...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi la prossima occorrenza
% nextR = occtmp(i) + RRm;
%
% %quindi tolgo tutto quello fra il primo picco "buono" e il margine
% %inferiore di tolleranza rispetto a dove dovrebbe essere il
% %prossimo picco
% j=i+1; %mi posiziono sulla prossima occorrenza
% while occtmp(j) < nextR - thRR %fino a che la distanza fra due occorrenze non supera la zona "buona" intorno al prossimo picco presunto
% occtmp(j)=60000; %marco per poi rimuovere
% occchk(j)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% j=j+1; %provo ad andre avanti di uno
% if j>length(occtmp)
% break
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% if abs(occtmp(i+1)-occtmp(i)-RRm) < thRR
% % if abs(occtmp(i+1)-occtmp(i)-nextR) < thRR
% occchk(i)=2;
% else
% occchk(i)=0;
% end
%
% nextR = occtmp(i) +RRm;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i+1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j+1;
% if j>length(occtmp)
% break
% end
% end
% if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
% %devo aggiungere un picco nella posizione presunta
% occtmp=[occtmp(1:i),nextR,occtmp(i+1:end)];
% occchk=[occchk(1:i),3,occchk(i+1:end)]; %col codice 3 identifico un picco che è stato aggiunto
% count_added = count_added+1;
% if abs(occtmp(i+2)-occtmp(i+1)-RRm) < thRR
% occchk(i+1)=3;
% else
% occchk(i+1)=0;
% end
% occchk(i)=3;
% else %ho trovato un picco molto prossimo alla posizione presunta
% %cancello tutti gli altri trovati
% for aux=i+1:j-1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% if(i<length(occtmp)-2)
% break;
% end
% %sistemo i vettori occchk e occtmp
% if j-1>=i+2 %se ne ho trovato solo uno lo lascio indicato com'è
% if abs(occtmp(i+2)-occtmp(i+1)-RRm) < thRR
% occchk(i+1)=1;
% else
% occchk(i+1)=0;
% end
% end
% end
% end
% i=i+1;
% end
% %coda se non sono state trovate occorrenze fino alla fine del segnale
% while stop_cond - occtmp(length(occtmp)) > RRm
% nextR = occtmp(length(occtmp)) + RRm;
% occtmp=[occtmp,nextR];
% occchk=[occchk,3]; %col codice 3 identifico un picco che è stato aggiunto
% count_added = count_added+1;
% end
%
%
% % adesso torniamo indietro
% i=start;
% RRm = occtmp(i+1)-occtmp(i);
% %RRm=round(median(RRist)); %mediana RR starting value per autoregressivo
% %RRm=100;
% while i>3 %fino alla testa del vettore (corretto! se metto 1 da errore, indici negativi)
%
% % stem(occtmp(1:end-1),occchk,'r')
% if occchk(i-1) ~= 0 %se la distanza fra l'i-1 e l'i è ok per qualche motivo...
% %non può essercene uno migliore intorno solo all'inizio, ma a
% %regime sì. Quindi...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi la precedente occorrenza
% nextR = occtmp(i) - RRm;
% if(nextR<starting_delay)
% break
% end
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i-1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j-1;
% if j<1
% break
% end
% end
% %cancello tutti i picchi nell'intorno del migliore (uno almeno
% %lo trovo, sennò non ci sarebbe stato un occchk=1
% for aux=i-1:-1:j+1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% %sistemo i vettori occchk e occtmp
% if j+1<i-1 %se ne ho trovato solo uno lo lascio indicato com'è
% if abs(occtmp(i-1)-occtmp(i-2)-RRm) < thRR
% occchk(i-2)=1;
% else
% occchk(i-2)=0;
% end
% end
%
% %aggiorno l'autoregressivo
% RRm=round(RRm*(1-gamma)+(occtmp(i)-occtmp(i-1))*gamma);
% else %se la distanza fra l'i e l'i-1 è fuori tolleranza...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi
% %la prossima occorrenza
% nextR = occtmp(i) - RRm;
%
% %quindi tolgo tutto quello fra il primo picco "buono" e il margine
% %inferiore di tolleranza rispetto a dove dovrebbe essere il
% %prossimo picco
% j=i-1; %mi posiziono sulla prossima occorrenza
% while occtmp(j) >= nextR + thRR %fino a che la distanza fra due occorrenze non supera la zona "buona" intorno al prossimo picco presunto
% occtmp(j)=60000; %marco per poi rimuovere
% occchk(j)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% j=j-1; %provo ad andre avanti di uno
% if j<1
% break
% end
% end
% if abs(occtmp(i)-occtmp(j)-RRm) <thRR%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% occchk(j)=2;
% else
% occchk(j)=0;
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
%
% nextR = occtmp(i) - RRm;
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i-1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j-1;
% if j<1
% break
% end
% end
% if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
% %devo aggiungere un picco nella posizione presunta
% occtmp=[occtmp(1:i-1),nextR,occtmp(i:end)];
% occchk=[occchk(1:i-1),3,occchk(i:end)]; %col codice 3 identifico un picco che è stato aggiunto%%%%%%%%%%%%%%
% count_added = count_added+1;
% if abs(occtmp(i)-occtmp(i-1)-RRm) < thRR %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% occchk(i-1)=3;
% else
% occchk(i-1)=0;
% end
% i=i+1;
% else %ho trovato un picco molto prossimo alla posizione presunta
% %cancello tutti gli altri trovati
% for aux=i-1:-1:j+1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% %sistemo i vettori occchk e occtmp
% if j+1<i-1
% i=j+2;
% if abs(occtmp(i)-occtmp(i-1)-RRm) < thRR
% occchk(i-1)=1;
% else
% occchk(i-1)=0;
% end
% end
% end
% end
% i=i-1;
% end
% %coda se non inizia subito il vettore delle occorrenze
% while occtmp(1) > RRm
% nextR = occtmp(1) - RRm;
% if(nextR<starting_delay)
% break
% end
% occtmp=[nextR,occtmp];
% occchk=[3,occchk]; %col codice 3 identifico un picco che è statoaggiunto
% count_added = count_added+1;
% end
%
% end
% end
%
% function[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_v2(occ,stop_cond,thRR,gamma,starting_delay)
% occtmp=0;
% occchk=0;
% RRm=0;
% count_removed=0;
% count_added=0;
% noise=0;
% if size(occ,1)>size(occ,2)
% occ=occ';
% end
% occtmp=occ(1,occ>0); %taglio la coda di eventuali zeri
% RRist=occtmp(2:end)-occtmp(1:end-1); %trovo gli RR istantanei
% RRm=round(median(RRist)); %mediana RR starting value per autoregressivo
% %RRm=100;%%%%%%%%%%%%%%%%%%%%%%%%%Solo per test.
% delta=abs(RRist-RRm); %identifico lo scostamento di ogni distanza RR dal valore mediano
% occchk=zeros(size(delta)); %creo vettore di check su tale scostamento(0=fuori tolleranza)
% occchk(delta<=thRR)=1; %come sopra (1=ok)
% start=find(occchk, 1, 'first'); %prendo il primo elemento ok e parto dalì
% if start+2 < length(occchk)
% while occchk(start)+occchk(start+1)+occchk(start+2) ~= 3
% start = start+1;
% if start+2 >= length(occchk)
% noise = 1;
% break;
% end
% end
% end
%
% start = start+1;
%
% %prima ragioniamo in avanti (da start in poi), poi, se necessario,andremo
% %ai punti che precedono start.
% if noise == 0
% count_removed = 0;
% count_added = 0;
% i=start;
% RRm = occtmp(i+1)-occtmp(i);
% while i<length(occtmp)-2 %fino alla fine del vettore
%
% if occchk(i) ~= 0 %se la distanza fra l'i+1 e l'i è ok per qualche motivo...
% %non può essercene uno migliore intorno solo all'inizio, ma a
% %regime sì. Quindi...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi la prossima occorrenza
% nextR = occtmp(i) + RRm;
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i+1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j+1;
% if j>length(occtmp)
% break
% end
% end
% %cancello tutti i picchi nell'intorno del migliore (uno almeno
% %lo trovo, sennò non ci sarebbe stato un occchk=1
% for aux=i+1:j-1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% %sistemo i vettori occchk e occtmp
% if(i>length(occtmp)-2)
% break;
% end
% if j-1>=i+2 %se ne ho trovato solo uno lo lascio indicato com'è
% if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
% occchk(i+1)=1;
% else
% occchk(i+1)=0;
% end
% end
%
% %aggiorno l'autoregressivo
% RRm=round(RRm*(1-gamma)+(occtmp(i+1)-occtmp(i))*gamma);
% else %se la distanza fra l'i+1 e l'i è fuori tolleranza...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi la prossima occorrenza
% nextR = occtmp(i) + RRm;
%
% %quindi tolgo tutto quello fra il primo picco "buono" e il margine
% % inferiore di tolleranza rispetto a dove dovrebbe essere il
% %prossimo picco
% j=i+1; %mi posiziono sulla prossima occorrenza
% while occtmp(j) < nextR - thRR %fino a che la distanza fra due occorrenze non supera la zona "buona" intorno al prossimo picco presunto
% occtmp(j)=60000; %marco per poi rimuovere
% occchk(j)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% j=j+1; %provo ad andre avanti di uno
% if j>length(occtmp)
% break
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% if abs(occtmp(i+1)-occtmp(i)-RRm) <= thRR
% % if abs(occtmp(i+1)-occtmp(i)-nextR) < thRR
% occchk(i)=2;
% else
% occchk(i)=0;
% end
%
% nextR = occtmp(i) +RRm;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i+1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j+1;
% if j>length(occtmp)
% break
% end
% end
% if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
% %devo aggiungere un picco nella posizione presunta
% occtmp=[occtmp(1:i),nextR,occtmp(i+1:end)];
% occchk=[occchk(1:i),3,occchk(i+1:end)]; %col codice 3 identifico un picco che è stato aggiunto
% count_added = count_added+1;
% if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
% occchk(i+1)=3;
% else
% occchk(i+1)=0;
% end
% occchk(i)=3;
% else %ho trovato un picco molto prossimo alla posizione presunta
% %cancello tutti gli altri trovati
% for aux=i+1:j-1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% if(i>length(occtmp)-2)
% break;
% end
% %sistemo i vettori occchk e occtmp
% if j-1>=i+2 %se ne ho trovato solo uno lo lascio indicato com'è
% if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
% occchk(i+1)=1;
% else
% occchk(i+1)=0;
% end
% end
% end
% end
% i=i+1;
% end
% %coda se non sono state trovate occorrenze fino alla fine del segnale
% while stop_cond - occtmp(length(occtmp)) > RRm
% nextR = occtmp(length(occtmp)) + RRm;
% occtmp=[occtmp,nextR];
% occchk=[occchk,3]; %col codice 3 identifico un picco che è stato aggiunto
% count_added = count_added+1;
% end
%
%
% % adesso torniamo indietro
% i=start;
% RRm = occtmp(i+1)-occtmp(i);
% %RRm=round(median(RRist)); %mediana RR starting value per autoregressivo
% %RRm=100;
% while i>3 %fino alla testa del vettore (corretto! se metto 1 da errore, indici negativi)
%
% if occchk(i-1) ~= 0 %se la distanza fra l'i-1 e l'i è ok per qualche motivo...
% %non può essercene uno migliore intorno solo all'inizio, ma a
% %regime sì. Quindi...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi la precedente occorrenza
% nextR = occtmp(i) - RRm;
% if(nextR<starting_delay)
% break
% end
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i-1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j-1;
% if j<1
% break
% end
% end
% %cancello tutti i picchi nell'intorno del migliore (uno almeno
% %lo trovo, sennò non ci sarebbe stato un occchk=1
% for aux=i-1:-1:j+1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% %sistemo i vettori occchk e occtmp
% if j+1<i-1 %se ne ho trovato solo uno lo lascio indicato com'è
% if abs(occtmp(i-1)-occtmp(i-2)-RRm) <= thRR
% occchk(i-2)=1;
% else
% occchk(i-2)=0;
% end
% end
%
% %aggiorno l'autoregressivo
% RRm=round(RRm*(1-gamma)+(occtmp(i)-occtmp(i-1))*gamma);
% else %se la distanza fra l'i e l'i-1 è fuori tolleranza...
% %provo a vedere con l'autoregressivo dove dovrebbe trovarsi
% %la prossima occorrenza
% nextR = occtmp(i) - RRm;
%
% %quindi tolgo tutto quello fra il primo picco "buono" e il margine
% %inferiore di tolleranza rispetto a dove dovrebbe essere il
% %prossimo picco
% j=i-1; %mi posiziono sulla prossima occorrenza
% while occtmp(j) >= nextR + thRR %fino a che la distanza fra due occorrenze non supera la zona "buona" intorno al prossimo picco presunto
% occtmp(j)=60000; %marco per poi rimuovere
% occchk(j)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% j=j-1; %provo ad andre avanti di uno
% if j<1
% break
% end
% end
% if abs(occtmp(i)-occtmp(j)-RRm) <= thRR%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% occchk(j)=2;
% else
% occchk(j)=0;
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
%
% nextR = occtmp(i) - RRm;
%
% %provo a mettermi nell'intorno di tolleranza sulla posizione
% %stimata del prossimo picco per "fare pulizia" se è il caso
% j=i-1;
% best_occ = [];
% best_idx = [];
% while abs(occtmp(j)-nextR) <= thRR
% if isempty(best_occ) %inizializzazione
% best_occ = abs(occtmp(j)-nextR);
% best_idx = j;
% else %se c'è più di un picco nella fascia di tolleranza
% if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
% best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
% best_idx = j; %conservo l'indice
% end
% end
% j=j-1;
% if j<1
% break
% end
% end
% if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
% %devo aggiungere un picco nella posizione presunta
% occtmp=[occtmp(1:i-1),nextR,occtmp(i:end)];
% occchk=[occchk(1:i-1),3,occchk(i:end)]; %col codice 3identifico un picco che è stato aggiunto%%%%%%%%%%%%%%
% count_added = count_added+1;
% if abs(occtmp(i)-occtmp(i-1)-RRm) <= thRR %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% occchk(i-1)=3;
% else
% occchk(i-1)=0;
% end
% i=i+1;
% else %ho trovato un picco molto prossimo alla posizione presunta
% %cancello tutti gli altri trovati
% for aux=i-1:-1:j+1
% if aux ~= best_idx
% occtmp(aux)=60000; %marco per poi rimuovere
% occchk(aux)=60000; %marco per poi rimuovere
% count_removed = count_removed+1; %conto i rimossi
% end
% end
% occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
% occchk(occchk==60000)=[]; %rimuovo quelli marcati
% %sistemo i vettori occchk e occtmp
% if j+1<i-1
% i=j+2;
% if abs(occtmp(i)-occtmp(i-1)-RRm) <= thRR
% occchk(i-1)=1;
% else
% occchk(i-1)=0;
% end
% end
% end
% end
% i=i-1;
% end
% %coda se non inizia subito il vettore delle occorrenze
% while occtmp(1) > RRm
% nextR = occtmp(1) - RRm;
% if(nextR<starting_delay)
% break
% end
% occtmp=[nextR,occtmp];
% occchk=[3,occchk]; %col codice 3 identifico un picco che è statoaggiunto
% count_added = count_added+1;
% end
%
% end
% end
%
%
function[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_cor_caller(ecg_ref,mark,occ,stop_cond,thRR,gamma,starting_delay)
[preval, idx_preval, len_longest, type] = prevalence(mark);
if preval == 1
other = 2;
else
other = 1;
end
switch type
case 1
% c'è solo una classe
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_2classes(ecg_ref,...
mark,occ,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,len_longest);
case 20
% situazione generica a due classi
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_2classes(ecg_ref,...
mark,occ,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,len_longest);
case 21
% c'è una classe molto più rappresentata dell'altra
i = find(mark==other);
mark_preval = mark;
occ_preval = occ;
mark_preval(i) = [];
occ_preval(i) = [];
[idx_preval, length_longest_preval] =longest_seq(mark_preval,preval);
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_2classes(ecg_ref,...
mark_preval,occ_preval,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,length_longest_preval);
case 22
% siamo in condizioni di alternanza
% pulisce delle occorrenze dell'altro template
i = find(mark==other);
mark_preval = mark;
occ_preval = occ;
mark_preval(i) = [];
occ_preval(i) = [];
[idx_preval, length_longest_preval] =longest_seq(mark_preval,preval);
[occtmp1,occchk1,RRm1,count_removed1,count_added1,noise1]=periodicity_correction_2classes(ecg_ref,...
mark_preval,occ_preval,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,length_longest_preval);
% pulisce delle occorrenze dell'altro template
i = find(mark==preval);
mark_other = mark;
occ_other = occ;
mark_other(i) = [];
occ_other(i) = [];
[idx_other, length_longest_other] = longest_seq(mark_other,other);
[occtmp2,occchk2,RRm2,count_removed2,count_added2,noise2]=periodicity_correction_2classes(ecg_ref,...
mark_other,occ_other,stop_cond,thRR,gamma,starting_delay,preval,idx_other,length_longest_other);
% confronta le sequenze per capire quale è materna
if RRm1>RRm2
occtmp = occtmp1;
occchk = occchk1;
RRm = RRm1;
count_removed = count_removed1;
count_added = count_added1;
noise = noise1;
else
occtmp = occtmp2;
occchk = occchk2;
RRm = RRm2;
count_removed = count_removed2;
count_added = count_added2;
noise = noise2;
end
otherwise % type = 0 (non ci sono proprio template riconosciuti)
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_v2(ecg_ref,occ,stop_cond,thRR,gamma,starting_delay,1,1);
end
end
function[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_cor_callerFETUS(ecg_ref,mark,occ,stop_cond,thRR,gamma,starting_delay)
[preval, idx_preval, len_longest, type] = prevalence(mark);
if preval == 1
other = 2;
else
other = 1;
end
switch type
case 1
% c'è solo una classe
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_2classes(ecg_ref,...
mark,occ,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,len_longest);
case 20
% situazione generica a due classi
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_2classes(ecg_ref,...
mark,occ,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,len_longest);
case 21
% c'è una classe molto più rappresentata dell'altra
i = find(mark==other);
mark_preval = mark;
occ_preval = occ;
mark_preval(i) = 0;
%occ_preval(i) = [];
[idx_preval, length_longest_preval] =longest_seq(mark_preval,preval);
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_2classes(ecg_ref,...
mark_preval,occ_preval,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,length_longest_preval);
case 22
% siamo in condizioni di alternanza
% pulisce delle occorrenze dell'altro template
i = find(mark==other);
mark_preval = mark;
occ_preval = occ;
mark_preval(i) = 0;
%occ_preval(i) = [];
[idx_preval, length_longest_preval] =longest_seq(mark_preval,preval);
[occtmp1,occchk1,RRm1,count_removed1,count_added1,noise1]=periodicity_correction_2classes(ecg_ref,...
mark_preval,occ_preval,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,length_longest_preval);
% pulisce delle occorrenze dell'altro template
i = find(mark==preval);
mark_other = mark;
occ_other = occ;
mark_other(i) = 0;
%occ_other(i) = [];
[idx_other, length_longest_other] = longest_seq(mark_other,other);
[occtmp2,occchk2,RRm2,count_removed2,count_added2,noise2]=periodicity_correction_2classes(ecg_ref,...
mark_other,occ_other,stop_cond,thRR,gamma,starting_delay,preval,idx_other,length_longest_other);
% confronta le sequenze per capire quale è fetale
if RRm1>RRm2
occtmp = occtmp2;
occchk = occchk2;
RRm = RRm2;
count_removed = count_removed2;
count_added = count_added2;
noise = noise2;
else
occtmp = occtmp1;
occchk = occchk1;
RRm = RRm1;
count_removed = count_removed1;
count_added = count_added1;
noise = noise1;
end
otherwise % type = 0 (non ci sono proprio template riconosciuti)
[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_v2(ecg_ref,occ,stop_cond,thRR,gamma,starting_delay,1,1);
end
end
%%
function[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_2classes(ecg_ref,...
mark,occ,stop_cond,thRR,gamma,starting_delay,preval,idx_preval,len_longest)
occtmp=0;
occchk=0;
RRm=0;
count_removed=0;
count_added=0;
noise=0;
if size(occ,1)>size(occ,2)
occ=occ';
end
occtmp=occ(1,occ>0); %taglio la coda di eventuali zeri
RRist = occtmp(2:end)-occtmp(1:end-1); %trovo gli RR istantanei solo per la mediana
if preval == -1 % non c'è una classe prevalente, ma ci sono 2 classi
current = mark(idx_preval);
[start, len] =reg_analysis(occtmp);
if len_longest >= 15
RRm = round(median(RRist(idx_preval:idx_preval+len_longest-2)));
else
if len > 1
RRm=round(median(RRist(start:start+len-2))); %mediana RR startingvalue per autoregressivo
else
RRm=RRist(idx_preval);
end
end
else
current = -1;
[y_n, idx_preval_t, len_longest_t] = preval_zeros(mark);
if y_n == 1
[start, len] =reg_analysis(occtmp);
idx_preval = start;
len_longest = len;
RRm=round(median(RRist(start:start+len-2))); %mediana RR starting value per autoregressivo
else
if len_longest > 1
RRm = round(median(RRist(idx_preval:idx_preval+len_longest-2)));
else
RRm = RRist(idx_preval);
end
end
end
RRmorig=RRm;
RRist=occtmp(2:end)-occtmp(1:end-1); %trovo gli RR istantanei
delta=abs(RRist-RRm); %identifico lo scostamento di ogni distanza RR dal valore mediano
occchk=zeros(size(delta)); %creo vettore di check su tale scostamento(0=fuori tolleranza)
occchk(delta<=thRR)=1; %come sopra (1=ok)
% start=find(occchk, 1, 'first'); %prendo il primo elemento ok e partodalì
% if start+2 < length(occchk)
% while occchk(start)+occchk(start+1)+occchk(start+2) ~= 3
% start = start+1;
% if start+2 >= length(occchk)
% noise = 1;
% break;
% end
% end
% end
start = idx_preval;
%prima ragioniamo in avanti (da start in poi), poi, se necessario,andremo
%ai punti che precedono start.
if noise == 0
count_removed = 0;
count_added = 0;
i=start;
while i<length(occtmp)-2 %fino alla fine del vettore
% close all
% plot(ecg_ref)
% hold on
% plot(occ(1:end-1),ecg_ref(occ(1:end-1)),'og');
% plot(occtmp(1:end-1),occchk*100,'*r')
if occchk(i) ~= 0 %se la distanza fra l'i+1 e l'i è ok per qualchemotivo...
%non può essercene uno migliore intorno solo all'inizio, ma a
%regime sì. Quindi...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi laprossima occorrenza
nextR = occtmp(i) + RRm;
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i+1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è piùvicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j+1;
if j>length(occtmp)
break
end
end
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1) ma cerco
%di vedere se non sto togliendo uno un po' spostato
%coerente con i precedenti in favore di uno non coerente
if (~isempty(best_idx))
if current < 0
if (mark(best_idx) ~= preval) &&(any(mark(i+1:j-1)==preval))
% dovrei scegliere il preval più vicino
for aux=i+1:j-1
if mark(aux) ~= preval
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
end
end
[best_occ, pos] = min(abs(occtmp(i+1:j-1)-nextR));
pos = i + pos;
for aux=i+1:j-1
if aux ~= pos
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000;
count_removed = count_removed+1; %conto irimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
else
%cancello tutti i picchi nell'intorno del migliore(uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i+1:j-1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto irimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
else
if (mark(best_idx) ~= current) &&(any(mark(i+1:j-1)==current))
% dovrei scegliere il preval più vicino
for aux=i+1:j-1
if mark(aux) ~= current
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
end
end
[best_occ, pos] = min(abs(occtmp(i+1:j-1)-nextR));
pos = i + pos;
for aux=i+1:j-1
if aux ~= pos
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000;
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
else
%cancello tutti i picchi nell'intorno del migliore(uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
current = mark(best_idx);
for aux=i+1:j-1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto irimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
end
end
%sistemo i vettori occchk e occtmp
if(i>length(occtmp)-2)
break;
end
if j-1>i+1 %se ne ho trovato solo uno lo lascio indicato com'è
if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
occchk(i+1)=2;
else
occchk(i+1)=0;
end
end
%aggiorno l'autoregressivo
RRm=round(RRm*(1-gamma)+(occtmp(i+1)-occtmp(i))*gamma);
else %se la distanza fra l'i+1 e l'i è fuori tolleranza...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi la prossima occorrenza
nextR = occtmp(i) + RRm;
%quindi tolgo tutto quello fra il primo picco "buono" e ilmargine
%inferiore di tolleranza rispetto a dove dovrebbe essere il
%prossimo picco
j=i+1; %mi posiziono sulla prossima occorrenza%================================================================))))))))))))
while occtmp(j) < nextR - thRR %fino a che la distanza fra dueoccorrenze non supera la zona "buona" intorno al prossimo picco presunto
occtmp(j)=60000; %marco per poi rimuovere
occchk(j)=60000; %marco per poi rimuovere
mark(j)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
j=j+1; %provo ad andre avanti di uno
if j>length(occchk)
break
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[]; %rimuovo quelli marcati
if i > length(occtmp)-2
break
end
% if abs(occtmp(i+1)-occtmp(i)-RRm) <= thRR
% % if abs(occtmp(i+1)-occtmp(i)-nextR) < thRR
% occchk(i)=2;
% else
% occchk(i)=0;
% end
if abs(occtmp(i+1)-occtmp(i)-RRm) <= thRR
% if abs(occtmp(i+1)-occtmp(i)-nextR) < thRR
occchk(i)=2;
else
occchk(i)=0;
end
nextR = occtmp(i)+RRm;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i+1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j+1;
if j>length(occtmp)
break
end
end
if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
%devo aggiungere un picco nella posizione presunta
occtmp=[occtmp(1:i),nextR,occtmp(i+1:end)];
occchk=[occchk(1:i),3,occchk(i+1:end)]; %col codice 3 identifico un picco che è stato aggiunto
mark=[mark(1:i),-1,mark(i+1:end)]; %col codice -1 identificoun picco che è stato aggiunto quindi non ha passato template matching
count_added = count_added+1;
if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
occchk(i+1)=3;
else
occchk(i+1)=0;
end
occchk(i)=3;
else %ho trovato un picco molto prossimo alla posizione presunta
%cancello tutti gli altri trovati
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1) ma cerco
%di vedere se non sto togliendo uno un po' spostato
%coerente con i precedenti in favore di uno non coerente
if ~isempty(best_idx)
if current < 0
if (mark(best_idx) ~= preval) &&(any(mark(i+1:j-1)==preval))
% dovrei scegliere il preval più vicino
for aux=i+1:j-1
if mark(aux) ~= preval
occtmp(aux)=60000; %marco per poirimuovere
occchk(aux)=60000; %marco per poirimuovere
mark(aux)=60000; %marco per poirimuovere
end
end
[best_occ, pos] =min(abs(occtmp(i+1:j-1)-nextR));
pos = i + pos;
for aux=i+1:j-1
if aux ~= pos
occtmp(aux)=60000; %marco per poirimuovere
occchk(aux)=60000; %marco per poirimuovere
mark(aux)=60000;
count_removed = count_removed+1; %contoi rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quellimarcati
occchk(occchk==60000)=[]; %rimuovo quellimarcati
mark(mark==60000)=[];
else
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i+1:j-1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
else
if (mark(best_idx) ~= current) && (any(mark(i+1:j-1)==current))
% dovrei scegliere il preval più vicino
for aux=i+1:j-1
if mark(aux) ~= current
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
end
end
[best_occ, pos] =min(abs(occtmp(i+1:j-1)-nextR));
pos = i + pos;
for aux=i+1:j-1
if aux ~= pos
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000;
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
else
current = mark(best_idx);
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i+1:j-1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
end
end
%sistemo i vettori occchk e occtmp
if(i>length(occtmp)-2)
break;
end
if j-1>i+1
if abs(occtmp(i+1)-occtmp(i)-RRm) <= thRR
occchk(i)=2;
else
occchk(i)=0;
end
end
end
end
i=i+1;
end
occtmp(i+1:end)=[];
occchk(i:end)=[];
mark(i:end)=[];
%coda se non sono state trovate occorrenze fino alla fine del segnale
while stop_cond - occtmp(length(occtmp)) > RRm
nextR = occtmp(length(occtmp)) + RRm;
occtmp=[occtmp,nextR];
occchk=[occchk,3]; %col codice 3 identifico un picco che è stato aggiunto
mark=[mark,-1];%col codice -1 identifico un picco che è stato aggiunto
count_added = count_added+1;
end
% adesso torniamo indietro
i=start;
RRm = RRmorig;
while i>3 %fino alla testa del vettore (corretto! se metto 1 da errore,indici negativi)
% close all
% plot(ecg_ref)
% hold on
% plot(occ(1:end-1),ecg_ref(occ(1:end-1)),'og');
% plot(occtmp(1:end-1),occchk*100,'*r')
if occchk(i-1) ~= 0 %se la distanza fra l'i-1 e l'i è ok per qualche motivo...
%non può essercene uno migliore intorno solo all'inizio, ma a
%regime sì. Quindi...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi la precedente occorrenza
nextR = occtmp(i) - RRm;
if(nextR<starting_delay)
break
end
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i-1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j-1;
if j<1
break
end
end
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1) ma cerco
%di vedere se non sto togliendo uno un po' spostato
%coerente con i precedenti in favore di uno non coerente
if ~isempty(best_idx)
if preval < 0
if (mark(best_idx) ~= preval) &&(any(mark(j+1:i-1)==preval))
% dovrei scegliere il preval più vicino
for aux=i-1:-1:j+1
if mark(aux) ~= preval
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
end
end
[best_occ, pos] = min(abs(occtmp(j+1:i-1)-nextR));
pos = i + pos;
for aux = i-1:-1:j+1
if aux ~= pos
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000;
count_removed = count_removed+1; %conto irimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
else
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto irimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
else
if (mark(best_idx) ~= current) &&(any(mark(j+1:i-1)==current))
% dovrei scegliere il preval più vicino
for aux=i-1:-1:j+1
if mark(aux) ~= current
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
end
end
[best_occ, pos] = min(abs(occtmp(j+1:i-1)-nextR));
pos = i + pos;
for aux = i-1:-1:j+1
if aux ~= pos
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000;
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
else
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
current = mark(best_idx);
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
end
end
if i < 3
break
end
%sistemo i vettori occchk e occtmp
if j+1<i-1
if abs(occtmp(i-1)-occtmp(i-2)-RRm) <= thRR
occchk(i-2)=2;
else
occchk(i-2)=0;
end
end
%aggiorno l'autoregressivo
RRm=round(RRm*(1-gamma)+(occtmp(i)-occtmp(i-1))*gamma);
else %se la distanza fra l'i e l'i-1 è fuori tolleranza...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi
%la prossima occorrenza
nextR = occtmp(i) - RRm;
%quindi tolgo tutto quello fra il primo picco "buono" e il margine
%inferiore di tolleranza rispetto a dove dovrebbe essere il
%prossimo picco
j=i-1; %mi posiziono sulla prossima occorrenza
while occtmp(j) >= nextR + thRR %fino a che la distanza fra due occorrenze non supera la zona "buona" intorno al prossimo picco presunto
occtmp(j)=60000; %marco per poi rimuovere
occchk(j)=60000; %marco per poi rimuovere
mark(j)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
j=j-1; %provo ad andre avanti di uno
if j<1
break
end
end
if j>1
if abs(occtmp(i)-occtmp(j)-RRm) <=thRR%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
occchk(j)=2;
else
occchk(j)=0;
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[]; %rimuovo quelli marcati
nextR = occtmp(i) - RRm;
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i-1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è piùvicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j-1;
if j<1
break
end
end
if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
%devo aggiungere un picco nella posizione presunta
occtmp=[occtmp(1:i-1),nextR,occtmp(i:end)];
occchk=[occchk(1:i-1),3,occchk(i:end)]; %col codice 3 identifico un picco che è stato aggiunto%%%%%%%%%%%%%%
mark=[mark(1:i-1),-1,mark(1:end)]; %col codice -1 identifico un picco che è stato aggiunto quindi non ha passato template matching
count_added = count_added+1;
if abs(occtmp(i)-occtmp(i-1)-RRm) <= thRR
occchk(i-1)=3;
else
occchk(i-1)=0;
end
i=i+1;
else %ho trovato un picco molto prossimo alla posizione presunta
%cancello tutti gli altri trovati
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1) ma cerco
%di vedere se non sto togliendo uno un po' spostato
%coerente con i precedenti in favore di uno non
%coerente
if ~isempty(best_idx)
if preval < 0
if (mark(best_idx) ~= preval) &&(any(mark(j+1:i-1)==preval))
% dovrei scegliere il preval più vicino
for aux=i-1:-1:j+1
if mark(aux) ~= preval
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
end
end
[best_occ, pos] =min(abs(occtmp(j+1:i-1)-nextR));
pos = i + pos;
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000;
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
else
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
else
if (mark(best_idx) ~= current) &&(any(mark(j+1:i-1)==current))
% dovrei scegliere il preval più vicino
for aux=i-1:-1:j+1
if mark(aux) ~= current
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
end
end
[best_occ, pos] =min(abs(occtmp(j+1:i-1)-nextR));
pos = i + pos;
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000;
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
else
current = mark(best_idx);
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
mark(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
mark(mark==60000)=[];
end
end
end
%sistemo i vettori occchk e occtmp
if j+1<i-1
i=j+2;
if abs(occtmp(i)-occtmp(i-1)-RRm) <= thRR
occchk(i-1)=2;
else
occchk(i-1)=0;
end
end
end
end
i=i-1;
end
%coda se non inizia subito il vettore delle occorrenze
while occtmp(1) > RRm
nextR = occtmp(1) - RRm;
if(nextR<starting_delay)
break
end
occtmp=[nextR,occtmp];
occchk=[3,occchk]; %col codice 3 identifico un picco che è statoaggiunto
mark=[mark,-1];%col codice -1 identifico un picco che è stato aggiunto
count_added = count_added+1;
end
end
% close all
% plot(ecg_ref)
% hold on
% plot(occ(1:end-1),ecg_ref(occ(1:end-1)),'og');
% plot(occtmp(1:end-1),occchk*100,'*r')
end
% [preval] = prevalence(a)
%
% a partire dallo spezzone più lungo di "mark" che non contiene zeri,
% restituisce l'etichetta del template più rappresentato
%%
function [preval, idx_preval, len_longest, type] = prevalence(a)
% cerca la prima occorrenza non nulla, che etichetta come seed
ix = find(a, 1, 'first');
if isempty(ix)
preval=0;
idx_preval=1;
len_longest = 1;
type = 0; % vuol dire che non ci sono template che sono stati trovati
return;
end
% in caso contrario, la prima occorrenza ci dà il seme
seed = a(ix);
idx_preval_seed = ix;
if ~any((a~=seed)&(a~=0)) % se oltre a zeri c'è rappresentata solo unaclasse
preval = seed;
[idx_preval, len_longest] = longest_seq(a, seed);
type = 1; % vuol dire che c'è solo una classe
else % se invece ci sono due classi le etichetta come seed e other
if seed == 1
other = 2;
else
other = 1;
end
% a questo punto controllo se esiste una classe prevalente oppure se
% siamo in una condizione nella quale c'è sostanziale alternanza
seed_vec_idx = find(a==seed);
other_vec_idx = find(a==other);
if min(length(seed_vec_idx),length(other_vec_idx)) <0.3*max(length(seed_vec_idx),length(other_vec_idx))
% vuol dire che c'è una classe molto più rappresentata dell'altra
type = 21; % lo indico così
if length(seed_vec_idx) > length(other_vec_idx)
[idx_preval, len_longest] = longest_seq(a, seed);
preval = seed;
else
[idx_preval, len_longest] = longest_seq(a, other);
preval = other;
end
else % cioè se invece non esiste questa relazione, cerco se esiste alternanza
temp = a(a~=0); % tolgo gli zeri
count_alternances = 0;
for i = 1:length(temp)-1
if temp(i+1)~=temp(i)
count_alternances = count_alternances + 1;
end
end
if abs(count_alternances-length(temp)) < 0.7*length(temp)
% siamo in condizioni di alternanza quindi è meglio analizzare
% le due sequenze separatamente
type = 22; % indico l'alternanza
if length(seed_vec_idx) > length(other_vec_idx)
preval = seed;
idx_preval = 0;
len_longest = 0;
else
preval = other;
idx_preval = 0;
len_longest = 0;
end
else
% non siamo in condizioni di alternanza. Non possiamo sfruttare
% ulteriori informazioni in analisi di periodicità
type = 20;
no_preval = a;
no_preval(no_preval~=0)=1;
[idx_preval, len_longest] = longest_seq(no_preval, 1);
preval=-1;
end
end
end
end
%%
function [y_n, idx_preval, len_longest] = preval_zeros(a)
% cerca la prima occorrenza non nulla, che etichetta come seed
if ~any(a~=0)
y_n=1;
idx_preval=1;
len_longest = length(a);
return;
end
% in caso contrario, la prima occorrenza ci dà il seme
a(a~=0)=1;
zeros_vec_idx = find(a==0);
other_vec_idx = find(a==1);
if length(other_vec_idx) < 0.4*length(zeros_vec_idx)
y_n=1;
[idx_preval, len_longest] = longest_seq(a, 0);
else
y_n=0;
[idx_preval, len_longest] = longest_seq(a, 1);
end
end
%%
% function [] = match(QRSs, MQRS, thmm)
%
% thmm è la tolleranza in matching
function [mark] = match(QRSs, MQRS, thmm) %thmm 15---> ora è 15*4
if nargin <3
thmm=15;
end
mark=zeros(size(QRSs));
% tt=MQRS+25;
tt=MQRS+25*4;
% tt(tt==25)=1000000;
tt(tt==25*4)=1000000;
i=1;
while i<=length(mark)
m = min(min(tt));
if abs(QRSs(i)-m) < thmm
[r,c]=find(tt==m);
mark(i) = r(1,1);
tt(r,c)=1000000;
i=i+1;
elseif m <= QRSs(i)
[r,c]=find(tt==m);
tt(r,c)=1000000;
else
i=i+1;
end
end
end
%%
%%
function [start_longest, length_longest] = longest_seq(a, key)
a_max = 0;
i_start_max = 0;
a_count = 0;
i_start = 0;
for i=1:length(a)
if a(i) == key
a_count = a_count+1;
if a_count == 1
i_start = i;
end
else
if a_max < a_count
a_max = a_count;
i_start_max = i_start;
end
a_count = 0;
i_start = 0;
end
end
if a_count > a_max
i_start_max = i_start;
a_max = a_count;
end
start_longest = i_start_max;
length_longest = a_max;
end
%%
function [start, len] =reg_analysis(a)
d = a(2:end)-a(1:end-1);
c = d(2:end)-d(1:end-1);
c(c < 10) = 1;
c(c >= 10) = 0;
[start, len] = longest_seq(c, 1);
len = len+2;
end
%%
function M = dist_matrix(d)
l = length(d);
M=zeros(l,l);
for i = 1:l
for j = 1:l
M(i,j)=abs(d(i)-d(j));
end
end
end
function[occtmp,occchk,RRm,count_removed,count_added,noise]=periodicity_correction_v2(ecg_ref,...
occ,stop_cond,thRR,gamma,starting_delay,idx_preval,len_longest)
occtmp=0;
occchk=0;
RRm=0;
count_removed=0;
count_added=0;
noise=0;
if size(occ,1)>size(occ,2)
occ=occ';
end
occtmp=occ(1,occ>0); %taglio la coda di eventuali zeri
RRist=occtmp(2:end)-occtmp(1:end-1); %trovo gli RR istantanei
RRm=round(median(RRist)); %mediana RR starting value per autoregressivo
%RRm=100;%%%%%%%%%%%%%%%%%%%%%%%%%Solo per test.
delta=abs(RRist-RRm); %identifico lo scostamento di ogni distanza RR dalvalore mediano
occchk=zeros(size(delta)); %creo vettore di check su tale scostamento(0=fuori tolleranza)
occchk(delta<=thRR)=1; %come sopra (1=ok)
% start=find(occchk, 1, 'first'); %prendo il primo elemento ok e parto da lì
% if start+2 < length(occchk)
% while occchk(start)+occchk(start+1)+occchk(start+2) ~= 3
% start = start+1;
% if start+2 >= length(occchk)
% noise = 1;
% break;
% end
% end
% end
start = idx_preval;
%prima ragioniamo in avanti (da start in poi), poi, se necessario,andremo
%ai punti che precedono start.
if noise == 0
count_removed = 0;
count_added = 0;
i=start;
if len_longest >= 5
RRm = occtmp(i+1)-occtmp(i);
end
while i<length(occtmp)-2 %fino alla fine del vettore
%
% close all
% plot(ecg_ref)
% hold on
% plot(occ(1:end-1),ecg_ref(occ(1:end-1)),'og');
% plot(occtmp(1:end-1),occchk*100,'*r')
if occchk(i) ~= 0 %se la distanza fra l'i+1 e l'i è ok per qualchemotivo...
%non può essercene uno migliore intorno solo all'inizio, ma a
%regime sì. Quindi...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi la prossima occorrenza
nextR = occtmp(i) + RRm;
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i+1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j+1;
if j>length(occtmp)
break
end
end
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i+1:j-1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
%sistemo i vettori occchk e occtmp
if(i>length(occtmp)-2)
break;
end
if j-1>=i+2 %se ne ho trovato solo uno lo lascio indicato com'è
if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
occchk(i+1)=1;
else
occchk(i+1)=0;
end
end
%aggiorno l'autoregressivo
RRm=round(RRm*(1-gamma)+(occtmp(i+1)-occtmp(i))*gamma);
else %se la distanza fra l'i+1 e l'i è fuori tolleranza...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi la prossima occorrenza
nextR = occtmp(i) + RRm;
%quindi tolgo tutto quello fra il primo picco "buono" e il margine
%inferiore di tolleranza rispetto a dove dovrebbe essere il
%prossimo picco
j=i+1; %mi posiziono sulla prossima occorrenza
while occtmp(j) < nextR - thRR %fino a che la distanza fra due occorrenze non supera la zona "buona" intorno al prossimo picco presunto
occtmp(j)=60000; %marco per poi rimuovere
occchk(j)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
j=j+1; %provo ad andre avanti di uno
if j>length(occchk)
break
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
if abs(occtmp(i+1)-occtmp(i)-RRm) <= thRR
% if abs(occtmp(i+1)-occtmp(i)-nextR) < thRR
occchk(i)=2;
else
occchk(i)=0;
end
nextR = occtmp(i) +RRm;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i+1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j+1;
if j>length(occtmp)
break
end
end
if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
%devo aggiungere un picco nella posizione presunta
occtmp=[occtmp(1:i),nextR,occtmp(i+1:end)];
occchk=[occchk(1:i),3,occchk(i+1:end)]; %col codice 3 identifico un picco che è stato aggiunto
count_added = count_added+1;
if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
occchk(i+1)=3;
else
occchk(i+1)=0;
end
occchk(i)=3;
else %ho trovato un picco molto prossimo alla posizione presunta
%cancello tutti gli altri trovati
for aux=i+1:j-1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
if(i>length(occtmp)-2)
break;
end
%sistemo i vettori occchk e occtmp
if j-1>=i+2 %se ne ho trovato solo uno lo lascio indicato com'è
if abs(occtmp(i+2)-occtmp(i+1)-RRm) <= thRR
occchk(i+1)=1;
else
occchk(i+1)=0;
end
end
end
end
i=i+1;
end
%coda se non sono state trovate occorrenze fino alla fine del segnale
while stop_cond - occtmp(length(occtmp)) > RRm
nextR = occtmp(length(occtmp)) + RRm;
occtmp=[occtmp,nextR];
occchk=[occchk,3]; %col codice 3 identifico un picco che è stato aggiunto
count_added = count_added+1;
end
% adesso torniamo indietro
i=start;
if len_longest >= 5
RRm = occtmp(i+1)-occtmp(i);
end
%RRm=round(median(RRist)); %mediana RR starting value per autoregressivo
%RRm=100;
while i>3 %fino alla testa del vettore (corretto! se metto 1 da errore, indici negativi)
%
% close all
% plot(ecg_ref)
% hold on
% plot(occ(1:end-1),ecg_ref(occ(1:end-1)),'og');
% plot(occtmp(1:end-1),occchk*100,'*r')
if occchk(i-1) ~= 0 %se la distanza fra l'i-1 e l'i è ok per qualche motivo...
%non può essercene uno migliore intorno solo all'inizio, ma a
%regime sì. Quindi...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi la precedente occorrenza
nextR = occtmp(i) - RRm;
if(nextR<starting_delay)
break
end
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i-1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j-1;
if j<1
break
end
end
%cancello tutti i picchi nell'intorno del migliore (uno almeno
%lo trovo, sennò non ci sarebbe stato un occchk=1
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
%sistemo i vettori occchk e occtmp
if j+1<i-1 %se ne ho trovato solo uno lo lascio indicato com'è
if abs(occtmp(i-1)-occtmp(i-2)-RRm) <= thRR
occchk(i-2)=1;
else
occchk(i-2)=0;
end
end
%aggiorno l'autoregressivo
RRm=round(RRm*(1-gamma)+(occtmp(i)-occtmp(i-1))*gamma);
else %se la distanza fra l'i e l'i-1 è fuori tolleranza...
%provo a vedere con l'autoregressivo dove dovrebbe trovarsi
%la prossima occorrenza
nextR = occtmp(i) - RRm;
%quindi tolgo tutto quello fra il primo picco "buono" e il margine
%inferiore di tolleranza rispetto a dove dovrebbe essere il
%prossimo picco
j=i-1; %mi posiziono sulla prossima occorrenza
while occtmp(j) >= nextR + thRR %fino a che la distanza fra due occorrenze non supera la zona "buona" intorno al prossimo picco presunto
occtmp(j)=60000; %marco per poi rimuovere
occchk(j)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
j=j-1; %provo ad andre avanti di uno
if j<1
break
end
end
if abs(occtmp(i)-occtmp(j)-RRm) <= thRR%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
occchk(j)=2;
else
occchk(j)=0;
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
nextR = occtmp(i) - RRm;
%provo a mettermi nell'intorno di tolleranza sulla posizione
%stimata del prossimo picco per "fare pulizia" se è il caso
j=i-1;
best_occ = [];
best_idx = [];
while abs(occtmp(j)-nextR) <= thRR
if isempty(best_occ) %inizializzazione
best_occ = abs(occtmp(j)-nextR);
best_idx = j;
else %se c'è più di un picco nella fascia di tolleranza
if abs(occtmp(j)-nextR) < best_occ %se il picco è più vicino alla posizione presunta del migliore precedente
best_occ = abs(occtmp(j)-nextR); %questo diventa il migliore
best_idx = j; %conservo l'indice
end
end
j=j-1;
if j<1
break
end
end
if isempty(best_occ) %vuol dire che non c'erano elementi nella zona intorno alla posizione presunta
%devo aggiungere un picco nella posizione presunta
occtmp=[occtmp(1:i-1),nextR,occtmp(i:end)];
occchk=[occchk(1:i-1),3,occchk(i:end)]; %col codice 3 identifico un picco che è stato aggiunto%%%%%%%%%%%%%%
count_added = count_added+1;
if abs(occtmp(i)-occtmp(i-1)-RRm) <= thRR
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
occchk(i-1)=3;
else
occchk(i-1)=0;
end
i=i+1;
else %ho trovato un picco molto prossimo alla posizione presunta
%cancello tutti gli altri trovati
for aux=i-1:-1:j+1
if aux ~= best_idx
occtmp(aux)=60000; %marco per poi rimuovere
occchk(aux)=60000; %marco per poi rimuovere
count_removed = count_removed+1; %conto i rimossi
end
end
occtmp(occtmp==60000)=[]; %rimuovo quelli marcati
occchk(occchk==60000)=[]; %rimuovo quelli marcati
%sistemo i vettori occchk e occtmp
if j+1<i-1
i=j+2;
if abs(occtmp(i)-occtmp(i-1)-RRm) <= thRR
occchk(i-1)=1;
else
occchk(i-1)=0;
end
end
end
end
i=i-1;
end
%coda se non inizia subito il vettore delle occorrenze
while occtmp(1) > RRm
nextR = occtmp(1) - RRm;
if(nextR<starting_delay)
break
end
occtmp=[nextR,occtmp];
occchk=[3,occchk]; %col codice 3 identifico un picco che è statoaggiunto
count_added = count_added+1;
end
end
end