For work, I need to write a Matlab program that will trigger a stimulus (TTL pulse) after set amounts of time. First, I need the program to wait 32 mins. Then, I want it to execute the stimulus pulse, wait 5 seconds, execute the stimulus pulse again, then wait an additional 115 seconds. I need it to do 5 iterations of this (excluding the 32 min wait period).
I am terrible at Matlab syntax. I worked with Python a little bit, but this particular function requires Matlab because it has a toolkit that works with the stimulus generator.
For what it's worth, the trigger output as it appears in existing code looks like this:
if i > 1
% insert output trigger for page 1
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
end;
Here's my crappy attempt at the loop part of the code, which is giving me all kinds of syntax errors:
% Use for loop for 5 iterations
for i = 1:5
% trigger TTL pulse
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
% trying to use tic and toc as a timer that resets each iteration
timerID = tic;
% I thought to use a while loop for the timing
% 5 second wait period
while true
if(toc(timerID)>5)
break;
end
% trigger TTL pulse again
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
% 115 second wait period
while true
if(toc(timerID)>120)
break;
end
end
That's all I've got. Any help at all would be greatly appreciated. Feel free to tell me if I need to use a completely different approach as I know I'm terrible at Matlab. Thank you.
You can use pause for this. Try something like this:
pause(32*60); % Pause 32 minutes
for ii = 1:5
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
pause(5);
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
pause(115);
end
Related
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
I need to merge around 50 million small Matlab matrices. Using a script like the below seems never to finish. Is there a faster way? I'd be willing to try a non-Matlab Route if that were faster.
main_data_a = zeros(10000000, 3);
main_data_b = zeros(10000000, 3);
main_data_c = ones(10000000, 1);
for i=1:1:10000000
try
to_load=sprintf('data/output%d.mat',i);
load(to_load);
catch
end;
if sum(a) ~= 0
main_data_a(i,:) = a;
main_data_b(i,:) = b;
main_data_c(i,:) = c;
end;
end;
Here is a complete example showing "parfor" usage.
disp('Using for-loop')
tmpData = zeros(100000,1);
tic
for i = 1:length(tmpData)
tmpData(i) = max(max(eig(i*ones(100,100)))); % Some operation
end
toc
disp('Using parfor-loop')
tic
parfor (i = 1:length(tmpData))
tmpData(i) = max(max(eig(i*ones(100,100)))); % Some operation
end
toc
The above code resulted in the following timings on my machine.
Using for-loop
Elapsed time is 32.792182 seconds.
Using parfor-loop
Elapsed time is 7.673821 seconds.
However, if some simple calculations are carried out inside the for (or parfor) loop body then "for-loop" runs faster than "parfor". For example, if you replace tmpData(i) = max(max(eig(i*ones(100,100)))); with tmpData(i) = i; then you could see that for-loop performs better.
i am somekind of "advanced" beginner in programing. I couldn't find answer to my question, i found this, MATLAB Speed Difference in Identical Code, but it is not exactly what i'm looking for. I have the following problem, my script or function consists of couple of segments, when i run them manually with Run Section, i need something like 15 sec. including scroling and clicking. When i start them as one function i need 72 sec. The code is:
a=diff(Min_ZR);
b=zeros(38000000,1)*NaN;
i=1;
while i<length(a)
if a(i)==1;
b(i)=1;
i=i+1;
else
b(i)=0;
i=i+1;
end
end
b(i:end) = [];
%%
iL=2;
kL=2;
L1=zeros(38000000,1)*0;
while iL<length(test_L)
if test_L(iL)==1
L1(iL)=L1(kL-1)+1;
iL=iL+1;
kL=iL;
else
L1(iL)=L1(iL-1);
iL=iL+1;
end
end
L1(iL:end)=[];
%%
iR=2;
kR=2;
L2=zeros(38000000,1)*0;
while iR<length(test_R)
if test_R(iR)==1
L2(iR)=L2(kR-1)+1;
iR=iR+1;
kR=iR;
else
L2(iR)=L2(iR-1);
iR=iR+1;
end
end
L2(iR:end)=[];
%%
iZ=2;
kZ=2;
ZR=zeros(38000000,1)*0;
%while i<length(test_R)
while iZ<length(b)
if b(iZ)==1
ZR(iZ)=ZR(kZ-1)+1;
iZ=iZ+1;
kZ=iZ;
else
ZR(iZ)=ZR(iZ-1);
iZ=iZ+1;
end
end
ZR(iZ:end)=[];
%%
L1=L1/4;
L2=L2/4;
ZR=ZR/8*34/22;
i=1;
diff_L1=zeros(38000000,1)*NaN;
diff_L2=zeros(38000000,1)*NaN;
while i<=length(ZR)
diff_L1(i)=L1(i)-ZR(i);
diff_L2(i)=L2(i)-ZR(i);
i=i+1;
end
diff_L1(i:end)=[];
diff_L2(i:end)=[];
l=length(ZR);
Drehmoment=zeros(l,1);
Drehmoment(1:10000)=100;
Drehmoment(10001:end)=380;
%%
figure % new figure
[hAx,hLine1,hLine2] = plotyy(ZR,diff_L2,ZR,Drehmoment);
title('Zahnradwandern 30.03.2016')
xlabel('Gesamtumdrehungen /1 ')
ylabel(hAx(1),'Differenzumdrehungen /1 ') % left y-axis
ylabel(hAx(2),'Drehmoment / Nm') % right y-axis
set(hAx(1),'Xlim',[0 1050000])
set(hAx(2),'Xlim',[0 1050000])
set(hAx(1),'Xtick',0:50000:1050000)
set(hAx(1),'XTickLabel',{'0','','100000','','200000','','300000','','400000','','500000','','600000','','700000','','800000','','900000','','1000000',''})
set(hAx(1),'Ylim',[-2 38])
set(hAx(1),'YTick',-2:2:38)
set(hAx(2),'YTick',0:20:400)
set(hAx(2),'Ylim',[0 400])
grid on
hold on
plot (ZR,diff_L1,'color','g')
hold off
legend('Differenzumdrehungen PL2','Differenzumdrehungen PL1','Antriebsmoment')
For each section i need less then 1 or 2 sec. just for the Plot i need a bit more, but as i wrote 15 sec. tops it is nowhere near to 72 sec. that i get when i Run the Function.
Thank you in advance.
I've found the Problem, if i start the program with run and time, it tells me 72 sec, or after i used hint 4. from Crowley 60 sec. It also says that the "Run and Time fkt" don't use resources but if i just Run the program it completes in under 10sec.
Does your code improve it's performance when:
you change indexes i to ii. i and j are reserved for imaginary units;
define b=nan(length(a),1); and L1=zeros(length(test_L),1); and ommit b(:,end)=[]; and L1(iL:end)=[];;
use for ii=1:length(a) instead of while loop;
use b=zeros(length(a),1);b(a==1)=1; instead of whole while loop;
use diff_L=L1-R1 instead of while loop;
use Drehmoment=ones(l,1)*380;Drehmoment(1:100000)=100;?
These are just suggestions where you can loose your time...
EDIT regarding to hbadert's comment
Have you tried:
Block=1;
BlockTic(Block)=tic;
%%Block 1
BlockToc(Block)=toc;
Block=Block+1;
BlockTic(Block)=tic;
%%...
BlockToc(Block)=toc;
AllTime=BlockToc(end)-BlockTic(1);
Times=BlockToc-BlockTic;
disp(['Global time: ',num2str(AllTime)])
disp('Block times:')
disp(Times')
I have a for loop like this
for t = 0: 1: 60
// my code
end
I want to execute my code in 1st, 2nd, 3rd, ..., 60th seconds. How to do this? Also how can I run my code at arbitrary times? For example in 1st, 3rd and 10th seconds?
What you can do is use the pause command and place how many seconds you want your code to pause for. Once you do that, you execute the code that you want. As an example:
times = 1:60;
for t = [times(1), diff(times)]
pause(t); % // Pause for t seconds
%// Place your code here...
...
...
end
As noted by #CST-Link, we should not take elapsed time into account, which is why we take the difference in neighbouring times of when you want to start your loop so that we can start your code as quickly as we can.
Also, if you want arbitrary times, place all of your times in an array, then loop through the array.
times = [1 3 10];
for t = [times(1), diff(times)]
pause(t); %// Pause for t seconds
%// Place your code here...
...
...
end
Polling is bad, but Matlab is by default single-threaded, so...
For the first case:
tic;
for t = 1:60
while toc < t, pause(0.01); end;
% your code
end;
For the second case:
tic;
for t = [1,3,10]
while toc < t, pause(0.01); end;
% your code
end;
The pause calls were added following the judicious observation of Amro about busy waiting. 0.01 seconds sounds like a good trade between timing precision and "amount" of spinning...
while pause is most of the time good enough, if you want better accuracy use java.lang.Thread.sleep.
For example the code below will display the minutes and seconds of your computer clock, exactly on the second (the function clock is accurate to ~ 1 microsecond), you can add your code instead of the disp command, the java.lang.Thread.sleep is just to illustrate it's accuracy (see after the code for an explanation)
while true
c=clock;
if mod(c(6),1)<1e-6
disp([c(5) c(6)])
java.lang.Thread.sleep(100); % Note: sleep() accepts [mSecs] duration
end
end
To see the difference in accuracy you can replace the above with java.lang.Thread.sleep(999); vs pause(0.999) and see how you sometimes skip an iteration.
For more info see here.
EDIT:
you can use tic\ toc instead of clock, this is probably more accurate because they take less time...
You can use a timer object. Here's an example that prints the numbers from 1 to 10 with 1 second between consecutive numbers. The timer is started, and it stops itself when a predefined number of executions is reached:
n = 1;
timerFcn = 'disp(n), n=n+1; if n>10, stop(t), end'; %// timer's callback
t = timer('TimerFcn' ,timerFcn, 'period', 1, 'ExecutionMode', 'fixedRate');
start(t) %// start the timer. Note that it will stop itself (within the callback)
A better version, with thanks to #Amro: specify the number of executions directly as a timer's property. Don't forget to stop the timer when done. But don't stop it too soon or it will not get executed the expected number of times!
n = 1;
timerFcn = 'disp(n), n=n+1;'; %// this will be the timer's callback
t = timer('TimerFcn', timerFcn, 'period', 1, 'ExecutionMode', 'fixedRate', ...
'TasksToExecute', 10);
start(t) %// start the timer.
%// do stuff. *This should last long enough* to avoid stopping the timer too soon
stop(t)
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)