runstim.html 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. <!DOCTYPE html
  2. PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  3. <html><head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <!--
  6. This HTML was auto-generated from MATLAB code.
  7. To make changes, update the MATLAB code and republish this document.
  8. --><title>runstim</title><meta name="generator" content="MATLAB 7.11"><link rel="schema.DC" href="http://purl.org/dc/elements/1.1/"><meta name="DC.date" content="2012-03-02"><meta name="DC.source" content="runstim.m"><style type="text/css">
  9. body {
  10. background-color: white;
  11. margin:10px;
  12. }
  13. h1 {
  14. color: #990000;
  15. font-size: x-large;
  16. }
  17. h2 {
  18. color: #990000;
  19. font-size: medium;
  20. }
  21. /* Make the text shrink to fit narrow windows, but not stretch too far in
  22. wide windows. */
  23. p,h1,h2,div.content div {
  24. max-width: 600px;
  25. /* Hack for IE6 */
  26. width: auto !important; width: 600px;
  27. }
  28. pre.codeinput {
  29. background: #EEEEEE;
  30. padding: 10px;
  31. }
  32. @media print {
  33. pre.codeinput {word-wrap:break-word; width:100%;}
  34. }
  35. span.keyword {color: #0000FF}
  36. span.comment {color: #228B22}
  37. span.string {color: #A020F0}
  38. span.untermstring {color: #B20000}
  39. span.syscmd {color: #B28C00}
  40. pre.codeoutput {
  41. color: #666666;
  42. padding: 10px;
  43. }
  44. pre.error {
  45. color: red;
  46. }
  47. p.footer {
  48. text-align: right;
  49. font-size: xx-small;
  50. font-weight: lighter;
  51. font-style: italic;
  52. color: gray;
  53. }
  54. </style></head><body><div class="content"><pre class="codeinput"><span class="keyword">function</span> runstim(Hnd)
  55. <span class="comment">%Updated 19_10_2011 Chris van der Togt</span>
  56. <span class="keyword">global</span> Par <span class="comment">%global parameters</span>
  57. <span class="keyword">global</span> LPStat <span class="comment">%das status values</span>
  58. <span class="keyword">global</span> StimObj <span class="comment">%stimulus objects</span>
  59. <span class="keyword">if</span> ~isfield(StimObj, <span class="string">'Stm'</span>)
  60. disp(<span class="string">'ERROR: No stimulus'</span>);
  61. <span class="keyword">return</span>
  62. <span class="keyword">end</span>
  63. Times = Par.Times; <span class="comment">%copy timing structure</span>
  64. BG = Par.BG; <span class="comment">%background Color</span>
  65. cgflip(BG(1), BG(2), BG(3))
  66. Stms = StimObj.Stm; <span class="comment">%all stimuli</span>
  67. Objs = StimObj.Obj; <span class="comment">%all graphical objects</span>
  68. IDs = [ Objs(:).Id ]; <span class="comment">%Ids of all graphical objects</span>
  69. <span class="comment">%they should all be not loaded, but just to make sure</span>
  70. <span class="keyword">for</span> i = 1:length(IDs)
  71. <span class="keyword">if</span> strcmp(Objs(i).Type, <span class="string">'Texture'</span>) || strcmp(Objs(i).Type, <span class="string">'Bitmap'</span>) || strcmp(Objs(i).Type, <span class="string">'Bezier'</span>)
  72. Objs(i).Data.isLoaded = false;
  73. <span class="keyword">end</span>
  74. <span class="keyword">end</span>
  75. <span class="comment">%....EVENTS.........................</span>
  76. FIX = 1;
  77. STM = 2;
  78. TARG = 3;
  79. TARGOF = 4;
  80. <span class="comment">%MICR = 5;</span>
  81. FS = 0;
  82. FO = 0;
  83. <span class="comment">%////YOUR STIMULATION CONTROL LOOP /////////////////////////////////</span>
  84. Hit = 2;
  85. Par.ESC = false; <span class="comment">%escape has not been pressed</span>
  86. <span class="keyword">while</span> ~Par.ESC
  87. <span class="comment">%Pretrial</span>
  88. <span class="comment">%SETUP YOUR STIMULI FOR THIS TRIAL</span>
  89. <span class="keyword">if</span> Par.Drum &amp;&amp; Hit ~= 2 <span class="comment">%if drumming and this was an error trial</span>
  90. <span class="comment">%just redo with current sttings</span>
  91. <span class="keyword">else</span>
  92. <span class="comment">%randomization</span>
  93. I = ceil(rand*length(Stms));
  94. <span class="comment">%or use custom randomisation procedure</span>
  95. <span class="comment">%condition and associated stimuli</span>
  96. EVENT = Stms(I).Event;
  97. <span class="comment">%calllib(Par.Dll, 'DO_Word', I); %send word bit and condition</span>
  98. dasword( I); <span class="comment">%send word bit and condition</span>
  99. <span class="comment">%timing</span>
  100. PREFIXT = Times.ToFix; <span class="comment">%time to enter fixation window</span>
  101. FIXT = fix(Times.Fix + rand*Times.RndFix); <span class="comment">%time to fix before stim onset</span>
  102. STIMT = fix(Par.Times.Stim + rand*Times.RndStim); <span class="comment">%time that stimulus is displayed</span>
  103. TARGT = fix(Times.Targ + round(2*rand-1)*Times.RndTarg); <span class="comment">%time to fix before target onset</span>
  104. RACT = Times.Rt; <span class="comment">%reaction time</span>
  105. FLtime = Par.fliptime; <span class="comment">%adjusting for fliptime</span>
  106. STIMT = (round(STIMT/FLtime) - 0) * FLtime;
  107. TARGT = (round(TARGT/FLtime) - 0) * FLtime;
  108. <span class="comment">%control window setup</span>
  109. FI = find(IDs == Stms(I).Fix, 1);
  110. TI = find(IDs == Stms(I).Targ, 1);
  111. WIN = [ Objs(FI).Data.cx, Objs(FI).Data.cy, Par.PixPerDeg*Par.FixWdDeg, Par.PixPerDeg*Par.FixHtDeg, 0; <span class="keyword">...</span><span class="comment"> %Fix</span>
  112. Objs(TI).Data.cx, Objs(TI).Data.cy, Par.PixPerDeg*Par.TargWdDeg, Par.PixPerDeg*Par.TargHtDeg, 2 ]; <span class="comment">%Targ</span>
  113. Par.OFFx = Objs(FI).Data.cx;
  114. Par.OFFy = Objs(FI).Data.cy;
  115. Alt = Stms(I).Talt{:};
  116. <span class="keyword">for</span> k = 1:length(Alt)
  117. AI = find(IDs == Alt(k), 1);
  118. WIN = [ WIN; <span class="keyword">...</span>
  119. Objs(AI).Data.cx, Objs(AI).Data.cy, Par.PixPerDeg*Par.TargWdDeg, Par.PixPerDeg*Par.TargHtDeg, 1 ]; <span class="comment">%TAlt</span>
  120. <span class="keyword">end</span>
  121. Par.WIN = WIN';
  122. <span class="comment">%preload tectures and bitmaps</span>
  123. Ids = unique([EVENT{:}]); <span class="comment">%get all object ids in stimulus</span>
  124. Notused = setxor(IDs, Ids);
  125. <span class="comment">%free memory of obsolete sprites</span>
  126. <span class="keyword">for</span> id = Notused <span class="comment">%indices into notused objects</span>
  127. idx = find(IDs == id); <span class="comment">%obtain index to the object corresponding with this id</span>
  128. <span class="keyword">if</span> strcmp(Objs(idx).Type, <span class="string">'Texture'</span>) || strcmp(Objs(idx).Type, <span class="string">'Bitmap'</span>) || strcmp(Objs(idx).Type, <span class="string">'Bezier'</span>)
  129. <span class="keyword">if</span> Objs(idx).Data.isLoaded
  130. cgfreesprite(id) <span class="comment">%unload this sprite to make memory free</span>
  131. Objs(idx).Data.isLoaded = false;
  132. <span class="keyword">end</span>
  133. <span class="keyword">end</span>
  134. <span class="keyword">end</span>
  135. <span class="comment">%load new sprites</span>
  136. <span class="keyword">for</span> id = Ids
  137. idx = find(IDs == id);
  138. <span class="keyword">if</span> strcmp(Objs(idx).Type, <span class="string">'Texture'</span>)
  139. OBJ = Objs(idx).Data;
  140. <span class="keyword">if</span> ~(OBJ.isLoaded) <span class="comment">%is not loaded</span>
  141. Objs(idx).Data = cgTexture(OBJ, <span class="string">'L'</span>, id); <span class="comment">%(L)oad the texture</span>
  142. <span class="keyword">end</span>
  143. <span class="keyword">elseif</span> strcmp(Objs(idx).Type, <span class="string">'Bitmap'</span>)
  144. OBJ = Objs(idx).Data;
  145. <span class="keyword">if</span> ~(OBJ.isLoaded) <span class="comment">%is not loaded</span>
  146. Objs(idx).Data = cgBitmap(OBJ, <span class="string">'L'</span>, id); <span class="comment">%Load the bitmap</span>
  147. <span class="keyword">end</span>
  148. <span class="keyword">elseif</span> strcmp(Objs(idx).Type, <span class="string">'Bezier'</span>)
  149. OBJ = Objs(idx).Data;
  150. <span class="keyword">if</span> ~(OBJ.isLoaded) <span class="comment">%is not loaded</span>
  151. Objs(idx).Data = cgBezier(OBJ, <span class="string">'S'</span>, id); <span class="comment">%draw the bezier on a sprite</span>
  152. <span class="keyword">end</span>
  153. <span class="keyword">end</span>
  154. <span class="keyword">end</span>
  155. <span class="keyword">end</span>
  156. <span class="comment">%/////////////////////////////////////////////////////////////////////</span>
  157. <span class="comment">%START THE TRIAL</span>
  158. <span class="comment">%set control window positions and dimensions</span>
  159. refreshtracker(1) <span class="comment">%for your control display</span>
  160. SetWindowDas <span class="comment">%for the dascard, initializes eye control windows</span>
  161. Abort = false; <span class="comment">%whether subject has aborted before end of trial</span>
  162. <span class="comment">%///////// EVENT 0 START FIXATING //////////////////////////////////////</span>
  163. <span class="comment">%cgellipse(Px,Py,20,20,[1 0 0 ],'f') %the red fixation dot on the screen</span>
  164. cgplotstim(EVENT{FIX}, Objs);
  165. cgflip(BG(1), BG(2), BG(3))
  166. dasreset( 0 ) <span class="comment">%test enter fix window</span>
  167. <span class="comment">% 0 enter fix window</span>
  168. <span class="comment">% 1 leave fix window</span>
  169. <span class="comment">% 2 enter target window</span>
  170. <span class="comment">%LPStat(1) = time (ms) passed since last reset</span>
  171. <span class="comment">%LPStat(2) = control window hit (1 : in or out, 2 : in correct</span>
  172. <span class="comment">% target window</span>
  173. <span class="comment">%LPStat.(3) = hit position x</span>
  174. <span class="comment">%LPStat(4) = hit postion y</span>
  175. <span class="comment">%LPStat(5) = reaction time</span>
  176. <span class="comment">%LPStat(6) = time saccade length</span>
  177. <span class="comment">%subject has to start fixating central dot</span>
  178. Par.SetZero = false; <span class="comment">%set key to false to remove previous presses</span>
  179. <span class="comment">%Par.Updatxy = 1; %centering key is enabled</span>
  180. Time = 1;
  181. Hit = 0;
  182. <span class="keyword">while</span> Time &lt; PREFIXT &amp;&amp; Hit == 0
  183. pause(0.05)
  184. [Hit Time] = DasCheck; <span class="comment">%retrieve position values and plot on Control display</span>
  185. <span class="keyword">end</span>
  186. <span class="comment">%///////// EVENT 1 KEEP FIXATING or REDO ////////////////////////////////////</span>
  187. <span class="keyword">if</span> Hit ~= 0 <span class="comment">%subjects eyes are in fixation window keep fixating for FIX time</span>
  188. <span class="comment">%the tril bit has now automatically been set high!! If the monkey</span>
  189. <span class="comment">%loses fixation he gets another chance but the tril bit just stays</span>
  190. <span class="comment">%high and this results in a longer prestim period</span>
  191. dasreset( 1 ); <span class="comment">%set test parameters for exiting fix window</span>
  192. Time = 1;
  193. Hit = 0;
  194. <span class="keyword">while</span> Time &lt; FIXT &amp;&amp; Hit== 0
  195. <span class="comment">%Check for 10 ms</span>
  196. pause(0.005)
  197. <span class="comment">%detect eye enter/exit of control windows</span>
  198. <span class="comment">%this will also automaitcally</span>
  199. <span class="comment">%occur during pauzes due to a</span>
  200. <span class="comment">%callback routine run every single ms</span>
  201. [Hit Time] = DasCheck; <span class="comment">%retrieve eyechannel buffer and events, plot eye motion,</span>
  202. <span class="keyword">end</span>
  203. <span class="keyword">if</span> Hit ~= 0 <span class="comment">%eye has left fixation to early</span>
  204. <span class="comment">%possibly due to eye overshoot, give subject another chance</span>
  205. dasreset( 0 );
  206. Time = 1;
  207. Hit = 0;
  208. <span class="keyword">while</span> Time &lt; PREFIXT &amp;&amp; Hit == 0
  209. pause(0.005)
  210. [Hit Time] = DasCheck; <span class="comment">%retrieve position values and plot on Control display</span>
  211. <span class="keyword">end</span>
  212. <span class="keyword">if</span> Hit ~= 0 <span class="comment">%subjects eyes are in fixation window keep fixating for FIX time</span>
  213. dasreset( 1 ); <span class="comment">%test for exiting fix window</span>
  214. Time = 1;
  215. Hit = 0;
  216. <span class="keyword">while</span> Time &lt; FIXT &amp;&amp; Hit == 0
  217. <span class="comment">%Check for 10 ms</span>
  218. pause(0.005)
  219. [Hit Time] = DasCheck;
  220. <span class="keyword">end</span>
  221. <span class="keyword">else</span>
  222. Hit = -1; <span class="comment">%the subject did not fixate</span>
  223. <span class="keyword">end</span>
  224. <span class="keyword">end</span>
  225. <span class="keyword">else</span>
  226. Hit = -1; <span class="comment">%the subject did not fixate</span>
  227. <span class="keyword">end</span>
  228. <span class="comment">%///////// EVENT 2 DISPLAY STIMULUS //////////////////////////////////////</span>
  229. <span class="keyword">if</span> Hit == 0 <span class="comment">%subject kept fixation, display stimulus</span>
  230. Par.Trlcount = Par.Trlcount + 1; <span class="comment">%counts total number of trials for this session</span>
  231. <span class="comment">%change your display between these lines.......................</span>
  232. <span class="comment">% cgpencol(1,1,1)</span>
  233. <span class="comment">% cgrect(-462, 334, 100, 100) %test stimulus for light diode</span>
  234. <span class="comment">% cgellipse(Px,Py,20,20,[1 0 0 ],'f') %fixation dot</span>
  235. <span class="comment">% cgellipse(Par.WIN(1,2), Par.WIN(2,2), 20, 20, [1 0 0 ], 'f') %target</span>
  236. cgplotstim(EVENT{STM}, Objs);
  237. <span class="comment">%..............................................................</span>
  238. FO = cgflip(BG(1), BG(2), BG(3));
  239. FS = FO;
  240. <span class="comment">%cgflip('v'); %this is not nice; cgflip does not give good timing</span>
  241. tic <span class="comment">%measure onset too</span>
  242. dasbit( Par.StimB, 1); <span class="comment">%send stimulus bit to TDT</span>
  243. dasreset( 1 ); <span class="comment">%test for exiting fix window</span>
  244. refreshtracker(2) <span class="comment">%set target window to green</span>
  245. Time = 0;
  246. <span class="comment">%prepare display for next flip TARGON.................</span>
  247. <span class="keyword">if</span> ~isempty(EVENT{TARG})
  248. cgplotstim(EVENT{TARG}, Objs);
  249. EPoch = min( STIMT-10, TARGT-50); <span class="comment">%determine smallest time</span>
  250. <span class="keyword">while</span> Time &lt; EPoch &amp;&amp; Hit == 0
  251. dasrun( 5 );
  252. <span class="comment">%get hit time</span>
  253. [Hit Time] = DasCheck;
  254. <span class="keyword">end</span>
  255. FS = cgflip(BG(1), BG(2), BG(3));
  256. <span class="keyword">end</span>
  257. <span class="keyword">if</span> ~isempty(EVENT{TARGOF})
  258. cgplotstim(EVENT{TARGOF}, Objs);
  259. <span class="comment">%prepare display for next flip.................</span>
  260. <span class="keyword">end</span>
  261. <span class="keyword">while</span> Time &lt; TARGT-50 &amp;&amp; Hit == 0 <span class="comment">%Keep fixating till just before (50ms) target onset</span>
  262. dasrun( 5 );
  263. <span class="comment">%get hit time and plot eyemotion</span>
  264. [Hit Time] = DasCheck; <span class="comment">%plot eye motion in tracker</span>
  265. <span class="keyword">end</span>
  266. <span class="comment">%how much time(ms) do we have left till target onset??? +</span>
  267. <span class="comment">%FlOP* FLtime</span>
  268. delay = floor(TARGT - toc*1000 - FLtime/2); <span class="comment">%hold up calling the next flip</span>
  269. <span class="keyword">if</span> delay &gt; 0
  270. <span class="comment">%calllib(Par.Dll, 'Check', delay)</span>
  271. dasrun(delay)
  272. Hit = LPStat(2); <span class="comment">%don't wast time!!!! on updating the screen</span>
  273. <span class="keyword">else</span>
  274. disp(<span class="string">'WARNING....not enough time between stimoffset and target onset.'</span>)
  275. <span class="keyword">end</span>
  276. <span class="comment">%///////// EVENT 3 TARGET ONSET, REACTION TIME%%//////////////////////////////////////</span>
  277. <span class="keyword">if</span> Hit == 0 <span class="comment">%subject kept fixation, subject may make an eye movement</span>
  278. FS = cgflip(BG(1), BG(2), BG(3));
  279. <span class="comment">% cgflip('v'); %this is not nice; cgflip doesnot give good timing</span>
  280. dasbit( Par.TargetB, 1); <span class="comment">%send target bit to TDT</span>
  281. dasreset(2); <span class="comment">%reset counter and check for entering target window</span>
  282. <span class="comment">%toc %display this to check your internal timing</span>
  283. refreshtracker(3) <span class="comment">%set fix point to green</span>
  284. Time = 0;
  285. <span class="keyword">while</span> Time &lt; RACT &amp;&amp; Hit &lt;= 0 <span class="comment">%RACT = time to respond (reaction time)</span>
  286. <span class="comment">%Check for 5 ms</span>
  287. dasrun( 5)
  288. [Hit Time] = DasCheck;
  289. <span class="keyword">end</span>
  290. <span class="keyword">else</span>
  291. Abort = true;
  292. <span class="keyword">end</span>
  293. <span class="comment">%END EVENT 3</span>
  294. <span class="keyword">else</span>
  295. Abort = true;
  296. <span class="keyword">end</span>
  297. <span class="comment">%END EVENT 2</span>
  298. cgflip(BG(1), BG(2), BG(3));
  299. <span class="comment">%///////// POSTTRIAL AND REWARD //////////////////////////////////////</span>
  300. <span class="keyword">if</span> Hit ~= 0 &amp;&amp; ~Abort <span class="comment">%has entered a target window (false or correct)</span>
  301. <span class="keyword">if</span> Par.Mouserun
  302. HP = line(<span class="string">'XData'</span>, Par.ZOOM * (LPStat(3) + Par.MOff(1)), <span class="string">'YData'</span>, Par.ZOOM * (LPStat(4) + Par.MOff(2)), <span class="string">'EraseMode'</span>,<span class="string">'none'</span>);
  303. <span class="keyword">else</span>
  304. HP = line(<span class="string">'XData'</span>, Par.ZOOM * LPStat(3), <span class="string">'YData'</span>, Par.ZOOM * LPStat(4), <span class="string">'EraseMode'</span>,<span class="string">'none'</span>);
  305. <span class="keyword">end</span>
  306. set(HP, <span class="string">'Marker'</span>, <span class="string">'+'</span>, <span class="string">'MarkerSize'</span>, 20, <span class="string">'MarkerEdgeColor'</span>, <span class="string">'m'</span>)
  307. <span class="comment">%drawnow</span>
  308. <span class="keyword">if</span> Hit == 2 &amp;&amp; Par.Reward &amp;&amp; LPStat(6) &lt; Times.Sacc <span class="comment">%correct target, give juice</span>
  309. dasbit( Par.CorrectB, 1);
  310. dasbit( Par.RewardB, 1);
  311. dasjuice( 5 );
  312. Par.Corrcount = Par.Corrcount + 1; <span class="comment">%log correct trials</span>
  313. <span class="comment">% beep</span>
  314. pause(Par.RewardTime) <span class="comment">%RewardTime is in seconds</span>
  315. dasbit( Par.RewardB, 0);
  316. dasjuice( 0 );
  317. <span class="keyword">elseif</span> Hit == 1
  318. dasbit( Par.ErrorB, 1);
  319. Par.Errcount = Par.Errcount + 1;
  320. <span class="comment">%in wrong target window</span>
  321. <span class="keyword">end</span>
  322. <span class="comment">%keep following eye motion to plot complete saccade</span>
  323. <span class="keyword">for</span> i = 1:10 <span class="comment">%keep targoff for 50ms</span>
  324. pause(0.005) <span class="comment">%not time critical, add some time to follow eyes</span>
  325. <span class="comment">%calllib(Par.Dll, 'Check', 5);</span>
  326. DasCheck; <span class="comment">%keep following eye motion</span>
  327. <span class="keyword">end</span>
  328. <span class="comment">%Save_eyetrace( I )</span>
  329. <span class="keyword">end</span>
  330. <span class="keyword">if</span> Hit ~= 2 <span class="comment">%error response</span>
  331. <span class="comment">%add pause when subject makes error</span>
  332. <span class="keyword">for</span> i = 1:round(Times.Err/5) <span class="comment">%keep targoff for Times.Err(ms)</span>
  333. pause(0.005)
  334. <span class="comment">% calllib(Par.Dll, 'Check', 5);</span>
  335. DasCheck;
  336. <span class="keyword">end</span>
  337. <span class="keyword">end</span>
  338. [ Hit Lasttime] = DasCheck;
  339. <span class="comment">%///////////////////////INTERTRIAL AND CLEANUP</span>
  340. display([<span class="string">'hit '</span> num2str(Hit) <span class="string">' reactiontime: '</span> num2str(LPStat(5)) <span class="string">' saccadetime: '</span> num2str(LPStat(6))]);
  341. disp([<span class="string">'stimulus-target duration: '</span> num2str((FS - FO)*1000) <span class="string">' ms '</span>]); <span class="comment">%check timing of target onset</span>
  342. <span class="comment">%reset all bits to null</span>
  343. <span class="keyword">for</span> i = [0 1 2 3 4 5 6 7] <span class="comment">%Error, Stim, Saccade, Trial, Correct,</span>
  344. <span class="comment">%calllib(Par.Dll, 'DO_Bit', i, 0);</span>
  345. dasbit( i, 0); <span class="comment">%clear bits</span>
  346. <span class="keyword">end</span>
  347. <span class="comment">%calllib(Par.Dll, 'Clear_Word');</span>
  348. dasclearword();
  349. SCNT = {<span class="string">'TRIALS'</span>};
  350. SCNT(2) = { [<span class="string">'N: '</span> num2str(Par.Trlcount) ]};
  351. SCNT(3) = { [<span class="string">'C: '</span> num2str(Par.Corrcount) ] };
  352. SCNT(4) = { [<span class="string">'E: '</span> num2str(Par.Errcount) ] };
  353. set(Hnd(1), <span class="string">'String'</span>, SCNT ) <span class="comment">%display updated numbers in GUI</span>
  354. SD = dasgetnoise();
  355. SD = SD./Par.PixPerDeg;
  356. set(Hnd(2), <span class="string">'String'</span>, SD )
  357. cgpencol(BG(1), BG(2), BG(3)) <span class="comment">%clear background before flipping</span>
  358. cgrect
  359. cgflip(BG(1), BG(2), BG(3))
  360. <span class="comment">%pause( Times.InterTrial/1000 ) %pause is called with seconds</span>
  361. <span class="comment">%Times.InterTrial is in ms</span>
  362. Time = Lasttime;
  363. <span class="keyword">while</span> Time &lt; Times.InterTrial + Lasttime
  364. pause(0.005)
  365. <span class="comment">%calllib(Par.Dll, 'Check', 5);</span>
  366. [Hit Time] = DasCheck;
  367. <span class="keyword">end</span>
  368. <span class="keyword">end</span> <span class="comment">%WHILE_NOT_ESCAPED%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</span>
  369. </pre><pre class="codeoutput">Attempt to reference field of non-structure array.
  370. Error in ==&gt; runstim at 13
  371. Times = Par.Times; %copy timing structure
  372. </pre><p class="footer"><br>
  373. Published with MATLAB&reg; 7.11<br></p></div><!--
  374. ##### SOURCE BEGIN #####
  375. function runstim(Hnd)
  376. %Updated 19_10_2011 Chris van der Togt
  377. global Par %global parameters
  378. global LPStat %das status values
  379. global StimObj %stimulus objects
  380. if ~isfield(StimObj, 'Stm')
  381. disp('ERROR: No stimulus');
  382. return
  383. end
  384. Times = Par.Times; %copy timing structure
  385. BG = Par.BG; %background Color
  386. cgflip(BG(1), BG(2), BG(3))
  387. Stms = StimObj.Stm; %all stimuli
  388. Objs = StimObj.Obj; %all graphical objects
  389. IDs = [ Objs(:).Id ]; %Ids of all graphical objects
  390. %they should all be not loaded, but just to make sure
  391. for i = 1:length(IDs)
  392. if strcmp(Objs(i).Type, 'Texture') || strcmp(Objs(i).Type, 'Bitmap') || strcmp(Objs(i).Type, 'Bezier')
  393. Objs(i).Data.isLoaded = false;
  394. end
  395. end
  396. %....EVENTS.........................
  397. FIX = 1;
  398. STM = 2;
  399. TARG = 3;
  400. TARGOF = 4;
  401. %MICR = 5;
  402. FS = 0;
  403. FO = 0;
  404. %////YOUR STIMULATION CONTROL LOOP /////////////////////////////////
  405. Hit = 2;
  406. Par.ESC = false; %escape has not been pressed
  407. while ~Par.ESC
  408. %Pretrial
  409. %SETUP YOUR STIMULI FOR THIS TRIAL
  410. if Par.Drum && Hit ~= 2 %if drumming and this was an error trial
  411. %just redo with current sttings
  412. else
  413. %randomization
  414. I = ceil(rand*length(Stms));
  415. %or use custom randomisation procedure
  416. %condition and associated stimuli
  417. EVENT = Stms(I).Event;
  418. %calllib(Par.Dll, 'DO_Word', I); %send word bit and condition
  419. dasword( I); %send word bit and condition
  420. %timing
  421. PREFIXT = Times.ToFix; %time to enter fixation window
  422. FIXT = fix(Times.Fix + rand*Times.RndFix); %time to fix before stim onset
  423. STIMT = fix(Par.Times.Stim + rand*Times.RndStim); %time that stimulus is displayed
  424. TARGT = fix(Times.Targ + round(2*rand-1)*Times.RndTarg); %time to fix before target onset
  425. RACT = Times.Rt; %reaction time
  426. FLtime = Par.fliptime; %adjusting for fliptime
  427. STIMT = (round(STIMT/FLtime) - 0) * FLtime;
  428. TARGT = (round(TARGT/FLtime) - 0) * FLtime;
  429. %control window setup
  430. FI = find(IDs == Stms(I).Fix, 1);
  431. TI = find(IDs == Stms(I).Targ, 1);
  432. WIN = [ Objs(FI).Data.cx, Objs(FI).Data.cy, Par.PixPerDeg*Par.FixWdDeg, Par.PixPerDeg*Par.FixHtDeg, 0; ... %Fix
  433. Objs(TI).Data.cx, Objs(TI).Data.cy, Par.PixPerDeg*Par.TargWdDeg, Par.PixPerDeg*Par.TargHtDeg, 2 ]; %Targ
  434. Par.OFFx = Objs(FI).Data.cx;
  435. Par.OFFy = Objs(FI).Data.cy;
  436. Alt = Stms(I).Talt{:};
  437. for k = 1:length(Alt)
  438. AI = find(IDs == Alt(k), 1);
  439. WIN = [ WIN; ...
  440. Objs(AI).Data.cx, Objs(AI).Data.cy, Par.PixPerDeg*Par.TargWdDeg, Par.PixPerDeg*Par.TargHtDeg, 1 ]; %TAlt
  441. end
  442. Par.WIN = WIN';
  443. %preload tectures and bitmaps
  444. Ids = unique([EVENT{:}]); %get all object ids in stimulus
  445. Notused = setxor(IDs, Ids);
  446. %free memory of obsolete sprites
  447. for id = Notused %indices into notused objects
  448. idx = find(IDs == id); %obtain index to the object corresponding with this id
  449. if strcmp(Objs(idx).Type, 'Texture') || strcmp(Objs(idx).Type, 'Bitmap') || strcmp(Objs(idx).Type, 'Bezier')
  450. if Objs(idx).Data.isLoaded
  451. cgfreesprite(id) %unload this sprite to make memory free
  452. Objs(idx).Data.isLoaded = false;
  453. end
  454. end
  455. end
  456. %load new sprites
  457. for id = Ids
  458. idx = find(IDs == id);
  459. if strcmp(Objs(idx).Type, 'Texture')
  460. OBJ = Objs(idx).Data;
  461. if ~(OBJ.isLoaded) %is not loaded
  462. Objs(idx).Data = cgTexture(OBJ, 'L', id); %(L)oad the texture
  463. end
  464. elseif strcmp(Objs(idx).Type, 'Bitmap')
  465. OBJ = Objs(idx).Data;
  466. if ~(OBJ.isLoaded) %is not loaded
  467. Objs(idx).Data = cgBitmap(OBJ, 'L', id); %Load the bitmap
  468. end
  469. elseif strcmp(Objs(idx).Type, 'Bezier')
  470. OBJ = Objs(idx).Data;
  471. if ~(OBJ.isLoaded) %is not loaded
  472. Objs(idx).Data = cgBezier(OBJ, 'S', id); %draw the bezier on a sprite
  473. end
  474. end
  475. end
  476. end
  477. %/////////////////////////////////////////////////////////////////////
  478. %START THE TRIAL
  479. %set control window positions and dimensions
  480. refreshtracker(1) %for your control display
  481. SetWindowDas %for the dascard, initializes eye control windows
  482. Abort = false; %whether subject has aborted before end of trial
  483. %///////// EVENT 0 START FIXATING //////////////////////////////////////
  484. %cgellipse(Px,Py,20,20,[1 0 0 ],'f') %the red fixation dot on the screen
  485. cgplotstim(EVENT{FIX}, Objs);
  486. cgflip(BG(1), BG(2), BG(3))
  487. dasreset( 0 ) %test enter fix window
  488. % 0 enter fix window
  489. % 1 leave fix window
  490. % 2 enter target window
  491. %LPStat(1) = time (ms) passed since last reset
  492. %LPStat(2) = control window hit (1 : in or out, 2 : in correct
  493. % target window
  494. %LPStat.(3) = hit position x
  495. %LPStat(4) = hit postion y
  496. %LPStat(5) = reaction time
  497. %LPStat(6) = time saccade length
  498. %subject has to start fixating central dot
  499. Par.SetZero = false; %set key to false to remove previous presses
  500. %Par.Updatxy = 1; %centering key is enabled
  501. Time = 1;
  502. Hit = 0;
  503. while Time < PREFIXT && Hit == 0
  504. pause(0.05)
  505. [Hit Time] = DasCheck; %retrieve position values and plot on Control display
  506. end
  507. %///////// EVENT 1 KEEP FIXATING or REDO ////////////////////////////////////
  508. if Hit ~= 0 %subjects eyes are in fixation window keep fixating for FIX time
  509. %the tril bit has now automatically been set high!! If the monkey
  510. %loses fixation he gets another chance but the tril bit just stays
  511. %high and this results in a longer prestim period
  512. dasreset( 1 ); %set test parameters for exiting fix window
  513. Time = 1;
  514. Hit = 0;
  515. while Time < FIXT && Hit== 0
  516. %Check for 10 ms
  517. pause(0.005)
  518. %detect eye enter/exit of control windows
  519. %this will also automaitcally
  520. %occur during pauzes due to a
  521. %callback routine run every single ms
  522. [Hit Time] = DasCheck; %retrieve eyechannel buffer and events, plot eye motion,
  523. end
  524. if Hit ~= 0 %eye has left fixation to early
  525. %possibly due to eye overshoot, give subject another chance
  526. dasreset( 0 );
  527. Time = 1;
  528. Hit = 0;
  529. while Time < PREFIXT && Hit == 0
  530. pause(0.005)
  531. [Hit Time] = DasCheck; %retrieve position values and plot on Control display
  532. end
  533. if Hit ~= 0 %subjects eyes are in fixation window keep fixating for FIX time
  534. dasreset( 1 ); %test for exiting fix window
  535. Time = 1;
  536. Hit = 0;
  537. while Time < FIXT && Hit == 0
  538. %Check for 10 ms
  539. pause(0.005)
  540. [Hit Time] = DasCheck;
  541. end
  542. else
  543. Hit = -1; %the subject did not fixate
  544. end
  545. end
  546. else
  547. Hit = -1; %the subject did not fixate
  548. end
  549. %///////// EVENT 2 DISPLAY STIMULUS //////////////////////////////////////
  550. if Hit == 0 %subject kept fixation, display stimulus
  551. Par.Trlcount = Par.Trlcount + 1; %counts total number of trials for this session
  552. %change your display between these lines.......................
  553. % cgpencol(1,1,1)
  554. % cgrect(-462, 334, 100, 100) %test stimulus for light diode
  555. % cgellipse(Px,Py,20,20,[1 0 0 ],'f') %fixation dot
  556. % cgellipse(Par.WIN(1,2), Par.WIN(2,2), 20, 20, [1 0 0 ], 'f') %target
  557. cgplotstim(EVENT{STM}, Objs);
  558. %..............................................................
  559. FO = cgflip(BG(1), BG(2), BG(3));
  560. FS = FO;
  561. %cgflip('v'); %this is not nice; cgflip does not give good timing
  562. tic %measure onset too
  563. dasbit( Par.StimB, 1); %send stimulus bit to TDT
  564. dasreset( 1 ); %test for exiting fix window
  565. refreshtracker(2) %set target window to green
  566. Time = 0;
  567. %prepare display for next flip TARGON.................
  568. if ~isempty(EVENT{TARG})
  569. cgplotstim(EVENT{TARG}, Objs);
  570. EPoch = min( STIMT-10, TARGT-50); %determine smallest time
  571. while Time < EPoch && Hit == 0
  572. dasrun( 5 );
  573. %get hit time
  574. [Hit Time] = DasCheck;
  575. end
  576. FS = cgflip(BG(1), BG(2), BG(3));
  577. end
  578. if ~isempty(EVENT{TARGOF})
  579. cgplotstim(EVENT{TARGOF}, Objs);
  580. %prepare display for next flip.................
  581. end
  582. while Time < TARGT-50 && Hit == 0 %Keep fixating till just before (50ms) target onset
  583. dasrun( 5 );
  584. %get hit time and plot eyemotion
  585. [Hit Time] = DasCheck; %plot eye motion in tracker
  586. end
  587. %how much time(ms) do we have left till target onset??? +
  588. %FlOP* FLtime
  589. delay = floor(TARGT - toc*1000 - FLtime/2); %hold up calling the next flip
  590. if delay > 0
  591. %calllib(Par.Dll, 'Check', delay)
  592. dasrun(delay)
  593. Hit = LPStat(2); %don't wast time!!!! on updating the screen
  594. else
  595. disp('WARNING....not enough time between stimoffset and target onset.')
  596. end
  597. %///////// EVENT 3 TARGET ONSET, REACTION TIME%%//////////////////////////////////////
  598. if Hit == 0 %subject kept fixation, subject may make an eye movement
  599. FS = cgflip(BG(1), BG(2), BG(3));
  600. % cgflip('v'); %this is not nice; cgflip doesnot give good timing
  601. dasbit( Par.TargetB, 1); %send target bit to TDT
  602. dasreset(2); %reset counter and check for entering target window
  603. %toc %display this to check your internal timing
  604. refreshtracker(3) %set fix point to green
  605. Time = 0;
  606. while Time < RACT && Hit <= 0 %RACT = time to respond (reaction time)
  607. %Check for 5 ms
  608. dasrun( 5)
  609. [Hit Time] = DasCheck;
  610. end
  611. else
  612. Abort = true;
  613. end
  614. %END EVENT 3
  615. else
  616. Abort = true;
  617. end
  618. %END EVENT 2
  619. cgflip(BG(1), BG(2), BG(3));
  620. %///////// POSTTRIAL AND REWARD //////////////////////////////////////
  621. if Hit ~= 0 && ~Abort %has entered a target window (false or correct)
  622. if Par.Mouserun
  623. HP = line('XData', Par.ZOOM * (LPStat(3) + Par.MOff(1)), 'YData', Par.ZOOM * (LPStat(4) + Par.MOff(2)), 'EraseMode','none');
  624. else
  625. HP = line('XData', Par.ZOOM * LPStat(3), 'YData', Par.ZOOM * LPStat(4), 'EraseMode','none');
  626. end
  627. set(HP, 'Marker', '+', 'MarkerSize', 20, 'MarkerEdgeColor', 'm')
  628. %drawnow
  629. if Hit == 2 && Par.Reward && LPStat(6) < Times.Sacc %correct target, give juice
  630. dasbit( Par.CorrectB, 1);
  631. dasbit( Par.RewardB, 1);
  632. dasjuice( 5 );
  633. Par.Corrcount = Par.Corrcount + 1; %log correct trials
  634. % beep
  635. pause(Par.RewardTime) %RewardTime is in seconds
  636. dasbit( Par.RewardB, 0);
  637. dasjuice( 0 );
  638. elseif Hit == 1
  639. dasbit( Par.ErrorB, 1);
  640. Par.Errcount = Par.Errcount + 1;
  641. %in wrong target window
  642. end
  643. %keep following eye motion to plot complete saccade
  644. for i = 1:10 %keep targoff for 50ms
  645. pause(0.005) %not time critical, add some time to follow eyes
  646. %calllib(Par.Dll, 'Check', 5);
  647. DasCheck; %keep following eye motion
  648. end
  649. %Save_eyetrace( I )
  650. end
  651. if Hit ~= 2 %error response
  652. %add pause when subject makes error
  653. for i = 1:round(Times.Err/5) %keep targoff for Times.Err(ms)
  654. pause(0.005)
  655. % calllib(Par.Dll, 'Check', 5);
  656. DasCheck;
  657. end
  658. end
  659. [ Hit Lasttime] = DasCheck;
  660. %///////////////////////INTERTRIAL AND CLEANUP
  661. display(['hit ' num2str(Hit) ' reactiontime: ' num2str(LPStat(5)) ' saccadetime: ' num2str(LPStat(6))]);
  662. disp(['stimulus-target duration: ' num2str((FS - FO)*1000) ' ms ']); %check timing of target onset
  663. %reset all bits to null
  664. for i = [0 1 2 3 4 5 6 7] %Error, Stim, Saccade, Trial, Correct,
  665. %calllib(Par.Dll, 'DO_Bit', i, 0);
  666. dasbit( i, 0); %clear bits
  667. end
  668. %calllib(Par.Dll, 'Clear_Word');
  669. dasclearword();
  670. SCNT = {'TRIALS'};
  671. SCNT(2) = { ['N: ' num2str(Par.Trlcount) ]};
  672. SCNT(3) = { ['C: ' num2str(Par.Corrcount) ] };
  673. SCNT(4) = { ['E: ' num2str(Par.Errcount) ] };
  674. set(Hnd(1), 'String', SCNT ) %display updated numbers in GUI
  675. SD = dasgetnoise();
  676. SD = SD./Par.PixPerDeg;
  677. set(Hnd(2), 'String', SD )
  678. cgpencol(BG(1), BG(2), BG(3)) %clear background before flipping
  679. cgrect
  680. cgflip(BG(1), BG(2), BG(3))
  681. %pause( Times.InterTrial/1000 ) %pause is called with seconds
  682. %Times.InterTrial is in ms
  683. Time = Lasttime;
  684. while Time < Times.InterTrial + Lasttime
  685. pause(0.005)
  686. %calllib(Par.Dll, 'Check', 5);
  687. [Hit Time] = DasCheck;
  688. end
  689. end %WHILE_NOT_ESCAPED%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  690. ##### SOURCE END #####
  691. --></body></html>