I have a matlab code running in a loop. The code is pretty heavy and time-consuming. Instead of using Ctrl-C, I am looking for a way to abort the function with GUI callback in runtime. I have my code designed as follows
function test
figure;
uicontrol('pos',[20 20 40 20],'string','abort','fontsize',12, 'callback', 'error(''p'');');
k=0;
while(k<10000)
m=1:10000;
x = rand(size(m));
for t=1:10000
x=x+sin(2*pi*m*0.02 + mod(t, 5)*pi);
end
% other code will be run here
plot(m, x);
drawnow;
k=k+1
end
end
Above code just as an example. I know it could be optimized but I don't concern about that now. I just want to know why above code doesn't work. The callback in which the 'error' function issued will not abort the code. How to make it work? Thanks.
The error callback is not called within the loop. Hence, the error callback and the loop are independent processes.
You could design your function this way:
function test
figure;
AbortButton = uicontrol('Style','togglebutton','pos',[20 20 40 20],'string','abort','fontsize',12);%, 'callback', 'error(''p'');');
k=0;
figure;
while(k<10000)
val = get(AbortButton,'val');
if (val == 0)
m=1:10000;
x = rand(size(m));
for t=1:10000
x=x+sin(2*pi*m*0.02 + mod(t, 5)*pi);
end
% other code will be run here
plot(m, x);
drawnow;
k=k+1;
elseif (val == 1)
break;
end
end
end
This is a rudimentary way, but might help.
Related
I try to update the value of a variable once it receive a data, so that I could update the message on waitbar on how many jobs it has completed. My code looks something like this:
function value = completedJobs(value)
value=value+1;
end
job=0;
dq = parallel.pool.DataQueue;
wb = waitbar(0,'Processing');
afterEach(dq, #(varargin) completedJobs(job)) // this is where I would like to update the waitbar with new completed jobs on the message
afterEach(dq, #(varargin) waitbar(job,sprintf('Completed: %d', job));
parfor i=1:100
send(dq, i);
end
And is it possible to merge twice calling of the afterEach into only one that could perform what those two calling did?
Thanks in advance!
This should do the trick. Make sure you move the completedJobs function to its own script otherwise the clear function on line 1 won't work.
clear completedJobs
dq = parallel.pool.DataQueue;
wb = waitbar(0,'Processing');
Listener = afterEach(dq, #(varargin) waitbar((completedJobs/100),wb,sprintf('Completed: %d', completedJobs(1))));
parfor i=1:100
send(dq, i);
end
delete(wb);
Because the completedJobs function is called twice for every listened event you need to have a switch within the function to ensure that n is only incremented once. This is done by passing a dummy input to completedJobs
function j = completedJobs(varargin)
persistent n
if isempty(n)
n = 0;
end
if numel(varargin) ~=0
else
n = n+1;
end
j=n;
end
I have the following function in matlab. I am trying to shuffle a matrix. But somehow matlab keeps executing the code from if even if the statement should go to else. And when it comes to else I have to put some aditional code, even if all it does is **i+1. It is normal for matlab or am I missing something?
function magic_matrix = magicsquare1(matrix,n)
magic_matrix=ones(n,n)*(-1);
i=3-1;
j=4+1;
for ki=1:n
for kj=1:n
if(i<1)
i=n;
end
if(j>n)
j=1;
end
if magic_matrix(i,j) == -1
magic_matrix(i,j)=matrix(ki,kj);
%X = sprintf('i=%d j=%d',i,j);
%disp(X)
i=i-1;
j=j+1;
else
i=i+2;
j=j-1;
if(i>n)
i=1;
end
if(j<1)
j=n;
end
magic_matrix(i,j)=matrix(ki,kj);
% X = sprintf('i=%d / j=%d',i,j);
%disp(X)
i=i-1;
j=j+1;
end
end
end
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.
I have a Matlab GUI which takes input in p array from different functions by different methods, my question is how I can terminates uiwait when the input of p array is taken, such that when any function of input is terminated successfully. I'm trying to put uiresume but it doesn't work on my side.
My code (Main Function):
function varargout = GUI(varargin)
if nargin == 0
fig = openfig(mfilename,'reuse');
handles = guihandles(fig);
guidata(fig, handles);
uiwait (fig);
if nargout > 0
varargout{1} = fig;
end
elseif ischar(varargin{1})
try
if (nargout)
[varargout{1:nargout}] = feval(varargin{:});
else
feval(varargin{:});
end
catch
end
end
I don't really get what exactly your code is supposed to do.
In any case:
uiresume has to be placed somewhere in a callback of the gui you're opening, since you're above code stops running in the uiwaitline.
So, you might have an "Ok"-Button on your GUI with a callback à la:
function ok_button_callback(object, evt, handles)
fig = ancestor(object, 'figure');
uiresume(fig);
end
I'm trying to use the bisection method in Matlab to find the root of an equation as q varies from 2000-3000 in 10 step intervals. My code however does not print out a graph even though I have a plot statement and I think it creates an infinite loop since when I run it matlab says busy and I can't close the program unless I force close. I can't see anything in my code that would cause this though, could someone help me out?
function myFunction
a = 20;
b = 40;
tol = 1e-4;
q = 2000:10:3000;
t = zeros(101,1);
for i=(1:length(q))
f = #(x) (((1800).*log((160000)./(160000 - (x.*q(i)))) - (9.812).*x)./750) - 1;
t(i) = bisect(f,a,b,tol);
end
figure(1)
plot(q,t)
function c=bisect(f,a,b,tol)
k=0;
while b-a > tol
c = (a-b)/2;
if sign(f(c)) == sign(f(b))
b=c;
else
a=c;
end
k=k+1;
end
end
end
It should also be noted that I have used this bisect method before and it does work so I don't think the problem is with that function.
Your error is here:
c = (a-b)/2;
You initialize a=20 and b=40. c is initially set to -10. But you really want c to be halfway between a and b, which means you want:
c = (a+b)/2;
Also, add a drawnow right after you plot statement to force MATLAB to draw graphics.