% METODA DESKRIPTORU A PRAVIDLA NEJBLIZSIHO SOUSEDA
%vsechny signaly jsou na CD 
clear all
clc
close all
senz_spec=zeros(10,46);% po skonceni cyklu for v teto matice budou vysledky, radky popsany dale
save senz_spec senz_spec
%4:49 signal zacne prochazet current folder pres vsechny signaly a 
%ulozi vysledky do matice senz_spec 

for q=4:49
files = dir;
directoryNames = {files([files.isdir]).name};
directoryNames = directoryNames(~ismember(directoryNames,{'.','..'}));
k=struct(files);
sign=files(q).name;
o=char(sign)
load(o)
load('senz_spec.mat')
time = 1/360:1/360:tm(end,1);  %casova osa signalu v sekundach
[~,y1]=size(time);
% figure(1)
% plot(time,x(1:y1,1)) % zobrazeni 1. signalu
% xlabel('t[s]')
% ylabel('U[mV]')

%pozice a pocty ruznych patologii
[pozice_V]=find(type=='V');%pvc
%% pokud signal bude obsahovat 0 pocet PVC --> konec
if length(pozice_V)>0 
[pozice_N]=find(type=='N');%normalni
[pozice_x]=find(type=='x');
[pozice_R]=find(type=='R');%Right brunch bundle boundaries
[pozice_L]=find(type=='L');%Left brunch bundle boundaries
[pozice_J]=find(type=='J');%Junctional premature	
[pozice_j]=find(type=='j');%Junctional escape	
[pozice_F]=find(type=='F');%fusion pvc
[pozice_A]=find(type=='A');%APC
[pozice_plus]=find(type=='+'); %sum a dalsi
[pozice_vlnka]=find(type=='~');%sum a dalsi

pozice_V=(pozice_V)';
% if length(pozice_V)>0
[y,~]=size(ann);
A=zeros(1,y);
Bpo=zeros(1,y);
Cpred=zeros(1,y);
Detekce=zeros(1,y);

for i=1:y 
A(i)=time(1,ann(i,1));
end

for j=3:length(ann)-2
Bpo(1,j)=A(j+1)-A(j);% deskriptor RR po aktualni pozice QRS
Cpred(1,j)=A(j)-A(j-1);% deskriptor RR pred aktualni pozice QRS
end 

for i=1:y
Rvse(i)=ann(i,1)   ;
% plot(time(1,Rvse(i)),x(Rvse(i),1),'*b');
end
%vymena PVC na 1 a Ostatni na 2
for i=1:length(ann)-2
    if type(i,1)=='V'
type_1(i,1)=1;
else
    type_1(i,1)=2;
    end
end

%% Detekce zacatku QRS, 73 vzorku = 200ms , vypocet nejvetsi diference
for j=3:length(Rvse)-2
txR=time(1,Rvse(1,j));
tyR=x(Rvse(1,j),1);
tx=time(1,Rvse(1,j)-72);
ty=x(Rvse(1,j)-72,1);

xuyrok(1,1:73)=x(Rvse(1,j)-72:Rvse(1,j),1);
krok=(abs(xuyrok(1,1))+xuyrok(1,end))/73;
kroknasobeni(1,:)=[1:1:150];

for i=2:74
xrovnomerne(1,1)=x(Rvse(1,j)-72,1);
xrovnomerne(1,i)=xrovnomerne(1,1)+krok*kroknasobeni(1,i-1);
end

for i=1:73
diference(1,i)=abs(xrovnomerne(1,i)-(xuyrok(1,i)));
end
m=max(diference);
[~,ymaxl]=find(diference==m);
[~,maxl]=size(ymaxl);
if maxl>1
    ymaxl=ymaxl(1);
end
ymax=ymaxl;
dvesektime=time(1,Rvse(1,j)-(73-ymaxl));
% xx=[dvesektime,dvesektime];
% yy=[xuyrok(1,ymax),2];
% plot(xx,yy,'r')
% line([dvesektime,dvesektime],[xuyrok(1,ymax),2])
padsekbodtime=time(1,Rvse(1,j)-(73-ymax)-18);
padsekbodampl=x(Rvse(1,j)-(73-ymax)-18,1);
% xx=[padsekbodtime,dvesektime];
% yy=[padsekbodampl,xuyrok(1,ymax)];
% plot(xx,yy,'r')
% line([padsekbodtime,dvesektime ],[padsekbodampl,xuyrok(1,ymax)])
%% 19 vzorku = 50 ms, vypocet nejvetsi diference -> zacatek detekovan
krokpades=(abs(x(Rvse(1,j)-(73-ymax),1)-padsekbodampl))/18;
for i=2:19
rovnopades(1,1)=x(Rvse(1,j)-(73-ymax)-18,1);
rovnopades(1,i)=rovnopades(1,1)-krokpades*kroknasobeni(1,i-1);
% plot(time(Rvse(1,3)-72:Rvse(1,3)),xrovnomerne(1,i-1),'*r')
end
xpadesxyrok(1,1:19)=x(Rvse(1,j)-(73-ymax)-18:Rvse(1,j)-(73-ymax),1);
for i=1:19
diferencepades(1,i)=abs(rovnopades(1,i)-(xpadesxyrok(1,i)));
end
mpad=max(diferencepades);
[~,ymaxx]=find(diferencepades==mpad);
[~,maxx]=size(ymaxx);
if maxx>1
ymaxx=ymaxx(1);
end
ymaxpad=ymaxx;
onset(1,j)=time(1,Rvse(1,j)-(73-ymax)-(19-ymaxpad));
pozice_a1(1,j)=Rvse(1,j)-(73-ymax)-(19-ymaxpad);
[~,tim]=find(time==onset(1,j));
timm(1,j)=tim;
posun(1,j)=abs(x(timm(1,j),1));
%% vykreskeni cervenou hvezdickou zacatku QRS
% figure(1)
% plot(time,x(1:y1,1)) % zobrazeni 1. signalu
% xlabel('t[s]')
% ylabel('U[mV]')
% hold on
% plot(onset(1,j),x(Rvse(1,j)-(73-ymax)-(19-ymaxpad),1),'*r')

%% Detekce konce QRS, 90 vzorku = 248 ms a vypocet nejvetsi diference
a3=diff(x(Rvse(1,j):Rvse(1,j)+90,1));
mdvapet=max(a3);
[ymaxdvapet]=find(a3==mdvapet);
if length(ymaxdvapet)>1
    ymaxdvapet=ymaxdvapet(1);
end
%% 19 vzorku 50 ms -> konec QRS je detekovan
dvapetktime=time(1,Rvse(1,j)+ymaxdvapet+19);
offsettime(1,j)=dvapetktime;
pozice_a2(1,j)=Rvse(1,j)+ymaxdvapet;
%%  Vykresleni konce QRS
% figure(1)
% plot(time,x(1:y1,1)) % zobrazeni 1. signalu
% xlabel('t[s]')
% ylabel('U[mV]')
% hold on
% plot(dvapetktime,x(Rvse(1,j)+ymaxdvapet+19,1),'*g')
end
%% kratke nazvy deskriptoru, viz tabulka 3.1 v BP
for j=3:length(Rvse)-2
pik(1,j)=x(Rvse(1,j),1);
if pik(1,j)>=0
    pozitivpik(1,j)=pik(1,j); %Pp   
    negativpik(1,j)=x(pozice_a2(1,j),1);
 else
     pozitivpik(1,j)=x(pozice_a2(1,j)+10,1);
     negativpik(1,j)=pik(1,j); %Pn
    end
end

for j=3:length(Rvse)-2
   if x(pozice_a1(1,j),1)>0  
        pozitivpik(1,j)=pozitivpik(1,j)-posun(1,j);
     negativpik(1,j)=negativpik(1,j)-posun(1,j); %Pn  
     if x(pozice_a1(1,j),1)<0 
         pozitivpik(1,j)=pozitivpik(1,j)+posun(1,j); %Pp   
    negativpik(1,j)=negativpik(1,j)+posun(1,j);
     if x(pozice_a1(1,j),1)==0 
         pozitivpik(1,j)=pozitivpik(1,j); %Pp   
    negativpik(1,j)=negativpik(1,j);
     end
   end
end         
delkaosnov(1,j)=time(1,Rvse(1,j))-onset(1,j);
delkapik(1,j)=pozitivpik(1,j);
gipot(1,j)=(delkaosnov(1,j)*delkapik(1,j))/2;
plocha(1,j)=abs(2*gipot(1,j)); % ArP

ima(1,j)=time(1,Rvse(1,j))-onset(1,j); % ima
sjedna(1,j)=sqrt((delkaosnov(1,j))^2+(pozitivpik(1,j))^2); % S1

negativpikabs(1,j)=abs(negativpik(1,j));
delkaosneg(1,j)=offsettime(1,j)-time(1,Rvse(j));
delkapikneg(1,j)=negativpikabs(1,j);
gipotneg(1,j)=(delkaosneg(1,j)*delkapikneg(1,j))/2;
plochaneg(1,j)=abs(2*gipotneg(1,j)); % ArN

imi(1,j)=dvapetktime-onset(1,j); % imi
sdva(1,j)=sqrt((dvapetktime-time(1,Rvse(1,j)))^2+(pozitivpik(1,j)+negativpikabs(1,j))^2);
[~,ons]=find(time==onset(1,j))  ;   
sdva(1,j)=sqrt((time(1,Rvse(j))-time(1,ons))^2+(pozitivpik(1,j)+negativpikabs(1,j))^2); % S2
%  sirka QRS
widthh(1,j)=offsettime(1,j)-onset(1,j);
end
% Ar
for i=1:length(plocha)
    Ar(1,i)=plocha(1,i)+plochaneg(1,i);
end
% Av1
for i=1:length(imi)
Av1(1,i)=ima(1,i)+imi(1,i);
end

else
end
if length(pozice_V)>0
%% Vytvoreni matice deskriptoru
matice_discr(:,1)=Av1;
matice_discr(:,2)=Ar;
matice_discr(:,3)=negativpik;
matice_discr(:,4)=pozitivpik;
matice_discr(:,5)=plocha;
matice_discr(:,6)=plochaneg;
matice_discr(:,7)=widthh;
% matice_discr(:,8)=imi;
matice_discr(:,8)=ima;
matice_discr(:,9)=sjedna;
matice_discr(:,10)=sdva;
matice_discr(:,11)=Cpred(1:length(Cpred)-2);
matice_discr(:,12)=Bpo(1:length(Bpo)-2);

rng(0,'twister'); % nastaveni, aby generovani zacinalo vzdy stejne
nfold=10;

paramOut=type_1;
param=matice_discr;

cv = cvpartition(paramOut,'kfold',nfold);  %paramOut je vektor, kde jsou ulozeny anotace (tj. zda je to PVC nebo ostatni-musi byt ve forme cisel - tj. PVC nahradte treba 1 a zbytek 2
indices = zeros(size(paramOut));
for i=1:nfold
    indices(cv.test(i)) = i;
end

type='euclidean'; % nastaveni typu pocitani vzdalenosti
k=1; % pocet uvazovanych nejblizsich sousedu
accInit=zeros(nfold,1); % deficnice promnene pro ukladani uspesnosti klasifikace s originalnimi hodnotami parmametru
accNorm = zeros(nfold,1); % deficnice promnene pro ukaldani uspesnosti klasifikace s normalizovanymi hodnotami parmametru

for i=1:nfold % pro kazdou iteraci
    testIdx = (indices == i); trainIdx = ~testIdx; % vyber jedne aktualni casti jako testovaci,zbytek bude trenovaci
    ptr=param(trainIdx,:); %  aktualni trenovaci cast matice matice_discr
    
    mitr=min(ptr); % minimum z treninkoveho setu
    matr=max(ptr); % maximum z treninkoveho setu
    ptrnorm=(ptr-repmat(mitr,size(ptr,1),1))./(repmat(matr,size(ptr,1),1)-repmat(mitr,size(ptr,1),1)); % normalizace treninovaci mnoziny
    
   
    pte=param(testIdx,:); % vyber aktualni testovaci mnoziny
    ptenorm=(pte-repmat(mitr,size(pte,1),1))./(repmat(matr,size(pte,1),1)-repmat(mitr,size(pte,1),1)); % normalizace testovaci mnoziny
       
    
    knnClassInit = knnclassify(pte, ptr, paramOut(trainIdx), k, type); % trenovani a klasifikace - s originalnimi hodnotami
    knnClassNorm = knnclassify(ptenorm,ptrnorm,paramOut(trainIdx),k,type); % trenovani a klasifikace - s normalizovanymi hodnotami
  
    badInit = ~strcmp(knnClassInit,paramOut(testIdx)); % vypocet spatne klasifikovanych cyklu
    badNorm = ~strcmp(knnClassNorm,paramOut(testIdx));
    N=sum(testIdx==1);
    accInit(i) = 1-sum(badInit)/N; % vypocet uspesnosti
    accNorm(i) = 1-sum(badNorm)/N;
    [aaknnInit,grpInit] = confusionmat(paramOut(testIdx),knnClassInit) % zobrazeni matice zmen
    [aaknnNorm,grpNorm] = confusionmat(paramOut(testIdx),knnClassNorm)
    usp(1:2,1:2,i)=aaknnNorm;

end
accKNNInit1 = mean(accInit) % presnost
accKNNNorm1 = mean(accNorm)
for i=1:nfold
if usp(1,1,i)==usp(2,1,i)&& usp(1,2,i)==usp(2,2,i)
usp(1,1,i)=0;
usp(1,2,i)=0;
usp(2,1,i)=0;
end
end
%% matice s vysledky
senzetivita=(sum(usp(1,1,:)))/(sum(usp(1,1,:))+(sum(usp(1,2,:)))); 
specificita=(sum(usp(2,2,:)))/(sum(usp(2,2,:))+(sum(usp(2,1,:))));
pocet_PVC=sum(type_1==1);
pocet_detek_PVC=sum(usp(1,1,:));
pocet_ostatnich=sum(type_1==2);
pocet_sprdetek_ost=sum(usp(2,2,:));
senz_spec(1,q-3)=senzetivita;
senz_spec(2,q-3)=specificita;
senz_spec(3,q-3)=accKNNNorm1;%presnost
senz_spec(4,q-3)=pocet_PVC; % celkovy pocet PVC v signalu
senz_spec(5,q-3)=pocet_detek_PVC; % pocet detekovanych spravne PVC
senz_spec(6,q-3)=sum(usp(1,2,:)); %zarazene do ostatnich,ale meli by patrit k PVC
senz_spec(7,q-3)=pocet_ostatnich;% celkovy pocet ostatnich patologii v signalu
senz_spec(8,q-3)=pocet_sprdetek_ost; % pocet detekovanych spravne ostatnich
senz_spec(9,q-3)=sum(usp(2,1,:)); % zarazene do PVC, ale meli byt zarazeny do Ostatnich
senz_spec(10,:)=[102,103,104,105,106,107,108,109,111,112,113,114,115,116,117,118,119,121,122,123,124,200,201,202,203,205,207,208,209,210,212,213,214,215,217,219,220,221,222,223,228,230,231,232,233,234];
% 10 radek obsahuje cisla signalu
save senz_spec senz_spec
clear all
clc
close all
else
%     sprintf('spuste,prosim,dalsi signal,v tomto signalu PVC nejsou')
    senz_spec(:,q-3)=0; % v signalu neobsahujicim extrasystoly budou vsude nuly ve sloupci matice senz_spec
    save senz_spec senz_spec
end

end
load('senz_spec.mat')
%% po ukonceni cyklu spustte tuto cast skriptu
mean_senz=sum(senz_spec(5,:))/(sum(senz_spec(5,:))+sum(senz_spec(6,:)))% stredni hodnota senzetivity
mean_spec=sum(senz_spec(8,:))/(sum(senz_spec(8,:))+sum(senz_spec(9,:))) % stredni hodnota specificity

% mean_senz =
% 
%     0.9478
% 
% 
% mean_spec =
% 
%     0.9963
%%




