# extracting one cycle from multiple sinusoidal waves

5 views (last 30 days)
Abdulla Almesmari on 1 Dec 2021
Commented: Mathieu NOE on 2 Dec 2021
I am trying to extract one single cycle from each of the four responses attached into the excel sheet. Eventually I want to combine those extracted cycles into one array, for example A will have four columns:
column 1: one cycle of response 1
column 2: one cycle of response 2
column 3: one cycle of response 3
column 4: one cycle of response 4

Mathieu NOE on 1 Dec 2021
hello
I used zero crossing interpolation method to select the last cycle of the data
the extracted data are interpolated because the start and stop time values are themselves interpolated data for maximum time precision and therefore may not belong to the actual data
clc
clearvars
t = T.time_sec_;
R1 = T.resp1;
R2 = T.resp2;
R3 = T.resp3;
R4 = T.resp4;
threshold = 0; % your value here
[t0_pos1,s0_pos1,t0_neg1,s0_neg1]= crossing_V7(R1,t,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
figure(1),plot(t,R1,t0_pos1,s0_pos1,'db',t0_neg1,s0_neg1,'dg','linewidth',2,'markersize',12);grid on
legend('signal 1','signal 1 positive slope crossing points','signal 1 negative slope crossing points' );
% NB : t0_pos1 is interpolated so maybe best solution is to interpolate
% the data on new time axis; last cycle of data is used
new_t1 = linspace(t0_pos1(end-1),t0_pos1(end),100);
new_R1 = interp1(t,R1,new_t1);
figure(2),plot(new_t1,new_R1);
% same logic on R2
[t0_pos2,s0_pos2,t0_neg2,s0_neg2]= crossing_V7(R2,t,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
figure(3),plot(t,R2,t0_pos2,s0_pos2,'db',t0_neg2,s0_neg2,'dg','linewidth',2,'markersize',12);grid on
legend('signal 2','signal 2 positive slope crossing points','signal 2 negative slope crossing points' );
new_t2 = linspace(t0_pos2(end-1),t0_pos2(end),100);
new_R2 = interp1(t,R2,new_t2);
figure(4),plot(new_t2,new_R2);
% same logic on R3
[t0_pos3,s0_pos3,t0_neg3,s0_neg3]= crossing_V7(R3,t,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
figure(5),plot(t,R3,t0_pos3,s0_pos3,'db',t0_neg3,s0_neg3,'dg','linewidth',2,'markersize',12);grid on
legend('signal 3','signal 3 positive slope crossing points','signal 3 negative slope crossing points' );
new_t3 = linspace(t0_pos3(end-1),t0_pos3(end),100);
new_R3 = interp1(t,R3,new_t3);
figure(6),plot(new_t3,new_R3);
% same logic on R4
[t0_pos4,s0_pos4,t0_neg4,s0_neg4]= crossing_V7(R4,t,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
figure(7),plot(t,R4,t0_pos4,s0_pos4,'db',t0_neg4,s0_neg4,'dg','linewidth',2,'markersize',12);grid on
legend('signal 4','signal 4 positive slope crossing points','signal 4 negative slope crossing points' );
new_t4 = linspace(t0_pos4(end-1),t0_pos4(end),100);
new_R4 = interp1(t,R4,new_t4);
figure(8),plot(new_t4,new_R4);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% % Some people like to get the data points closest to the zero crossing,
% % so we return these as well
% [CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
% ind2 = ind + (II-2); %update indices
%
% t0close = t(ind2);
% s0close = S(ind2);
end
Mathieu NOE on 2 Dec 2021
My pleasure !