Reputation: 21
distances = sqrt((x - max(x)).^2 + (y - max(y)).^2);
[peaks, iPeaks] = findpeaks(distances);%to find out where the curve turns around
for i = 1 : length(iPeaks)-1
iPeaks1 = iPeaks(i);
iPeaks2 = iPeaks(i+1)-1;%analyse of consecutive pair of peaks
%skip small noise peaks
if length(iPeaks1:iPeaks2)>=5
xx=x(iPeaks1:iPeaks2)
yy=y(iPeaks1:iPeaks2)
end
end
hello
i need to construct vectors xx and yy. The problem is that at each cycle the past xx and yy is deleted but i want the opposite. i want them to keep the past information and grow at each cycle. what can i do? and also i know i should preallocate xx and yy.
i appreciate any help. thank you very much.
**this is a possible solution. the problem here is i need to preallocate. but if i do it, the xx and yy keep the zeros and continue to grow 'with the zeros inside' and that is wrong
:
distances = sqrt((x - max(x)).^2 + (y - max(y)).^2);
[peaks, iPeaks] = findpeaks(distances);%to find out where the curve turns around
xx=[];
yy=[];
for i = 1 : length(iPeaks)-1
iPeaks1 = iPeaks(i);
iPeaks2 = iPeaks(i+1)-1;%analyse of consecutive pair of peaks
%skip small noise peaks
if length(iPeaks1:iPeaks2)>=5
xx = [xx; x(iPeaks1:iPeaks2)];%''concatenate''(connect)
yy = [yy; y(iPeaks1:iPeaks2)];
end
end
Upvotes: 0
Views: 618
Reputation: 8527
Growing a vector is easily done using concatenation:
x = [1, 2, 3];
y = [4, 5, 6, 7];
z = [x, y]; %# z will be [1, 2, 3, 4, 5, 6, 7]
In your case you would do
%# Start with an empty vector.
xx = [];
for i = 1 : length(iPeaksNoise)-1
[...]
xx = [xx, x(iPeaks1:iPeaks2)];
end
To be independent of the shape of iPeaksNoise
(i.e. no matter if it is a row- or
column-vector) you could use
for [...]
t = x(iPeaks1:iPeaks2);
xx = [xx; t(:)];
end
Preallocation means to create a vector of zeros, which has the length of your final output. You would do something like this
final_size = what_so_ever;
xx = zeros(final_size, 1);
start_index = 1;
for [...]
t = x(iPeaks1:iPeaks2);
xx(start_index : start_index + length(t) - 1) = t;
start_index = start_index + length(t);
end
However, in your case you have the additional difficulty that do not know the final size
of xx
in advance, because you do not know how often length(iPeaks1:iPeaks2)>=5
is
fulfilled inside the loop.
Edit:
A code with pre-allocation of xx
could look like:
distances = sqrt((x - max(x)).^2 + (y - max(y)).^2);
[peaks, iPeaks] = findpeaks(distances);
%# Compute the distance between two peaks.
peakDistance = diff(iPeaks);
%# Filter peaks which are of length 5 or less.
peakMask = peakDistance > 5;
finalSize = sum(peakDistance(peakMask));
%# Copy the values in a new vector.
xx = zeros(1, finalSize);
idx = 1;
for count = 1 : length(peakDistance)
if peakMask(count)
pD = peakDistance(count);
xx(idx : idx + pD - 1) = x(iPeaks(count) : iPeaks(count) + pD - 1);
idx = idx + pD;
end
end
Upvotes: 1
Reputation: 421
Here I'm presuming that the number of elements you are going to add to xx and yy in each iteration is NOT the same every time. Then if you want to preallocate space you need to find out how much you are going to add up then. So the code will become more complicated with an extra loop. One version might be
x=(5*sin(0:(pi/100):2*pi)+rand(201,1)'-0.5)';
y=(5*cos(0:(pi/100):2*pi)+rand(201,1)'-0.5)';
%%
distances = sqrt((x - max(x)).^2 + (y - max(y)).^2);
[peaks, iPeaks] = findpeaks(distances);%to find out where the curve turns around
counterx = 0;
for i = 1 : length(iPeaks)-1
iPeaks1 = iPeaks(i);
iPeaks2 = iPeaks(i+1)-1;%analyse of consecutive pair of peaks
%skip small noise peaks
if length(iPeaks1:iPeaks2)>=5
counterx =counterx+ iPeaks2-iPeaks1+1;
end
end
xx=zeros(counterx,1);
yy=xx;
counterx=0;
clc
for i = 1 : length(iPeaks)-1
iPeaks1 = iPeaks(i);
iPeaks2 = iPeaks(i+1)-1;%analyse of consecutive pair of peaks
%skip small noise peaks
if length(iPeaks1:iPeaks2)>=5
% xx = [xx; x(iPeaks1:iPeaks2)];%''concatenate''(connect)
% yy = [yy; y(iPeaks1:iPeaks2)];
counterx=counterx+1;
xx(counterx:counterx+iPeaks2-iPeaks1) = x(iPeaks1:iPeaks2);
yy(counterx:counterx+iPeaks2-iPeaks1) = y(iPeaks1:iPeaks2);
counterx=counterx+iPeaks2-iPeaks1;
end
end
disp([xx yy]')
But then, this is matlab. You shouldn't have to do all that. Here's some code that does the same thing using logical flags and just removes all the small peaks in a single swoop:
% find all the iPeaks that are 5 apart from the next one
peakdiffs = find((iPeaks(2:end)-iPeaks(1:end-1)-1)>=5);
% make a logical array quickly with same size as x
removeflag = x<=inf;
for i=1:numel(peakdiffs)
% for each peak that is bigger than your threshold, those parts of the
% logical array will be made false.
removeflag(iPeaks(peakdiffs(i)):iPeaks(peakdiffs(i)+1)-1)=false;
end
%remove all indices in x,y that are still false in removeflag and store in xx
%and yy resp
xx= x; xx(removeflag)=[];
yy= x; yy(removeflag)=[];
disp([xx yy]')
Upvotes: 0
Reputation: 11810
You need to explicitly state where in xx
and yy
you want to place the data. From your code it is difficult to understand where you want it, but it should look something in these lines
start = some_index_in_xx;
v = x(iPeaks1:iPeaks2);
xx(start:start+numel(v)-1)=v;
And the same for yy
. start
you have to compute yourself.
If on the other hand you want to append the new x
and y
vector parts to the end of xx
and yy
, you'd do this
xx = [xx x(iPeaks1:iPeaks2)];
yy = [yy y(iPeaks1:iPeaks2)];
You have to initialize xx
and yy
before the loop:
xx = [];
yy = [];
Upvotes: 0