I'm trying to avoid using eval() but am at a loss. My code works fine using eval(), but I'm curious to see if somebody can solve the same problem without it.
I have a class called "Wavefront" with a method called "ToMAT". Let W be an instance of a Wavefront object. I want the behavior of
>>W.ToMAT('filename.mat')
to save the variable W to filename.mat. I want the variable name to be preserved so that
>> load('filename.mat')
creates a variable called W. The only way I have figured out how to do this is with code that looks like the following (I've trimmed out some error handling and other stuff). This is a member function in Wavefront.m.
function [success, filename] = ToMAT(obj, filename)
var_name = inputname(1);
eval(sprintf('%s = obj;', var_name));
save(filename, var_name);
Can somebody solve this problem without using eval?
Thanks,
Eric
|
|
0
|
|
|
|
Reply
|
Eric
|
5/12/2010 5:51:04 PM |
|
"Eric " <not@givingemail.com> wrote in message <hsepq8$1a7$1@fred.mathworks.com>...
> I'm trying to avoid using eval() but am at a loss. My code works fine using eval(), but I'm curious to see if somebody can solve the same problem without it.
>
> I have a class called "Wavefront" with a method called "ToMAT". Let W be an instance of a Wavefront object. I want the behavior of
>
> >>W.ToMAT('filename.mat')
>
> to save the variable W to filename.mat. I want the variable name to be preserved so that
>
> >> load('filename.mat')
>
> creates a variable called W. The only way I have figured out how to do this is with code that looks like the following (I've trimmed out some error handling and other stuff). This is a member function in Wavefront.m.
>
> function [success, filename] = ToMAT(obj, filename)
> var_name = inputname(1);
> eval(sprintf('%s = obj;', var_name));
> save(filename, var_name);
>
> Can somebody solve this problem without using eval?
>
> Thanks,
> Eric
one of the many(!) other solutions
function tom(d,fnam)
s.(inputname(1))=d;
save(fnam,'s');
end
us
|
|
0
|
|
|
|
Reply
|
us
|
5/12/2010 6:13:04 PM
|
|
Eric wrote:
> I have a class called "Wavefront" with a method called "ToMAT". Let W
> be an instance of a Wavefront object. I want the behavior of
> >>W.ToMAT('filename.mat')
>
> to save the variable W to filename.mat. I want the variable name to be
> preserved so that
>
> >> load('filename.mat')
>
> creates a variable called W. The only way I have figured out how to do
> this is with code that looks like the following (I've trimmed out some
> error handling and other stuff). This is a member function in Wavefront.m.
>
> function [success, filename] = ToMAT(obj, filename)
> var_name = inputname(1);
> eval(sprintf('%s = obj;', var_name));
> save(filename, var_name);
>
> Can somebody solve this problem without using eval?
function [success, filename] = ToMat(obj, filename);
var_name = inputname(1);
SaveStruct.(var_name) = obj;
save(filename, '-STRUCT', SaveStruct);
|
|
0
|
|
|
|
Reply
|
Walter
|
5/12/2010 6:15:16 PM
|
|
"Eric " <not@givingemail.com> wrote in message <hsepq8$1a7$1@fred.mathworks.com>...
> I'm trying to avoid using eval() but am at a loss. My code works fine using eval(), but I'm curious to see if somebody can solve the same problem without it.
>
> I have a class called "Wavefront" with a method called "ToMAT". Let W be an instance of a Wavefront object. I want the behavior of
>
> >>W.ToMAT('filename.mat')
>
> to save the variable W to filename.mat. I want the variable name to be preserved so that
>
> >> load('filename.mat')
==============
Note: It is dangerous to create variables using load, and therefore questionable why you would want to do this.
The advisable practice is to do
S=load('filename');
myVariable=S.whatever; %whatever is the variable name as stored in the file
> creates a variable called W. The only way I have figured out how to do this is with code that looks like the following (I've trimmed out some error handling and other stuff). This is a member function in Wavefront.m.
>
> function [success, filename] = ToMAT(obj, filename)
> var_name = inputname(1);
> eval(sprintf('%s = obj;', var_name));
> save(filename, var_name);
>
> Can somebody solve this problem without using eval?
==============
The following modification should do it.
function [success, filename] = ToMAT(obj, filename)
var_name = inputname(1);
S.(var_name)=obj;
save(filename, '-struct',S);
|
|
0
|
|
|
|
Reply
|
Matt
|
5/12/2010 6:17:04 PM
|
|
us wrote:
> function tom(d,fnam)
> s.(inputname(1))=d;
> save(fnam,'s');
> end
That would create a .mat file in which the variable name was 's', rather
than being the variable name of the object. Adding the -struct option
does the needed conversion work.
|
|
0
|
|
|
|
Reply
|
Walter
|
5/12/2010 6:25:16 PM
|
|
Walter Roberson <roberson@hushmail.com> wrote in message <goCGn.8258$Gx2.5836@newsfe20.iad>...
> us wrote:
>
> > function tom(d,fnam)
> > s.(inputname(1))=d;
> > save(fnam,'s');
> > end
>
> That would create a .mat file in which the variable name was 's', rather
> than being the variable name of the object. Adding the -struct option
> does the needed conversion work.
walter
now THAT is not (necessarily) advisable (in my view)...
the OP should learn to organize his/her data in a STRUCT...
otherwise, he/she ends up with all those zillions of variables in his/her workspace...
that's why i left this option off...
urs
|
|
0
|
|
|
|
Reply
|
us
|
5/12/2010 6:45:22 PM
|
|
Thanks to everybody for their help. I skipped over reading the -STRUCT sections of the help for save() since I wasn't trying to save a structure. I'll try to be more careful in the future.
In response to Matt J's question about the utility: It's possible I might use this method from several Wavefronts to save to the same MAT file. I stripped this part out of the code that I posted to try to be brief. Without changing the variable name to something meaningful, each time ToMAT(obj, filename) is called, a variable called "obj" would be appended to the MAT file, presumably overwriting the first one.
Thus
>>W1.ToMAT('c:\temp.mat')
>>W2.ToMAT('c:\temp.mat')
in my more-detailed function would allow both W1 and W2 to exist in the temp.mat file.
I definitely agree that you have to be careful using the non-functional form of load(). I do this as rarely as possible and add comments indicating what variables are being created in the workspace to help make the code more readable. I also generally only do this in script files where there's significant overhead associated with loading or processing data which I would hope to avoid in future runs.
Thanks again,
Eric
|
|
0
|
|
|
|
Reply
|
Eric
|
5/12/2010 6:45:22 PM
|
|
"Eric " <not@givingemail.com> wrote in message
news:hset02$oa1$1@fred.mathworks.com...
> Thanks to everybody for their help. I skipped over reading the -STRUCT
> sections of the help for save() since I wasn't trying to save a structure.
> I'll try to be more careful in the future.
>
> In response to Matt J's question about the utility: It's possible I might
> use this method from several Wavefronts to save to the same MAT file. I
> stripped this part out of the code that I posted to try to be brief.
> Without changing the variable name to something meaningful, each time
> ToMAT(obj, filename) is called, a variable called "obj" would be appended
> to the MAT file, presumably overwriting the first one.
>
> Thus
>>>W1.ToMAT('c:\temp.mat')
>>>W2.ToMAT('c:\temp.mat')
>
> in my more-detailed function would allow both W1 and W2 to exist in the
> temp.mat file.
> I definitely agree that you have to be careful using the non-functional
> form of load(). I do this as rarely as possible and add comments
> indicating what variables are being created in the workspace to help make
> the code more readable. I also generally only do this in script files
> where there's significant overhead associated with loading or processing
> data which I would hope to avoid in future runs.
>
> Thanks again,
> Eric
So what would you expect this code to write to the MAT-file?
W = cell(1, 2);
W{1} = Wavefront(5); % Assume I used the correct constructor syntax here
W{2} = Wavefront(7);
W{1}.ToMAT('c:\temp.mat')
% or if you prefer
ToMAT(W{1}, 'c:\temp.mat')
W{1} is not a valid variable name and as such calling SAVE with W{1} as the
string corresponding to the variable to save should (and does) error. Okay,
you could say, in that case I use something like GENVARNAME.
Now how about this?
ToMAT(Wavefront(5), 'c:\temp.mat')
% or even better
ToMAT(Wavefront, 'c:\temp.mat') % using the fact that this will call the
0-input constructor
Would you attempt to save this to a variable named Wavefront in the
MAT-file? Then you'd run into problems when you LOAD it, as the variable
would then shadow the constructor of the class.
--
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
|
|
0
|
|
|
|
Reply
|
Steven
|
5/12/2010 7:20:25 PM
|
|
Steve brings up an interesting point. My Wavefront class does have a "Name" member, so I switched the code to use that for the variable name in the MAT file. I first use assert(isvarname(obj.Name),...) to check that the Name is a valid Matlab variable name. If it's not, an error is reported and no saving is allowed.
I believe this also addresses the ToMAT(Wavefront, 'c:\temp.mat') problem. In this case the returned empty wavefront has a name that is an empty string. This fails the isvarname() test as well. Honestly I never use the empty constructor explicitly, though, as I'm always creating a Wavefront object from data in some form.
I'm not sure what "us" means when he says I should learn how to organize my data in a STRUCT. My data is already organized in a single object. There aren't thousands of variables in my workspace, just one. I would claim that organizing my data in a user-defined class is preferable to using a STRUCT. The object-oriented functionality of Matlab is quite powerful. I'm guessing there's been some misunderstanding of what I'm doing.
Thanks to everybody once again.
-Eric
|
|
0
|
|
|
|
Reply
|
Eric
|
5/12/2010 8:40:20 PM
|
|
When I try to use this solution I keep getting the following error message
"Error using save
The argument to -STRUCT must be the name of a scalar structure variable."
this is the code I use:
var_name = catchmentName(1);
S.(var_name) = rainfallRunoffCatchment;
save('WQmodelData.mat', '-struct',S);
The variable rainfallRunoffCatchment is a mxn double so I do not understand why this does not create a scalar structure, according to the help (http://www.mathworks.nl/help/matlab/ref/struct.html) :
If value is not a cell array, then s is a scalar structure
This is my case but still I get this strange error saying that is not a scalar structure...
Any thoughts on what I am doing wrong?
|
|
0
|
|
|
|
Reply
|
ingrid.keupers (2)
|
9/20/2012 2:21:07 PM
|
|
"Echidna " <ingrid.keupers@bwk.kuleuven.be> wrote in message
news:k3f8oj$l02$1@newscl01ah.mathworks.com...
> When I try to use this solution I keep getting the following error message
>
> "Error using save
> The argument to -STRUCT must be the name of a scalar structure variable."
>
> this is the code I use:
> var_name = catchmentName(1);
> S.(var_name) = rainfallRunoffCatchment; save('WQmodelData.mat',
> '-struct',S);
>
> The variable rainfallRunoffCatchment is a mxn double so I do not
> understand why this does not create a scalar structure, according to the
> help (http://www.mathworks.nl/help/matlab/ref/struct.html) :
> If value is not a cell array, then s is a scalar structure
> This is my case but still I get this strange error saying that is not a
> scalar structure...
No, read the error message more closely.
S is a scalar struct array, but S is not the NAME of a scalar struct array.
The string 'S' IS the name of a scalar struct array. See the 4th example on
the documentation page for SAVE for an example of how to save a structure to
a MAT-file with each field being stored as a separate variable. Pay close
attention to the last input in that SAVE call.
http://www.mathworks.com/help/matlab/ref/save.html
--
Steve Lord
slord@mathworks.com
To contact Technical Support use the Contact Us link on
http://www.mathworks.com
|
|
0
|
|
|
|
Reply
|
slord (13276)
|
9/20/2012 3:14:53 PM
|
|
|
10 Replies
168 Views
(page loaded in 0.124 seconds)
|