saving multiple fields of structure as separate mat files and creating directory non-existing directories - matlab

There are two parts of my query
1) How to save different fields of structures as separate files(each file containing only named field of structure )?
2) Forcing save command to create directories in the save path when intermediate directories do not exist?
For first part:
data.a.name='a';
data.a.age=5;
data.b.name='b';
data.b.age=6;
data.c.name='c';
data.c.age=7;
fields=fieldnames(data);
for i=1:length(fields)
save(['E:\data\' fields{i} '.mat'],'-struct','data');
end
I want to save each field of struct data as a separate .mat file. So that after executing the loop, I should have 3 files inside E:\data viz. a.mat,b.mat and c.mat and a.mat contains only data of field 'a', b.mat contains only data of field 'b' and so on.
When I exeucte the above code, I get three files in my directory but each file contains identical content of all three variables a, b and c, instead of individual variables in each file.
Following command does not work:
for i=1:length(fields)
save(['E:\data\' fields{i} '.mat'],'-struct',['data.' fields{i} ]);
end
Error using save
The argument to -STRUCT must be the name of a scalar structure variable.
Is there some way to use save command to achieve my purpose without having to create temporary vaiables for saving each field?
For Second Part:
I have large number of files which need to stored in a directory structure. I want following to work.
test='abcdefgh';
save(['E:\data\' test(1:2) '\' test(3:4) '\' test(5:6) '\result.mat'])
But it showing following error
Error using save
Cannot create 'result.mat' because 'E:\data\ab\cd\ef' does not exist.
If any intermediate directory are not present, then they should be created by save command. I can get this part to work by checking if directory is present or not using exist command and then create directory using mkdir. I am wondering if there is some way to force save command to do the work using some argument I am not aware of.

Your field input argument to save is wrong. Per the documentation, the format is:
'-struct',structName,field1,...,fieldN
So the appropriate save syntax is:
data.a.name='a';
data.a.age=5;
data.b.name='b';
data.b.age=6;
data.c.name='c';
data.c.age=7;
fields = fieldnames(data);
for ii = 1:length(fields)
save(['E:\data\' fields{ii} '.mat'], '-struct', 'data', fields{ii});
end
And no, you cannot force save to generate the intermediate directories. Check for the existence of the save path first and create it if necessary.

Related

how to load multiple files from directory into an array using matlab?

i have a directory that includes some .mat files , i want to load all these files into an array .
i tried something like this :;
x1=load('C:\Users\me\OneDrive\Desktop\project\a\first_file.mat')
x2=load('C:\Users\me\OneDrive\Desktop\project\a\second_file.mat')
... and so on for all the files in the directory , and at the end i want to have an array such that:
arr(1)=x1 ...
how can i access the directory and load all of the files at the same time into an array ?
ps: i tried using path before and dir but then i got this error :
error using eval , undefind function 'workspacefun' for input
arguments of type struct
thank you in advance.
The load function loads what variables are in the .mat file with their real names into the current workspace. If you assign x as an output for load, the variables names appear as fields of a struct named x. For example, if first.mat contains v1, then, x = load('first.mat') will result in a x = struct with fields: v1.
So, in your case, assuming that you are sure that each .mat file contains a single variable, you can write the following loop to load all .mat files into a cell array arr.
fds = fileDatastore('*.mat', 'ReadFcn', #load); % assume same folder
files = fds.Files;
for i = 1:length(files)
% convert one-field struct into array, store in "arr"
arr{i} = struct2array(load(files{i}));
end
And each arr{i} will now contain a variable, say vi, in lexicographic order. If the .mat file contains more than one variable, this code will break. If the files are in another folder, you can use their actual path and extension like this fileDatastore('path', 'ReadFcn', #load, 'FileExtensions','.mat').

MATLAB: Save figure with default name

I am running a matlab-script that produces a figure. To save this figure I use:
print(h_f,'-dpng','-r600','filename.png')
What this means is that if I don't change filename for each time I run the script, the figure filename.png will be overwritten.
Is there a way to save a figure to a default name, e.g. untitled.png, and then when the script is run twice it will make a new figure untitled(1).png instead of overwriting the original one?
You could create a new filename based on the number of existing files
defaultName = 'untitled';
fileName = sprintf('%s_%d.png', defaultName, ...
length(dir([defaultName '_*.png'])));
print(h_f,'-dpng','-r600', fileName)
Add a folder path to your dir search path if the files aren't located in your current working directory.
This will create a 0-index file name list
untitled_0.png
untitled_1.png
untitled_2.png
untitled_3.png
...
You could also use tempname to generate a long random name for each iteration. Unique for most cases, see section Limitations.
print(h_f,'-dpng','-r600', [tempname(pwd) '.png'])
The input argument (pwd in the example) is needed if you do not want to save the files in your TEMPDIR
You can try something like this:
for jj=1:N
name_image=sscanf('filename','%s') ;
ext=sscanf('.png','%s') ;
%%do your stuff
filename=strcat(name_image,num2str(jj),ext);
print(h_f,'-dpng','-r600',filename)
end
If you want to execute your script multiple time (because you don't want to use a "for") just declare a variable (for example jjthat will be incremented at the end of the script:
jj=jj+1;
Be careful to don't delete this variable and, when you start again your script, you will use the next value of jj to compose the name of the new image.
This is just an idea

How to load mat files w/ different names?

I have different mat files w/ distinct names. So I am using a function whose input is the mat file. I used "varargin" to enable the function to take different files.
function bestfunc(varargin)
data = load(varargin, '-mat');
end
when I try to call the function like
bestfunc('matrix777')
Matlabe comes up w/ this error:
Error using load
Argument must contain a string.
Any ideas?
you have to get the names of the files. You can use dir() to do that.
dir('*.mat') % will return information about all .mat files in the folder
The output is a struct with more information for each file. TO get the names try
names=struct2cell(dir('*.mat'));
names=names(1,:);
now names is a cellarray with the names of all *.mat files of your folder. TO load data from each go for
for i=1:length(names)
bestfun(names{i});
end
Since you're only passing one argument, you don't need varargin, which is used when you may have a variable number of arguments to a function.
Just use a normal variable name like matname:
function bestfunc(matname)
data = load(matname, '-mat');
end
Then call it as you did before:
bestfunc('matrix777')

Store user input as wildcard

I am having some trouble with a data processing function in MATLAB. The function takes the name of the file to be processed as an input, finds the desired files, and reads in the data.
However, several of the desired files are variants, such as Data_00.dat, Data.dat, or Data_1_March.dat. Within my function, I would like to search for all files containing Data and condense them into one usable file for processing.
To solve this, I would like desiredfile to be converted into a wildcard.
Here is the statement I would like to use.
selectedfiles = dir *desiredfile*.dat % Search for file names containing desiredfile
This returns all files containing the variable name desiredfile, rather than the user input.
The only solution that I can think of is writing a separate function that manually condenses all the variants into one file before my function is run, but I am trying to keep the number of files used down and would like to avoid this.
You could concatenate strings for that. Considering desiredFile as a variable.
desiredFile = input('Files: ');
selectedfiles = dir(['*' desiredfile '*.dat']) % Search for file names containing desiredfile
Enclosing strings between square brackets [string1 string2 ... stringN]concatenates them. Matlab's dir function receives a string.
I believe you can achieve that using the dir command.
dataSets = dir('/path/to/dir/containing/Data*.dat');
dataSets = {dataSets.name};
Now simply loop over them, more information here.
To quote the matlab help:
dir lists the files and folders in the MATLABĀ® current folder. Results appear in the order returned by the operating system.
dir name lists the files and folders that match the string name. When name is a folder, dir lists the contents of the folder. Specify name using absolute or relative path names. You can use wildcards (*).

Matlab - Error using save Cannot create '_' because '_____' does not exist

I have some data in a cell array,
data2={[50,1;49,1;26,1];...
[36,2;12,2;37,2;24,2;47.3,2];}
and names in another cell array,
names2={'xxx/01-ab-07c-0fD3/0';'xxx/01-ab-07s-0fD3/6';}
I want to extract a subset of the data,
data2_subset=data2{1,:}(:,1);
then a temporary file name,
tempname2=char(names2(2));
an save the subset to a text file with
save (tempname2, 'data2_subset', '-ASCII');
But I get this error message: _
Error using save
Cannot create '6' because 'xxx/01-ab-07s-0fD3' does not exist.
To try to understand what is happening, I created a mock dataset with simpler names:
names={'12-05';'14-03'};
data={[50,1;29,1;25,1];[35,2;22,2;16,2;38,2];[40,3;32,3;10,3;44,3;43,3];};
data_subset=data{1,:}(:,1);
tempname=char(names(2));
save (tempname, 'data_subset', '-ASCII');
in which case the save command works properly.
Unfortunately I still do not understand what the problem is in the first case. Any suggestions as to what is happening, and of possible solutions?
MATLAB is interpreting the the forward slashes (/) as directory separators and 6 as the intended file name (your second example doesn't have this slash problem).
Since the relative directory tree xxx/01-ab-07s-0fD3/ doesn't exist, MATLAB can't create the file.
To solve the problem, you can either create the directories beforehand using mkdir():
>> pieces = strsplit(tempname2,'/');
>> mkdir(pieces{1:2});
>> save(tempname2, 'data2_subset', '-ASCII');
or replace the / with some other benign symbol like _:
>> tempname3= strrep(tempname2,'/','_');
>> save (tempname3, 'data2_subset', '-ASCII');
(which works for me).