Filter EKG with artifacts (respiratory or movement of electrode)
    4 views (last 30 days)
  
       Show older comments
    
Hi Everybody,
I'm doing a resarch with a t-shirt with built-in sensors, in particular I'm doing HRV analyses, I'm not very good at signal filtering so I'm asking for help.
From this t-shirt i can extract the respiratory signal and the EKG both attached here, in both file the first raw is time in seconds.
I would like to clean this EKG (and other similar of this patient) so that i can extract reliably peak R, in this case I attached also the respiratory signal as I think the fluctuations in the signal may be due to that.
Thank for the help.
2 Comments
  Mathieu NOE
      
 on 22 Dec 2021
				hello 
my 2 cents
tried rapidely some filering and other stuff on the breath signal - not sure if this will help you ...

load('breath.mat')
time = Breath(1,:);
signal = detrend(Breath(2,:),'linear');
signal = signal-min(signal); % so the min is set at zero
dt = mean(diff(time));
Fs = 1/dt;
%smoothed curve
signal_sm = smoothdata(signal,'gaussian',500);
% difference = dynamic portion
signal_dyn = signal-signal_sm;
% computing "threshold" level crossing points on the smoothed signal 
threshold1 = max(signal_sm)*0.7; % your value here
[t0_pos1,s0_pos1,t0_neg1,s0_neg1]= crossing_V7(signal_sm,time,threshold1,'linear'); % positive (pos) and negative (neg) slope crossing points 
% ind => time index (samples)
% t0 => corresponding time (x) values 
% s0 => corresponding function (y) values , obviously they must be equal to "threshold"
% computing "threshold" level crossing points on the dynamic signal 
threshold2 = max(signal_dyn)*0.25; % your value here
[t0_pos2,s0_pos2,t0_neg2,s0_neg2]= crossing_V7(signal_dyn,time,threshold2,'linear'); % positive (pos) and negative (neg) slope crossing points 
figure(1);
subplot(211),plot(time,signal,time,signal_sm);
plot(time,signal,time,signal_sm,time,threshold1*ones(size(time)),'k--',t0_pos1,s0_pos1,'dr',t0_neg1,s0_neg1,'dg','linewidth',2,'markersize',12);grid on
xlabel('time (s)');
legend('signal','signal smoothed','threshold','positive slope crossing points','negative slope crossing points');
subplot(212),plot(time,signal_dyn)
subplot(212),plot(time,signal_dyn,time,threshold2*ones(size(time)),'k--',t0_pos2,s0_pos2,'dr',t0_neg2,s0_neg2,'dg','linewidth',2,'markersize',12);grid on
legend('signal dynamic','threshold','positive slope crossing points','negative slope crossing points');
xlabel('time (s)');
period1 = diff(t0_pos1) % period in seconds for smoothed signal
period2 = diff(t0_pos2) % period in seconds for dynamic signal
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [t0_pos,s0_pos,t0_neg,s0_neg] = crossing_V7(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth,slope_sign) % older format
% CROSSING find the crossings of a given level of a signal
%   ind = CROSSING(S) returns an index vector ind, the signal
%   S crosses zero at ind or at between ind and ind+1
%   [ind,t0] = CROSSING(S,t) additionally returns a time
%   vector t0 of the zero crossings of the signal S. The crossing
%   times are linearly interpolated between the given times t
%   [ind,t0] = CROSSING(S,t,level) returns the crossings of the
%   given level instead of the zero crossings
%   ind = CROSSING(S,[],level) as above but without time interpolation
%   [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
%   par = {'none'|'linear'}.
%	With interpolation turned off (par = 'none') this function always
%	returns the value left of the zero (the data point thats nearest
%   to the zero AND smaller than the zero crossing).
%
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
	% if no time vector is given, use the index vector as time
    t = 1:length(S);
elseif length(t) ~= length(S)
	% if S and t are not of the same length, throw an error
    error('t and S must be of identical length!');    
end
% check the level input
if nargin < 3
	% set standard value 0, if level is not given
    level = 0;
end
% check interpolation method input
if nargin < 4
    imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of 
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S   = S - level;
% first look for exact zeros
ind0 = find( S == 0 ); 
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together 
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind); 
s0 = S(ind);
if ~isempty(ind)
    if strcmp(imeth,'linear')
        % linear interpolation of crossing
        for ii=1:length(t0)
            %if abs(S(ind(ii))) >= eps(S(ind(ii)))    % MATLAB V7 et +
            if abs(S(ind(ii))) >= eps*abs(S(ind(ii)))    % MATLAB V6 et -    EPS * ABS(X)
                % interpolate only when data point is not already zero
                NUM = (t(ind(ii)+1) - t(ind(ii)));
                DEN = (S(ind(ii)+1) - S(ind(ii)));
                slope =  NUM / DEN;
                slope_sign(ii) = sign(slope);
                t0(ii) = t0(ii) - S(ind(ii)) * slope;
                s0(ii) = level;
            end
        end
    end
    % extract the positive slope crossing points 
    ind_pos = find(sign(slope_sign)>0);
    t0_pos = t0(ind_pos);
    s0_pos = s0(ind_pos);
    % extract the negative slope crossing points 
    ind_neg = find(sign(slope_sign)<0);
    t0_neg = t0(ind_neg);
    s0_neg = s0(ind_neg);
else
    % empty output
    ind_pos = [];
    t0_pos = [];
    s0_pos = [];
    % extract the negative slope crossing points 
    ind_neg = [];
    t0_neg = [];
    s0_neg = [];
end
end
Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!