Submatrix based on size vector - matlab

It seems like this problem should be common, but I haven't found a good duplicate...
I'm implementing a level 2 S-function with a variable-sized multidimensional output. The state has to be in fixed-size Dwork vectors, so I zero-pad the input matrix to the maximum size allowed for the input and then reshape it to a vector.
When I reshape it back to a matrix for output, I need to trim it back down to the correct size.
The function needs to be general enough to support an arbitrary number of dimensions. The size of the output is stored in a size array.
For example, I may have a 500x500 matrix N, and a size array S = [40 25]. I need a MATLAB expression that would give me N(1:S(1), 1:S(2)), but it needs to work for any number of dimensions so I can't simply hardcode it like that.

Here is a solution in m-code:
%your input
M=rand(10,10,10);
S=[2,3,4]
%generate indices:
Index=arrayfun(#(x)(1:x),S,'uni',0)
%use comma separated list to index:
smallM=M(Index{:})

Related

pre-allocation of array size in Matlab

What is the efficient way of dynamically preallocating the size of an array variable which appears to change its size on every loop iteration in Matlab? It is possible to initialize it using the zeros() matrix but it sometimes is very tricky (for example: in determining the upper and lower limits).
This is the solution that I use for 2D arrays of dynamic size. Say the maximal limit of my array is 2000x2000, then I just preallocate zeros of the 1-D vector analogue (a 2000^2x1 vector) and after the code ends get rid of the zeros (or just ignore them in case the data is going to a histogram), and reshape once if needed after the code ends...
For example:
for n=1:100;
v=zeros(2000^2,1);
v(1:numel(data))=data(:);
% rest of the code here
end

Putting vectors of different size in a matrix

I am trying to add a number of vectors in a Matrix where each row represents a vector, but it gives me "Subscripted assignment dimension mismatch." error. The main problem is that each vector has a different size. I tried to add zeros at the end of the short vectors but I couldn't do it. Any Help.
Example:
%signal is a vector of data.
[x(1,:),y(1,:)] = findpeaks(signal1);
[x(2,:),y(2,:)] = findpeaks(signal2); %error as the peaks count in signal 2 is not the same as in signal 1.
OK, given two vectors of unequal length,
A=rand(1,10)
B=rand(1,5)
the proper way to deal with this is to use a cell array
D={A;B}
And then you can get whatever elements you want like this, for example:
D{1}(1:3) %// A(1:3)
If you don't want to use cells, you can add rows using this little function that adds row vector M to matrix F
addRow=#(F,M) [F NaN(size(F,1),size(M,2)-size(F,2));M NaN(1,size(F,2)-size(M,2))]
you would use it like this:
F=A
F=addRow(F,B)

When the input matrix is supposed to be: "The rows of X correspond to observations, and columns correspond to variables."?

I'm not getting the correct results from the Matlab function so maybe my data arrangement is wrong. I looked at the help file of the function I am using and the input, "X" that it takes must be in the form.
The rows of X correspond to observations, and columns correspond to
variables.
I am sorry if this is very basic but how exactly should my input matrix be arranged?
I have 5 writers, each have a feature vector of length 18 (for example for the sake of simplicity).
So I assumed that by observations it is meant the different features of the same writer and variables mean the writers, so I arranged the input matrix as [18 x 5] where each column is a writer.
This example is simple. What of in the case of SIFT features? where each writer will produce a feature matrix [128 x num. of keypoints] which usually becomes [128 x 70] for one image. So if I want to concatenate all of them into the input matrix my input matrix will become [128 x 350].
Will this just be the input matrix X? Then in the case of SIFT each variable in 70 columns wide.
Thank you in advance
If all of your writers data have different size, I suggest you to use cell() which is cell array. http://www.mathworks.com/help/matlab/cell-arrays.html - here is your reference. So for example if you need to calculate covariance you can do it for each matrix separately. Then your covariance matrices will be same size(128*128) so you can put them together and have your 3D matrix data.
Hope it will help you.

Sparse Matrix Assignment becomes very slow in Matlab

I am filling a sparse matrix P (230k,290k) with values coming from a text file which I read line by line, here is the (simplified) code
while ...
C = textscan(text_line,'%d','delimiter',',','EmptyValue', 0);
line_number = line_number+1;
P(line_number,:)=C{1};
end
the problem I have is that while at the beginning the
P(line_number,:)=C{1};
statement is fast, after a few thousands lines become exterely slow, I guess because Matlab need to find the memory space to allocate every time. Is there a way to pre-allocate memory with sparse matrixes? I don't think so but maybe I am missing something. Any other advise which can speed up the operation (e.g. having a lot of free RAM can make the difference?)
There's a sixth input argument to sparse that tells the number of nonzero elements in the matrix. That's used by Matlab to preallocate:
S = sparse(i,j,s,m,n,nzmax) uses vectors i, j, and s to generate an
m-by-n sparse matrix such that S(i(k),j(k)) = s(k), with space
allocated for nzmax nonzeros.
So you could initiallize with
P = sparse([],[],[],230e3,290e3,nzmax);
You can make a guess about the number of nonzeros (perhaps checking file size?) and use that as nzmax. If it turns you need more nonzero elements in the end, Matlab will preallocate on the fly (slowly).
By far the fastest way to generate a sparse matrix wihtin matlab is to load all the values in at once, then generate the sparse matrix in one call to sparse. You have to load the data and arrange it into vectors defining the row and column indices and values for each filled cell. You can then call sparse using the S = sparse(i,j,s,m,n) syntax.

Invalid index error in Scilab when trying to access array element

I'm not sure why I can't do this in Scilab.
-->foo=zeros(500);
-->foo(300)
!--error 21
Invalid index.
Why do I get the 'Invalid index' error? I thought I had initialized foo as an array with 500 elements, each of which was set to 0?
In Scilab, you have to give both the number of rows as well as the number of columns. So, if you want to create a 500x500 matrix, you need to say zeros(500, 500). If you want a 500x1 vector, you need to say zeros(500, 1).
If you want to create a zeros matrix that has precisely as many rows and columns as another matrix (say A), you need to say zeros(A). This is where the confusion stems from.
In Scilab, zeros(500) would take 500 as a 1x1 matrix and generate a zeros matrix of size 1x1, that is [0]. In MATLAB, zeros(500) would take 500 to be the size of the matrix required, assuming a square matrix.
If zeros in Scilab behaves just like zeros in Matlab the call zeros(500) creates a 500x500 array of 0s. That said, foo(300) would be a valid Matlab expression as Matlab understands what it calls 'linear indexing' on arrays of rank greater than 1.
If zeros in Scilab does bot behave just like zeros in Matlab I can't help.
printf("%d\n",Md(y,u))
!--error 21
Índice inválido.
at line 69 of exec file called by :
como soluciono esto?