How to loop through each value in a 3D matrix? - matlab

I have a matrix, 10x10x40, that is storing information of an image through time, where the the rows and columns indicate the spectral value at a specific point, and the third dimension is time. So in other words, a 10x10 image at 40 points in time. I would like to loop through each row, column and view that pixel history (1,1,:), (1,2,:)....(10,10,:).
Here's what I'm doing now:
val = [];
for i = 1:10;
for j = 1:10;
for k = 1:length(timevector)
val(k) = my_matrix(i,j,k);
end
end
end
Since I want to iterate through each pixel in time and then save that data, what would be the best way to store the new value/time vectors? I want to end up with 100 pixel history vectors, right now I end with one, and it's because val is written over within the loop. I know it's not advised to create variables within a loop, so what is the best alternative? Should I look into storing the output as a structure? I've been staring at this and I have over-complicated everything.

Depending on the structure you prefer, you can also use matlab's functions reshape and num2cell to get the output in the following form:
Alternative 1:
A = reshape(A,[],10);
This will return a matrix (100x40) where each row is a pixel's history.
Alternative 2:
A = num2cell( reshape(A,[],40), 2)
This will return a cell array (100x1) where each cell contains a vector (40x1) with each pixel's history.
Alternative 3:
A = squeeze( num2cell( permute(A, [3,1,2]), 1) );
This will return a cell array (10x10) where each cell contains a vector (40x1) with each pixel's history.

Depending on what you want to do with it, you don't need to store them in separate vectors. You can just get one of these pixel history vectors, like so,
pixel_history = squeeze(my_matrix(1,1,:));
squeeze will remove the singleton dimension from the slice, and make it into a 40-by-1 vector, instead of a 1-by-1-by-40 matrix.
To make the time dimension the first matrix dimension, you could also permute the matrix,
permute(my_matrix, [3 2 1]);
This will swap the 3rd and 1st dimensions, making the 1st dimension time.

Related

Element wise creation of matrix

How can we create element wise matrix from 4 matrices without using loops. For ex.we have
A=[a1 a2;a3 a4] B=[b1 b2;b3 b4] C=[c1 c2;c3 c4] D=[d1 d2;d3 d4]
We need to create a cell array such that each array location contains values such as
[a1 b1;c1 d1] %Matrix at First location
[a2 b2;c2 d2] %Matrix at Second location
and so on so that all the elements are covered.
Thanks in advance.
The short version:
newMatrix= permute(reshape([A(:),B(:),C(:),D(:)]',2,2,4),[2,1,3]);
The matrices that you need are in newMatrix(:,:,idx)
Lets break it down:
temp1 = [A(:),B(:),C(:),D(:)]';
temp1 is a new matrix that contains all of the other matrices values in every row and the values you need for the new matrices (that you wanted to create) in every column.
temp2 = reshape([A(:),B(:),C(:),D(:)]',2,2,4);
temp2 takes temp1 and permutates it. Basically it changes the matrix dimensions from a 4X4 to 2X2X4. if you look at each "layer" (along the 3rd dimension) of this 3D matrix i.e. every 2X2 it contains the information you wanted only transposed. So all thats left to do is transpose it , here ' doesnt work since its a 3D matrix so we use
newMatrix = permute(temp2,[2,1,3]);
This means that the third dimensions stais the same but you switch between dimensions 1,2.

Indexing sections to plot in a MATLAB for loop

I have a matlab indexing question. I have a vector of 34 elements that I would like to plot in a for loop. However, I do not wish to plot them all at once. It would be great if I were able to plot elements 1:6, then 7:11, then 12:20, and so on. Is it possible to do this type of plotting in a for loop? If it is, I am having trouble with the indexing. Since these elements are all in sequential order, matlab seems to want to plot them all together. Any help would be appreciated. Thanks!
Here is an example of what I am trying to do:
for i = 1: [1:6, 7:11, 12:20]
plot(x(i), y(i))
end
Hopefully, I can get three plot, one with data from elements 1:6, another from elements 7:11, and the last one from elements 12:20.
You can just use a cell to store the variable-length vectors containing the various indices:
x = linspace(0, 1, 20);
y = x;
i_cell = {1:6, 7:11, 12:20};
for i = 1:length(i_cell)
figure
indices = i_cell{i}
plot(x(indices), y(indices))
end

Subtract vector from 3d array

Say if I have a 3d array:
lat = 45:49;
lon = -116:-110;
b = rand(5,7,12);
where the first dimension represents the latitude, the second dimension represents the longitude and the third row represents the data. I aim to plot this 3d data on a map using the mapping toolbox. But, before doing this, I would like to find the difference between the data in 'b' and the following vector:
vals = [2.3,5,6.8,5.4,3.3,12,1.5,4.6,9.8,82,3.3,1];
Specifically, for each spatial data point that I have in my mapped data I owuld like to calculate the mean absolute error between that vector and the data at each point in b. If these were two normal vectors I would use:
mae = mean(abs(bv - vals))
but I'm not sure how this can be done with the 3d array. Eventually, I aim to map this mean absolute error to see how it varies spatially. Can anyone suggest how this can be done in matlab?
Use bsxfun for this (it's more efficient than repmat):
V = permute(vals, [1,3,2]) %// Make sure that the dimesions 'align' correctly. i.e. 12 elements must go in the thrid dimension to match b
mae = mean(abs(bsxfun(#minus, b, V)),3)
As MATLAB does not support broadcasting, you need to create a matrix the same size as b with the repeated values of vals. To be able to do that, first you need to change vals to a shape of 1x1x12 and then repeat it 5x7 times. You can do that with
values=repmat(permute(vals,[1 3 2]),[5 7 1]);
now you can
mae = mean(abs(bv - values))

storing and accessing with matrices of more than two dimensions

I am using ode45 to solve a system with 4 variables. For each time I execute the code:
[t y] = ode45(#func, tspan, y0);
t will be a one dimensional matrix, while y will be a 2 dimensional matrix, with 4 columns, each of which is the solution for one of the variables in question.
I want to run multiple trials of this, and keep them in a 3D matrix my_y_results and my_t_results. I want to be able to, for example, plot the final value of a certain variable for a particular initial condition, as I change the initial condition. How would I do this?
So, on each iteration of the loop below, I want to place the new values in a new matrix.
for i = 1:1:10
y0 = **some value**
[t_temp, y_temp] = ode45(#func, tspan, y0);
my_t_results = **something**
my_y_results = *something* //your code here
end
Also, how would I access the different values after setting them? For example, to get the last value of the variable y(1) for each of the 10 trials, what code would I use?
Higher dimensions can be accessed similar to the usual row and column dimensions. Let's assume t is Nx1 and y is Nx4, and that we are running M trials (note that each trial will have to have the same number of points, N, in order to store the data in a 3-dimensional array).
Your array my_t_results doesn't have to be 3-dimensional and can simply be NxM, where each column is the time vector for a different trial.
The array my_y_results would be Nx4xM and can be defined in MATLAB with:
my_y_results = zeros(N,4,M);
At the end of each i'th trial you would store the results like this:
my_y_results(:,:,i) = y;
And of course accessing the data is similar:
y_i = my_y_results(:,:,i);

Loop matrices into a structure

I'm not even sure if the title describes what I want to do, so let me try to elaborate.
Each iteration of the loop creates an X matrix. As it stands now, only the final iteration of the X matrix remains after the loop finishes.
However my desired final output is 6 X matrices. One for each of the loop iterations.
Basically, I want to save all 6 of the X matrices, not overwrite them after each iteration.
for col=2:7
logprice=log(ret(1:end,col));
logret=diff(logprice);
exret=logret-logRFree;
price_mat(:,col-1)=logprice;
ret_mat(:,col-1)=logret;
exret_mat(:,col-1)=exret;
X=[ret_mat(:,col-1) termspread creditspread inflation realrate ];
end
If the size of X is different on each iteration (and it looks that way), it may be easiest to store them in a cell array:
% before loop
X = cell(N,1);
% in loop, with a counter ii ...
X{ii} = [...];
If the X matrix were the same size on each iteration of the loop, you could preallocate a 3D array and save to each slice (e.g. X=zeros(R,C,P); ... X(:,:,ii) = [...];);
There are two most common ways. Cell arrays is one of them. The other one is 3-D matrices. It can be generalized to n-D matrices too.
Cell arrays can handle different size of matrix X on every iteration. 3-D matrices cannot. All matrices have to be of the same size. You can pre-allocate cells as well as 3-D matrices to save execution time on large loops. Also, it is a good practice to follow.
Preallocate cell array
Preallocate matrix
It can be done as follows:
count=0;
for col=2:7
count=count+1;
logprice=log(ret(1:end,col));
logret=diff(logprice);
exret=logret-logRFree;
price_mat(:,col-1)=logprice;
ret_mat(:,col-1)=logret;
exret_mat(:,col-1)=exret;
%%%%%%Execute only one of the following two statements%%%%%%%
X{count}=[ret_mat(:,col-1) termspread creditspread inflation realrate ];
X(:,:,count)=[ret_mat(:,col-1) termspread creditspread inflation realrate ];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end