I am looking for an elegant way to use a conditional try catch statement.
I suppose it could look something like this:
tryif loose==1
% Do something, like loading the user preferences
catch %Or catchif?
% Hande it
end
So far I know that you can use try catch blocks to let your compiled code run, but force it to stop in a debug session with dbstop if caught error. Now I am basically looking for the opposite:
Normally I want the code to stop if unexpected situations occur (to guarantee the integrity of results) but want to be less strict about certain things sometimes when I am debugging.
How about this:
try
% Do something, like loading the user preferences
catch exception
if loose ~= 1
rethrow(exception)
end
% Handle it
end
I don't know about elegant ;-), but at least it avoids the duplication of "do something".
I know one way to do it, though I would hardly call this elegant:
if loose == 1
try
% Do something, like loading the user preferences
catch
% Hande it
end
else
% Do something, like loading the user preferences
end
The best I've been able to do is:
try
% Do something, like loading the user preferences
catch me
errorLogger(me);
%Handle the error
end
And then
function errorLogger(me)
LOOSE = true;
%LOOSE could also be a function-defined constant, if you want multiple uses.
% (See: http://blogs.mathworks.com/loren/2006/09/13/constants/)
if LOOSE
%Log the error using a logger tool. I use java.util.logging classes,
%but I think there may be better options available.
else
rethrow(me);
end
Then, if desired for production-style deployments, avoid the constant condition checking like this:
function errorLogger(me)
%Error logging disabled for deployment
For the "tryif" functionality, you could assert on the first line of the try block:
try
assert(loose==1)
% Do something
catch err
if strcmp(err.identifier,'MATLAB:assertion:failed'),
else
% Hande error from code following assert
end
end
Note that the "Do something" code will not be executed if loose==1.
For the "catchif" functionality, A.Donda's approach of checking loose~=1 on the first line of the catch block seems quite good.
Related
I am calling an external exec. file (not written by me) using the system() command inside the MATLAB code. For some reasons the external file s/t gives the Segmentation fault error, and if I run the code again, it gets fixed.
Therefore, as we do in other languages, I am using try catch to catch the error, w/o stopping the whole process. Here is what I have written:
flag = false;
while(~flag)
try
system('….');
flag = true;
catch MExc
flag = false;
end
end
However, it does not catch the error. How to fix it?
I doubt that you can catch an exception thrown by an external application when called within Matlab (actually it's not a doubt, I'm certain, but the sentence is much more elegant). Anyway, from my knowledge, an application that shuts down without errors should return an ExitCode equal to 0.
Fortunately, the system function returns that value as its first output argument (official documentation), so try the following code instead:
status = -1;
while (status ~= 0)
[status,cmdout] = system('...');
end
% do something with cmdout
I am working on some modifications to EEGlab's eegplot function (things like vim-style navigation etc.) that need to work through WindowKeyPressFcn.
However, the callback is not being called for some reason. I have been debugging the issue for some time and am a bit lost. I am looking for suggestions on what might be wrong. Unfortunatelly the eegplot function is big, complex and somewhat convoluted and I was unable to reproduce the issue in a simple example. Therefore I am looking for general suggestions on why a function handle that is clearly present in WindowKeyPressFcn might stop being used at some point.
Here is what I have learned so far:
If I go to debug mode in eegplot (set a breakpoint near the end of the setup function [the first half of eegplot]) I am able to run the WindowKeyPressFcn at least once.
However - the function stops being called at some point during debug (sometimes even after being called only once).
If I run eegplot without debug (that is wait for it to finish and return control to me) I am unable to call WindowKeyPressFcn by pressing a key. The function handle is still present in WindowKeyPressFcn property of the figure.
Whener the WindowKeyPressFcn is not being used when I press a key, I can still call it with:
figh = gcf;
fun = get(figh, 'WindowKeyPressFcn');
ev.Key = 'rightarrow';
ev.Character = ' ';
ev.Modifier = [];
feval(fun, figh, ev);
So the function handle is 'healthy' so to speak, but for some reason it is not being used any more when a key is pressed and the figure has focus. When and why something like this could happen? Any ideas on things I should check to understand this issue?
Update:
I found out that WindowKeyPressFcn callback can sometimes be blocked by some window listeners, and tried out the following solution:
hManager = uigetmodemanager(gcf);
set(hManager.WindowListenerHandles,'Enable','off');
It doesn't work - WindowKeyPressFcn is still not called when I press a key. :(
Update 2:
Another thing that does not work:
chld = get(gcf, 'Children');
tp = get(chld, 'type');
chld = chld(strcmp(tp, 'uicontrol'));
set(chld, 'KeyPressFcn', #eegplot_readkey_new)
(eegplot_readkey_new is the function I use for reacting to keypresses)
Update 3:
And another one not working:
addlistener(gcf, 'WindowKeyPress', #eegplot_readkey_new);
Ok - I fiugred it out, although the solution is weird to say the least.
For some mysterious reason using linesmoothing undocummented property prevents WindowKeyPressFcn from being called. I have absolutely no idea why...
I am looking for a way to save 'everything' in the matlab session when it is stopped for debugging.
Example
function funmain
a=1;
if a>1
funsub(1)
end
funsub(2)
end
function funsub(c)
b = c + 1;
funsubsub(c)
end
function funsubsub(c)
c = c + 2; %Line with breakpoint
end
When I finally reach the line with the breakpoint, I can easily navigate all workspaces and see where all function calls are made.
The question
How can I preserve this situation?
When debugging nested programs that take a long time to run, I often find myself waiting for a long time to reach a breakpoint. And sometimes I just have to close matlab, or want to try some stuff and later return to this point, so therefore finding a way to store this state would be quite desirable. I work in Windows Server 2008, but would prefer a platform independant solution that does not require installation of any software.
What have I tried
1. Saving all variables in the workspace: This works sometimes, but often I will also need to navigate other workspaces
2. Saving all variables in the calling workspace: This is already better as I can run the lowest function again, but may still be insufficient. Doing this for all nested workspaces is not very convenient, and navigating the saved workspaces may be even worse.
Besides the mentioned inconveniences, this also doesn't allow me to see the exact route via which the breakpoint is reached. Therefore I hope there is a better solution!
Code structure example
The code looks a bit like this
function fmain
fsub1()
fsub2()
fsub3()
end
function fsub1
fsubsub11
fsubsub12
...
fsubsub19
end
function fsub2
fsubsub21
fsubsub22
...
fsubsub29
end
function fsub3
fsubsub31
fsubsub32
...
fsubsub39
end
function fsubsub29
fsubsubsub291
fsubsubsub292% The break may occur in here
...
fsubsubsub299
The break can of course occur anywhere, and normally I would be able to navigate the workspace and all those above it.
Checkpointing
What you're looking to implement is known as checkpointing code. This can be very useful on pieces of code that run for a very long time. Let's take a very simple example:
f=zeros(1e6,1);
for i=1:1e6
f(i) = g(i) + i*2+5; % //do some stuff with f, not important for this example
end
This would obviously take a while on most machines so it would be a pain if it ran half way, and then you had to restart. So let's add a checkpoint!
f=zeros(1e6,1);
i=1; % //start at 1
% //unless there is a previous checkpoint, in which case skip all those iterations
if exist('checkpoint.mat')==2
load('checkpoint.mat'); % //this will load f and i
end
while i<1e6+1
f(i) = g(i) + i*2+5;
i=i+1;
if mod(i,1000)==0 % //let's save our state every 1000 iterations
save('checkpoint.mat','f','i');
end
end
delete('checkpoint.mat') % //make sure to remove it when we're done!
This allows you to quit your code midway through processing without losing all of that computation time. Deciding when and how often to checkpoint is the balance between performance and lost time!
Sample Code Implementation
Your Sample code would need to be updated as follows:
function fmain
sub1done=false; % //These really wouldn't be necessary if each function returns
sub2done=false; % //something, you could just check if the return exists
sub3done=false;
if exist('checkpoint_main.mat')==2, load('checkpoint_main.mat');end
if ~sub1done
fprintf('Entering fsub1\n');
fsub1()
fprintf('Finished with fsub1\n');
sub1done=true;
save('checkpoint_main.mat');
end
if ~sub2done
fprintf('Entering fsub2\n');
fsub2()
fprintf('Finished with fsub2\n');
sub2done=true;
save('checkpoint_main.mat');
end
if ~sub3done
fprintf('Entering fsub3\n');
fsub3()
fprintf('Finished with fsub3\n');
sub3done=true;
save('checkpoint_main.mat');
end
delete('checkpoint_main.mat');
end
function fsub2
subsub21_done=false;subsub22_done=false;...subsub29_done=false;
if exist('checkpoint_fsub2')==2, load('checkpoint_fsub2');end
if ~subsub21_done
fprintf('\tEntering fsubsub21\n');
fsubsub21
fprintf('\tFinished with fsubsub21\n');
subsub21_done=true;
save('checkpoint_fsub2.mat');
end
...
if ~subsub29_done
fprintf('\tEntering fsubsub29\n');
fsubsub29
fprintf('\tFinished with fsubsub29\n');
subsub29_done=true;
save('checkpoint_fsub2.mat');
end
delete('checkpoint_fsub2.mat');
end
function fsubsub29
subsubsub291_done=false;...subsubsub299_done=false;
if exist('checkpoint_fsubsub29.mat')==2,load('checkpoint_fsubsub29.mat');end
if ~subsubsub291_done
fprintf('\t\tEntering fsubsubsub291\n');
fsubsubsub291
fprintf('\t\tFinished with fsubsubsub291\n');
subsubsub291_done=true;
save('checkpoint_fsubsub29.mat');
end
if ~subsubsub292_done
fprintf('\t\tEntering fsubsubsub292\n');
fsubsubsub292% The break may occur in here
fprintf('\t\tFinished with fsubsubsub292\n')
subsubsub292_done=true;
save(checkpoint_fsubsub29.mat');
end
delete('checkpoint_fsubsub29.mat');
end
So in this structure if you restarted the program after it was killed it would resume back to the last saved checkpoint. So for example if the program died in subsubsub291, the program would skip fsub1 altogether, just loading the result. And then it would skip subsub21 all the way down to subsub29 where it would enter subsub29. Then it would skip subsubsub291 and enter 292 where it left off, having loaded all of the variables in that workspace and in previous workspaces. So if you backed out of 292 into 29 you would have the same workspace as if the code just ran. Note that this will also print a nice tree structure as it enters and exits functions to help debug execution order.
Reference:
https://wiki.hpcc.msu.edu/pages/viewpage.action?pageId=14781653
After a bit of googling, I found that using putvar (custom function from here: http://au.mathworks.com/matlabcentral/fileexchange/27106-putvar--uigetvar ) solved this.
I have some code which I need to run both in MATLAB and in Freemat, using different service functions in each case. To make the whole thing portable I need to find a way to determine which functions to call at the start of my code, depending on which environment I am in.
How does one do that?
I was thinking of using the version command but no too sure if this is really robust.
Use verstring in the context of a try \ catch, the output in matlab will be an error while in Freemat it'll be something like "freemat 4.0", for example:
try
txt=verstring;
output='Freemat';
catch err
output='Matlab';
end
I would try to identify each, and give an error if unsure, or ask the user to identify it manually in such case:
% try to identify if it is freeMat
isDefinatelyFreeMat = false;
try
versionIdentifier=verstring;
if (strcmpi(versionIdentifier(1:7), 'FreeMat'))
isDefinatelyFreeMat = true;
end
catch e
end
% try to identify if it is Matlab
isDefinatelyMatlab = false;
try
versionIdentifier=ver;
if (strcmpi(versionIdentifier.Name, 'Matlab'))
isDefinatelyMatlab = true;
end
catch e
end
% if identification was not successful
if ((isDefinatelyFreeMat && isDefinatelyMatlab) || (~isDefinatelyFreeMat && ~isDefinatelyMatlab))
error('Was unable to identify software.');
% TODO: Ask user to identify software manually
end
I've been looking over, but I don't think it exists.
There is return to essentially force close your function, which is nice, but in my current script, I want if it does something incorrectly, to instead return to the start of the sub function that it exists in.
Are there any functions that exist already to do that, or will I have to make a system in order to let myself do that?
Instead of using return, error out of the function when something is "done incorrectly", then use try/catch in a while-loop:
while 1
try
myFunction();
break; % if myFunction() was successful, this will exit the while loop
catch
% do some sort of processing here, then go back to the while loop
end
end
The catch portion of the try/catch block will execute only if myFunction() had an error. return implies the function succeeded (whether or not it gave correct output is a different issue entirely).
Alternatively, you could put your function in a while-loop as suggested by #natan. Return some sort of error code, then check for that error code in the while condition.
Just use an while 1 loop to wrap around the whole function and continue when you want to restart the function.
Here is how I would do it if you are not looking for error handling, but just outcome handling
finishedSuccesfully = false
while ~finishedSuccesfully
output = myFunction();
finishedSuccesfully = evaluateoutput(output);
end