In matlab I have a function which should take in a file name.
This file has a struct in it, later this file should be executed with in the function so that the struct will be loaded to the work space.
For example:
My function is hello(a), where 'a' is a file name, this file has a struct.
On executing the file in command window this struct will be loaded in the workspace.
Same way I want the struct to be loaded in to the workspace when I call the function.
I tried eval(a), but this is not loading the struct in the file to the workspace.
From the file name how will I obtain the struct name, even though I know that there is a struct in the file, but this is going to vary dynamically.
So how should I return the structure in function?
I am not sure whether you want the struct (or structs) inside the file to be copied automatically to the workspace, or if you want to assign the data yourself.
The following solution copies all variables from file a to the "base"-workspace automatically using the assignin() function. The solution also assumes that you give it a file for a .mat file.
function hello(a)
all_structs = load('-mat', a);
var_names = fieldnames(all_structs);
for k = 1:length(var_names)
assignin('base', var_names{k}, all_structs.(var_names{k}));
end
end
Try eval:
function mystruct = readstruct(filename)
% ... read in text from file here ...
eval(text)
For example, assume your file contains text 'mystruct.myval = 1', then after reading the file contents into string text, eval(text) returns
mystruct =
myval: 1
To load the structure into the workspace, the function should return the structure.
If the file contains arbitrary data (presumably but not necessarily in ascii format) then you can simply assign it to a structure after the file is read:
function mystruct = readstruct(filename)
% ... read in text from file here ...
% ... perform conversion of data type ...
mystruct.value = values
Related
I have a folder with files named like this: "speaker1_001.wav". It goes From 001 to speaker1_020. How can I do a for loop to "audioread" all the files and storing the value in variables with different names?
This is what I got, but I only obtain one variable instead of 20.
mypath = fullfile('TrainVoices', 'speaker1');
for idx = 1:20
filename = fullfile(mypath, sprintf('speaker1_%d.wav', idx));
nameSpeaker = sprintf('speaker1_%d', idx);
[nameSpeaker, fs] = audioread(filename);
end
In your code, you try to dinamically create the name of the output variable nameSpeaker with the instruction nameSpeaker = sprintf('speaker1_%d', idx); in order to use it as output variable in the call to audioread.
This is not correct since you actually assign the string created with sprintf to the variable nameSpeaker rather then "change" the name of it.
Also, you have to manage the "zeros" included in the filename.
A part from this error (which can be fixed), in general it is not a good practice to use dinamically created variable.
A possible solution could be to store the wav data in a struct which allows to dinamically create the name of the field.
Moreover, since according to the code you've posted you know in advance the path and the root name of the inout files, you can create the complete filename by simply appending the different strings rather than using fullfile
In the following you can find a possible implementaton of the proposed solution.
The output will be a struct named nameSpeaker with a set of fields named speaker1_1, speaker1_2, speaker1_3 ... etc after the name of the input file in which, for semplicity the "zeros"have been removed.
Each of this fields is a struct with the field: data and fs containing the data of the wav file.
For example:
the data of speaker1_001.wav arfe stored in the struct
nameSpeaker.speaker1_1.data
nameSpeaker.speaker1_1.fa
the data of speaker1_002.wav arfe stored in the struct
nameSpeaker.speaker1_2.data
nameSpeaker.speaker1_2.fs
and so on.
% Defina the path
mypath='TrainVoices\speaker1'
% Define the file root name
f_root_name='speaker1_'
% Define the extension of the input file\
ext='.wav'
% Loop over the input filess
for idx = 1:20
%& add the proper number of "0" to tjhe filename
if(idx <= 9)
f_name=[f_root_name '00' num2str(idx)]
else
f_name=[f_root_name '0' num2str(idx)]
end
% Build the filename
filename=fullfile(mypath,[f_name ext])
% Read the wav file
[data,fs] = audioread(filename);
% Store the wav file data in a struct
nameSpeaker.([f_root_name num2str(idx)]).data=data;
nameSpeaker.([f_root_name num2str(idx)]).fs=fs;
end
You can make access to the data by simply specify the "idx" of the file.
For example, to make access to the data of speaker1_001.wav, you can simply define the file "idx" and then build the names of the fields accordingly:
file_idx=3
data=nameSpeaker.([f_root_name num2str(file_idx)]).data
fs=nameSpeaker.([f_root_name num2str(file_idx)]).fs
I'm new to MATLAB, and I can't manage to make my function work in order to save my data into a .mat file.
The input:
A structure, with 5 fields:
data: 3D matrix of 19x1000x143
labels: 1x143 matrix with 1 or -1 in it
subject_number: an integer
sampling_rate: an integer, 500 Hz
channel_names: 1x19 matrix with text in it
name: a string for the name of the file
clean: a matrix 1x143 with 1 or 0 in it.
The idea is to save only the clean data, marked as 1 in the clean matrix.
If clean(i) is equal to 1:
save data(:,:,i) and labels(:,i)
This is the code I've tried to implement in the saving.m file:
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
for j=1:nb_epoch
if clean(j) == 1
% Keep the epoch and label
data = cat(3, data, EEG_struct.data(:,:,j));
labels = cat(2, labels, EEG_struct.labels(:,j));
end
end
save(name, data, labels, subject_number, fs, chan_names)
As you can see, I would like to save the data as a structure with the same shape as the EEG_struct input.
Moreover, I would like to use a parfor instead of a for, but it raised me an error I didn't quite get:
An UndefinedFunction error was thrown on the workers for 'data'. This might be because the file containing 'data' is not accessible on the workers. Use addAttachedFiles(pool, files) to specify the required files to be attached. See the documentation for 'parallel.Pool/addAttachedFiles' for more details. Caused by: Undefined function or variable 'data'.
Thanks for the help !
You can use your clean variable as a logical index and parse out your data and labels at once. So there is no need for a loop.
Also the save command needs the "names" of the vars to save not the variables themselves. So I just put ' ' around each one.
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
%No need for a loop at all
data = EEG_struct.data(:,:,logical(clean));
labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
save(name, 'data', 'labels', 'subject_number', 'fs', 'chan_names');
EDIT:
Per you comment if you want to just leave everything in the structure. I gave you 2 options for how to save it.
function saving(EEG_struct, clean, name)
%Crop out ~clead data
EEG_struct.data = EEG_struct.data(:,:,logical(clean));
EEG_struct.labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
% Option 1
save(name, 'EEG_struct');
% Option2
save(name, '-struct', 'EEG_struct');
Option 1 will directly save the struct to the MAT file. So if you were to load the data back like this:
test = load(name);
test =
EEG_struct: [1x1 struct]
You would get your structure placed inside another structure ... which might not be ideal or require an extra line to de-nest it. On the other hand just loading the MAT file with no outputs load(name) would put EEG_struct into your current workspace. But if in a function then it sort of springs into existence without every being declared which makes code a bit harder to follow.
Option 2 uses the '-struct' option which breaks out each field automatically into separate vars in the MAT file. So loading like this:
EEG_struct = load(name);
Will put all the fields back together again. To me at least this looks cleaner when done within a function but is probably just my preference
So comment out which ever you prefer. Also, not I did not include clean in the save. You could either append it to the MAT or add it to your structure.
To get a structure the same as EEG_struct but with only the data/labels corresponding with the clean variable, you can simply make a copy of the existing structure and remove the rows where clean=0
function saving(EEG_struct, clean, name)
newstruct = EEG_struct;
newstruct.data(:,:,logical(~clean)) = '';
newstruct.labels(logical(~clean)) = '';
save(name,'newstruct');
When loading data from a .Mat file directly into a variable, it stores an struct instead of the variable itself.
Example:
myData.mat contains var1, var2, var3
if I do:
load myData.mat
it will create the variables var1, var2 and var3 in my workspace. OK.
If I assign what load returns to a variable, it stores an struct. This is normal since I'm loading several variables.
foo = load('myData.mat')
foo =
struct with fields:
var1
var2
var3
However suppose that I'm only interested in var1 and I want to directly store into a variable foo.
Load has an option of loading only specific variables from a .mat file, however it still stores an struct
foo = load('myData.mat', 'var1')
foo =
struct with fields:
var1
I want var1 to be directly assigned to foo.
Of course I can do:
foo = load('myData.mat', 'var1')
foo = foo.var1;
But it should be a way of doing this automatically in one line right?
If the MAT-file contains one variable, use
x = importdata(mat_file_name)
load does not behave this way otherwise load would behave inconsistently depending upon the number of variables that you have requested which would lead to an extremely confusing behavior.
To illustrate this, imagine that you wrote a general program that wanted to load all variables from a .mat file, make some modification to them, and then save them again. You want this program to work with any file so some files may have one variable and some may have multiple variables stored in them.
If load used the behavior you've specified, then you'd have to add in all sorts of logic to check how many variables were stored in a file before loading and modifying it.
Here is what this program would look like with the current behavior of load
function modifymyfile(filename)
data = load(filename);
fields = fieldnames(data);
for k = 1:numel(fields)
data.(fields{k}) = modify(data.(fields{k}));
end
save(filename, '-struct', 'data')
end
If the behavior was the way that you think you want
function modifymyfile(filename)
% Use a matfile to determine the number of variables
vars = whos(matfile(filename));
% If there is only one variable
if numel(vars) == 1
% Assign that variable (have to use eval)
tmp = load(filename, vars(1).name);
tmp = modify(tmp);
% Now to save it again, you have to use eval to reassign
eval([vars(1).name, '= tmp;']);
% Now resave
save(filename, vars(1).name);
else
data = load(filename);
fields = fieldnames(data);
for k = 1:numel(fields)
data.(fields{k}) = modify(data.(fields{k}));
end
save(filename, '-struct', 'data');
end
end
I'll leave it to the reader to decide which of these is more legible and robust.
The best way to do what you're trying to do is exactly what you've shown in your question. Simply reassign the value after loading
data = load('myfile.mat', 'var1');
data = data.var1;
Update
Even if you only wanted the variable to not be assigned to a struct when a variable was explicitly specified, you'd still end up with inconsistent behavior which would make it difficult if my program accepted a list of variables to change as a cell array
variables = {'var1', 'var2'}
data = load(filename, variables{:}); % Would yield a struct
variables = {'var1'};
data = load(filename, variables{:}); % Would not yield a struct
#Suever is right, but in case you wish for a one-line workaround this will do it:
foo = getfield(load('myData.mat'), 'var1');
It looks ugly but does what you want:
foo = subsref(matfile('myData.mat'),struct('type','.','subs','var1'))
Use matfile allows partial loading of variables into memory i.e. it only loads what is necessary. The function subsref does the job of the indexing operator "." in this case.
I wnat to create a function:
function[check]=createFile(filename, matrix)
Where I create a blank text file with the name 'filename'.
Where later in the function inputs from 'matrix' can be put in and stored.
2 question:
1)How do I create just a blank .txt file?
2)I've had some problem with this in somewhat simular functions, but is there an easy way to get rid of the need to write apostrophes in the arguments when calling the function?(i.e: createFile(name,matrix) instead of createFile('name',matrix)
to create the text file just use:
fid = fopen('filename.txt','w')
and there is no way to avoid the apostrophies 'filename.txt' - as matlab would try to call a function filename.txt which it wouldn't find.
for your function you can use
function [check] = createFile(filename, matrix)
% filename contains string!
fid = fopen(filename,'w')`
if exist('fid')
check = true;
else
check = false;
end
... write your matrix to file.
end
2) but is there an easy way to get rid of the need to write apostrophes in the arguments when calling the function?(i.e: createFile(name,matrix) instead of createFile('name',matrix)
Yes: you can type
createFile name matrix
after you have included this in createFile.m:
function createFile(name,matrix)
matrix=evalin('caller',matrix);
I want to save variables in a loop with different image names, like
for i = 1:length(imagefile)
name = imagefile{i};
var = rand(100); % Just for example
save name var
end
It will save var as name, but how do I save it with a value of name, for example Canon101?
Sayyad, you don't have to use eval. You can simply use the function form of save, i.e., save(filename,variables). This will use the value of filename. Remember that the variables need to be entered as strings. So, in your example, it would be
save(name,'var')