why my structure variable does not contain the changes applied by my handle functions - matlab

I created a structure that contains fields and a group of handles functions.
I initialized my structure when I press a button from my Matlab GUI, and then I proceed to call my handle functions, which either add new fields to my struct or update the default ones.
However, I have difficulty to see the changes, despite assigning the structure to my workspace, as I wish to call it in other functions to use the updated fields.
I used assignin(ws,var,val) and evalin(ws, expression)
function struct = initialisedStruct(arg)
struct = struct ();
struct.a = arg;
struct.b = 1;
struct.run= {...
#aaaa,... %update some existed fields
#bbbb, ...%add here a new field call c. -> struct.c now exists.
#cccc,... %do something else
};
end
function [applyToStructure] = applyMethod(applyToStructure, handles)
for i = 1:length(handles)
[applyToStructure] = handles{i}(applyToStructure);
end
end
function clickOnThisButton(hObject, eventdata, handles)
input = 12;
struct = initialisedStruct(input);
applyMethodHandles(struct, struct.run); %modify the struct
assignin('base', 'struct', struct);
end
function clickOnAnotherButton(hObject, eventdata, handles)
myvar = struct.c; % here is my problem as it does not exist
end
I was expected after applying applyMethodHandles which loops through each handle containing in the run field and using assignin, to see in the workspace my struct variable with its new fields.

You are not grabbing the output of the function. There are no references in matlab, you need to copy the new modified structure.
Instead of:
applyMethodHandles(struct, struct.run); %modify the struct
Do:
struct=applyMethodHandles(struct, struct.run); %modify the struct
Also struct is the worst name you can choose. Not only is bad programming because it says nothing about what it is, you are shadowing MATLABs struct name, so it can not use it. I strongly suggest changing the name.

Related

How does one load a .mat file in the GUI, matlab app development

I am attempting to create a MATLAB app that saves the specific fields in a .mat file and allows for custom naming. Saving has seemed to work however attempting to load leads to nothing changing.
Any help would be appreciated
function SaveButtonPushed(app, event) % Saving element
props = properties(app);
lp = length(props);
values = cell(1,lp);
visibilities = cell(1,lp);
for i = 1:lp
propName = props{1};
property = app.(propName);
if isprop(property, 'Value')
values{i} = app.(propName).Value;
end
% if isprop(property, 'Visible')
% visibilities{i} = app.(props{i}).Visible;
% end
end
file = uiputfile('*.mat', "Save Message" );
if file
save(file, 'props', 'values', 'visibilities');
end
end
function LoadButtonPushed(app, event) % Loading element
[file,path] = uigetfile('*.mat');
selectedfile = fullfile(file);
load(selectedfile)
end
It is like Wolfie said in his comment. The variables in the .mat file are loaded into the private workspace for that function, which is cleared at once it exits.
So within the function you should be able to loop over your app properties again and set the values the ones loaded from the file.
Note that if you add a breakpoint, as Wolfie says, you should be able to see the private workspace and your loaded variables will be there until the function exits.
Alternatively, you could load the variables in to a structure:
S = load(selectedfile);
(See https://uk.mathworks.com/help/matlab/ref/load.html for more details)
and return that structure,
function [S] = LoadButtonPushed(app, event) % Loading element
You will have to change the interface/load function call to accept the returned variable, and I'm not sure that you can add the contents of the structure to the global namespace. However, you can access them through the loaded structure as:
S.props

Matlab load mat into variable

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.

Custom class containing a scalar categorical displays as "[1x1 categorical]" instead of displaying the category

On MATLAB R2014b, when you have a struct (or custom class) having a field that is a scalar categorical, when displaying the struct it will show [1x1 categorical] instead of what I want to achieve as shown below.
MWE:
struct.field = categorical({'category'})
Output:
struct =
field: [1x1 categorical]
My desired output:
struct =
field: category
or:
struct =
field: category [1x1 categorical]
I want this, because I'm writing some classes that have a categorical property that is always scalar; because I know this by definition, I don't need the objects' category to be displayed as [1x1 categorical]. When displaying the custom objects, I'd like it to show the category instead.
I could overload disp in my class methods, but then I'd need to rewrite a lot of displaying code from disp itself instead of merely changing the way a scalar categorical in a struct field shows.
Any ideas on how to achieve this? If your answer involves overloading disp in the class definition, then I want to see how you could display the object's other properties like a normal disp(obj) would, in addition to displaying the categorical property the way I want. Any ideas or thoughts you have might help me write my own answer, so please share any.
After playing around with this for a while, I think I finally have something that works for displaying these scalar categorical values within a custom class.
The basic idea is that I overload the get method for the property that is holding the categorical. I can then check the call stack to see what is trying to get the value of the variable. If it's our overloaded disp method (which is called any time we want to display our class), then I return the category name if it's only a scalar categorical. Otherwise, I return the value of the property itself (as a categorical).
It's definitely not the most elegant due to it's reliance on dbstack but it seems to work quite well.
classdef categoryclass < handle
properties
a = categorical({'category'});
end
methods
% Get Method for "a" property
function res = get.a(self)
% Get the call stack to determine *what* called this
stack = dbstack();
methodname = sprintf('%s.disp', class(self));
% If it is a scalar and it was called by our overloaded display
% method, then return the category name
if isscalar(self.a) && isa(self.a, 'categorical') && ...
strcmp(methodname, stack(end).name)
res = categories(self.a);
res = res{1};
% Otherwise return just the value itself
else
res = self.a;
end
end
% This ensure that disp() shows up in the stack
function disp(self)
% Simply call the built-in display function
builtin('disp', self);
end
end
end
Now if we try this out.
cls = categoryclass()
categoryclass with properties:
a: 'category'
Check that when we request the value we actually get a categorical.
class(cls.a)
ans =
categorical
Now change the value of it.
cls.a = categorical({'another category'})
categoryclass with properties:
a: 'another category'
Now use two categories
cls.a = categorical({'one', 'two'})
categoryclass with properties:
a: [1x2 categorical]
NOTE: This only appears to be an issue in R2014b and R2015a. It was fixed in all later releases.
It's been a while, but today I needed this again. I thought of another way to display scalar categorical variables. The following example class does the trick.
classdef dispfmtTest < matlab.mixin.Copyable
properties
prop = categorical(1) % default value is a scalar categorical
end
methods
function dispfmt(obj) % dispfmtTest object to display format
obj.prop = char(obj.prop); % convert to char type
end
function disp(self)
obj = copy(self); % copy is provided by superclass
dispfmt(obj)
disp#matlab.mixin.Copyable(obj) % call superclass disp
delete(obj)
end
end
end
The dispfmtTest class is a subclass of matlab.mixin.Copyable, which is in turn a subclass of handle. It provides the copy method to the disfmtTest class, which is used to temporarily create a copy of which the value of property prop is changed to whatever desired display format in method dispfmt. Then, the modified copy of the object is displayed using the regular disp function as provided by matlab.mixin.Copyable.
Demo
Running obj = dispfmtTest yields
d =
dispfmtTest with properties:
prop: '1'
and class(d.prop) yields
ans =
categorical
This is the behaviour as I expected. Support for array properties can be achieved too using isscalar.

Calling class object from a function without insert it to the function in MATLAB

We have this code in 'Reconstruction the subclass object from a saved struct' from MATLAB OOP documentation.
classdef MySuper
% Superclass definition
properties
X
Y
end
methods
function S = saveobj(obj)
% Save property values in struct
% Return struct for save function to write to MAT-file
S.PointX = obj.X;
S.PointY = obj.Y;
end
function obj = reload(obj,S)
% Method used to assign values from struct to properties
% Called by loadobj and subclass
obj.X = S.PointX;
obj.Y = S.PointY;
end
end
methods (Static)
function obj = loadobj(S)
% Constructs a MySuper object
% loadobj used when a superclass object is saved directly
% Calls reload to assign property values retrived from struct
% loadobj must be Static so it can be called without object
obj = MySuper;
obj = reload(obj,S);
end
end
end
I have a question about obj = MySuper. What is purpose of this line? How we can call MySuper object from this function without insert any object to loadobj function?
You first question is: What is the purpose of the obj = MySuper; line?
The answer is that the obj = MySuper; line initiates the variable obj as an element of the class MySuper. Non-static functions in a class will only run if the first input parameter is an instance of the class, so if obj is not initiated as a MySuper-object, then matlab will look for other functions called reload to run, and if none is found give you an error.
For your second question, I am not 100% sure what you mean. But I hope one of the following points will answer your question:
If you want to make a function that relates to a class, but not to a specific instance of the class, you can make a static function, these can take any input (also (if you want it that way) no input at all) - that is they don't need to have a first input parameter of the specific class.
To run a static function, use the class name followed by a dot and then the function name, so here you would type MySuper.loadobj(S) to run the function with the parameter S.
I would suggest that you try this out with the given example to better get to know the way oop works in matlab, you may for example try:
S.PointX = 1;
S.PointY = 2;
obj = MySuper.loadobj(S)
I hope this answers your questions.

Clever way to assign multiple fields at once?

Due to legacy function calls I'm sometimes forced to write ugly wrappers like this
function return = someWrapper(someField)
a = someField.a;
b = someField.b;
% and so on, realistically it's more like ten variables that
% could actually be grouped in a struct
save('params.mat', 'a', 'b'); %etc.
% then, on another machine, a function loads params.mat, does the calculations
% and saves the result in result.mat containing the variables c,d,...
load('result.mat', 'c', 'd');
return.c = c;
return.d = d;
% again, it's more than just two return values
So the basic idea is to create variables with the same names as someField's fieldnames, run a function and create a return structure using someFunction's return variable's names as fieldnames.
Is there some way simplify this using some loop e.g. over fieldnames(someField)?
Or should I actually use some different approach? Since some further processing is done with someField and result I'd like to keep using structs, but maybe a second question would be
Can save and load redirect varibale names? I.e. could e.g. the variable a in params.mat be stored using someField.a as value instead of having to assign a = someField.a first?
Why not something like this?
if this is s:
s.a=1
s.b=2
s.c=3
Then this command creates a matfile named "arguments" with variables a, b, c:
save arguments.mat -struct s
And this command loads a matfiles variables into a structure
r = load('arguments.mat')
How about using ASSIGNIN and dynamic fieldnames to loop over the structure fields and create the appropriate variables in the workspace:
function struct2base(s)
for f = fieldnames(s)'
assignin('base', f{:}, s.(f{:}))
end
Have a look at the deal() function.