M1_20141007_B002_runstim.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. function runstim(Hnd) %#ok<FNDEF>
  2. global Par %global parameters
  3. global LPStat %das status values
  4. global STIM
  5. Par.TrainSession = false;
  6. % set to false for recording sessions !
  7. % it will allow more control over file-naming
  8. % files will get a default name if set to true (see line 52 and later)
  9. %Difficulty =================================================
  10. % CK20140128: Timing is taken from par file but overwritten by
  11. % CK20140128: values from the settings file in this runstim
  12. load('PAR_HICKEY.mat'); % load the default parameter-file
  13. % (maybe we can remove this later, but default Tracker relies on some settings)
  14. LOG.DefMonkeyName = 'Duvel'; % default monkey name used in creating a filename
  15. % can be overruled in filename when it's set through the dialog
  16. % Load settings file
  17. LOG.SettingsFile = 'HICKEY_SETTINGS_Duvel';
  18. eval(LOG.SettingsFile);
  19. LOG.SettingsFileFull = fullfile(pwd,[LOG.SettingsFile '.m']);
  20. Par.Trlcount = 0; %reset trialcount to 0
  21. % Every time you press run, Tracker will generate a unique list of stimuli
  22. % and conditions. If we continue the trialcount over repeated runs the
  23. % references to conditions won't work anymore. THis automatically means
  24. % that for every time you press run, there will be a separate log file
  25. % saved. There should also be a matching TDT file, so always stop and start
  26. % TDT and Tracker together.
  27. % Save stuff in this version
  28. cc=clock; % get time info from the system clock
  29. LOG.datestr=[sprintf('%04d',cc(1)) sprintf('%02d',cc(2)) ...
  30. sprintf('%02d',cc(3))]; % YYYYMMDD
  31. LOG.timestr=[sprintf('%02d',cc(4)) sprintf('%02d',cc(5)) ...
  32. sprintf('%02d',round(cc(6)))]; % HHMMSS
  33. % Create a random number in the largest range that can be encoded using 14 bits
  34. % We will send this as a word bit to TDT as an extra check when matching up
  35. % our TDT data-file and the Tracker-log. THis is in addition to consistent
  36. % filenaming.
  37. LOG.uniqueID = round(rand(1).*2^14);
  38. dasword(LOG.uniqueID);
  39. pause(.05); % make sure the word is received
  40. dasclearword();
  41. WordsSent=1; %keep track of how many words are sent so we back-check TDT against the log
  42. LOG.Words(WordsSent)=LOG.uniqueID; %collect all the words that are sent to TDT
  43. % Create a filename Monkeyname_YYYYMMDD_B#
  44. if Par.TrainSession
  45. fnLead = [LOG.DefMonkeyName '_' LOG.datestr '_TRAIN' ];
  46. % Training- and Recording sessions will be saved under different names
  47. else
  48. fnLead = [LOG.DefMonkeyName '_' LOG.datestr '_B' ];
  49. % this filename construction is convention for TDT as well
  50. end
  51. % look for log files with this date and find the lowest new block nr
  52. % will only check for files that follow the filename convention
  53. % MonkeyName_YYYYMMDD_Bx.mat (where x=blocknr)
  54. cd LOG; % go to log folder
  55. prevfiles=dir([fnLead '*']);
  56. % Assuming the last file has the highest blocknr
  57. % as it should when naming conventions are followed
  58. if ~isempty(prevfiles)
  59. CurrBlockNr = str2num(prevfiles(end).name(end))+1; %#ok<*ST2NM>
  60. else
  61. CurrBlockNr = 1;
  62. end
  63. cd ..
  64. % create an input dialog for setting the filename
  65. % suggest a default name based on the files that are already present
  66. LOG.FileNameSug = [fnLead sprintf('%03d',CurrBlockNr)];
  67. if ~Par.TrainSession
  68. LOG.FileName = inputdlg(...
  69. 'Start a new TDT block and set filename for Tracker-log consistently\n',...
  70. 'Filename',1,{LOG.FileNameSug});
  71. % take input name on 'ok', suggested name on 'cancel'
  72. if ~isempty(LOG.FileName)
  73. LOG.FileName = LOG.FileName{1};
  74. else
  75. LOG.FileName = LOG.FileNameSug;
  76. end
  77. else
  78. LOG.FileName = LOG.FileNameSug;
  79. end
  80. % Create an empty screen
  81. BG = STIM.BackCol; %background Color
  82. cgflip(BG(1), BG(2), BG(3)) %flip the videobuffer
  83. nf=1; %keep track of number of flips
  84. nfr=100; %refresh tracker every nfr frame flips
  85. %timing ====================================================
  86. % Timing from the Settings-file are used
  87. PREFIXT = STIM.PreFixT; % time allowed to initiate fixation
  88. FIXT = STIM.FixT; % duration to hold fixation before stimuli appear
  89. TARGT = STIM.KeepFixT; % Duration to hold fixation while stimuli are on the screen
  90. RACT = STIM.ReacT; % Time allowed to select a target after target onset
  91. SACCT= STIM.SaccT; % Allowed saccade time between leaving fixwin and entering targwin
  92. ISI = STIM.ISI; % interstimulus interval
  93. ISI_R = STIM.ISI_RAND; % max random addition to ISI
  94. ERRT = STIM.ErrT; % punishment addition to ISI after error trial
  95. %Stimulus information ======================================
  96. %Fixation dot size and location in pixels
  97. FixPosPix = STIM.FixPos*Par.PixPerDeg;
  98. px = FixPosPix(1); py = FixPosPix(2);
  99. Fsz = STIM.FixSz.*Par.PixPerDeg;
  100. TargSz = STIM.TarSz.*Par.PixPerDeg;
  101. %Windowing information =====================================
  102. % Info will be read from the settings file upon 'run'
  103. % but can be altered in the parameters tab
  104. Par.FixWdDeg = STIM.FixWinSz(1);
  105. Par.FixHtDeg = STIM.FixWinSz(2);
  106. Par.TargWdDeg = STIM.TarWinSz(1);
  107. Par.TargHtDeg = STIM.TarWinSz(2);
  108. %Make targets & distractors ----------------------
  109. targx = STIM.TarPos(:,1)'.*Par.PixPerDeg; % x-coordinates
  110. targy = STIM.TarPos(:,2)'.*Par.PixPerDeg; % y-coordinates
  111. %////YOUR STIMULATION CONTROL LOOP /////////////////////////////////
  112. Hit = 2;
  113. Par.ESC = false; %escape has not been pressed
  114. Par.Distcount = 0; %also count the number of times the distractor was selected
  115. TrialNr=0; % this is the index to rows in the triallist STIM.TrialList
  116. % it will increase when a new trial needs to be defined and stay the same
  117. % if a trial needs to be repeated. NB! this is not the same as the trial
  118. % count, which keep track of the number of started trials
  119. LOG.TotRew = 0; %keep track of earned total reward (excluding manual rewards)
  120. while ~Par.ESC
  121. %Pretrial
  122. %SETUP YOUR STIMULI FOR THIS TRIAL
  123. if Par.Drum && Hit ~= 2 %if drumming and this was an error trial
  124. %just redo with current settings
  125. else
  126. TrialNr=TrialNr+1;
  127. % CK20140128: This whole procedure is unflexible
  128. % CK20140128: I re-wrote it completely
  129. TrialTypeNo=STIM.TrialList(TrialNr,1);
  130. % be careful with referencing via Par.Trlcount
  131. % control window setup
  132. % 0 = fixation, 2 = target
  133. WIN=zeros(STIM.TarN+1,5);
  134. WIN(1,:)=[Par.PixPerDeg*STIM.FixPos(1),Par.PixPerDeg*STIM.FixPos(2),...
  135. Par.PixPerDeg*Par.FixWdDeg, Par.PixPerDeg*Par.FixHtDeg, 0];
  136. for i=1:STIM.TarN
  137. WIN(i+1,:)=[Par.PixPerDeg*STIM.TarPos(i,1),Par.PixPerDeg*STIM.TarPos(i,2), ...
  138. Par.PixPerDeg*Par.TargWdDeg, Par.PixPerDeg*Par.TargHtDeg, 1];
  139. end
  140. % which is the target?
  141. WIN(STIM.TrialTypes(TrialTypeNo,1)+1,5)=2;
  142. Par.WIN = WIN';
  143. end
  144. %/////////////////////////////////////////////////////////////////////
  145. %START THE TRIAL
  146. %set control window positions and dimensions
  147. refreshtracker(1) %for your control display
  148. SetWindowDas %for the dascard
  149. Abort = false; %whether subject has aborted before end of trial
  150. % sent trial number as word
  151. dasword(TrialNr);
  152. % TrialNr is the row index in STIM.TrialList for the prepared
  153. % next trial. In this row STIM.TrialList defines the stimuus array as:
  154. % # STIM.TrialList(TrialNr,1) = TrialType, which in turn indexes a
  155. % row in STIM.TrialTypes where c1 is target location, c2 is target
  156. % shape (1=circle, 2=square), and c3 is distractor location
  157. % # STIM.TrialList(TrialNr,2) = Index to STIM.ColSchemes that
  158. % defines the RGB values for target, distractor and non-targets
  159. % # STIM.TrialList(TrialNr,3) = Index to STIM.RewardValues to
  160. % dissociate between high and low rewarded trials.
  161. WordsSent=WordsSent+1;
  162. LOG.Words(WordsSent)=TrialNr;
  163. %///////// EVENT 0 START FIXATING//////////////////////////////////////
  164. cgellipse(px,py,Fsz,Fsz,STIM.FixCol_NoGo,'f') %the red fixation dot on the screen
  165. cgflip(BG(1), BG(2), BG(3))
  166. nf=nf+1;
  167. dasreset(0); %test enter fix window
  168. % 0 enter fix window
  169. % 1 leave fix window
  170. % 2 enter target window
  171. %subject has to start fixating central dot
  172. Par.SetZero = false; %set key to false to remove previous presses
  173. %Par.Updatxy = 1; %centering key is enabled
  174. Time = 1;
  175. Hit = 0;
  176. while Time < PREFIXT && Hit == 0
  177. %dasrun(5)
  178. [Hit Time] = DasCheck; %#ok<*NCOMMA> %retrieve position values and plot on Control display
  179. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  180. end
  181. %disp( [num2str(hitbreak) ' enter ' num2str(toc)])
  182. %///////// EVENT 1 KEEP FIXATING or REDO ////////////////////////////////////
  183. if Hit ~= 0 %subjects eyes are in fixation window keep fixating for FIX time
  184. dasreset(1); %set test parameters for exiting fix window
  185. Time = 1;
  186. Hit = 0;
  187. while Time < FIXT && Hit== 0
  188. %Check for 10 ms
  189. %dasrun(5)
  190. [Hit Time] = DasCheck; %retrieve eyechannel buffer and events, plot eye motion,
  191. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  192. end
  193. if Hit ~= 0 %eye has left fixation to early
  194. %possibly due to eye overshoot, give another chance
  195. dasreset(0);
  196. Time = 1;
  197. Hit = 0;
  198. while Time < PREFIXT && Hit == 0
  199. %dasrun(5)
  200. [Hit Time] = DasCheck; %retrieve position values and plot on Control display
  201. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  202. end
  203. if Hit ~= 0 %subjects eyes are in fixation window keep fixating for FIX time
  204. dasreset( 1); %test for exiting fix window
  205. Time = 1;
  206. Hit = 0;
  207. while Time < FIXT && Hit == 0
  208. %Check for 10 ms
  209. % pause(0.005)
  210. %dasrun(5)
  211. [Hit Time] = DasCheck;
  212. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  213. end
  214. else
  215. Hit = -1; %the subject did not fixate
  216. end
  217. end
  218. else
  219. Hit = -1; %the subject did not fixate
  220. end
  221. % LPP = dasrun 10);
  222. % setdatatype(LPP, 'int32Ptr', 2, 1)
  223. % display(LPP.Value)
  224. %///////// EVENT 2 DISPLAY STIMULUS //////////////////////////////////////
  225. if Hit == 0 %subject kept fixation, display stimulus
  226. Par.Trlcount = Par.Trlcount + 1; %counts total number of trials for this session
  227. % a trial is only counted when prefix is fullfilled
  228. % as long as no stimulus is shown, it's still the same trial
  229. % since this trial is started and the trial count updated:
  230. % log extensive info for this trial
  231. LOG.Trial(Par.Trlcount).TrialNr = TrialNr;
  232. LOG.Trial(Par.Trlcount).TrialCnt = Par.Trlcount;
  233. LOG.Trial(Par.Trlcount).TrialTypeNo = TrialTypeNo;
  234. LOG.Trial(Par.Trlcount).WordsSent = WordsSent;
  235. LOG.Trial(Par.Trlcount).LastWord = LOG.Words(WordsSent);
  236. LOG.Trial(Par.Trlcount).TarPos = STIM.TrialTypes(STIM.TrialList(TrialNr,1),1);
  237. LOG.Trial(Par.Trlcount).TarShape = STIM.TrialTypes(STIM.TrialList(TrialNr,1),2);
  238. LOG.Trial(Par.Trlcount).DistPos = STIM.TrialTypes(STIM.TrialList(TrialNr,1),3);
  239. LOG.Trial(Par.Trlcount).ColScheme = STIM.TrialList(TrialNr,2);
  240. LOG.Trial(Par.Trlcount).RewValue = STIM.RewardValues(STIM.TrialList(TrialNr,3));
  241. % draw stimuli
  242. for s = 1:STIM.TarN
  243. if s==STIM.TrialTypes(TrialTypeNo,1) %this is the target
  244. if STIM.TrialTypes(TrialTypeNo,2) == 1 % target is circle
  245. cgellipse(targx(s),targy(s),...
  246. TargSz,TargSz,STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColCorr,'f');
  247. else % target is rect
  248. cgrect(targx(s),targy(s),...
  249. sqrt(pi.*((TargSz/2).^2)),sqrt(pi.*((TargSz/2).^2)),...
  250. STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColCorr);
  251. end
  252. elseif s==STIM.TrialTypes(TrialTypeNo,3) %this is the salient non-target
  253. if STIM.TrialTypes(TrialTypeNo,2) == 1 % target is circle
  254. cgrect(targx(s),targy(s),...
  255. sqrt(pi.*((TargSz/2).^2)),sqrt(pi.*((TargSz/2).^2)),...
  256. STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_Sal);
  257. else % target is rect
  258. cgellipse(targx(s),targy(s),...
  259. TargSz,TargSz,STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_Sal,'f');
  260. end
  261. else % normal non-target
  262. if STIM.TrialTypes(TrialTypeNo,2) == 1 % target is circle
  263. cgrect(targx(s),targy(s),...
  264. sqrt(pi.*((TargSz/2).^2)),sqrt(pi.*((TargSz/2).^2)),...
  265. STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_NonSal);
  266. else % target is rect
  267. cgellipse(targx(s),targy(s),...
  268. TargSz,TargSz,STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_NonSal,'f');
  269. end
  270. end
  271. end
  272. cgellipse(px,py,Fsz,Fsz,STIM.FixCol_NoGo,'f') %the red fixation dot on the screen
  273. FO = cgflip(BG(1), BG(2), BG(3));
  274. nf=nf+1;
  275. dasbit(Par.StimB, 1); % set the stim channel in TDT to 1 to allow stimulus onset reconstruction
  276. %dasbit( Par.MicroB, 1);
  277. tic %measure onset to
  278. %..............................................................
  279. dasreset(1); %test for exiting fix window
  280. refreshtracker(2)
  281. Time = 0;
  282. %StimFlg = true;
  283. while Time < TARGT && Hit == 0 %Keep fixating till target onset
  284. if TARGT - Time < 5
  285. %dasrun(5)
  286. %don't plot any more, so we immediately break from loop
  287. Hit = LPStat(2);
  288. break
  289. else
  290. %Check for 5 ms
  291. %dasrun(5)
  292. %get hit time and plot eyemotion
  293. [Hit Time] = DasCheck;
  294. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  295. end
  296. end
  297. % if 0 % Never executed? For debugging? [CK]
  298. % %..............................................................
  299. % %%%%%%
  300. % %how much time(ms) do we have left till target onset???
  301. % delay = floor(TARGT + 5 * FLtime - toc*1000 - 5); %hold up calling the next flip
  302. % if delay > 0
  303. % dasrun(delay)
  304. % Hit = LPStat(2); %don't wast time!!!! on updating the screen
  305. % end
  306. % end
  307. %///////// EVENT 3 TARGET ONSET, REACTION TIME%%//////////////////////////////////////
  308. if Hit == 0 %subject kept fixation, subject may make an eye movement
  309. %Draw targets
  310. for s = 1:STIM.TarN
  311. if s==STIM.TrialTypes(TrialTypeNo,1) %this is the target
  312. if STIM.TrialTypes(TrialTypeNo,2) == 1 % target is circle
  313. cgellipse(targx(s),targy(s),...
  314. TargSz,TargSz,STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColCorr,'f');
  315. else % target is rect
  316. cgrect(targx(s),targy(s),...
  317. sqrt(pi.*((TargSz/2).^2)),sqrt(pi.*((TargSz/2).^2)),...
  318. STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColCorr);
  319. end
  320. elseif s==STIM.TrialTypes(TrialTypeNo,3) %this is the salient non-target
  321. if STIM.TrialTypes(TrialTypeNo,2) == 1 % target is circle
  322. cgrect(targx(s),targy(s),...
  323. sqrt(pi.*((TargSz/2).^2)),sqrt(pi.*((TargSz/2).^2)),...
  324. STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_Sal);
  325. else % target is rect
  326. cgellipse(targx(s),targy(s),...
  327. TargSz,TargSz,STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_Sal,'f');
  328. end
  329. else % normal non-target
  330. if STIM.TrialTypes(TrialTypeNo,2) == 1 % target is circle
  331. cgrect(targx(s),targy(s),...
  332. sqrt(pi.*((TargSz/2).^2)),sqrt(pi.*((TargSz/2).^2)),...
  333. STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_NonSal);
  334. else % target is rect
  335. cgellipse(targx(s),targy(s),...
  336. TargSz,TargSz,STIM.ColSchemes(STIM.TrialList(TrialNr,2)).TargColErr_NonSal,'f');
  337. end
  338. end
  339. end
  340. cgellipse(px,py,Fsz,Fsz,STIM.FixCol_Go,'f') %the green fixation dot on the screen
  341. FS = cgflip(BG(1), BG(2), BG(3));
  342. nf=nf+1;
  343. LOG.Trial(Par.Trlcount).StimTarDur = FS - FO; % log time between stim and targ onset
  344. dasbit(Par.TargetB, 1); % set the target channel in TDT to 1 to allow target onset reconstruction
  345. dasreset(2); %check target window enter
  346. refreshtracker(3) %set fix point to green
  347. Time = 0;
  348. while Time < RACT && Hit <= 0 %RACT = time to respond (reaction time)
  349. %Check for 5 ms
  350. %dasrun(5)
  351. [Hit Time] = DasCheck;
  352. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  353. end
  354. %Hit % don't output this to cmd
  355. else
  356. Abort = true;
  357. end
  358. %END EVENT 3
  359. else
  360. Abort = true;
  361. end
  362. %END EVENT 2
  363. %///////// POSTTRIAL AND REWARD //////////////////////////////////////
  364. if Hit ~= 0 && ~Abort %has entered a target window (false or correct)
  365. if Par.Mouserun
  366. HP = line('XData', Par.ZOOM * (LPStat(3) + Par.MOff(1)), 'YData', Par.ZOOM * (LPStat(4) + Par.MOff(2)), 'EraseMode','none');
  367. else
  368. HP = line('XData', Par.ZOOM * LPStat(3), 'YData', Par.ZOOM * LPStat(4), 'EraseMode','none');
  369. end
  370. set(HP, 'Marker', '+', 'MarkerSize', 20, 'MarkerEdgeColor', 'm')
  371. if Hit == 2 && LPStat(6) < SACCT %correct target within max allowed saccade time >> give juice
  372. dasbit( Par.CorrectB, 1); % set the Correct channel in TDT to 1
  373. dasbit( Par.RewardB, 1); % set the Reward channel in TDT to 1
  374. dasjuice(5); % open reward valve
  375. Par.Corrcount = Par.Corrcount + 1; %log correct trials
  376. % beep
  377. TrialStatus='Target';
  378. % find out how much reward should be given and give it
  379. if STIM.UseSpecRew
  380. RewTime = STIM.RewardValues(STIM.TrialList(TrialNr,3));
  381. LOG.TotRew = LOG.TotRew+RewTime;
  382. pause(RewTime) %RewardTime is in seconds
  383. else
  384. pause(Par.RewardTime) %RewardTime is in seconds
  385. LOG.TotRew = LOG.TotRew+Par.RewardTime;
  386. end
  387. dasjuice(0.0); % switch off reward
  388. dasbit( Par.RewardB, 0); % set the Reward channel in TDT to 0
  389. % log which target was selected
  390. LOG.Trial(Par.Trlcount).TarChoice=LOG.Trial(Par.Trlcount).TarPos;
  391. elseif Hit == 1 && LPStat(6) < SACCT
  392. dasbit( Par.ErrorB, 1);
  393. Par.Errcount = Par.Errcount + 1;
  394. % what kind of error?
  395. % check x,y endpoints against target windows
  396. % these are the x and y endpoints of the eye data
  397. xE=LPStat(3);
  398. yE=LPStat(4);
  399. %targx is a column of target x positions
  400. %targy is a column of target y positions
  401. % calculate the distance from the eye-endpoint to all targets
  402. EyeDistFromTar = sqrt((targx-xE).^2+(targy-yE).^2);
  403. % find the closest target (should be the one that is selected)
  404. SelTar=find(EyeDistFromTar==min(EyeDistFromTar),1,'first');
  405. % this procedure fails if target windows overlap
  406. % which they shouldn't anyway
  407. % log which target was selected
  408. LOG.Trial(Par.Trlcount).TarChoice=SelTar;
  409. % determine the status of the chosen target
  410. if SelTar==STIM.TrialTypes(TrialTypeNo,3)
  411. % salient distractor selected
  412. TrialStatus='Distractor';
  413. Par.Distcount=Par.Distcount+1;
  414. else
  415. %in wrong target window
  416. TrialStatus='Nontarget';
  417. end
  418. elseif Hit ~= 0 && LPStat(6) >= SACCT % too slow
  419. TrialStatus='SaccadeTooSlow';
  420. end
  421. %keep following eye motion to plot complete saccade
  422. for i = 1:10 %keep targoff for 50ms
  423. %dasrun(5) %not time critical, add some time to follow eyes
  424. %dasrun 5);
  425. DasCheck; %keep following eye motion
  426. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  427. end
  428. % log some behavioral info
  429. LOG.Trial(Par.Trlcount).ReactTime = LPStat(5);
  430. LOG.Trial(Par.Trlcount).SaccTime = LPStat(6);
  431. LOG.Trial(Par.Trlcount).HitPos = [LPStat(3) LPStat(4)];
  432. LOG.Trial(Par.Trlcount).Status = TrialStatus;
  433. LOG.Trial(Par.Trlcount).TotRew = LOG.TotRew;
  434. %output some info to cmd
  435. % trial nr and status
  436. fprintf(['Trial ' num2str(Par.Trlcount) ': ' TrialStatus '\n']);
  437. % reaction time (RT), saccade time(ST), and Total reward (TR) until now
  438. fprintf(['RT: ' num2str(LPStat(5)) ...
  439. ' ST: ' num2str(LPStat(6)) ...
  440. ' TR: ' num2str(LOG.TotRew) '\n\n']);
  441. elseif Par.Trlcount>0 && ~Abort % trial was not aborted but no target was selected in time
  442. TrialStatus='NoHit';
  443. % log some behavioral info
  444. LOG.Trial(Par.Trlcount).ReactTime = [];
  445. LOG.Trial(Par.Trlcount).SaccTime = [];
  446. LOG.Trial(Par.Trlcount).HitPos = [];
  447. LOG.Trial(Par.Trlcount).Status = TrialStatus;
  448. LOG.Trial(Par.Trlcount).TotRew = LOG.TotRew;
  449. %output some info to cmd
  450. fprintf(['Trial ' num2str(Par.Trlcount) ': ' TrialStatus '\n']);
  451. fprintf(['RT: ' num2str(LPStat(5)) ...
  452. ' ST: ' num2str(LPStat(6)) ...
  453. ' TR: ' num2str(LOG.TotRew) '\n\n']);
  454. elseif Par.Trlcount>0 && Abort % trial was started but aborted
  455. TrialStatus='Aborted';
  456. % log some behavioral info
  457. LOG.Trial(Par.Trlcount).ReactTime = [];
  458. LOG.Trial(Par.Trlcount).SaccTime = [];
  459. LOG.Trial(Par.Trlcount).HitPos = [];
  460. LOG.Trial(Par.Trlcount).Status = TrialStatus;
  461. LOG.Trial(Par.Trlcount).TotRew = LOG.TotRew;
  462. end
  463. if Hit ~= 2 %error response
  464. %add pause when subject makes error
  465. for i = 1:round(ERRT/5) %keep targoff for Times.Err ms
  466. % pause(0.005)
  467. %dasrun(5)
  468. DasCheck;
  469. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  470. end
  471. end %Times.Err is in ms
  472. [Hit Lasttime] = DasCheck;
  473. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  474. %///////////////////////INTERTRIAL AND CLEANUP
  475. %reset all bits to null
  476. for i = [0 1 2 3 4 5 6 7] %Error, Stim, Saccade, Trial, Correct,
  477. dasbit( i, 0);
  478. end
  479. dasclearword();
  480. SCNT = {'TRIALS'};
  481. SCNT(2) = { ['N: ' num2str(Par.Trlcount) ]}; % n trials
  482. SCNT(3) = { ['C: ' num2str(Par.Corrcount) ] }; % n correct
  483. SCNT(4) = { ['E: ' num2str(Par.Errcount) ] }; % n error
  484. SCNT(5) = { ['D: ' num2str(Par.Distcount) ] }; % n distractor
  485. set(Hnd(1), 'String', SCNT ) %display updated numbers in GUI
  486. SD = dasgetnoise();
  487. SD = SD./Par.PixPerDeg;
  488. set(Hnd(2), 'String', SD )
  489. cgpencol(BG(1), BG(2), BG(3)) %clear background before flipping
  490. cgrect
  491. cgflip(BG(1), BG(2), BG(3))
  492. nf=nf+1;
  493. %pause( Times.InterTrial/1000 ) %pause is called with seconds
  494. %Times.InterTrial is in ms
  495. Time = Lasttime;
  496. while Time < ISI + ISI_R*rand(1) + ERRT
  497. % pause(0.005)
  498. %dasrun(5)
  499. [hit Time] = DasCheck; %#ok<ASGLU>
  500. if mod(nf,nfr)==0; refreshtracker(1); end %keep eye-position line short
  501. end
  502. end %WHILE_NOT_ESCAPED%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  503. %% Save log file ===============================
  504. cd LOG;
  505. % create a folder for this run
  506. warning off; %#ok<*WNOFF>
  507. mkdir(LOG.FileName);
  508. cd(LOG.FileName);
  509. % the generated parameters in a log-file
  510. save(LOG.FileName,'LOG','Par','STIM','-v7.3');
  511. % a copy of this runstim
  512. fn=[LOG.FileName '_runstim.m'];
  513. cfn=[mfilename('fullpath') '.m'];
  514. copyfile(cfn,fn);
  515. % a copy of the settings file
  516. copyfile(LOG.SettingsFileFull,[LOG.FileName '_settings.m']);
  517. cd ..
  518. cd ..
  519. % backup under unique time name in case you accidentally overwrite
  520. mkdir('REDUNDANT_LOG');
  521. warning on; %#ok<*WNON>
  522. cd 'REDUNDANT_LOG';
  523. save(['DATA_' LOG.datestr '_' LOG.timestr],'LOG','Par','STIM','-v7.3');
  524. copyfile(cfn,['Runstim_' LOG.datestr '_' LOG.timestr '.m']);
  525. copyfile(LOG.SettingsFileFull,['Settings_' LOG.datestr '_' LOG.timestr '.m']);
  526. cd ..