Switch to side-by-side view

--- a
+++ b/preprocessOfApneaECG/BioSigKit/Algorithms/SimpleRST.m
@@ -0,0 +1,310 @@
+function [R_i,R_amp,S_i,S_amp,T_i,T_amp,Q_i,Q_amp,buffer_plot] = SimpleRST(ecg,fs,gr)
+%% function [R_i,R_amp,S_i,S_amp,T_i,T_amp]=peakdetect(ecg,fs,view)
+%% =================== Online Adaptive QRS detector ==================== %%
+%% ========================== Description ============================= %%
+% QRS detection
+% Detects Q , R and S waves,T Waves
+% Uses the state-machine logic to determine different peaks in an ECG
+% signal. It has the ability to confront noise by canceling out the noise
+% by high pass filtering and baseline wander by low pass. Besides, check
+% out criterion to stop detection of spikes.
+% The code is written in a way for future online implementation.
+%% Inputs
+% ecg : raw ecg vector
+% fs : sampling frequency
+% view : display results? (0: no, 1: Yes)
+
+%% Outputs
+% indexes and amplitudes of R_i, R_amp, etc
+% heart_rate computed heart rate
+% buffer_plot : processed signal
+%% ============== Licensce ========================================== %%
+% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+% OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+% TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+% PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+% LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+% Author :
+% Hooman Sedghamiz, Feb, 2018
+% MSc. Biomedical Engineering, Linkoping University
+% Email : Hooman.sedghamiz@gmail.com
+%% Updates :
+%  Feb, 2018 : Clean up and fixes.
+%% ============== Now Part of BioSigKit ======================== %%
+if nargin < 3
+    gr = 1;                                                                % on show Sig
+    if nargin <2
+       fs = 250;                                                           % default Sampling frequency
+       if nargin < 1
+           error('You need to provide a signal!');
+       end
+    end 
+end
+
+%% ========================= initialize ============================ %%
+R_i = zeros(1,length(ecg));                                                % save index of R wave
+R_amp = zeros(1,length(ecg));                                              % save amp of R wave
+S_i = zeros(1,length(ecg));                                                % save index of S wave
+S_amp = zeros(1,length(ecg));                                              % save amp of S wave
+T_i = zeros(1,length(ecg));                                                % save index of T wave
+T_amp = zeros(1,length(ecg));                                              % save amp of T wave
+Q_i = zeros(1,length(ecg));                                                % vectors to store Q wave
+Q_amp = zeros(1,length(ecg));                                              % Vectors to store Q wave
+S_amp1 = zeros(1,length(ecg));                                             % Buffer to set the adaptive T wave onset
+thres_p =zeros(1,length(ecg));                                             % For plotting adaptive threshold
+S_amp1_i = zeros(1,length(ecg));                                           % To save indices of S thres
+buffer_plot = zeros(1,length(ecg));
+thres2_p = zeros(1,length(ecg));                                           % T wave threshold indices
+window = round(0.04*fs);                                                   % averaging window size
+buffer_long= zeros(1,window);                                              % buffer for online processing
+state = 0 ;                                                                % determines the state of the machine in the algorithm
+c = 0;                                                                     % counter to determine that the state-machine doesnt get stock in T wave detection wave
+T_on = 0;                                                                  % counter showing for how many samples the signal stayed above T wave threshold
+T_on1=0;                                                                   % counter to make sure its the real onset of T wave
+S_on = 0;                                                                  % counter to make sure its the real onset of S wave
+sleep = 0;                                                                 % counter that avoids the detection of several R waves in a short time
+buffer_base=zeros(1,2*fs);                                                 % buffer to determine online adaptive mean of the signal
+dum = 0;                                                                   % counter for detecting the exact R wave
+weight = 1.8;                                                              % initial value of the weigth
+co = 0;                                                                    % T wave counter to come out of state after a certain time
+thres_p_i = zeros(1,length(ecg));                                          % To save indices of main thres
+thres2_p_i = zeros(1,length(ecg));                                         %to save indices of T threshold
+%% ========================= preprocess ================================ %%
+ecg = ecg (:);                                                             % make sure its a vector
+ecg_raw =ecg;                                                              % take the raw signal for plotting later
+%% ==================== Noise cancelation(Filtering) =================== %% 
+f1=0.5;                                                                    % cuttoff low frequency to get rid of baseline wander
+f2=45;                                                                     % cuttoff frequency to discard high frequency noise
+Wn=[f1 f2]*2/fs;                                                           % cutt off based on fs
+N = 3;                                                                     % order of 3 less processing
+[a,b] = butter(N,Wn);                                                      % bandpass filtering
+ecg = filtfilt(a,b,ecg);
+
+%% ==============  define two buffers ================= %%
+
+buffer_mean=mean(abs(ecg(1:2*fs)-mean(ecg(1:2*fs))));                      % adaptive threshold DC corrected (baseline removed)
+buffer_T = mean(ecg(1:2*fs));                                              % second adaptive threshold to be used for T wave detection
+%% ================== Counters ============================ %%
+B_Lcounter = 0;
+B_counter = 0;
+SP_counter = 0;
+thres_p_C = 0;
+R_C = 0;
+S_C = 0;
+T_C = 0;
+Q_C = 0;
+thres2_p_C = 0;
+%% =start online inference (Assuming the signal is being acquired online) %%
+for i = 1 : length(ecg)
+ B_Lcounter = B_Lcounter + 1;  
+ buffer_long(B_Lcounter) = ecg(i);                                         % save the upcoming new samples
+ if B_Lcounter > window
+    B_Lcounter = 0; 
+ end
+
+ B_counter = B_counter + 1;
+ buffer_base(B_counter) = ecg(i);                                          % save the baseline samples
+
+%% ============================= Renew Mean ======================= %%
+ if B_counter >= 2*fs
+    buffer_mean = mean(abs(buffer_base - mean(buffer_base)));
+    buffer_T = mean(buffer_base);
+    B_counter = 0;
+ end
+
+%% ========= Smooth  15 samples and add the new upcoming samples ======== %%
+  if i >= window                                                  % take a window with length 15 samples for averaging
+      mean_online = mean(buffer_long);                       % take the mean
+      SP_counter = SP_counter + 1;
+      buffer_plot(SP_counter) = mean_online;                               % save the processed signal
+      
+      
+    %% ==============  Enter state 1(putative R wave) ================ %%
+    if state == 0  
+     if SP_counter >= 3                                                                         % added to handle bugg for now
+      if (mean_online > buffer_mean*weight) && (buffer_plot(i-1-window) > buffer_plot(i-window))    % 2.4*buffer_mean   
+          state = 1;                                                                            % entered R peak detection mode
+          currentmax = buffer_plot(i-1-window);
+          ind = i-1-window;
+          thres_p_C = thres_p_C + 1;
+          thres_p(thres_p_C) = buffer_mean*weight;
+          thres_p_i(thres_p_C) = ind;
+      else     
+          state = 0;
+      end
+     end
+    end
+    
+%% ============= Locate R by finding highest Peak =================== %%
+      if state == 1                                                        % look for the highest peak
+            if  currentmax > buffer_plot(i-window)
+                dum = dum + 1;
+                if dum > 4 
+                   R_C = R_C + 1;
+                   R_i(R_C) = ind;                                          % save index
+                   R_amp(R_C) = buffer_plot(ind);                          % save index
+                %-------------- Locate Q wave --------------------%
+                  [Q_tamp,Q_ti] = min(buffer_plot(ind-round(0.040*fs):(ind)));
+                  Q_ti = ind-round(0.040*fs) + Q_ti -1;
+                  Q_C = Q_C + 1;
+                  Q_i(Q_C) = Q_ti;
+                  Q_amp(Q_C) = Q_tamp;                           
+                  if R_C > 8
+                     weight = 0.30*mean(R_amp(R_C-7:R_C));                  % calculate the 35% of the last 8 R waves
+                     weight = weight/buffer_mean;
+                  end
+                  state = 2;                                                % enter S detection mode state 2
+                  dum = 0;
+                end
+            else
+                dum = 0;
+                state = 0;
+            end 
+            
+      end
+      
+  %% === check if Sig drops below the threshold to look for S wave === %%
+      if state == 2 
+        if  mean_online <= buffer_mean                                     % check the threshold
+             state = 3;                                                    % enter S detection           
+        end
+      end
+      
+  %% ============ Enter S wave detection state3 (S detection) =========== %%
+         if state == 3
+            co = co + 1;    
+          if co < round(0.200*fs)
+            if buffer_plot(i-window-1) <= buffer_plot(i-window)            % see when the slope changes
+             S_on = S_on + 1;                                              % set a counter to see if its a real change or just noise
+             if S_on >= round(0.0120*fs)
+                S_C = S_C + 1;
+                S_i(S_C) = i-window-4;                                     % save index of S wave
+                S_amp(S_C) = buffer_plot(i-window-4);                      % save index
+                S_amp1(S_C) = buffer_plot(i-window-4);                     % ecg(i-4)
+                S_amp1_i(S_C) = ind;                                       % index of S_amp1_i
+                state = 4;                                                 % enter T detection mode
+                S_on = 0;
+                co = 0;
+             end
+            end
+          else
+                state = 4;
+                co = 0;
+          end
+          end
+      
+       %% ======= enter state 4 possible T wave detection ============ %%
+       if state == 4    
+         if mean_online < buffer_mean                                      % See if the signal drops below mean 
+           state = 6;                                                      % Confirm
+         end
+       end
+       %% ======= Enter state 6 which is T wave possible detection ======%%
+       if state ==6   
+         c = c + 1;                                                        % set a counter to exit the state if no T wave detected after 0.3 second
+         if c <= 0.7*fs  
+             %------------------------------------------------------------%
+             % set a double threshold based on the last detected S wave and
+             % baseline of the signal and look for T wave in between these
+             % two threshold
+             %------------------------------------------------------------%
+             thres2 = ((abs(abs(buffer_T)-abs(S_amp1(S_C))))*3/4 + S_amp1(S_C)); 
+             thres2_p_C = thres2_p_C + 1;
+             thres2_p(thres2_p_C) = thres2;
+             thres2_p_i(thres2_p_C) = ind;
+             if mean_online > thres2
+              T_on = T_on +1;                                              % make sure it stays on for at least 3 samples
+              if T_on >= round(0.0120*fs)
+               if buffer_plot(i-window-1)>= buffer_plot(i-window)
+                   T_on1 = T_on1+1;                                        % make sure its a real slope change
+                  if T_on1 > round(0.0320*fs) 
+                   T_C = T_C + 1;
+                   T_i(T_C) = i-window-11;                                 % save index of T wave
+                   T_amp(T_C) = buffer_plot(i-window-11);                  % save index
+                   state = 5;                                              % enter sleep mode
+                   T_on = 0;
+                   T_on1 = 0;
+                  end                      
+               end
+              end
+             end         
+         else
+             state= 5;                                                     % enter Sleep mode
+         end
+         
+       end  
+  %% ==== Sleep To avoid multiple detections ================== %%
+       if state==5
+           sleep =sleep+c+1;
+           c = 0;
+           if sleep/fs >= 0.400
+               state = 0;
+               sleep = 0;
+           end  
+       end     
+  end
+  
+end
+%% ============== Adjust Length of Signals ===================== %%
+R_i = R_i(1:R_C);
+S_i = S_i(1:S_C);
+S_amp1 = S_amp1(1:S_C);
+S_amp1_i = S_amp1_i(1:S_C);
+T_i = T_i(1:T_C);
+Q_i = Q_i(1:Q_C);
+thres_p_i = thres_p_i(1:thres_p_C);
+thres_p = thres_p(1:thres_p_C);
+buffer_plot = buffer_plot(1:SP_counter);
+thres2_p = thres2_p(1:thres2_p_C);
+thres2_p_i = thres2_p_i(1:thres2_p_C);
+%% conditions
+%heart_rate=R_C/(time_scale/60); % calculate heart rate
+%msgbox(strcat('Heart-rate is = ',mat2str(heart_rate)));
+
+
+%% plottings 
+if gr
+   view = length(ecg)/fs;
+   time = 1/fs:1/fs:view;
+   R = find(R_i <= view*fs);                                                  % determine the length for plotting vectors
+   S = find(S_i <= view*fs);                                                  % determine the length for plotting vectors
+   T = find(T_i <= view*fs);                                                  % determine the length for plotting vectors
+   Q = find(Q_i <= view*fs);                                                  % determine the length for plotting vectors
+   L1 = find(thres_p_i <= view*fs);
+   L2 = find(S_amp1_i <= view*fs);
+   L3 = find(thres2_p_i <= view*fs);
+   if view*fs > length(buffer_plot)
+      ax(1) = subplot(211);plot(time(1:length(buffer_plot)),buffer_plot(1:end));   
+   else
+      ax(1) = subplot(211);plot(time,buffer_plot(1:(view*fs)));
+   end
+   axis tight;
+   hold on,scatter(R_i(1:R(end))./fs,R_amp(1:R(end)),'r');
+   hold on,scatter(S_i(1:S(end))./fs,S_amp(1:S(end)),'g');
+   hold on,scatter(T_i(1:T(end))./fs,T_amp(1:T(end)),'k');
+   hold on,scatter(Q_i(1:Q(end))./fs,Q_amp(1:Q(end)),'m');
+   hold on,plot(thres_p_i(1:L1(end))./fs,thres_p(1:L1(end)),'LineStyle','-.','color','r',...
+    'LineWidth',2.5);
+   hold on,plot(S_amp1_i(1:L2(end))./fs,S_amp1(1:L2(end)),'LineStyle','--','color','c',...
+    'LineWidth',2.5);
+   hold on,plot(thres2_p_i(1:L3(end))./fs,thres2_p(1:L3(end)),'-k','LineWidth',2);
+   legend('Raw ECG Signal','R wave','S wave','T wave','R adaptive thres','Latest S wave','T wave adaptive threshold threshold','Location','NorthOutside','Orientation','horizontal'); 
+   xlabel('Time(sec)'),ylabel('V');
+   axis tight; 
+   title('Zoom in to see both signal details overlaied');
+   title('Filtered, smoothed and processed signal');
+   ax(2) =subplot(212);
+   plot(time,ecg_raw(1:(round(view*fs))));
+   title('Raw ECG')
+   xlabel('Time(sec)'),ylabel('V');
+   legend(); 
+   linkaxes(ax,'x');
+   zoom on;
+   axis tight;
+end
\ No newline at end of file