How to save multi-dimensional array in matlab? - matlab

I have an array M=(1000000,12,2,2).
How do I write it to a file to work on later?
save('filename.txt','M','-ASCII')
doesn't seem to work...
Regards,

Why not save it as a mat file (binary) ?
save('filename.mat', 'M' );
afterwards you simply load it
% some code ...
M = [];
load( 'filename.mat' );
% now you have M
% code handling multi-dim M

1) just like the answer from #Shai, you can save it to be mat file
2) if you want to save it to be txt file, you can do it in this way:
clear;clc;
M=[1000000,12,2,2];
dlmwrite('a.txt',M); % save M to file--a.txt
type a.txt; % print content in a.txt
M = dlmread('a.txt'); % load content of a.txt to M and then you will have 'M=[1000000,12,2,2]'
3) you can also use fopen, fprintf, fclose to save a matrix to a file. check this post: How to save data in .txt file in MATLAB
4) for the code you have, I tested it. It works. The Matlab version I have is R2011b. please check your code again. The code I used to test is as follows:
clear;clc;
M=[1000000,12,2,2];
save('b.txt','M','-ASCII');
clear;clc;
M = load('b.txt','-ASCII');

Related

Save the data in a form of three columns in text files

This function reads the data from multiple mat files and save them in multiple txt files. But the data (each value) are saved one value in one column and so on. I want to save the data in a form of three columns (coordinates) in the text files, so each row has three values separated by space. Reshape the data before i save them in a text file doesn't work. I know that dlmwrite should be modified in away to make newline after three values but how?
mat = dir('*.mat');
for q = 1:length(mat)
load(mat(q).name);
[~, testName, ~] = fileparts(mat(q).name);
testVar = eval(testName);
pos(q,:,:) = testVar.Bodies.Positions(1,:,:);
%pos=reshape(pos,2,3,2000);
filename = sprintf('data%d.txt', q);
dlmwrite(filename , pos(q,:,:), 'delimiter','\t','newline','pc')
end
My data structure:
These data should be extracted from each mat file and stored in the corresponding text files like this:
332.68 42.76 42.663 3.0737
332.69 42.746 42.655 3.0739
332.69 42.75 42.665 3.074
A TheMathWorks-trainer once told me that there is almost never a good reason nor a need to use eval. Here's a snippet of code that should solve your writing problem using writematrix since dlmwrite is considered to be deprecated.
It further puts the file-handling/loading on a more resilient base. One can access structs dynamically with the .(FILENAME) notation. This is quite convenient if you know your fields. With who one can list variables in the workspace but also in .mat-files!
Have a look:
% path to folder
pFldr = pwd;
% get a list of all mat-files (returns an array of structs)
Lst = dir( fullfile(pFldr,'*.mat') );
% loop over files
for Fl = Lst.'
% create path to file
pFl = fullfile( Fl.folder, Fl.name );
% variable to load
[~, var2load, ~] = fileparts(Fl.name);
% get names of variables inside the file
varInfo = who('-file',pFl);
% check if it contains the desired variables
if ~all( ismember(var2load,varInfo) )
% display some kind of warning/info
disp(strcat("the file ",Fl.name," does not contain all required varibales and is therefore skipped."))
% skip / continue with loop
continue
end
% load | NO NEED TO USE eval()
Dat = load(pFl, var2load);
% DO WHATEVER YOU WANT TO DO
pos = squeeze( Dat.(var2load)(1,:,1:2000) );
% create file name for text file
pFl2save = fullfile( Fl.folder, strrep(Fl.name,'.mat','.txt') );
writematrix(pos,pFl2save,'Delimiter','\t')
end
To get your 3D-matrix data into a 2D matrix that you can write nicely to a file, use the function squeeze. It gets rid of empty dimensions (in your case, the first dimension) and squeezes the data into a lower-dimensional matrix
Why don't you use writematrix() function?
mat = dir('*.mat');
for q = 1:length(mat)
load(mat(q).name);
[~, testName, ~] = fileparts(mat(q).name);
testVar = eval(testName);
pos(q,:,:) = testVar(1,:,1:2000);
filename = sprintf('data%d.txt', q);
writematrix(pos(q,:,:),filename,'Delimiter','space');
end
More insight you can find here:
https://www.mathworks.com/help/matlab/ref/writematrix.html

Open .mtx file in MATLAB

I have a .mtx file which contains a vector which I am suppose to use for matrix vector multiplication. I tried to open the file using
fopen('filename') but this does not work, it returns a single number. I have also tried using readmtx but this gives me the following error: File size does not match inputs. Expected a file size of 232316 bytes. Instead the file size is
365 bytes. Could you please advise how I can open and work with this type of file in MATLAB.
fopen('filename') outputs only the fileID, which is typically an integer >3. This fileID can be used with e.g. fscanf(fileID) to get the content of the file.
For the .mtx format, where each line contains [row-number column-number matrix-entry], you could also do something like:
%% file
filename = 'my_matrix.mtx';
%% read Matrix
Mat = read_mtx(filename);
%% function
function Mat = read_mtx(filename)
% open file
fID = fopen(filename,'r');
M = fscanf(fID, '%f');
% reshape M vector into Nx3 matrix
M = reshape(M, [3, length(M)/3])';
% assemble final matrix
Mat = zeros(M(end,1),M(end,1));
for ii = 1:size(M,1)
Mat(M(ii,1),M(ii,2)) = M(ii,3);
end
end

How to edit multiple .mat files in a folder using MATLAB?

I am trying to edit 100 .mat files in a folder with no pattern in their names. Each file contains a matrix of size 100-by-10, and I want to convert them to 10-by-10-by-10. How do I go about this?
Provided you have a single matrix in each file, and want to overwrite the original matrix:
listing = dir('*.mat'); % finds all .mat files in your pwd
for ii = 1:numel(listing)
tmp = listing(ii).name;
s = load(tmp); % load a file
Fname = fieldnames(s); % get matrix name
out = reshape(s.(Fname{1}),[10 10 10]); % reshape
save(tmp,'out') % Save, overwriting original
end

Saving binary file in Matlab in a loop?

Consider a matrix A in Matlab of dimension mxn and suppose I want to save it as a binary file test.dat using
File_id = fopen('test.dat', 'w');
fwrite(File_id, A, 'float32');
fclose(File_id);
Now suppose that A is created within a loop for h=1:100: how can I assign to the binary files the names test1.dat, test2.dat,...,test100.dat? In other words this is what I want to do and my question is related to step 2):
%for h=1:H
%1)do something that creates A
%2) Save A using
%File_id = fopen('test'h'.dat', 'w'); %clearly wrong
%fwrite(File_id, A, 'float32');
%fclose(File_id);
%end
In the code you posted, the line:
%File_id = fopen('test'h'.dat', 'w'); %clearly wrong
should read:
File_id = fopen(strcat('test',num2str(h),'.dat'),'w');
and that should do the trick nicely.

FSEEK error while running Matlab function

I got this error while running a function in Matlab
"Error using fseek Invalid file identifier. Use fopen to generate a valid file identifier."
May I know what is the possible causes of this error? I am very new to Matlab. Please help me. Thanks a lot
I am sorry if I should not post the overall function. But I am afraid the information I gave is not enough. The overall command of the function is:
function gau_hmm_init_train(traininglist_filename,model_filename,MODEL_NO,STATE_NO, dim )
if nargin == 0
traininglist_filename='training_list.mat' ;
model_filename='models.mat';
MODEL_NO=11;
STATE_NO=4;
dim=12;
end
MIN_SELF_TRANSITION_COUNT=0;
load(traininglist_filename,'list');
% allocate mean, var vectors, transition prob. for the of models
mean_vec_i_m=zeros(dim,STATE_NO,MODEL_NO);
var_vec_i_m=zeros(dim,STATE_NO,MODEL_NO);
A_i_m=zeros(STATE_NO,MODEL_NO);
vector_sums_i_m=zeros(dim,STATE_NO,MODEL_NO);
var_vec_sums_i_m=zeros(dim,STATE_NO,MODEL_NO);
fr_no_i_m=zeros(STATE_NO,MODEL_NO);
self_tr_fr_no_i_m=zeros(STATE_NO,MODEL_NO);
utterance_no=size(list,1);
total_fr_no=0;
for k=1:utterance_no
filename=list{k,2};
m=list{k,1}; % word ID
fid=fopen(filename,'r');
fseek(fid, 12, 'bof'); % skip the 12-byte HTK header
%fopen(fid, 12, 'bof'); % skip the 12-byte HTK header
c=fread(fid,'float','b');
fclose(fid);
fr_no=length(c)/dim;
total_fr_no=total_fr_no+fr_no;
c=reshape(c,dim,fr_no);
for i=1:STATE_NO
begin_fr=round( fr_no*(i-1) /STATE_NO)+1;
end_fr=round( fr_no*i /STATE_NO);
seg_length=end_fr-begin_fr+1;
vector_sums_i_m(:,i,m) = vector_sums_i_m(:,i,m) + sum(c(:,begin_fr:end_fr),2);
var_vec_sums_i_m(:,i,m) = var_vec_sums_i_m(:,i,m) + sum( c(:,begin_fr:end_fr).*c(:,begin_fr:end_fr) , 2);
fr_no_i_m(i,m)=fr_no_i_m(i,m)+seg_length;
self_tr_fr_no_i_m(i,m)= self_tr_fr_no_i_m(i,m) + seg_length-1;
end %for s=1:STATE_NO
end % for k=1:utterance_no
for m=1:MODEL_NO
for i=1:STATE_NO
mean_vec_i_m(:,i,m) = vector_sums_i_m(:,i,m) / fr_no_i_m(i,m);
var_vec_i_m(:,i,m) = var_vec_sums_i_m(:,i,m) / fr_no_i_m(i,m);
A_i_m(i,m)=(self_tr_fr_no_i_m(i,m)+MIN_SELF_TRANSITION_COUNT)/(fr_no_i_m(i,m)+2*MIN_SELF_TRANSITION_COUNT);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% tying of cov. matrices
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
overall_var_vec=sum(sum(var_vec_sums_i_m(:,:,:),3 ),2)/sum(sum(fr_no_i_m,2 ),1);
for m=1:MODEL_NO
for i=1:STATE_NO
var_vec_i_m(:,i,m)=overall_var_vec;
end
end
%%%%%%%%%%%%%%%% end of cov. matrices tying
save(model_filename, 'mean_vec_i_m', 'var_vec_i_m', 'A_i_m');
fprintf('init. train complete \n');***
Sounds like the line fid=fopen(filename, 'r'). This filename comes from the list variable which is loaded from the file traininglist_filename, so you should check that these files exist. If you're passing it a traininglist_filename you should load this file in MATLAB and look at the contents of list; otherwise it will load the default 'training_list.mat', so you should look in there to make sure all the filenames are valid. Perhaps you're missing a file?
To continue the reply by #Wakjah, the training_list.mat file is missing from the reference path by the code you are using because it is automatically created at MATLAB default path. Therefore, just change the path at the 'Current Folder' to where you had open your current code and it should work.