Pause Matlab without breakpoint - matlab

I have a script that is running a lot more time than I expected, it has been running for the last 3 days and only achieved 55% progress.
I would be perfectly happy to stop it at about 67% (I can live without the remaining 33%) But If I stop it now (ctrl+c or ctlr+break), I will lose all the data.
So is there a way to pause Matlab, perhaps into debug mode so I can check the variables without losing data?

The command (needs to be input manually before you start your function!)
dbstop if error
should catch a ctrl-c and leave you in debug mode.

I assume that you are doing something iteratively here and not relying on a built-in matlab function.
The way I usually solve the issue you have is to have an iteration counter and an if statement on that counter - when the condition is met, the statement has a breakpoint.
Something like this:
itCounter = 0;
itHalt = 100;
while (someCondition)
if (itCounter == itHalt)
itCounter = 0; %<= Put a breakpoint here
else
itCounter = itCounter+1;
end
% Here you calculate away whatever you need to calculate
end
This way, in every itHalt iterations you get a breakpoint. Also, since we're dealing with matlab, you can change the value of itHalt as you see fit as soon as the breakpoint is hit.

I'm thinking to an alternative solution:
Let's have a script which basically consists of a main loop.
The script periodically writes information about the execution status (e. g. the number of iteration done) into a log file.
Also, the script periodically reads a number from the input file
1 meaning "continue"
0 meaning "stop the script execution"
At the beginning of the simulation, 1 is written in the file.
The user can read the log and can decide, at a certain point, to stop the script.
To do it, he has just to change 1 to 0 in the file as save it.
An if section exemines the value read on it.
If 1, nothing appens and the script continues running.
If 0, a break statement terminates the main loop and the script stops.
Just before the break statement, in the if section, the script saves the whole workspace into a .mat file.
The user has now access to MatLab (he can evan close MatLab) and can look, for example, at the output files generated up to that moment by the script, process them, make somo plot and so on.
Then he might decide to continue the execution of the script from the point in which it has been stopped.
At the begining of the script, a variable controls the way the script has to be executed:
Mode 0: start from the beginning
Mode 1: resume the script
An if - else section maneges the user selection.
In particular, if Mode 1 is selected, the script loads the previously saved workspace (stored in a .mat file), then the value of some variables of the script are set to the old values.
As an example: the script was stopped when the index of the for loop was, say, 100.
if the for loop is defined as
for i=start_loop_1:100000
in the Mode 1 of the if, start_loop_1 is set to i+1 (the value of i was saved in the .mat file).
This allows the loop "continuing" the execution from the point in which it was stopped.
In order to effectively "resume" the running of the script, some other variables used in the script might require to be managed in the same way in the Mode 1 section.
In tha case of a "big", "complicated" script this might be difficult, but ... not impossible
This solution has been implemented in the following script.
I can see a potential criticality consisting in the unlucky case in which the user saves the file containing 1,0 at the same time the script reads it.
% Flag to select the running mode
% Mode 0: start from the beginning
% Mode 1: resume the running
continue_my_script=1;
% if "Mode 1" has been selected, the "old" workspace is loaded and some
% variables are properly set
if(continue_my_script == 1)
load my_script_data
start_loop_1=i+1;
start_loop_2=1;
% if Mode 0 has been selected some variables are set to their default value
else
start_loop_1=1;
start_loop_2=1;
% counter to enable writing of the log file
cnt_log=0;
% counter to enable reading the "go / no go" input file
cnt_go=0;
end
% Definition of the condition for writing the log file (in this case, a
% certain number of iterations")
log_iter=13;
% Definition of the condition for reading the "go / no go" input file (in
% this case, a certain number of iterations")
go_nogo_iter=20;
% Starting point of the "real script"
for i=start_loop_1:100000
% Increment the log counter
cnt_log=cnt_log+1;
% if "log_iter" have been done, update the log file
if(cnt_log == log_iter)
cnt_log=0;
t=clock;
fp=fopen('my_script_log.log','wt');
fprintf(fp,'i= %d at %d %d %f\n',i,floor(t(4)),floor(t(5)),t(6));
fclose(fp);
end
% Another loop of the script
for j=start_loop_2:100000
a(i,j)=sqrt(i);
end
% Increment the "read input file" counter
cnt_go=cnt_go+1;
% if "go_nogo_iter" have been done, read the go_nogo input file
if(cnt_go == go_nogo_iter)
cnt_go=0;
fp1=fopen('my_script_go.log','rt');
go_nogo=fscanf(fp1,'%d');
fclose(fp1);
% If the user made the decision to stop the execution, save the workspace
% and exit; otherwise ... do noting, just continue running
if(go_nogo == 0)
save my_script_data
break;
end
end
end
Hope this helps.

Okay, just to rephrase what I said in the comments with inputs from other users who commented. If your script is a MATLAB script, (Not a function), all the variables will be accessible from the workspace as long as you did not explicitly called 'clear' in the script if the script is stopped. In the usual case, ctrl+c will terminate the running script. The MATLAB variables used in the script will still be accessible from the MATLAB Workspace.

I don't think there is anything you can do while the code is already running, unless you put some hooks in place beforehand. Some of these other suggestions are good for that. Here is another one that I like: say you are leaving for the night, but coming back the next day, so you want your code to run for 14 hours and then stop and be waiting for you with however much data it got to in that time.
start_time = now;
final_time = start_time + 10/86400; % datenums are in days in Matlab, so +14/24 for 14 hours
% alternative: final_time = datenum('12-Aug-2015 09:00:00');
while now < final_time
% do work
disp('Working...')
pause(1)
end
% potential clean up code to save results
disp('Clean up code.')

Related

How can I run Matlab .m file repetitive in background?

I have project that was wrote in MATLAB. It has Main file like Main.m, I want to run Main.m repetitive every 1 Second in background.
I don't want to see any display and opening windows from MATLAB.
How can I do this ?
There are two steps to achieve this. First write some m script which calls your Main function every 1s. You can use a loop like this one. Getting the time via toc is important in case your main function takes some time to compute. An alternative are timers, which avoid any time drift (The loop is typically slightly above 1s, the timer will be 1s on average).
Once your MATLAB knows what to do, the question is who to start it. There is the -batch option:
Execute MATLAB script, statement, or function non-interactively.
MATLAB:
Starts without the desktop
Does not display the splash screen
Executes statement
Disables changes to preferences
Disables toolbox caching
Logs text to stdout and stderr
Does not display dialog boxes
Exits automatically with exit code 0 if script executes successfully.
Otherwise, MATLAB terminates with a non-zero exit code.
statement is MATLAB code enclosed in double quotation marks. If
statement is the name of a MATLAB function or script, do not specify
the file extension. Any required file must be on the MATLAB search
path or in the startup folder.
Use the -batch option in non-interactive scripting or command line
work flows. Do not use this option with the -r option.
To test if a session of MATLAB is running in batch mode, call the
batchStartupOptionUsed function.
Example: -batch "myscript"
This means MATLAB will not open any window, instead you see any output in the calling command line. How it looks on LINUX:
x#y ~ $ matlab -batch "1+1"
ans =
2
Assuming there is a top-level function in Main.m that you would like to execute once every 1 second, one possibility is to start an instance of Matlab and create another script that calls your function in a forever loop with a 1 second pause (making sure that this other script has Main.m file in the PATH so it can see it)
function run_main_forever()
while true
my_function()
pause(1)
end
end
You can have a .bat file start matlab in the background and run the script like this:
matlab -nodesktop -nosplash -r "cd('C:\Path\To\'); run_main_forever();"
See this link for further details on launching MATLAB without the desktop: https://blogs.mathworks.com/community/2010/02/22/launching-matlab-without-the-desktop/

is there a command to clear the worksheet from all output? (not using GUI)

I use worksheet (not document mode).
I know one can do Edit>Remove Output>From Worksheet to "Removes Maple output from all execution groups in a worksheet."
But I could not find a command to do this. I need to do this, since when I run a loop as in
for i from 1 to n do
some_function();
od
And the function above say prints to the screen (i.e. worksheet currently open) lots of information, then the worksheet slows down and I really also do not want to see the logging from all the calls accumulated any way. I just need to see prints from one iteration only at a time.
(Maple has other problems with having large output accumulate in worksheet also, but this is for another topic).
I'd like to do something like this
for i from 1 to n do
some_function();
delete_all_output_in_current_worksheet();
od;
So only one call's output shows up as the some_function is running.
In Matlab, this is easily done using clc which clears the command windows in Matlab.
Is there something like the above in Maple?
Maple 2018.1 on windows.
There is no programmatic way to clear all the output of the current worksheet.
But you can push the running result from some_function() (each time through the loop) to Embedded Components, eg. TextBox, MathContainer, etc.
You don't even have to manually insert such Components from the palettes. Instead you can use the DocumentTools:-Tabulate command to programmatically insert a tabulated collection of components right after the current Execution Group.
For example, as 1D code in a Worksheet, you could have these blocks of code in three separate Execution Groups.
restart;
and,
some_function:=proc(i)
int( sin(x)^i, x);
end proc:
Leafcutoff := 150:
and,
# Put all this in the same Execution Group
for i from 1 to 111 by 10 do
res[i] := some_function(i);
K := MmaTranslator:-Mma:-LeafCount(res[i]);
if K <= Leafcutoff then
L := res[i];
else
L := sprintf("LeafCount > %a",Leafcutoff);
end if;
DocumentTools:-Tabulate(
[["i","LeafCount","result"],
[sprintf("%a",i), K, L]],
':-weights'=[10,10,40],
':-fillcolor'=((T,i,jj)->`if`(i=1,"grey",
"white")),
':-widthmode'=':-pixels',
':-width'=600);
Threads:-Sleep(1.5); # delay at least 1.5 sec
end do:
DocumentTools:-Tabulate([[]]):
I put in a time-delay of 1.5 seconds just to illustrate it working. You can adjust that, or remove it.
The last call to Tabulate is only there to blank it out, when the loop is finished.
The GUI Table inserted by Tabulate actually appears in a region right after the Execution Group. Only one such region appears, per Execution Group. Basically, each call to Tabulate overwrites that region.
If you changed the end do: to end do; then all the regular output would also be shown, as usual for a loop.

How to use pause with openvar in a for loop

Using the following code:
tmpTable = table([1;2;3]);
for i = 1:5
openvar tmpTable
pause
end
When I run the for loop, all I get is a blank screen in the Variable Editor, except the dimensions of the table are displayed correctly. If I break from the for loop the table displays correctly.
My question is, how do I make this table display programmatically in the for loop, with a pause like command that allows me to inspect the table before moving onto the next one?
What's happening is that pause is pausing the main MATLAB thread which is why you aren't seeing anything in the Variable Editor. You have to make MATLAB enter debug mode if you want the main MATLAB thread to be free.... or of course break the loop as you have discovered.
A "hackish" way to get things going is to insert a keyboard statement instead of pause to force MATLAB to go into debug mode. Once you're there, you'd have to use dbcont to continue onto the next iteration of the loop. This will make MATLAB enter debug mode again as the keyboard statement will be encountered again thus freeing the main thread. This repeats until the last iteration.
Therefore:
tmpTable = table([1;2;3]);
for i = 1:5
openvar tmpTable
keyboard; %// Change
end
You will then see K>> once you execute the first iteration of the loop when you look at the Command Prompt. This signifies that you are in debug mode. To proceed to the next iteration, type in dbcont in the Command Prompt and push ENTER. You can reuse the last command by pushing the Up arrow on your keyboard then push ENTER again and keep doing this until the last iteration of your loop. You will unfortunately have to click back in the Command Prompt as the focus will be placed on the Variable Editor before you enter in the command again. If at any time you want to quit debug mode, use dbquit. This will terminate any code execution and bring you back to the Command Prompt.
This is the only way really to free up the main MATLAB thread at each iteration that I know of.

Seeing which part of code MatLab is currently running [duplicate]

Is there any way to stop the execution of a matlab program from the debugger like ctrl+c does, but then being able to continue execution (like you can in say c#)?
If not, is there any better way to workaround this other than trying to pre-emptively set break points or dbstop statements in your matlab code?
I would like to be able to interrupt a long running simulation to look at the current state and then continue the simulation.
The two options I'm currently using/considering are
dbstop commands (or (conditional) breakpoints) in the code.
Drawback is that sometimes I don't want to stop the simulation for a few hours, sometimes want to stop after only a few seconds (and I don't necessarily know that in advance) and this doesn't work well with this approach: If I set the break condition to break every 5 minutes, I can't leave matlab running for hours without interaction. If I set the condition to higher, I have to wait too long for the condition to hit.
include code to save the workspace every few seconds/minutes and import the workspace into a second matlab instance. Drawback is that this is a huge hassle and also doesn't necessarily allows me to resume the simulation with the state of the saved workspace then step through the code for a few iterations.
I'm hoping there is a better solution than either of the 2. Thanks for any advice!
Edit: I think what I'm going to do is write simple matlab function that checks an environment variable or a file on disk every iteration and calls dbstop if I set a flag in this file or env. This way I can control when (and if needed which of several) the breakpoint hits from outside matlab by editing the file. Messy, but should work.
This is not necessarily the best way, but you could simulate a file-based signal/interrupt framework. It could be done by checking every once in a while inside the long simulation loop for the existence of a specific file. If it does, you enter interactive mode using the keyboard command.
Something along the lines:
CHECK_EVERY = 10; %# like a polling rate
tic
i = 1; %# loop counter
while true %# long running loop
if rem(i,CHECK_EVERY) == 0 && exist('debug.txt','file')
fprintf('%f seconds since last time.\n', toc)
keyboard
tic
end
%# ... long calculations ...
i = i + 1;
end
You would run your simulation as usual. When you would like to step in the code, simply create a file debug.txt (manually that is), and the execution will halt and you get the prompt:
2.803095 seconds since last time.
K>>
You could then inspect your variables as usual... To continue, simply run return (dont forget to temporarily rename or remove the file). In order to exit, use dbquit
EDIT: Just occurred to me, instead of checking for files, an easier solution would be to use a dummy figure as the flag (as long as the figure is open, keep running).
hFig = figure; drawnow
while true
if ~ishandle(hFig)
keyboard
hFig = figure; drawnow
end
%# ...
pause(0.5)
end
With the release of R2016a, you can just hit the Pause button in the code editor and it will halt right away. The keyboard shortcut is Ctrl+F5.
To pause the execution of a program while it is running, in the Editor tab, click the Pause button. MATLAB pauses execution at the next executable line*.
When your code is running, the Start button will turn into a pause:
Another change with this release is the ability to add/remove breakpoints while running. Previously you couldn't do this, apparently.
You can set a conditional breakpoint in the MATLAB Editor. You can also use DBSTOP to do this. For example, this will set a conditional breakpoint in the file myFcn at line 20 which will stop execution when a loop variable i is a multiple of 500:
dbstop in myFcn.m at 20 if rem(i,500) == 0
Then you can continue execution after you inspect some of your variables.
If saving the workspace to a file is a good proxy for what you want, how about making a simple GUI with a toggle button. In your code, check the state of the button. If the button is depressed, save the state, update a static text to reflect time stamp of last save, unpress the button. Optionally, have a conditional breakpoint based on the state of that toggle button.
Here is an alternate solution using the waitinput File Exchange submission.
The advantage is that you can use it from whithin the current session or in cases where it is troublesome to set up a file. Also it won't leave a file behind on the computer.
The downside is there as well unfortunately, you need to wait for the checking moment before you can terminate and it costs a little bit of time.
for t = 1:10
pause(3) %Doing some calculations
str = waitinput('Enter 1 if you want to stop ',5);
if ~isnan(str)
keyboard; % Enter dbcont if you want to continue from here
end
['moving on, it is now: ' datestr(now)]
pause(3) %Doing some more calculations
end
If you want, you can prevent lines being printed to the screen. In this case you need to enter the input at the time the figure window is open (Look in your start bar on windows).
To summarize, the short code that you can put somewhere like a conditional breakpoint would be:
if ~isnan(waitinput('',5))
keyboard;
end
After certain version (I don't know which one exactly):
Windows: Ctrl + F5
Mac: Command + F5 (I guess)
Unix: I am looking for answer too
After 2016a, there is a button for that on the interface too.

Replacing Matlab title name with process Id does not work with startup.m

I want to start matlab and replace the title of matlab window to process id. So I created the following startup.m file:
cd E:\matlab_files\
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
jDesktop.getMainFrame.setTitle(['PID:' num2str(feature('getpid'))]);
Now, matlab changes folder to E:\matlab_files but process Id is not replaced. Once matlab has started and I execute 2nd and 3rd line of startup.m, then the title of matlab window is replaced by process id.
Please explain the cause of this behaviour.
I am using Matlab 2009b.
All of the graphics haven't finished initialising -> so you are not able to replace the title (I assume it hasn't yet been created).
You can check this by trying to disp the jDesktop.getMainFrame.getTitle to your startup.m and you will see that that is empty.
Thats the explanation as to why - you haven't asked for a fix - but I assume you want one!! ;)
You can fix this by using a timer - note I put 60 seconds in the timer below - but it could be a lot less.
function startup
if ~isdeployed % its agood practice to use this incase you ever compile your codes.
cd E:\matlab_files\
timerFcn = #updatetitle;
tfcn = timer('StartDelay', 60, 'TimerFcn', timerFcn );
start(tfcn)
end
end
function updatetitle(varargin)
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
jDesktop.getMainFrame.setTitle(['PID:' num2str(feature('getpid'))]);
end
I observe the same behavior. Note that startup.m is run from matlabrc.m while MATLAB is still starting up. You could experiment by putting your code in matlabrc.m, although I can't recommend editing that file.
There are a few possible reasons:
After startup.m runs, MATLAB may overwrite the title of the matlab window.
Java may not be fully available during startup, and your code clearly relies on Java.