OSCR

Disentangling Respiratory Phase-Dependent and Phase-Independent Components of Anticipatory Cardiac Deceleration.

Code ↔ Paper

16 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 16 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
  1. [1] § Methods › Behavioral Task Paradigm › Eye‐Tracking Calibration and Controlling for the Fixation Breaks ↔ VTD/VTD_experiment/trials_VTDnew_egeVersion.m, lines 440–488 · score 0.91 · blink allowance, 0.5–0.7 s, intertrial interval, visual angle, April Tags, radius
  2. [2] § Methods › Behavioral Task Paradigm › Training and Threshold Assessment ↔ VTD/VTD_experiment/trials_VTDnew_egeVersion.m, lines 275–344 · score 0.83 · tGuess, QUEST algorithm, hit rate, stimulus absent, calibration, grating
  3. [3] § Methods › Statistical Methods and Analyses › RSA Estimations ↔ VTD/VTD_analysis/VTD_baseline_breathingPhaseLocking.m, lines 193–234 · score 0.80 · 0.12–0.4 Hz, bandpass filtered, Porges Bohrer, overlap, 0.12 Hz, segmented
  4. [4] § Results › Differential Contributions of Respiratory Phase‐Dependent and Phase‐Independent Heart Rate Modulations to Visual Stimulus Detection ↔ VTD/VTD_analysis/VTD_van_acd_timeCourseCorrelations.m, lines 105–148 · score 0.70 · 188–318 ms, correlation coefficient, 188 ms, VAN, linear, window
  5. [5] § Methods › Statistical Methods and Analyses › Linear Correlations ↔ VTD/VTD_analysis/VTD_ACD_inhalationVsExhalation.m, lines 1210–1257 · score 0.68 · robust linear regression, correlation coefficients, Huber, fitlm, intercept, fitting
  6. [6] § Methods › Data Preprocessing › EEG Data Pre‐Processing ↔ VTD/VTD_preProcessing/VTD_EEG_PreProcessMAIN.m, lines 573–652 · score 0.68 · surrogate VEP, corrected VEP, subtracted, epoched, pre, EEG
  7. [7] § Results › Differential Contributions of Respiratory Phase‐Dependent and Phase‐Independent Heart Rate Modulations to Visual Stimulus Detection ↔ VTD/VTD_analysis/VTD_van_acd_timeCourseCorrelations.m, lines 105–148 · score 0.67 · 188–318 ms, correlation coefficient, 188 ms, Spearman, VAN, linear
  8. [8] § Methods › Behavioral Task Paradigm › Stimulus Properties ↔ VTD/VTD_experiment/params_VTD_egeVersion.m, lines 191–196 · score 0.64 · outer radius, visual angle, inner, annulus, grating
  9. [9] § Methods › Statistical Methods and Analyses › RSA Estimations ↔ VTD/VTD_rsaSinusoidalModel/RSA_sinusoidalFit.m, the whole file · a weak match · score 0.61 · initial guesses, loss function, fminsearch, IBI, RSA, phase
  10. [10] § Results › The Role of RSA and Respiratory Phase Alignment in Anticipatory Cardiac Deceleration (ACD) ↔ VTD/VTD_analysis/VTD_ACD_inhalationVsExhalation.m, lines 1259–1302 · score 0.61 · Porges Bohrer, linear regression, correlation coefficient, RSA amplitude, horizontal, Sinusoidal
  11. [11] § Methods › Data Preprocessing › EEG Data Pre‐Processing ↔ VTD/VTD_preProcessing/VTD_EEG_PreProcessMAIN.m, lines 654–741 · score 0.60 · target stimulus onset, pre processed, EEGLAB, downsampled, epoched
  12. [12] § Methods › Data Preprocessing › EEG Data Pre‐Processing ↔ VTD/VTD_preProcessing/VTD_EEG_PreProcessMAIN.m, lines 430–442 · score 0.58 · ICA components, EEGLAB, SD, epochs, Pre
  13. [13] § Methods › Behavioral Task Paradigm › Eye‐Tracking Calibration and Controlling for the Fixation Breaks ↔ VTD/VTD_experiment/trials_VTDnew_egeVersion.m, lines 567–679 · score 0.56 · gaze position, Pupil Labs, Breaks, fixation
  14. [14] § Methods › Experimental Recordings › Pupillometry ↔ VTD/VTD_experiment/trials_VTDnew_egeVersion.m, lines 41–69 · score 0.54 · eye positions, Eye tracking, Pupil
  15. [15] § Methods › Behavioral Task Paradigm ↔ VTD/VTD_experiment/trials_VTDnew_egeVersion.m, lines 1349–1441 · score 0.54 · gaze locations, April Tags, axis, surface, block, EEG
  16. [16] § Methods › Data Preprocessing › ECG Data Pre‐Processing ↔ VTD/VTD_preProcessing/VTD_baselineECG_BR_preProcess.m, lines 36–47 · score 0.52 · QRS complex, bandpass, ECG, 45 Hz, Pre, 0.5 Hz

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 1,596 lines · 75 KB · no license · 5 matches

  1. function [output, keyboard_events, params, ET, gazes] = trials_VTDnew_egeVersion(params)
  2. % Trials function for MAIN_VTD.m
  3. % Sukanya C, Ege Kingir (MSc Thesis, IMPRS)
  4. % 12 Nov 2023
  5. % Trials function for the visual detection task after threshold calibration
  6. %%% This function contains the trial loop. The loop is a state-based one:
  7. %%% If the subject fixates to the center successfully (state=1), we move on
  8. %%% to the warning cue state (state=2). Afterwards, the stimulus is
  9. %%% presented. Then some delay and "detection (yes/no)" and "confidence"
  10. %%% reports by the subject.
  11. %%% If the subject breaks fixation to the center during the pre-stimulus
  12. %%% window, the trial restarts.
  13. %%% 60 trials per block: 87% stimulus-present, 13% catch.
  14. %%% 6-8 blocks in a session.
  15. %% CHANGE LOG
  16. % Following changes made by XX on XX.XX.XXX
  17. % 30.11.2023 -- EK updates:
  18. % 1) Added the continuous confidence scale bar.
  19. % 2) Under state==1, flag2 should be defined as zero before you enter the...
  20. % %...loop. Otherwise the variable is not recognized (I added the...
  21. % %...definition).
  22. % 13.12.2023 updates:
  23. % Removed the online plots for gaze and accuracy as they are slowing the
  24. % code down
  25. %% FUNCTIONS CALLED IN THIS SCRIPT / RELEVANT FILES
  26. % params_VTD.m
  27. % startupEyetracking.m
  28. % SendSignal.m
  29. % display_cycle_clock.m
  30. %% Set up eye tracking
  31. if params.eyetracking == 1
  32. if params.whicheyetracker == 1
  33. params.samplingrate = 1000;
  34. params.maxeyesamples = params.numtrials*params.totaltrialdur*params.samplingrate;
  35. params.eyedatafile = sprintf('M%s_%d.edf', params.subject, params.runnumber); % has to be less than 8 characters
  36. % Initialize Eyelink
  37. el = startupEyetracking(params.window, params.eyedatafile);
  38. % start recording eye position
  39. Eyelink('StartRecording');
  40. % record a few samples before we actually start displaying
  41. WaitSecs(0.1);
  42. % mark zero-plot time in data file
  43. Eyelink('Message', 'SYNCTIME');
  44. % Initialize eye data structure
  45. eyetrack.trial(1:params.maxeyesamples,1) = NaN;
  46. eyetrack.state(1:params.maxeyesamples,1) = NaN;
  47. eyetrack.eyetime(1:params.maxeyesamples,1) = NaN;
  48. eyetrack.ptbtime(1:params.maxeyesamples,1) = NaN;
  49. eyetrack.xpos(1:params.maxeyesamples,2) = NaN;
  50. eyetrack.ypos(1:params.maxeyesamples,2) = NaN;
  51. eyetrack.pupil(1:params.maxeyesamples,2) = NaN;
  52. elseif params.whicheyetracker == 2
  53. %%% Initialize Pupil Labs Remote Control
  54. % Pupil Remote address -- you can check this from PupilCapture
  55. endpoint = 'tcp://169.254.53.40:50020';
  56. % Setup zmq context and remote helper
  57. ctx = zmq.core.ctx_new();
  58. socket = zmq.core.socket(ctx, 'ZMQ_REQ');
  59. % set timeout to 1000ms in order to not get stuck in a blocking
  60. % mex-call if server is not reachable, see
  61. % http://api.zeromq.org/4-0:zmq-setsockopt#toc19
  62. zmq.core.setsockopt(socket, 'ZMQ_RCVTIMEO', 1000);
  63. fprintf('Connecting to %s\n', endpoint);
  64. zmq.core.connect(socket, endpoint);
  65. % Request sub port
  66. zmq.core.send(socket, uint8('SUB_PORT'));
  67. sub_port = char(zmq.core.recv(socket));
  68. fprintf('Received sub port: %s\n', sub_port);
  69. if isequal(sub_port, false)
  70. warning('No valid sub port received');
  71. return; % exit script
  72. end
  73. % Create and connect sub socket
  74. ip_address = '169.254.53.40';
  75. sub_endpoint = sprintf('tcp://%s:%s', ip_address, sub_port);
  76. sub_socket = zmq.core.socket(ctx, 'ZMQ_SUB');
  77. %Connect to sub port
  78. zmq.core.connect(sub_socket, sub_endpoint);
  79. zmq.core.setsockopt(sub_socket, 'ZMQ_RCVTIMEO', 1000);
  80. fprintf('Connecting to SUB: %s\n', sub_endpoint);
  81. tic; % Measure round trip delay
  82. zmq.core.send(socket, uint8('t'));
  83. result = zmq.core.recv(socket);
  84. fprintf('%s\n', char(result));
  85. fprintf('Round trip command delay: %s\n', toc);
  86. % set current Pupil time to 0.0
  87. zmq.core.send(socket, uint8('T 0.0'));
  88. result = zmq.core.recv(socket);
  89. fprintf('%s\n', char(result));
  90. % start recording
  91. pause(1.0);
  92. zmq.core.send(socket, uint8('R')); %%%%
  93. result = zmq.core.recv(socket); %%%%
  94. fprintf('Recording should start: %s\n', char(result));
  95. % zmq.core.send(socket, uint8('t'));
  96. % currentTime = zmq.core.recv(socket);
  97. end;
  98. end;
  99. %% Pupil Labs calibration
  100. if params.eyetracking == 1
  101. if params.whicheyetracker == 2
  102. %open a grey window
  103. [params.window, params.windowRect] = PsychImaging('OpenWindow', params.screenNumber, params.grey);
  104. % Size of the on screen window in pixels
  105. % [params.screenXpixelscalib, params.screenYpixelscalib] = Screen('WindowSize', params.window);
  106. Screen('BlendFunction', params.window, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA');
  107. %get the center coordinates (in pixels, bottom-left of the screen
  108. %is [0 0].
  109. [params.screenXcentre_pix, params.screenYcentre_pix] = RectCenter(params.windowRect);
  110. params.centercoords = [params.screenXcentre_pix params.screenYcentre_pix];
  111. %% get the pupil labs calibration marker
  112. % % marker = imread('calibMarker.jpg');
  113. % % markerTexture = Screen('MakeTexture', params.window, marker);
  114. % %
  115. % % Screen('DrawTexture', params.window, markerTexture, [], [], 0);
  116. baseRect1 = [0 0 165 165];
  117. baseRect2 = [0 0 160 160];
  118. baseRect3 = [0 0 100 100];
  119. baseRect4 = [0 0 60 60];
  120. baseRect5 = [0 0 30 30];
  121. x=[0 -params.screenX_pix/2+baseRect1(3) params.screenX_pix/2-baseRect1(3) -params.screenX_pix/2+baseRect1(3) params.screenX_pix/2-baseRect1(3)];
  122. y=[0 -params.screenY_pix/2+baseRect1(3) -params.screenY_pix/2+baseRect1(3) params.screenY_pix/2-baseRect1(3) params.screenY_pix/2-baseRect1(3)];
  123. valid = 1;
  124. for valid=1:4
  125. for stim=1:5
  126. centeredRect1 = CenterRectOnPointd(baseRect1, params.screenXcentre_pix+x(stim), params.screenYcentre_pix+y(stim));
  127. centeredRect2 = CenterRectOnPointd(baseRect2, params.screenXcentre_pix+x(stim), params.screenYcentre_pix+y(stim));
  128. centeredRect3 = CenterRectOnPointd(baseRect3, params.screenXcentre_pix+x(stim), params.screenYcentre_pix+y(stim));
  129. centeredRect4 = CenterRectOnPointd(baseRect4, params.screenXcentre_pix+x(stim), params.screenYcentre_pix+y(stim));
  130. centeredRect5 = CenterRectOnPointd(baseRect5, params.screenXcentre_pix+x(stim), params.screenYcentre_pix+y(stim));
  131. xCoords = [-2 2 0 0];
  132. yCoords = [0 0 -2 2];
  133. allCoords = [xCoords; yCoords];
  134. lineWidthPix = 2;
  135. %nested doughnut shaped ovals to make calibration spots...
  136. %recognizable by PupilCapture.
  137. Screen('FillOval', params.window, [0.5 0.5 0.5],centeredRect1, max(baseRect1)*1.01);
  138. Screen('FillOval', params.window, [1 1 1],centeredRect2, max(baseRect2)*1.01);
  139. Screen('FillOval', params.window, [0 0 0],centeredRect3, max(baseRect3)*1.01);
  140. Screen('FillOval', params.window, [1 1 1],centeredRect4, max(baseRect4)*1.01);
  141. Screen('FillOval', params.window, [0 0 0],centeredRect5, max(baseRect5)*1.01);
  142. %fixation cross
  143. Screen('DrawLines', params.window, allCoords, lineWidthPix, [1 1 1], [params.screenXcentre_pix+x(stim) params.screenYcentre_pix+y(stim)],2);
  144. % Screen('DrawLines', params.window,
  145. Screen('Flip', params.window);
  146. KbStrokeWait;
  147. end
  148. Screen('Flip', params.window);
  149. % calibstart = input('Do you want to restart the calibration (in case accuracy is low) (1 = Yes, 0 = No) ');
  150. % if calibstart == 1
  151. % valid = 1;
  152. % elseif calibstart == 0
  153. % valid = 0;
  154. % %
  155. % end
  156. end
  157. WaitSecs(5);
  158. Screen('Flip',params.window);
  159. end
  160. end
  161. %% Initialisation of parameters for checking fixation
  162. ET.TrialAborted = false;
  163. ET.FixationEstablished = false;
  164. ET.FixationPending = false;
  165. ET.FixationPendingStartTime = NaN;
  166. ET.AbortPending = false;
  167. ET.AbortPendingStartTime = NaN;
  168. ET.AbortStartTime = NaN;
  169. ET.IsFixation = false;
  170. %% Cycling warm up if necessary
  171. if strcmp(params.runtype, 'TC') || strcmp(params.runtype, 'L') || strcmp(params.runtype, 'H')
  172. display_cycle_clock_VTD(params);
  173. end
  174. %% Output struct
  175. output = struct('condition', [], 'trialonset', []);
  176. %% Initialising
  177. triggertime = NaN;
  178. triggerout = 0;
  179. cursample = 0;
  180. %% Keyboard set up
  181. % Enable unified mode of KbName, so KbName accepts identical key names on
  182. % all operating systems:
  183. KbName('UnifyKeyNames');
  184. % Prevent spilling of keystrokes into console:
  185. ListenChar(-1); % suppress keyboard input
  186. % Define key list
  187. keylist = zeros(1,256); % create mask for keys
  188. % set keylist / mask to 1 for all the keys you want to monitor
  189. % keylist(KbName('1!')) = 1;
  190. keylist(KbName('3#')) = 1;
  191. keylist(KbName('2@')) = 1;
  192. keylist(KbName('1!')) = 1;
  193. % keylist(KbName('5%')) = 1;
  194. % create and start a restricted KbQueue
  195. KbQueueCreate(-1, keylist); %'-1' uses default keyboard, this is a restricted KbQueue, used for detecting button presses
  196. KbQueueStart;
  197. % Initialize keyboard_events as an empty structure array
  198. keyboard_events = struct([]);
  199. trial = 0;
  200. flag = 0;
  201. % Define your response keys
  202. responseKeys = {'3#', '2@', '1!'};
  203. %% Set up fixed and variable delays
  204. fixation_Duration = 2.7; %% In Park et al., fixation duration is specified as 0.5 to 0.7 seconds,
  205. % and if stable gaze fixation
  206. % is achieved for the said duration, a trial is initiated. However, since
  207. % it is yet not well sorted how to feed in Pupil Capture data into MATLAB,
  208. % we choose to define a range of 0.7s (max gaze fixation defined in Park et
  209. % al., 2014) + 0.5 seconds i.e., 1.2 seconds.
  210. warning_before_stimRange = [1.5, 1.7]; % this is the variable delay for which the fixation remains red before the stimulus appears
  211. % stimulusDuration = 0.05; % this is the fixed stimulus presentation duration in seconds, converted to frames
  212. stimulusFrames = round(0.05/params.flipinterval);
  213. stimulusDuration = 0.05;
  214. var_delay_after_stimRange = [0.3, 0.7]; % this is the variable delay range after stimulus presentation
  215. time_for_response = 3; % this is the time accounted to the participant to make a key press
  216. %% Initialise parameters for the QUEST algorithm
  217. tGuess = 0.04; % Estimated signal strength (contrast value) which is the threshold for detection
  218. tGuessSd = 2; % Standard Deviation allowed to the QUEST algorithm for the distribution centred on tGuess
  219. pThreshold = 0.65; % Probability of correct response - We want the hit rate to be at 65%
  220. beta = 3.5; % Slope of the Weibull function
  221. delta = 0.01;
  222. gamma = 0; % Guess rate or probabilty of an incorrect guess at values high above threshold
  223. grain = 0.0025; % Step shift in contrast - WE DO NOT CHANGE THE GRAIN
  224. range = 0.075; %Range of contrast values under practical testing conditions
  225. keyHit = '2@'; % Key for hit
  226. keyMiss = '3#'; % Key for miss
  227. % Initialize QUEST parameters
  228. q=QuestCreate(tGuess,tGuessSd,pThreshold,beta,delta,gamma, grain, range);
  229. p = QuestPdf(q,tGuess);
  230. % q.x = linspace(0,1,501);
  231. % q.x2 = linspace(0,2,1001);
  232. % Define the center of the screen as empty!
  233. center = [];
  234. % Define the iterations fo getting gaze on surface inputs
  235. iter=1;
  236. for block = 1:params.numblocks
  237. random_trl_order = params.trialorder;
  238. Screen('TextSize',params.window, 30)
  239. Screen('DrawText',params.window, 'FIXATION CALIBRATION!',(params.screenX_pix/2)-100, params.screenY_pix*0.5, params.black);
  240. Screen('Flip', params.window);
  241. WaitSecs(1);
  242. % Plotting parameters initialisation
  243. hitCount = 0;
  244. missCount = 0;
  245. faCount = 0;
  246. hitRates = zeros(1, length(random_trl_order)); % Initialize hit rates vector
  247. falseAlarmRates = zeros(1, length(random_trl_order)); % Initialize false alarm rates vector
  248. stimPresentCount = 0;
  249. stimAbsentCount = 0;
  250. contrasts = zeros(1, length(random_trl_order)); % Initialize contrasts vector
  251. x1 = [];
  252. y1 = [];
  253. x2 = [];
  254. y2 = [];
  255. x3 = [];
  256. y3 = [];
  257. % figure(1);
  258. % subplot(2, 1, 1);
  259. % % % % plot1 = plot(x1, y1, 'r-'); % Initialize plot 1 (red line)
  260. % xlabel('Trial');
  261. % ylabel('Hit and False Alarm Rates');
  262. % title('QUEST modulated accuracy');
  263. % subplot(2, 1, 2);
  264. % % % % plot3 = plot(x3, y3, 'k-'); % Initialize plot 1 (red line)
  265. % xlabel('Trial');
  266. % ylabel('Grating Contrast');
  267. % title('QUEST modulated contrast');
  268. %figure(10);
  269. % % % plot1 = plot(x1, y1, 'r-'); % Initialize plot 1 (red line)
  270. % xlabel('x gaze');
  271. % ylabel('y gaze');
  272. % title('Real Time gaze');
  273. %% Main Trials Loop
  274. %% Display April tags on PTB screen to detect surface via PupilLabs
  275. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  276. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  277. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  278. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  279. % fixation circle
  280. Screen('FillOval', params.window, params.black, params.centeredcircleRectOUT, params.maxDiameterOUT);
  281. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  282. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, params.white, [], 1);
  283. Screen('Flip', params.window);
  284. if params.eyetracking == 1
  285. if params.whicheyetracker == 2
  286. zmq.core.setsockopt(sub_socket, 'ZMQ_SUBSCRIBE', 'surface'); %now you can subscribe to surface because we drew it!
  287. end
  288. end
  289. WaitSecs(2);
  290. initialSurfaceDef = 3; %number of secs allowed to define the surface and at the same time get baseline gaze data
  291. startSurfDef = GetSecs();
  292. gazes = [];
  293. while 1
  294. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  295. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  296. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  297. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  298. % fixation circle
  299. Screen('FillOval', params.window, params.black, params.centeredcircleRectOUT, params.maxDiameterOUT);
  300. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  301. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, [0.8 0.8 0.8], [], 1);
  302. Screen('Flip', params.window);
  303. if params.eyetracking == 1
  304. if params.whicheyetracker == 2
  305. cursample = cursample + 1;
  306. % Get gaze positions from pupil labs
  307. % (filtermessages)
  308. [topic, note] = recv_message(sub_socket, 2500);
  309. if ~isequal(note, false) % test for valid message
  310. gaze_positions{1,iter}= [topic, note('gaze_on_surfaces')]; % print pupil norm_pos
  311. for j=2:size(gaze_positions{1,iter},2)
  312. gazecoordinates = gaze_positions{1,iter}{1,j}('norm_pos');
  313. x(j) = gazecoordinates{1,1};
  314. y(j) = gazecoordinates{1,2};
  315. end
  316. %This alternative is decreasing the temporal...
  317. %...resolution in case matlab fails.
  318. ET.CurrentGaze(1,1) = x(j);
  319. ET.CurrentGaze(1,2) = y(j);
  320. % plot(x(j),y(j),'p')
  321. % drawnow
  322. % hold on
  323. end
  324. gazes(end+1,1) = ET.CurrentGaze(1,1);
  325. gazes(end,2) = ET.CurrentGaze(1,2);
  326. ET.currentTime = GetSecs();
  327. ET.eyetime(cursample,1) = ET.currentTime;
  328. % ET = CheckFixation_VTD_egeVersion(ET, trial, params, output);
  329. iter=iter+1;
  330. end
  331. elseif params.eyetracking == 0
  332. cursample = cursample + 1;
  333. [ET.CurrentGaze(1,1) ET.CurrentGaze(1,2)] = GetMouse(params.window);
  334. ET.currentTime = GetSecs();
  335. ET.eyetime(cursample,1) = ET.currentTime;
  336. gazes(end+1,1) = ET.CurrentGaze(1,1);
  337. gazes(end,2) = ET.CurrentGaze(1,2);
  338. end
  339. if GetSecs()> startSurfDef + initialSurfaceDef
  340. break
  341. end
  342. end
  343. meanGazeOne = [mean(gazes(:,1)) mean(gazes(:,2))];
  344. meanGazeOne
  345. %% start the trial loop here
  346. while 1
  347. trial=trial+1;
  348. if random_trl_order(trial) == 1 % For stimulus present trials
  349. stimPresentCount = stimPresentCount + 1; % Increment stimulus present trial count
  350. % WaitSecs(fixation_Duration);
  351. elseif random_trl_order(trial) == 2 % For stimulus absent trials
  352. stimAbsentCount = stimAbsentCount + 1; % Increment stimulus absent count
  353. % WaitSecs(fixation_Duration);
  354. end
  355. % We only have a single trial type for now, as we are not considering
  356. % the inter-trial interval separately, but rather adding it in with the
  357. % fixation check to initiate trial
  358. if flag == 1
  359. Screen('DrawText', params.window, 'FIXATE PLEASE!', (params.screenX_pix/2)-100, (params.screenY_pix/2), params.black);
  360. %% Display April tags on PTB screen to detect surface via PupilLabs
  361. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  362. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  363. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  364. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  365. Screen('Flip', params.window);
  366. WaitSecs(2);
  367. end
  368. ET.TrialAborted = false;
  369. ET.FixationEstablished = false;
  370. ET.FixationPending = false;
  371. ET.FixationPendingStartTime = NaN;
  372. ET.AbortPending = false;
  373. ET.AbortPendingStartTime = NaN;
  374. ET.AbortStartTime = NaN;
  375. ET.IsFixation = false;
  376. flag = 0;
  377. earlyResponseFlag=0;
  378. flagResponse=1;
  379. output(trial).condition = random_trl_order(trial);
  380. delayBeforeStimulus = warning_before_stimRange(1) + rand() * (warning_before_stimRange(2) - warning_before_stimRange(1));
  381. delayAfterStimulus = var_delay_after_stimRange(1) + rand() * (var_delay_after_stimRange(2) - var_delay_after_stimRange(1));
  382. totaldur = fixation_Duration + delayBeforeStimulus + delayAfterStimulus + 6.05;
  383. totaldurtoresponse = fixation_Duration + delayBeforeStimulus + delayAfterStimulus + 0.05;
  384. params.fixRadiusdeg = 2; % Window in degrees of visual angles for checking for fixation
  385. params.fixRadius = params.fixRadiusdeg*params.pixperdeg; % Window in pixels for checking for fixation
  386. intertrial_Interval_Range = [1.5, 2]; % this is the variable delay range for intertrial interval in seconds - default in Park et al. ,
  387. % is 1.5 to 2, but since we allow another additional 1 sec to the subjects to start the fixation,
  388. % we have reduced this range accordingly
  389. intertrialInterval = intertrial_Interval_Range(1) + rand() * (intertrial_Interval_Range(2) - intertrial_Interval_Range(1));
  390. params.TimeToBeginFixation = intertrialInterval; % Time allowed after the ITI to start fixating
  391. establish_fixation_range = [0.5, 0.7];
  392. establishFixation = establish_fixation_range(1) + rand() * (establish_fixation_range(2) - establish_fixation_range(1));
  393. params.TimeToEstablishFixation = establishFixation; % Time allowed to establish fixation after the time to begin fixation
  394. params.BlinkAllowance = 0.2; % Time given to allow for blinks, usually around 200-300 ms.
  395. %reliance on previous fixation centers vs. the most recent fixation
  396. weightOld = 0.90;
  397. weightNew = 0.10;
  398. % target stimulus contrast in the current trial
  399. currentEstimate = QuestMean(q);
  400. output(trial).AllContrastEstimatesMean = currentEstimate;
  401. currentContrast = QuestQuantile(q);
  402. output(trial).AllContrastEstimatesQuantile = currentContrast;
  403. contrasts(trial) = currentContrast;
  404. %% STATE 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  405. fprintf('\nTrial %d of %d, Run %d, Trial Type - SP (1) or SA (2): %d \n\n\n\n\n\n', trial, params.numtrials, params.runnumber, random_trl_order(trial));
  406. % Hereon starts the first state - fixation on the central black circle
  407. state = 1;
  408. flag2 = 0;
  409. Screen('FillOval', params.window, params.black, params.centeredcircleRectOUT, params.maxDiameterOUT);
  410. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  411. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, params.black, [], 1);
  412. %% Display April tags on PTB screen to detect surface via PupilLabs
  413. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  414. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  415. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  416. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  417. vbl = Screen('Flip', params.window);
  418. output(trial).trialonset = vbl;
  419. % Send EEG trigger code for trial start
  420. if params.EEG == 1
  421. SendSignal(params.ioObj, params.address, random_trl_order(trial)); %1 for stimulus present, 2 for stimulus absent
  422. triggerout = 1;
  423. triggertime = GetSecs;
  424. else
  425. end
  426. if params.eyetracking == 1 % Send Annotation from Matlab to Pupil Labs
  427. if params.whicheyetracker == 2
  428. zmq.core.send(socket, uint8('t'));
  429. currentTime_bytes = zmq.core.recv(socket,20);
  430. % fprintf('first measure: %s\n', char(currentTime_bytes));
  431. currentTimeChar = char(currentTime_bytes);
  432. currentTimeNum = str2num(currentTimeChar);
  433. keys_start = {'topic', 'label', 'timestamp', 'duration'};
  434. values_start = {'annotation.TrialStart', strcat('Trial #', num2str(trial),' started'), currentTimeNum, 1.0};
  435. start_annotation = containers.Map(keys_start, values_start);
  436. send_annotation(socket, start_annotation);
  437. result = zmq.core.recv(socket);
  438. end
  439. end
  440. gazes = []; %to note down all of the recorded gaze locations within the surface, during a trial! It is redefined as empty when the trial restarts due to fixation.
  441. if params.checkfix == 1
  442. if trial == 1
  443. center(trial,:) = meanGazeOne
  444. % center
  445. elseif trial == 2
  446. oldGaze = meanGazeOne * weightOld;
  447. newGaze = output(1).meanGazes * weightNew;
  448. % vector = [meanGazeOne;output(1).meanGazes];
  449. center(trial,:) = oldGaze + newGaze
  450. % center
  451. else
  452. oldGaze = center(trial-1,:) * weightOld;
  453. newGaze = output(trial-1).meanGazes * weightNew;
  454. % vector = [center(trial-1,:);output(trial-1).meanGazes];
  455. center(trial,:) = oldGaze + newGaze
  456. % center
  457. end
  458. end
  459. while state == 1
  460. [pressed, firstPress] = KbQueueCheck;
  461. if pressed
  462. % Extract information about the key presses
  463. [key,ind] = max(firstPress);
  464. % Check if any of the response keys are pressed
  465. if ismember(ind, KbName(responseKeys(1:2)))
  466. % Identify the pressed key
  467. % idx = find(ismember(KbName(responseKeys), pressedKeys));
  468. % response = responseKeys{idx}; % Assign the pressed key as response
  469. Screen('TextSize',params.window, 30);
  470. Screen('DrawText',params.window, 'WAIT QUESTION MARK TO RESPOND!',(params.screenX_pix/2)-100, params.screenY_pix*0.5, params.black);
  471. % Screen('DrawText',params.window, 'Please wait till the question mark sign appears on screen to make your report.',(params.screenX_pix/2)-100, params.screenY_pix*0.55, params.black);
  472. %% Display April tags on PTB screen to detect surface via PupilLabs
  473. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  474. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  475. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  476. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  477. Screen('Flip', params.window);
  478. WaitSecs(2);
  479. flag2 = 1;
  480. end
  481. end
  482. if flag2 == 1
  483. fprintf('early response');
  484. earlyResponseFlag=1; %apart from trial abortion by fixation break; this is another way to abort the trial: because the subject pressed a response button earlier than they were supposed to!
  485. break
  486. end
  487. % If eyetracking
  488. %
  489. if params.eyetracking == 1
  490. if params.whicheyetracker == 2
  491. if params.checkfix == 1
  492. cursample = cursample + 1;
  493. % Get gaze positions from pupil labs
  494. % (filtermessages)
  495. [topic, note] = recv_message(sub_socket, 2500);
  496. if ~isequal(note, false) % test for valid message
  497. gaze_positions{1,iter}= [topic, note('gaze_on_surfaces')]; % print pupil norm_pos
  498. for j=2:size(gaze_positions{1,iter},2)
  499. gazecoordinates = gaze_positions{1,iter}{1,j}('norm_pos');
  500. x(j) = gazecoordinates{1,1};
  501. y(j) = gazecoordinates{1,2};
  502. end
  503. end
  504. ET.CurrentGaze(1,1) = x(j);
  505. ET.CurrentGaze(1,2) = y(j);
  506. if GetSecs() > output(trial).trialonset + params.TimeToBeginFixation % we do not consider the gazes during the ITI for calculating the center for the next trial
  507. gazes(end+1,1) = ET.CurrentGaze(1,1);
  508. gazes(end,2) = ET.CurrentGaze(1,2);
  509. end
  510. ET.currentTime = GetSecs();
  511. ET.eyetime(cursample,1) = ET.currentTime;
  512. if trial == 1
  513. %
  514. dx = abs(x(j) - center(trial,1));
  515. dy = abs(y(j) - center(trial,2));
  516. % center
  517. elseif trial ==2
  518. %
  519. dx = abs(x(j) - center(trial,1));
  520. dy = abs(y(j) - center(trial,2));
  521. % center
  522. else
  523. %
  524. dx = abs(x(j) - center(trial,1));
  525. dy = abs(y(j) - center(trial,2));
  526. % center
  527. end
  528. ET.offset_x = dx * params.pix_x;
  529. ET.offset_y = dy * params.pix_y;
  530. ET = CheckFixation_VTD_egeVersion(ET, trial, params, output);
  531. end
  532. end
  533. elseif params.eyetracking == 0
  534. cursample = cursample + 1;
  535. [ET.CurrentGaze(1,1) ET.CurrentGaze(1,2)] = GetMouse(params.window);
  536. ET.currentTime = GetSecs();
  537. ET.eyetime(cursample,1) = ET.currentTime;
  538. gazes(end+1,1) = ET.CurrentGaze(1,1);
  539. gazes(end,2) = ET.CurrentGaze(1,2);
  540. x = ET.CurrentGaze(1,1);
  541. y = ET.CurrentGaze(1,2);
  542. % figure(10);
  543. plot(x,y,'p')
  544. drawnow
  545. hold on
  546. if trial == 1
  547. center(trial,:) = meanGazeOne;
  548. center
  549. elseif trial == 2
  550. oldGaze = meanGazeOne * weightOld;
  551. newGaze = output(1).meanGazes * weightNew;
  552. % vector = [meanGazeOne;output(1).meanGazes];
  553. center(trial,:) = oldGaze + newGaze
  554. % center
  555. else
  556. oldGaze = center(trial-1,:) * weightOld;
  557. newGaze = output(trial-1).meanGazes * weightNew;
  558. % vector = [center(trial-1,:);output(trial-1).meanGazes];
  559. center(trial,:) = oldGaze + newGaze
  560. % center
  561. end
  562. ET = CheckFixation_VTD_egeVersion(ET, trial, params, output, center);
  563. end
  564. if ET.TrialAborted == true
  565. flag = 1;
  566. if params.EEG == 1
  567. SendSignal(params.ioObj, params.address,55); %trial aborted trigger
  568. triggerout = 1;
  569. triggertime = GetSecs;
  570. else
  571. end
  572. %% Display April tags on PTB screen to detect surface via PupilLabs
  573. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  574. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  575. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  576. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  577. Screen('DrawText', params.window, 'FIXATE PLEASE!', (params.screenX_pix/2)-100, (params.screenY_pix/2), params.black);
  578. Screen('Flip',params.window);
  579. break
  580. end
  581. if params.checkfix==1
  582. if ET.FixationEstablished && GetSecs>output(trial).trialonset+params.TimeToBeginFixation
  583. state = 2;
  584. end
  585. else
  586. if GetSecs>output(trial).trialonset+params.TimeToBeginFixation
  587. state = 2;
  588. end
  589. end
  590. end
  591. if flag == 1 || earlyResponseFlag ==1 %if trial is aborted, 'continue' comment takes you back to line with 'while 1'
  592. if random_trl_order(trial) == 1
  593. stimPresentCount=stimPresentCount-1;
  594. elseif random_trl_order(trial) == 2
  595. stimAbsentCount=stimAbsentCount-1;
  596. end
  597. trial = trial - 1;
  598. continue
  599. end
  600. %% STATE 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  601. if random_trl_order(trial) == 1 % For stimulus present trials
  602. % Change fixation circle to red and wait for
  603. % variable delay before stimulus presentation
  604. Screen('FillOval', params.window, [0.5 0 0], params.centeredcircleRectOUT, params.maxDiameterOUT);
  605. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  606. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, [0.5 0 0], [], 1);
  607. %% Display April tags on PTB screen to detect surface via PupilLabs
  608. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  609. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  610. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  611. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  612. Screen('Flip', params.window);
  613. % Get warning onset time
  614. output(trial).warningOnset = GetSecs;
  615. elseif random_trl_order(trial) == 2 % For stimulus absent trials
  616. % Change fixation circle to red and wait for
  617. % variable delay before stimulus presentation
  618. Screen('FillOval', params.window, [0.5 0 0], params.centeredcircleRectOUT, params.maxDiameterOUT);
  619. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  620. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, [0.5 0 0], [], 1);
  621. %% Display April tags on PTB screen to detect surface via PupilLabs
  622. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  623. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  624. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  625. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  626. Screen('Flip', params.window);
  627. % Get warning onset time
  628. output(trial).warningOnset = GetSecs;
  629. end
  630. flag3=0;
  631. earlyResponseFlag=0;
  632. while state == 2
  633. [pressed, firstPress] = KbQueueCheck;
  634. if pressed
  635. % Extract information about the key presses
  636. [~,pressedKeys] = find(firstPress);
  637. % Check if any of the response keys are pressed
  638. if any(ismember(pressedKeys, KbName(responseKeys(1:2))))
  639. % Identify the pressed key
  640. % idx = find(ismember(KbName(responseKeys), pressedKeys));
  641. % response = responseKeys{idx}; % Assign the pressed key as response
  642. Screen('TextSize',params.window, 30)
  643. Screen('DrawText',params.window, 'WAIT QUESTION MARK TO RESPOND!',(params.screenX_pix/2)-100, params.screenY_pix*0.5, params.black);
  644. % Screen('DrawText',params.window, 'Please wait till the question mark sign appears on screen to make your report.',(params.screenX_pix/2)-100, params.screenY_pix*0.55, params.black);
  645. %% Display April tags on PTB screen to detect surface via PupilLabs
  646. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  647. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  648. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  649. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  650. Screen('Flip', params.window);
  651. WaitSecs(2);
  652. flag3 = 1;
  653. end
  654. end
  655. if flag3 == 1
  656. fprintf('early response');
  657. earlyResponseFlag = 1;
  658. break
  659. end
  660. % If eyetracking
  661. if params.eyetracking == 1
  662. if params.whicheyetracker == 2
  663. if params.checkfix == 1
  664. cursample = cursample + 1;
  665. % Get gaze positions from pupil labs
  666. % (filtermessages)
  667. [topic, note] = recv_message(sub_socket, 2500);
  668. if ~isequal(note, false) % test for valid message
  669. gaze_positions{1,iter}= [topic, note('gaze_on_surfaces')]; % print pupil norm_pos
  670. for j=2:size(gaze_positions{1,iter},2)
  671. gazecoordinates = gaze_positions{1,iter}{1,j}('norm_pos');
  672. x(j) = gazecoordinates{1,1};
  673. y(j) = gazecoordinates{1,2};
  674. end
  675. %This alternative is decreasing the temporal...
  676. %...resolution in case matlab fails.
  677. end
  678. ET.CurrentGaze(1,1) = x(j);
  679. ET.CurrentGaze(1,2) = y(j);
  680. gazes(end+1,1) = ET.CurrentGaze(1,1);
  681. gazes(end,2) = ET.CurrentGaze(1,2);
  682. ET.currentTime = GetSecs();
  683. ET.eyetime(cursample,1) = ET.currentTime;
  684. if trial == 1
  685. % center(trial,:) = meanGazeOne;
  686. dx = abs(x(j) - center(trial,1));
  687. dy = abs(y(j) - center(trial,2));
  688. % center
  689. elseif trial ==2
  690. % vector = [meanGazeOne;output(1).meanGazes];
  691. % center(trial,:) = mean(vector,1);
  692. dx = abs(x(j) - center(trial,1));
  693. dy = abs(y(j) - center(trial,2));
  694. % center
  695. else
  696. % vector = [center(trial-1,:);output(trial-1).meanGazes];
  697. % center(trial,:) = mean(vector,1);
  698. dx = abs(x(j) - center(trial,1));
  699. dy = abs(y(j) - center(trial,2));
  700. % center
  701. end
  702. ET.offset_x = dx * params.pix_x;
  703. ET.offset_y = dy * params.pix_y;
  704. % offset = sqrt(offset_x^2 + offset_y^2);
  705. ET = CheckFixation_VTD_egeVersion(ET, trial, params, output, center);
  706. end
  707. end
  708. elseif params.eyetracking == 0
  709. cursample = cursample + 1;
  710. [ET.CurrentGaze(1,1) ET.CurrentGaze(1,2)] = GetMouse(params.window);
  711. ET.currentTime = GetSecs();
  712. ET.eyetime(cursample,1) = ET.currentTime;
  713. gazes(end+1,1) = ET.CurrentGaze(1,1);
  714. gazes(end,2) = ET.CurrentGaze(1,2);
  715. x = ET.CurrentGaze(1,1);
  716. y = ET.CurrentGaze(1,2);
  717. % figure(10);
  718. % plot(x,y,'p')
  719. % drawnow
  720. % hold on
  721. if trial == 1
  722. center(trial,:) = meanGazeOne;
  723. center
  724. elseif trial ==2
  725. vector = [meanGazeOne;output(1).meanGazes];
  726. center(trial,:) = mean(vector,1);
  727. center
  728. else
  729. vector = [center(trial-1,:);output(trial-1).meanGazes];
  730. center(trial,:) = mean(vector,1);
  731. center
  732. end
  733. ET = CheckFixation_VTD_egeVersion(ET, trial, params, output, center);
  734. end
  735. if ET.TrialAborted == true
  736. flag = 1;
  737. if params.EEG == 1
  738. SendSignal(params.ioObj, params.address,55); %trial aborted trigger
  739. triggerout = 1;
  740. triggertime = GetSecs;
  741. else
  742. end
  743. %% Display April tags on PTB screen to detect surface via PupilLabs
  744. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  745. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  746. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  747. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  748. Screen('DrawText', params.window, 'FIXATE PLEASE!', (params.screenX_pix/2)-100, (params.screenY_pix/2), params.black);
  749. Screen('Flip',params.window);
  750. break
  751. end
  752. % Timeout after state2
  753. if GetSecs>=output(trial).warningOnset+delayBeforeStimulus
  754. state = 3;
  755. break;
  756. else
  757. end
  758. end
  759. if flag == 1 || earlyResponseFlag==1
  760. fprintf('This trial is aborted at state # %d',state);
  761. if random_trl_order(trial) == 1
  762. stimPresentCount=stimPresentCount-1;
  763. elseif random_trl_order(trial) == 2
  764. stimAbsentCount=stimAbsentCount-1;
  765. end
  766. trial = trial - 1;
  767. continue
  768. end
  769. %% STATE 3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  770. % Send EEG trigger code for trial start
  771. if random_trl_order(trial) == 1 % For stimulus present trials
  772. % Apply the circular aperture to the
  773. % grating with the contrast recommended
  774. % by the QUEST algorithm
  775. params.gratingannulus = params.grey + params.grey * currentContrast * params.gratingtex;
  776. params.gratingannulus(params.annulusaperture == 0) = params.grey; % Set areas outside the annulus to gray
  777. % Creating the final texture from the grating with gray outside the annulus with PTB
  778. params.gratingannulustex = Screen('MakeTexture', params.window, params.gratingannulus);
  779. Screen('DrawTexture', params.window, params.gratingannulustex);
  780. Screen('FillOval', params.window, [0.5 0 0], params.centeredcircleRectOUT, params.maxDiameterOUT);
  781. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  782. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, [0.5 0 0], [], 1);
  783. %Draw the peripheral white square for the photodiode
  784. Screen('DrawDots', params.window, [params.dotXpos1, params.dotYpos1], 10, [0.7 0.7 0.7], [], 4);
  785. %% Display April tags on PTB screen to detect surface via PupilLabs
  786. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  787. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  788. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  789. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  790. % Get timestamp
  791. vbl = Screen('Flip', params.window);
  792. output(trial).stimulusOnset = vbl;
  793. if params.EEG == 1 %we only need this in stimulus present trials
  794. SendSignal(params.ioObj, params.address, 3); %3 = stimulus onset
  795. triggerout = 1;
  796. triggertime = GetSecs;
  797. else
  798. end
  799. if params.eyetracking == 1 % Send Annotation from Matlab to Pupil Labs
  800. if params.whicheyetracker == 2
  801. zmq.core.send(socket, uint8('t'));
  802. currentTime_bytes = zmq.core.recv(socket,20);
  803. % fprintf('first measure: %s\n', char(currentTime_bytes));
  804. currentTimeChar = char(currentTime_bytes);
  805. currentTimeNum = str2num(currentTimeChar);
  806. keys_start = {'topic', 'label', 'timestamp', 'duration'};
  807. values_start = {'annotation.StimulusOnset', strcat('Trial #', num2str(trial),' Stimulus Onset'), currentTimeNum, 1.0};
  808. start_annotation = containers.Map(keys_start, values_start);
  809. send_annotation(socket, start_annotation);
  810. result = zmq.core.recv(socket);
  811. end
  812. end
  813. elseif random_trl_order(trial) == 2 % For stimulus present trials
  814. % Draw stimulus and wait for stimulus presentation
  815. % duration but no stimulus is actually
  816. % presented
  817. % Screen('DrawTexture', params.window, params.gratingannulustex);
  818. % Get stimulus onset time
  819. output(trial).stimulusOnset = GetSecs;
  820. end
  821. flag4=0;
  822. earlyResponseFlag = 0;
  823. while state == 3
  824. [pressed, firstPress] = KbQueueCheck;
  825. if pressed
  826. % Extract information about the key presses
  827. [~,pressedKeys] = find(firstPress);
  828. % Check if any of the response keys are pressed
  829. if any(ismember(pressedKeys, KbName(responseKeys)))
  830. % Identify the pressed key
  831. % idx = find(ismember(KbName(responseKeys), pressedKeys));
  832. % response = responseKeys{idx}; % Assign the pressed key as response
  833. Screen('TextSize',params.window, 30)
  834. Screen('DrawText',params.window, 'WAIT QUESTION MARK TO RESPOND!',(params.screenX_pix/2)-100, params.screenY_pix*0.5, params.black);
  835. % Screen('DrawText',params.window, 'Please wait till the question mark sign appears on screen to make your report.',(params.screenX_pix/2)-100, params.screenY_pix*0.55, params.black);
  836. %% Display April tags on PTB screen to detect surface via PupilLabs
  837. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  838. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  839. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  840. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  841. Screen('Flip',params.window);
  842. WaitSecs(2);
  843. flag4 = 1;
  844. end
  845. end
  846. if flag4 == 1
  847. earlyResponseFlag=1;
  848. fprintf('early response');
  849. break
  850. end
  851. % Timeout after [params.LCandHC] seconds
  852. if GetSecs>=output(trial).stimulusOnset+ stimulusDuration
  853. state = 4;
  854. break;
  855. else
  856. end
  857. %
  858. end
  859. %
  860. %% STATE 4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  861. state = 4;
  862. if random_trl_order(trial) == 1
  863. % Remove stimulus and wait for variable
  864. % delay duration after stimulus, during
  865. % this period the red fixation mark still
  866. % remains
  867. Screen('FillOval', params.window, [0.5 0 0], params.centeredcircleRectOUT, params.maxDiameterOUT);
  868. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  869. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, [0.5 0 0], [], 1);
  870. %% Display April tags on PTB screen to detect surface via PupilLabs
  871. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  872. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  873. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  874. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  875. Screen('Flip', params.window, output(trial).stimulusOnset + (stimulusFrames - 0.5) * params.flipinterval);
  876. output(trial).delayOnset = GetSecs;
  877. % Get delay onset time
  878. elseif random_trl_order(trial) == 2 % For stimulus present trials
  879. % Remove stimulus and wait for variable
  880. % delay duration after stimulus, during
  881. % this period the red fixation mark still
  882. % remains
  883. Screen('FillOval', params.window, [0.5 0 0], params.centeredcircleRectOUT, params.maxDiameterOUT);
  884. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  885. Screen('DrawDots', params.window, [params.xcenter_pix, params.ycenter_pix], params.fixationSize_pix, [0.5 0 0], [], 1);
  886. %% Display April tags on PTB screen to detect surface via PupilLabs
  887. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  888. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  889. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  890. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  891. Screen('Flip', params.window, output(trial).stimulusOnset + (stimulusFrames - 0.5) * params.flipinterval);
  892. % Get delay onset time
  893. output(trial).delayOnset = GetSecs;
  894. end
  895. flag5=0;
  896. earlyResponseFlag = 0;
  897. while state == 4
  898. [pressed, firstPress] = KbQueueCheck;
  899. if pressed
  900. % Extract information about the key presses
  901. [~,pressedKeys] = find(firstPress);
  902. % Check if any of the response keys are pressed
  903. if any(ismember(pressedKeys, KbName(responseKeys)))
  904. % Identify the pressed key
  905. % idx = find(ismember(KbName(responseKeys), pressedKeys));
  906. % response = responseKeys{idx}; % Assign the pressed key as response
  907. Screen('TextSize',params.window, 30)
  908. Screen('DrawText',params.window, 'WAIT QUESTION MARK TO RESPOND!',(params.screenX_pix/2)-100, params.screenY_pix*0.5, params.black);
  909. % Screen('DrawText',params.window, 'Please wait till the question mark sign appears on screen to make your report.',(params.screenX_pix/2)-100, params.screenY_pix*0.55, params.black);
  910. %% Display April tags on PTB screen to detect surface via PupilLabs
  911. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  912. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  913. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  914. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  915. Screen('Flip',params.window);
  916. WaitSecs(2);
  917. flag5 = 1;
  918. end
  919. end
  920. if flag5 == 1
  921. earlyResponseFlag=1;
  922. fprintf('early response');
  923. break
  924. end
  925. % If eyetracking
  926. if params.eyetracking == 1
  927. if params.whicheyetracker == 2
  928. if params.checkfix == 1
  929. cursample = cursample + 1;
  930. % Get gaze positions from pupil labs
  931. % (filtermessages)
  932. [topic, note] = recv_message(sub_socket, 2500);
  933. if ~isequal(note, false) % test for valid message
  934. gaze_positions{1,iter}= [topic, note('gaze_on_surfaces')]; % print pupil norm_pos
  935. for j=2:size(gaze_positions{1,iter},2)
  936. gazecoordinates = gaze_positions{1,iter}{1,j}('norm_pos');
  937. x(j) = gazecoordinates{1,1};
  938. y(j) = gazecoordinates{1,2};
  939. end
  940. %This alternative is decreasing the temporal...
  941. %...resolution in case matlab fails.
  942. end
  943. ET.CurrentGaze(1,1) = x(j);
  944. ET.CurrentGaze(1,2) = y(j);
  945. gazes(end+1,1) = ET.CurrentGaze(1,1);
  946. gazes(end,2) = ET.CurrentGaze(1,2);
  947. ET.currentTime = GetSecs();
  948. ET.eyetime(cursample,1) = ET.currentTime;
  949. if trial == 1
  950. % center(trial,:) = meanGazeOne;
  951. dx = abs(x(j) - center(trial,1));
  952. dy = abs(y(j) - center(trial,2));
  953. % center
  954. elseif trial ==2
  955. % vector = [meanGazeOne;output(1).meanGazes];
  956. % center(trial,:) = mean(vector,1);
  957. dx = abs(x(j) - center(trial,1));
  958. dy = abs(y(j) - center(trial,2));
  959. % center
  960. else
  961. % vector = [center(trial-1,:);output(trial-1).meanGazes];
  962. % center(trial,:) = mean(vector,1);
  963. dx = abs(x(j) - center(trial,1));
  964. dy = abs(y(j) - center(trial,2));
  965. % center
  966. end
  967. ET.offset_x = dx * params.pix_x;
  968. ET.offset_y = dy * params.pix_y;
  969. % offset = sqrt(offset_x^2 + offset_y^2);
  970. ET = CheckFixation_VTD_egeVersion(ET, trial, params, output, center);
  971. end
  972. end
  973. elseif params.eyetracking == 0
  974. cursample = cursample + 1;
  975. [ET.CurrentGaze(1,1) ET.CurrentGaze(1,2)] = GetMouse(params.window);
  976. ET.currentTime = GetSecs();
  977. ET.eyetime(cursample,1) = ET.currentTime;
  978. gazes(end+1,1) = ET.CurrentGaze(1,1);
  979. gazes(end,2) = ET.CurrentGaze(1,2);
  980. x = ET.CurrentGaze(1,1);
  981. y = ET.CurrentGaze(1,2);
  982. % figure(10);
  983. % plot(x,y,'p')
  984. % drawnow
  985. % hold on
  986. if trial == 1
  987. center(trial,:) = meanGazeOne;
  988. center
  989. elseif trial ==2
  990. vector = [meanGazeOne;output(1).meanGazes];
  991. center(trial,:) = mean(vector,1);
  992. center
  993. else
  994. vector = [center(trial-1,:);output(trial-1).meanGazes];
  995. center(trial,:) = mean(vector,1);
  996. center
  997. end
  998. ET = CheckFixation_VTD_egeVersion(ET, trial, params, output, center);
  999. end
  1000. if ET.TrialAborted == true
  1001. flag = 1;
  1002. if params.EEG == 1
  1003. SendSignal(params.ioObj, params.address,55); %trial aborted trigger
  1004. triggerout = 1;
  1005. triggertime = GetSecs;
  1006. else
  1007. end
  1008. %% Display April tags on PTB screen to detect surface via PupilLabs
  1009. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  1010. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  1011. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  1012. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  1013. Screen('DrawText', params.window, 'FIXATE PLEASE!', (params.screenX_pix/2)-100, (params.screenY_pix/2), params.black);
  1014. Screen('Flip',params.window);
  1015. break
  1016. end
  1017. % EEG trigger off
  1018. % if triggerout == 1 && GetSecs >= triggertime + params.triggerofftime
  1019. % SendSignal(0);
  1020. % triggerout = 0;
  1021. % triggertime = NaN;
  1022. % else
  1023. % end
  1024. % Timeout after [params.LCandHC] seconds
  1025. if GetSecs>=output(trial).delayOnset+delayAfterStimulus
  1026. state = 5;
  1027. break;
  1028. else
  1029. end
  1030. end
  1031. if earlyResponseFlag==1
  1032. if params.EEG == 1
  1033. SendSignal(params.ioObj, params.address,55); %trial aborted trigger
  1034. triggerout = 1;
  1035. triggertime = GetSecs;
  1036. else
  1037. end
  1038. end
  1039. if earlyResponseFlag==1 || flag==1
  1040. fprintf('this trial is aborted at state # %d',state);
  1041. if random_trl_order(trial) == 1
  1042. stimPresentCount=stimPresentCount-1;
  1043. elseif random_trl_order(trial) == 2
  1044. stimAbsentCount=stimAbsentCount-1;
  1045. end
  1046. trial = trial - 1;
  1047. continue
  1048. end
  1049. %% STATE 5 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1050. % Set the background to gray and display message
  1051. % for participant to give their report and
  1052. % confidence
  1053. % Screen('FillRect', params.window, params.grey);
  1054. % Screen('Flip', params.window);
  1055. Report = '?';
  1056. Screen('FillOval', params.window, params.black, params.centeredcircleRectOUT, params.maxDiameterOUT);
  1057. Screen('FillOval', params.window, params.grey, params.centeredcircleRectIN, params.maxDiameterIN);
  1058. Screen('TextSize', params.window, 30);
  1059. Screen('DrawText', params.window, Report, (params.screenX_pix/2)-10, (params.screenY_pix/2)-10, params.black);
  1060. %% Display April tags on PTB screen to detect surface via PupilLabs
  1061. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  1062. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  1063. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  1064. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  1065. Screen('Flip', params.window);
  1066. % WaitSecs(time_for_response);
  1067. response = [];
  1068. flag6 = 0;
  1069. flagResponse=1;
  1070. responseStartTime = GetSecs(); % Record response start time
  1071. while GetSecs() - responseStartTime <= time_for_response
  1072. [pressed, firstPress] = KbQueueCheck;
  1073. if pressed
  1074. % Extract information about the key presses
  1075. [~,pressedKeys] = find(firstPress);
  1076. % Check if any of the response keys are pressed
  1077. if any(ismember(pressedKeys, KbName(responseKeys)))
  1078. % Identify the pressed key
  1079. idx = find(ismember(KbName(responseKeys), pressedKeys));
  1080. response = responseKeys{idx}; % Assign the pressed key as response
  1081. break; % Exit the loop upon response detection
  1082. end
  1083. end
  1084. end
  1085. if ~isempty(response)
  1086. if random_trl_order(trial) == 1
  1087. if strcmp(response, keyHit)
  1088. % Update QUEST for 'hit'
  1089. outputSP(stimPresentCount).response = 1;
  1090. output(trial).response = 1;
  1091. hitCount = hitCount + 1;
  1092. if params.EEG == 1 %we only need this in stimulus present trials
  1093. SendSignal(params.ioObj, params.address, 4); %4 = response 'hit'
  1094. triggerout = 1;
  1095. triggertime = GetSecs;
  1096. else
  1097. end
  1098. if stimPresentCount <= 10 | strcmp (params.runtype, 'TR') %if we are in the test run, we want contrast update after every trial
  1099. q = QuestUpdate(q, currentContrast, 1);
  1100. else
  1101. last10 = [outputSP(stimPresentCount-10:stimPresentCount).response];
  1102. sumlast10=sum(last10);
  1103. if sumlast10/10<0.5
  1104. q = QuestUpdate(q, currentContrast, 1);
  1105. elseif sumlast10/10>0.8
  1106. q = QuestUpdate(q, currentContrast, 1);
  1107. else
  1108. end
  1109. end
  1110. elseif strcmp(response, keyMiss)
  1111. % Update QUEST for 'miss'
  1112. outputSP(stimPresentCount).response = 0;
  1113. output(trial).response = 0;
  1114. missCount = missCount + 1;
  1115. if params.EEG == 1 %we only need this in stimulus present trials
  1116. SendSignal(params.ioObj, params.address, 5); %5 = response 'miss'
  1117. triggerout = 1;
  1118. triggertime = GetSecs;
  1119. else
  1120. end
  1121. if stimPresentCount <= 10
  1122. q = QuestUpdate(q, currentContrast, 0);
  1123. else
  1124. last10 = [outputSP(stimPresentCount-10:stimPresentCount).response]
  1125. sumlast10=sum(last10)
  1126. if sumlast10/10<0.5
  1127. q = QuestUpdate(q, currentContrast, 0);
  1128. elseif sumlast10/10>0.8
  1129. q = QuestUpdate(q, currentContrast, 0);
  1130. else
  1131. end
  1132. end
  1133. end
  1134. elseif random_trl_order(trial) == 2
  1135. if strcmp(response, keyHit)
  1136. faCount = faCount + 1;
  1137. output(trial).response = 1;
  1138. elseif strcmp(response, keyMiss)
  1139. output(trial).response = 0;
  1140. end
  1141. end
  1142. elseif isempty(response)
  1143. flag6 = 1;
  1144. Screen('TextSize',params.window, 30)
  1145. Screen('DrawText',params.window, 'RESPOND ON TIME!',(params.screenX_pix/2)-100, params.screenY_pix*0.5, params.black);
  1146. %% Display April tags on PTB screen to detect surface via PupilLabs
  1147. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  1148. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  1149. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  1150. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  1151. Screen('Flip',params.window);
  1152. WaitSecs(2);
  1153. end
  1154. if flag6 == 1
  1155. flagResponse = 0;
  1156. end
  1157. if flagResponse == 0
  1158. if params.EEG == 1
  1159. SendSignal(params.ioObj, params.address,55); %trial aborted trigger
  1160. triggerout = 1;
  1161. triggertime = GetSecs;
  1162. else
  1163. end
  1164. fprintf('this trial is aborted at state # %d',state);
  1165. if random_trl_order(trial) == 1
  1166. stimPresentCount=stimPresentCount-1;
  1167. elseif random_trl_order(trial) == 2
  1168. stimAbsentCount=stimAbsentCount-1;
  1169. end
  1170. trial = trial - 1;
  1171. continue
  1172. end
  1173. WaitSecs(0.5);
  1174. [pos_conf] = slideScale(params.window, 'Rate your confidence', params.resolution, {'LOW', 'AVERAGE', 'HIGH'},params, 'device','keyboard');
  1175. %% Display April tags on PTB screen to detect surface via PupilLabs
  1176. Screen('DrawTextures', params.window, params.txt1, [], params.dstRects(:,1));
  1177. Screen('DrawTextures', params.window, params.txt2, [], params.dstRects(:,2));
  1178. Screen('DrawTextures', params.window, params.txt3, [], params.dstRects(:,3));
  1179. Screen('DrawTextures', params.window, params.txt4, [], params.dstRects(:,4));
  1180. Screen('Flip',params.window);
  1181. WaitSecs(0.5);
  1182. output(trial).confidenceAnswer = pos_conf; %deviation from the center
  1183. hitRates(trial) = (hitCount / stimPresentCount)*100; % Calculate hit rate
  1184. falseAlarmRates(trial) = (faCount / stimAbsentCount)*100; % Calculate false alarm rate
  1185. output(trial).accuracy = hitRates(trial);
  1186. output(trial).falsealarm = falseAlarmRates(trial);
  1187. fprintf('Current hit rate: %d',hitRates(trial));
  1188. fprintf('\nCurrent false alarm rate: %d',falseAlarmRates(trial));
  1189. % % % Update data arrays
  1190. % x1 = [x1, trial]; % X-axis as index
  1191. % y1 = [y1, hitRates(trial)];
  1192. % x2 = [x2, trial]; % X-axis as index
  1193. % y2 = [y2, falseAlarmRates(trial)];
  1194. % x3 = [x3, trial];
  1195. % y3 = [y3, currentContrast];
  1196. %
  1197. % % Plot online for the first figure
  1198. % figure(1); % Activate the first figure
  1199. % subplot(2, 1, 1);
  1200. % plot(x1, y1, 'r-', 'LineWidth', 2); % Plot updated data for plot 1
  1201. % hold on; % Hold the current plot to add more data
  1202. % plot(x1, y2, 'b--', 'LineWidth', 2); % Plot y2 in red dashed line
  1203. % hold off
  1204. % % Release the current plot
  1205. % xlabel('Trial');
  1206. % ylabel('Hits and False Alarms');
  1207. % ylim([0,1]);
  1208. % title('QUEST modulated accuracy');
  1209. % drawnow; % Refresh the plot
  1210. %
  1211. %
  1212. % % Plot online for the second figure
  1213. % % figure(2); % Activate the second figure
  1214. % subplot(2, 1, 2);
  1215. % plot(x3, y3, 'k-', 'LineWidth', 2); % Plot updated data for plot 2
  1216. % xlabel('Trial');
  1217. % ylabel('Grating Contrast');
  1218. % ylim([0,0.3]);
  1219. % title('QUEST modulated contrast');
  1220. % drawnow; % Refresh the plot
  1221. % EEG trigger off
  1222. % if triggerout == 1 && GetSecs >= triggertime + params.triggerofftime
  1223. % SendSignal(0);
  1224. % triggerout = 0;
  1225. % triggertime = NaN;
  1226. % else
  1227. % end;
  1228. fprintf('\nThis trial is successfully completed, trial number: %d',trial);
  1229. if params.checkfix == 1
  1230. newMean = [mean(gazes(:,1)) mean(gazes(:,2))]; %after a successful completion of a trial, you get the mean gaze locations to re-define it as the center!
  1231. output(trial).meanGazes = newMean;
  1232. end
  1233. if trial == params.numtrials
  1234. break
  1235. end
  1236. end; % end of trial loop
  1237. WaitSecs(2);
  1238. KbQueueStop; % Stop delivering events to the queue
  1239. [pressed, firstPress] = KbQueueCheck;
  1240. % [pressed, firstPress, firstRelease, lastPress, lastRelease] = KbQueueCheck;
  1241. % Create key presses struct
  1242. for i = 1:KbEventAvail
  1243. [evt, n] = KbEventGet;
  1244. if i == 1
  1245. keyboard_events = evt;
  1246. else
  1247. keyboard_events(end+1) = evt;
  1248. end;
  1249. end;
  1250. end % end of blocks loop
  1251. %% Close properly
  1252. % Show end message for the subject
  1253. Screen('DrawText', params.window, 'Done - Thank you!', (params.screenX_pix/2)-100, (params.screenY_pix/2), params.black);
  1254. Screen('Flip', params.window);
  1255. WaitSecs(2);
  1256. % Show mouse cursor again
  1257. ShowCursor;
  1258. % % Calculate hit rate and false alarm rate as percentages
  1259. overallhitRate = (hitCount / stimPresentCount) * 100;
  1260. overallfalseAlarmRate = (faCount / stimAbsentCount) * 100;
  1261. % Save data to .mat file
  1262. cd(params.savepath);
  1263. save(params.filename,'params','output','keyboard_events','ET','gazes','-v7.3');
  1264. disp('Data saved');
  1265. KbQueueRelease;
  1266. ListenChar(0);
  1267. if strcmp (params.runtype, 'TR')| strcmp (params.runtype, 'TC')
  1268. % Display the estimated threshold
  1269. disp(['Estimated Threshold from the Calibration Run: ' num2str(QuestMean(q))]);
  1270. elseif strcmp (params.runtype, 'R')| strcmp (params.runtype, 'H')
  1271. disp(['Estimated Threshold from the Last Run: ' num2str(QuestMean(q))]);
  1272. end
  1273. % Close Eyelink eyetracker
  1274. if params.eyetracking == 1
  1275. if params.whicheyetracker == 1
  1276. Eyelink('StopRecording');
  1277. Eyelink('CloseFile');
  1278. % download data file
  1279. try
  1280. fprintf('Receiving data file ''%s''\n', params.eyedatafile);
  1281. status=Eyelink('ReceiveFile');
  1282. if status > 0
  1283. fprintf('ReceiveFile status %d\n', status);
  1284. end
  1285. if 2==exist(params.eyedatafile, 'file')
  1286. fprintf('Data file ''%s'' can be found in ''%s''\n', params.eyedatafile, pwd );
  1287. end
  1288. catch rdf
  1289. fprintf('Problem receiving data file ''%s''\n', params.eyedatafile);
  1290. rdf;
  1291. end
  1292. Eyelink('Command', 'set_idle_mode');
  1293. WaitSecs(0.05);
  1294. Eyelink('shutdown')
  1295. elseif params.whicheyetracker == 2
  1296. %stop the recording of Pupil Labs
  1297. zmq.core.send(socket, uint8('r'));
  1298. result = zmq.core.recv(socket);
  1299. fprintf('Recording stopped: %s\n', char(result));
  1300. % disconnect sub socket
  1301. zmq.core.disconnect(sub_socket, sub_endpoint);
  1302. zmq.core.close(sub_socket);
  1303. fprintf('Disconnected from SUB: %s\n', sub_endpoint);
  1304. zmq.core.disconnect(socket, endpoint);
  1305. zmq.core.close(socket);
  1306. % zmq.core.ctx_shutdown(ctx);
  1307. % zmq.core.ctx_term(ctx);
  1308. end
  1309. end
  1310. % Find indices of stimulus-absent trials
  1311. stimulusAbsentIdx = find(random_trl_order == 2);
  1312. % Generate plots
  1313. % Plot for Accuracy (hit rate and false alarm rate vs Trial Number)
  1314. trialNumbers = 1:length(random_trl_order);
  1315. figure;
  1316. subplot(2, 1, 1);
  1317. plot(trialNumbers, hitRates, 'Color', [0.6, 0, 0], 'LineWidth', 2); % Plot hit rate
  1318. hold on;
  1319. plot(trialNumbers, falseAlarmRates, 'Color', [0, 0.6, 0], 'LineWidth', 2); % Plot false alarm rate
  1320. xlabel('Trial Number');
  1321. ylabel('Accuracy (%)');
  1322. % legend('Hit Rate', 'False Alarm Rate', 'Location','eastoutside');
  1323. title('Accuracy');
  1324. xlim([1, length(trialNumbers)]);
  1325. % Plot the stimulus-absent trials individually with a grey background
  1326. for i = 1:length(stimulusAbsentIdx)
  1327. idx = stimulusAbsentIdx(i);
  1328. % Check if this is not the last stimulus-absent trial
  1329. if i < length(stimulusAbsentIdx)
  1330. % Define x-coordinates for the grey background area
  1331. x = [idx, trialNumbers(idx+1), trialNumbers(idx+1), idx];
  1332. else
  1333. % For the last stimulus-absent trial
  1334. if idx == trialNumbers(end)
  1335. x = [idx, trialNumbers(end), trialNumbers(end), idx];
  1336. else
  1337. x = [idx, trialNumbers(idx+1), trialNumbers(idx+1), idx];
  1338. end
  1339. end
  1340. % Define y-coordinates for the grey background area (0 to 0.25 for contrast)
  1341. y = [0, 0, 100, 100];
  1342. % Plot the grey background area for this stimulus-absent trial
  1343. patch(x, y, 'k', 'EdgeColor', 'none', 'FaceColor', [0.8, 0.8, 0.8], 'FaceAlpha', 0.3);
  1344. end
  1345. % Plot for currentContrast vs Trial Number
  1346. subplot(2, 1, 2);
  1347. plot(trialNumbers, contrasts, 'Color', [0.6, 0, 0], 'LineWidth', 2);
  1348. xlabel('Trial Number');
  1349. ylabel('Stimulus Contrast');
  1350. title('QUEST recommended contrast');
  1351. ylim([0, 0.25]); % Set y-axis limits for contrast plot
  1352. xlim([1, length(trialNumbers)]);
  1353. % Plot the stimulus-absent trials individually with a grey background
  1354. for i = 1:length(stimulusAbsentIdx)
  1355. idx = stimulusAbsentIdx(i);
  1356. % Check if this is not the last stimulus-absent trial
  1357. if i < length(stimulusAbsentIdx)
  1358. % Define x-coordinates for the grey background area
  1359. x = [idx, trialNumbers(idx+1), trialNumbers(idx+1), idx];
  1360. else
  1361. % For the last stimulus-absent trial
  1362. if idx == trialNumbers(end)
  1363. x = [idx, trialNumbers(end), trialNumbers(end), idx];
  1364. else
  1365. x = [idx, trialNumbers(idx+1), trialNumbers(idx+1), idx];
  1366. end
  1367. end
  1368. % Define y-coordinates for the grey background area (0 to 0.25 for contrast)
  1369. y = [0, 0, 0.25, 0.25];
  1370. % Plot the grey background area for this stimulus-absent trial
  1371. patch(x, y, 'k', 'EdgeColor', 'none', 'FaceColor', [0.8, 0.8, 0.8], 'FaceAlpha', 0.3);
  1372. end
  1373. hold off;
  1374. % Save the plots
  1375. saveas(gcf, fullfile(params.savepathplot, params.filenameplot));
  1376. end

trials_VTDnew_egeVersion.m at commit bd6707d, no license · at the source

Overview

Authors: Ege Kingir1, Sukanya Chakraborty1, Caspar M Schwiedrzik2,3,4, Melanie Wilke1,5
  1. Department of Cognitive Neurology, Heart and Brain Center Goettingen, University Medical Center, Goettingen, Germany
  2. Neural Circuits and Cognition Lab, European Neuroscience Institute Goettingen—A Joint Initiative of the University Medical Center Goettingen and the Max Planck Institute for Multidisciplinary Sciences, Goettingen, Germany
  3. Perception and Plasticity Group, German Primate Center—Leibniz Institute for Primate Research, Göttingen, Germany
  4. Cognitive Neurobiology, Research Center One Health Ruhr, University Alliance Ruhr, Faculty of Biology and Biotechnology, Ruhr‐University Bochum, Bochum, Germany
  5. Cognitive Neurology Group, German Primate Center, Cognitive Neuroscience Laboratory, Leibniz Institute for Primate Research, Goettingen, Germany
Journal: Psychophysiology, volume 63, issue 3, article e70271
Dates: received 15 August 2025; accepted 18 February 2026; published online 9 March 2026; in print March 2026
Type: Research article · Language: English
License: CC BY-NC
Identifiers: DOI 10.1111/psyp.70271 · PMID 41800588 · PMCID PMC12969548 · OpenAlex W7134230605
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality), other (modality), human (organism), cognitive (subfield)
Methods: Spectral & time-frequency, Connectivity, Statistics, Smoothing, state filtering, decompositions, Preprocessing, Evoked potentials, Physiology & signal measures, Machine learning
Keywords: anticipatory cardiac deceleration, heart rate variability, respiration, respiratory sinus arrhythmia, visual perception
MeSH: Anticipation, Psychological*, Evoked Potentials*, Heart Rate*, Respiratory Sinus Arrhythmia*, Visual Perception*, Adult, Electrocardiography, Electroencephalography, Female, Humans, Male, Young Adult (* major topic)
Topic: Heart Rate Variability and Autonomic Control (Cardiology and Cardiovascular Medicine, Medicine), according to OpenAlex
Funding: International Max Planck Research School for Neurosciences (IMPRS); International Max Planck Research School for Advanced Methods in Process and Systems Engineering; Else Kröner-Fresenius-Stiftung; Deutsche Forschungsgemeinschaft (SCHW1683/2‐1, GRK 2824); German Research Foundation (GRK 2824, SCHW1683/2-1)
Citations: not cited yet (Europe PMC); 65 references in the paper

Abstract

The heart does not beat like a metronome: varying parasympathetic input to the heart leads to constant heart rate variability. Vagal cardiomotor neuron activity is coupled to the respiratory cycle, leading to respiratory sinus arrhythmia (RSA), a permanent oscillation of heart rate synchronized to respiration. Heart rate also temporarily decelerates in specific conditions such as in freezing due to perceived threat or in anticipation of a salient stimulus. Anticipatory cardiac deceleration (ACD) is observed consistently in anticipation of a stimulus in perceptual tasks, but its relationship with perceptual performance is debated. Previous quantifications of ACD neglect ongoing heart rate oscillations due to RSA, which may have led to inconsistencies in the ACD‐related analyses across studies. Here, we suggest a novel approach to estimate trial‐averaged RSA amplitude and respiratory phase‐independent cardiac deceleration simultaneously and apply it to an EEG‐ECG dataset from a visual detection task. While the total ACD was not associated with perception, dissociating RSA‐dependent and non‐respiratory cardiac modulations revealed that they showed negative and positive correlations with perceptual performance, respectively. Additionally, we found that participants with higher ACD amplitudes also displayed larger Visual Awareness Negativity potentials, further supporting a contribution of ACD to visual perception.

Reproduced under the paper's license (CC BY-NC), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 16 matches between paragraphs and lines of code.

ege-kingir/VisualThresholdDetection

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Commit: bd6707dfffe9276a67c0b1cae2260bc1041f9070, 26 February 2026
Languages: MATLAB (21)
Size: 26 files, 21 scripts
Software Heritage: not archived
Found in: “Data Availability Statement”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Psychtoolbox (7 files), EEGLAB (5 files), Statistics and Machine Learning Toolbox (3 files), CircStat (2 files), FieldTrip (1 file), Image Processing Toolbox (1 file), Signal Processing Toolbox (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers
  • 30 September 2026: the link answers
22 files

The paper's code and data availability statement is in the Data section.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 21 scripts, each with its path and the digest of its content;
  • 16 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data Availability Statement

The datasets generated and analyzed for the current study, and the corresponding code, are available from the corresponding author on request. Code for running the visual perception task, physiological data preprocessing, and analysis can be found in this public GitHub repository: https://github.com/ege‐kingir/VisualThresholdDetection (https://github.com/ege-kingir/VisualThresholdDetection).

Reproduced under the paper's license (CC BY-NC), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 30 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 5 keywords, 12 MeSH terms, 5 funders, 63 references.

Cite

This paper

Kingir, E., Chakraborty, S., Schwiedrzik, C. M., & Wilke, M. (2026). Disentangling Respiratory Phase-Dependent and Phase-Independent Components of Anticipatory Cardiac Deceleration. Psychophysiology, 63(3), e70271. https://doi.org/10.1111/psyp.70271

BibTeX

@article{kingir2026disentangling,
author = {Kingir, Ege and Chakraborty, Sukanya and Schwiedrzik, Caspar M and Wilke, Melanie},
title = {{Disentangling Respiratory Phase-Dependent and Phase-Independent Components of Anticipatory Cardiac Deceleration}},
journal = {Psychophysiology},
year = {2026},
month = mar,
volume = {63},
number = {3},
pages = {e70271},
publisher = {Wiley},
issn = {0048-5772},
doi = {10.1111/psyp.70271},
url = {https://doi.org/10.1111/psyp.70271},
pmid = {41800588},
pmcid = {PMC12969548}
}

RIS

TY - JOUR
AU - Kingir, Ege
AU - Chakraborty, Sukanya
AU - Schwiedrzik, Caspar M
AU - Wilke, Melanie
TI - Disentangling Respiratory Phase-Dependent and Phase-Independent Components of Anticipatory Cardiac Deceleration
T2 - Psychophysiology
J2 - Psychophysiology
PY - 2026
DA - 2026/03/01
VL - 63
IS - 3
SP - e70271
SN - 0048-5772
PB - Wiley
DO - 10.1111/psyp.70271
UR - https://doi.org/10.1111/psyp.70271
LA - en
ER -

CSL-JSON

{
"id": "10.1111/psyp.70271",
"type": "article-journal",
"title": "Disentangling Respiratory Phase-Dependent and Phase-Independent Components of Anticipatory Cardiac Deceleration",
"container-title": "Psychophysiology",
"author": [
{
"family": "Kingir",
"given": "Ege"
},
{
"family": "Chakraborty",
"given": "Sukanya"
},
{
"family": "Schwiedrzik",
"given": "Caspar M"
},
{
"family": "Wilke",
"given": "Melanie"
}
],
"container-title-short": "Psychophysiology",
"volume": "63",
"issue": "3",
"page": "e70271",
"DOI": "10.1111/psyp.70271",
"PMID": "41800588",
"PMCID": "PMC12969548",
"ISSN": "0048-5772",
"publisher": "Wiley",
"URL": "https://doi.org/10.1111/psyp.70271",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
1
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41467-026-71604-8 [code]
Respiration as a dynamic modulator of sensory sampling.
Journal: Nature communications
In common: CircStat, FieldTrip, Signal Processing Toolbox, 1 other tool, cognitive, 6 references
[2] doi:10.1371/journal.pbio.3003938 [code]
Theta oscillations tag episodic memories for sleep-dependent consolidation.
Journal: PLoS biology
In common: CircStat, EEGLAB, FieldTrip, 3 other tools, EEG, cognitive, 2 references
[3] doi:10.1162/imag.a.1199 [code]
Sustained alpha oscillations serve attentional prioritization in working memory, not maintenance.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: CircStat, EEGLAB, FieldTrip, 3 other tools, EEG, cognitive, 2 references
[4] doi:10.7554/elife.107081 [code]
Cortical motor activity modulates respiration and reduces apnoea in neonates.
Journal: eLife
In common: EEGLAB, FieldTrip, Image Processing Toolbox, 2 other tools, EEG, 3 references
[5] doi:10.1038/s41598-026-49900-6 [code]
Global neural oscillations underlie performance variability and attentional state fluctuations in humans.
Journal: Scientific reports
In common: CircStat, EEGLAB, FieldTrip, 3 other tools, cognitive, 1 reference
[6] doi:10.1016/j.isci.2026.116586 [code]
Condition-specific neural signatures of reactivation during post-retrieval rest: An EEG study.
Journal: iScience
In common: EEGLAB, FieldTrip, Image Processing Toolbox, 2 other tools, EEG, cognitive, 3 references
[7] doi:10.1523/jneurosci.0154-26.2026 [code]
Faster but less precise: expectation enhances response speed while reducing sensory fidelity.
Journal: The Journal of neuroscience : the official journal of the Society for Neuroscience
In common: CircStat, EEGLAB, Image Processing Toolbox, 2 other tools, EEG, cognitive, 2 references
[8] doi:10.7554/elife.110795 [code]
REM sleep prefrontal high-frequency oscillation chains mediate distinct cortical - hippocampal reactivation patterns compared to NREM sleep.
Journal: eLife
In common: CircStat, EEGLAB, FieldTrip, 3 other tools, 1 reference
[9] doi:10.1162/imag.a.1229 [code]
40 Hz audiovisual stimulation improves sustained attention and related brain oscillations.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: CircStat, EEGLAB, FieldTrip, 3 other tools, EEG
[10] doi:10.1162/imag.a.1353 [code]
Model-based cardiac field artefact correction for OP-MEG.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: EEGLAB, FieldTrip, Signal Processing Toolbox, 1 other tool, EEG, 3 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.