creating handles in a for loop - matlab

I'm creating a GUI with a large number of checkboxes
h.f = figure('units','pixels','position',[200,200,150,50],...
'toolbar','none','menu','none');
for i=1:100
num_data=round((100*(5*rand()))/100);
end
h.t(i) = uicontrol('style','text','units','pixels',...
'position',[30,820-15.*i,150,15],'string','za');
h.c.a(i) = uicontrol('style','checkbox','units','pixels',...
'position',[150,820-15.*i,125,15],'string','1');
if num_data>1
h.c.b(i) = uicontrol('style','checkbox','units','pixels',...
'position',[175,820-15.*i,25,15],'string','2');
end
if num_data>2
h.c.c(i) = uicontrol('style','checkbox','units','pixels',...
'position',[200,820-15.*i,25,15],'string','3');
end
if num_data>3
h.c.d(i) = uicontrol('style','checkbox','units','pixels',...
'position',[225,820-15.*i,25,15],'string','4');
end
if num_data>4
h.c.e(i) = uicontrol('style','checkbox','units','pixels',...
'position',[250,820-15.*i,25,15],'string','5');
end
h.p = uicontrol('style','pushbutton','units','pixels',...
'position',[40,5,70,20],'string','OK',...
'callback',#p_call);
% Pushbutton callback
function p_call(varargin)
vals=get(h.c, 'Value');
checked = find([vals{:}]);
if isempty(checked)
checked = 'none';
disp(checked)
else
for i=checked
Data1=dlmread(strcat(files{i}, ' PYRO.txt'),2,0);
plot(Data1(3:end,1),Data1(3:end,2))
hold on
end
end
hold off
The code is placing the checkboxes in the right place, but h is disappearing at the end of the for loop, and this is the error I'm getting.
??? Undefined variable "h" or class "h.c".
Error in ==> checkboxesGUI>p_call at 50
vals=get(h.c, 'Value');
??? Error while evaluating uicontrol Callback
How do I make it so I can call back on h?

The error indicates that p_call does not have access to the struct h where your handles are stored. Your entire code is not posted, but it seems clear that p_call is not nested in the function that owns h. Restructure your code so p_call has access to h, or pass h as an input argument every time it is called.
Also, a problem is that h.c is a struct, not a handle. Your handles are in the subfields of h.c (i.e. h.c.a, h.c.b, etc.). This is a bit messy, so I would suggest changing the code so you keep the checkbox handles in an array addressed via h.c(i) so your get and find lines will work.

Related

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

Invoking a method defined into a running Figure

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.

Matlab gui with pause function

I am using the GUIDE for matlab gui.
The gui built in order to communicate with keithley current measurement device through GPIB.
When using a toggle button for Current measurement while loop, i am using a pause() function inside the while loop for each iteration and a ytranspose on the y array reading results.
function Measure_Callback(hObject, eventdata, handles)
global GPIB1
global filename
global timeStep
disp('Measurement in progress \n stopwatch starts!');
tic
x=0;
n=0;
while get(hObject,'Value')
fprintf(GPIB1, 'printnumber(smua.measure.i(smua.nvbuffer1))');
fprintf(GPIB1, 'printbuffer(1,1,nvbuffer1)');
A = fscanf(GPIB1);
if length(A)<20
x = x+1;
n = n+1;
t(n) = toc ;
y(x) = str2double(A);
plot(t,y,'-bo',...
'LineWidth',2,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[.49 1 .63],...
'MarkerSize',10);
grid on
hold on
end
title('Current vs Time','FontSize', 15)
xlabel('Time [s]','FontSize', 15)
ylabel('Current [A]','FontSize', 15)
a = timeStep;
pause(a)
end
disp('Measurement terminated');
disp('Elapsed time: ');
elapsedtime = toc;
elapsedtime_string = num2str(elapsedtime);
disp(elapsedtime_string);
ytrans = transpose(y);
csvwrite(filename,ytrans);
fprintf(GPIB1, 'smua.source.output = smua.OUTPUT_OFF');
For the pause function i'm geting error:
?? Error using ==> pause Error while evaluating uicontrol Callback
For the transpose(y) function i'm also getting a error:
its undefined y.
Cant understand why are those errors and could use some help.
Thank you!
First off, as people say, post the errors and the code. Do you know if length(A) is smaller than 20 in the first time you run the loop? Because if not, A is not defined and you can't transpose something that is not there. Initialize A before the loop to something and see if the error persists (or print out length(A) to make sure the loop gets entered the first run).
As for the pause error, make sure pause is an int or double, not a string. If you get your global timeStep from the GUI field, it is probably a string and you need to covert it to double first.

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.

parfor and handle classes

I have a handle class:
classdef A<handle
properties
a;
end
methods
function obj = A(a)
obj.a=a;
end
end
end
And I have a cell array of A objects:
arr={};
for i=1:3
arr{i}=A(i);
end
What I would like to do is pass that cell array to a parfor loop so that each object's value will change:
parfor i=1:3
arr{i}.a=i*5;
end
However, this code does not change arr at all. Indeed, here it states that
Changes made to handle classes on the workers during loop iterations are not automatically propagated to the client.
How can I overcome this?
An interesting question; I actually never encountered this problem. It's always good to know everything about parfor limitations, so I did some googlin' and came up with this:
I have received an answer to this issue from technical support.
Apparently the Mathworks regard it as a 'feature' that changes to
objects are not returned - though I can't see that it's a very useful
feature. Anyway, the way to get modified class properties returned
from a parfor loop is to make an explicit change which can be
recognised by parfor. Here are two examples which work for the above
example object:
parfor n = 1:num
exArray(n).data = n:n+5;
end
or
parfor n = 1:num
temp = exArray(n);
setData(temp,n:n+5);
exArray(n) = temp;
end
Actually, if you change any object property it also seems to work. So
for example this also works, if there is a second property data2 which
is set explicitly, both data and data2 are correctly returned:
parfor n = 1:num
setData(exArray(n),n:n+5);
exArray(n).data2 = n:n+5;
end
Where the example object is given by
classdef Example < handle
properties
data
end
methods
function obj = Example(data)
obj.data = data;
end
function setData(obj,data)
obj.data = data;
end
function data = getData(obj)
data = obj.data;
end
end
end
and the array is initialized simply as
% Initialise array of objects
for n = 1:num
exArray(n) = Example(zeros(1,6));
end