Remove the cycles - matlab

I need to get rid of loops in my Matlab code. During this procedure, i encountered the following problem. Here is the part of the code
Nx=11; Ny=11;
A=rand(Ny,Nx);
A1=A;
for j=2:Ny-1
for i=2:Nx-1
A(j,i)=A(j,i-1);
end;
end;
A1(2:Ny-1,2:Nx-1)=A1(2:Ny-1,1:Nx-2);
A2=A-A1;
I get that A is not equal to A1. The situation is the same with the j-1 index on the right side. However, if we take the index i + 1 or j + 1, then everything works fine.

The problem is relatively simple: you are shifting the columns of A1 to the right all at once (copying over column 1 into 2 and discarding column Nx-1 in the process), whereas your for loop shifts the columns of A to the right one at a time, left to right. This means that first you overwrite column 2 with the contents of column 1, then 3 with 2, and so on, so that you finally end up with Nx-1 copies of the first column. (When I speak of copying/moving/discarding columns, I mean their values from row 2 to row Ny-1.)
As you have noticed, if you modify your loop to shift columns to the left, i.e.
for j=2:Ny-1
for i=2:Nx-1
A(j,i)=A(j,i+1);
%...
then this issue does not happen, since you have a chance to read the original contents of any given column and save them elsewhere before overwriting them with new values.
All of the above results apply when the for loop iterates over columns from left to right. If you reverse the direction of iteration, i.e.
%...
for i=Nx-1:-1:2
A(j,i)=%...
then right-shifting columns works as intended, while shifting them to the left produces bogus results.

Related

Finding the max element in a column of a matrix excluding certain rows

Consider I have an nxn matrix. My goal is to find the max element of the first column, swap the row containing that largest element and the first row. Next, I want to find the max element of the second column, excluding the first row, then swap the row of this new max element and the second row. Again, finding the max element of the jth column excluding rows 1:j-1, then swapping the max element row with the jth row, up until the n-1th column (as during the nth column, I would only be able to choose from the nth row).
My current setup for this is as follows
for j = 1:n-1
[~,row]=max(A(j:n,j));
temp = A(row,:);
A(row,:)=A(j,:);
A(j,:)=temp;
...
While the switching function works well enough, [~, row]=max(A(j:n,j)) is able to, and consistently does for the matrix I'm specifically working on, output row 1 during the second iteration of j. My thought process behind this was that j:n represents the rows we want to check. Noting j=2, for its second iteration, I hoped this would search row 2-to-n; however, it seems to still check every row.
While this question has been asked before, the answer, I found, was this same line of code.
You are using [~,row]=max(A(j:n,j));. Let's say you are in iteration j=2. max will only consider the input from the 2nd row on. A return value of row=1 indicates a maximum in the second row of A. The first row you put into the function. The max function has no clue that you actually input something larger. You have to correct for this.
n=5
A=magic(n); %just some input data
for j = 1:n-1
[~,row]=max(A(j:n,j));
row=row+j-1;
temp = A(row,:);
A(row,:)=A(j,:);
A(j,:)=temp;
end
by the way, matlab can do row swapping without helper variable:
for j = 1:n-1
[~,row]=max(A(j:n,j));
row=row+j-1;
A([row,j],:)=A([j,row],:);
end

How to save matrices from for loop into another matrix

I have a 5-by-200 matrix where the i:50:200, i=1:50 are related to each other, so for example the matrix columns 1,51,101,151 are related to each other, and columns 49,99,149,199 are also related to each other.
I want to use a for-loop to create another matrix that re-sorts the previous matrix based on this relationship.
My code is
values=zeros(5,200);
for j=1:50
for m=1:4:200
a=factor_mat(:,j:50:200)
values(:,m)=a
end
end
However, the code does not work.
Here's what's happening. Let's say we're on the first iteration of the outer loop, so j == 1. This effectively gives you:
j = 1;
for m=1:4:200
a=factor_mat(:,j:50:200)
values(:,m)=a;
end
So you're creating the same submatrix for a (j doesn't change) 50 times and storing it at different places in the values matrix. This isn't really what you want to do.
To create each 4-column submatrix once and store them in 50 different places, you need to use j to tell you which of the 50 you're currently processing:
for j=1:50
a=factor_mat(:,j:50:200);
m=j*4; %// This gives us the **end** of the current range
values(:,m-3:m)=a;
end
I've used a little trick here, because the indices of Matlab arrays start at 1 rather than 0. I've calculated the index of the last column we want to insert. For the first group, this is column 4. Since j == 1, j * 4 == 4. Then I subtract 3 to find the first column index.
That will fix the problem you have with your loops. But loops aren't very Matlab-ish. They used to be very slow; now they're adequate. But they're still not the cool way to do things.
To do this without loops, you can use reshape and permute:
a=reshape(factor_mat,[],50,4);
b=permute(a,[1,3,2]);
values=reshape(b,[],200);

Selecting cells in a table using for-loop

I need to obtain individual values from cells incrementally.
For example in a table called "T":
Can Matlab create a loop to yield the following?:
T(1,1)
T(1,2)
T(1,3)
T(1,4)
and so forth.
First of all the first parameter in MATLAB equals the row, the second the column. So following your picture you would want to extract a complete column. Then you have to loop over your first parameter and keep the 2nd constant.
So not sure if this is really what you want but:
for k = 1:size(T,1)
T(k,1)
end
would write all elements in column 1 row after row. This is because size(T,1) returns the No. of rows in your Table. So by looping over all rows you return one column. Easier with the same result would be:
T(:,1)
which would return the whole first column.
If you don't want them to be displayed but to use them as entries for another variable use:
new_T = T(:,1);
The ; makes sure that the command isn't displayed on the console. And the new_T would have all entries from column 1.
Another example:
new_T2 = T(1:500, 4);
This would result in the first 500 elements from column 4.
Hopefully this solves your question, if not please explain your question more detailed.

recording 'bursts' of samples at 300 samples per sec

I am recording voltage changes over a small circuit- this records mouse feeding. When the mouse is eating, the circuit voltage changes, I convert that into ones and zeroes, all is well.
BUT- I want to calculate the number and duration of 'bursts' of feeding- that is, instances of circuit closing that occur within 250 ms (75 samples) of one another. If the gap between closings is larger than 250ms I want to count it as a new 'burst'
I guess I am looking for help in asking matlab to compare the sample number of each 1 in the digital file with the sample number of the next 1 down- if the difference is more than 75, call the first 1 the end of one bout and the second one the start of another bout, classifying the difference as a gap, but if it is NOT, keep the sample number of the first 1 and compare it against the next and next and next until there is a 75-sample difference
I can compare each 1 to the next 1 down:
n=1; m=2;
for i = 1:length(bouts4)-1
if bouts4(i+1) - bouts4(i) >= 75 %250 msec gap at a sample rate of 300
boutend4(n) = bouts4(i);
boutstart4(m)= bouts4(i+1);
m = m+1;
n = n+1;
end
I don't really want to iterate through i for both variables though...
any ideas??
-DB
You can try the following code
time_diff = diff(bouts4);
new_feeding = time_diff > 75;
boutend4 = bouts4(new_feeding);
boutstart4 = [0; bouts4(find(new_feeding) + 1)];
That's actually not too bad. We can actually make this completely vectorized. First, let's start with two signals:
A version of your voltages untouched
A version of your voltages that is shifted in time by 1 step (i.e. it starts at time index = 2).
Now the basic algorithm is really:
Go through each element and see if the difference is above a threshold (in your case 75).
Enumerate the locations of each one in separate arrays
Now onto the code!
%// Make those signals
bout4a = bouts4(1:end-1);
bout4b = bouts4(2:end);
%// Ensure column vectors - you'll see why soon
bout4a = bout4a(:);
bout4b = bout4b(:);
% // Step #1
loc = find(bouts4b - bouts4a >= 75);
% // Step #2
boutend4 = [bouts4(loc); 0];
boutstart4 = [0; bouts4(loc + 1)];
Aside:
Thanks to tail.b.lo, you can also use diff. It basically performs that difference operation with the copying of those vectors like I did before. diff basically works the same way. However, I decided not to use it so you can see how exactly your code that you wrote translates over in a vectorized way. Only way to learn, right?
Back to it!
Let's step through this slowly. The first two lines of code make those signals I was talking about. An original one (up to length(bouts) - 1) and another one that is the same length but shifted over by one time index. Next, we use find to find those time slots where the time index was >= 75. After, we use these locations to access the bouts array. The ending array accesses the original array while the starting array accesses the same locations but moved over by one time index.
The reason why we need to make these two signals column vector is the way I am appending information to the starting vector. I am not sure whether your data comes in rows or columns, so to make this completely independent of orientation, I'm going to make sure that your data is in columns. This is because if I try to append a 0, if I do it to a row vector I have to use a space to denote that I'm going to the next column. If I do it for a column vector, I have to use a semi-colon to go to the next row. To completely avoid checking to see whether it's a row or column vector, I'm going to make sure that it's a column vector no matter what.
By looking at your code m=2. This means that when you start writing into this array, the first location is 0. As such, I've artificially placed a 0 at the beginning of this array and followed that up with the rest of the values.
Hope this helps!

matlab: understanding matlab behavior

Could somebody explain the following code snippet? I have no background in computer science or programming and just recently became aware of Matlab. I understand the preallocation part from data=ceil(rand(7,5)*10)... to ...N*(N-1)/2).
I need to understand every aspect of how matlab processes the code from kk=0 to the end. Also, the reasons why the code is codified in that manner. There's no need to explain the function of: bsxfun(#minus), just how it operates in the scheme of the code.
data=ceil(rand(7,5)*10);
N = size(data,2);
b=cell(N-1,1);
c=NaN(size(data,1),N*(N-1)/2);
kk=0;
for ii=1:N-1
b{ii} = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
c(:,kk+(1:N-ii)) = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
kk=kk+N-ii;
end
Start at zero
kk=0;
Loop with ii going from 1 up to N-1 incrementing by 1 every iteration. Type 1:10 in the command line of matlab and you'll see that it outputs 1 2 3 4 5 6 7 8 9 10. Thuis colon operator is a very important operator to understand in matlab.
for ii=1:N-1
b{ii} = ... this just stores a matrix in the next element of the cell vector b. Cell arrays can hold anything in each of their elements, this is necessary as in this case each iteration is creating a matrix with one fewer column than the previous iteration.
data(:,ii) --> just get the iith column of the matrix data (: means get all the rows)
data(:, ii + 1:end) means get a subset of the matrix data consisting of all the rows but only of columns that appear after column ii
bsxfun(#minus, data(:,ii), data(:,ii+1:end)) --> for each column in the matrix data(:, ii+1:end), subtract the single column data(:,ii)
b{ii} = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
%This does the same thing as the line above but instead of storing the resulting matrix of the loop in a separate cell of a cell array, this is appending the original array with the new matrix. Note that the new matrix will have the same number of rows each time but one fewer column, so this appends as new columns.
%c(:,kk + (1:N-ii)) = .... --> So 1:(N-ii) produces the numbers 1 up to the number of columns in the result of this iteration. In matlab, you can index an array using another array. So for example try this in the command line of matlab: a = [0 0 0 0 0]; a([1 3 5]) = 1. The result you should see is a = 1 0 1 0 1. but you can also extend a matrix like this so for example now type a(6) = 2. The result: a = 1 0 1 0 1 2. So by using c(:, 1:N-ii) we are indexing all the rows of c and also the right number of columns (in order). Adding the kk is just offsetting it so that we do not overwrite our previous results.
c(:,kk+(1:N-ii)) = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
Now we just increment kk by the number of new columns we added so that in the next iteration, c is appended at the end.
kk=kk+N-ii;
end;
I suggest that you put a breakpoint in this code and step through it line by line and look at how the variables change in matlab. To do this click on the little dashed line next to k=0; in the mfile, you will see a red dot appear there, and then run the code. The code will only execute as far as the dot, you are now in debug mode. If you hover over a variable in debug mode matlab will show its contents in a tool tip. For a really big variable check it out in the workspace. Now step through the code line by line and use my explanations above to make sure you understand how each line is changing each variable. For more complex lines like b{ii} = bsxfun(#minus,data(:,ii),data(:,ii+1:end)); you should highlight code snippets and ruin these in the command line to see what each part is doing so for example run data(:,ii) to see what that does and then try data(:,ii+1:end)) or even just ii+1:end (well in that case it wont work, replace end with size(data, 2)). Debugging is the best way to understand code that confuses you.
bsxfun(#minus,A,B)
is almost the same as
A-B
The difference is that the bsxfun version will handle inputs of different size: In each dimension (“direction,” if you find it easier to think about that way), if one of the inputs is scalar and the other one a vector, the scalar one will simply be repeated sufficiently often.
http://www.mathworks.com/help/techdoc/ref/bsxfun.html