How can I make this find function in a for loop run faster using vectorization?
1 view (last 30 days)
Show older comments
%% 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
Rik
on 26 Jun 2020
Edited: Rik
on 26 Jun 2020
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
Accepted Answer
Star Strider
on 29 Nov 2018
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
Star Strider
on 29 Nov 2018
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!
Rik
on 26 Jun 2020
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?
More Answers (0)
See Also
Categories
Find more on Probability Distributions 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!