PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/toolboxes/biosig/t300/nqrsdetect.m

http://brainstream.googlecode.com/
Objective C | 436 lines | 413 code | 23 blank | 0 comment | 42 complexity | 63857a19b785b350c759cb5a7b88280e MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, LGPL-2.0, GPL-3.0, GPL-2.0, LGPL-2.1, LGPL-3.0, BSD-2-Clause
  1. function QRS=nqrsdetect(S,fs);
  2. % nqrsdetect - detection of QRS-complexes
  3. %
  4. % QRS=nqrsdetect(S,fs);
  5. %
  6. % INPUT
  7. % S ecg signal data
  8. % fs sample rate
  9. %
  10. % OUTPUT
  11. % QRS fiducial points of qrs complexes
  12. %
  13. %
  14. % see also: QRSDETECT
  15. %
  16. % Reference(s):
  17. % [1]: V. Afonso, W. Tompkins, T. Nguyen, and S. Luo, "ECG beat detection using filter banks,"
  18. % IEEE Trans. Biomed. Eng., vol. 46, no. 2, pp. 192--202, Feb. 1999
  19. %
  20. % [2]: A.V. Oppenheim, R.W. Schafer, and J.R. Buck, Discrete-Time Signal
  21. % Processing, second edition, Prentice Hall, 1999, chapter 4.7.3
  22. % Copyright (C) 2006 by Rupert Ortner
  23. %
  24. %% This program is free software; you can redistribute it and/or modify
  25. %% it under the terms of the GNU General Public License as published by
  26. %% the Free Software Foundation; either version 2 of the License, or
  27. %% (at your option) any later version.
  28. %%
  29. %% This program is distributed in the hope that it will be useful, ...
  30. %% but WITHOUT ANY WARRANTY; without even the implied warranty of
  31. %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  32. %% GNU General Public License for more details.
  33. %%
  34. %% You should have received a copy of the GNU General Public License
  35. %% along with this program; if not, write to the Free Software
  36. %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  37. %% USA
  38. S=S(:);
  39. S=full(S);
  40. N=round(fs); %Filter order
  41. %---------------------------------------
  42. %Replaces filter bank in [1]
  43. Bw=5.6; %filter bandwidth
  44. Bwn=1/(fs/2)*Bw;
  45. M=round((fs/2)/Bw); %downsampling rate
  46. Wn0=Bwn; %bandwidth of the first filter
  47. Wn1=[Bwn 2*Bwn]; %bandwidth of the second filter
  48. Wn2=[2*Bwn 3*Bwn];
  49. Wn3=[3*Bwn 4*Bwn];
  50. Wn4=[4*Bwn 5*Bwn];
  51. h0=fir1(N,Wn0); %impulse response of the first filter
  52. h1=fir1(N,Wn1,'bandpass');
  53. h2=fir1(N,Wn2,'bandpass');
  54. h3=fir1(N,Wn3,'bandpass');
  55. h4=fir1(N,Wn4,'bandpass');
  56. %Polyphase implementation of the filters
  57. y=cell(1,5);
  58. y{1}=polyphase_imp(S,h0,M); %W0 (see [1]) filtered and downsampled signal
  59. y{2}=polyphase_imp(S,h1,M); %W1
  60. y{3}=polyphase_imp(S,h2,M); %W2
  61. y{4}=polyphase_imp(S,h3,M); %W3
  62. y{5}=polyphase_imp(S,h4,M); %W4
  63. %----------------------------------------------
  64. cut=ceil(N/M); %Cutting off of initial transient because of the filtering
  65. y1=[zeros(cut,1);y{1}(cut:length(y{1}))];
  66. y2=[zeros(cut,1);y{2}(cut:length(y{2}))];
  67. y3=[zeros(cut,1);y{3}(cut:length(y{3}))];
  68. y4=[zeros(cut,1);y{4}(cut:length(y{4}))];
  69. y5=[zeros(cut,1);y{5}(cut:length(y{5}))];
  70. %----------------------------------------
  71. P1=sum([abs(y2) abs(y3) abs(y4)],2); %see [1] equation (13)
  72. P2=sum([abs(y2) abs(y3) abs(y4) abs(y5)],2);
  73. P4=sum([abs(y3) abs(y4) abs(y5)],2);
  74. FL1=MWI(P1); %Feature 1 according to Level 1 in [1]
  75. FL2=MWI(P2); %Feature 2 according to Level 2
  76. FL4=MWI(P4); %Feature 4 according to Level 4
  77. %--------------------------------------
  78. %Level 1 [1]
  79. d=sign(diff(FL1));
  80. d1=[0;d];
  81. d2=[d;0];
  82. f1=find(d1==1);
  83. f2=find(d2==-1);
  84. EventsL1=intersect(f1,f2); %Detected events
  85. %-------------------------------------------------------
  86. %Level 2 [1]
  87. meanL1=sum(FL2(EventsL1),1)/length(EventsL1);
  88. NL=meanL1-meanL1*0.1; %Start Noise Level
  89. SL=meanL1+meanL1*0.1; %Start Signal Level
  90. threshold1=0.08; %Threshold detection block 1
  91. threshold2=0.7; %Threshold detection block 2
  92. [SignalL21,Noise1,DS1,Class1]=detectionblock(FL2,EventsL1,NL,SL,threshold1);
  93. [SignalL22,Noise2,DS2,Class2]=detectionblock(FL2,EventsL1,NL,SL,threshold2);
  94. %---------------------------------------------------
  95. %Level 3 [1]
  96. ClassL3=[];
  97. for i=1:length(EventsL1)
  98. C1=Class1(i);
  99. C2=Class2(i);
  100. if C1==1
  101. if C2==1
  102. ClassL3=[ClassL3 1]; %Classification as Signal
  103. else
  104. delta1=(DS1(i)-threshold1)/(1-threshold1);
  105. delta2=(threshold2-DS2(i))/threshold2;
  106. if delta1>delta2
  107. ClassL3=[ClassL3 1]; %Classification as Signal
  108. else
  109. ClassL3=[ClassL3 0]; %Classification as Noise
  110. end
  111. end
  112. else
  113. if C2==1;
  114. ClassL3=[ClassL3 1]; %Classification as Signal
  115. else
  116. ClassL3=[ClassL3 0]; %Classification as Noise
  117. end
  118. end
  119. end
  120. SignalL3=EventsL1(find(ClassL3)); %Signal Level 3
  121. NoiseL3=EventsL1(find(ClassL3==0)); %Noise Level 3
  122. %--------------------------------------------
  123. %Level 4 [1]
  124. threshold=0.3;
  125. VSL=(sum(FL4(SignalL3),1))/length(SignalL3);
  126. VNL=(sum(FL4(NoiseL3),1))/length(NoiseL3);
  127. SL=(sum(FL4(SignalL3),1))/length(SignalL3); %Initial Signal Level
  128. NL=(sum(FL4(NoiseL3),1))/length(NoiseL3); %Initial Noise Level
  129. SignalL4=[];
  130. NoiseL4=[];
  131. DsL4=[]; %Detection strength Level 4
  132. for i=1:length(EventsL1)
  133. Pkt=EventsL1(i);
  134. if ClassL3(i)==1; %Classification after Level 3 as Signal
  135. SignalL4=[SignalL4,EventsL1(i)];
  136. SL=history(SL,FL4(Pkt));
  137. Ds=(FL4(Pkt)-NL)/(SL-NL); %Detection strength
  138. if Ds<0
  139. Ds=0;
  140. elseif Ds>1
  141. Ds=1;
  142. end
  143. DsL4=[DsL4 Ds];
  144. else %Classification after Level 3 as Noise
  145. Ds=(FL4(Pkt)-NL)/(SL-NL);
  146. if Ds<0
  147. Ds=0;
  148. elseif Ds>1
  149. Ds=1;
  150. end
  151. DsL4=[DsL4 Ds];
  152. if Ds>threshold %new classification as Signal
  153. SignalL4=[SignalL4,EventsL1(i)];
  154. SL=history(SL,FL4(Pkt));
  155. else %new classification as Noise
  156. NoiseL4=[NoiseL4,EventsL1(i)];
  157. NL=history(NL,FL4(Pkt));
  158. end
  159. end
  160. end
  161. %------------------------------------------------
  162. %Level 5
  163. %if the time between two RR complexes is too long => go back and check the
  164. %events again with lower threshold
  165. SignalL5=SignalL4;
  166. NoiseL5=NoiseL4;
  167. periods=diff(SignalL4);
  168. M1=100;
  169. a=1;
  170. b=1/(M1)*ones(M1,1);
  171. meanperiod=filter(b,a,periods); %mean of the RR intervals
  172. SL=sum(FL4(SignalL4))/length(SignalL4);
  173. NL=sum(FL4(NoiseL4))/length(NoiseL4);
  174. threshold=0.2;
  175. for i=1:length(periods)
  176. if periods(i)>meanperiod*1.5 %if RR-interval is to long
  177. intervall=SignalL4(i):SignalL4(i+1);
  178. critical=intersect(intervall,NoiseL4);
  179. for j=1:length(critical)
  180. Ds=(FL4(critical(j))-NL)/(SL-NL);
  181. if Ds>threshold %Classification as Signal
  182. SignalL5=union(SignalL5,critical(j));
  183. NoiseL5=setxor(NoiseL5,critical(j));
  184. end
  185. end
  186. end
  187. end
  188. %---------------------------------------------------
  189. %Umrechnung auf Originalsignal (nicht downgesamplet)
  190. Signaln=conversion(S,FL2,SignalL5,M,N,fs);
  191. %----------------------------------------------------
  192. %Level 6 If interval of two RR-complexes <0.24 => go back and delete one of them
  193. height=FL2(SignalL5);
  194. Signal=Signaln;
  195. temp=round(0.1*fs);
  196. difference=diff(Signaln); %Difference between two signal points
  197. k=find(difference<temp);
  198. for i=1:length(k)
  199. pkt1=SignalL5(k(i));
  200. pkt2=SignalL5(k(i)+1);
  201. verg=[height(k(i)),height(k(i)+1)];
  202. [x,j]=max(verg);
  203. if j==1
  204. Signal=setxor(Signal,Signaln(k(i)+1)); %Deleting first Event
  205. else
  206. Signal=setxor(Signal,Signaln(k(i))); %Deleting second Event
  207. end
  208. end
  209. QRS=Signal;
  210. %-------------------------------------------------------------------
  211. %-------------------------------------------------------------------
  212. %-------------------------------------------------------------------
  213. %subfunctions
  214. function y=MWI(S)
  215. % MWI - Moving window integrator, computes the mean of two samples
  216. % y=MWI(S)
  217. %
  218. % INPUT
  219. % S Signal
  220. %
  221. % OUTPUT
  222. % y output signal
  223. a=[0;S];
  224. b=[S;0];
  225. c=[a,b];
  226. y=sum(c,2)/2;
  227. y=y(1:length(y)-1);
  228. %------------------------------------------------
  229. function y=polyphase_imp(S,h,M)
  230. % polyphase_imp - polyphase implementation of decimation filters [2]
  231. % y=polyphase_imp(S,h,M)
  232. %
  233. % INPUT
  234. % S ecg signal data
  235. % h filter coefficients
  236. % M downsampling rate
  237. %
  238. % OUTPUT
  239. % y filtered signal
  240. %
  241. %Determining polyphase components ek
  242. e=cell(M,1);
  243. l=1;
  244. m=mod(length(h),M);
  245. while m>0
  246. for n=1:ceil(length(h)/M)
  247. el(n)=h(M*(n-1)+l);
  248. end
  249. e{l}=el;
  250. l=l+1;
  251. m=m-1;
  252. end
  253. clear el;
  254. for i=l:M
  255. for n=1:floor(length(h)/M)
  256. el(n)=h(M*(n-1)+i);
  257. end
  258. e{i}=el;
  259. end
  260. %Filtering
  261. max=ceil((length(S)+M)/M);
  262. Sdelay=S;
  263. for i=1:M
  264. Sd=downsample(Sdelay,M);
  265. a=filter(e{i},1,Sd);
  266. if length(a)<max
  267. a=[a;zeros(max-length(a),1)];
  268. end
  269. w(:,i)=a;
  270. Sdelay=[zeros(i,1);S];
  271. end
  272. y=sum(w,2);
  273. %----------------------------------------------------------
  274. function [Signal,Noise,VDs,Class]=detectionblock(mwi,Events,NL,SL,threshold)
  275. % detectionblock - computation of one detection block
  276. %
  277. % [Signal,Noise,VDs,Class]=detectionblock(mwi,Events,NL,SL,threshold)
  278. %
  279. % INPUT
  280. % mwi Output of the MWI
  281. % Events Events of Level 1 (see [1])
  282. % NL Initial Noise Level
  283. % SL Initial Signal Level
  284. % threshold Detection threshold (between [0,1])
  285. %
  286. % OUTPUT
  287. % Signal Events which are computed as Signal
  288. % Noise Events which are computed as Noise
  289. % VDs Detection strength of the Events
  290. % Class Classification: 0=noise, 1=signal
  291. Signal=[];
  292. Noise=[];
  293. VDs=[];
  294. Class=[];
  295. sumsignal=SL;
  296. sumnoise=NL;
  297. for i=1:length(Events)
  298. P=Events(i);
  299. Ds=(mwi(P)-NL)/(SL-NL); %Detection strength
  300. if Ds<0
  301. Ds=0;
  302. elseif Ds>1
  303. Ds=1;
  304. end
  305. VDs=[VDs Ds];
  306. if Ds>threshold %Classification as Signal
  307. Signal=[Signal P];
  308. Class=[Class;1];
  309. sumsignal=sumsignal+mwi(P);
  310. SL=sumsignal/(length(Signal)+1); %Updating the Signal Level
  311. else %Classification as Noise
  312. Noise=[Noise P];
  313. Class=[Class;0];
  314. sumnoise=sumnoise+mwi(P);
  315. NL=sumnoise/(length(Noise)+1); %Updating the Noise Level
  316. end
  317. end
  318. %------------------------------------------------------------
  319. function [pnew]=conversion(S,FL2,pold,M,N,fs)
  320. % conversion - sets the fiducial points of the downsampled Signal on the
  321. % samplepoints of the original Signal
  322. %
  323. % [pnew]=conversion(S,FL2,pold,M,N,fs)
  324. %
  325. % INPUT
  326. % S Original ECG Signal
  327. % FL2 Feature of Level 2 [1]
  328. % pold old fiducial points
  329. % M M downsampling rate
  330. % N filter order
  331. % fs sample rate
  332. %
  333. % OUTPUT
  334. % pnew new fiducial points
  335. %
  336. Signaln=pold;
  337. P=M;
  338. Q=1;
  339. FL2res=resample(FL2,P,Q); %Resampling
  340. nans1=isnan(S);
  341. nans=find(nans1==1);
  342. S(nans)=mean(S); %Replaces NaNs in Signal
  343. for i=1:length(Signaln)
  344. Signaln1(i)=Signaln(i)+(M-1)*(Signaln(i)-1);
  345. end
  346. %------------------- Sets the fiducial points on the maximum of FL2
  347. Signaln2=Signaln1;
  348. Signaln2=Signaln2';
  349. int=2*M; %Window length for the new fiducial point
  350. range=1:length(FL2res);
  351. for i=1:length(Signaln2)
  352. start=Signaln2(i)-int/2;
  353. if start<1
  354. start=1;
  355. end
  356. stop=Signaln2(i)+int/2;
  357. if stop>length(FL2res)
  358. stop=length(FL2res);
  359. end
  360. intervall=start:stop; %interval
  361. FL2int=FL2res(intervall);
  362. pkt=find(FL2int==max(FL2int)); %Setting point on maximum of FL2
  363. if length(pkt)==0 % if pkt=[];
  364. pkt=Signaln2(i)-start;
  365. else
  366. pkt=pkt(1);
  367. end
  368. delay=N/2+M;
  369. Signaln3(i)=pkt+Signaln2(i)-int/2-delay; %fiducial points according to FL2
  370. end
  371. %Sets the fiducial points on the maximum or minimum
  372. %of the signal
  373. Bw=5.6;
  374. Bwn=1/(fs/2)*Bw;
  375. Wn=[Bwn 5*Bwn];
  376. N1=32;
  377. b=fir1(N1,Wn,'bandpass');
  378. Sf=filtfilt(b,1,S); %Filtered Signal with bandwidth 5.6-28 Hz
  379. beg=round(1.5*M);
  380. fin=1*M;
  381. for i=1:length(Signaln3)
  382. start=Signaln3(i)-beg;
  383. if start<1
  384. start=1;
  385. end
  386. stop=Signaln3(i)+fin;
  387. if stop>length(Sf)
  388. stop=length(Sf);
  389. end
  390. intervall=start:stop; %Window for the new fiducial point
  391. Sfint=abs(detrend(Sf(intervall),0));
  392. pkt=find(Sfint==max(Sfint)); %Setting point on maximum of Sfint
  393. if length(pkt)==0 %if pkt=[];
  394. pkt=Signaln3(i)-start;
  395. else
  396. pkt=pkt(1);
  397. end
  398. pkt=pkt(1);
  399. Signaln4(i)=pkt+Signaln3(i)-beg-1;
  400. end
  401. Signal=Signaln4'; %New fiducial points according to the original signal
  402. cutbeginning=find(Signal<N); %Cutting out the first points because of initial transient of the filter in polyphase_imp
  403. fpointsb=Signal(cutbeginning);
  404. cutend=find(Signal>length(S)-N); %Cutting out the last points
  405. fpointse=Signal(cutend);
  406. pnew=setxor(Signal,[fpointsb;fpointse]);
  407. %-------------------------------------------
  408. function yn=history(ynm1,xn)
  409. % history - computes y[n]=(1-lambda)*x[n]+lambda*y[n-1]
  410. %
  411. % yn=history(ynm1,xn)
  412. lambda=0.8; %forgetting factor
  413. yn=(1-lambda)*xn+lambda*ynm1;