Creating Continuous Output in Matlab - matlab

I have a script that is something like this:
i = 1;
while i <10000
a = input('enter a ');
c(i) = a;
i = i + 1;
end
I am trying to have 'a' be saved in 'c' about every second regardless of how long the user takes to input the value or anything else going on in the loop. So for example, lets say the user inputs 3 for 'a' waits 2 secs, then inputs 6 for 'a' then waits 3 secs then inputs 12 then nothing for a while, 'c' would look like this:
c = 3 3 6 6 6 12 12 12 12 12...
Right now, 'c' looks like this:
c = 3 6 12...
which is NOT what I want. Any suggestions? it doesn't have to be a second on the dot but i want continuous output.

Your question is interesting, but is not very well specified. I'm assuming the following:
Each input should be immediately appended to c, and repeatedly appended again every second until a new value is entered, which resets the time count. It's not clear from your question if you want that initial, fixed "commit" of the new input to c or not.
You want the updated c to be automatically displayed, according to your comment to a now deleted question. You should have stated that in your question to begin with.
Then, you can use a timer object that is stopped and restarted when each new input value has been entered. The timer is configured to wake up every second. When it wakes, it appends the latest input value a to vector c and displays it. Care should be taken to stop and delete the timer when no longer needed. In addition,
I'm considering empty input as an exit signal; that is, empty input indicates that the user wants to finish even if the iterations have not been exhausted. Using Ctrl-C to abort input is not viable, because the timer would keep running. I don't know anmy way to intercept Ctrl-C.
I'm removing the prompt string from the input function input as it interferes with the automatic display of the updated c vector.
User input blocks execution of the program. If you want other operations done with c as it's being updated by the timer, include them in its 'TimerFcn' function. Currently that function is just 'c = [c a]; disp(c)' (append the input and display it).
Code
c = []; % initiallize
t = timer('ExecutionMode', 'fixedRate', ... % Work periodically
'Period', 1, ... % Every 1 second...
'TimerFcn', 'c = [c a]; disp(c)', ... % ... append latest value to c
'ErrorFcn', 'delete(t)'); % If user ends with Ctrl-C, delete the timer
i = 1;
done = false;
clc % clear screen
while i < 10 & ~done
a = input(''); % Input new value. No prompt string
stop(t) % stop appending previous a
if isempty(a)
done = true; % no more iterations will not be run
else
start(t) % start timer: appends current a, and repeats every second
end
i = i + 1;
end
delete(t) % stop and delete timer
clear t % remove timer from workspace
Example
Here's a gif with an example run, where I'm inputting values 10, 20, 30, 40 with different pause times, and exiting with an empty input.

Related

How to make for loops run faster - Psychtoolbox in matlab

I created a MATLAB code using Psychtoolbox to make an experiment.
Everything works as I intended but it seems the initial loading of the experiment takes too long. The task is a simple yes/no response task whether the target word('probe') appeared in the previous set of word stimuli.
I put basic intro text as an image and then wait for any keypress to start the experiment but it will take about 40 seconds to actually begin the first trial after any keystroke. I want to make it work without any delay. It should start its first trial immediately after any keystroke.
I checked the timestops with GetSecs() on numerous positions in the code and it was not anything to do with loading stimuli or initial setting of the experiment before the for loop I attached below.
To make things look simpler, I changed some of the variables into actual numbers I used. I can gurantee that it is not due to large stimuli size since it is only 1500 words. Once the for loop starts, it goes smoothly but it takes 40 seconds to actually start the first trial so I think it is something to do with a specific function in the for loop or the way I built it.
Please let me know if anything is too vague or unclear. I will do my best to make things read better.
Edit: I minimalized the code leaving only the function names used in Psychtoolbox. I left the functions I used in between loops to let you know if they could cause any delay. It will not be possible to run this without Psychtoolbox installed so I guess you can briefly examine the structure of the code.
for trial = 1:250
for i = 1:6
DrawFormattedText();
Screen();
WaitSecs(0.5);
end
DrawFormattedText();
flipTime = Screen();
WaitSecs(0.5);
DrawFormattedText();
flipTime = Screen();
rt = 0;
resp = 0;
while GetSecs - flipTime < 3
clear keyCode;
RestrictKeysForKbCheck();
[keyIsDown,secs,keyCode] = KbCheck;
respTime = GetSecs;
pressedKeys = find(keyCode);
% ESC key quits the experiment
if keyCode(KbName('ESCAPE')) == 1
clear all
close all
sca
return
end
% Check for response keys
if ~isempty(pressedKeys)
for i = 1:2
if KbName(i) == pressedKeys(1)
resp = i;
rt = respTime - flipTime;
end
end
end
% Exit loop once a response is recorded
if rt > 0
break;
end
end
if rt == 0 || rt > 3 % 3 second limit for subjects to react to the probe stimuli
DrawFormattedText();
Screen();
WaitSecs(1);
end
Screen();
vbl = Screen();
WaitSecs(1);
% Record the trial data into output data matrix
respMat{1, trial} = trial;
respMat{2, trial} = resp;
respMat{3, trial} = rt;
end

Continue ‘for’ loop with the existing variables in Matlab

I have a Matlab script including a for loop which loos like the following:
for k = 1:10
c = myfun(k,a,b);
result{k} = c;
end
Right now, the problem is that during the for loop, sometimes myfun() may have errors and stop. After fixing the error in myfun(), how can I continue to run with the existing value of variables? The reason is that myfun() will take a very long time to get the result and the previous results are right.
For example, if a error happens when k == 4, then I save all the variables in the current workspace. I set a breakpoint at c = myfun(k,a,b); and restore the saved variables, but I find that in the next loop, k will be 2 instead of 5 as I want. Matlab is not allowed to modify the value of k during the for loop I think. I have tested this for a few times.
How can I continue the for loop with some existing data?
You cannot change your for loop iterator programmatically inside of the loop.
For example:
for ii = 1:3
disp(ii)
ii = 3;
end
Prints:
1
2
3
If you're going to be modifying code based on errors received, dbstop if error is not going to be beneficial because it will not reflect changes in your code until the debugger is exited and your code executed again (unless you execute manually in the debugger). If you're not modifying code you could potentially use a try/except clause to catch fixable issues.
If you're loading data for a later index and then restarting, you can change where your for loop begins, or use a while loop (if appropriate).
For example:
% Load data here
for ii = 3:3
disp(ii)
end
Prints 3.
Where the while interpretation would be:
% Load data here
ii = 3
while ii <= 3
disp(ii)
ii = ii + 1;
end
For the same result.
On solution can be first catch the exception likes the following and pass from them:
bug = [];
for k = 1:10
try
c = myfun(k,a,b);
result{k} = c;
catch
warning('some bug for the following values:');
display([k a b]);
bug = [bug; k a b];
result{k} = NaN;
end
end
Then iterate over bug to compute missing information after debugging. This solution works when your algorithm is not dependent on the previous value of the result (or is not recursive).

Prompt user input, time 4 seconds and prompt again

I have a matrix testNumbers = [1, 3, 8, 6, 9, 7].
What I want to do now is to make the user prompt a input and check if that input is equal to testNumbers(1), if it is do something (for later, %do something) and after 4 seconds continue to make the user input a number again but this time check if testNumbers(2) is equal to the user prompt. This will then continue until the length(testNumbers) has ended.
Can this be done? I assume a for loop has to be used, but I am totally new and therefore a example would be great. Then I can continue building this.
A example:
testNumbers = [1, 3, 8, 6, 9, 7]
A timer starts (4sec)
User inputs 1 within t <= 4 sec
Do something like disp('Correct')
User inputs 3 within t <= 4 sec
Do something like disp('Correct')
User should input 8 but time runs out
Do something like disp('time run out')
User inputs 5 within t <= 4 sec but is wrong, shall be 6
Do something like disp('Wrong')
Continue like this until the matrix ends...
You can use tic and toc to measure the elapsed time between two points. You can place the tic before the user input (to start the timer), and then use a toc wherever you want to check the time that has elapsed since that point. You can use multilple toc's and they will all refer to the closest tic.
% Start the timer
tic
% Prompt the user for input
value = input('Enter a number:');
elapsed_time = toc;
% If the response took more than 4 seconds
if elapsed_time > 4
disp('took too long')
end
If instead (as your title states) you want to wait 4 seconds, you can use pause to pause execution of your program for a given amount of time
input('Enter a number:');
pause(4) % Pause for 4 seconds
% Do something else

Run the for loop only once Matlab

total_Route = zeros(4,4);
tmp = evalin('base', 't'); % i initialise t in the Workspace with the value 1
if(tmp==5)
tmp=1;
end
total_Route(tmp,1) = Distance_Traveled_CM;
total_Route(tmp,2) = Hauptantrieb_Verbrauchte_Energie_CM;
total_Route(tmp,3) = Nebenaggregate_Verbrauch_Real_CM;
total_Route(tmp,4) = t;
Total_Distance_Traveled_CM = sum(total_Route(:,1));
set(handles.edit3, 'string',Total_Distance_Traveled_CM);
Total_Hauptantrieb_Verbrauchte_Energie_CM = sum(total_Route(:,2));
set(handles.edit4, 'string',Total_Hauptantrieb_Verbrauchte_Energie_CM);
Total_Nebenaggregate_Verbrauch_Real_CM = sum(total_Route(:,3));
set(handles.edit5, 'string',Total_Nebenaggregate_Verbrauch_Real_CM);
%% Index
set(handles.edit15, 'string',tmp);
assignin('base', 't', tmp + 1); % with this line i can increment "t" after each pass
guidata(hObject,handles);
Sorry that I did not explain my problem well.
#Sardar_Usama I want to run the loop only once but t should be incremented after each time I click on my Button.
# Sembei Norimaki end is at the end of my codes, have forgotten to write it in my question
#Patrik & #Dennis Jaheruddin let me explain my problem again
I created a Matrix with 4×4 Elements with the Goal to save the results of each my Variable (Total_Distance_Traveled_CM, Total_Hauptantrieb_Verbrauchte_Energie_CM etc...) after each Simulation in the element of my Matrix (See image below).
I want by pressing a button (on my GUI) to get always the sum of each Column.
Example
The first pass: t = 1--> Distance_Traveled(1,1) is 900 the GUI will take through clicking on the Button, the sum of the first column (which is 900+0+0+0) and write it in a static test.
The second pass t = 2--> Distance_traveled(2,1) is 800 the GUI will take the sum of the first column (which is 900+800+0+0) and write it in a static test and the same thing should happen with the other column.
This should continue until t = 4 i.e. until it does the same thing for each column, then it should reset.
I hope, I have explained my problem better this time and I apologize for my bad English.
I appreciate any help.
Based on your code fragment the for loop is only called once.
However, the contents of the for loop are ran for four times. (first for i=1 then for 1=2 etc..)
If you only want to run one of these options the solution is very simple:
i = 1
yourLoopContent
If i is always 0 the first time, and you always want to run it for the current i, it would also be simple:
yourLoopContent
i = i+1;
However if i may not be set properly the first time, things get messy. This is because i is by default defined as the square root of minus 1.
Therefore I would recommend you to use a different letter like t instead. Then you could do this:
if ~exists(t)
t=0;
end
yourLoopContent %Everywhere using t instead of i
t = t+1;
In general you may want to avoid i as an index to stay clear of complex number issues.
I'm not sure if I got your question correctly, but it seems to me that what you look for is a cumulative sum. This can be done either buy summing on 1:t or by using cumsum. I'm not sure why you use a loop, but if this is only for the summing then cumsum can replace that.
Here is some example in your code:
total_Route = zeros(4,4);
% I commented below what is not part of the question
for t = 1:4
total_Route(t,:) = [Distance_Traveled_CM,
Hauptantrieb_Verbrauchte_Energie_CM,
Nebenaggregate_Verbrauch_Real_CM,
t];
% the following line compute the comulative sum from the top of each
% column to every element in it, so cs_total_Route(3,2) is like
% sum(total_Route(1:3,2)):
cs_total_Route = cumsum(total_Route);
Total_Distance_Traveled_CM = cs_total_Route(t,1); % OR sum(total_Route(1:t,1))
% set(handles.edit3, 'string',Total_Distance_Traveled_CM);
Total_Hauptantrieb_Verbrauchte_Energie_CM = cs_total_Route(t,2); % OR sum(total_Route(1:t,2))
% set(handles.edit4, 'string',Total_Hauptantrieb_Verbrauchte_Energie_CM);
Total_Nebenaggregate_Verbrauch_Real_CM = cs_total_Route(t,3); % OR sum(total_Route(1:t,3))
% set(handles.edit5, 'string',Total_Nebenaggregate_Verbrauch_Real_CM);
% set(handles.edit15, 'string',t);
end
And here is a quick look on what cumsum does (with some random numbers for total_Route):
total_Route =
671 4.6012 1.0662 1
840 3.6475 0.58918 2
354 8.6056 2.1313 3
893 4.1362 2.0118 4
cs_total_Route =
671 4.6012 1.0662 1
1511 8.2487 1.6554 3
1865 16.854 3.7867 6
2758 20.991 5.7985 10
Is this what you looked for?

Matlab: Print progress from parfor loop

I run a lot of long simulations in Matlab, typically taking from a couple of minutes to a couple of hours, so to speed things up I decided to run the simulations simultaneously using a parfor loop.
arglist = [arg1, arg2, arg3, arg4];
parfor ii = 1:size(arglist, 2)
myfun(arglist(ii));
end
Everything worked just fine, except for one thing: the progress printing. Since each simulation takes a lot of time, I usually print progress using something like
prevlength = 0;
for ii = 1:tot_iter
% Some calculations here
msg = sprintf('Working on %d of %d, %.2f percent done', ii, tot_iter, ii/tot_iter);
fprintf(repmat('\b', 1, prevlength))
fprintf(msg);
prevlength = numel(msg);
end
but, as could be expected, when doing this inside a parfor loop, you get chaos.
I have googled a lot in search of a solution and have found a bunch of "parfor progress printers" like this one. However, all of them print the progress of the entire parfor loop instead of showing how far each of the individual iterations have come. Since I only have about 4-8 iterations in the parfor loop, but each iteration takes about an hour, this approach isn't very helpful to me.
The ideal solution for me would be something that looks like this
Working on 127 of 10000, 1.27 percent done
Working on 259 of 10000, 2.59 percent done
Working on 3895 of 10000, 38.95 percent done
Working on 1347 of 10000, 13.47 percent done
that is, each simulation gets one line showing how far it has run. I'm not sure though if this is possible at all, I can at least not imagine any way to do this.
Another way would be to do something like this
Sim 1: 1.27% Sim 2: 2.59% Sim 3: 38.95% Sim 4: 13.47%
that is, show all the progresses on the same line. To do this, you would need to keep track of what position on the line each simulation is to write on and write there, without erasing the other progresses. I can't figure out how this would be done, is this possible to do?
If there is some other solution to my problem (showing the progress of each individual iteration) that I haven't thought of, I'd be happy to hear about it.
Since this is the first time I ask a question here on SO it is quite possible that there is something that I have missed; if so, please feel free to comment below.
Edit
After receiving this answer, I thought that I should share how I used it to solve my problem since I didn't use it exactly as in the answer, in case someone else encounters the same problem.
Here is a small test program with basically the same structure as my program, making use of the progress bar (parfor_progress) mentioned in the answer:
function parfor_progress_test()
cpus = feature('numCores');
matlabpool('open', cpus);
cleaner = onCleanup(#mycleaner);
args = [1000, 1000, 1000, 1000];
m = sum(args);
parfor_progress(m);
parfor ii = 1:size(args,2)
my_fun(args(ii));
end
parfor_progress(0);
end
function my_fun(N)
for ii = 1:N
pause(rand*0.01);
parfor_progress;
end
end
function mycleaner
matlabpool close;
fclose all;
end
Simple Progress Bar
Something like a progress bar could be done similar to this...
Before the parfor loop :
fprintf('Progress:\n');
fprintf(['\n' repmat('.',1,m) '\n\n']);
And during the loop:
fprintf('\b|\n');
Here we have m is the total number of iterations, the . shows the total number of iterations and | shows the number of iterations completed. The \n makes sure the characters are printed in the parfor loop.
Progress Bar and Percentage Completion
Otherwise you could try this: http://www.mathworks.com/matlabcentral/fileexchange/32101-progress-monitor--progress-bar--that-works-with-parfor
It will display a progress bar and percentage completion but can be easily modified to just include the percentage completion or progress bar.
This function amends a character to a file on every iteration and then reads the number of characters written to that file which indicates the number of iterations completed. This file accessing method is allowed in parfor's.
Assuming you correctly add the above to your MATLAB path somehow, you can then use the following:
arglist = [arg1, arg2, arg3, arg4];
parfor_progress(size(arglist, 2)); % Set the total number of iterations
parfor ii = 1:size(arglist, 2)
myfun(arglist(ii));
parfor_progress; % Increment the progress counter
end
parfor_progress(0); % Reset the progress counter
Time to Completion and Percentage Completion
There is also a function called showTimeToCompletion() which is available from: https://www.soundzones.com/software/sound-zone-tools/
and works alongside parfor_progress. This function allows you to print a detailed summary of the progress of a parfor loop (or any loop for that matter) which contains the start time, length of time running, estimated finish time and percentage completion. It makes smart use of the \b (backspace) character so that the command window isn't flooded with text. Although not strictly a progress 'bar' it is perhaps more informative.
The third example in the header of the function file,
fprintf('\t Completion: ');
showTimeToCompletion; startTime=tic;
len=1e2;
p = parfor_progress( len );
parfor i = 1:len
pause(1);
p = parfor_progress;
showTimeToCompletion( p/100, [], [], startTime );
end
outputs the following to the command window:
Completion: 31.00%
Remaining: 00:00:23
Total: 00:00:33
Expected Finish: 3:30:07PM 14-Nov-2017
Useful for estimating the completion of a running simulation, especially one that may take hours or days.
Starting in R2013b, you can use PARFEVAL to evaluate your function asynchronously and have the client display progress updates. (Obviously this approach is not quite as simple as adding stuff to your PARFOR loop). There's an example here.
The Diary property of the Future returned by PARFEVAL is updated continuously while processing, so that might also be useful if you have a small number of large tasks.
Starting in R2017a, you can use parallel.pool.DataQueue and afterEach to implement a waitbar for parfor, like so:
if isempty(gcp('nocreate'))
parpool('local', 3);
end
dq = parallel.pool.DataQueue;
N = 10;
wb = waitbar(0, 'Please wait...');
% Use the waitbar's UserData to track progress
wb.UserData = [0 N];
afterEach(dq, #(varargin) iIncrementWaitbar(wb));
afterEach(dq, #(idx) fprintf('Completed iteration: %d\n', idx));
parfor idx = 1:N
pause(rand());
send(dq, idx);
end
close(wb);
function iIncrementWaitbar(wb)
ud = wb.UserData;
ud(1) = ud(1) + 1;
waitbar(ud(1) / ud(2), wb);
wb.UserData = ud;
end
after exploring #Edric answer I found that there is an example in the Matlab documentation that exactly implements a waitbar for a pareval loop. Check help FetchNext
N = 100;
for idx = N:-1:1
% Compute the rank of N magic squares
F(idx) = parfeval(#rank, 1, magic(idx));
end
% Build a waitbar to track progress
h = waitbar(0, 'Waiting for FevalFutures to complete...');
results = zeros(1, N);
for idx = 1:N
[completedIdx, thisResult] = fetchNext(F);
% store the result
results(completedIdx) = thisResult;
% update waitbar
waitbar(idx/N, h, sprintf('Latest result: %d', thisResult));
end
% Clean up
delete(h)