Invoking a method defined into a running Figure - matlab

I have the following UIFigure:
classdef gui < matlab.apps.AppBase
...
function app = gui
% Construct app
end
...
properties (Access = public)
myFuncRef = #myFun
end
...
function myFun(app)
% do something
end
...
end
in which I have defined the method myFun.
If the figure is running (that is, it's showing a window), how can I invoke the method myFun from the Command Window of MATLAB ? I tried with
h = findobj(0, 'type', 'figure');
funcRef = get(h, 'myFuncRef');
funcRef(h);
but I get the error
An error occurred while running the simulation and the simulation was
terminated Caused by: Function 'subsindex' is not defined for values
of class 'matlab.graphics.GraphicsPlaceholder'.
Thanks in advance!

Try this one:
h = findobj(gcf,'-method','myFuncRef')
or
h = findobj(0,'class','gui')
let me know if it works
The probelm is probably that you get just your figure with findobj(0, 'type', 'figure'), this is just a Grahics Obejct which is manimulated by the App-Class.

First I'd like to address the error you're getting. The reason for it is that the h returned by your call to findobj() is empty. Instead you should use findall(0,'Type','Figure',...) [src].
I know this is possible when the method you're referencing is static. Considering the following class:
classdef q45062561 < matlab.apps.AppBase
properties (Access = public)
myFuncRef = #q45062561.myFun
end
methods (Access = private, Static = true)
function myFun()
disp('This works!')
end
end
end
Then, running the following would yield the desired result:
>> F = q45062561;
>> F.myFuncRef()
This works!
Notes:
Rather than finding the handle of the figure via findobj, I'm just storing it during creation.
The modifiers of myFun are unclear from the question so I can't know if this solution is suitable in your case.
Personally, I think it's a better idea to just define the method public and/or static, instead of using a function reference stored in a property.

Related

Matlab-GUI warning when using parfeval(): "Unable to save App Designer app object."

I am trying to call parallel functions within my Matlab-GUI by pushing a startbutton.
For the beginning I tried to call one single function ("ReadTwinCAT") but I'm always getting the following error-message:
"Warning: Unable to save App Designer app object. Save not supported
for matlab.apps.AppBase objects."
As I thought I already used parallel functions like this within a GUI, I don't know what I am doing wrong...
Matlab-App-Designer Code:
properties (Access = private)
running_state = 0; % Description
tcClient;
db_conn;
end
methods (Access = private)
function ReadTwinCAT(app)
while app.running_state == 1
disp('running')
pause(0.1)
end
disp('stopped')
end
end
% Callbacks that handle component events
methods (Access = private)
function StartButtonPushed(app, event)
app.running_state = 1;
pool = gcp(); %Initialize pool of workers
parfeval(pool, #ReadTwinCAT, 0, app); %Call parallel function
end
end
Ok, I think I found an answer from Mathworks staff:
https://www.mathworks.com/matlabcentral/answers/366576-will-there-be-a-support-of-the-parallel-toolbox-in-matlab-app-designer#comment_720548
Note the limitation of accessing the app object inside the parfor loop or any other functions called though Parallel Computing Toolbox.
If you need to access properties of your app pass them down as values directly, e.g. instead of
b = [0,0];
parfor i=1:2
b(i) = app.myprop*2
end
use
tmp = app.myprop;
b = [0,0];
parfor i=1:2
b(i) = tmp*2
end
So it seems that you can't access (or it would seem set) the properties of the app object within a parallelized function. If you want to get data out, you'll probably have to set up a communication system using parallel.pool.DataQueue. Your example is tough to parallelize. A better option would probably be to add a listener to your running_state property, and/or use a timer function.
The major downside of this is that the function you call from the timer is not actually parallelized - it runs in the same thread, so if you have a lot of computation in ReadTwinCAT, I think it will cause lag/unresponsiveness in the GUI.
I've modified your code to use a timer instead of parfeval:
properties (Access = private)
running_state = 0; % Description
runningTimer;
tcClient;
db_conn;
end
methods (Access = private)
function ReadTwinCAT(app, varargin)
if app.running_state == 1
disp('running')
else
stop(app.runningTimer);
disp('stopped')
end
end
end
% Callbacks that handle component events
methods (Access = private)
function StartButtonPushed(app, event)
app.running_state = 1;
app.runningTimer = timer;
app.runningTimer.Period = 0.1;
app.runningTimer.ExecutionMode = 'fixedRate';
app.runningTimer.TimerFcn = #app.ReadTwinCAT;
start(app.runningTimer)
end
end
I'll share my half-baked solution here for parfor and app. If you get your function outside of App Designer you can do the following
function ExternalFunction(app)
dataQueueUpdateUI = parallel.pool.DataQueue;
afterEach(dataQueuePorthole, #UpdateUI);
parfor i = 1 : 4
CalculatingFunction(arg1, dataQueueUpdateUI)
send(dataQueueUpdateUI, 'whatever')
end
end
UpdateUI can take only one argument (cell, array, struct etc.), but based on type, you can trigger different actiens in app. The function is evaluated on client, therefore it can find app handles. You can also have multiple DataQueue objects, but I can't really tell how does it affect the lag. Speaking of it, there might be some, anything from 0-5 seconds, at least in my case.
Example for UpdateUI function, I run it every 0.5 s while I have few instances of other programs working in background. Within UpdateUI, you can do whatever you want to with the app.
function UpdateUI(arg)
% Initialising app
persistent app
if isempty(app)
app = get(findall(0, 'type', 'figure'), 'RunningAppInstance'); % if you only have one figure on
end
pause(0.1)
drawnow limitrate;
end

Matlab class dynamic filling of a property

I'm trying to dynamically fill a property in a Matlab class.
I pass vectors to a method function and then compute various parameters. I would like to fill the properties in a for loop, see code example. The OwnClassFunction is just an example of a further function in the class, but is not implemented in the code example. How can I do this correctly?
classdef Sicherung < handle
properties
x = ([],1)
end
methods
function examplefunction(object,...
single_parameter_vector) % (n,1) n can be any size
for i=1:length(param_vector)
[object.x(i,1)] = object.OwnClassFunction(single_parameter_vector(i,1));
end
end
end
end
If i try something like that
...
properties
x = []
end
...
function ...(object,parameter)
for i=1:length(parameter)
[object.x(i)] = function(parameter(i));
end
I get the error message Subscripted assignment dimension mismatch.
I don’t have MATLAB in hand to test, but the following should work.
Your code is pretty close to a correctly functioning method. Change it as follows:
classdef Sicherung < handle
properties
x = [] % initialize to empty array
end
methods
function examplefunction(object,param_vector)
if ~isvector(param_vector)
error('vector expected') % check input
end
n = numel(param_vector)
object.x = zeros(n,1); % preallocate
for i=1:n
object.x(i) = object.OwnClassFunction(param_vector(i));
end
end
end
end

I pass an anonymous function f = #(x) x.^2 to a MatLab class, but then it disappears?

I have a class Solver:
classdef Solver
properties
myFunc
end
methods
function setMyFunc(this, myFunc)
this.myFunc = myFunc;
end
end
end
I create an instance of this class and then pass it an anonymous function like so:
f = #(x) x.^2;
solver = Solver();
solver.setMyFunc(f);
If I debug the code and print the 'this' variable inside the setMyFunc method I get the following:
Solver with properties:
myFunc: #(z) x.^2
However when the code exits back to my main file and I print the solver variable this time I get:
Solver with properties:
myFunc: []
And so clearly it has lost the reference to the function I passed it. What is happening here, how can I pass an anonymous function to a class?
Matlab strictly uses the pass-by-value convention. The only exception is when you derive from the handle class. If you do not want to derive from the handle class you need to do
methods
function this = setMyFunc(this, myFunc)
this.myFunc = myFunc;
end
end
and use it with
solver = solver.setMyFunc(f);
Since this is a bit awkward, so I would use the following (standard way)
methods
function this = set.myFunc(this, myFunc)
this.myFunc = myFunc;
end
end
Using this property set method you can actually write
solver.myFunc = XXX;
to involke the set function. Note, that in both cases you need this also as output argument.
using classdef Solver < handle worked for me:
classdef Solver < handle
properties
myFunc;
end
methods
function setMyFunc(this,myFunc)
this.myFunc = myFunc;
end
end
end

How to pass parameter by reference in Matlab

I am a beginner in matlab and learn about the following question online and was having trouble solving it. I have a 1 x 20 matrix called current_load that I need to update periodically. This matrix resides in the main workspace of Matlab (as shown in the code bellow).
current_loads = zeros(1, 20);
for col=1:20
current_loads(1,col)=10; %// Initially give all nodes a current value of 10
end
Object = HandleObject(current_load);%To pass by reference
recursive_remove(Object, 0);
In order to pass current_load by reference, I have created the following class HandleObject.m
classdef HandleObject < handle
properties
Object=[];
end
methods
function obj=HandleObject(receivedObject)
obj.Object=receivedObject;
end
end
end
This matrix will be passed to a function call recursive_remove (shown bellow).
function recursive_remove( current_load, val )
current_load.object = new matrix;
if(val<10)
current_load.object(1,3) = 2+val; %Not the correct way of using current_load ??
end
recursive_remove( current_load, current_load.object (1,3) )
end
Intention here is to modify current_load variable in this function and later I can see these same changes from the main. But This code doesn't work since I don't know how to pass by reference. I need to pass by reference since I am calling this recursively without returning to the main to make it overwrite its variable at the caller. Please show with an example if possible.
If you really need this feature, you can look into turning your HandleObject class into a Singleton like this:
classdef HandleObject < handle
properties
Object=[];
end
methods(Static)
function obj = Instance(receivedObject)
persistent uniqueInstance
try
if isempty(uniqueInstance)
obj = HandleObject(receivedObject);
uniqueInstance = obj;
else
obj = uniqueInstance;
end
catch ME
disp(ME.getReport);
end
end
end
methods
function obj=HandleObject(receivedObject)
obj.Object=receivedObject;
end
end
end
Your recursive function would become a bit simpler then:
function recursive_remove(val )
current_load = HandleObject.Instance();
current_load.object = new matrix;
if(val<10)
current_load.object(1,3) = 2+val;
end
recursive_remove(current_load.object (1,3) )
end
And to create an instance of your HandleObject class, you do something like:
Object = HandleObject.Instance(current_load);
Hope this helps you further.

H must be the handle to a figure or figure descendent Matlab

I'm calling GUI function in matlab's classdefbut it gives error of "H must be the handle to a figure or figure descendent." in guihandles(GUI);
How can I call function of GUI in matlab's class?
The working of the class is perfect by the way, but it gives error then figure is closed.
My class code:
classdef GUIclass < handle
properties (Access = private)
gui_h;
end
methods
function obj = GUIclass
guihandles(GUI);
end
end
end
This function guihandles(h) expects a handle. If the handle specified by h (in your case, GUI) is closed then it is no longer valid. You can check to see if GUI is a valid handle before using it with ishandle(h) or ishandle(GUI).
See the following code:
close all;
h = 1;
% We just closed everything, so we expect handle h=1 to be bad:
if ishandle(h)
disp('Is a valid handle');
else
disp('Is not a valid handle');
end
% Now make the figure (we specify '1' so that will make h okay
figure(1);
% check to see if h is valid:
if ishandle(h)
disp('Is a valid handle');
else
disp('Is not a valid handle');
end