How to discard beginning and end of the signal when extracting elements of the signal identified via findpeaks?

2 views (last 30 days)
Tomaszzz on 28 Jan 2022
Commented: Mathieu NOE on 2 Feb 2022
Hi all,
I have a 'good looking'signal like this:
I am extracting parts of the signal between first red and first green, second red and second green and so on, using the following code:
load 'badsignal'
% identify all troughs in data
[all_trough_value,all_trough_location]= findpeaks(-thigh_orient_y);
all_trough_value = -all_trough_value;
% Identify main peaks (i.e. ones lower than 50; blue stars)
[main_trough_value,main_trough_location]= findpeaks(thigh_orient_y,'minpeakheight',-50);
% Identify start of the movement cycle (first minimum before main peak; red circle)
for i = 1:length(main_trough_location)
peak_location = find(islocalmax(thigh_orient_y,'MinProminence',40));
backward = arrayfun(@(x) diff(thigh_orient_y(x:-1:1)),peak_location,'UniformOutput',false);
num_back = cellfun(@(x) find(x>0,1,'first'),backward);
start_location = peak_location-num_back+1;
start_value = thigh_orient_y(start_location);
% Identify end of the movement cycle (first minimum after the main peak; grean circle)
counter = 0;
for i = 1:length(main_trough_location)
%finds end of movement cycle
index = all_trough_location > main_trough_location(i);
if sum(index)>0 % this will ignore if the main trough is too far right so there are no peaks afterwards
counter = counter + 1;
end_location(counter) = all_trough_location(find(index,1));
end_value(counter) = all_trough_value(find(index, 1));
% Plot
hold on
h = legend('signal',' all troughs','midcycle','start', 'end');
box off
% Extract parts of the signal between red and green cycles
a = start_location ;
b = end_location;
n = length(a);
T_or_y_cycle = cell(n,1) ;
%Fill in the above cell with data per movement cycle
for i = 1:n
T_or_y_cycle{i} = thigh_orient_y(a(i):b(i)) ;
However, I get the following error
Index exceeds the number of array elements (8).
when I have a 'bad-lookng' signal (attached) like this
which I suppose is due to lack of first minimum after last main peak as circled in red on the right side. I might have signals that will lack both minimas at the begginig and end of the signal (as indicated by large red cirlces).
Thus, if this is the case, when I extract elements of the signals into the cells I want to omit first and last parts i.e. first red to first green and last red to last green. Or using any more optimal way to make this work.
Can you help please?

Accepted Answer

Mathieu NOE
Mathieu NOE on 31 Jan 2022
I wanted to challenge your code and came with a different solution . This new code will retain only valid peaks with one local mimimum before and after each peak . Your cell array extraction is now inside the single main loop.
load 'badsignal'
A = thigh_orient_y;
x = 1:numel(A);
% find all peaks above -50
ind_peaks = islocalmax(A);
ind_peaks = find(ind_peaks & (A > -50));
x_peaks = x(ind_peaks);
A_peaks = A(ind_peaks);
% find all troughs
ind_trough = find(islocalmin(A));
x_ind_trough = x(ind_trough);
A_trough = A(ind_trough);
% find local minimum before and after peak
ind_failed = [];
for ci = 1:numel(ind_peaks)
% local minimum before peak
tmp1 = find(x_ind_trough <= x_peaks(ci),1,'last');
% local minimum after peak
tmp2 = find(x_ind_trough >= x_peaks(ci),1,'first');
if ~isempty(tmp1) & ~isempty(tmp2)
i_lower(ci) = ind_trough(tmp1);
x_lower(ci) = x(i_lower(ci));
A_lower(ci) = A(i_lower(ci));
i_higher(ci) = ind_trough(tmp2);
x_higher(ci) = x(i_higher(ci));
A_higher(ci) = A(i_higher(ci));
x_peaks_final(ci) = x_peaks(ci);
A_peaks_final(ci) = A_peaks(ci);
% Extract parts of the signal between red and green cycles
T_or_y_cycle{ci} = A(i_lower(ci):i_higher(ci)) ;
%figure(1+ci),plot(T_or_y_cycle{ci}) % for debug / vizualisation only
ind_failed = [ind_failed ci]; % for information mostly

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!