MATLAB nested event notifications? - matlab

It seems MATLAB handles will not respond to more than one notification from the same source at a time. Unfortunately this is a big problem for me. Here's an example of what I'm talking about:
classdef testClass < handle
events
testevent
end
methods
function obj = testClass
obj.addlistener('testevent', #obj.respond);
end
function raise(obj)
obj.notify('testevent');
end
function respond(obj, varargin)
fprintf('Responded!\n');
obj.raise();
end
end
end
when I execute the code
c = testClass;
c.raise();
The result is
Responded!
But I really want the recursion to work, though obviously in this simple example it would recurse infinitely. Is there any way to get this behavior?

You can make the listener recursive by setting the listener handle's Recursive property to true. Listener handle properties are in the event.listener help page. You just need to specify an output argument to obj.addlistener to retrieve the handle.
Here's the code I used to make it work:
classdef testClass < handle
events
testevent
end
methods
function obj = testClass
lh = obj.addlistener('testevent', #obj.respond);
lh.Recursive = true;
end
function raise(obj)
notify(obj,'testevent');
end
function respond(obj, varargin)
fprintf('Responded!\n');
obj.raise();
end
end
end
Also note that there is a default recursion limit of 500 calls, so naively the code won't infinitely recur; use set(0, 'RecursionLimit', N) to change that. I would think setting N=inf is a bad idea.

Related

Program in same OOP style as App Designer

I like the OO programming style that matlabs App Designer uses (or at least the way I'm using it). Now I'm wondering if I can use the same style in my "normal" matlab class.
What I have now:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
obj = DoSomething(obj);
disp(obj.myVar) % outputs "c"
end
function obj = DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
Which can be called externally using:
myClassInst = myClass;
myClassInst.Main()
I would like to get rid of all the "obj = " in the classdef, as is possible in App Designer. So something that would look like this:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
DoSomething(obj); % Just call the function without "obj = "
disp(obj.myVar) % outputs "a" because I didn't overwrite obj
end
function DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
The equivalent of this seems to work in App Designer. So it appears you can modify variables in a class (instance?) in App Designer, while also being able to access the modified variable without explicitly overwriting your old class instance.
I noticed App Designer has all methods an properties set to (Access = private), though I'm not sure that has anything to do with it. Of course if I set everything to private, then I can't access the Main() method from outside anymore.
So my question is, how can I program in "normal" matlab, the same way as is possible in App Designer?
EDIT:
The following works in App Designer (I left out the methods/properties for the GUI elements):
classdef tmp < matlab.apps.AppBase
properties (Access = private)
myVar; % Description
end
methods (Access = private)
function doSomething(app)
if app.myVar == "a"
app.myVar = "c";
else
app.myVar = "b";
end
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
app.myVar = "a";
doSomething(app);
disp(app.myVar); % outputs "c"
end
end
end
You definitely can! All you have to do is inherit from the handle class, as opposed to a value class which is the default for matlab. You can also define private and public methods as in other languages.
The only thing you have to do is:
classdef myclass < handle % this is how you inherit from base class
properties
public_property
end
properties (Access=private)
private_property
end
methods
function obj = myclass() % class constructor
...
end
function public_function()
...
end
end
methods (Access=private)
function private_function()
...
end
end
end
Now every time you pass an object of this class to a function, you are not passing it by value, you are passing by reference (as you might be used to from python) and modifying it's properties modifies them also in the original object.
You need to inherit (< at the top of the class) from a handle class
classdef myClass < handle
properties
var
end
methods
function obj = myClass( varargin )
% Constructor function, called automatically when object is created
end
function someFunction( obj )
obj.randomizeVar(); % Equivalent to randomizeVar( obj );
end
function randomizeVar( obj )
obj.var = rand();
end
end
end
See the documentation for the difference between a "handle" and "value" class:
A value class constructor returns an object that is associated with the variable to which it is assigned. If you reassign this variable, MATLABĀ® creates an independent copy of the original object. If you pass this variable to a function to modify it, the function must return the modified object as an output argument. For information on value-class behavior, see Avoid Unnecessary Copies of Data.
A handle class constructor returns a handle object that is a reference to the object created. You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object. A function that modifies a handle object passed as an input argument does not need to return the object.
Moreover, if you edit matlab.apps.AppBase, the class which you app designer code inherits, you can see that the first line is
classdef AppBase < handle
So you are literally doing the same thing, without the AppBase middle-man.

how to change value in map.continer child class

i have this superClass
classdef SysSignal<handle
%SIGNALP Summary of this class goes here
% Detailed explanation goes here
properties (SetAccess = public, GetAccess = public )
SetOfSignal = containers.Map('KeyType','char', 'ValueType', 'any')
end
methods
%constructor
function sys=SysSignal()
end
function sys=adds(sys,varargin)
%convert form cell to signalup
for n=1:length(varargin)
signal=varargin{1,n};
if isempty(signal.name)
continue
else
%add to the map
sys.SetOfSignal(signal.name)= signal;
end
end
end
and that child class
classdef Signalp<SysSignal
%SIGNALP Summary of this class goes here
% Detailed explanation goes here
properties
name
lineNo
color='red'
sumrole
end
properties (SetAccess=private,GetAccess=public)
arrPrice
LineLength
LineProportion
end
methods
%constructor
function sig=Signalp(varargin)
end
end
end
now i want to change the properties like this:
sys=SysSignal;
s=Signalp;
s.name='dd';
sys.adds(s)
sys.SetOfSignal('dd').sumrole='hello'
but i get that error :
??? Error using ==> subsasgn
Only one level of indexing is supported by a containers.Map.
how can i change the values from the superClass?
The answer is to seperate sys.SetOfSignal('dd').sumrole='hello' into two statements:
dd = sys.SetOfSignal('dd');
dd.sumrole='hello'
That is because sys.SetOfSignal('dd').sumrole doesn't do what you'd intuitively think it does. Indeed the containers.Map class overloads the subscripted reference and subscripted assignment operators. In essence they 'intercepts' the (), {} and . operators at the same time (ie .sumrole is 'sent' to the map.Containers object - instead of your object!). In my opinion that's a really weird design decision but we must live with it!
Have a look at these links for more info:
subsref, subsasgn
gregswiss's answer is correct, except that accessing the containers map creates a copy, so you finish by replacing the old value with the new modified one
dd = sys.SetOfSignal('dd');
dd.sumrole='hello'
sys.SetOfSignal('dd') = dd;

How to use Global Objects in Matlab S-Function

I need to use an object among several functions on a Matlab S-Function.
The object is used as a library and it is needed to set the conection with a server, get data from it in each loop and close it at the end of simulation. The use of the object its something like this:
ClassX ObjectX;
[Handle clientID]=ObjectX.setConnection(...);
while(coonection)
[result]=ObjectX.getPosition(Handle ClientID,...);
[result]=ObjectX.getAngle(Handle ClientID,...);
...
end
[result]=ObjectX.CloseConnection(...);
Its not convinient to instance and close the comunication in every loop. So I whant to create the object and set the conection on "function setup(block)", update data on "function Update(block)" and close the conection on "function Terminate(block)" but to do this I need to share the "ObjectX" an "clientID" among the functions.
I hope you can help me.
You can use a Singleton class, which is instantiated once and returns the same instance everytime you ask for it.
classdef (Sealed) SingleInstance < handle
methods (Access = private)
function obj = SingleInstance
end
end
methods (Static)
function singleObj = getInstance
persistent localObj
if isempty(localObj) || ~isvalid(localObj)
localObj = SingleInstance;
end
singleObj = localObj;
end
end
method (Access = public)
function setup(obj, block)
end
function update(obj, block)
end
function terminate(obj, block)
end
end
end
More information is available here

How can I close files that are left open after an error?

I am using
fid = fopen('fgfg.txt');
to open a file.
Sometimes an error occurs before I manage to close the file. I can't do anything with that file until I close Matlab.
How can I close a file if an error occurs?
First of all, you can use the command
fclose all
Secondly, you can use try-catch blocks and close your file handles
try
f = fopen('myfile.txt','r')
% do something
fclose(f);
catch me
fclose(f);
rethrow(me);
end
There is a third approach, which is much better. Matlab is now an object-oriented language with garbage collector. You can define a wrapper object that will take care of its lifecycle automatically.
Since it is possible in Matlab to call object methods both in this way:
myObj.method()
and in that way:
method(myObj)
You can define a class that mimics all of the relevant file command, and encapsulates the lifecycle.
classdef safefopen < handle
properties(Access=private)
fid;
end
methods(Access=public)
function this = safefopen(fileName,varargin)
this.fid = fopen(fileName,varargin{:});
end
function fwrite(this,varargin)
fwrite(this.fid,varargin{:});
end
function fprintf(this,varargin)
fprintf(this.fid,varargin{:});
end
function delete(this)
fclose(this.fid);
end
end
end
The delete operator is called automatically by Matlab. (There are more functions that you will need to wrap, (fread, fseek, etc..)).
So now you have safe handles that automatically close the file whether you lost scope of it or an error happened.
Use it like this:
f = safefopen('myFile.txt','wt')
fprintf(f,'Hello world!');
And no need to close.
Edit:
I just thought about wrapping fclose() to do nothing. It might be useful for backward compatibility - for old functions that use file ids.
Edit(2): Following #AndrewJanke good comment, I would like to improve the delete method by throwing errors on fclose()
function delete(this)
[msg,errorId] = fclose(this.fid);
if errorId~=0
throw(MException('safefopen:ErrorInIO',msg));
end
end
You can try a very neat "function" added by ML called onCleanup. Loren Shure had a complete writeup on it when it was added. It's a class that you instantiate with your cleanup code, then it executes when it goes out of scope - i.e. when it errors, or the function ends. Makes the code very clean. This is a generic version of the class that Andrey had above. (BTW, for complex tasks like hitting external data sources, custom classes are definitely the way to go.)
from the help:
function fileOpenSafely(fileName)
fid = fopen(fileName, 'w');
c = onCleanup(#()fclose(fid));
functionThatMayError(fid);
end % c executes fclose(fid) here
Basically, you give it a function handle (in this case #()fclose(fid))that it runs when it goes out of scope.
Your cleanup code is executed either when an error is thrown OR when it exits normally, because you exit fileOpenSafely and c goes out of scope.
No try/catch or conditional code necessary.
Andrey's solution above is indeed the best approach to this problem. I just wanted to add that throwing an exception in method delete() might be problematic, if you deal with arrays of safefopen objects. During destruction of such an array, MATLAB will call delete() on each array element and, if any delete() throws, then you might end up with leftover open file handles. If you really need to know whether something went wrong during destruction then issuing a warning would be a better option IMHO.
For those that feel lazy to write all the forwarding methods to every MATLAB builtin that uses file handles, you may consider the simple alternative of overloading method subsref for class safefopen:
methods(Access=public)
function varargout = subsref(this, s)
switch s(1).type
case '.'
if numel(s) > 1,
feval(s(1).subs, this.fid, s(2).subs{:});
else
feval(s(1).subs, this.fid);
end
% We ignore outputs, but see below for an ugly solution to this
varargout = {};
otherwise
varargout{1} = builtin('subsref', this, s);
end
end
end
This alternative uses the somewhat ugly feval, but has the advantage of working even if the MATLAB guys (or yourself) decide to add new functions that involve file handles, or if the number/order of the input arguments to a given function change. If you decide to go for the subsref alternative then you should use class safefopen like this:
myFile = safefopen('myfile.txt', 'w');
myFile.fprintf('Hello World!');
EDIT: A disadvantage of the subsref solution is that it disregards all output arguments. If you need the output arguments then you will have to introduce some more ugliness:
methods(Access=public)
function varargout = subsref(this, s)
if nargout > 0,
lhs = 'varargout{%d} ';
lhs = repmat(lhs, 1, nargout);
lhs = ['[' sprintf(lhs, 1:nargout) ']='];
else
lhs = '';
end
switch s(1).type
case '.'
if numel(s) > 1,
eval(...
sprintf(...
'%sfeval(''%s'', this.fid, s(2).subs{:});', ...
lhs, s(1).subs) ...
);
else
eval(...
sprintf('%sfeval(''%s'', this.fid);', ...
lhs, s(1).subs) ...
);
end
otherwise
varargout{1} = builtin('subsref', this, s);
end
end
end
And then you could do things like:
myFile = safefopen('myfile.txt', 'w');
count = myFile.fprintf('Hello World!');
[filename,permission,machineformat,encoding] = myFile.fopen();
fids=fopen('all');
fclose(fids);
%assuming that you want to close all open filehandles

Is it possible to hide the methods inherited from the handle class in matlab?

I'm working on a command line application for ultrasound simulation in MATLAB. Nearly every object in our code is a subclass of handle (to pass as references). The problem I'm having is that all the methods inherited from the handle class shows up under the "Methods" section in MATLAB (see example below).
What I want is to hide the inherited methods from the handle class so that only the function the user is allowed to use is shown under "Methods". This way it doesn't look so messy for the user if he/she wants to know which methods to use.
Example Test class:
classdef Test < handle
methods
function myFunction(obj)
end
end
end
In the command line:
T = Test()
T =
Test handle with no properties.
Methods, Events, Superclasses
After clicking on "Methods":
Methods for class Test:
Test delete findobj ge isvalid lt ne
addlistener eq findprop gt le myFunction notify
What I want:
Methods for class Test:
Test myFunction
Is this possible in MATLAB?
If you overload all of the subclass methods in a hidden methods block I think it will do exactly what you're looking for.
I'm not sure which versions of Matlab this works in, but it definitely works for me in R2012b.
The exception is isvalid as it is Sealed so you can't override it in a handle subclass.
classdef handle_light < handle
methods(Hidden)
function lh = addlistener(varargin)
lh = addlistener#handle(varargin{:});
end
function notify(varargin)
notify#handle(varargin{:});
end
function delete(varargin)
delete#handle(varargin{:});
end
function Hmatch = findobj(varargin)
Hmatch = findobj#handle(varargin{:});
end
function p = findprop(varargin)
p = findprop#handle(varargin{:});
end
function TF = eq(varargin)
TF = eq#handle(varargin{:});
end
function TF = ne(varargin)
TF = ne#handle(varargin{:});
end
function TF = lt(varargin)
TF = lt#handle(varargin{:});
end
function TF = le(varargin)
TF = le#handle(varargin{:});
end
function TF = gt(varargin)
TF = gt#handle(varargin{:});
end
function TF = ge(varargin)
TF = ge#handle(varargin{:});
end
function TF = isvalid(varargin)
TF = isvalid#handle(varargin{:});
end
end
end
If you save the above class to handle_light.m and then type methods handle_light in the command window you will get the following result:
Methods for class handle_light:
handle_light isvalid
The Test class then becomes:
classdef Test < handle_light
methods
function myFunction(obj)
end
end
end
Doing it in this way means that you don't need to put the overloads in the Test class which keeps things neater.
There is a solution here, including sample code.
In short, what you need to do is to overload Matlab's built-in function methods, so that when it is called on your class, it removes the methods of handle from the output. Make sure it works on everything else, though so that you don't mess up your user's other code. If you don't use the #foldername variant to store your class, you could put it into a private directory, for example.
Not a full solution, but if you do methods(T, '-full'), then it at least tells you which methods are inherited from handle, so you know what to ignore.
Just get the functions from the inherited class and cancel them out with the ones from the main class using setdiff.
mH = methods('handle');
m = methods('MyClass');
m = setdiff(m,mH);