A way to dynamically save files in Matlab? [duplicate] - matlab

This question already has answers here:
Dynamically Assign Variables in Matlab
(2 answers)
Closed 8 years ago.
I want to be able to save variables to disk sometimes. And I want to save it in a subfolder called '_WorkData'.
The bellow code works fine as a stand alone code
OutputName = 'my favorite file';
save(['_WorkData/' OutputName '.mat'], 'foobar');
However as a function it cant find the variable Variable 'foobar' not found.
function noDataReturn = saveFileDisk(name,variable)
save(['_WorkData/' name '.mat'], variable);
noDataReturn = 'file saved';
end
I can see why this happens but I'm not familair enough with matlab code to understand how to correct it.
Any help would be appreciated!

This is a three-fold problem.
You have to pass the variable to your function (and not the string)
However, the save call actually needs the string
The function has to have a variable with the original name to save it as intended.
Here's how it works:
function noDataReturn = saveFileDisk(name,variable)
savename = sprintf('%s',inputname(2));
S.(savename) = variable;
save(['_WorkData/' name '.mat'], '-struct', 'S', savename);
noDataReturn = 'file saved';
end
You obtain the original variable name using the inputname function (in this case, the second input is what you are after).
Next, you need to create a struct with a field name corresponding to your original variable name.
With this, you can utilize the save function's option to save fields from a struct individually.
Now, when you call
saveFileDisk('test_name',foobar)
the result will be a variable foobar in your test_name.mat-file.

Related

Matlab - using a function mulitple times in the same workspace, to add values and fields to a structure

I have a structure such as:
specimen.trial1 = 1
I now want to add another trial to the specimen, so that
specimen.trial1 = 1
specimen.trial2 = 2
I can do this without a problem within the workspace and command window. But, if I'm using a function to calculate the numbers for each trial (with dynamic fields), the new field and value erases the previous one. Eg:
function [specimen] = dummy(trial,value)
specimen.(trial) = value
end
run the function:
[specimen] = dummy('trial1',1)
then run the function again with different inputs, but keeping the structure intact in the workspace
[specimen] = dummy('trial2',2)
Instead of getting a structure with 2 fields, I get just one with Trial2 being the only field. Does that make any sense? What would like is to use the outputs of a function to progressively add to a structure.
Thank you,
Chris
Yes it makes sense, because you're creating a new struct specimen within your function.
Solution: pass the the previous specimen to the function as well.
function [specimen] = dummy(specimen,trial,value)
specimen.(trial) = value
end
and call:
[specimen] = dummy(specimen,'trial1',1)
or alternativly leave out the assignment at all and use the following
function [output] = dummy(value)
output = value
end
and call:
[specimen.trail1] = dummy(1)
which really depends on what you actually want to do. Put passing a name to a function which uses this name to define a struct is a little pointless unless you "use" that name otherwise. Also if you want to have input-dependent dynamic names you'd also go with the first alternative

Auto generate a name when saving file in Matlab?

I am working on a GUI and I have a file named 'work.mid'. The user can make some modifications to it and when they click the save button I want it to be saved as 'work1.mid' to 'c:\saved_datas\'. When they click that button second time, it should save it as 'work2.mid', on the third time 'work3.mid' and so on. Here's the code I have so far:
nmat = readmidi_java('work.mid');
Name = fullfile('c:\saved_datas\', '?????');
writemidi_java(nmat, Name);
Figuring out what should go at ????? is where I'm stuck.
The following code would work if you have no prior work*.mid or if you have any number of sequential work*.mid files inside c:\saved_datas\. Now, if the files are not in sequence, this code could be tweaked for that, just let me know if you would like to handle that case too.
Code listed here -
%// Parameters
org_filename = 'work.mid';
main_dir = 'c:\saved_datas\'; %//'
%// Your code
nmat = readmidi_java(org_filename);
%// Added code
[~,filename_noext,ext] = fileparts(org_filename)
filenames = ls(strcat(main_dir,filename_noext,'*',ext))
new_filename = strcat(filename_noext,num2str(size(filenames,1)+1),ext)
Name = fullfile(main_dir,new_filename)
%// Your code
writemidi_java(nmat, Name);
For achieving uniqueness of filenames, some also use timestamps. This could be implemented like this -
org_filename = 'work.mid'; %//'
main_dir = 'c:\saved_datas\'; %//'
[~,filename_noext,ext] = fileparts(org_filename)
new_filename = strcat('filename_noext','-',datestr(clock,'yyyy-mm-dd-hh-MM-SS'),ext)
Name = fullfile(main_dir,new_filename);
This could be done a couple of ways depending on how you have structured your GUI. You need to keep track of how many times the button has been pressed. In the callback for the button you could use a persistent variable ('count') and increment it by one at the start of the function. Then construct the filename with filename = ['work' num2str(count) '.mid']. Alternatively you could increment a class member variable if you have implemented your GUI using OOP.
To save the file use the 'save()' function with the previously constructed file name and a reference to the variable.
Check out the documentation for persistent variables, save, fullfile and uiputfile for extra info.

get/edit code of function with Ipython

when you enter function??, besides the info you get the source code of the function if there is available.
Is there a way of?:
1) get the code as str object
2) edit in place similar to %load
Assuming that you have the module and function names as "module" and "function" string variables, then
from inspect import getmembers, isfunction, getsource
internal_module = __import__(module)
internal_functions = dict(getmembers(internal_module, isfunction))
source_code = getsource(internal_functions[function])
will give you a dictionary (internal_functions) containing all functions in the module and a string (source_code) containing the source of that specific function.
You would then have to manipulate the string in order to edit the function, I think.

Calling the function doesn't work

I have a cell array of stucts, each containing the personalia of a person. I put it into this function to get them listed in a text file of a chosen name.
function store( filename, persons )
fid = fopen(filename,'w');
for i=1:length(persons)
fprintf(fid, '%s',serialize_person(persons{i}));
end
Now this function works fine: I enter a <1x3 cell> and get out a text file with three listed persons. However, I want to call this function from another:
function process_store()
list=input('Write in the list of persons you want listed: ');
fprintf('\n')
newfile=input('Give the text file a name: ','s');
store(filename,list)
end
Here I enter the name of the <1x3 cell> as before, but I get a error message "Error using input,Undefined function or variable 'persons'."
Why is this? Am I not using the exact same data as Im using in 'store'?
The problem is that the variable persons isn't accessible inside the function process_store. In Matlab (and most other programming languages) functions can't access variables defined in their calling functions. To understand this better, I recommend having a read of the Wikipedia article on levels of scope.
You essentially have two options here:
Make persons a global variable, both in your workspace and in the function process_store, by using the declaration global persons. I wouldn't recommend this.
Use the function evalin to allow process_store to access variables in its parent workspace.
I'd go with option 2 if I were you. It's a little tricky, so let me explain how it works. Let's create a variable persons in the global workspace.
>> persons = {'John', 'Jack', 'Jill'};
Now say we have the following function
function example()
x = input('Give me a variable name: ');
disp(x)
end
What happens if we try to use it?
>> example()
Give me a variable name: persons
Error using input
Undefined function of variable 'persons'
Error in example (line 2)
x = input('Give me a variable name: ');
Oh dear. That's because the function example doesn't have access to the global workspace, which is where persons is defined. But instead, we can store the name of the variable we want to access, and then check out its value in the global workspace by using evalin, like this
function example()
s = input('Give me a variable name: ', 's');
x = evalin('caller', s);
disp(x)
end
Now if we use it:
>> example()
Give me a variable name: persons
'John' 'Jack' 'Jill'
It works as we expected! Great!
Massive disclaimer
There is almost never a good reason to use functions like evalin (or eval, or assignin or any other function that messes around executing strings as code). There's almost certainly a better way of doing what you want to do. But without knowing what it is you're trying to do, it's hard to give you better advice.
At the prompt
Write in the list of persons you want listed:
if you typed
persons
then you would get exactly that error message if the variable persons was not defined.

Matlab: How to remove the error of non-existent field

I am getting an error when running matlab code. Here I am trying to use one of the outputs of previous code as input to my new code.
??? Reference to non-existent field 'y1'.
Can anyone help me?
A good practice might be to check if the field exists before accessing it:
if isfield( s, 'y1' )
% s.y1 exists - you may access it
s.y1
else
% s.y1 does not exist - what are you going to do about it?
end
To take Edric's comment into account, another possible way is
try
% access y1
s.y1
catch em
% verify that the error indeed stems from non-existant field
if strcmp(em.identifier, 'MATLAB:nonExistentField')
fprintf(1, 'field y1 does not exist...\n');
else
throw( em ); % different error - handle by caller?
end
end
Have you used the command load to load data from file(s)?
if yes, this function overwrite your current variables, therefore, they become non-existent, so when you call, it instead of using:
load ('filename');
use:
f=load ('filename');
now, to refer to any variable inside the loaded file use f.varname, for
example if there is a network called net saved within the loaded data you may use it like:
a = f.net(fv);
I would first explain my situation and then give the solution.
I first save a variable op, it is a struct , its name is coef.mat;
I load this variable using coef = load( file_path, '-mat');
In a new function, I pass variable coef to it as a parameter, at here, the error Reference to non-existent field pops out.
My solution:
Just replace coef with coef.op, then pass it to the function, it will work.
So, I think the reason behind is that: the struct was saved as a variable, when you use load and want to acess the origin variable, you need point it out directly using dot(.) operation, you can directly open the variable in Matlab workspace and find out what it wraps inside the variable.
In your case, if your the outputs of previous code is a struct(It's my guess, but you haven't pointed out) and you saved it as MyStruct, you load it as MyInput = load(MyStruct), then when use it as function's parameter, it should be MyInput.y1.
Hops it would work!
At first load it on command window and observe the workspace window. You can see the structure name. It will work by accessing structure name. Example:
lm=load('data.mat');
disp(lm.SAMPLE.X);
Here SAMPLE is the structure name and X is a member of the structure