Cartesian product of undefined length Matlab - matlab

There is a downloadable function called CARTPROD which gives the cartesian product of given vectors
(link to CARTPROD function)
For example
cartprod(1:3,1:3)
ans =
1 1
2 1
3 1
1 2
2 2
3 2
1 3
2 3
3 3
However, is there a way in which I can specify how many times a given vector should be read in the cartesian product. I want something like this:
%If user chooses the vector to be used 4 times
cartprod(1:3,1:3,1:3, 1:3)
%If user chooses the vector to be used 2 times
cartprod(1:3,1:3)
I have tried thinking about it, but I can't think of doing it any way besides manually. Thanks!

What you're looking for is comma separated lists. Haven't tested this, but try
myvec={1:3,1:3,1:3,1:3};
cartprod(myvec{:}); %get cartprod of all vectors in the cell-array.
or as #Sardar_Usama pointed out, you can replace myvec={1:3,1:3,1:3,1:3} with this:
n=4; %number of repeated vectors
myvec=repmat({1:3},1,n); %repeat cell-array {1:3} 4 times

The other answer points out how you can use the same cartprod function from the FEX. However, there is another function named combvec (from the Neural Network Toolbox) which does exactly the same.
n = 4; %Number of times to be repeated
myvec = repmat({1:3},1,n); %Repeating the cell array vector
result = combvec(myvec{:}).'; %Converting to comma-separated list and applying combvec

Related

Matlab Dimensions Swapped in Meshgrid

In something which made me spent several hours, I have found an inconsistency in how Matlab deals with dimensions. I somebody can explain to me OR indicate me how to report this to Matlab, please enlight me.
For size, ones,zeros,mean, std, and most every other old and common commands existing inside Matlab, the dimension arrangement is like the classical one and like the intended standard (as per the size of every dimension), the first dimension is along the column vector, the second dimension is along the row vector, and the following are the non graphical following indexes.
>x(:,:,1)=[1 2 3 4;5 6 7 8];
>x(:,:,2)=[9 10 11 12;13 14 15 16];
>m=mean(x,1)
m(:,:,1) = 3 4 5 6
m(:,:,2) = 11 12 13 14
m=mean(x,2)
m(:,:,1) =
2.5000
6.5000
m(:,:,2) =
10.5000
14.5000
m=mean(x,3)
m = 5 6 7 8
9 10 11 12
d=size(m)
d = 2 4 2
However, for graphical commands like stream3,streamline and others relying on the meshgrid output format, the dimensions 1 and 2 are swapped!: the first dimension is the row vector and the second dimension is the column vector, and the following (third) is the non graphical index.
> [x,y]=meshgrid(1:2,1:3)
x = 1 2
1 2
1 2
y = 1 1
2 2
3 3
Then, for stream3 to operate with classically arranged matrices, we should use permute(XXX,[2 1 3]) at every 3D argument:
xyz=stream3(permute(x,[2 1 3]),permute(y,[2 1 3]),permute(z,[2 1 3])...
,permute(u,[2 1 3]),permute(v,[2 1 3]),permute(w,[2 1 3])...
,xs,ys,zs);
If anybody can explain why this happens, and can indicate to me why this is not a bug, welcome.
This behavior is not a bug because it is clearly documented as the intended behavior: https://www.mathworks.com/help/matlab/ref/meshgrid.html. Specifically:
[X,Y,Z]= meshgrid(x,y,z) returns 3-D grid coordinates defined by the vectors x, y, and z. The grid represented by X, Y, and Z has size length(y)-by-length(x)-by-length(z).
Without speaking to the original authors, the exact motivation may be a bit obscure, but I suspect it has to do with the fact that the y-axis is generally associated with the rows of an image, while x is the columns.
Columns are either "j" or "x" in the documentation, rows are either "i" or "y".
Some functions deal with spatial coordinates. The documentation will refer to "x, y, z". These functions will thus take column values before row values as input arguments.
Some functions deal with array indices. The documentation will refer to "i, j" (or sometimes "i1, i2, i3, ..., in", or using specific names instead of "i" before the dimension number). These functions will thus take row values before column values as input arguments.
Yes, this can be confusing. But if you pay attention to the names of the variables in the documentation, you will quickly figure out the right order.
With meshgrid in particular, if the "x, y, ..." order of arguments is confusing, use ndgrid instead, which takes arguments in array indexing order.

Understanding Matlab multidimentionnal array

I would like to have a better comprehension of Matlab mutidimensionnal arrays and the : operator with a quick question
So I ran this example
A = zeros(2,3,4,5);
size(A)
% ans = 2 3 4 5
%% 1.
size(A(:,:,1,1))
% ans = 2 3
%% 2.
size(A(1,1,:,:))
% ans = 1 1 4 5
%% 3.
size(reshape(A(1,1,:,:), 4, 5))
% ans = 4 5
1. is the behavior I actually expected for all operations.
I don't understand why do I kept unwanted dimension in 2.
Do I need to reshape like in 3. everytime I need a subarray ?
Matlab removes singleton trailing dimensions only, so what you see is normal.
In 1, you removed a 2D subset from a 4D array, but the first two dimensions were "row" and "column".
In 2, the "row" and "column" are both singleton, and the rest of the array is in the third and fourth dimensions, so Matlab keeps it that way.
Instead of reshapeing, you can squeeze(A(1,1,:,:)) to remove dimensions that have length one (except for dimensions 1 and 2, which are sort of hard-coded into Matlab).
You can use reshape or simply squeeze in this case.
MATLAB always removes trailing singleton dimensions (past the first two):
>> size(zeros(4,4,4,1,1))
ans =
4 4 4
But it also adds them when needed (or as Ander points out in the comment, they are always implicitly there):
>> a = zeros(4,4);
>> a(2,2,1,1); % is OK
>> size(a,100)
ans =
1
On the other hand, other singleton dimensions are kept. squeeze removes them.
For your particular application it makes sense to remove singleton dimensions, but other applications would have problems if this were the default behavior. Imagine code that extracts a certain sub-volume, and changing the direction of the data depending on how many rows or columns are selected. For example:
>> a(1:x,1:y,1:z)
would return an array of size (x,y,z) as long as x and y are larger than one. Make x=1, and now it's an array of size (y,z)? Bad idea!

How to use `find` to find the indices of each page of a 3D matrix?

I have a 3D matrix that each page/slice is independent of other slices. Thus, I would like to use the find command to filter my data in each page. However, when applied, find will return the indices in a row vector that describe my data as a whole, where actually it is not. For example:
a=rand(1,10,5);
ind=find(a<0.3);
This would return ind something like:
ind=
1 2 5 9 10 11 20 24 25 ...
I expected something like:
ind(:,:,1)=
1 2 3
ind(:,:,2)=
1 5 6 10 %based on each slice, independent to other slices
I intended to do so (independently), so that I could apply the found indices to each slice of other matrix.
Can this be done without using loop? Thanks in advance!
Use ind2sub() to convert your indices to subscripts. Something like this should work for a 3d array:
[i,j,k] = ind2sub(size(a), ind)
That said, the outputs (i, j, k), will all be the same size, that is the same size as ind. In other words, it gives one set of subscripts (i,j,k) (coordinates) for each value of a<0.3.
It's not completely clear what output you want/expect from your question, but if you want separate subscripts for each page in a, you'll have to filter further (e.g. j(i==1),k(i==1) for the first page in i).

Matlab median(A(:,:,I), 3)

I have matrix A and I. When I run
Z = median(A(:,:,I), 3)
It gives me this output but I do not know how.
Lets take a look at your code
Z = median(A(:,:,I), 3)
What this says is that you want to find the median of some 3D matrix along the 3rd dimension.
Note that I=[0 1 1] means that A(:,:,I) selects the 2nd and 3rd pages of matrix A. When we call median(A(:,:,I), 3) we are asking for the median then across only pages 2 and 3 which results in an average of pages 2 and 3 because the median of two items is equal to the mean.

Average on contiguos segments of a vector

I'm sure this is a trivial question for a signals person. I need to find the function in Matlab that outputs averaging of contiguous segments of windowsize= l of a vector, e.g.
origSignal: [1 2 3 4 5 6 7 8 9];
windowSize = 3;
output = [2 5 8]; % i.e. [(1+2+3)/3 (4+5+6)/3 (7+8+9)/3]
EDIT: Neither one of the options presented in How can I (efficiently) compute a moving average of a vector? seems to work because I need that the window of size 3 slides, and doesnt include any of the previous elements... Maybe I'm missing it. Take a look at my example...
Thanks!
If the size of the original data is always a multiple of widowsize:
mean(reshape(origSignal,windowSize,[]));
Else, in one line:
mean(reshape(origSignal(1:end-mod(length(origSignal),windowSize)),windowSize,[]))
This is the same as before, but the signal is only taken to the end minus the extra values less than windowsize.