Matlab: Looping over segments of an array - matlab

I have 2 m x n matrices and would like to calculate canonical correlations for segments within a given window length. For example, if my window length is 100, I'd like to have the correlation coefficients for
canoncorr(X(1:100,:),Y(1:100,:))
canoncorr(X(101:200,:),Y(101:200,:))
canoncorr(X(201:300,:),Y(201:300,:))
...
and so on all accumulated into one matrix. I am only interested in the correlation coefficient r.
I am trying the following:
win=100;
r=[];
for i=1:win:size(X,1)-win-2
[A,B,r(i,:)] = canoncorr(X(i:i+win,:),Y(i:i+win,:));
end
However, my resulting matrix does not only save the values from row 1, 101, 201 etc. but also fills the rows between 1 and 101 and so on with zeroes.
If I try
[A,B,r(i:i+win,:)] = canoncorr(X(i:i+win,:),Y(i:i+win,:));
then subscripted assignment dimensions mismatch.
What am I doing wrong?

i goes from 1, 101, 201, ...
so, please check for 101th row and see if they are zero.
you can also spy(r) to see matrix elements.

Related

Monotonicty with the interp1 function

Sometimes when I use the interp1 function in MATLAB, it throws an error saying my vectors need to be monotonically increasing, and other times it doesn't.
For example, let's say I have 3 vectors.
A = [286, 295, 298, 301, 304, 308, 310, 324, 330, 335];
B = [31000, 30950, 30875, 30775, 30650, 30500, 30425, 29900, 29675, 29450];
C = [290, 291, 292, 293, 294, 295, 296, 297, 298, 299];
And I want to run
D = interp1(A,B,C);
This function will return successfully even though B is not monotonically increasing. Does the monotonicity only apply to the first and third vectors passing into the equation?
What the error message actually means
The error is actually a little mis-leading in this case and is caused by all values in A not being unique (not strictly monotonic). The error (which is less useful) actually propagates up from griddedInterpolant which is used by many interpolation functions and therefore has a generic error message.
Why it only applies to some inputs
With interp1 you are essentially attempting to construct an estimate of a function f(x) using x locations provided by the user as well as their corresponding values (f(x)). In your example, A contains the location of each data point (x) and B contains the values of your function at each of those points (f(x)). It is only necessary that the locations (values in A) are unique so that you don't have multiple values in B for the same value of A. If you did, interp1 doesn't know how to cope with that.
The ordering of A (the monotonically increasing part of the error) doesn't matter because interp1 will automatically sort A to be increasing (it also re-arranges B so that the values still correspond to A).*
C is simply the locations at which you want to sample the interpolant. You can request the value of the function at the same point a million times with no issue. interp1 will simply return the corresponding value for each location in C so there are no constraints on the values or ordering of C.
A = [1 3 2]; % Not monotically increasing but DOES need to be unique values
B = [1 2 1]; % Can have any value and can repeat values but each
% value corresponds with each element in A
C = [3 3 1 1 2 2]; % Can be any order and can repeat values
% ERROR FREE!
interp1(A, B, C)
% 2 2 1 1 1 1
*If you do want the ordering of your A and B points to be respected, then you'll want to parameterize your input data in a different way as suggested in this answer

How to use reshape in Matlab?

I want to reshape pixel intensity by imagesize*1(column vector).
Imvect = reshape(I,imsize,1);
But why these error comes?
Error using reshape
To RESHAPE the number of elements must not change.
Let's start with the syntax used in the documentation:
B = reshape(A,sz1,...,szN)
What reshape does is to take the matrix A, straightens it out, and gives it a new size, that's determined by the 2nd, 3rd to the Nth argument. For this to be possible, you need to have the same number of elements in the input matrix as you have in the output matrix. You can't make a 1x5 vector turn into a 2x3 vector, as one element would be missing. The number of elements in the output matrix will be proportional to the product of sz1, sz2, ..., szN. Now, if you know you want N rows, but don't know exactly how many columns you have, you might use the [] syntax, that tells MATLAB to use as many columns as necessary to make the number of elements be equal.
So reshape(A, 2, [], 3) will become a 2xNx3 matrix, where, for a matrix with 24 elements, N will be 4.
Now, in your case this is not the case. numel(I) ~= imsize. If mod(numel(I), imsize) ~= 0 then your imsize is definitely incorrect. However, if mod(numel(I), imsize) == 0, then your error might be that you want imsize number of rows, and a number of columns that makes this possible. If it's the latter, then this should work:
Imvect = reshape(I,imsize, []);
If you simply want to make you matrix I a vector of size (numel(I), 1), then you should use the colon operator :, as such:
Imvect = I(:);
An alternative, if you really want to use reshape, is to specify that you want a single column, and let MATLAB select the number of rows, as such:
Imvect = reshape(I, [], 1);

Finding the largest vector inside a matrix

I am trying to find the largest vector inside a matrix compound by vectors with MATLAB, however I am having some difficulties, so I would be very thankful if someone help me. I have this:
The matrix paths (solution of a Dijkstra function), which is a 1000x1000 matrix, whose values are vectors of 1 row and different number of columns (when the columns are bigger than 10, the values appear as "1x11 double, 1x12 double, etc"). The matrix paths have this form:
1 2 3 ....
1 1 <1x20 double> <1x16 double>
2 <1x20 double> 2 [2,870,183,492,641,863,611,3]
3 <1x16 double> [3,611,863,641,492,183,870,2] 3
4 <1x25 double> <1x12 double> <1x14 double>
.
.
.
At first I thought in just finding the largest vector in the matrix by
B = max(length(paths))
However MATLAB returns B = 1000, value which is feasible, but not likely. When trying to find out the position of the vector by using:
[row,column] = find(length(paths) == B)
MATLAB returns row = 1, column = 1, which for sure is wrong... I have thought that maybe is a problem of how MATLAB takes the data. It is like it doesn't consider the entries of the matrix as vectors, because when I enter:
length(paths(3,2))
It returns me 1, but it should return 8 as I understand, also when introducing:
paths(3,2)
It returns [1x8 double] but I expect to see the whole vector. I don't know what to do, maybe a "for" loop, I really do not know if MATLAB takes the data of the matrix as vectors or as simple double values.
The cell with the largest vector can be found using cellfun and numel to get the number of elements in each numeric matrix stored in the cells of paths:
vecLens = cellfun(#numel,paths);
[maxLen,im] = max(vecLens(:));
[rowMax,colMax] = ind2sub(size(vecLens),im)
This gets a 1000x1000 numeric matrix vecLens containing the sizes, max gets the linear index of the largest element, and ind2sub translates that to row,column indexes.
A note on length: It gives you the size of the largest dimension. The size of paths is 1000x1000, so length(paths) is 1000. My advice is, Don't ever use length. Use size, specifying the dimension you want.
If multiple vectors are the same length, you get the first one with the above approach. To get all of them (starting after the max command):
maxMask = vecLens==maxLen;
if nnz(maxMask)>1,
[rowMax,colMax] = find(maxMask);
else
[rowMax,colMax] = ind2sub(size(vecLens),im)
end
or just
[rowMax,colMax] = find(vecLens==maxLen);

Matlab: Structure with 6x6 matrices - how to get the average across the group

I have a structure named 'data' with 100 entries, each corresponding to a participant from an experiment. Each of the 100 entries contains multiple 6x6 matrices giving different values.
For instance, an example of a matrix from my first participant is:
data.p001.matrixCB
18.9737 17.0000 14.2829 12.4499 11.7898 10.0995
18.1384 16.0000 13.4907 11.7898 11.2250 10.3441
14.7986 12.5300 11.7898 11.7473 12.2066 9.3808
14.3527 13.4536 12.9615 13.3417 12.7279 11.7047
18.0278 17.8885 17.6068 17.4642 17.1464 16.6132
24.1661 24.7790 23.7697 23.3880 22.6495 23.8537
...and this is one of 100 entries in the structure with a similar setup.
I'd like to get the mean average value for each cell in the matrix across my 100 participants. So I would have a mean value for the 100 values in position matrixCB(1,1), and all other positions in the matrix. Unfortunately I can't see how this is done, and the help functions are less than helpful. Any assistance would be greatly appreciated!
You can sum all your 100 matrix into Sum and then divide it by 100 - Sum./100 and then each cell would represent the avg of all 100 cells on each index .
For example -
Sum = A + B ;
Sum./2 ;
Structures can be a pain. To avoid typing out a bunch of code, you could take the following approach:
Convert required matrices to cell array
Reshape the cell array into 3D matrix
Compute means across 3rd dimension
Code for this:
Mcell = arrayfun(#(x) data.(sprintf('p%03d',x)).matrixCB, 1:100, 'uni', 0);
M = mean( reshape(cell2mat(Mcell), 6, 6, []), 3 );

Matlab "for loop" to create a matrix

I have a fairly large vector named blender. I have extracted n elements for which blender is greater than x (irrelevant). Now my difficulty is the following:
I am trying to create a (21 x n) matrix with each element of blender plus 10 things before, and the 10 things after.
element=find(blender >= 120);
I have been trying variations of the following:
for i=element(1:end)
Matrix(i)= Matrix(blender(i-10:i+10));
end
then I want to plot one column of the matrix at the time when I hit Enter.
This second part I can figure out later, but I would appreciate some help making the Matrix
Thanks
First, you can use "logical indexing" of your array, which uses a logical expression do address your vector. With blender = [2, 302, 35, 199, 781, 312, 8], it could look like this:
>> b_hi = blender(blender>=120)
b_hi =
302 199 781 312
Second, you can concatenate arrays like in b_padded = [1, 2, b_hi, 3, 4]. If b_hi was a column vector, you'd use semicolons instead of commas.
Third, there is a function reshape that allows you to turn the resulting vector into a matrix. doc reshape will tell you details. For example, to turn b_padded into a 2-by-4 matrix,
>> b_matrix = reshape(b_padded, 4, 2)
b_matrix =
1 302 781 3
2 199 312 4
will do. This means you can do all of the job without any for-loop. Note that transposing the result of reshape(b_padded, 2, 4) will give you the other possible 2-by-4 matrix. You obtain the transpose of a matrix A by A'. You will find out which one you want.
You need to create a new matrix, and use two indices so that Matlab knows it is assigning to a column in a 2D matrix.
NewMatrix = zeros(21, length(element));
for i = 1:length(element)
k = element(i);
NewMatrix(:,i)= Matrix(blender(k-10:k+10));
end