% 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)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(media145)) % 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=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=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+81) [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 (zi0.5*l1) residui_materni=[residui_materni 1]; end zi=1; while (zi0.5*l2) residui_materni=[residui_materni 2]; end zi=1; while (zi0.5*l3) residui_materni=[residui_materni 3]; end zi=1; while (zi0.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 (zi0); 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=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 c0) 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)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(stopsoglia); 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)&&(qp)&&(pys(qrs_f(j-1))) qrs_f(j-1)=qrs_f(j); qrs_f(j)=[]; elseif(ys(qrs_f(j)) 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)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 j0 start_m=j; while cctemp(j)>0 && j 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)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)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 ilength(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=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=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= 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) RRm % nextR = occtmp(1) - RRm; % if(nextRsize(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 ilength(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= 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 RRm % nextR = occtmp(1) - RRm; % if(nextRRRm2 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 ilength(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= 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 RRm nextR = occtmp(1) - RRm; if(nextR 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 ilength(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= 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 RRm nextR = occtmp(1) - RRm; if(nextR