How can I make this find function in a for loop run faster using vectorization?

%% Find Peaks of raw data
tic
if MinPeakDistance == 0
[y_enc, t_pks] = findpeaks(y_raw, freq_s, 'MinPeakProminence', MinPeakProminence);
else
[y_enc, t_pks] = findpeaks(y_raw, freq_s,'MinPeakDistance', MinPeakDistance);
end
toc
%% Find Threshold Points on Rising Edge (threshold value = 2)
x1 = NaN(length(t_pks),1);
x2 = NaN(length(t_pks),1);
y1 = NaN(length(t_pks),1);
y2 = NaN(length(t_pks),1);
y = NaN(length(t_pks)-1,1);
x = NaN(length(t_pks)-1,1);
for i=1:length(t_pks)-1 %trying to find a point above and below the threshold then interpolating for the point at y = 2
ind_y = find(t_raw < t_pks(i+1)& t_raw>t_pks(i));
threshold_pt = find(y_raw(ind_y)<2,1,'last');
x0 = threshold_pt;
y1(i) = y_raw(ind_y(x0));
x1(i) = t_raw(ind_y(x0));
y2(i) = y_raw(ind_y(x0)+1);
x2(i) = t_raw(ind_y(x0)+1);
y(i) = 2;
x(i) = (y(i)-y1(i))*(x2(i)-x1(i))/(y2(i)-y1(i)) + x1(i);
end

2 Comments

Question posted by doyi joo on 29 Nov 2018 restored from Google cache:
How can I make this find function in a for loop run faster using vectorization?
%% Find Peaks of raw data
tic
if MinPeakDistance == 0
[y_enc, t_pks] = findpeaks(y_raw, freq_s, 'MinPeakProminence', MinPeakProminence);
else
[y_enc, t_pks] = findpeaks(y_raw, freq_s,'MinPeakDistance', MinPeakDistance);
end
toc
%% Find Threshold Points on Rising Edge (threshold value = 2)
x1 = NaN(length(t_pks),1);
x2 = NaN(length(t_pks),1);
y1 = NaN(length(t_pks),1);
y2 = NaN(length(t_pks),1);
y = NaN(length(t_pks)-1,1);
x = NaN(length(t_pks)-1,1);
for i=1:length(t_pks)-1 %trying to find a point above and below the threshold then interpolating for the point at y = 2
ind_y = find(t_raw < t_pks(i+1)& t_raw>t_pks(i));
threshold_pt = find(y_raw(ind_y)<2,1,'last');
x0 = threshold_pt;
y1(i) = y_raw(ind_y(x0));
x1(i) = t_raw(ind_y(x0));
y2(i) = y_raw(ind_y(x0)+1);
x2(i) = t_raw(ind_y(x0)+1);
y(i) = 2;
x(i) = (y(i)-y1(i))*(x2(i)-x1(i))/(y2(i)-y1(i)) + x1(i);
end

Sign in to comment.

 Accepted Answer

Try this:
zci = @(v) find(v(:).*circshift(v(:), [-1 0]) <= 0); % Returns Approximate Zero-Crossing Indices Of Argument Vector
x = linspace(0, 8*pi, 150); % Create Data
y = 3*sin(x); % Create Data
y2idx = zci(y-2); % Approximate Indices Where y=2
for k1 = 1:numel(y2idx)
idxrng = [y2idx(k1)-1 y2idx(k1)+1];
b = [x(idxrng(1)) 1; x(idxrng(2)) 1]\y(idxrng).'; % Calculate Linear Fit
xy2(k1) = (2-b(2))/b(1); % Evaluate Linear Fit
end
figure
plot(x, y)
hold on
plot(xy2, 2*ones(size(xy2)), 'x')
hold off
grid
It uses a little utility function ‘zci’ to calculate the zero-crossing indices (with ‘zero’ is defined here as +2), then loops through the indices, calculating a linear fit and then doing the interpolation at each step, returning the interpolated x-value in the ‘xy2’ vector. The plot simply shows the results, and how to use them.

2 Comments

My pleasure!
I did not have your data to work with, so I created my own data to illustrate the approach.
Yes. I wrote ‘zci’ for my own use originally.
If my Answer helped you solve your problem, please Accept it!
Comment restored from Google cache:
Hi, thanks for replying!
I tried to use it...basically substituting your X and Y with my datasets. I get Subscript indices must either be real positive integers or logicals.error. I am not sure what is happening in the for loop to figure out how to mitigate it...
Comment restored from Google cache:
I figured it out!
Thank you so much!
Did you write the ZCI Function?

Sign in to comment.

More Answers (0)

Categories

Find more on Descriptive Statistics and Insights in Help Center and File Exchange

Products

Release

R2017b

Tags

No tags entered yet.

Asked:

J J
on 29 Nov 2018

Commented:

on 12 Oct 2020

Community Treasure Hunt

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

Start Hunting!