runstim.m 145 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262
  1. function runstim(Hnd)
  2. % Updated November 2017, Chris Klink (c.klink@nin.knaw.nl)
  3. % Fixation & diverse retinotopic mapping stimuli
  4. global Par %global parameters
  5. global StimObj %stimulus objects
  6. global Log %Logs
  7. %% THIS SWITCH ALLOW TESTING THE RUNSTIM WITHOUT DASCARD & TRACKER ========
  8. TestRunstimWithoutDAS = false;
  9. %==========================================================================
  10. % Do this only for testing without DAS
  11. if TestRunstimWithoutDAS
  12. cd .. %#ok<*UNRCH>
  13. addpath(genpath(cd));
  14. ptbInit % initialize PTB
  15. Par.scr=Screen('screens');
  16. Par.ScrNr=max(Par.scr); % use the screen with the highest #
  17. Par.ScreenChoice = 'Mock';
  18. if Par.ScrNr==0
  19. % part of the screen
  20. [Par.window, Par.wrect] = ...
  21. Screen('OpenWindow',Par.ScrNr,0,[0 0 1000 800],[],2);
  22. else
  23. [Par.window, Par.wrect] = Screen('OpenWindow',Par.ScrNr,0,[],[],2);
  24. end
  25. % Reduce PTB3 verbosity
  26. oldLevel = Screen('Preference', 'Verbosity', 0); %#ok<*NASGU>
  27. Screen('Preference', 'VisualDebuglevel', 0);
  28. Screen('Preference','SkipSyncTests',1);
  29. %Do some basic initializing
  30. AssertOpenGL;
  31. KbName('UnifyKeyNames');
  32. %Set ParFile and Stimfile
  33. Par.PARSETFILE = 'ParSettings_NoDas';
  34. Par.STIMSETFILE = 'StimSettings_NaturalMovie_1'; %'StimSettings_pRF_8bars'; %'StimSettings_FullscreenCheckerboard';
  35. Par.MONKEY = 'TestWithoutDAS';
  36. end
  37. clc;
  38. %% Prior To Dealing With Stimuli ==========================================
  39. % set PTB priority to max
  40. priorityLevel=MaxPriority(Par.window);
  41. oldPriority=Priority(priorityLevel);
  42. Par.ExpFolder = pwd;
  43. %% set up the manual response task ========================================
  44. for define_square=1 % left / square
  45. lmost=-1/2; rmost= 1/2;
  46. tmost=-1/2; bmost= 1/2;
  47. left_square = [lmost,tmost; rmost,tmost; rmost,bmost; lmost,bmost ];
  48. end
  49. for define_diamond=1 % right / diamond
  50. lmost=-sqrt(2)*1/2; rmost= sqrt(2)*1/2;
  51. tmost=-sqrt(2)*1/2; bmost= sqrt(2)*1/2;
  52. right_diamond = [lmost,0; 0,tmost; rmost,0; 0,bmost ];
  53. end
  54. for define_circle=1 % shown when subject needs to release response
  55. lmost=-sqrt(1/pi); rmost= sqrt(1/pi);
  56. tmost=-sqrt(1/pi); bmost= sqrt(1/pi);
  57. blocked_circle = [lmost, tmost, rmost, bmost ];
  58. end
  59. %% initialize stuff =======================================================
  60. Par.ESC = false; %escape has not been pressed
  61. GrandTotalReward=0;
  62. LastRewardAdded=false;
  63. CollectPerformance=[];
  64. CloseTextures=false;
  65. json_done=false;
  66. Par.RewardStartTime=0;
  67. % re-run parameter-file to update stim-settings without restarting Tracker
  68. eval(Par.PARSETFILE); % can be chosen in menu
  69. if ~isfield(Par,'PostErrorDelay')
  70. Par.PostErrorDelay = 0;
  71. fprintf('No PostErrorDelay defined: Setting it to 0\n');
  72. end
  73. if ~isfield(Par,'DelayOnMiss')
  74. Par.DelayOnMiss = 0;
  75. fprintf('No DelayOnMiss defined: Setting it to 0\n');
  76. end
  77. if ~isfield(Par,'RewardForHandsIn_Delay')
  78. Par.RewardForHandsIn_Delay = 0;
  79. fprintf('No RewardForHandsIn_Delay defined: Setting it to 0\n');
  80. end
  81. if ~isfield(Par,'RewardForHandIn_ResetIntervalWhenOut')
  82. Par.RewardForHandIn_ResetIntervalWhenOut = false;
  83. Par.RewardForHandIn_MinIntervalBetween = 0;
  84. fprintf('No RewardForHandIn_ResetIntervalWhenOut defined: Setting it to false\n');
  85. end
  86. if ~isfield(Par,'LeversUpTimeOut')
  87. Par.LeversUpTimeOut = [Inf 0];
  88. fprintf('No LeversUpTimeOut defined: Setting it to [Inf 0]\n');
  89. end
  90. if strcmp(StimObj.Stm(1).RetMap.StimType{1},'movie-vlc')
  91. Par.ResponseBox.Task = 'Fixate';
  92. fprintf('No hand task possible during vlc-movies\n');
  93. fprintf('Setting task to fixate\n');
  94. end
  95. % Add keys to fix left/right/random responses
  96. Par.KeyLeftResp = KbName(',<');
  97. Par.KeyRightResp = KbName('.>');
  98. Par.KeyRandResp = KbName('/?');
  99. Par.RespProbSetting=0; % initialize with random left/right indicators
  100. Par.ScrCenter=Par.wrect(3:4)/2;
  101. DateString_sec = datestr(clock,30);
  102. DateString = DateString_sec(1:end-2);
  103. Par_BU=Par;
  104. if ~TestRunstimWithoutDAS
  105. refreshtracker(1);
  106. end
  107. if strcmp(Par.SetUp,'NIN')
  108. blockstr = inputdlg('BlockNr','BlockNr',1,{'000'});
  109. blockstr=blockstr{1};
  110. end
  111. % output stimsettings filename to cmd
  112. fprintf(['Setup selected: ' Par.SetUp '\n']);
  113. %fprintf(['Screen selected: ' Par.ScreenChoice '\n']);
  114. fprintf(['TR: ' num2str(Par.TR) 's\n\n']);
  115. fprintf(['=== Running ' Par.STIMSETFILE ' for ' Par.MONKEY ' ===\n']);
  116. if ~strcmp(Par.ResponseBox.Task, 'DetectGoSignal')% do no show this if reward is based on task
  117. if numel(Par.Times.Targ)>1
  118. fprintf(['Progressive fix-to-reward times between ' num2str(Par.Times.Targ(1,2)) ...
  119. ' and ' num2str(Par.Times.Targ(end,2)) ' ms\n']);
  120. else
  121. fprintf(['Hold fixation for ' num2str(Par.Times.Targ) ' ms to get reward\n']);
  122. end
  123. end
  124. Par.RewardTime=Par.RewardTimeSet;
  125. Stm = StimObj.Stm;
  126. fprintf(['Started at ' DateString '\n']);
  127. % overwrite the stimsettings fix-window with the one from parsettings
  128. for sss=1:length(Stm)
  129. Stm(sss).FixWinSize = Par.FixWinSize;
  130. if ~TestRunstimWithoutDAS
  131. refreshtracker(1);
  132. end
  133. end
  134. % If multiple stimuli are defined, arrange order
  135. Log.StimOrder=[];
  136. for nR=1:Stm(1).nRepeatsStimSet
  137. if length(Stm)>1
  138. nSTIM=length(Stm);
  139. if Stm(1).RandomizeStim
  140. Log.StimOrder = [Log.StimOrder randperm(nSTIM)];
  141. else
  142. Log.StimOrder = [Log.StimOrder 1:nSTIM];
  143. end
  144. StimLoopNr=0;
  145. else
  146. Log.StimOrder = [Log.StimOrder 1];
  147. StimLoopNr=0;
  148. end
  149. end
  150. % This control parameter needs to be outside the stimulus loop
  151. FirstEyeRecSet=false;
  152. if ~TestRunstimWithoutDAS
  153. dasbit(0,1); %set eye-recording trigger to 1 (=stopped)
  154. %reset reward slider based on ParSettings
  155. handles=guihandles(Par.hTracker);
  156. if numel(Par.RewardTime)==1
  157. set(handles.Lbl_Rwtime, 'String', num2str(Par.RewardTime, 5))
  158. set(handles.slider1, 'Value', Par.RewardTime)
  159. else
  160. set(handles.Lbl_Rwtime, 'String', num2str(Par.RewardTime(1,2), 5))
  161. set(handles.slider1, 'Value', Par.RewardTime(1,2))
  162. end
  163. end
  164. %% Load stimuli before entering the display loop to be faster later =======
  165. % Load retinotopic mapping stimuli
  166. FaceRingsLoaded=false; FaceWedgeLoaded=false;
  167. WalkerRingsLoaded=false; WalkerWedgeLoaded=false;
  168. for STIMNR = unique(Log.StimOrder)
  169. switch Stm(STIMNR).RetMap.StimType{1}
  170. case 'none'
  171. Stm(STIMNR).Descript = 'NoStim';
  172. case 'ret'
  173. %% Retinotopy stim
  174. if strcmp(Stm(STIMNR).RetMap.StimType{2},'pRF_8bar')
  175. Stm(STIMNR).Order=1:Stm(STIMNR).RetMap.nSteps;
  176. Stm(STIMNR).Descript = 'pRF_8bar';
  177. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge_cw')
  178. Stm(STIMNR).Order=Stm(STIMNR).RetMap.nSteps:-1:1;
  179. Stm(STIMNR).Descript = 'wedge_cw';
  180. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge_ccw')
  181. Stm(STIMNR).Order=1:Stm(STIMNR).RetMap.nSteps;
  182. Stm(STIMNR).Descript = 'wedge_ccw';
  183. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'ring_con')
  184. Stm(STIMNR).Order=Stm(STIMNR).RetMap.nSteps:-1:1;
  185. Stm(STIMNR).Descript = 'ring_con';
  186. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'ring_exp')
  187. Stm(STIMNR).Order=1:Stm(STIMNR).RetMap.nSteps;
  188. Stm(STIMNR).Descript = 'ring_exp';
  189. end
  190. if Stm(STIMNR).RetMap.LoadFromFile
  191. fprintf(['\nLoading retinotopy stimulus: ' ...
  192. Stm(STIMNR).RetMap.FileName '...\n']);
  193. cd Stimuli
  194. cd RetMap
  195. D=load(Stm(STIMNR).RetMap.FileName);
  196. stimulus=D.stimulus;fps=D.fps;
  197. cd ..
  198. cd ..
  199. else
  200. fprintf('Creating retinotopy stimulus...\n');
  201. stimulus = ck_ret(Stm,STIMNR);
  202. fps = Stm(STIMNR).RetMap.fps;
  203. if Stm(STIMNR).RetMap.SaveToFile
  204. fprintf('\nSaving retinotopy stimulus...\n');
  205. cd Stimuli
  206. cd RetMap
  207. save(Stm(STIMNR).RetMap.FileName,'stimulus','fps','Stm','-v7.3');
  208. cd ..
  209. cd ..
  210. end
  211. end
  212. %% img to textures
  213. pos=0; %Stm(STIMNR).RetMap.posmap = [];
  214. if strcmp(Stm(STIMNR).RetMap.StimType{2},'pRF_8bar')
  215. for rv=1:length(stimulus(1).orient) %length(stimulus) % directions
  216. for ii=1:length(stimulus(1).img) % positions
  217. pos=pos+1;
  218. for jj = 1:size(stimulus(1).img{ii},3) % frame
  219. if rv==1
  220. img1 = stimulus(1).img{ii}(:,:,jj);
  221. ret_vid(pos).img{jj} = img1; %#ok<*AGROW>
  222. ret_vid(pos).text(jj) = Screen('MakeTexture', ...
  223. Par.window,img1);
  224. end
  225. ret_vid(pos).fps = fps;
  226. ret_vid(pos).orient(jj) = stimulus(1).orient(rv);
  227. end
  228. end
  229. end
  230. else
  231. for rv=1:length(stimulus)
  232. for ii=1:length(stimulus(rv).img) % positions
  233. pos=pos+1;
  234. for jj = 1:size(stimulus(rv).img{ii},3) % frame
  235. ret_vid(pos).img{jj} = stimulus(rv).img{ii}(:,:,jj); %#ok<*AGROW>
  236. ret_vid(pos).fps = fps;
  237. ret_vid(pos).text(jj) = Screen('MakeTexture', Par.window, ...
  238. ret_vid(pos).img{jj});
  239. end
  240. end
  241. end
  242. end
  243. CloseTextures = true;
  244. Stm(STIMNR).RetMap.posmap = stimulus(1).posmap;
  245. case 'face'
  246. %% Classic retinotopy: faces
  247. if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
  248. if Stm(STIMNR).RetMap.Dir == 1 %expanding
  249. Stm(STIMNR).Order=1:32;
  250. Stm(STIMNR).Descript = 'FaceRingExp';
  251. elseif Stm(STIMNR).RetMap.Dir == -1 %contracting
  252. Stm(STIMNR).Order=32:-1:1;
  253. Stm(STIMNR).Descript = 'FaceRingCon';
  254. end
  255. if ~FaceRingsLoaded
  256. cd Stimuli
  257. cd faces
  258. fprintf('Loading faces01_rings.mat\n');
  259. vid_face_ring = load('faces01_rings.mat'); % loads 'ret_vid' structure
  260. FaceRingsLoaded=true;
  261. cd ..
  262. cd ..
  263. face_ring_vidtex_made=false;
  264. end
  265. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
  266. if Stm(STIMNR).RetMap.Dir == 1 %ccw
  267. Stm(STIMNR).Order=1:32;
  268. Stm(STIMNR).Descript = 'FaceWedgeCCW';
  269. elseif Stm(STIMNR).RetMap.Dir == -1 %cw
  270. Stm(STIMNR).Order=[1 32:-1:2];
  271. Stm(STIMNR).Descript = 'FaceWedgeCW';
  272. end
  273. if ~FaceWedgeLoaded
  274. cd Stimuli
  275. cd faces
  276. fprintf('Loading faces01_wedge.mat\n');
  277. vid_face_wedge = load('faces01_wedge.mat'); % loads 'ret_vid' structure
  278. FaceWedgeLoaded=true;
  279. cd ..
  280. cd ..
  281. face_wedge_vidtex_made=false;
  282. end
  283. end
  284. Stm(STIMNR).RetMap.posmap = [(1:32)' Stm(STIMNR).Order'];
  285. % img to textures
  286. if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle') && ~face_ring_vidtex_made
  287. fprintf('Creating stimulus textures\n');
  288. for rv=1:length(vid_face_ring.ret_vid)
  289. for ii=1:length(vid_face_ring.ret_vid(rv).img)
  290. vid_face_ring.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
  291. vid_face_ring.ret_vid(rv).img{ii});
  292. end
  293. end
  294. face_ring_vidtex_made=true;
  295. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge') && ~face_wedge_vidtex_made
  296. fprintf('Creating stimulus textures\n');
  297. for rv=1:length(vid_face_wedge.ret_vid)
  298. for ii=1:length(vid_face_wedge.ret_vid(rv).img)
  299. vid_face_wedge.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
  300. vid_face_wedge.ret_vid(rv).img{ii});
  301. end
  302. end
  303. face_wedge_vidtex_made=true;
  304. end
  305. CloseTextures = true;
  306. case 'walker'
  307. %% Classic retinotopy: walkers
  308. if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
  309. if Stm(STIMNR).RetMap.Dir == 1 %expanding
  310. Stm(STIMNR).Order=1:32;
  311. Stm(STIMNR).Descript = 'WalkerRingExp';
  312. elseif Stm(STIMNR).RetMap.Dir == -1 %contracting
  313. Stm(STIMNR).Order=32:-1:1;
  314. Stm(STIMNR).Descript = 'WalkerRingCon';
  315. end
  316. if ~WalkerRingsLoaded
  317. cd Stimuli
  318. cd walkers
  319. fprintf('Loading walker01_rings.mat\n');
  320. vid_walker_ring = load('walker01_rings.mat'); % loads ret_vid structure
  321. WalkerRingsLoaded=true;
  322. cd ..
  323. cd ..
  324. walker_ring_vidtex_made=false;
  325. end
  326. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
  327. if Stm(STIMNR).RetMap.Dir == 1 %ccw
  328. Stm(STIMNR).Order=1:32;
  329. Stm(STIMNR).Descript = 'WalkerWedgeCCW';
  330. elseif Stm(STIMNR).RetMap.Dir == -1 %cw
  331. Stm(STIMNR).Order=[1 32:-1:2];
  332. Stm(STIMNR).Descript = 'WalkerWedgeCW';
  333. end
  334. if ~WalkerWedgeLoaded
  335. cd Stimuli
  336. cd walkers
  337. fprintf('Loading walker01_wedge.mat\n');
  338. vid_walker_wedge = load('walker01_wedge.mat'); % loads ret_vid structure
  339. WalkerWedgeLoaded=true;
  340. cd ..
  341. cd ..
  342. walker_wedge_vidtex_made=false;
  343. end
  344. end
  345. Stm(STIMNR).RetMap.posmap = [(1:32)' Stm(STIMNR).Order'];
  346. % img to textures
  347. if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle') && ~walker_ring_vidtex_made
  348. fprintf('Creating stimulus textures\n');
  349. for rv=1:length(vid_walker_ring.ret_vid)
  350. for ii=1:length(vid_walker_ring.ret_vid(rv).img)
  351. vid_walker_ring.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
  352. vid_walker_ring.ret_vid(rv).img{ii});
  353. end
  354. end
  355. walker_ring_vidtex_made=true;
  356. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge') && ~walker_wedge_vidtex_made
  357. fprintf('Creating stimulus textures\n');
  358. for rv=1:length(vid_walker_wedge.ret_vid)
  359. for ii=1:length(vid_walker_wedge.ret_vid(rv).img)
  360. vid_walker_wedge.ret_vid(rv).text(ii) = Screen('MakeTexture', Par.window, ...
  361. vid_walker_wedge.ret_vid(rv).img{ii});
  362. end
  363. end
  364. walker_wedge_vidtex_made=true;
  365. end
  366. CloseTextures = true;
  367. case 'checkerboard'
  368. %% fullscreen checkerboard
  369. Stm(STIMNR).Descript = 'FullChecker';
  370. case 'movie'
  371. Stm(STIMNR).Descript = 'movie';
  372. case 'movie-vlc'
  373. Stm(STIMNR).Descript = 'movie-vlc';
  374. end
  375. end
  376. TotTime=0;
  377. for i=1:length(Stm)
  378. if strcmp(Stm(i).RetMap.StimType{1},'checkerboard')
  379. Stm(i).RetMap.PreDur = ...
  380. Stm(i).RetMap.PreDur_TRs*Par.TR;
  381. Stm(i).RetMap.PostDur = ...
  382. Stm(i).RetMap.PostDur_TRs*Par.TR;
  383. Stm(i).RetMap.Checker.OnOff = ...
  384. Stm(i).RetMap.Checker.OnOff_TRs*Par.TR;
  385. TotTime = TotTime + ...
  386. (sum(Stm(i).RetMap.Checker.OnOff)*Stm(i).RetMap.nCycles)+...
  387. Stm(i).RetMap.PreDur+Stm(i).RetMap.PostDur;
  388. elseif strcmp(Stm(i).RetMap.StimType{1},'movie') || ...
  389. strcmp(Stm(i).RetMap.StimType{1},'movie-vlc')
  390. Stm(i).RetMap.PreDur = ...
  391. Stm(i).RetMap.PreDur_TRs*Par.TR;
  392. Stm(i).RetMap.PostDur = ...
  393. Stm(i).RetMap.PostDur_TRs*Par.TR;
  394. TotTime = TotTime + ...
  395. Stm(i).RetMap.moviedur + ...
  396. Stm(i).RetMap.PreDur + Stm(i).RetMap.PostDur;
  397. else
  398. Stm(i).RetMap.PreDur = ...
  399. Stm(i).RetMap.PreDur_TRs*Par.TR;
  400. Stm(i).RetMap.PostDur = ...
  401. Stm(i).RetMap.PostDur_TRs*Par.TR;
  402. if strcmp(Stm(i).RetMap.StimType{1},'ret')
  403. if Stm(i).RetMap.nCycles
  404. TotTime = TotTime + ...
  405. Stm(i).RetMap.nCycles*...
  406. size(Stm(i).RetMap.posmap,1)*...
  407. Stm(i).RetMap.TRsPerStep*Par.TR + ...
  408. Stm(i).RetMap.PreDur + Stm(i).RetMap.PostDur;
  409. else % no endpoint defined
  410. TotTime = Inf;
  411. end
  412. else
  413. if Stm(i).RetMap.nCycles
  414. TotTime = TotTime + ...
  415. Stm(i).nRepeatsStimSet*Stm(i).RetMap.nCycles*...
  416. Stm(i).RetMap.nSteps *...
  417. Stm(i).RetMap.TRsPerStep*Par.TR + ...
  418. Stm(i).RetMap.PreDur + Stm(i).RetMap.PostDur;
  419. else % no endpoint defined
  420. TotTime = Inf;
  421. end
  422. end
  423. end
  424. end
  425. if ~isinf(TotTime)
  426. NumVolNeeded=(Stm(1).nRepeatsStimSet*TotTime)/Par.TR;
  427. if strcmp(Par.SetUp,'NIN') % ephys
  428. fprintf(['This StimSettings file will take ' ...
  429. num2str(ceil(Stm(1).nRepeatsStimSet*TotTime)) ' seconds.\n']);
  430. Log.uniqueID = round(rand(1).*2^14);
  431. if strcmp(Par.SetUp,'NIN')
  432. send_serial_data(Log.uniqueID); % Xing's Blackrock rig
  433. % dasword(Log.uniqueID); % other ephys
  434. else
  435. dasword(Log.uniqueID);
  436. end
  437. pause(.05); % make sure the word is received
  438. dasclearword();
  439. WordsSent=1; %keep track of how many words are sent so we back-check TDT against the log
  440. Log.Words(WordsSent)=Log.uniqueID; %collect all the words that are sent to TDT
  441. else
  442. fprintf(['This StimSettings file requires at least ' num2str(ceil(NumVolNeeded)) ...
  443. ' scanvolumes (check scanner)\n']);
  444. end
  445. else
  446. fprintf('NB: No end-time defined. This will keep running until stopped.\n')
  447. end
  448. %% Run this loop all stimuli the StimSettings file ========================
  449. Par.ESC=false; Log.TotalTimeOut = 0; Par.Pause = false;
  450. update_trackerfix_now = true;
  451. for STIMNR = Log.StimOrder
  452. %% Cycles of stimuli --------------------------------------------------
  453. nCyclesDone=0;
  454. nCyclesReported=0;
  455. Log.TimeOutThisRun=0;
  456. Stm(STIMNR).IsPostDur=false;
  457. if ~Par.ESC
  458. StimLoopNr=StimLoopNr+1;
  459. Log.RunNr=StimLoopNr;
  460. %% Stimulus preparation -------------------------------------------
  461. % Fixation
  462. if StimLoopNr == 1 % only defining the fix window on first loop allows setting it via gui
  463. Stm(STIMNR).FixWinSizePix = round(Stm(STIMNR).FixWinSize*Par.PixPerDeg);
  464. RunParStim_Saved = false;
  465. end
  466. Stm(STIMNR).FixDotSizePix = round(Stm(STIMNR).FixDotSize*Par.PixPerDeg);
  467. Par.RespIndSizePix = round(Par.RespIndSize*Par.PixPerDeg);
  468. Stm(STIMNR).FixDotSurrSizePix = round(Stm(STIMNR).FixDotSurrSize*Par.PixPerDeg);
  469. Par.GoBarSizePix = round(Par.GoBarSize*Par.PixPerDeg);
  470. Stm(STIMNR).Center =[];
  471. for i=1:size(Stm(STIMNR).Position,2)
  472. Stm(STIMNR).Center =[Stm(STIMNR).Center; ...
  473. round(Stm(STIMNR).Position{i}.*Par.PixPerDeg)];
  474. end
  475. % Load retinotopic mapping stimuli
  476. switch Stm(STIMNR).RetMap.StimType{1}
  477. case 'none'
  478. %% only fixation
  479. RetMapStimuli=false;
  480. DispChecker=false;
  481. MovieRun=false;
  482. VLCMovieRun=false;
  483. case 'ret'
  484. %% Population receptive field stim
  485. RetMapStimuli=true;
  486. DispChecker=false;
  487. MovieRun=false;
  488. VLCMovieRun=false;
  489. case 'face'
  490. %% Classic retinotopy: faces
  491. RetMapStimuli=true;
  492. DispChecker=false;
  493. MovieRun=false;
  494. VLCMovieRun=false;
  495. if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
  496. ret_vid=vid_face_ring.ret_vid;
  497. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
  498. ret_vid=vid_face_wedge.ret_vid;
  499. end
  500. case 'walker'
  501. %% Classic retinotopy: walkers
  502. RetMapStimuli=true;
  503. DispChecker=false;
  504. MovieRun=false;
  505. VLCMovieRun=false;
  506. if strcmp(Stm(STIMNR).RetMap.StimType{2},'circle')
  507. ret_vid=vid_walker_ring.ret_vid;
  508. elseif strcmp(Stm(STIMNR).RetMap.StimType{2},'wedge')
  509. ret_vid=vid_walker_wedge.ret_vid;
  510. end
  511. case 'checkerboard'
  512. %% fullscreen checkerboard
  513. fn_lead='fullchecker_';
  514. Stm(STIMNR).Descript = 'FullChecker';
  515. RetMapStimuli=false;
  516. DispChecker=true;
  517. MovieRun=false;
  518. VLCMovieRun=false;
  519. if Stm(STIMNR).RetMap.Checker.LoadFromFile
  520. fprintf(['\nLoading checkerboard ' ...
  521. Stm(STIMNR).RetMap.Checker.FileName '...\n']);
  522. cd Stimuli
  523. cd fullchecker
  524. load(Stm(STIMNR).RetMap.Checker.FileName);
  525. cd ..
  526. cd ..
  527. else
  528. fprintf('\nCreating checkerboard...\n');
  529. % create the checkerboard
  530. chksize = ceil(Stm(STIMNR).RetMap.Checker.Size*Par.PixPerDeg);
  531. chkimg = double(RadialCheckerBoard(...
  532. [chksize ...
  533. ceil(Stm(STIMNR).RetMap.Checker.centerradius*Par.PixPerDeg)], ...
  534. Stm(STIMNR).RetMap.Checker.Sector, ...
  535. Stm(STIMNR).RetMap.Checker.chsz));
  536. if Stm(STIMNR).RetMap.Checker.SaveToFile
  537. fprintf('\nSaving checkerboard...\n');
  538. cd Stimuli
  539. cd fullchecker
  540. save(Stm(STIMNR).RetMap.Checker.FileName,'chkimg');
  541. cd ..
  542. cd ..
  543. end
  544. end
  545. % create texture
  546. CB1R = chkimg(:,:,1)./Par.ScrWhite;
  547. CB1R(chkimg(:,:,1)==Par.ScrWhite) = ...
  548. Stm(STIMNR).RetMap.Checker.Colors(1,1);
  549. CB1R(chkimg(:,:,1)==0) = ...
  550. Stm(STIMNR).RetMap.Checker.Colors(2,1);
  551. CB1G=chkimg(:,:,1)./Par.ScrWhite;
  552. CB1G(chkimg(:,:,1)==Par.ScrWhite) = ...
  553. Stm(STIMNR).RetMap.Checker.Colors(1,2);
  554. CB1G(chkimg(:,:,1)==0) = ...
  555. Stm(STIMNR).RetMap.Checker.Colors(2,2);
  556. CB1B=chkimg(:,:,1)./Par.ScrWhite;
  557. CB1B(chkimg(:,:,1)==Par.ScrWhite) = ...
  558. Stm(STIMNR).RetMap.Checker.Colors(1,3);
  559. CB1B(chkimg(:,:,1)==0) = ...
  560. Stm(STIMNR).RetMap.Checker.Colors(2,3);
  561. CB1A = chkimg(:,:,3);
  562. CB1 = CB1R.*Par.ScrWhite;
  563. CB1(:,:,2)=CB1G.*Par.ScrWhite;
  564. CB1(:,:,3)=CB1B.*Par.ScrWhite;
  565. %CB1(:,:,4)=CB1A;
  566. CB1(:,:,4)=CB1A *1; % Make more transparent
  567. CB2R = chkimg(:,:,2)./Par.ScrWhite;
  568. CB2R(chkimg(:,:,2)==Par.ScrWhite) = ...
  569. Stm(STIMNR).RetMap.Checker.Colors(1,1);
  570. CB2R(chkimg(:,:,2)==0) = ...
  571. Stm(STIMNR).RetMap.Checker.Colors(2,1);
  572. CB2G=chkimg(:,:,2)./Par.ScrWhite;
  573. CB2G(chkimg(:,:,2)==Par.ScrWhite) = ...
  574. Stm(STIMNR).RetMap.Checker.Colors(1,2);
  575. CB2G(chkimg(:,:,2)==0) = ...
  576. Stm(STIMNR).RetMap.Checker.Colors(2,2);
  577. CB2B=chkimg(:,:,2)./Par.ScrWhite;
  578. CB2B(chkimg(:,:,2)==Par.ScrWhite) = ...
  579. Stm(STIMNR).RetMap.Checker.Colors(1,3);
  580. CB2B(chkimg(:,:,2)==0) = ...
  581. Stm(STIMNR).RetMap.Checker.Colors(2,3);
  582. CB2A = chkimg(:,:,3);
  583. CB2 = CB2R.*Par.ScrWhite;
  584. CB2(:,:,2)=CB2G.*Par.ScrWhite;
  585. CB2(:,:,3)=CB2B.*Par.ScrWhite;
  586. %CB2(:,:,4)=CB2A;
  587. CB2(:,:,4)=CB2A *1; % Make more transparent
  588. CheckTexture(1)=Screen('MakeTexture', Par.window, CB1);
  589. CheckTexture(2)=Screen('MakeTexture', Par.window, CB2);
  590. TrackingCheckerContChange = false;
  591. case 'movie'
  592. %% only fixation
  593. RetMapStimuli=false;
  594. DispChecker=false;
  595. MovieRun=true;
  596. VLCMovieRun=false;
  597. moviename = fullfile(Par.ExpFolder,'Stimuli','Movies',...
  598. Stm(STIMNR).RetMap.FileName);
  599. % prepare the movie
  600. [Log.movie.name, Log.movie.duration, ...
  601. Log.movie.fps, Log.movie.imgw, Log.movie.imgh] = ...
  602. Screen('OpenMovie', Par.window, moviename, ...
  603. [], [], [], [], []);
  604. MovieRunning=false;
  605. case 'movie-vlc'
  606. RetMapStimuli=false;
  607. DispChecker=false;
  608. MovieRun=false;
  609. VLCMovieRun=true;
  610. moviebat = fullfile(Par.ExpFolder,'Stimuli','Movies',...
  611. Stm(STIMNR).RetMap.VLC_batfile);
  612. stopVLCbat = fullfile(Par.ExpFolder,'Stimuli','Movies',...
  613. Stm(STIMNR).RetMap.VLC_stop);
  614. MovieRunning=false;
  615. end
  616. fprintf(['\nRun: ' num2str(Log.RunNr)]);
  617. fprintf(['\n-- Stimulus: ' Stm(STIMNR).Descript ' --\n']);
  618. %% Code Control Preparation ---------------------------------------
  619. Par.FixStatToCMD=true;
  620. % Some intitialization of control parameters
  621. if Par.MRITrigger_OnlyOnce && StimLoopNr == 1
  622. Log.MRI.TriggerReceived = false;
  623. elseif ~Par.MRITrigger_OnlyOnce
  624. Log.MRI.TriggerReceived = false;
  625. end
  626. Log.MRI.TriggerTime = [];
  627. Log.ManualReward = false;
  628. Log.ManualRewardTime = [];
  629. Log.TotalReward=0;
  630. % Initial stimulus position is 1
  631. Par.PosNr=1;
  632. Par.PrevPosNr=1;
  633. % Initialize the side of response
  634. Par.ResponseSide=0;
  635. Par.CurrResponseSide=Par.ResponseSide;
  636. Par.CurrOrient=1; % 1=default, 2=switched
  637. Par.Orientation = [1 0]; % [def a1lt] 0=hor, 1=vert
  638. Par.ResponseState = Par.RESP_STATE_DONE;
  639. Par.ResponseStateChangeTime = 0;
  640. % Initialize KeyLogging
  641. Par.KeyIsDown=false;
  642. Par.KeyWasDown=false;
  643. Par.KeyDetectedInTrackerWindow=false;
  644. % Initialize control parameters
  645. Par.SwitchPos = false;
  646. Par.ToggleCyclePos = false; % overrules the Stim(1)setting; toggles with 'p'
  647. Par.ToggleHideStim = false;
  648. Par.ToggleHideFix = false;
  649. Par.ManualReward = false;
  650. Par.PosReset=false;
  651. Par.RewardStarted=false;
  652. Par.MovieStopped=false;
  653. Par.Allow_Calls_To_PTB_win = true;
  654. % Trial Logging
  655. Par.Response = 0; % maintained fixations
  656. Par.ResponsePos = 0; % maintained fixations
  657. Par.RespTimes = [];
  658. Par.ManRewThisTrial=[];
  659. Par.FirstInitDone=false;
  660. Par.CheckFixIn=false;
  661. Par.CheckFixOut=false;
  662. Par.CheckTarget=false;
  663. Par.RewardRunning=false;
  664. % Initialize photosensor manual response
  665. Par.BeamIsBlocked=false(size(Par.ConnectBox.PhotoAmp));
  666. Par.HandIsIn =[false false];
  667. Par.HandWasIn = Par.HandIsIn;
  668. Par.LeverIsUp = [false; false];
  669. Par.LeverWasUp = Par.LeverIsUp;
  670. Par.BothLeversUp_time = Inf;
  671. AutoPauseStartTime = Inf;
  672. AutoPausing = false;
  673. %video control
  674. Par.VideoLoaded=false;
  675. Par.VideoPlaying=false;
  676. Par.VidNumber=1;
  677. Par.nVidStarted=0;
  678. Par.VidFrameTime=-1;
  679. Par.LastVidFrameTime=-1;
  680. Par.VidFrameNr=1;
  681. Par.VidCycleNr=1;
  682. Par.VidTexMade=false;
  683. Par.VideoAppend=false;
  684. LogFirstVidStartTime=false;
  685. FirstVidDrawn=false;
  686. % keep track of timing
  687. Log.lfts=[];
  688. %Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite); % black first
  689. % Flip the proper background on screen
  690. %Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
  691. if ~Par.Pause
  692. Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
  693. else
  694. Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite); % black first
  695. end
  696. lft=Screen('Flip', Par.window);
  697. Par.ExpStart = lft;
  698. Log.nEvents=1;
  699. Log.Events = [];
  700. Log.Events(Log.nEvents).event='ExpStart';
  701. Log.Events(Log.nEvents).t=0;
  702. Log.Events(Log.nEvents).info='Start';
  703. Log.Eye =[];
  704. Par.CurrEyePos = [];
  705. Par.CurrEyeZoom = [];
  706. EyeRecMsgShown=false;
  707. RunEnded=false;
  708. %% Eye-tracker recording
  709. if Par.EyeRecAutoTrigger
  710. if ~FirstEyeRecSet
  711. SetEyeRecStatus(0); % send record off signal
  712. hmb=msgbox('Prepare the eye-tracker for recording','Eye-tracking');
  713. uiwait(hmb);
  714. FirstEyeRecSet=true;
  715. pause(1);
  716. end
  717. MoveOn=false;
  718. StartSignalSent=false;
  719. while ~MoveOn
  720. StartEyeRecCheck = GetSecs;
  721. while ~Par.EyeRecStatus && GetSecs < StartEyeRecCheck + 3 % check for 3 seconds
  722. CheckEyeRecStatus; % checks the current status of eye-recording
  723. if ~StartSignalSent
  724. SetEyeRecStatus(1);
  725. StartSignalSent=true;
  726. end
  727. end
  728. BreakTime = GetSecs;
  729. if Par.EyeRecStatus % recording
  730. StartedEyeRecTime=BreakTime;
  731. fprintf('Started recording eyetrace\n');
  732. MoveOn=true;
  733. else
  734. fprintf('not recording yet\n')
  735. SetEyeRecStatus(1); %trigger recording
  736. end
  737. end
  738. else
  739. fprintf('Eye recording not triggered (ephys or training?). Make sure it''s running!\n');
  740. end
  741. %% MRI triggered start
  742. Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
  743. lft=Screen('Flip', Par.window);
  744. if Par.MRITriggeredStart
  745. fprintf('Waiting for MRI trigger (or press ''t'' on keyboard)\n');
  746. while ~Log.MRI.TriggerReceived
  747. CheckKeys;
  748. %Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
  749. %lft=Screen('Flip', Par.window);
  750. end
  751. if Par.MRITrigger_OnlyOnce && lft-Par.ExpStart == 0
  752. fprintf('Triggering only once, move on automatically now.\n');
  753. else
  754. fprintf(['MRI trigger received after ' num2str(GetSecs-Par.ExpStart) ' s\n']);
  755. end
  756. end
  757. else
  758. if VLCMovieRun
  759. if MovieRunning
  760. eval(['!' stopVLCbat])
  761. Reopen_PTB_win;
  762. MovieRunning=false;
  763. end
  764. end
  765. end
  766. %% Displaying the stimuli ---------------------------------------------
  767. while ~Par.ESC && ~RunEnded
  768. while ~Par.FirstInitDone
  769. %set control window positions and dimensions
  770. if ~TestRunstimWithoutDAS
  771. DefineEyeWin(STIMNR);
  772. refreshtracker(1) %for your control display
  773. last_tracker_update = GetSecs;
  774. SetWindowDas; %for the dascard, initializes eye control windows
  775. end
  776. Par.Trlcount = Par.Trlcount+1; %keep track of trial numbers
  777. % send trial nr to ephys rig
  778. if strcmp(Par.SetUp,'NIN') % ephys
  779. %dasword(Par.Trlcount(1)); % TDT
  780. send_serial_data(Par.Trlcount(1)); % Blackrock
  781. WordsSent+1; %#ok<*VUNUS>
  782. Log.Words(WordsSent)=Par.Trlcount(1);
  783. Log.nEvents=Log.nEvents+1;
  784. Log.Events(Log.nEvents).event='TrialStart';
  785. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  786. Log.Events(Log.nEvents).info = Par.Trlcount(1);
  787. end
  788. Par.ResponseGiven=false;
  789. Par.FalseResponseGiven=false;
  790. Par.RespValid = false;
  791. Par.CorrectThisTrial=false;
  792. Par.LastFixInTime=0;
  793. Par.LastFixOutTime=0;
  794. Par.FixIn=false; %initially set to 'not fixating'
  795. Par.CurrFixCol=Stm(STIMNR).FixDotCol(1,:).*Par.ScrWhite;
  796. Par.FixInOutTime=[0 0];
  797. Par.FirstStimDrawDone=false;
  798. Par.ForceRespSide = false;
  799. Par.IsCatchBlock = false;
  800. Par.RewHandStart = GetSecs;
  801. Par.HandInNew_Moment = 0;
  802. Par.HandInPrev_Moment = 0;
  803. Par.PickRandomIndicatorPosition = true;
  804. Par.s_order=[1]; %#ok<*NBRAK>
  805. if StimLoopNr == 1 % allow time-outs to across runs
  806. Par.Pause=false;
  807. end
  808. if Par.Pause
  809. Screen('FillRect',Par.window,[0 0 0]);
  810. lft=Screen('Flip', Par.window); %initial flip to sync up timing
  811. else
  812. lft=Screen('Flip', Par.window); %initial flip to sync up timing
  813. end
  814. nf=0;
  815. Log.StartBlock=lft;
  816. Stm(STIMNR).IsPreDur=true;
  817. Log.nEvents=Log.nEvents+1;
  818. Log.Events(Log.nEvents).event='PreDurStart';
  819. Log.Events(Log.nEvents).t=Log.StartBlock-Par.ExpStart;
  820. Log.Events(Log.nEvents).info = 'Start';
  821. if TestRunstimWithoutDAS; Hit=0; end
  822. PreStarted = false;
  823. OnStarted = false;
  824. OffStarted = false;
  825. PostStarted = false;
  826. CurrPostErrorDelay = 0;
  827. nNonCatchTrials = 0;
  828. LastMissed = false;
  829. NumberOfConsecutiveErrors=0;
  830. if Par.CatchBlock.StartWithCatch
  831. Prev_nNonCatchTrials = -1;
  832. else
  833. Prev_nNonCatchTrials = nNonCatchTrials;
  834. end
  835. Log.dtm=[];
  836. if strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
  837. RESP_NONE = 0;
  838. RESP_CORRECT = 1;
  839. RESP_FALSE = 2;
  840. RESP_MISS = 3;
  841. RESP_EARLY = 4;
  842. RESP_BREAK_FIX = 5;
  843. RespText = {'Correct', 'False', 'Miss', 'Early', 'Fix. break'};
  844. Par.ManResponse = [0 0 0 0 0];
  845. end
  846. RewardGivenForHandPos=false;
  847. Par.FirstInitDone=true;
  848. end
  849. %% Check what to draw depending on time ---------------------------
  850. if RetMapStimuli || MovieRun || VLCMovieRun
  851. if GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur % PreDur
  852. IsPre=true;
  853. IsPost=false;
  854. if ~PreStarted
  855. PreStarted = true;
  856. CheckStartLogged = false;
  857. Log.nEvents=Log.nEvents+1;
  858. Log.Events(Log.nEvents).event='PreDurStart';
  859. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  860. Log.Events(Log.nEvents).info = 'Start';
  861. posn=0;
  862. end
  863. elseif RetMapStimuli && ...
  864. GetSecs >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur && ...
  865. GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  866. (Stm(STIMNR).RetMap.nCycles*size(Stm(STIMNR).RetMap.posmap,1)*...
  867. Stm(STIMNR).RetMap.TRsPerStep*Par.TR) % in stimulus cycle
  868. IsPre=false;
  869. IsPost=false;
  870. if ~OnStarted
  871. OnStarted=true;
  872. Log.nEvents=Log.nEvents+1;
  873. Log.Events(Log.nEvents).event='StimON';
  874. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  875. Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
  876. end
  877. TRn=ceil((GetSecs-Log.StartBlock-Stm(STIMNR).RetMap.PreDur)/Par.TR);
  878. prevposn=posn;
  879. posn = ceil(TRn/Stm(STIMNR).RetMap.TRsPerStep);
  880. while posn>size(Stm(STIMNR).RetMap.posmap,1)
  881. posn=posn-size(Stm(STIMNR).RetMap.posmap,1);
  882. end
  883. posn=Stm(STIMNR).RetMap.posmap(posn,2);
  884. if posn ~= prevposn
  885. Log.nEvents=Log.nEvents+1;
  886. Log.Events(Log.nEvents).event='NewPosition';
  887. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  888. Log.Events(Log.nEvents).info = posn;
  889. if strcmp(Par.SetUp,'NIN') % ephys
  890. dasbit(Par.StimB,1);
  891. daspause(0.05);
  892. dasbit(Par.StimB,0);
  893. %send_serial_data(posn);
  894. %WordsSent+1;
  895. %Log.Words(WordsSent)=posn;
  896. end
  897. end
  898. if strcmp(Stm(STIMNR).RetMap.StimType{1},'ret') && posn
  899. posn_adj = mod(posn-1,length(stimulus(1).img))+1;
  900. texn = ceil(mod(GetSecs-Log.StartBlock,Par.TR)*...
  901. ret_vid(posn_adj).fps);
  902. if ~texn; texn=1; end
  903. while texn>numel(ret_vid(posn_adj).text)
  904. texn=texn-numel(ret_vid(posn_adj).text);
  905. end
  906. elseif posn
  907. % posn_adj = mod(posn-1,length(stimulus(1).img))+1;
  908. % texn = ceil(mod(GetSecs-Log.StartBlock,Par.TR)*...
  909. % ret_vid(Stm(STIMNR).Order(posn_adj)).fps);
  910. % if ~texn; texn=1; end;
  911. % while texn>numel(ret_vid(Stm(STIMNR).Order(posn_adj)).text);
  912. % texn=texn-numel(ret_vid(Stm(STIMNR).Order(posn_adj)).text);
  913. % end
  914. texn = ceil(mod(GetSecs-Log.StartBlock,Par.TR)*...
  915. ret_vid(Stm(STIMNR).Order(posn)).fps);
  916. if ~texn; texn=1; end
  917. while texn>numel(ret_vid(Stm(STIMNR).Order(posn)).text)
  918. texn=texn-numel(ret_vid(Stm(STIMNR).Order(posn)).text);
  919. end
  920. end
  921. elseif (MovieRun || VLCMovieRun) && ...
  922. GetSecs >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur && ...
  923. GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  924. (Stm(STIMNR).RetMap.moviedur/Stm(STIMNR).RetMap.movierate)
  925. IsPre=false;
  926. IsPost=false;
  927. if ~OnStarted
  928. OnStarted=true;
  929. Log.nEvents=Log.nEvents+1;
  930. Log.Events(Log.nEvents).event='StimON';
  931. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  932. Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
  933. end
  934. elseif RetMapStimuli && ...
  935. GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  936. (Stm(STIMNR).RetMap.nCycles*size(Stm(STIMNR).RetMap.posmap,1)*...
  937. Stm(STIMNR).RetMap.TRsPerStep*Par.TR) + ...
  938. Stm(STIMNR).RetMap.PostDur % PostDur
  939. IsPre=false;
  940. IsPost = true;
  941. if ~PostStarted
  942. PostStarted=true;
  943. Log.nEvents=Log.nEvents+1;
  944. Log.Events(Log.nEvents).event='PostDurStart';
  945. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  946. Log.Events(Log.nEvents).info = 'Start';
  947. tPostStarted=GetSecs;
  948. end
  949. elseif MovieRun && ...
  950. GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  951. (Stm(STIMNR).RetMap.moviedur/Stm(STIMNR).RetMap.movierate) + ...
  952. Stm(STIMNR).RetMap.PostDur % PostDur
  953. IsPre=false;
  954. IsPost = true;
  955. if ~PostStarted
  956. PostStarted=true;
  957. Log.nEvents=Log.nEvents+1;
  958. Log.Events(Log.nEvents).event='PostDurStart';
  959. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  960. Log.Events(Log.nEvents).info = 'Start';
  961. tPostStarted=GetSecs;
  962. % Done. Stop playback:
  963. Screen('PlayMovie', Log.movie.name, 0);
  964. % Close movie object:
  965. Screen('CloseMovie', Log.movie.name);
  966. MovieRunning=false;
  967. end
  968. elseif VLCMovieRun && ...
  969. GetSecs < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  970. Stm(STIMNR).RetMap.moviedur + Stm(STIMNR).RetMap.PostDur % PostDur
  971. IsPre=false;
  972. IsPost = true;
  973. if ~PostStarted
  974. PostStarted=true;
  975. Log.nEvents=Log.nEvents+1;
  976. Log.Events(Log.nEvents).event='PostDurStart';
  977. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  978. Log.Events(Log.nEvents).info = 'Start';
  979. tPostStarted=GetSecs;
  980. % Done. Stop playback:
  981. eval(['!' stopVLCbat])
  982. Reopen_PTB_win;
  983. MovieRunning=false;
  984. end
  985. else
  986. RunEnded=true;
  987. IsPre=false;
  988. IsPost=false;
  989. Log.nEvents=Log.nEvents+1;
  990. Log.Events(Log.nEvents).event='RunStop';
  991. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  992. Log.Events(Log.nEvents).info = 'Stop';
  993. end
  994. DrawChecker=false;
  995. elseif DispChecker % coarse checkerboard
  996. %% fullscreen checkerboard
  997. if lft < Log.StartBlock+Stm(STIMNR).RetMap.PreDur
  998. IsPre = true;
  999. IsOn = false;
  1000. IsOff = false;
  1001. IsPost = false;
  1002. if ~PreStarted
  1003. PreStarted = true;
  1004. CheckStartLogged = false;
  1005. Log.CheckerON=[];
  1006. Log.CheckerOFF=[];
  1007. CheckStartLogged=false;
  1008. CheckStopLogged=false;
  1009. ChkNum = 1;
  1010. end
  1011. WasPreDur=true;
  1012. DrawChecker = false;
  1013. elseif mod(lft-Log.StartBlock-Stm(STIMNR).RetMap.PreDur,...
  1014. sum(Stm(STIMNR).RetMap.Checker.OnOff)) <= ...
  1015. Stm(STIMNR).RetMap.Checker.OnOff(1) && ...
  1016. lft < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  1017. sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles
  1018. IsPre = false;
  1019. IsOn = true;
  1020. IsOff = false;
  1021. IsPost = false;
  1022. if ~OnStarted
  1023. OnStarted=true;
  1024. OffStarted=false;
  1025. Log.CheckerON = [Log.CheckerON; lft];
  1026. Log.nEvents=Log.nEvents+1;
  1027. Log.Events(Log.nEvents).event='StimON';
  1028. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  1029. Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
  1030. CheckStartLogged = true;
  1031. CheckStopLogged =false;
  1032. end
  1033. if WasPreDur % coming out of predur
  1034. Par.FixInOutTime=[Par.FixInOutTime;0 0];
  1035. WasPreDur=false;
  1036. end
  1037. if nCyclesDone < Stm(STIMNR).RetMap.nCycles || ...
  1038. ~Stm(STIMNR).RetMap.nCycles
  1039. DrawChecker = true;
  1040. if nCyclesDone > 0 && nCyclesReported < nCyclesDone
  1041. %output fixation statistics
  1042. if Par.FixStatToCMD
  1043. fprintf(['Fix perc. cycle ' num2str(nCyclesDone) ': ' ...
  1044. sprintf('%0.1f',...
  1045. 100*(Par.FixInOutTime(end,1)/sum(Par.FixInOutTime(end,:)))) ...
  1046. '%%, Run: ' ...
  1047. sprintf('%0.1f',...
  1048. 100*(sum(Par.FixInOutTime(2:end,1))/sum(sum(Par.FixInOutTime(2:end,:))))) ...
  1049. '%%\n']);
  1050. Par.FixInOutTime = [Par.FixInOutTime;0 0];
  1051. nCyclesReported=nCyclesReported+1;
  1052. end
  1053. end
  1054. end
  1055. elseif mod(lft-Log.StartBlock-Stm(STIMNR).RetMap.PreDur-Stm(STIMNR).RetMap.Checker.OnOff(1),...
  1056. sum(Stm(STIMNR).RetMap.Checker.OnOff)) <= ...
  1057. Stm(STIMNR).RetMap.Checker.OnOff(1) && ...
  1058. lft < Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  1059. sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles
  1060. IsPre = false;
  1061. IsOn = false;
  1062. IsOff = true;
  1063. IsPost = false;
  1064. if ~OffStarted
  1065. OffStarted=true;
  1066. OnStarted=false;
  1067. Log.CheckerOFF = [Log.CheckerOFF; lft];
  1068. Log.nEvents=Log.nEvents+1;
  1069. Log.Events(Log.nEvents).event='StimOFF';
  1070. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  1071. Log.Events(Log.nEvents).info = Stm(STIMNR).Descript;
  1072. nCyclesDone=nCyclesDone+1;
  1073. CheckStartLogged = false;
  1074. CheckStopLogged =true;
  1075. end
  1076. DrawChecker = false;
  1077. elseif mod(lft-Log.StartBlock-Stm(STIMNR).RetMap.PreDur,...
  1078. sum(Stm(STIMNR).RetMap.Checker.OnOff)) <= ...
  1079. Stm(STIMNR).RetMap.Checker.OnOff(1) && ...
  1080. lft >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  1081. sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles && ...
  1082. ~PostStarted
  1083. IsPre = false;
  1084. IsOn = false;
  1085. IsOff = false;
  1086. IsPost = true;
  1087. if ~PostStarted
  1088. PostStarted=true;
  1089. Log.StartPostDur=lft;
  1090. Log.nEvents=Log.nEvents+1;
  1091. Log.Events(Log.nEvents).event='PostDurStart';
  1092. Log.Events(Log.nEvents).t=Log.StartPostDur-Par.ExpStart;
  1093. Log.Events(Log.nEvents).info = 'Start';
  1094. DrawChecker = false;
  1095. if nCyclesDone > 0 && nCyclesReported < nCyclesDone
  1096. %output fixation statistics
  1097. if Par.FixStatToCMD
  1098. fprintf(['Fix perc. cycle ' num2str(nCyclesDone) ': ' ...
  1099. sprintf('%0.1f',...
  1100. 100*(Par.FixInOutTime(end,1)/sum(Par.FixInOutTime(end,:)))) ...
  1101. '%%, Run: ' ...
  1102. sprintf('%0.1f',...
  1103. 100*(sum(Par.FixInOutTime(2:end,1))/sum(sum(Par.FixInOutTime(2:end,:))))) ...
  1104. '%%\n']);
  1105. Par.FixInOutTime = [Par.FixInOutTime;0 0];
  1106. nCyclesReported=nCyclesReported+1;
  1107. end
  1108. end
  1109. end
  1110. elseif lft >= Log.StartBlock + Stm(STIMNR).RetMap.PreDur + ...
  1111. sum(Stm(STIMNR).RetMap.Checker.OnOff)*Stm(STIMNR).RetMap.nCycles + ...
  1112. Stm(STIMNR).RetMap.PostDur
  1113. RunEnded = true;
  1114. Log.nEvents=Log.nEvents+1;
  1115. Log.Events(Log.nEvents).event='RunStop';
  1116. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  1117. Log.Events(Log.nEvents).info = 'Stop';
  1118. end
  1119. else
  1120. DrawChecker = false;
  1121. end
  1122. prevlft=lft;
  1123. FixTimeThisFlip = 0; NonFixTimeThisFlip = 0;
  1124. Par.LastFlipFix = Par.FixIn;
  1125. %% Check if eye enters fixation window ----------------------------
  1126. if ~Par.FixIn %not fixating
  1127. if ~Par.CheckFixIn && ~TestRunstimWithoutDAS
  1128. dasreset(0); % start testing for eyes moving into fix window
  1129. % sets timer to 0
  1130. %fprintf('dasreset in\n')
  1131. end
  1132. Par.CheckFixIn=true;
  1133. Par.CheckFixOut=false;
  1134. Par.CheckTarget=false;
  1135. elseif Par.FixIn %fixating
  1136. if ~Par.CheckFixOut && ~TestRunstimWithoutDAS
  1137. dasreset(1); % start testing for eyes leaving fix window
  1138. % sets timer to 0
  1139. %fprintf('dasreset out\n')
  1140. end
  1141. Par.CheckFixIn=false;
  1142. Par.CheckFixOut=true;
  1143. Par.CheckTarget=false;
  1144. end
  1145. %% Check eye position ---------------------------------------------
  1146. %Hit=0;
  1147. if ~TestRunstimWithoutDAS
  1148. dasrun(5); % takes max 5 ms
  1149. [Hit, Time] = DasCheck;
  1150. %Hit = LPStat(1); %Hit yes or no
  1151. %Time = LPStat(0); %time
  1152. end
  1153. %% interpret ------------------------------------------------------
  1154. if Par.CheckFixIn && Hit~=0
  1155. % add time to fixation duration
  1156. NonFixTimeThisFlip = NonFixTimeThisFlip+Time;
  1157. Par.FixIn=true;
  1158. %fprintf('fix in detected\n')
  1159. Par.LastFixInTime=GetSecs;
  1160. %Par.GoBarOnset = rand(1)*Par.EventPeriods(2)/1000 + ...
  1161. % Par.EventPeriods(1)/1000;
  1162. elseif Par.CheckFixOut && Hit~=0
  1163. % add time to non-fixation duration
  1164. FixTimeThisFlip = FixTimeThisFlip+Time;
  1165. Par.FixIn=false;
  1166. %fprintf('fix out detected\n')
  1167. Par.LastFixOutTime=GetSecs;
  1168. end
  1169. %% Do this routine for all remaining flip time --------------------
  1170. DoneOnce=false;
  1171. while ~DoneOnce || GetSecs < prevlft+0.80*Par.fliptimeSec
  1172. DoneOnce=true;
  1173. %% check for key-presses --------------------------------------
  1174. CheckKeys; % internal function
  1175. %% Change stimulus if required --------------------------------
  1176. ChangeStimulus(STIMNR);
  1177. %% give manual reward -----------------------------------------
  1178. if Par.ManualReward && ~TestRunstimWithoutDAS
  1179. GiveRewardManual;
  1180. Par.ManualReward=false;
  1181. end
  1182. %% give reward for hand in box --------------------------------
  1183. if Par.RewardForHandsIn && ...
  1184. any(Par.HandIsIn) && ~Par.Pause && ...
  1185. ~Par.RewardRunning && ...
  1186. GetSecs - Par.HandInNew_Moment > Par.RewardForHandsIn_Delay
  1187. if GetSecs - Par.RewHandStart > Par.RewardForHandIn_MinInterval % kept in long enough
  1188. GiveRewardAutoHandIn;
  1189. elseif Par.RewardForHandIn_ResetIntervalWhenOut && ...
  1190. Par.HandInPrev_Moment ~= Par.HandInNew_Moment && ...
  1191. GetSecs - Par.RewHandStart > Par.RewardForHandIn_MinIntervalBetween
  1192. GiveRewardAutoHandIn;
  1193. end
  1194. end
  1195. %% check photosensor ------------------------------------------
  1196. if ~TestRunstimWithoutDAS
  1197. CheckManual;
  1198. if ~strcmp(Par.ResponseBox.Task,'DetectGoSignal') && ...
  1199. Par.StimNeeds.HandIsIn && ...
  1200. ((strcmp(Par.HandInBothOrEither,'Both') && ~any(Par.HandIsIn)) || ...
  1201. (strcmp(Par.HandInBothOrEither,'Either') && ~all(Par.HandIsIn)))
  1202. % assumes only 1 photo-channel in use, or only checks
  1203. % first defined channel
  1204. Par.FixIn = false;
  1205. % reset the fixation status to false if his hands are not where
  1206. % they should be, otherwise he may get an immediate reward when
  1207. % he maintains the proper eye-position and puts his hand in
  1208. %
  1209. % Doing this via StimNeedsHandInBox allows showing a fix dot
  1210. % which is only marked as fixating when the hands are also in
  1211. % the box
  1212. end
  1213. end
  1214. %% Stop reward ------------------------------------------------
  1215. StopRewardIfNeeded();
  1216. end
  1217. %% Draw stimulus --------------------------------------------------
  1218. if ~Par.Pause
  1219. if RetMapStimuli
  1220. DrawStimuli;
  1221. if ~IsPre && ~IsPost && ~RunEnded && ~Par.ToggleHideStim ...
  1222. && ~Par.HideStim_BasedOnHandIn(Par) ...
  1223. && ~Par.Pause
  1224. if strcmp(Stm(STIMNR).RetMap.StimType{1},'ret')
  1225. posn_adj = (mod(posn-1,length(stimulus(1).img))+1);
  1226. orinum = ceil(posn/length(stimulus(1).img));
  1227. if posn
  1228. if strcmp(Stm(STIMNR).RetMap.StimType{2},'pRF_8bar')
  1229. Screen('DrawTexture',Par.window,ret_vid(posn_adj).text(texn),...
  1230. [],[],ret_vid(posn).orient(orinum),1);
  1231. else
  1232. Screen('DrawTexture',Par.window,ret_vid(posn).text(texn),...
  1233. [],[],[],1);
  1234. end
  1235. end
  1236. else
  1237. if posn
  1238. Screen('DrawTexture',Par.window,ret_vid(posn).text(texn),...
  1239. [],[Par.ScrCenter(1)-Par.wrect(4)/2 0 ...
  1240. Par.ScrCenter(1)+Par.wrect(4)/2 Par.wrect(4)],...
  1241. [],1);
  1242. end
  1243. end
  1244. end
  1245. elseif MovieRun || VLCMovieRun
  1246. if MovieRun
  1247. DrawStimuli;
  1248. end
  1249. if ~IsPre && ~IsPost && ~RunEnded && ~Par.ToggleHideStim ...
  1250. && ~Par.HideStim_BasedOnHandIn(Par) ...
  1251. && ~Par.Pause
  1252. % start the movie if it hasn't started yet
  1253. if ~MovieRunning
  1254. if MovieRun
  1255. Screen('PlayMovie', Log.movie.name, Stm(STIMNR).RetMap.movierate, 1, 0);
  1256. % looping avoid early stops (duration is regulated
  1257. % based on movieduration separately)
  1258. MovieRunning=true;
  1259. % calculate movie presentation size
  1260. PlayWindow = [ (Par.wrect(3)-Stm(STIMNR).RetMap.PlaySize(1))/2 0 ...
  1261. Par.wrect(3)-(Par.wrect(3)-Stm(STIMNR).RetMap.PlaySize(1))/2 ...
  1262. Stm(STIMNR).RetMap.PlaySize(2)];
  1263. elseif VLCMovieRun
  1264. fprintf('\n========================================\n');
  1265. fprintf('Temporarily closing PTB window for VLC\n');
  1266. fprintf('========================================\n');
  1267. Close_PTB_win;
  1268. eval(['!' moviebat ' &']);
  1269. MovieRunning=true;
  1270. end
  1271. end
  1272. if MovieRun
  1273. % grab a texture
  1274. movietex = Screen('GetMovieImage', Par.window, Log.movie.name, 1);
  1275. % draw that texture
  1276. if movietex>0
  1277. Screen('DrawTexture', Par.window, movietex, [], ...
  1278. PlayWindow, [], [], [], [], []);
  1279. end
  1280. end
  1281. end
  1282. elseif DrawChecker
  1283. DrawStimuli;
  1284. if ~Par.HideStim_BasedOnHandIn(Par) && ~Par.Pause
  1285. Screen('DrawTexture',Par.window,CheckTexture(ChkNum),[],...
  1286. [],[],1);
  1287. end
  1288. else
  1289. DrawStimuli;
  1290. end
  1291. end
  1292. %% Draw fixation dot ----------------------------------------------
  1293. if ~Par.ToggleHideFix ...
  1294. && ~Par.HideFix_BasedOnHandIn(Par) ...
  1295. && ~Par.Pause && ~MovieRun && ~VLCMovieRun
  1296. DrawFix(STIMNR);
  1297. end
  1298. if ~FixTimeThisFlip && ~NonFixTimeThisFlip
  1299. % new event
  1300. if FixTimeThisFlip > NonFixTimeThisFlip % more fixation than not
  1301. Par.AddFixIn = true;
  1302. else
  1303. Par.AddFixIn = false;
  1304. end
  1305. else
  1306. % continuation of previous flip
  1307. if Par.FixIn % already fixating
  1308. Par.AddFixIn = true;
  1309. else
  1310. Par.AddFixIn = false;
  1311. end
  1312. end
  1313. %% darken the screen if on time-out -------------------------------
  1314. if Par.Pause
  1315. Screen('FillRect',Par.window,[0 0 0]);
  1316. end
  1317. %% Calculate proportion fixation for this flip-time and label it --
  1318. % fix or no-fix
  1319. if Par.FixIn
  1320. if Par.RewardFixFeedBack
  1321. Par.CurrFixCol=Stm(STIMNR).FixDotCol(2,:).*Par.ScrWhite;
  1322. end
  1323. Par.Trlcount=Par.Trlcount+1;
  1324. %refreshtracker(3);
  1325. if GetSecs >= Par.LastFixInTime+Par.Times.TargCurrent/1000 % fixated long enough
  1326. % start Reward
  1327. if ~Par.RewardRunning && ~TestRunstimWithoutDAS && ~Par.Pause && ...
  1328. Par.Rew_BasedOnHandIn(Par) && ~Par.HideFix_BasedOnHandIn(Par)
  1329. % nCons correct fixations
  1330. Par.CorrStreakcount=Par.CorrStreakcount+1;
  1331. Par.Response=Par.Response+1;
  1332. Par.ResponsePos=Par.ResponsePos+1;
  1333. % Start reward ========================================
  1334. if ~strcmp(Par.ResponseBox.Task, 'DetectGoSignal') % when not doing task
  1335. GiveRewardAutoFix; % ------------------------ Fix Reward
  1336. Par.RewardRunning=true;
  1337. Par.RewardStartTime=GetSecs;
  1338. Par.LastFixInTime=Par.RewardStartTime; % reset start fix time
  1339. end
  1340. Par.Trlcount=Par.Trlcount+1;
  1341. %refreshtracker(1);refreshtracker(3);
  1342. end
  1343. end
  1344. else
  1345. Par.CurrFixCol=Stm(STIMNR).FixDotCol(1,:).*Par.ScrWhite;
  1346. Par.CorrStreakcount=[0 0];
  1347. %refreshtracker(1);
  1348. end
  1349. %% Stop reward ----------------------------------------------------
  1350. StopRewardIfNeeded();
  1351. %% Autopause due to lever lifts -----------------------------------
  1352. if Par.LeversUpTimeOut(2) % there is a timeout interval defined
  1353. if all(Par.LeverIsUp) && ... % both up
  1354. GetSecs > Par.BothLeversUp_time + Par.LeversUpTimeOut(1) && ...
  1355. ~Par.Pause % levers have been up too long
  1356. Par.Pause=true;
  1357. fprintf(['Automatic time-out due to lever lifts ON (min ' ...
  1358. num2str(Par.LeversUpTimeOut(2)) 's)\n']);
  1359. Log.nEvents=Log.nEvents+1;
  1360. Log.Events(Log.nEvents).event='AutoPauseOn';
  1361. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  1362. Log.Events(Log.nEvents).info = 'Start';
  1363. AutoPauseStartTime=GetSecs;
  1364. AutoPausing = true;
  1365. elseif GetSecs > AutoPauseStartTime + Par.LeversUpTimeOut(2) && ...
  1366. Par.Pause && AutoPausing % Time-out time over
  1367. if all(Par.LeverIsUp)
  1368. % still both up, continue time-out
  1369. else
  1370. Par.Pause=false;
  1371. fprintf('Automatic time-out due to lever lifts OFF\n');
  1372. Log.nEvents=Log.nEvents+1;
  1373. Log.Events(Log.nEvents).event='AutoPauseOff';
  1374. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  1375. Log.Events(Log.nEvents).info = 'Stop';
  1376. AutoPausing = false;
  1377. end
  1378. end
  1379. end
  1380. %% if doing Par.ResponseBox.Task of 'DetectGoSignal': -------------
  1381. if strcmp(Par.ResponseBox.Task, 'DetectGoSignal') && ~TestRunstimWithoutDAS
  1382. % ==== Start wait period ====
  1383. if Par.ResponseState == Par.RESP_STATE_DONE && ...
  1384. Par.CanStartTrial(Par)
  1385. UpdateHandTaskState(Par.RESP_STATE_WAIT);
  1386. %Par.ResponseState = Par.RESP_STATE_WAIT;
  1387. %Par.ResponseStateChangeTime = GetSecs;
  1388. StartWaitTime = Par.ResponseStateChangeTime;
  1389. if Par.PickRandomIndicatorPosition
  1390. Par.s_order=randperm(size(Par.RespIndPos,1));
  1391. Par.PickRandomIndicatorPosition = false;
  1392. end
  1393. if ~Par.IsCatchBlock
  1394. if Par.ResponseSide == 0 || Par.ForceRespSide
  1395. if NumberOfConsecutiveErrors >= Par.MaxNumberOfConsecutiveErrors
  1396. if Par.ResponseSide == 1
  1397. Par.ResponseSide = 2;
  1398. else
  1399. Par.ResponseSide =1;
  1400. end
  1401. else
  1402. if Par.RespProbSetting % 0=random, 1=left, 2=right
  1403. Par.ResponseSide = Par.RespProbSetting;
  1404. else
  1405. Par.ResponseSide = randi([1 2]);
  1406. Par.ForceRespSide = false;
  1407. end
  1408. end
  1409. end
  1410. elseif Par.IsCatchBlock % catchblock
  1411. Par.ResponseSide = CatchSides(1);
  1412. end
  1413. Par.CurrResponseSide = Par.ResponseSide;
  1414. Log.Events(Log.nEvents).info = num2str(Par.ResponseSide);
  1415. Par.GoBarOnset = rand(1)*Par.EventPeriods(2)/1000 + ...
  1416. Par.EventPeriods(1)/1000 + CurrPostErrorDelay/1000;
  1417. Par.WaitIndicatorOnset = Par.DrawDuringWait_SOA + CurrPostErrorDelay/1000;
  1418. % Give side indicator (1 or 2) ... again
  1419. Log.nEvents=Log.nEvents+1;
  1420. Log.Events(Log.nEvents).event=strcat(...
  1421. 'HandTask-TargetSide', num2str(Par.ResponseSide));
  1422. Log.Events(Log.nEvents).t=Par.ResponseStateChangeTime;
  1423. % ==== During wait period ====
  1424. elseif Par.ResponseState == Par.RESP_STATE_WAIT
  1425. if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
  1426. if GetSecs >= Par.ResponseStateChangeTime + Par.GoBarOnset
  1427. UpdateHandTaskState(Par.RESP_STATE_GO);
  1428. %Par.ResponseState = Par.RESP_STATE_GO;
  1429. %Par.ResponseStateChangeTime = GetSecs;
  1430. CurrPostErrorDelay=0;
  1431. end
  1432. % check for early responses before go-signal -----
  1433. t = GetSecs;
  1434. if (Par.CorrectResponseGiven(Par) || ... % Early during wait
  1435. Par.IncorrectResponseGiven(Par))
  1436. UpdateHandTaskState(Par.RESP_STATE_DONE);
  1437. if Par.CorrectResponseGiven(Par)
  1438. Log.Events(Log.nEvents).info = 'EarlyCorrect';
  1439. else
  1440. Log.Events(Log.nEvents).info = 'EarlyIncorrect';
  1441. end
  1442. Par.ManResponse(RESP_EARLY) = Par.ManResponse(RESP_EARLY)+1;
  1443. %fprintf('Early during wait\n');
  1444. CurrPostErrorDelay = Par.PostErrorDelay;
  1445. if ~Par.ForceRespSide
  1446. if rand(1) <= Par.ProbSideRepeatOnEarly % same side
  1447. Par.ResponseSide=Par.ResponseSide; % keep same
  1448. else
  1449. if Par.ResponseSide==1
  1450. Par.ResponseSide=2;
  1451. else
  1452. Par.ResponseSide=1;
  1453. end
  1454. end
  1455. end
  1456. if Par.IsCatchBlock
  1457. CatchSides = Shuffle(CatchSides);
  1458. else
  1459. nNonCatchTrials = nNonCatchTrials+1;
  1460. end
  1461. LastMissed = false;
  1462. % play feedback sound
  1463. if Par.ResponseState > 0 && ...
  1464. isfield(Par, 'FeedbackSound') && ...
  1465. isfield(Par, 'FeedbackSoundPar') && ...
  1466. Par.FeedbackSound(4) && ...
  1467. all(~isnan(Par.FeedbackSoundPar(4,:)))
  1468. if Par.FeedbackSoundPar(4)
  1469. try
  1470. % fprintf('trying to play a sound\n')
  1471. PsychPortAudio('Start', ...
  1472. Par.FeedbackSoundSnd(4).h, 1, 0, 1);
  1473. catch
  1474. end
  1475. end
  1476. end
  1477. end
  1478. % -----
  1479. % ==== Go signal is given ====
  1480. elseif Par.ResponseState == Par.RESP_STATE_GO
  1481. t = GetSecs;
  1482. % ---- Early after go ----
  1483. if (Par.CorrectResponseGiven(Par) || ...
  1484. Par.IncorrectResponseGiven(Par)) && ...
  1485. t < Par.ResponseStateChangeTime + ...
  1486. Par.ResponseAllowed(1)/1000
  1487. % Early response after go-signal ------
  1488. UpdateHandTaskState(Par.RESP_STATE_DONE);
  1489. if Par.CorrectResponseGiven(Par)
  1490. Log.Events(Log.nEvents).info = 'EarlyCorrect';
  1491. else
  1492. Log.Events(Log.nEvents).info = 'EarlyIncorrect';
  1493. end
  1494. Par.ManResponse(RESP_EARLY) = Par.ManResponse(RESP_EARLY)+1;
  1495. %fprintf('Early after go\n');
  1496. CurrPostErrorDelay = Par.PostErrorDelay;
  1497. if ~Par.ForceRespSide
  1498. if rand(1) <= Par.ProbSideRepeatOnEarly % same side
  1499. Par.ResponseSide=Par.ResponseSide; % keep same
  1500. else
  1501. if Par.ResponseSide==1
  1502. Par.ResponseSide=2;
  1503. else
  1504. Par.ResponseSide=1;
  1505. end
  1506. end
  1507. if Par.IsCatchBlock
  1508. CatchSides = Shuffle(CatchSides);
  1509. else
  1510. nNonCatchTrials = nNonCatchTrials+1;
  1511. end
  1512. end
  1513. LastMissed = false;
  1514. % play feedback sound
  1515. if Par.ResponseState > 0 && ...
  1516. isfield(Par, 'FeedbackSound') && ...
  1517. isfield(Par, 'FeedbackSoundPar') && ...
  1518. Par.FeedbackSound(4) && ...
  1519. all(~isnan(Par.FeedbackSoundPar(4,:)))
  1520. if Par.FeedbackSoundPar(4)
  1521. try
  1522. % fprintf('trying to play a sound\n')
  1523. PsychPortAudio('Start', ...
  1524. Par.FeedbackSoundSnd(4).h, 1, 0, 1);
  1525. catch
  1526. end
  1527. end
  1528. end
  1529. % ---- Incorrect ----
  1530. elseif Par.IncorrectResponseGiven(Par) && Par.RespLeverMatters
  1531. UpdateHandTaskState(Par.RESP_STATE_DONE);
  1532. Log.Events(Log.nEvents).info = 'Incorrect';
  1533. NumberOfConsecutiveErrors=NumberOfConsecutiveErrors+1;
  1534. if ~Par.ForceRespSide
  1535. if rand(1) <= Par.ProbSideRepeatOnError % same side
  1536. Par.ResponseSide=Par.ResponseSide; % keep same
  1537. else
  1538. if Par.ResponseSide==1
  1539. Par.ResponseSide=2;
  1540. else
  1541. Par.ResponseSide=1;
  1542. end
  1543. end
  1544. end
  1545. % RESP_NONE = 0; RESP_CORRECT = 1;
  1546. % RESP_FALSE = 2; RESP_MISS = 3;
  1547. % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
  1548. Par.ManResponse(RESP_FALSE) = Par.ManResponse(RESP_FALSE)+1;
  1549. %fprintf('Error\n');
  1550. CurrPostErrorDelay = Par.PostErrorDelay;
  1551. if Par.IsCatchBlock
  1552. CatchSides = Shuffle(CatchSides);
  1553. else
  1554. nNonCatchTrials = nNonCatchTrials+1;
  1555. end
  1556. LastMissed = false;
  1557. % play feedback sound
  1558. if Par.ResponseState > 0 && ...
  1559. isfield(Par, 'FeedbackSound') && ...
  1560. isfield(Par, 'FeedbackSoundPar') && ...
  1561. Par.FeedbackSound(2) && ...
  1562. all(~isnan(Par.FeedbackSoundPar(2,:)))
  1563. if Par.FeedbackSoundPar(2)
  1564. try
  1565. % fprintf('trying to play a sound\n')
  1566. PsychPortAudio('Start', ...
  1567. Par.FeedbackSoundSnd(2).h, 1, 0, 1);
  1568. catch
  1569. end
  1570. end
  1571. end
  1572. % ---- Correct ----
  1573. elseif Par.CorrectResponseGiven(Par) && Par.RespLeverMatters
  1574. %Par.ResponseStateChangeTime = GetSecs;
  1575. %Par.ResponseState = Par.RESP_STATE_DONE;
  1576. UpdateHandTaskState(Par.RESP_STATE_DONE);
  1577. Log.Events(Log.nEvents).info = 'Hit';
  1578. NumberOfConsecutiveErrors=0;
  1579. GiveRewardAutoTask;
  1580. if ~Par.ForceRespSide
  1581. if rand(1) <= Par.ProbSideRepeatOnCorrect % same side
  1582. Par.ResponseSide=Par.ResponseSide; % keep same
  1583. else
  1584. if Par.ResponseSide==1
  1585. Par.ResponseSide=2;
  1586. else
  1587. Par.ResponseSide=1;
  1588. end
  1589. end
  1590. end
  1591. % RESP_NONE = 0; RESP_CORRECT = 1;
  1592. % RESP_FALSE = 2; RESP_MISS = 3;
  1593. % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
  1594. Par.ManResponse(RESP_CORRECT) = Par.ManResponse(RESP_CORRECT)+1;
  1595. %fprintf('Correct\n');
  1596. CurrPostErrorDelay = Par.PostCorrectDelay;
  1597. if Par.IsCatchBlock
  1598. CatchSides(1) = [];
  1599. else
  1600. nNonCatchTrials = nNonCatchTrials+1;
  1601. end
  1602. LastMissed = false;
  1603. % play feedback sound
  1604. if Par.ResponseState > 0 && ...
  1605. isfield(Par, 'FeedbackSound') && ...
  1606. isfield(Par, 'FeedbackSoundPar') && ...
  1607. Par.FeedbackSound(1) && ...
  1608. all(~isnan(Par.FeedbackSoundPar(1,:)))
  1609. if Par.FeedbackSoundPar(1)
  1610. try
  1611. % fprintf('trying to play a sound\n')
  1612. PsychPortAudio('Start', ...
  1613. Par.FeedbackSoundSnd(1).h, 1, 0, 1);
  1614. catch
  1615. end
  1616. end
  1617. end
  1618. % Correct if side doesn't matter
  1619. elseif ~Par.RespLeverMatters && ...
  1620. (Par.CorrectResponseGiven(Par) || Par.IncorrectResponseGiven(Par))
  1621. UpdateHandTaskState(Par.RESP_STATE_DONE);
  1622. Log.Events(Log.nEvents).info = 'HitEither';
  1623. GiveRewardAutoTask;
  1624. if ~Par.ForceRespSide
  1625. if rand(1) <= Par.ProbSideRepeatOnCorrect % same side
  1626. Par.ResponseSide=Par.ResponseSide; % keep same
  1627. else
  1628. if Par.ResponseSide==1
  1629. Par.ResponseSide=2;
  1630. else
  1631. Par.ResponseSide=1;
  1632. end
  1633. end
  1634. end
  1635. % RESP_NONE = 0; RESP_CORRECT = 1;
  1636. % RESP_FALSE = 2; RESP_MISS = 3;
  1637. % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
  1638. Par.ManResponse(RESP_CORRECT) = Par.ManResponse(RESP_CORRECT)+1;
  1639. %fprintf('Correct\n');
  1640. CurrPostErrorDelay = Par.PostCorrectDelay;
  1641. if Par.IsCatchBlock
  1642. CatchSides(1) = [];
  1643. else
  1644. nNonCatchTrials = nNonCatchTrials+1;
  1645. end
  1646. LastMissed = false;
  1647. % play feedback sound
  1648. if Par.ResponseState > 0 && ...
  1649. isfield(Par, 'FeedbackSound') && ...
  1650. isfield(Par, 'FeedbackSoundPar') && ...
  1651. Par.FeedbackSound(1) && ...
  1652. all(~isnan(Par.FeedbackSoundPar(1,:)))
  1653. if Par.FeedbackSoundPar(1)
  1654. try
  1655. % fprintf('trying to play a sound\n')
  1656. PsychPortAudio('Start', ...
  1657. Par.FeedbackSoundSnd(1).h, 1, 0, 1);
  1658. catch
  1659. end
  1660. end
  1661. end
  1662. % ---- Miss ----
  1663. elseif t >= Par.ResponseStateChangeTime + ...
  1664. Par.ResponseAllowed(2)/1000
  1665. UpdateHandTaskState(Par.RESP_STATE_DONE);
  1666. Log.Events(Log.nEvents).Info = 'Miss';
  1667. %Par.ResponseState = Par.RESP_STATE_DONE;
  1668. %Par.ResponseStateChangeTime = GetSecs;
  1669. if ~Par.ForceRespSide
  1670. if rand(1) <= Par.ProbSideRepeatOnMiss % same side
  1671. Par.ResponseSide=Par.ResponseSide; % keep same
  1672. else
  1673. if Par.ResponseSide==1
  1674. Par.ResponseSide=2;
  1675. else
  1676. Par.ResponseSide=1;
  1677. end
  1678. end
  1679. end
  1680. % RESP_NONE = 0; RESP_CORRECT = 1;
  1681. % RESP_FALSE = 2; RESP_MISS = 3;
  1682. % RESP_EARLY = 4; RESP_BREAK_FIX = 5;
  1683. Par.ManResponse(RESP_MISS) = Par.ManResponse(RESP_MISS)+1;
  1684. LastMissed = true;
  1685. %fprintf('Miss\n');
  1686. CurrPostErrorDelay = Par.DelayOnMiss;
  1687. if Par.IsCatchBlock
  1688. CatchSides = Shuffle(CatchSides);
  1689. else
  1690. nNonCatchTrials = nNonCatchTrials+1;
  1691. end
  1692. % play feedback sound
  1693. if Par.ResponseState > 0 && ...
  1694. isfield(Par, 'FeedbackSound') && ...
  1695. isfield(Par, 'FeedbackSoundPar') && ...
  1696. Par.FeedbackSound(3) && ...
  1697. all(~isnan(Par.FeedbackSoundPar(3,:)))
  1698. if Par.FeedbackSoundPar(3)
  1699. try
  1700. % fprintf('trying to play a sound\n')
  1701. PsychPortAudio('Start', ...
  1702. Par.FeedbackSoundSnd(3).h, 1, 0, 1);
  1703. catch
  1704. end
  1705. end
  1706. end
  1707. end
  1708. end
  1709. % draw the indicators
  1710. if ~Par.ToggleHideFix && ~Par.HideFix_BasedOnHandIn(Par) && ~Par.Pause
  1711. if Par.ResponseState == Par.RESP_STATE_WAIT && ... ~LastMissed && ...
  1712. (isfield(Par,'NoIndicatorDuringPunishDelay') && ...
  1713. Par.NoIndicatorDuringPunishDelay) && ...
  1714. (GetSecs < StartWaitTime + CurrPostErrorDelay/1000)
  1715. else
  1716. DrawHandIndicator(STIMNR);
  1717. DrawGoBar(STIMNR);
  1718. end
  1719. end
  1720. end
  1721. %% dim the screen if requested due to hand position ---------------
  1722. AutoDim; % checks by itself if it's required
  1723. %% refresh the screen ---------------------------------------------
  1724. if Par.Allow_Calls_To_PTB_win
  1725. %lft=Screen('Flip', Par.window, prevlft+0.9*Par.fliptimeSec);
  1726. lft=Screen('Flip', Par.window); % as fast as possible
  1727. nf=nf+1;
  1728. end
  1729. %% log eye-info if required ---------------------------------------
  1730. LogEyeInfo;
  1731. %% change the checkerboard contrast if required -------------------
  1732. if DrawChecker
  1733. if TrackingCheckerContChange
  1734. if lft-tLastCheckerContChange >= ...
  1735. 1/Stm(1).RetMap.Checker.FlickFreq_Approx
  1736. if ChkNum==1
  1737. ChkNum=2;
  1738. elseif ChkNum==2
  1739. ChkNum=1;
  1740. end
  1741. tLastCheckerContChange=lft;
  1742. end
  1743. else
  1744. tLastCheckerContChange=lft;
  1745. TrackingCheckerContChange=true;
  1746. end
  1747. end
  1748. %% Switch position if required to do this automatically -----------
  1749. if Par.ToggleCyclePos && Stm(STIMNR).CyclePosition && ...
  1750. Par.Trlcount(1) >= Stm(STIMNR).CyclePosition
  1751. % next position
  1752. Par.SwitchPos = true;
  1753. Par.WhichPos = 'Next';
  1754. ChangeStimulus(STIMNR);
  1755. Par.SwitchPos = false;
  1756. end
  1757. %% update fixation times ------------------------------------------
  1758. if nf>1 %&& ~Stm(STIMNR).IsPreDur
  1759. dt=lft-prevlft;
  1760. % log the screen flip timing
  1761. Log.dtm=[Log.dtm;dt GetSecs-Par.ExpStart];
  1762. if Par.FixIn % fixating
  1763. Par.FixInOutTime(end,1)=Par.FixInOutTime(end,1)+dt;
  1764. else
  1765. Par.FixInOutTime(end,2)=Par.FixInOutTime(end,2)+dt;
  1766. end
  1767. end
  1768. %% Update Tracker window ------------------------------------------
  1769. if ~TestRunstimWithoutDAS && update_trackerfix_now
  1770. %SCNT = {'TRIALS'};
  1771. SCNT(1) = { ['F: ' num2str(Par.Response) ' FC: ' num2str(Par.CorrStreakcount(2))]};
  1772. %SCNT(2) = { ['FC: ' num2str(Par.CorrStreakcount(2)) ] };
  1773. SCNT(2) = { ['%FixC: ' ...
  1774. sprintf('%0.1f',100*(Par.FixInOutTime(end,1)/sum(Par.FixInOutTime(end,:))))]};
  1775. if size(Par.FixInOutTime,1)>=2
  1776. SCNT(3) = { ['%FixR: ' ...
  1777. sprintf('%0.1f',100* ( sum(Par.FixInOutTime(2:end,1))/sum( sum(Par.FixInOutTime(2:end,:)))))]};
  1778. else
  1779. SCNT(3) = { ['%FixR: ' ...
  1780. sprintf('%0.1f',100* ( sum(Par.FixInOutTime(:,1))/sum( sum(Par.FixInOutTime) ) ))]};
  1781. end
  1782. if strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
  1783. SCNT(4) = { ['C: ' num2str(Par.ManResponse(RESP_CORRECT)) ...
  1784. ' F: ' num2str(Par.ManResponse(RESP_FALSE))]};
  1785. SCNT(5) = { ['M: ' num2str(Par.ManResponse(RESP_MISS)) ...
  1786. ' E: ' num2str(Par.ManResponse(RESP_EARLY))]};
  1787. else
  1788. SCNT(4) = { 'NO MANUAL'};
  1789. SCNT(5) = { 'NO MANUAL'};
  1790. end
  1791. SCNT(6) = { ['Rew: ' num2str(Log.TotalReward) ] };
  1792. set(Hnd(1), 'String', SCNT ) %display updated numbers in GUI
  1793. % Give noise-on-eye-channel info
  1794. SD = dasgetnoise();
  1795. SD = SD./Par.PixPerDeg;
  1796. set(Hnd(2), 'String', SD )
  1797. last_trackerfix_update = GetSecs;
  1798. end
  1799. if ~TestRunstimWithoutDAS && ...
  1800. GetSecs - last_trackerfix_update >= 1 % update tracker every second
  1801. update_trackerfix_now=true;
  1802. else
  1803. update_trackerfix_now=false;
  1804. end
  1805. %% Catch block ----------------------------------------------------
  1806. if strcmp(Par.ResponseBox.Task,'DetectGoSignal') && ...
  1807. Par.CatchBlock.do && ~Par.IsCatchBlock && ...
  1808. nNonCatchTrials > Prev_nNonCatchTrials && ...
  1809. mod(nNonCatchTrials,Par.CatchBlock.AfterNumberOfTrials)==0
  1810. Par.IsCatchBlock = true;
  1811. %fprintf('Catch block started...')
  1812. CatchSides = Shuffle([ones(1,Par.CatchBlock.NoCorrectPerSideNeeded) ...
  1813. 2*ones(1,Par.CatchBlock.NoCorrectPerSideNeeded)]);
  1814. Prev_nNonCatchTrials = nNonCatchTrials;
  1815. elseif strcmp(Par.ResponseBox.Task,'DetectGoSignal') && ...
  1816. Par.CatchBlock.do && Par.IsCatchBlock && isempty(CatchSides)
  1817. Par.IsCatchBlock = false;
  1818. %fprintf('completed\n')
  1819. end
  1820. %% Stop reward ----------------------------------------------------
  1821. StopRewardIfNeeded();
  1822. end
  1823. % if breaking out with stop/escape during vlc
  1824. if VLCMovieRun
  1825. if MovieRunning
  1826. eval(['!' stopVLCbat])
  1827. Reopen_PTB_win;
  1828. MovieRunning=false;
  1829. end
  1830. end
  1831. %% Clean up and Save Log ----------------------------------------------
  1832. % end eye recording if necessary
  1833. if Par.EyeRecAutoTrigger && ~EyeRecMsgShown
  1834. cn=0;
  1835. while Par.EyeRecStatus == 0 && cn < 100
  1836. CheckEyeRecStatus; % checks the current status of eye-recording
  1837. cn=cn+1;
  1838. end
  1839. if Par.EyeRecStatus % recording
  1840. while Par.EyeRecStatus
  1841. SetEyeRecStatus(0);
  1842. pause(1)
  1843. CheckEyeRecStatus
  1844. end
  1845. fprintf('\nStopped eye-recording. Save the file or add more runs.\n');
  1846. %fprintf(['Suggested filename: ' Par.MONKEY '_' DateString '.tda\n']);
  1847. else % not recording
  1848. fprintf('\n>> Alert! Could not find a running eye-recording!\n');
  1849. end
  1850. EyeRecMsgShown=true;
  1851. end
  1852. if MovieRun
  1853. if MovieRunning
  1854. % Done. Stop playback:
  1855. Screen('PlayMovie', Log.movie.name, 0);
  1856. % Close movie object:
  1857. Screen('CloseMovie', Log.movie.name);
  1858. MovieRunning=false;
  1859. end
  1860. end
  1861. if ~isempty(Stm(STIMNR).Descript) && ~TestRunstimWithoutDAS
  1862. % Empty the screen
  1863. if ~Par.Pause
  1864. Screen('FillRect',Par.window,Par.BG.*Par.ScrWhite);
  1865. else
  1866. Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite); % black first
  1867. end
  1868. lft=Screen('Flip', Par.window,lft+.9*Par.fliptimeSec);
  1869. if ~TestRunstimWithoutDAS
  1870. dasjuice(0); %stop reward if its running
  1871. end
  1872. % go back to default priority
  1873. Priority(oldPriority);
  1874. % save stuff
  1875. if strcmp(Par.SetUp,'NIN') % ephys
  1876. LogPath = fullfile(Par.LogFolder,... % base log folder
  1877. Par.SetUp,... % setup
  1878. Par.LogFolder,... % task (/subtask)
  1879. Par.MONKEY,... % subject
  1880. [Par.MONKEY '_' DateString(1:8)],... % session
  1881. [Par.MONKEY '_HRF_' DateString_sec]... % run
  1882. );
  1883. else
  1884. LogPath = fullfile(getenv('TRACKER_LOGS'),... % base log folder
  1885. Par.SetUp,... % setup
  1886. Par.LogFolder,... % task (/subtask)
  1887. Par.MONKEY,... % subject
  1888. [Par.MONKEY '_' DateString(1:8)],... % session
  1889. [Par.MONKEY '_HRF_' DateString_sec]... % run
  1890. );
  1891. end
  1892. LogFn = [Par.SetUp '_' Par.MONKEY '_' DateString_sec];
  1893. [~,~,~] = mkdir(LogPath);
  1894. cd(LogPath)
  1895. if ~TestRunstimWithoutDAS
  1896. if strcmp(Par.SetUp,'NIN')
  1897. FileName=['Log_' LogFn '_' ...
  1898. Stm(STIMNR).Descript '_Run' num2str(StimLoopNr) '_Block' num2str(blockstr)];
  1899. evFileName=[FileName '_eventlog.csv'];
  1900. else
  1901. FileName=['Log_' LogFn '_' ...
  1902. Stm(STIMNR).Descript '_Run' num2str(StimLoopNr)];
  1903. evFileName=[FileName '_eventlog.csv'];
  1904. end
  1905. else
  1906. FileName=['Log_NODAS_' LogFn '_' ...
  1907. Stm(STIMNR).Descript '_Run' num2str(StimLoopNr)];
  1908. evFileName=[FileName '_eventlog.csv'];
  1909. end
  1910. warning off;
  1911. if TestRunstimWithoutDAS; cd ..;end
  1912. StimObj.Stm=Stm;
  1913. % 1st is PreStim, last is PostStim
  1914. Log.FixPerc=100*(Par.FixInOutTime(:,1)./sum(Par.FixInOutTime,2));
  1915. % copy the originally used files
  1916. if ~RunParStim_Saved
  1917. % runstim
  1918. fn=['Runstim_' LogFn '.m'];
  1919. cfn=[mfilename('fullpath') '.m'];
  1920. copyfile(cfn,fn);
  1921. % parsettings
  1922. parsetpath = which(Par.PARSETFILE);
  1923. if isempty(ls(Par.PARSETFILE)) % doesn't exist yet
  1924. copyfile(parsetpath,[Par.PARSETFILE '.m']);
  1925. end
  1926. % stimsettings
  1927. stimsetpath = which(Par.STIMSETFILE);
  1928. if isempty(ls(Par.STIMSETFILE)) % doesn't exist yet
  1929. copyfile(stimsetpath,[Par.STIMSETFILE '.m']);
  1930. end
  1931. % stimulus
  1932. if RetMapStimuli
  1933. save('RetMap_Stimulus','ret_vid');
  1934. end
  1935. RunParStim_Saved=true;
  1936. end
  1937. % save the events to a csv file
  1938. if length(Log.Events) > 8
  1939. EventCell = cell(length(Log.Events)+1,3);
  1940. %VarNames={'time_s','type','StimName'}; % << old column names
  1941. VarNames={'time_s','event','info'}; % compatible eith other experiments
  1942. for ev = 1:length(Log.Events)
  1943. %EventCell(ev,:)={...
  1944. % Log.Events(ev).t,...
  1945. % Log.Events(ev).type,...
  1946. % Log.Events(ev).StimName };
  1947. EventCell(ev,:)={...
  1948. Log.Events(ev).t,...
  1949. Log.Events(ev).event,...
  1950. Log.Events(ev).info };
  1951. end
  1952. EvTable = cell2table(EventCell,'variablenames',VarNames');
  1953. writetable(EvTable,evFileName)
  1954. % save mat and json files
  1955. if ~TestRunstimWithoutDAS && ~json_done &&...
  1956. (StimLoopNr==Stm(1).nRepeatsStimSet || ...
  1957. (Par.ESC && StimLoopNr~=Stm(1).nRepeatsStimSet))
  1958. % save json file ===========
  1959. Par.jf.Project = 'Retinotopy';
  1960. if strcmp(Par.SetUp,'NIN')
  1961. Par.jf.Method = 'EPHYS';
  1962. else
  1963. Par.jf.Method = 'MRI';
  1964. end
  1965. Par.jf.Protocol = '17.25.01';
  1966. Par.jf.Dataset = Par.LogFolder(...
  1967. find(Par.LogFolder=='\',1,'last')+1:end);
  1968. Par.jf.Date = datestr(now,'yyyymmdd');
  1969. Par.jf.Subject = Par.MONKEY;
  1970. Par.jf.Researcher = 'ChrisKlink';
  1971. Par.jf.Setup = Par.SetUp;
  1972. Par.jf.Group = 'awake';
  1973. Par.jf.Stimulus = Stm(STIMNR).Descript;
  1974. Par.jf.LogFolder = [Par.MONKEY '_' DateString];
  1975. Par.jf.logfile_name = FileName; %%%%%%%%
  1976. Par.jf.fixperc = Log.FixPerc;
  1977. Par.jf.RunNumber = 'XXX';
  1978. Par.jf.QualityAsses = '10';
  1979. Par.jf.Comment = '';
  1980. % give the possibility to change
  1981. % only when at scanner
  1982. if strcmp(Par.SetUp, 'Spinoza_3T') || strcmp(Par.SetUp, 'NIN')
  1983. json_defanswer = {Par.jf.Project,Par.jf.Method,Par.jf.Protocol,...
  1984. Par.jf.Dataset,Par.jf.Subject,Par.jf.Researcher,...
  1985. Par.jf.Setup,Par.jf.Group,Par.jf.RunNumber,...
  1986. Par.jf.QualityAsses,Par.jf.Comment};
  1987. json_answer = inputdlg(...
  1988. {'Project','Method','Protocol',...
  1989. 'Dataset','Subject','Researcher',...
  1990. 'Setup','Group','Run','Quality (0-10)',...
  1991. 'Comment'},'JSON SPECS',1,json_defanswer,'on');
  1992. if isempty(json_answer);json_answer=json_defanswer;end
  1993. Par.jf.Project = json_answer{1};
  1994. Par.jf.Method = json_answer{2};
  1995. Par.jf.Protocol = json_answer{3};
  1996. Par.jf.Dataset = json_answer{4};
  1997. Par.jf.Subject = json_answer{5};
  1998. Par.jf.Researcher = json_answer{6};
  1999. Par.jf.Setup = json_answer{7};
  2000. Par.jf.Group = json_answer{8};
  2001. Par.jf.RunNumber = json_answer{9};
  2002. Par.jf.QualityAsses = json_answer{10};
  2003. Par.jf.Comment = json_answer{11};
  2004. end
  2005. json.project.title = Par.jf.Project;
  2006. json.project.method = Par.jf.Method;
  2007. json.dataset.protocol = Par.jf.Protocol;
  2008. json.dataset.name = Par.jf.Dataset;
  2009. json.session.date = Par.jf.Date;
  2010. json.session.subjectId = Par.jf.Subject;
  2011. json.session.investigator = Par.jf.Researcher;
  2012. json.session.setup = Par.jf.Setup;
  2013. json.session.group = Par.jf.Group;
  2014. json.session.stimulus = Par.jf.Stimulus;
  2015. json.session.logfile = Par.jf.logfile_name;
  2016. json.session.logfolder = Par.jf.LogFolder;
  2017. json.session.fixperc = Par.jf.fixperc;
  2018. json.session.run = Par.jf.RunNumber;
  2019. json.session.quality = Par.jf.QualityAsses;
  2020. json.session.comment = Par.jf.Comment;
  2021. % retrospectively create jsons for all runs
  2022. for jj = 1:StimLoopNr % save json files for all runs
  2023. if strcmp(Par.SetUp,'NIN')
  2024. json.session.logfile=['Log_' LogFn '_' ...
  2025. Stm(STIMNR).Descript '_Run' num2str(jj) '_Block' num2str(blockstr)];
  2026. else
  2027. json.session.logfile=['Log_' LogFn '_' ...
  2028. Stm(STIMNR).Descript '_Run' num2str(jj)];
  2029. end
  2030. if jj<StimLoopNr
  2031. json.session.fixperc = CollectPerformance{jj,2};
  2032. else
  2033. json.session.fixperc = Par.jf.fixperc;
  2034. end
  2035. savejson('', json, ['Log_' DateString_sec ...
  2036. '_Run' num2str(jj,'%03.f') '_session.json']);
  2037. %savejson('', json, ['Log_' DateString '_session.json']);
  2038. end
  2039. json_done=true;
  2040. end
  2041. end
  2042. if ~TestRunstimWithoutDAS
  2043. % save log mat-file ============
  2044. temp_hTracker=Par.hTracker;
  2045. Par=rmfield(Par,'hTracker');
  2046. save(FileName,'Log','Par','StimObj');
  2047. Par.hTracker = temp_hTracker;
  2048. end
  2049. % write some stuff to a text file as well
  2050. if ~TestRunstimWithoutDAS
  2051. fid=fopen([FileName '.txt'],'w');
  2052. fprintf(fid,['Runstim: ' Par.RUNFUNC '\n']);
  2053. fprintf(fid,['StimSettings: ' Par.STIMSETFILE '\n']);
  2054. fprintf(fid,['ParSettings: ' Par.PARSETFILE '\n\n']);
  2055. fprintf(fid,['Stimulus: ' Stm(STIMNR).Descript '\n\n']);
  2056. fprintf(fid,['Fixation perc over run (inc. pre/post): ' num2str(mean(Log.FixPerc)) '\n']);
  2057. fprintf(fid,['Fixation perc over run (exc. pre/post): ' num2str(mean(Log.FixPerc(2:end-1))) '\n']);
  2058. for i=1:length(Log.FixPerc)
  2059. if i==1
  2060. fprintf(fid,['Fixation perc PreStim: ' ...
  2061. num2str(Log.FixPerc(i)) '\n']);
  2062. elseif i==length(Log.FixPerc)
  2063. fprintf(fid,['Fixation perc PostStim: ' ...
  2064. num2str(Log.FixPerc(i)) '\n']);
  2065. else
  2066. fprintf(fid,['Fixation perc cycle ' num2str(i-1) ': ' ...
  2067. num2str(Log.FixPerc(i)) '\n']);
  2068. end
  2069. end
  2070. fprintf(fid,['\nTotal reward: ' num2str(Log.TotalReward) '\n']);
  2071. fclose(fid);
  2072. end
  2073. cd(Par.ExpFolder)
  2074. % now show the suggested filename for the eye file
  2075. fprintf(['Suggested filename for eye-file: ' Par.MONKEY '_' DateString '.tda\n']);
  2076. if TestRunstimWithoutDAS; cd Experiment;end
  2077. warning on;
  2078. % if running without DAS close ptb windows
  2079. if TestRunstimWithoutDAS
  2080. Screen('closeall');
  2081. end
  2082. end
  2083. %% diagnostics to cmd -------------------------------------------------
  2084. if ~Par.ESC && ~TestRunstimWithoutDAS
  2085. GrandTotalReward=GrandTotalReward+Log.TotalReward;
  2086. fprintf(['Total reward this run: ' num2str(Log.TotalReward) '\n']);
  2087. fprintf(['Total reward thusfar: ' num2str(GrandTotalReward) '\n']);
  2088. fprintf(['Total time-out this run: ' num2str(Log.TimeOutThisRun) '\n']);
  2089. fprintf(['Total time-out thusfar: ' num2str(Log.TotalTimeOut) '\n']);
  2090. fprintf(['Fixation percentage: ' num2str(nanmean(Log.FixPerc)) '\n']);
  2091. CollectPerformance{StimLoopNr,1} = Stm(STIMNR).Descript;
  2092. CollectPerformance{StimLoopNr,2} = nanmean(Log.FixPerc);
  2093. CollectPerformance{StimLoopNr,3} = nanstd(Log.FixPerc)./sqrt(length(Log.FixPerc));
  2094. CollectPerformance{StimLoopNr,4} = Log.TotalReward;
  2095. CollectPerformance{StimLoopNr,5} = Log.TimeOutThisRun;
  2096. elseif Par.ESC && ~LastRewardAdded && ~TestRunstimWithoutDAS
  2097. GrandTotalReward=GrandTotalReward+Log.TotalReward;
  2098. fprintf(['Total reward this run: ' num2str(Log.TotalReward) '\n']);
  2099. fprintf(['Total reward thusfar: ' num2str(GrandTotalReward) '\n']);
  2100. fprintf(['Total time-out this run: ' num2str(Log.TimeOutThisRun) '\n']);
  2101. fprintf(['Total time-out thusfar: ' num2str(Log.TotalTimeOut) '\n']);
  2102. fprintf(['Fixation percentage: ' num2str(nanmean(Log.FixPerc)) '\n']);
  2103. CollectPerformance{StimLoopNr,1} = Stm(STIMNR).Descript;
  2104. CollectPerformance{StimLoopNr,2} = nanmean(Log.FixPerc);
  2105. CollectPerformance{StimLoopNr,3} = nanstd(Log.FixPerc);
  2106. CollectPerformance{StimLoopNr,4} = Log.TotalReward;
  2107. CollectPerformance{StimLoopNr,5} = Log.TimeOutThisRun;
  2108. LastRewardAdded=true;
  2109. end
  2110. if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
  2111. end
  2112. %% PostExpProcessing ======================================================
  2113. Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite);
  2114. Screen('Flip', Par.window);
  2115. Screen('FillRect',Par.window,[0 0 0].*Par.ScrWhite);
  2116. Screen('Flip', Par.window);
  2117. fprintf('\n\n------------------------------\n');
  2118. fprintf('Experiment ended as planned\n');
  2119. fprintf('------------------------------\n');
  2120. % close audio devices
  2121. for i=1:length(Par.FeedbackSoundSnd)
  2122. if ~isnan(Par.FeedbackSoundSnd(i).h)
  2123. PsychPortAudio('Close', Par.FeedbackSoundSnd(i).h);
  2124. end
  2125. end
  2126. if TestRunstimWithoutDAS
  2127. sca; cd Experiment; rmpath(genpath(cd));
  2128. end
  2129. %% Close textures to clean memory =========================================
  2130. if CloseTextures
  2131. fprintf('Cleaning up textures...\n\n');
  2132. for rv = 1:length(ret_vid)
  2133. for jj=1:length(ret_vid(rv).text)
  2134. Screen('Close',ret_vid(rv).text(jj));
  2135. end
  2136. end
  2137. end
  2138. %% Process performance ====================================================
  2139. if ~isempty(CollectPerformance) && ~TestRunstimWithoutDAS
  2140. ColPerf=[];
  2141. cd(LogPath);
  2142. fid2=fopen(['SUMMARY_' LogFn '.txt'],'w');
  2143. fprintf(fid2,['Runstim: ' Par.RUNFUNC '\n']);
  2144. fprintf(fid2,['StimSettings: ' Par.STIMSETFILE '\n']);
  2145. fprintf(fid2,['ParSettings: ' Par.PARSETFILE '\n\n']);
  2146. for rr = 1:size(CollectPerformance,1)
  2147. fprintf([num2str(rr) ': Performance for ' CollectPerformance{rr,1} ' = ' num2str(CollectPerformance{rr,2}) ' %%\n']);
  2148. fprintf(fid2,[num2str(rr) ': Performance for ' CollectPerformance{rr,1} ' = ' num2str(CollectPerformance{rr,2}) ' %%\n']);
  2149. ColPerf=[ColPerf; CollectPerformance{rr,2}];
  2150. end
  2151. fprintf(['\nAverage performance: ' num2str(nanmean(ColPerf)) '%% (std: ' num2str(nanstd(ColPerf)) ' %%)\n']);
  2152. fprintf(['Total reward: ' num2str(GrandTotalReward) ' s\n']);
  2153. fprintf(fid2,['Average performance: ' num2str(nanmean(ColPerf)) '%% (std: ' num2str(nanstd(ColPerf)) ' %%)\n']);
  2154. fprintf(fid2,['Total reward: ' num2str(GrandTotalReward) ' s']);
  2155. fclose(fid2);
  2156. % plot performance
  2157. if Par.PlotPerformance
  2158. if size(CollectPerformance,1) > 15
  2159. xtick_use = 2:2:size(CollectPerformance,1);
  2160. else
  2161. xtick_use = 1:size(CollectPerformance,1);
  2162. end
  2163. figperf = figure('units','pixels','outerposition',[0 0 1000 1000]);
  2164. subplot(4,4,1:3); hold on; box on;
  2165. errorbar(1:size(CollectPerformance,1),...
  2166. [CollectPerformance{:,2}],[CollectPerformance{:,3}],...
  2167. 'ko','MarkerFaceColor','k','MarkerSize',6,'linestyle','none')
  2168. set(gca,'ylim',[0 100],'xlim',[0 size(CollectPerformance,1)+1],...
  2169. 'xtick', xtick_use,'FontSize',11)
  2170. tt=title(['Performance: ' Par.MONKEY '_' Par.STIMSETFILE ...
  2171. '_' DateString],'interpreter','none');
  2172. %xx=xlabel('Stimulus (chronol. order)');
  2173. yy=ylabel('Fixation (%)');
  2174. set(tt,'FontSize', 12);
  2175. %set(xx,'FontSize', 12);
  2176. set(yy,'FontSize', 12);
  2177. subplot(4,4,5:7); hold on; box on;
  2178. plot(1:size(CollectPerformance,1),[CollectPerformance{:,4}],...
  2179. 'ko','MarkerFaceColor','k','MarkerSize',6)
  2180. set(gca,'xlim',[0 size(CollectPerformance,1)+1],...
  2181. 'xtick', xtick_use,'FontSize',11)
  2182. % tt=title(['Reward (s): ' Par.MONKEY '_' Par.STIMSETFILE ...
  2183. % '_' DateString],'interpreter','none');
  2184. %xx=xlabel('Stimulus (chronol. order)'); yy=ylabel('Reward (s)');
  2185. %xx=xlabel('Stimulus (chronol. order)');
  2186. yy=ylabel('Reward (s)');
  2187. %set(tt,'FontSize', 12);
  2188. %set(xx,'FontSize', 12);
  2189. set(yy,'FontSize', 12);
  2190. subplot(4,4,9:11); hold on; box on;
  2191. for sn=1:size(CollectPerformance,1)
  2192. CP{sn}=[num2str(sn) ': ' CollectPerformance{sn,1}];
  2193. end
  2194. plot(1:size(CollectPerformance,1),cumsum([CollectPerformance{:,4}]),...
  2195. 'ro-','MarkerFaceColor','r','MarkerSize',6)
  2196. set(gca,'xlim',[0 size(CollectPerformance,1)+1],...
  2197. 'xtick', xtick_use,'FontSize',11)
  2198. % tt=title(['Reward (s): ' Par.MONKEY '_' Par.STIMSETFILE ...
  2199. % '_' DateString],'interpreter','none');
  2200. %xx=xlabel('Stimulus (chronol. order)');
  2201. yy=ylabel('Cumul. reward (s)');
  2202. %set(tt,'FontSize', 12);
  2203. %set(xx,'FontSize', 12);
  2204. set(yy,'FontSize', 12);
  2205. subplot(4,4,13:15); hold on; box on;
  2206. plot(1:size(CollectPerformance,1),[CollectPerformance{:,5}],...
  2207. 'ko','MarkerFaceColor','k','MarkerSize',6)
  2208. set(gca,'xlim',[0 size(CollectPerformance,1)+1],...
  2209. 'xtick', xtick_use,'FontSize',11)
  2210. % tt=title(['Time-outs (s): ' Par.MONKEY '_' Par.STIMSETFILE ...
  2211. % '_' DateString],'interpreter','none');
  2212. xx=xlabel('Stimulus (chronol. order)');
  2213. yy=ylabel('Time-outs (s)');
  2214. %set(tt,'FontSize', 12);
  2215. set(xx,'FontSize', 12);
  2216. set(yy,'FontSize', 12);
  2217. subplot(4,4,[4,8,12,16])
  2218. set(gca,'XColor','w','YColor','w','xtick',[],'ytick',[]);
  2219. tb=annotation('textbox',[.75 .1 .15 .8]);
  2220. set(tb,'BackGroundColor','w','EdgeColor','none','String',...
  2221. CP,'FontSize',10,'interpreter','none')
  2222. set(figperf,'Color','w');
  2223. % saveas(figperf,['PERFORM_' Par.MONKEY '_' Par.STIMSETFILE '_' DateString],'fig');
  2224. % export_fig(['PERFORM_' Par.MONKEY '_' Par.STIMSETFILE '_' DateString],...
  2225. % '-pdf','-nocrop',figperf);
  2226. saveas(figperf,['PERFORM_' LogFn],'fig');
  2227. export_fig(['PERFORM_' LogFn],'-pdf','-nocrop',figperf);
  2228. close(figperf);
  2229. end
  2230. save(['PERFORM_' LogFn],'CollectPerformance');
  2231. cd(Par.ExpFolder)
  2232. end
  2233. clear Log
  2234. Par=Par_BU;
  2235. %% Standard functions called throughout the runstim =======================
  2236. % create fixation window around target
  2237. function DefineEyeWin(STIMNR)
  2238. FIX = 0; %this is the fixation window
  2239. TALT = 1; %this is an alternative/erroneous target window --> not used
  2240. TARG = 2; %this is the correct target window --> not used
  2241. Par.WIN = [...
  2242. Stm(STIMNR).Center(Par.PosNr,1), ...
  2243. -Stm(STIMNR).Center(Par.PosNr,2), ...
  2244. Stm(STIMNR).FixWinSizePix(1), ...
  2245. Stm(STIMNR).FixWinSizePix(2), FIX]';
  2246. refreshtracker( 1) %clear tracker screen and set fixation and target windows
  2247. SetWindowDas %set das control thresholds using global parameters : Par
  2248. end
  2249. % draw fixation
  2250. function DrawFix(STIMNR)
  2251. % fixation area
  2252. rect=[...
  2253. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Stm(STIMNR).FixDotSizePix/2, ...
  2254. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Stm(STIMNR).FixDotSizePix/2, ...
  2255. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Stm(STIMNR).FixDotSizePix/2, ...
  2256. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Stm(STIMNR).FixDotSizePix/2];
  2257. rect2=[...
  2258. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Stm(STIMNR).FixDotSurrSizePix/2, ...
  2259. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Stm(STIMNR).FixDotSurrSizePix/2, ...
  2260. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Stm(STIMNR).FixDotSurrSizePix/2, ...
  2261. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Stm(STIMNR).FixDotSurrSizePix/2];
  2262. Screen('FillOval',Par.window,Par.BG.*Par.ScrWhite,rect2);
  2263. Screen('FillOval',Par.window,Par.CurrFixCol,rect);
  2264. cen = [Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1), ...
  2265. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)];
  2266. end
  2267. % draw handindicator
  2268. function DrawHandIndicator(STIMNR)
  2269. if any(any(Par.RespIndPos)) % stimuli not centered
  2270. cen = [Par.ScrCenter(1),Par.ScrCenter(2)];
  2271. if size(Par.RespIndPos,1)>2
  2272. % pick a target location from the options
  2273. p=Par.s_order(1);
  2274. cen1 = [Par.RespIndPos(p,1)*Par.PixPerDeg+Par.ScrCenter(1), ...
  2275. Par.RespIndPos(p,2)*Par.PixPerDeg+Par.ScrCenter(2)];
  2276. cen2=cen1;
  2277. else
  2278. cen1 = [Par.RespIndPos(1,1)*Par.PixPerDeg+Par.ScrCenter(1), ...
  2279. Par.RespIndPos(1,2)*Par.PixPerDeg+Par.ScrCenter(2)];
  2280. cen2 = [Par.RespIndPos(2,1)*Par.PixPerDeg+Par.ScrCenter(1), ...
  2281. Par.RespIndPos(2,2)*Par.PixPerDeg+Par.ScrCenter(2)];
  2282. end
  2283. else % stimulus centered (but can be cycled)
  2284. cen = [Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1), ...
  2285. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)];
  2286. cen1=cen;cen2=cen;
  2287. end
  2288. if strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
  2289. if Par.ResponseState == Par.RESP_STATE_DONE && ...
  2290. ~Par.CanStartTrial(Par) && ...
  2291. GetSecs >= Par.ResponseStateChangeTime + 500/1000
  2292. if Par.DrawBlockedInd && (Par.TrialNeeds.LeversAreDown && any(Par.LeverIsUp))
  2293. Screen('FillOval',Par.window, Par.BlockedIndColor.*Par.ScrWhite, ...
  2294. [cen,cen] + Par.RespIndSizePix*blocked_circle)
  2295. end
  2296. elseif Par.ResponseState == Par.RESP_STATE_WAIT && Par.ResponseSide == 1
  2297. if Par.DrawNeutralWaitInd
  2298. if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
  2299. Screen('FillOval',Par.window, Par.BlockedIndColor.*Par.ScrWhite, ...
  2300. [cen1,cen1] + Par.RespIndSizePix*blocked_circle)
  2301. end
  2302. else
  2303. if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
  2304. Screen('FillPoly',Par.window, Par.RespIndColor(1,:).*Par.ScrWhite, ...
  2305. [cen1;cen1;cen1;cen1] + Par.RespIndSizePix*left_square)
  2306. end
  2307. end
  2308. if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
  2309. elseif Par.ResponseState == Par.RESP_STATE_WAIT && Par.ResponseSide == 2
  2310. if Par.DrawNeutralWaitInd
  2311. if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
  2312. Screen('FillOval',Par.window, Par.BlockedIndColor.*Par.ScrWhite, ...
  2313. [cen2,cen2] + Par.RespIndSizePix*blocked_circle)
  2314. end
  2315. else
  2316. if GetSecs >= Par.ResponseStateChangeTime + Par.WaitIndicatorOnset
  2317. Screen('FillPoly',Par.window, Par.RespIndColor(2,:).*Par.ScrWhite, ...
  2318. [cen2;cen2;cen2;cen2] + Par.RespIndSizePix*right_diamond)
  2319. end
  2320. end
  2321. if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
  2322. elseif Par.ResponseState == Par.RESP_STATE_GO && ...
  2323. Par.ResponseSide == 1
  2324. Screen('FillPoly',Par.window, Par.RespIndColor(1,:).*Par.ScrWhite, ...
  2325. [cen1;cen1;cen1;cen1] + Par.RespIndSizePix*left_square)
  2326. if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
  2327. elseif Par.ResponseState == Par.RESP_STATE_GO && ...
  2328. Par.ResponseSide == 2
  2329. Screen('FillPoly',Par.window, Par.RespIndColor(2,:).*Par.ScrWhite, ...
  2330. [cen2;cen2;cen2;cen2] + Par.RespIndSizePix*right_diamond)
  2331. if Par.RespIndLeds; dasbit(Par.LED_B(Par.ResponseSide),1); end % LED on
  2332. elseif Par.ResponseState == Par.RESP_STATE_DONE && ...
  2333. Par.CurrResponseSide == 1
  2334. if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
  2335. % Screen('FillPoly',Par.window, Par.RespIndColor(1,:).*Par.ScrWhite, ...
  2336. % [cen1;cen1;cen1;cen1] + Par.RespIndSizePix*left_square)
  2337. elseif Par.ResponseState == Par.RESP_STATE_DONE && ...
  2338. Par.CurrResponseSide == 2
  2339. if Par.RespIndLeds; dasbit(Par.LED_B(1),0);dasbit(Par.LED_B(2),0);end % LEDS off
  2340. % Screen('FillPoly',Par.window, Par.RespIndColor(2,:).*Par.ScrWhite, ...
  2341. % [cen2;cen2;cen2;cen2] + Par.RespIndSizePix*right_diamond)
  2342. end
  2343. end
  2344. end
  2345. % draw "go bar"
  2346. function DrawGoBar(STIMNR)
  2347. if Par.ResponseSide==0
  2348. return
  2349. end
  2350. % Target bar
  2351. %if ~Par.Orientation(Par.CurrOrient)
  2352. if Par.ResponseState == Par.RESP_STATE_GO %horizontal
  2353. rect=[...
  2354. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Par.GoBarSizePix(1)/2, ...
  2355. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Par.GoBarSizePix(2)/2, ...
  2356. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Par.GoBarSizePix(1)/2, ...
  2357. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Par.GoBarSizePix(2)/2];
  2358. Screen('FillRect',Par.window,Par.GoBarColor.*Par.ScrWhite,rect);
  2359. elseif Par.ResponseState == Par.RESP_STATE_WAIT %vertical
  2360. rect=[...
  2361. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)-Par.GoBarSizePix(2)/2, ... left
  2362. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)-Par.GoBarSizePix(1)/2, ... top
  2363. Stm(STIMNR).Center(Par.PosNr,1)+Par.ScrCenter(1)+Par.GoBarSizePix(2)/2, ... right
  2364. Stm(STIMNR).Center(Par.PosNr,2)+Par.ScrCenter(2)+Par.GoBarSizePix(1)/2];
  2365. Screen('FillRect',Par.window,Par.GoBarColor.*Par.ScrWhite,rect);
  2366. end
  2367. end
  2368. % draw stimuli
  2369. function DrawStimuli
  2370. % Background
  2371. Screen('FillRect',Par.window,ceil(Par.BG.*Par.ScrWhite));
  2372. end
  2373. % auto-dim the screen if hand is out
  2374. function AutoDim
  2375. if Par.HandOutDimsScreen && (...
  2376. (strcmp(Par.HandInBothOrEither,'Both') && ~all(Par.HandIsIn)) || ...
  2377. (strcmp(Par.HandInBothOrEither,'Either') && ~any(Par.HandIsIn)) ...
  2378. )
  2379. if ~any(Par.HandIsIn) % no hands in
  2380. if size(Par.HandOutDimsScreen_perc,2) == 2
  2381. Screen('FillRect',Par.window,...
  2382. [0 0 0 (Par.HandOutDimsScreen_perc(2))].*Par.ScrWhite,....
  2383. [Par.wrect(1:2) Par.wrect(3:4)+1]);
  2384. else
  2385. Screen('FillRect',Par.window,...
  2386. [0 0 0 (Par.HandOutDimsScreen_perc(1))].*Par.ScrWhite,....
  2387. [Par.wrect(1:2) Par.wrect(3:4)+1]);
  2388. end
  2389. else % a hand in
  2390. Screen('FillRect',Par.window,...
  2391. [0 0 0 (Par.HandOutDimsScreen_perc(1))].*Par.ScrWhite,....
  2392. [Par.wrect(1:2) Par.wrect(3:4)+1]);
  2393. end
  2394. end
  2395. end
  2396. % change stimulus features
  2397. function ChangeStimulus(STIMNR)
  2398. % Change stimulus features if required
  2399. % Position
  2400. if Par.SwitchPos
  2401. Par.PosReset=true;
  2402. Par.PrevPosNr=Par.PosNr;
  2403. switch Par.WhichPos
  2404. case '1'
  2405. Par.PosNr = 1;
  2406. case '2'
  2407. Par.PosNr = 2;
  2408. case '3'
  2409. Par.PosNr = 3;
  2410. case '4'
  2411. Par.PosNr = 4;
  2412. case '5'
  2413. Par.PosNr = 5;
  2414. case 'Next'
  2415. Par.PosNr = Par.PosNr + 1;
  2416. if Par.PosNr > 5
  2417. Par.PosNr = Par.PosNr - 5;
  2418. end
  2419. % case 'Prev'
  2420. % Par.PosNr = Par.PosNr -1;
  2421. % if Par.PosNr < 1
  2422. % Par.PosNr = Par.PosNr + 5;
  2423. % end
  2424. end
  2425. Log.nEvents=Log.nEvents+1;
  2426. Log.Events(Log.nEvents).event=['Pos' num2str(Par.PosNr)];
  2427. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2428. DefineEyeWin(STIMNR);
  2429. end
  2430. end
  2431. % check for key-presses
  2432. function CheckKeys
  2433. % check
  2434. [Par.KeyIsDown,Par.KeyTime,KeyCode]=KbCheck; %#ok<*ASGLU>
  2435. InterpretKeys(KeyCode)
  2436. end
  2437. % interpret key presses
  2438. function InterpretKeys(KeyCode)
  2439. % Par.KeyDetectedInTrackerWindow is true when key press is detected
  2440. % in the Tracker window, false if it's not. Allows key-press isolation
  2441. % interpret key presses
  2442. if Par.KeyIsDown && ~Par.KeyWasDown
  2443. Key=KbName(KbName(KeyCode));
  2444. if isscalar(KbName(KbName(KeyCode)))
  2445. switch Key
  2446. case Par.KeyEscape
  2447. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2448. Par.ESC = true;
  2449. elseif TestRunstimWithoutDAS
  2450. Par.ESC = true;
  2451. end
  2452. case Par.KeyTriggerMR
  2453. Log.MRI.TriggerReceived = true;
  2454. Log.MRI.TriggerTime = ...
  2455. [Log.MRI.TriggerTime; Par.KeyTime];
  2456. Log.nEvents=Log.nEvents+1;
  2457. Log.Events(Log.nEvents).event='MRI_Trigger';
  2458. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2459. Log.Events(Log.nEvents).info = 'Received';
  2460. if strcmp(Par.SetUp,'NIN') % send start bit to sync ephys system
  2461. %dasword(00000);
  2462. send_serial_data(0);
  2463. WordsSent=WordsSent+1; %keep track of how many words are sent so we back-check TDT against the log
  2464. Log.Words(WordsSent)=00000; %collect all the words that are sent to TDT
  2465. end
  2466. case Par.KeyJuice
  2467. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2468. Par.ManualReward = true;
  2469. Log.ManualRewardTime = ...
  2470. [Log.ManualRewardTime; Par.KeyTime];
  2471. end
  2472. case Par.KeyStim
  2473. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2474. if ~Par.ToggleHideStim
  2475. Par.ToggleHideStim = true;
  2476. Log.nEvents=Log.nEvents+1;
  2477. Log.Events(Log.nEvents).event='StimOff';
  2478. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2479. Log.Events(Log.nEvents).info = 'Off';
  2480. else
  2481. Par.ToggleHideStim = false;
  2482. Log.nEvents=Log.nEvents+1;
  2483. Log.Events(Log.nEvents).event='StimOn';
  2484. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2485. Log.Events(Log.nEvents).info = 'On';
  2486. end
  2487. end
  2488. case Par.KeyFix
  2489. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2490. if ~Par.ToggleHideFix
  2491. Par.ToggleHideFix = true;
  2492. Log.nEvents=Log.nEvents+1;
  2493. Log.Events(Log.nEvents).event='FixOff';
  2494. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2495. Log.Events(Log.nEvents).info = 'Off';
  2496. else
  2497. Par.ToggleHideFix = false;
  2498. Log.nEvents=Log.nEvents+1;
  2499. Log.Events(Log.nEvents).event='FixOn';
  2500. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2501. Log.Events(Log.nEvents).info = 'On';
  2502. end
  2503. end
  2504. case Par.KeyPause
  2505. if Par.KeyDetectedInTrackerWindow && Par.Allow_Calls_To_PTB_win % only in Tracker
  2506. if ~Par.Pause
  2507. Par.Pause=true;
  2508. fprintf('Time-out ON\n');
  2509. Log.nEvents=Log.nEvents+1;
  2510. Log.Events(Log.nEvents).event='PauseOn';
  2511. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2512. Log.Events(Log.nEvents).info = 'On';
  2513. Par.PauseStartTime=Par.KeyTime;
  2514. else
  2515. Par.Pause=false;
  2516. Par.PauseStopTime=Par.KeyTime-Par.PauseStartTime;
  2517. fprintf(['Time-out OFF (' num2str(Par.PauseStopTime) ' s)\n']);
  2518. Log.TotalTimeOut = Log.TotalTimeOut+Par.PauseStopTime;
  2519. Log.TimeOutThisRun=Log.TimeOutThisRun+Par.PauseStopTime;
  2520. Log.nEvents=Log.nEvents+1;
  2521. Log.Events(Log.nEvents).event='PauseOff';
  2522. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2523. Log.Events(Log.nEvents).info = 'Off';
  2524. end
  2525. elseif ~Par.Allow_Calls_To_PTB_win
  2526. fprintf('You cannot give a time-out during a vlc-movie...\n');
  2527. end
  2528. case Par.KeyRewTimeSet
  2529. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2530. Par.RewardTime=Par.RewardTimeSet;
  2531. Par.Times.Targ = Par.RewardFixHoldTime;
  2532. fprintf('Reward schedule set as defined in ParSettings\n');
  2533. end
  2534. case Par.KeyShowRewTime
  2535. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2536. fprintf('Reward amount (s):\n');
  2537. Par.RewardTime
  2538. fprintf('Fix time to get reward:\n' );
  2539. Par.Times.Targ
  2540. end
  2541. case Par.KeyCyclePos
  2542. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2543. if ~Par.PositionLocked
  2544. if Par.ToggleCyclePos
  2545. Par.ToggleCyclePos = false;
  2546. fprintf('Toggle automatic position cycling: OFF\n');
  2547. else
  2548. Par.ToggleCyclePos = true;
  2549. fprintf('Toggle automatic position cycling: ON\n');
  2550. end
  2551. end
  2552. end
  2553. case Par.KeyLockPos
  2554. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2555. if ~Par.PositionLocked
  2556. Par.PositionLocked=true;
  2557. fprintf('Fix position LOCKED\n');
  2558. else
  2559. Par.PositionLocked=false;
  2560. fprintf('Fix position UNLOCKED\n');
  2561. end
  2562. end
  2563. case Par.Key1
  2564. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2565. if ~Par.PositionLocked
  2566. Par.SwitchPos = true;
  2567. Par.WhichPos = '1';
  2568. end
  2569. end
  2570. case Par.Key2
  2571. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2572. if ~Par.PositionLocked
  2573. Par.SwitchPos = true;
  2574. Par.WhichPos = '2';
  2575. end
  2576. end
  2577. case Par.Key3
  2578. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2579. if ~Par.PositionLocked
  2580. Par.SwitchPos = true;
  2581. Par.WhichPos = '3';
  2582. end
  2583. end
  2584. case Par.Key4
  2585. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2586. if ~Par.PositionLocked
  2587. Par.SwitchPos = true;
  2588. Par.WhichPos = '4';
  2589. end
  2590. end
  2591. case Par.Key5
  2592. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2593. if ~Par.PositionLocked
  2594. Par.SwitchPos = true;
  2595. Par.WhichPos = '5';
  2596. end
  2597. end
  2598. case Par.KeyNext
  2599. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2600. if ~Par.PositionLocked
  2601. Par.SwitchPos = true;
  2602. Par.WhichPos = 'Next';
  2603. % case Par.KeyPrevious
  2604. % Par.SwitchPos = true;
  2605. % Par.WhichPos = 'Prev';
  2606. end
  2607. end
  2608. case Par.KeyLeftResp
  2609. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2610. fprintf('LEFT response indicators only\n');
  2611. Log.nEvents=Log.nEvents+1;
  2612. Log.Events(Log.nEvents).event='LeftRespOnly';
  2613. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2614. Log.Events(Log.nEvents).info = 'None';
  2615. Par.RespProbSetting=1;
  2616. Par.ForceRespSide = true;
  2617. end
  2618. case Par.KeyRightResp
  2619. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2620. fprintf('RIGHT response indicators only\n');
  2621. Log.nEvents=Log.nEvents+1;
  2622. Log.Events(Log.nEvents).event='RightRespOnly';
  2623. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2624. Log.Events(Log.nEvents).info = 'None';
  2625. Par.RespProbSetting=2;
  2626. Par.ForceRespSide = true;
  2627. end
  2628. case Par.KeyRandResp
  2629. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2630. fprintf('PROBABLISTIC response indicators\n');
  2631. Log.nEvents=Log.nEvents+1;
  2632. Log.Events(Log.nEvents).event='RandRespInd';
  2633. Log.Events(Log.nEvents).t=Par.KeyTime-Par.ExpStart;
  2634. Log.Events(Log.nEvents).info = 'None';
  2635. Par.RespProbSetting=0;
  2636. Par.ForceRespSide = true;
  2637. end
  2638. case Par.KeyBeam
  2639. if Par.KeyDetectedInTrackerWindow % only in Tracker
  2640. Par.KeyBeamInd = Par.KeyBeamInd+1;
  2641. if Par.KeyBeamInd > size(Par.KeyBeamStates,1)-1
  2642. Par.KeyBeamInd = Par.KeyBeamInd - ...
  2643. (size(Par.KeyBeamStates,1)-1);
  2644. end
  2645. switch Par.KeyBeamInd
  2646. case 1
  2647. fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
  2648. ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
  2649. ' - TRIAL & FIX need hand in\n']);
  2650. case 2
  2651. fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
  2652. ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
  2653. ' - ONLY TRIAL needs hand in\n']);
  2654. case 3
  2655. fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
  2656. ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
  2657. ' - ONLY FIX needs hand in\n']);
  2658. case 4
  2659. fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
  2660. ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
  2661. ' - TRIAL & FIX need hand in\n']);
  2662. case 5
  2663. fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
  2664. ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
  2665. ' - TRIAL & FIX need hand in\n']);
  2666. case 6
  2667. fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
  2668. ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
  2669. ' - ONLY TRIAL needs hand in\n']);
  2670. case 7
  2671. fprintf(['BEAMSTATE: ' Par.KeyBeamStates{Par.KeyBeamInd+1,1} ...
  2672. ' - ' Par.KeyBeamStates{Par.KeyBeamInd+1,2} ...
  2673. ' - ONLY FIX needs hand in\n']);
  2674. end
  2675. Par.HandInBothOrEither = Par.KeyBeamStates{Par.KeyBeamInd+1,2};
  2676. Par.TrialNeeds.HandIsIn = Par.KeyBeamStates{Par.KeyBeamInd+1,3};
  2677. Par.FixNeeds.HandIsIn = Par.KeyBeamStates{Par.KeyBeamInd+1,4};
  2678. % set-up function to check whether to draw fixation
  2679. if Par.FixNeeds.HandIsIn && strcmp(Par.HandInBothOrEither,'Both')
  2680. Par.HideFix_BasedOnHandIn = @(Par) ~all(Par.HandIsIn);
  2681. elseif Par.FixNeeds.HandIsIn && strcmp(Par.HandInBothOrEither,'Either')
  2682. Par.HideFix_BasedOnHandIn = @(Par) ~any(Par.HandIsIn);
  2683. else
  2684. Par.HideFix_BasedOnHandIn = @(Par) false;
  2685. end
  2686. % functions for lever task
  2687. if Par.TrialNeeds.HandIsIn && Par.TrialNeeds.LeversAreDown % hands in / levers down
  2688. Par.CanStartTrial = @(Par) (all(Par.HandIsIn) && ~any(Par.LeverIsUp));
  2689. elseif Par.TrialNeeds.HandIsIn % only hands in
  2690. Par.CanStartTrial = @(Par) all(Par.HandIsIn);
  2691. elseif Par.TrialNeeds.LeversAreDown % only levers down
  2692. Par.CanStartTrial = @(Par) ~any(Par.LeverIsUp);
  2693. else % independent of hand and lever position
  2694. Par.CanStartTrial = @(Par) true;
  2695. end
  2696. end
  2697. end
  2698. Par.KeyWasDown=true;
  2699. end
  2700. elseif Par.KeyIsDown && Par.KeyWasDown
  2701. Par.SwitchPos = false;
  2702. elseif ~Par.KeyIsDown && Par.KeyWasDown
  2703. % key is released
  2704. Par.KeyWasDown = false;
  2705. Par.SwitchPos = false;
  2706. end
  2707. % reset to false
  2708. Par.KeyDetectedInTrackerWindow=false;
  2709. end
  2710. % check DAS for manual responses
  2711. function CheckManual
  2712. %check the incoming signal on DAS channel #3
  2713. % NB dasgetlevel only starts counting at the third channel (#2)
  2714. daspause(5);
  2715. ChanLevels=dasgetlevel;
  2716. Log.RespSignal = ChanLevels(Par.ConnectBox.PhotoAmp(:)-2);
  2717. % dasgetlevel starts reporting at channel 3, so
  2718. % subtract 2 from the channel you want (1 based)
  2719. % Log.RespSignal is a vector with as many channels as are in use
  2720. InterpretManual;
  2721. end
  2722. % interpret manual response signal
  2723. function InterpretManual
  2724. % levels are different for differnet das cards
  2725. if strcmp(computer,'PCWIN64')
  2726. Threshold=40000;
  2727. elseif strcmp(computer,'PCWIN')
  2728. Threshold=2750;
  2729. end
  2730. Par.BeamWasBlocked = Par.BeamIsBlocked;
  2731. % vector that tells us for all used channels whether blocked
  2732. Par.BeamIsBlocked = Log.RespSignal < Threshold;
  2733. % Log any changes
  2734. if any(Par.BeamWasBlocked(:) ~= Par.BeamIsBlocked(:))
  2735. Log.nEvents=Log.nEvents+1;
  2736. Log.Events(Log.nEvents).event=...
  2737. strcat('BeamStateChange ', mat2str(Par.BeamIsBlocked));
  2738. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  2739. Par.HandIsIn =Par.BeamIsBlocked(Par.ConnectBox.PhotoAmp_HandIn);
  2740. Par.LeverIsUp=Par.BeamIsBlocked(Par.ConnectBox.PhotoAmp_Levers);
  2741. if any(Par.LeverIsUp ~= Par.LeverWasUp) && all(Par.LeverIsUp)
  2742. % now both levers are up
  2743. Par.BothLeversUp_time = GetSecs;
  2744. Par.LeverWasUp = Par.LeverIsUp;
  2745. elseif any(Par.LeverIsUp ~= Par.LeverWasUp) && ~all(Par.LeverIsUp)
  2746. % something changed: both are not up
  2747. Par.BothLeversUp_time = Inf;
  2748. Par.LeverWasUp = Par.LeverIsUp;
  2749. end
  2750. end
  2751. if ~strcmp(Par.ResponseBox.Task, 'DetectGoSignal')
  2752. % interpret depending on response box type
  2753. switch Par.ResponseBox.Type
  2754. % case 'Beam'
  2755. case 'Lift'
  2756. if ~any(Par.HandWasIn) && any(Par.HandIsIn) % from none to any
  2757. %fprintf('going from none to one\n')
  2758. Par.HandInPrev_Moment = Par.HandInNew_Moment; % the previous hand-in moment
  2759. Par.HandInNew_Moment = GetSecs; % current hand-in moment
  2760. Par.HandWasIn = Par.HandIsIn;
  2761. elseif any(Par.HandWasIn) && ~any(Par.HandIsIn)
  2762. %fprintf('all out now\n')
  2763. Par.HandInPrev_Moment = Par.HandInNew_Moment;
  2764. Par.HandWasIn = Par.HandIsIn;
  2765. elseif any(Par.HandWasIn) && any(Par.HandIsIn) && Par.RewardRunning
  2766. Par.HandInPrev_Moment = Par.HandInNew_Moment;
  2767. end
  2768. if strcmp(Par.HandInBothOrEither, 'Both') && ...
  2769. all(Par.HandIsIn) % both in
  2770. if ~any(Par.HandWasIn)
  2771. % only do this if 1 channel is used
  2772. Log.nEvents=Log.nEvents+1;
  2773. Log.Events(Log.nEvents).event='BothHandsIn';
  2774. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  2775. Par.HandWasIn=Par.HandIsIn;
  2776. end
  2777. elseif strcmp(Par.HandInBothOrEither, 'Either') && ...
  2778. any(Par.HandIsIn) % both in % at least one blocked
  2779. if ~all(Par.HandWasIn)
  2780. % only do this if 1 channel is used
  2781. Log.nEvents=Log.nEvents+1;
  2782. if Par.HandIsIn(1)
  2783. Log.Events(Log.nEvents).event='LeftHandIn';
  2784. else
  2785. Log.Events(Log.nEvents).event='RightHandIn';
  2786. end
  2787. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  2788. Par.HandWasIn=Par.HandIsIn;
  2789. end
  2790. elseif ~all(Par.HandIsIn)
  2791. if any(Par.HandWasIn)
  2792. Log.nEvents=Log.nEvents+1;
  2793. Log.Events(Log.nEvents).event='HandsOut';
  2794. Log.Events(Log.nEvents).t=lft-Par.ExpStart;
  2795. Par.HandWasIn=Par.HandIsIn;
  2796. end
  2797. end
  2798. end
  2799. end
  2800. end
  2801. % give automated reward for fixation
  2802. function GiveRewardAutoFix
  2803. % Get correct reward duration
  2804. switch Par.RewardType
  2805. case 0
  2806. Par.RewardTimeCurrent = Par.RewardTime;
  2807. case 1
  2808. if size(Par.RewardTime,2)>1 % progressive schedule still active
  2809. % Get number of consecutive correct trials
  2810. rownr= find(Par.RewardTime(:,1)<Par.CorrStreakcount(2),1,'last');
  2811. Par.RewardTimeCurrent = Par.RewardTime(rownr,2);
  2812. else %schedule overruled by slider settings
  2813. Par.RewardTimeCurrent = Par.RewardTime;
  2814. end
  2815. case 2
  2816. Par.RewardTimeCurrent = 0;
  2817. end
  2818. if ~isempty(Par.RewardFixMultiplier)
  2819. if ~all(Par.HandIsIn) && any(Par.HandIsIn) % one hand in
  2820. hig = Par.FixReward_HandInGain(1);
  2821. elseif all(Par.HandIsIn) % both hands in
  2822. hig = Par.FixReward_HandInGain(2);
  2823. else % no hands in
  2824. hig = 1;
  2825. end
  2826. Par.RewardTimeCurrent = hig * Par.RewardFixMultiplier * Par.RewardTimeCurrent;
  2827. if Par.RewardFixMultiplier <= 0 % no reward given if true
  2828. return
  2829. end
  2830. end
  2831. if size(Par.Times.Targ,2)>1
  2832. rownr= find(Par.Times.Targ(:,1)<Par.CorrStreakcount(2),1,'last');
  2833. Par.Times.TargCurrent=Par.Times.Targ(rownr,2);
  2834. else
  2835. Par.Times.TargCurrent=Par.Times.Targ;
  2836. end
  2837. % only give reward when Reward time >0
  2838. if Par.RewardTimeCurrent>0
  2839. % Give the reward
  2840. Par.RewardStartTime=GetSecs;
  2841. if strcmp(computer,'PCWIN64')
  2842. dasjuice(10); % 64bit das card
  2843. else
  2844. dasjuice(5) %old card dasjuice(5)
  2845. end
  2846. Par.RewardRunning=true;
  2847. % Play back a sound
  2848. if Par.RewardSound
  2849. RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
  2850. RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
  2851. sound(RewY,Par.RewSndPar(1));
  2852. end
  2853. Log.nEvents=Log.nEvents+1;
  2854. Log.Events(Log.nEvents).event='RewardFix';
  2855. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  2856. Log.Events(Log.nEvents).info = 'None';
  2857. end
  2858. end
  2859. % stop reward delivery
  2860. function StopRewardIfNeeded
  2861. if Par.RewardRunning && GetSecs >= ...
  2862. Par.RewardStartTime+Par.RewardTimeCurrent
  2863. dasjuice(0);
  2864. Par.RewardRunning=false;
  2865. Log.TotalReward = Log.TotalReward+Par.RewardTimeCurrent;
  2866. %Par.ResponseSide = 0;
  2867. Log.nEvents=Log.nEvents+1;
  2868. Log.Events(Log.nEvents).event='RewardStopped';
  2869. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  2870. Log.Events(Log.nEvents).info = 'None';
  2871. end
  2872. end
  2873. % give automated reward for task
  2874. function GiveRewardAutoTask
  2875. if Par.Rew_BasedOnHandIn(Par) && ~Par.Pause
  2876. if ~isempty(Par.RewardTaskMultiplier)
  2877. Par.RewardTimeCurrent = Par.RewardTaskMultiplier * Par.RewardTime;
  2878. else
  2879. Par.RewardTimeCurrent = Par.RewardTime;
  2880. end
  2881. % gain for which lever is used
  2882. if isfield(Par,'RespLeverGain')
  2883. if any(Par.LeverIsUp) && ~all(Par.LeverIsUp) % only one up
  2884. Par.RewardTimeCurrent = Par.RespLeverGain(...
  2885. logical(Par.LeverIsUp))*Par.RewardTimeCurrent;
  2886. end
  2887. end
  2888. % gain for having hands in (when defined)
  2889. if isfield(Par,'TaskReward_HandInGain')
  2890. if any(Par.HandIsIn) && ~all(Par.HandIsIn) % only hand in
  2891. Par.RewardTimeCurrent = Par.TaskReward_HandInGain(1)*Par.RewardTimeCurrent;
  2892. elseif all(Par.HandIsIn) % both hands in
  2893. Par.RewardTimeCurrent = Par.TaskReward_HandInGain(2)*Par.RewardTimeCurrent;
  2894. end
  2895. end
  2896. % Give the reward
  2897. if Par.RewardTimeCurrent>0
  2898. Par.RewardStartTime=GetSecs;
  2899. if strcmp(computer,'PCWIN64')
  2900. dasjuice(5.1); % 64bit das card
  2901. else
  2902. dasjuice(5) %old card dasjuice(5)
  2903. end
  2904. Par.RewardRunning=true;
  2905. % Play back a sound
  2906. if Par.RewardSound
  2907. RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
  2908. RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
  2909. sound(RewY,Par.RewSndPar(1));
  2910. end
  2911. Log.nEvents=Log.nEvents+1;
  2912. Log.Events(Log.nEvents).event='RewardAutoTask';
  2913. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  2914. Log.Events(Log.nEvents).info = 'None';
  2915. end
  2916. end
  2917. end
  2918. % give automated reward for hand in
  2919. function GiveRewardAutoHandIn
  2920. Par.RewardTimeCurrent = Par.RewardForHandsIn_Quant(sum(Par.HandIsIn));
  2921. if ~all(Par.HandIsIn) && any(Par.HandIsIn) % only one hand in
  2922. Par.RewardTimeCurrent = ...
  2923. Par.RewardForHandsIn_MultiplierPerHand(Par.HandIsIn)*Par.RewardTimeCurrent;
  2924. end
  2925. % Give the reward
  2926. if Par.RewardTimeCurrent>0
  2927. Par.RewardStartTime=GetSecs;
  2928. Par.RewHandStart=Par.RewardStartTime;
  2929. if strcmp(computer,'PCWIN64')
  2930. dasjuice(10); % 64bit das card
  2931. else
  2932. dasjuice(5) %old card dasjuice(5)
  2933. end
  2934. Par.RewardRunning=true;
  2935. % Play back a sound
  2936. if Par.RewardSound
  2937. RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
  2938. RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
  2939. sound(RewY,Par.RewSndPar(1));
  2940. end
  2941. Log.nEvents=Log.nEvents+1;
  2942. Log.Events(Log.nEvents).event='RewardAutoHand';
  2943. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  2944. Log.Events(Log.nEvents).info = 'None';
  2945. end
  2946. end
  2947. % give manual reward
  2948. function GiveRewardManual
  2949. Par.RewardTimeCurrent = Par.RewardTimeManual;
  2950. % Give the reward
  2951. Par.RewardStartTime=GetSecs;
  2952. Par.RewardRunning=true;
  2953. if strcmp(computer,'PCWIN64')
  2954. dasjuice(10); % 64bit das card
  2955. else
  2956. dasjuice(5) %old card dasjuice(5)
  2957. end
  2958. % Play back a sound
  2959. if Par.RewardSound
  2960. RewT=0:1/Par.RewSndPar(1):Par.RewardTimeCurrent;
  2961. RewY=Par.RewSndPar(3)*sin(2*pi*Par.RewSndPar(2)*RewT);
  2962. sound(RewY,Par.RewSndPar(1));
  2963. end
  2964. Log.nEvents=Log.nEvents+1;
  2965. Log.Events(Log.nEvents).event='RewardMan';
  2966. Log.Events(Log.nEvents).t=GetSecs-Par.ExpStart;
  2967. Log.Events(Log.nEvents).info = 'None';
  2968. end
  2969. % check eye-tracker recording status
  2970. function CheckEyeRecStatus
  2971. daspause(5);
  2972. ChanLevels=dasgetlevel;
  2973. Par.CheckRecLevel=ChanLevels(Par.ConnectBox.EyeRecStat-2);
  2974. %Par.CheckRecLevel
  2975. % dasgetlevel starts reporting at channel 3, so subtract 2 from the channel you want (1 based)
  2976. if strcmp(computer,'PCWIN64') && Par.CheckRecLevel < 48000 % 64bit das card
  2977. Par.EyeRecStatus = 1;
  2978. elseif strcmp(computer,'PCWIN') && Par.CheckRecLevel < 2750 % old das card
  2979. Par.EyeRecStatus = 1;
  2980. else
  2981. Par.EyeRecStatus = 0;
  2982. end
  2983. end
  2984. % set eye-tracker recording status
  2985. function SetEyeRecStatus(status)
  2986. if status % switch on
  2987. Par.EyeRecTriggerLevel=0;
  2988. elseif ~status % switch off
  2989. Par.EyeRecTriggerLevel=1;
  2990. end
  2991. tEyeRecSet = GetSecs;
  2992. %Par.EyeRecTriggerLevel
  2993. dasbit(0,Par.EyeRecTriggerLevel);
  2994. Log.nEvents=Log.nEvents+1;
  2995. if Par.EyeRecTriggerLevel
  2996. Log.Events(Log.nEvents).event='EyeRecOff';
  2997. else
  2998. Log.Events(Log.nEvents).event='EyeRecOn';
  2999. end
  3000. Log.Events(Log.nEvents).t=tEyeRecSet-Par.ExpStart;
  3001. Log.Events(Log.nEvents).info = 'None';
  3002. end
  3003. % create radial checkerboard
  3004. function chkimg = RadialCheckerBoard(radius, sector, chsz)
  3005. %img = RadialCheckerBoard(radius, sector, chsz, propel)
  3006. % Returns a bitmap image of a radial checkerboard pattern.
  3007. % The image is a square of 2*OuterRadius pixels.
  3008. %
  3009. % Parameters of wedge:
  3010. % radius : eccentricity of radii in pixels = [outer, inner]
  3011. % sector : polar angles in degrees = [start, end] from -180 to 180
  3012. % chsz : size of checks in log factors & degrees respectively = [eccentricity, angle]
  3013. % propel : Optional, if defined there are two wedges, one in each hemifield
  3014. %
  3015. checkerboard = [0 Par.ScrWhite; Par.ScrWhite 0];
  3016. img = ones(2*radius(1), 2*radius(1)) * ceil(Par.ScrWhite/2);
  3017. for x = -radius : radius
  3018. for y = -radius : radius
  3019. [th, r] = cart2pol(x,y);
  3020. th = th * 180/pi;
  3021. if th >= sector(1) && th < sector(2) && r < radius(1) && r > radius(2)
  3022. img(y+radius(1)+1,x+radius(1)+1) = checkerboard(mod(floor(log(r)*chsz(1)),2) + 1, mod(floor((th + sector(1))/chsz(2)),2) + 1);
  3023. end
  3024. end
  3025. end
  3026. img = flipud(img);
  3027. if nargin > 3
  3028. rotimg = rot90(img,2);
  3029. non_grey_pixels = find(rotimg ~= ceil(Par.ScrWhite/2));
  3030. img(non_grey_pixels) = rotimg(non_grey_pixels);
  3031. end
  3032. img = uint8(img);
  3033. width = radius(1)*2;
  3034. [X, Y] = meshgrid([-width/2:-1 1:width/2], [-width/2:-1 1:width/2]);
  3035. [T, R] = cart2pol(X,Y);
  3036. circap = ones(width, width);
  3037. circap(R > width/2) = 1;
  3038. alphas = linspace(1, 0, 0);
  3039. circap(R > width/2) = 0;
  3040. circap(R < radius(2)) = 0;
  3041. chkimg = img;
  3042. chkimg(:,:,2) = uint8(abs(double(img)-Par.ScrWhite));
  3043. chkimg(:,:,3)=circap.*Par.ScrWhite;
  3044. end
  3045. % check eye only (dascheck without tracker gui update)
  3046. function [Hit, Time] = DasCheckEyeOnly %#ok<*DEFNU>
  3047. Hit = LPStat(1); %Hit yes or no
  3048. Time = LPStat(0); %time
  3049. POS = dasgetposition();
  3050. P = POS.*Par.ZOOM; %average position over window initialized in DasIni
  3051. % eye position to global to allow logging
  3052. Par.CurrEyePos = [POS(1) POS(2)];
  3053. end
  3054. % log eye info
  3055. function LogEyeInfo
  3056. % if nothing changes in calibration
  3057. % only log position at 5 Hz
  3058. if size(Log.Eye,2)==0 || ...
  3059. (sum(Par.ScaleOff-Log.Eye(end).ScaleOff) ~= 0 || ...
  3060. (GetSecs-Par.ExpStart) - Log.Eye(end).t > 1/5)
  3061. eye_i = size(Log.Eye,2)+1;
  3062. Log.Eye(eye_i).t = GetSecs-Par.ExpStart;
  3063. Log.Eye(eye_i).CurrEyePos = Par.CurrEyePos;
  3064. Log.Eye(eye_i).CurrEyeZoom = Par.ZOOM;
  3065. Log.Eye(eye_i).ScaleOff = Par.ScaleOff;
  3066. end
  3067. end
  3068. % Update hand task state
  3069. function UpdateHandTaskState(NewState)
  3070. Par.ResponseState = NewState;
  3071. Par.ResponseStateChangeTime = GetSecs;
  3072. Log.nEvents=Log.nEvents+1;
  3073. switch NewState
  3074. case Par.RESP_STATE_WAIT
  3075. Log.Events(Log.nEvents).event=...
  3076. 'HandTaskState-Wait';
  3077. Par.PickRandomIndicatorPosition = true;
  3078. case Par.RESP_STATE_GO
  3079. Log.Events(Log.nEvents).event=...
  3080. 'HandTaskState-Go';
  3081. case Par.RESP_STATE_DONE
  3082. Log.Events(Log.nEvents).event=...
  3083. 'HandTaskState-Done';
  3084. otherwise
  3085. Log.Events(Log.nEvents).event=...
  3086. strcat('HandTaskState-Unknown-',NewState);
  3087. end
  3088. Log.Events(Log.nEvents).t=Par.ResponseStateChangeTime;
  3089. end
  3090. % Close the current PTB window
  3091. function Close_PTB_win
  3092. Screen('Close', Par.window);
  3093. Par.Allow_Calls_To_PTB_win = false;
  3094. end
  3095. % Re-open the default PTB window
  3096. function Reopen_PTB_win
  3097. [Par.window, Par.wrect] = PsychImaging('OpenWindow',...
  3098. Par.ScrNr,0,[],[],2,[],[],1);
  3099. [sourceFactorOld,destinationFactorOld,colorMaskOld] = ...
  3100. Screen('BlendFunction',Par.window,...
  3101. GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  3102. MaxPriority(Par.window);
  3103. Par.Allow_Calls_To_PTB_win = true;
  3104. end
  3105. end