Pattern extraction from a signal
    5 views (last 30 days)
  
       Show older comments
    
I am trying to get all the patterns that could be extracted from my signal. I could extract patterns by defining a threshold and only taking part of signal that crosses the threshold. But to use  this approach, I need to define the sample/time difference between each pattern beforehand. Furhtermore I have lot of zero-crossing in the signal and there is no trend in the amplitude either. Is there any approcah where I can just extract all the patterns straightforwardly without using thershold or time difference. I have also attached my signal and patterns that I got using  the threshold approach.
Thanks.
4 Comments
  Walter Roberson
      
      
 on 15 Mar 2022
				When you do not have hard rules about the boundaries, then the number of patterns is related to Partition Theory https://en.wikipedia.org/wiki/Partition_function_(number_theory) and becomes huge as the signal grows modestly in length.
  Mathieu NOE
      
 on 15 Mar 2022
				hi
can you make a decision based on spectral content ? if you were to do a spectrogram , can you select the patterns because a certain rule based on amplitude / frequency can be used ? 
otherwise , I would too have used a kind of envelope and zero crossing detection 
Answers (1)
  Mathieu NOE
      
 on 15 Mar 2022
        hello 
maybe this ? (already discussed above) 

clc
clearvars
% dummy signal
n=1000;
x=linspace(0,2*pi*3,n);
y = 0.25*randn(size(x));
y(100:199) = randn(1,100);
y(400:499) = randn(1,100);
y(600:699) = randn(1,100);
% home made envelope
env = smoothdata(abs(y),'gaussian',100);
threshold = 0.25*max(env)+0.75*min(env); % your value here
[t0_pos,s0_pos,t0_neg,s0_neg]= crossing_V7(env,x,threshold,'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"
figure(1)
plot(x,y,x,env,x,threshold*ones(size(x)),'k--',t0_pos,s0_pos,'dr',t0_neg,s0_neg,'dg','linewidth',2,'markersize',12);grid on
legend('signal',' my envelope','threshold','positive slope crossing points','negative slope crossing points');
period = diff(t0_pos)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
0 Comments
See Also
Categories
				Find more on Multirate Signal Processing in Help Center and File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!