Inner matrix dimensions must agree error - matlab

I have a piece of code in which i save array values to a .txt file and then in another function i have to retrieve those values from .txt to an array...the code looks somewhat like this...
fid = fopen('c:\\coeffs2.txt','wt');
fprintf(fid,'%f\n',descr2);
fclose(fid);
And in another file i retrieve it this way..
fid = fopen('c:\\coeffs2.txt');
des2= [];
des2 = fscanf(fid,'%f\n');
fclose(fid);
i get the error as inner matrix dimension must agree...please help!

Are you sure these lines are the ones generating that error? Exactly what is the line where the error occurs? Normally this would happen if you did (for example) a matrix multiplication (*) when you intended to do element-by-element multiplication (.*) with a non square matrix...
You can use save('c:\\coeffs2.mat', 'descr2'); and load('c:\\coeffs2.mat'); as an alternative (and more efficient) way to store / retrieve the matrix, and be sure you didn't change the dimensions.
Did you try to see what size(descr2) gives before the save, and after retrieving? Maybe you just need a resize...

Related

Splitting an audio file in Matlab

I'm trying to split an audio file into 30 millisecond disjoint intervals using Matlab. I have the following code at the moment:
clear all
close all
% load the audio file and get its sampling rate
[y, fs] = audioread('JFK_ES156.wav');
for m = 1 : 6000
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs) ((m+1)*(0.03)*fs)]);
end
But the problem is that I get the following error:
In an assignment A(I) = B, the number of elements in B and I
must be the same.
Error in splitting (line 12)
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs)
((m+1)*(0.03)*fs)]);
I don't see why there's a mismatch in the number of elements in B and I and how to solve this. How can I get past this error? Or is there just an easier way to split the audio file (maybe another function I don't know about or something)?
I think the easiest way to split audio is to just load it and use the vec2mat function. so you would have something like this;
[X,Fs] = audioread('JFK_ES156.wav');
%Calculate how many samples you need to capture 30ms of audio
matSize = Fs*0.3;
%Pay attention to that apostrophe. Makes sure samples are stored in columns
%rather than rows.
output = vec2mat(x,matSize)';
%You can now have your audio split up into the different columns of your matrix.
%You can call them by using the column calling command for matrices.
%Plot first 30ms of audio
plot(output(:,1));
%You can join the audio back together using this command.
output = output(:);
Hope that helps. Another good thing about this method is that it keeps all your data in one place!
Edit : One thing I thought of, you may get a problem with this depending on your vector size. But I think vec2mat actually zeroPads your vector. Not a big thing, but if you're moving back and forth between the two, then it might be a good idea to have another variable that stores the original length of your signal.
You should just use the variable y and reshape it to form your split audio. For example,
chunk_size = fs*0.03;
y_chunks = reshape(y, chunk_size, 6000);
That will give you a matrix with each column a 30 ms chunk. This code will also be faster than reading small segments from file in a loop.
As hiandbaii suggested you could also use cell array. Make sure you clear your existing variables before that. Not clearing the array t is probably the reason you got the error "Cell contents assignment to a non-cell array object."
Your original error is because you cannot assign a vector with scalar indexing. That is, 'm' is a scalar, but your audioread call is returning a vector. This is what the error says about mismatch in size of I and B. You could also fix that by making t a 2-D array and use an assignment like
[t(m,:), fs] =
It appears that each 30 ms segment is not equal to one sample. That would be the only case where your code works. i.e. 0.03*fs != 1.
You could try using cells instead.. i.e. replace t(m) with t{m}

Error using ' Transpose on ND array is not defined?

I am getting error for my below code: temp=reshape(img',irow*icol,1);
Error message:Error using '
Transpose on ND array is not defined.
What is solution for this. I think I have to use permute(A,order) command. But I dont know how to use this command in my code. Do you know any solution?
for i=1:M
str=strcat(int2str(i),'.jpg'); %concatenates two strings that form the name of the image
eval('img=imread(str);');
subplot(ceil(sqrt(M)),ceil(sqrt(M)),i)
imshow(img)
if i==3
title('Training set','fontsize',18)
end
drawnow;
[irow icol]=size(img); % get the number of rows (N1) and columns (N2)
temp=reshape(img',irow*icol,1); %creates a (N1*N2)x1 matrix
S=[S temp]; %X is a N1*N2xM matrix after finishing the sequence
%this is our S
end
I assume the code was designed for grey scale images. For matrices with more than two dimensions, you have to use permute. One solution could be:
[irow icol d]=size(img);
temp=reshape(permute(img,[2,1,3]),[irow*icol,d]);
Which results in a nx3 matrix, each column corresponding to one colour. You have to change the last line as well, but I don't know what you are expecting. Maybe take a look at cat

Is there a compact view for matrices in matlab?

I want to have a look at a large matrix in MATLAB such that all columns are printed in one single line rather than spread out over several lines.
Is such thing possible? That would be great to know.
Try disp(matrixName(:)). The matrixName(:) command turns your matrix into a long vector in column-major order, so it basically just shows you the first column, followed by the second, the third, etc.
If that does not do the trick, you could look into the doprint command.
EDIT: You could also save the matrix to a text file and view the file. You do this like so:
fileID = fopen('C:/path/to/file/myMatrix.txt');
fprintf(fileID, formatString, myMat);
fclose(fileID);
fopen documentation
fprintf documentation
Additional information can be found here
The formatString variable in the above tells fprintf how the data should be displayed. If you have a really big matrix with tons of columns, where all of the values are floats, the easiest way to create this string is to use something like:
formatString = strcat(repmat('%f ', 1, size(myMat, 2)), '\n');
This will create a long string specifying that each element in your matrix is a float, and where it goes, and then cap it off with a line feed so that the next row of your matrix starts on the next line.
Suppress your original matrix with a semicolon and then use the "disp" command to show your matrix however you want.
for i = 1 : length(matrix(1,:))
disp(matrix(:,i))
end
Some "obvious" answers:
You can choose a smaller font - then more values will fit in a line
You can play with the format command to have less digits displayed
(my favourite) Use the variable viewer - via "open selection" or Ctrl-D when the name of a variable is highlighted. This will show your matrix in an excel-like table.

How to read text fields into MATLAB and create a single matrix

I have a huge CSV file that has a mix of numerical and text datatypes. I want to read this into a single matrix in Matlab. I'll use a simpler example here to illustrate my problem. Let's say I have this CSV file:
1,foo
2,bar
I am trying to read this into MatLab using:
A=fopen('filename.csv');
B=textscan(A,'%d %d', 'delimiter',',');
C=cell2mat(B);
The first two lines work fine, but the problem is that texscan doesn't create a 2x2 matrix; instead it creates a 1x2 matrix with each value being an array. So I try to use the last line to combine the arrays into one big matrix, but it generates an error because the arrays have different datatypes.
Is there a way to get around this problem? Or a better way to combine the arrays?
I am note sure if combining them is a good idea. It is likely that you would be better off with them separate.
I changed your code, so that it works better:
clear
clc
A=fopen('filename.csv');
B=textscan(A,'%d %s', 'delimiter',',')
fclose(A)
Looking at the results
K>> B{1}
ans =
1
2
K>> B{2}
ans =
'foo'
'bar'
Really, I think this is the format that is most useful. If anything, most people would want to break this cell array into smaller chunks
num = B{1}
txt = B{2}
Why are your trying to combine them? They are already together in a cell array, and that is the most combined you are going to get.
There is a natural solution to this, but it requires the Statistics toolbox (version 6.0 or higher). Mixed data types can be read into a dataset array. See the Mathworks help page here.
I believe you can't use textscan for this purpose. I'd use fscanf which always gives you a matrix as specified. If you don't know the layout of the data it gets kind of tricky however.
fscanf works as follows:
fscanf(fid, format, size)
where fid is the fid generated by the fopen
format is the file format & how you are reading the data (['%d' ',' '%s'] would work for your example file)
size is the matrix dimensions ([2 2] would work on your example file).

How can I save a very large MATLAB sparse matrix to a text file?

I have a 30000x14000 sparse matrix in MATLAB (version 7), which I need to use in another program. Calling save won't write this as ASCII (not supported). Calling full() on this monster results in an Out of Memory error.
How do I export it?
You can use find to get index & value vectors:
[i,j,val] = find(data)
data_dump = [i,j,val]
You can recreate data from data_dump with spconvert, which is meant to "Import from sparse matrix external format" (so I guess it's a good export format):
data = spconvert( data_dump )
You can save to ascii with:
save -ascii data.txt data_dump
But this dumps indices as double, you can write it out more nicely with fopen/fprintf/fclose:
fid = fopen('data.txt','w')
fprintf( fid,'%d %d %f\n', transpose(data_dump) )
fclose(fid)
Hope this helps.
Save the sparse matrix as a .mat file. Then, in the other program, use a suitable library to read the .mat file.
For instance, if the other program is written in Python, you can use the scipy.io.mio.loadmat function, which supports sparse arrays and gives you a sparse numpy matrix.
I saved it as text using Java within MATLAB.
MATLAB Code:
pw=java.io.PrintWriter(java.io.FileWriter('c:\\retail.txt'));
line=num2str(0:size(data,2)-1);
pw.println(line);
for index=1:length(data)
disp(index);
line=num2str(full(data(index,:)));
pw.println(line);
end
pw.flush();
pw.close();
Here data is an extremely large sparse matrix.
Did you try partitioning it ?
I mean try calling full() on the 1000 first rows (or 5000) and then repeat the process if it works.
Use the find function to get the indices of non-zero elements...
idcs = find(data);
vals = data(idcs);
...save the index vector and value vector in whatever format you want...
If you want, you can use ind2sub to convert the linear indices to row, column subscripts.
If you need to recreate a sparse matrix in matlab from subscripts + values, use spconvert.
dlmwrite - Write matrix to ASCII-delimited file
Syntax
dlmwrite(filename, M)
dlmwrite(filename, M, 'D')
dlmwrite(filename, M, 'D', R, C)
dlmwrite(filename, M, 'attrib1', value1, 'attrib2', value2, ...)
dlmwrite(filename, M, '-append')
dlmwrite(filename, M, '-append', attribute-value list)
If this is pretty much a one time deal, then I would just iterate through the matrix and write the matrix to an ASCII file by brute force, or else use #Veynom's suggestion and call full() on a subset of rows. It may take a while, but it will probably be done faster than it might take to learn how to read in a .mat file outside of the MATLAB environment.
If this is something you need to do on a recurring basis, then I would take #Vebjorn's advice and use a library to read the .mat file.
Use this script:
msm_to_mm.m, writes an MATLAB sparse matrix to an MatrixMarket file.
And This thread may also be useful.