user1675777
user1675777

Reputation: 21

concatenate vectors if cycle matlab

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

Answers (3)

Mehrwolf
Mehrwolf

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

user930916
user930916

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

angainor
angainor

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

Related Questions