How to cut data after defined number of peaks?

23 views (last 30 days)
Hello,
I have input data from force plates to analyse a side hop test. I have to find the time, that is needed to perform 20 jumps overall. Sometimes the athlets do one or two jumps more, because of counting errors. I would like to cut the data before the first and after the 20th jump.
I define a jump by its flight phases (red in the picture) and the peaks are the landings. It would also be possible to define the jumps by the peaks (maybe this is easier), but I don´t have toolboxes, I use usualy "peekseak" from Peter O'Connor instead of findpeaks.
The blue marked points are supposed to be my start and end points for the time meassuring. The first is before the athlet starts to jump and the last is the contact to the ground after the 20th jump.
Is it possible to count 20 jumps and "measure" the time?
Hopefully you can understand me.
My code is below and the data is attached.
Thank you very much!
[filename,pathname] = uigetfile('*.mat','Bitte Kraftdaten von Side Hop links auswählen','C:\Users\Hannah\OneDrive\Dokumente\MATLAB\BG_Motoriklabor');
load([pathname, filename]);
%
Data = struct2cell(load([pathname,filename]));
% Force data
F1 = (Data{1,1}.Force(1).Force);
F2 = (Data{1,1}.Force(2).Force);
f = Data{1,1}.Force.Frequency;
Frames = Data{1,1}.Force.NrOfSamples;
% isolate vertical force for each force plate
F_ges = F1 + F2;
F_vert = F_ges(3,:);
F_vert_l = F1(3,:);
F_vert_r = F2(3,:);
%% Side Hop Test mit linkem Fuß
MinPeakHt = 800; % Mindesthöhe der Peaks
MinPeakDist = 290; % Mindestabstand der Peaks
% Sprünge in den Daten finden
[locs, pks] = peakseek(F_vert, MinPeakDist, MinPeakHt);
x = 1:length(F_vert); % create x axis data
% Plot
figure
plot(x, F_vert)
hold on
plot(x(locs),F_vert(locs),'dr');
% Define the flight phases
index_Flug_l = find(F__vert_l < 10);
index_Flug_r = find(F_vert_r < 10);
% ("zeros")
diffstart_l = zeros(1, length(index_Flug_l)-1);
diffstart_r = zeros(1, length(index_Flug_r)-1);
% every datapoint with y=0
for n = 1:length(index_Flug_l)-1
diffstart_l(n) = index_Flug_l(n+1)-index_Flug_l(n); % difference between the points
end
% beginning and end of the contact with the ground
indexdiff_l = find(diffstart_l > 50);
for n = 1:length(index_Flug_r)-1
diffstart_r(n) = index_Flug_r(n+1)-index_Flug_r(n); %gibt die Differenz zum vorhergehenden Punkt an
end
indexdiff_r = find(diffstart_r > 50);
function [locs, pks]=peakseek(x,minpeakdist,minpeakh)
% x is a vector input (generally a timecourse)
% minpeakdist is the minimum desired distance between peaks (optional, defaults to 1)
% minpeakh is the minimum height of a peak (optional)
%
% (c) 2010
% Peter O'Connor
% peter<dot>ed<dot>oconnor .AT. gmail<dot>com
if size(x,2)==1, x=x'; end
% Find all maxima and ties
locs=find(x(2:end-1)>=x(1:end-2) & x(2:end-1)>=x(3:end))+1;
if nargin<2, minpeakdist=1; end % If no minpeakdist specified, default to 1.
if nargin>2 % If there's a minpeakheight
locs(x(locs)<=minpeakh)=[];
end
if minpeakdist>1
while 1
del=diff(locs)<minpeakdist;
if ~any(del), break; end
pks=x(locs);
[garb, mins]=min([pks(del) ; pks([false del])]); %#ok<ASGLU>
deln=find(del);
deln=[deln(mins==1) deln(mins==2)+1];
locs(deln)=[];
end
end
if nargout>1
pks=x(locs);
end
end

Accepted Answer

Mathieu NOE
Mathieu NOE on 21 Jul 2022
hello Hannah
here you are - blue start / end points defined by your preferred peakseek function
NB : the blue points are not anyhow related to the 'red' peaks you have already picked. You coule even remove that portion of the code you can still get the answer for the two blue points
the result is stored in
t_delta = 8352 samples
hope it helps !
% [filename,pathname] = uigetfile('*.mat','Bitte Kraftdaten von Side Hop links auswählen','C:\Users\Hannah\OneDrive\Dokumente\MATLAB\BG_Motoriklabor');
% load([pathname, filename]);
% Data = struct2cell(load([pathname,filename]));
clc
clearvars
% modified load data for my own purpose (switch back to yours)
pathname = pwd;
filename = 'SideHop_l.mat';
Data = struct2cell(load(fullfile(pathname,filename)));
% Force data
F1 = (Data{1,1}.Force(1).Force);
F2 = (Data{1,1}.Force(2).Force);
f = Data{1,1}.Force.Frequency;
Frames = Data{1,1}.Force.NrOfSamples;
% isolate vertical force for each force plate
F_ges = F1 + F2;
F_vert = F_ges(3,:);
F_vert_l = F1(3,:);
F_vert_r = F2(3,:);
%% Side Hop Test mit linkem Fuß
MinPeakHt = 800; % Mindesthöhe der Peaks
MinPeakDist = 290; % Mindestabstand der Peaks
% Sprünge in den Daten finden
[locs, pks] = peakseek(F_vert, MinPeakDist, MinPeakHt);
samples = numel(F_vert);
x = 1:samples; % create x axis data
%% Define the flight phases
% let's take the force signal and create a start /stop time of flight periods
low_F_signal = zeros(size(F_vert)); % init
ind = find(F_vert<200); %
low_F_signal(ind) = 1;
startstop = [0 diff(low_F_signal)];
flight_start_points = find(startstop>0);
flight_stop_points = find(startstop<0);
%% find 'blue' start point
% isolate beginning of signal from index 1 to first index of flight_start_points
ind_begin = (1:flight_start_points(1));
F_begin = F_vert(ind_begin);
% smooth a bit the signal (to avoid multiple peak detects due to background noise)
F_begin = smoothdata(F_begin,'gaussian',15);
% find peaks
MinPeakHt = 500; % Mindesthöhe der Peaks
MinPeakDist = 200; % Mindestabstand der Peaks
[locs_begin, pks_begin]=peakseek(F_begin,MinPeakDist,MinPeakHt);
% the first blue mark is the one before last index (=> locs(end-1))
ind_begin = ind_begin(locs_begin(end-1));
x_begin = x(ind_begin);
F_begin = F_vert(ind_begin);
%% find 'blue' stop point
% similar logic as above - first extract ending portion of force signal and
% get first peak = second blue mark
% isolate ending of signal from index flight_stop_points(end) to index =
% samples
% here the last flight_stop_points point correspond to 20 jumps so both
% following lines of code are equivalent :
% ind_ending = (flight_stop_points(end):samples);
% or
jumps = 20;
ind_ending = (flight_stop_points(jumps):samples); % <= I picked this one as we explicit that we want 20 jumps
x_ending = x(ind_ending);
F_ending = F_vert(ind_ending);
% smooth a bit the signal (to avoid multiple peak detects due to background noise)
F_ending = smoothdata(F_ending,'gaussian',15);
% find peaks
MinPeakHt = 500; % Mindesthöhe der Peaks
MinPeakDist = 200; % Mindestabstand der Peaks
[locs_ending, pks_ending]=peakseek(F_ending,MinPeakDist,MinPeakHt);
% the second (last) blue mark is the first peak
ind_ending = ind_ending(locs_ending(1));
x_ending = x(ind_ending);
F_ending = F_vert(ind_ending);
% Plot
figure(1)
subplot(2,1,1),
plot(x,F_vert,x(locs),F_vert(locs),'*r','markersize',8)
hold on
plot(x_begin,F_begin,'db',x_ending,F_ending,'db','markersize',18)
hold off
subplot(2,1,2),plot(x, startstop)
title('positive pulses = start of flight / negative pulses = end of flight');
%% Time delta
t_delta = x_ending - x_begin; % here in samples , multiply by sampling period to have it in seconds
%%%%
function [locs, pks]=peakseek(x,minpeakdist,minpeakh)
% x is a vector input (generally a timecourse)
% minpeakdist is the minimum desired distance between peaks (optional, defaults to 1)
% minpeakh is the minimum height of a peak (optional)
%
% (c) 2010
% Peter O'Connor
% peter<dot>ed<dot>oconnor .AT. gmail<dot>com
if size(x,2)==1, x=x'; end
% Find all maxima and ties
locs=find(x(2:end-1)>=x(1:end-2) & x(2:end-1)>=x(3:end))+1;
if nargin<2, minpeakdist=1; end % If no minpeakdist specified, default to 1.
if nargin>2 % If there's a minpeakheight
locs(x(locs)<=minpeakh)=[];
end
if minpeakdist>1
while 1
del=diff(locs)<minpeakdist;
if ~any(del), break; end
pks=x(locs);
[garb, mins]=min([pks(del) ; pks([false del])]); %#ok<ASGLU>
deln=find(del);
deln=[deln(mins==1) deln(mins==2)+1];
locs(deln)=[];
end
end
if nargout>1
pks=x(locs);
end
end

More Answers (0)

Community Treasure Hunt

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

Start Hunting!