OSCR

Advantages and artifacts of high-speed OLED monitors for vision, eye-tracking, and EEG research.

Code ↔ Paper

18 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 18 matches
  1. [1] § Methods › Practical test 2: Intra-saccadic stimulation ↔ Fig10_saccadeTask/plotdata_intrasaccadic_Fig9.m, lines 21–38 · score 0.82 · parallel port trigger, EYE EEG toolbox, downsampled, synchronized, EEGLAB, error
  2. [2] § Methods › Temporal light modulation (TLM) during each cycle ↔ Fig03_TLMflicker/Figure3_quantifyTLM_osf.m, lines 1–25 · score 0.81 · temporal light modulation, full screen stimuli, 0–255, TLM, gamma, spike
  3. [3] § Methods › Temporal independence (paired-pulse paradigm) ↔ Fig04_PairedPulsesTest/code_analyze_PairedPulseParadigm_OSF.m, lines 1–17 · score 0.80 · paired pulse paradigm, Hallum Cloherty, recorded photodiode, temporal dependencies, biphasic, sum
  4. [4] § Methods › Display properties and settings ↔ Fig04_PairedPulsesTest/code_analyze_PairedPulseParadigm_OSF.m, lines 1–17 · score 0.75 · Single biphasic pulses, double pulse, Paired pulse, temporal dependencies, simulate, summed
  5. [5] § Methods › Display properties and settings ↔ Fig03_TLMflicker/Figure3_quantifyTLM_osf.m, lines 1–25 · score 0.74 · temporal light modulation, flicker spikes, 0–255, ordinal, TLM, amplitude
  6. [6] § Results › Temporal independence (paired-pulse paradigm) ↔ Fig04_PairedPulsesTest/code_analyze_PairedPulseParadigm_OSF.m, lines 357–400 · score 0.72 · artificially doubling, double pulse, single pulse, simulation, spikes, amplitude
  7. [7] § Results › Transition times ↔ Fig01_Fig06C_Fig08_photodiodeData/plotdata_photodiode_Fig1_Fig4_Fig5.m, lines 47–141 · score 0.71 · duty cycle, peak luminance, luminance response, stimulus duration, extremely, horizontal
  8. [8] § Methods › Display properties and settings ↔ Fig10_saccadeTask/plotdata_intrasaccadic_Fig9.m, lines 267–334 · score 0.69 · flip command, critical latencies, saccade onset, boundary, executes, contingent
  9. [9] § Methods › Practical test 2: Intra-saccadic stimulation ↔ Fig10_saccadeTask/plotdata_intrasaccadic_Fig9.m, lines 49–66 · score 0.64 · eye tracking, velocity threshold, saccade detection, offline, algorithm
  10. [10] § Methods › Spatial uniformity ↔ Fig05_uniformity_angles_operatingtime/plotdata_photometer_Fig2.m, lines 10–33 · score 0.61 · operating temperature, luminance uniformity, viewing angle, IPS, LCD, Figure 5
  11. [11] § Methods › Temporal independence (paired-pulse paradigm) ↔ Fig04_PairedPulsesTest/code_analyze_PairedPulseParadigm_OSF.m, lines 357–400 · score 0.59 · double pulse, single pulse, prediction, summing, error, quantify
  12. [12] § Methods › Stimulus presentation ↔ Fig10_saccadeTask/plotdata_intrasaccadic_Fig9.m, lines 21–38 · score 0.58 · parallel port, photodiode signal, trigger
  13. [13] § Methods › Practical test 2: Intra-saccadic stimulation ↔ matlab/detect_saccade_2d_C_ONSET.cpp, lines 1–44 · score 0.57 · gaze position, retrieved, SDs, millisecond, algorithm, median
  14. [14] § Methods › Practical test 2: Intra-saccadic stimulation ↔ R/detect_saccade_for_R.c, lines 1–34 · score 0.56 · gaze position, retrieved, SDs, millisecond, algorithm, median
  15. [15] § Methods › Viewing angle ↔ Fig05_uniformity_angles_operatingtime/plotdata_photometer_Fig2.m, lines 10–33 · score 0.56 · horizontal viewing angle, azimuth, photometer, LCD, monitor, OLED
  16. [16] § Methods › Practical test 2: Intra-saccadic stimulation ↔ matlab/detect_saccade_2d_C_ONSET.cpp, lines 1–44 · score 0.55 · velocity threshold, saccade detection, SDs, algorithm, median, min
  17. [17] § Results › Practical test 1: Fast flicker stimulation ↔ Fig01_Fig06C_Fig08_photodiodeData/plotdata_photodiode_Fig1_Fig4_Fig5.m, lines 328–361 · score 0.55 · RIFT signal, photodiode signal, arbitrary, flickering, ms, cycles
  18. [18] § Methods › Transition times ↔ Fig01_Fig06C_Fig08_photodiodeData/plotdata_photodiode_Fig1_Fig4_Fig5.m, lines 47–141 · score 0.52 · peak luminance, stimulus duration, interval, rise, photodiode, cycle

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 · 521 lines · 20 KB · no license · 4 matches

  1. %% Test of 240 Hz OLED monitor: Analyzed eye-tracking & photodiode from experiment with intrasaccadic stimulation
  2. % This Matlab script generates Figure 6 of Dimigen & Stein, 2024
  3. % Code is provided solely to replicate our analysis, all rights reserved
  4. % The code is organized so that the analysis can be replicated without the need to download toolboxes
  5. %
  6. % [email hidden], 2024
  7. clear all, close all
  8. %% subfunctions needed
  9. addpath Violinplot-Matlab % from: https://github.com/bastibe/Violinplot-Matlab (DOI: 10.5281/zenodo.4559847)
  10. addpath eeglab_eyeeeg % EEGLAB (copy of version 2021.1) with the EYE-EEG extension (v1.0) installed
  11. eeglab; close % start EEGLAB % close the GUI window (not needed)
  12. % load custom colormap for plotting
  13. load colormap.mat cmap % cbrewer('seq','Blues', 256,[]);
  14. %% load logfile of the experiment (Matlab format)
  15. load('data_logfile/OLED_logfile_901.mat');
  16. %% Load integrated dataset (EEGLAB format) containing synchronized eye movement & photodiode data
  17. EEG = pop_loadset('filename','OLED_eeglab_synchronized_901.set','filepath','data_eeglab/');
  18. % Notes about this dataset
  19. % - integrated data was generated with the EYE-EEG toolbox (v.99)
  20. % - channel names should be self-explanatory
  21. % - photo didoe data was downsampled from the original 8000 Hz to now 2000 Hz
  22. % - eye-trackign data was upsampled from the original 1000 Hz to now 2000 Hz
  23. % - data is near-perfectly synchronized with error < 0.4 ms
  24. % Channels:
  25. % Channel 1: Photodiode signal (raw)
  26. % Channel 2: Left eye, horizontal gaze position (X)
  27. % Channel 3: Left eye, vertical gaze position (Y)
  28. % Channel 4: Received parallel port triggers
  29. % Channel 5: Eye velocity X (optional, only minimally smoothed)
  30. % Channel 6: Eye velocity Y (optional, only minimally smoothed)
  31. % Channel 7: eye velocity, 2D
  32. % Channel 8: Photodiode signal (normalized, range 0 to 1)
  33. %% Cut an initial set of epochs around the trigger marking that the saccade was detected online ("S99")
  34. % make the epoch long enough so it does not distort the median-based velocity
  35. % threshold computation by including predominantly saccade samples
  36. EEG = pop_epoch(EEG,{'s99'}, [-0.5 0.5], 'epochinfo', 'yes');
  37. EEG = pop_rmbase(EEG,[-200 -100],[],1); % note: remove baseline ONLY from photo channel not from eye-tracking data!
  38. %% Remove epochs with blinks (sub-zero gaze values)
  39. [~, ix_badepochs] = pop_eegthresh(EEG,1,[2 3],[1 1],[c.resx c.resy],EEG.xmin,EEG.xmax,0,0);
  40. %% Detect saccades with adaptive Engbert & Kliegl (2003) algorithm
  41. LAMBDA = 6; % velocity multiplier
  42. MINDUR = 20; % = 10 ms at 2000 Hz sampling rate
  43. SMOOTH = 1; % smooth velocity time series
  44. GLOABLTHRESH = 0; % compute velocity threshold individ. for each epoch
  45. MININTERVAL = 100; % has no effect here
  46. CLUSTERMODE = 1; % detect all saccades (can include post-sacc. oscillations)
  47. PLOTFIG = 0;
  48. ADDSACC = 1;
  49. ADDFIX = 1;
  50. degperpix = 0.0190; % degrees of visual angle per screen pixel
  51. % Note: since we have an upsampled 2 kHz sampling rate for the eye-tracking data,
  52. % even more velocity smoothing might be a good idea, the exact saccON to saccDETECT interval
  53. % will obviously always depend on the algorithm and parameters for offline
  54. % saccade detection, but this interval is not essential for the current
  55. % monitor test
  56. EEG = pop_detecteyemovements(EEG,[2 3],[],LAMBDA,MINDUR,degperpix,SMOOTH,GLOABLTHRESH,MININTERVAL,CLUSTERMODE,PLOTFIG,ADDSACC,ADDFIX);
  57. %% Plot the epoched data in EEGLAB
  58. pop_eegplot( EEG, 1, 1, 1); % note: click "Disply" --> "Remove DC Offset" to the gaze position channels properly
  59. %% Loop trough the epochs
  60. % - detect when OLED reaches 90% luminance in trial
  61. % - store epoch latencies
  62. for e = 1:size(EEG.data,3)
  63. % get onset of stim (onset = >90% of avg. sustained luminance of stimulus)
  64. epdata = squeeze(EEG.data(1,:,e));
  65. % normalize data using maximal peak (can be outlier due to flicker or noise)
  66. [epmx, mxsmp] = max(epdata);
  67. dataN = epdata ./ epmx;
  68. % now get actual sustained stim. luminance while the stim. is on (takes into account flicker/noise)
  69. ixstim = find(dataN > .80); % we define peak duration as values above 80% of "epmx"
  70. mlum = mean(dataN(ixstim)); % take mean luminance
  71. % stim onset: look for first point exceeding 90% of sustained stim. luminance
  72. LUMTHRESH_ON = 0.90;
  73. LUMTHRESH_OFF = 0.10;
  74. oled_on = find(dataN > LUMTHRESH_ON.*mlum);
  75. if ~isempty(oled_on)
  76. oled_on_ms = EEG.times(oled_on(1));
  77. else
  78. error('No onset found, there might be a problem')
  79. end
  80. % stimulus offset: once stim. has dropped below 10% again
  81. oled_off90 = oled_on(end);
  82. oled_below10 = dataN < LUMTHRESH_OFF.*mlum; % samples below 10%
  83. helpvec = false(1,size(EEG.data,2));
  84. helpvec(oled_off90:end) = true;
  85. oled_off10 = find(oled_below10 & helpvec); % get samples below 10% happening after lumin. has dropped again
  86. % get latency of last stimulus sample in ms
  87. oled_off90_ms = EEG.times(oled_off90);
  88. % did we find a proper offset?
  89. if ~isempty(oled_off10)
  90. oled_off10 = oled_off10(1);
  91. oled_off10_ms = EEG.times(oled_off10);
  92. else
  93. oled_off10 = NaN;
  94. oled_off10_ms = NaN;
  95. % warning('No offset <10 perc. found, maybe stim. was shown for too long?');
  96. end
  97. %% Control figure for onset/offset detection
  98. % figure; hold on; title(sprintf('Epoch: %i',e));
  99. % plot(EEG.times,epdata);
  100. % xline(oled_on_ms,'g')
  101. % xline(oled_off90_ms,'r')
  102. % xline(oled_off10_ms,'k:')
  103. % xlim([-30 80])
  104. fprintf('\nApprox. stim. lumin. in epoch %i was %.2f',e,mlum);
  105. %% Get infos for this epoch from EEG.epoch
  106. E = EEG.epoch(e);
  107. % E.eventtype
  108. ix_sac = find(ismember(E.eventtype,'saccade'));
  109. ix_bnd = find(ismember(E.eventtype,'s99'));
  110. ix_Son = find(ismember(E.eventtype,{'s20','s21'}));
  111. ix_Soff = find(ismember(E.eventtype,{'s30','s31'}));
  112. ix_fix = find(ismember(E.eventtype,'fixation'));
  113. % catch rare exception: ix_sac is empty
  114. if ~isempty(ix_sac)
  115. if length(ix_sac)>1
  116. lats = [E.eventlatency{ix_sac}];
  117. [~,ixs] = min(abs(lats)); % find saccade temporally closest to boundary trigger
  118. else
  119. ixs = 1;
  120. end
  121. ms_sac = E.eventlatency{ix_sac(ixs)};
  122. sacamp = E.eventsac_amplitude{ix_sac(ixs)};
  123. x_saccOn = E.eventsac_startpos_x{ix_sac(ixs)};
  124. y_saccOn = E.eventsac_startpos_y{ix_sac(ixs)};
  125. x_saccOff = E.eventsac_endpos_x{ix_sac(ixs)};
  126. y_saccOff = E.eventsac_endpos_y{ix_sac(ixs)};
  127. else % ix_sac empty?
  128. ms_sac = NaN;
  129. sacamp = NaN;
  130. x_saccOn = NaN;
  131. y_saccOn = NaN;
  132. x_saccOff = NaN;
  133. y_saccOff = NaN;
  134. end
  135. ms_bnd = E.eventlatency{ix_bnd(1)};
  136. ms_Son = E.eventlatency{ix_Son(1)};
  137. if ~isempty(ix_Soff)
  138. ms_Soff = E.eventlatency{ix_Soff(1)};
  139. else
  140. ms_Soff = NaN;
  141. end
  142. if ~isempty(ix_fix)
  143. ms_fix = E.eventlatency{ix_fix(2)};
  144. fix_x = E.eventfix_avgpos_x{ix_fix(2)};
  145. fix_y = E.eventfix_avgpos_y{ix_fix(2)};
  146. else
  147. ms_fix = NaN;
  148. fix_x = NaN;
  149. fix_y = NaN;
  150. end
  151. %% check for blinks in this epoch/trial
  152. xydata = EEG.data([2 3],:,e);
  153. isblink = any(xydata(:) < 0); % any blinks in this trial?
  154. %%
  155. trialinfo(e,1) = e;
  156. trialinfo(e,2) = ms_sac;
  157. trialinfo(e,3) = ms_bnd;
  158. trialinfo(e,4) = ms_Son; % on trigger
  159. trialinfo(e,5) = oled_on_ms; % actual on
  160. trialinfo(e,6) = ms_Soff; % off trigger
  161. trialinfo(e,7) = oled_off10_ms; % actual off
  162. trialinfo(e,8) = ms_fix;
  163. trialinfo(e,9) = fix_x;
  164. trialinfo(e,10) = fix_y;
  165. trialinfo(e,11) = sacamp;
  166. trialinfo(e,12) = fliplog(e,2); % trialnumber (just to check)
  167. trialinfo(e,13) = fliplog(e,12); % gaze X at saccade detection / bound. crossing
  168. trialinfo(e,14) = fliplog(e,13); % gaze Y at saccade detection / bound. crossing
  169. trialinfo(e,15) = fliplog(e,14); %
  170. trialinfo(e,16) = fliplog(e,15); %
  171. trialinfo(e,17) = isblink;
  172. trialinfo(e,18) = x_saccOn;
  173. trialinfo(e,19) = y_saccOn;
  174. trialinfo(e,20) = x_saccOff;
  175. trialinfo(e,21) = y_saccOff;
  176. if ~ismember(e,ix_badepochs)
  177. trialinfo(e,22) = 0; % good, gaze on screen
  178. else
  179. trialinfo(e,22) = 1; % bad, gaze temporarily lost or outside screen
  180. end
  181. % write normalized photo diode data into empty channel 8
  182. EEG.data(8,:,e) = dataN;
  183. end % go tru epochs
  184. % note: latencies for the stim. triggers have a temporal "pseudo-resolution" now, due
  185. % to the downsampling from 8K to 2K; round them again to nearest sample
  186. accu = 0.5;
  187. trialinfo(:,4) = round(trialinfo(:,4)./accu)*accu;
  188. % Add actual photo onsets and offsets as new EEG.event events
  189. % Example use of addevents:
  190. % EEG = addevents(EEG,[100 1 456 1; 200 1 789 2;],{'latency','duration','xxxx','epoch'},'ARRRRRRGGG');
  191. %% Get a subset of trials without problems (sanity checks)
  192. ixgood = trialinfo(:,11) > 16 ...
  193. & trialinfo(:,11) < 24 ... % sacc. amplitude not off by more than 4°
  194. & trialinfo(:,20) > c.boundary2xpix ... % sacc. of proper/sufficient amplitude to cross right boundary (at
  195. ...
  196. & trialinfo(:,2) < trialinfo(:,3) ... % saccOn before saccDetect (!)
  197. & trialinfo(:,7) > trialinfo(:,5) ... % stimOff after stimOn (!)
  198. & trialinfo(:,8) > trialinfo(:,2) ... % fixOn after saccOn (!)
  199. & ~isnan(trialinfo(:,2)) ... % at least 1 saccade event was found
  200. & ~isnan(trialinfo(:,8)) ... % at least 1 fixation event was found
  201. ...
  202. & ~isnan(trialinfo(:,6)) ... % a stim offset trigger was found
  203. & trialinfo(:,7) <= 198 ... % OLED offset (signal below 10% again) was detected within 200 ms of boundary crossing
  204. ...
  205. & trialinfo(:,2) > -30 ... % detected a saccade within -30 ms...
  206. & trialinfo(:,2) < 0 ... % ...to 0 ms relative to boundary trigger
  207. & trialinfo(:,22) == 0; % gaze data in epoch contains no out-of-monitor-area values
  208. %% Visualize the gaze and photo diode signal in "bad" trials
  209. % ixbad = find(~ismember(1:200, find(ixgood)))
  210. % for j = ixbad
  211. % EEG.epoch(j)
  212. % figure;
  213. % subplot(2,1,1); hold on, plot(EEG.data(2,:,j),'r-'); plot(EEG.data(3,:,j),'b-'); title(j) % gaze
  214. % subplot(2,1,2); hold on, plot(EEG.data(1,:,j),'k-'); title('Photodiode')
  215. % pause
  216. % close
  217. % end
  218. %% Make figure of single-trial latencies as dots
  219. figure;
  220. hold on; title('Critical latencies')
  221. plot(trialinfo(ixgood,2),'mo')
  222. plot(trialinfo(ixgood,3),'b.-')
  223. plot(trialinfo(ixgood,4),'cx')
  224. plot(trialinfo(ixgood,5),'ko')
  225. plot(trialinfo(ixgood,6),'m.')
  226. plot(trialinfo(ixgood,7),'b.')
  227. plot(trialinfo(ixgood,8),'r.')
  228. ylim([-20 60])
  229. yline(0,'k:')
  230. % #########################################################################
  231. %% Compute the most interesting latencies
  232. % #########################################################################
  233. fprintf('\n\nCritical latencies in the saccade-contingent experiment:\ns')
  234. % Interval (1): Saccade onset to saccade detected
  235. mean(trialinfo(ixgood,3)-trialinfo(ixgood,2)) % 444: 6.35 ms vs. 5.64 (445) vs. 4.714 ms (901)
  236. std(trialinfo(ixgood,3)-trialinfo(ixgood,2))
  237. % MS: 5.28 ms
  238. % SD: 1.84 ms
  239. % Interval (2): Saccade detected to flip command executed
  240. mean(trialinfo(ixgood,4)-trialinfo(ixgood,3)) % 444: 4.56 ms vs. 4.51 vs. 4.683
  241. std(trialinfo(ixgood,4)-trialinfo(ixgood,3))
  242. % MS: 4.69 ms
  243. % SD: 1.19 ms
  244. % Interval (3): Flip command executed to OLED reaches 90% luminance
  245. mean(trialinfo(ixgood,5)-trialinfo(ixgood,4)) % 444: 2.90 ms vs. 2.92 (of which (1000/240)/2) = 2.08 ms should be due to central position vs. 2.99 ms
  246. std(trialinfo(ixgood,5)-trialinfo(ixgood,4))
  247. % MS: 2.92 ms
  248. % SD: 0.29 ms
  249. % Interval (4): Saccade-contingent display change latency: Boundary to StimOn
  250. mean(trialinfo(ixgood,5))
  251. std(trialinfo(ixgood,5))
  252. % MS: 7.61 ms
  253. % SD: 1.18 ms
  254. median(trialinfo(ixgood,5))
  255. % median(trialinfo(ixgood,5))
  256. % min(trialinfo(ixgood,5))
  257. % max(trialinfo(ixgood,5))
  258. % Interval (5): Total time: Saccade onset until OLED reaches 90% luminance
  259. mean(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 444: 13.82 ms, 445: 13.07 ms, 901: 12.39 ms
  260. std(trialinfo(ixgood,5)-trialinfo(ixgood,2))
  261. % MS: 12.89 ms
  262. % SD: 2.25 ms
  263. median(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 901: 12 ms
  264. % min(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 444: 5 ms, 445: 5.5 ms, 901: 5.5
  265. % max(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 444: 20.5 ms, 445: 254 ms, 901: 21 ms
  266. % Extra-Time: 4: Fixation onset relative to OLED offset
  267. mean(trialinfo(ixgood,8)-trialinfo(ixgood,7)) % 444: 2.90 ms vs. 2.92 (of which (1000/240)/2) = 2.08 ms should be due to central position, 7.50 ms for 901!
  268. std(trialinfo(ixgood,8)-trialinfo(ixgood,7))
  269. % MS: 8.13 ms
  270. % SD: 3.58 ms
  271. % min(trialinfo(ixgood,8)-trialinfo(ixgood,7)) % -8
  272. % max(trialinfo(ixgood,8)-trialinfo(ixgood,7)) % +9
  273. % how many offsets were well-timed and not too late?
  274. sum(trialinfo(ixgood,8)-trialinfo(ixgood,7) > 0) % 72 well-timed; 901: 155!
  275. sum(trialinfo(ixgood,8)-trialinfo(ixgood,7) <= 0) % 99 slightly too late, 901: 6!
  276. fprintf('\n\nPercentage of trials remaining: %.3f', 100 * (sum(ixgood) / 200))
  277. % percentage of false alarms = stimOn happened before saccOn
  278. nFalseAlarm = sum(trialinfo(:,5)-trialinfo(:,2) <= 0)
  279. fprintf('\n\nTrials with a false alarm (premature change): %.3f', 100 * (nFalseAlarm / 200))
  280. saccdur = mean(trialinfo(ixgood,8)-trialinfo(ixgood,2)); % 60.36 ms
  281. stimdur = mean(trialinfo(ixgood,7)-trialinfo(ixgood,5)); % 39.33 ms
  282. saccperc = (stimdur/saccdur).*100;
  283. fprintf('\n\nMean Saccade Duration and Stimulus Duration: %.3f and %.3f ms', saccdur, stimdur)
  284. fprintf('\n\nStimulus was shown for %.3f percent of the entire saccade duration (as detected offline)', saccperc)
  285. %% Remove bad epochs from the EEG.data (i.e., those not found in "ixgood")
  286. ixkill = find(~ixgood);
  287. EEG = pop_selectevent(EEG,'omitepoch',ixkill,'deleteevents','off','deleteepochs','on','invertepochs','off');
  288. %% Re-code critical saccade as "saccadeCrit" in EEG.event
  289. % (to distinguish them from microsaccades/refixations/overshoot saccades)
  290. for e = 1:size(EEG.data,3)
  291. EP = EEG.epoch(e);
  292. nsacc = sum(ismember(EP.eventtype,'saccade'));
  293. ix = find(ismember(EP.eventtype,'saccade'));
  294. if nsacc > 0
  295. % recode name of first saccade, which should always be the critical one
  296. eventindex = EP.event(ix(1));
  297. EEG.event(eventindex).type = 'saccadeCrit';
  298. latency_ms = EP.eventlatency{ix(1)};
  299. if latency_ms < -30 || latency_ms > 1
  300. error('Something wrong here, implausible latency for critical saccade')
  301. end
  302. else
  303. error('epoch without saccade event!: %i',e)
  304. end
  305. end
  306. EEG = eeg_checkset(EEG,'eventconsistency'); % rebuild/update EEG.epoch
  307. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  308. %% MAKE BIG FIGURE (Figure 6 of manuscript
  309. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  310. SMOOTH = 1; % = do not do vertical smoothing across trials
  311. CHAN = 8;
  312. xLimits = [-20 65];
  313. LW = 1.5; % linewidth
  314. LW2 = 1.1;
  315. % EEG3: Cut new epochs around the (online) saccade detection event
  316. EEG3 = pop_epoch(EEG,{'s99'},[-0.030 0.070],'epochinfo','yes');
  317. % get ERPimage
  318. [outdata,outvar,outtrials] = pop_erpimage(EEG3,1,CHAN,[],'pDiode',SMOOTH,1,{'s20','s21'},[],'latency' ,'yerplabel','\muV','erp','on','cbar','on','topo', {[1] EEG.chanlocs EEG.chaninfo}); close;
  319. % outdata: nsamples * epochs
  320. % outvar: sorting variable
  321. % ERP averages
  322. ERP_s99_hgaze_median = median(EEG3.data(2,:,:),3);
  323. ERP_s99_velo_median = median(EEG3.data(7,:,:),3);
  324. ERP_s99_horVelo_median = median(EEG3.data(5,:,:),3);
  325. %% Data for VIOLIN plot
  326. % trialinfo(e,2) = ms_sac;
  327. % trialinfo(e,3) = ms_bnd;
  328. % trialinfo(e,4) = ms_Son; % on trigger
  329. % trialinfo(e,5) = oled_on_ms; % actual on
  330. % trialinfo(e,6) = ms_Soff; % off trigger
  331. % trialinfo(e,7) = oled_off10_ms; % actual off
  332. % trialinfo(e,8) = ms_fix;
  333. % data for violin plots (from good trials)
  334. viodata = [trialinfo(ixgood,2),trialinfo(ixgood,4),trialinfo(ixgood,5), trialinfo(ixgood,7), trialinfo(ixgood,8)];
  335. % get median values
  336. medi(1) = nanmedian(viodata(:,1));
  337. medi(2) = nanmedian(viodata(:,2));
  338. medi(3) = nanmedian(viodata(:,3));
  339. medi(4) = nanmedian(viodata(:,4));
  340. medi(5) = nanmedian(viodata(:,5));
  341. xmean(1) = nanmean(viodata(:,1));
  342. xmean(2) = nanmean(viodata(:,2));
  343. xmean(3) = nanmean(viodata(:,3));
  344. xmean(4) = nanmean(viodata(:,4));
  345. xmean(5) = nanmean(viodata(:,5));
  346. xstd(1) = nanstd(viodata(:,1));
  347. xstd(2) = nanstd(viodata(:,2));
  348. xstd(3) = nanstd(viodata(:,3));
  349. xstd(4) = nanstd(viodata(:,4));
  350. xstd(5) = nanstd(viodata(:,5));
  351. % get colors
  352. viocolors = [cmap(50,:); cmap(101,:); cmap(152,:); cmap(203,:); cmap(255,:)];
  353. %% CREATE FIGURE 6 OF MANUSSRIPT
  354. figure('Name','OLED: Big Figure')
  355. %% 1. Violin plot (using violinplot.m from B. Bechtold)
  356. subplot(3,1,1); hold on;
  357. vs = violinplot(viodata,[],...
  358. 'Orientation', 'horizontal',...
  359. 'ViolinColor',viocolors,...
  360. 'DataStyle', 'scatter',... % histogram, none...
  361. 'ShowMedian', true,...
  362. 'ShowMean', true,...
  363. 'MedianMarkerSize',60,...
  364. 'MarkerSize',6,... % data points, default is 24
  365. 'BoxColor',[.1 .1 .1],... % color for box-and-whiskers
  366. 'ShowNotches', false,...
  367. 'QuartileStyle','boxplot',... % , none
  368. 'HalfViolin','full',... % left, full
  369. 'QuartileStyle','boxplot'); % shadow. boxplot, none
  370. ylim([0.5 5.5])
  371. yticks(1:5)
  372. yticklabels({'Sacc. onset','Flip','Stim. ON (>90%)','Stim. OFF (<5%)','Fixation'})
  373. xlabel('Time relative to sacc. detection [ms]');
  374. xline(0,'k-','linewidth',LW) % detection time = 0 ms
  375. xline(medi(1),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % sacc detection
  376. xline(medi(2),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % flip
  377. xline(medi(3),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim at 90%
  378. xline(medi(4),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim at 95%
  379. xline(medi(5),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % fixation onset
  380. grid on;
  381. xlim(xLimits);
  382. set(gca,'XTick',xLimits(1):5:xLimits(2));
  383. box off
  384. FIGSIZE = [650 10 1090 920];
  385. set(findall(gcf,'-property','FontName'),'FontName','Arial');
  386. set(findall(gcf,'-property','FontSize'),'FontSize',12);
  387. set(gcf,'color','white')
  388. set(gcf,'Position',FIGSIZE)
  389. nanmedian(viodata(:,3))
  390. nanmean(viodata(:,3))
  391. %% 2. Average saccadic gaze position trajectory
  392. subplot(3,1,2); hold on;
  393. % yyaxis left
  394. plot(EEG3.times,ERP_s99_hgaze_median,'Color',cmap(206,:),'LineWidth',LW)
  395. xlim(xLimits)
  396. xline(0,'k-','linewidth',LW)
  397. yline(30,'k:','LineWidth',LW/2) % 30°/sec line
  398. grid on
  399. % ylabel('Eye velocity (°/s)')
  400. ylabel('Horiz. gaze position [px]')
  401. xlabel('Time relative to saccade detection (ms)')
  402. set(gca,'XTick',[xLimits(1):5:xLimits(2)]);
  403. xline(medi(1),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % sacc detection
  404. xline(medi(2),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % flip
  405. xline(medi(3),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim at 90%
  406. xline(medi(4),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim off (< 5%)
  407. xline(medi(5),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % fixation onset
  408. % limits for gaze:
  409. ylim([c.fixposLx-100 c.fixposRx+100])
  410. fill([medi(3) medi(4) medi(4) medi(3)],[c.fixposLx-100 c.fixposLx-100 c.fixposRx+100 c.fixposRx+100],[.4 .2 .1],'edgecolor','none','facealpha',0.2)
  411. % yyaxis right
  412. % plot(EEG3.times,ERP_s99_horVelo_median,'Color',cmap(56,:),'LineWidth',LW)
  413. % ylim([0 500])
  414. % ylabel('Eye velocity [deg/s]')
  415. %% 3. ERPIMAGE of single-trial photo diode responses
  416. h1 = subplot(3,1,3); hold on;
  417. img = outdata';
  418. imagesc(EEG3.times,1:size(EEG3.data,3),img);
  419. % plot sorting line
  420. plot(outvar,1:size(EEG3.data,3),'k-','LineWidth',LW)
  421. xline(0,'k-','linewidth',LW)
  422. ylabel('Trials')
  423. xlabel('Time relative to saccade detection (ms)')
  424. orgSize = get(gca,'Position'); % add colorbar without resizing
  425. colorbar
  426. set(gca,'Position',orgSize);
  427. colormap(cmap)
  428. set(gca,'XTick',[xLimits(1):5:xLimits(2)]);
  429. axis tight
  430. xlim(xLimits)
  431. grid on
  432. % resize figure
  433. set(gcf,'Position',[10 10 975 980]);
  434. %% export
  435. % EXPORTFIG = false;
  436. % if EXPORTFIG
  437. % addpath M:/Dropbox/_subfunc_master/export_fig_2018
  438. % export_fig(gcf,sprintf('G:/Meine Ablage/2024_MonitorTest/_Results_Figures/ISS_simple/ISS_Figure6.eps'),'-painters','-transparent','-pdf')
  439. % end
  440. fprintf('\nDone.')

plotdata_intrasaccadic_Fig9.m, no license · at the source

Overview

Authors: Olaf Dimigen1,2, Arne Stein1,2
ORCID iDs: Olaf Dimigen
  1. Department of Experimental Psychology, University of Groningen, Grote Kruisstraat 2/1, 9712 TS Groningen, The Netherlands
  2. Research School of Behavioural and Cognitive Neurosciences, Faculty of Science and Engineering, University of Groningen, Groningen, The Netherlands
Institutions: University of Groningen (Netherlands)
Journal: Behavior research methods, volume 58, issue 6, article 161
Dates: received 5 September 2024; accepted 14 April 2026; published online 11 May 2026; in print 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.3758/s13428-026-03034-9 · PMID 42115564 · PMCID PMC13161341 · OpenAlex W7160844750
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: EEG (modality), human (organism), methods / tools (subfield)
Methods: Connectivity, Statistics, Physiology & signal measures
Keywords: Laboratory monitor, Organic light-emitting diode (OLED), Visual psychophysics, Vision science, Gaze-contingent display updates, OLED temperature artifacts
MeSH: Artifacts*, Electroencephalography*, Eye-Tracking Technology*, Vision, Ocular*, Humans, Photic Stimulation (* major topic)
Topic: Organic Light-Emitting Diodes Research (Electrical and Electronic Engineering, Engineering), according to OpenAlex
Citations: cited by 1 paper (Europe PMC); 65 references in the paper

Abstract

The recent introduction of organic light-emitting diode (OLED) monitors with refresh rates of 240 Hz or more opens new possibilities for their use as precise stimulation devices in vision research, experimental psychology, and electrophysiology. These affordable high-speed monitors, targeted at video gamers, promise several advantages over cathode ray tube (CRT) and liquid crystal display (LCD) monitors. Unlike LCDs, OLEDs have self-emitting pixels that can show true black, resulting in superior contrast, a broad color spectrum, and wide viewing angles. More importantly, the latest OLEDs offer excellent timing properties with minimal input lag and rapid transition times. However, OLED technology also has potential drawbacks, such as auto-brightness limiting (ABL), where luminance changes with the number of illuminated pixels. This study characterized a 240 Hz OLED monitor (ASUS PG27AQDM) in terms of its timing, temporal independence, spatial uniformity, viewing angles, warm-up time, and ABL behavior, and compared it with CRTs and LCDs. Results confirm excellent temporal performance, with CRT-like transition times, wide viewing angles, and good spatial uniformity. We show that ABL can be prevented with appropriate settings. However, we also report a novel type of luminance artifact on OLEDs, where high-contrast stimuli, shown for long durations, can create image persistence via localized warming or cooling of the panel. Finally, we demonstrate the monitor’s benefits in two time-critical paradigms: rapid invisible flicker tagging (RIFT) and saccade-contingent display changes. The latest consumer OLEDs provide precise and cost-effective stimulation devices for time-critical experiments, although some caution is warranted in experiments involving long exposures to high-contrast stimuli.

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

Repositories

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

richardschweitzer/OnlineSaccadeDetection

License: GPL-3.0
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Commit: bad52ff7ad164abf3795fbf6476f162d42535e25, 29 October 2024
Languages: R (3), C (2), C/C++ (2), MATLAB (2), C++ (1), Python (1)
Size: 22 files, 11 scripts
Software Heritage: not archived
Found in: the text, “Practical test 2: Intra-saccadic stimulation”
Holds: README, license file
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (1 file), NumPy (1 file), Psychtoolbox (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers
  • 28 September 2026: the link answers
13 files

OSF 8h4fg

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Languages: MATLAB (6)
Size: 13 files, 6 scripts
Software Heritage: not checked
Found in: “Data availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
  • 28 September 2026: the link answers (HTTP 200)
6 files
At the source: osf.io/8h4fg/

Code availability

Code is available; see statement regarding availability of data and materials.

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

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:

  • 2 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 17 scripts, each with its path and the digest of its content;
  • 18 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

Data and MATLAB code to reproduce all results and figures are available at https://osf.io/8h4fg/

Code is available; see statement regarding availability of data and materials.

Reproduced under the paper's license (CC BY), 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 2, 28 September 2026

  • Publisher: n/a → Springer Science+Business Media

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 2 authors, 6 keywords, 6 MeSH terms, 51 references.

Cite

This paper

Dimigen, O., & Stein, A. (2026). Advantages and artifacts of high-speed OLED monitors for vision, eye-tracking, and EEG research. Behavior research methods, 58(6), 161. https://doi.org/10.3758/s13428-026-03034-9

BibTeX

@article{dimigen2026advantages,
author = {Dimigen, Olaf and Stein, Arne},
title = {{Advantages and artifacts of high-speed OLED monitors for vision, eye-tracking, and EEG research}},
journal = {Behavior research methods},
year = {2026},
month = may,
volume = {58},
number = {6},
pages = {161},
publisher = {Springer Science+Business Media},
issn = {1554-351X},
doi = {10.3758/s13428-026-03034-9},
url = {https://doi.org/10.3758/s13428-026-03034-9},
pmid = {42115564},
pmcid = {PMC13161341}
}

RIS

TY - JOUR
AU - Dimigen, Olaf
AU - Stein, Arne
TI - Advantages and artifacts of high-speed OLED monitors for vision, eye-tracking, and EEG research
T2 - Behavior research methods
J2 - Behav Res Methods
PY - 2026
DA - 2026/05/11
VL - 58
IS - 6
SP - 161
SN - 1554-351X
PB - Springer Science+Business Media
DO - 10.3758/s13428-026-03034-9
UR - https://doi.org/10.3758/s13428-026-03034-9
LA - en
ER -

CSL-JSON

{
"id": "10.3758/s13428-026-03034-9",
"type": "article-journal",
"title": "Advantages and artifacts of high-speed OLED monitors for vision, eye-tracking, and EEG research",
"container-title": "Behavior research methods",
"author": [
{
"family": "Dimigen",
"given": "Olaf"
},
{
"family": "Stein",
"given": "Arne"
}
],
"container-title-short": "Behav Res Methods",
"volume": "58",
"issue": "6",
"page": "161",
"DOI": "10.3758/s13428-026-03034-9",
"PMID": "42115564",
"PMCID": "PMC13161341",
"ISSN": "1554-351X",
"publisher": "Springer Science+Business Media",
"URL": "https://doi.org/10.3758/s13428-026-03034-9",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
11
]
]
}
}

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.1126/sciadv.aea3919 [code]
Hierarchical brain dynamics supporting visual perceptual transitions.
Journal: Science advances
In common: Psychtoolbox, Statistics and Machine Learning Toolbox, Matplotlib, 1 other tool, 3 references
[2] doi:10.1038/s41467-026-73878-4 [code]
Neural Response to Familiar Names Predicts Outcome of Comatose ICU Patients: A Prospective Observational Cohort Study.
Journal: Nature communications
In common: Violinplot-Matlab, Curve Fitting Toolbox, EEGLAB, 2 other tools, EEG
[3] doi:10.1111/psyp.70362 [code]
Pupil Constriction Causes Activity in the Human Retina and Visual System.
Journal: Psychophysiology
In common: Matplotlib, NumPy, EEG, author Olaf Dimigen
[4] doi:10.1038/s41562-026-02533-1 [code]
Fluctuations in arousal reflect latent state transitions that facilitate behavioural optimization.
Journal: Nature human behaviour
In common: Psychtoolbox, EEGLAB, Statistics and Machine Learning Toolbox, EEG, 1 reference
[5] 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: Violinplot-Matlab, EEGLAB, Statistics and Machine Learning Toolbox, 2 other tools, EEG
[6] doi:10.1038/s41467-026-71151-2 [code]
Common and distinct neural correlates of social interaction processing and theory of mind in narratives.
Journal: Nature communications
In common: Violinplot-Matlab, Psychtoolbox, Statistics and Machine Learning Toolbox, 2 other tools
[7] doi:10.1038/s41467-026-75490-y [code]
Topographically organized dorsal raphe activity modulates forebrain sensory-motor representations and contributes to defensive behaviors.
Journal: Nature communications
In common: Violinplot-Matlab, Curve Fitting Toolbox, EEGLAB, 1 other tool
[8] doi:10.1038/s41467-026-76306-9 [code]
Non-invasive characterization of perivascular subarachnoid spaces.
Journal: Nature communications
In common: Violinplot-Matlab, Curve Fitting Toolbox, Statistics and Machine Learning Toolbox, 2 other tools
[9] doi:10.1038/s41467-026-72935-2 [code]
Spindle neurons in human cortex possess distinctive firing properties and transcriptomic signatures.
Journal: Nature communications
In common: Violinplot-Matlab, Curve Fitting Toolbox, Statistics and Machine Learning Toolbox, 2 other tools
[10] doi:10.1002/hbm.70602 [code]
Neuroimaging Correlates of Post-Stroke Pain After Ischemic Stroke: Secondary Analysis of the INSPiRE-TMS Trial.
Journal: Human brain mapping
In common: Psychtoolbox, Curve Fitting Toolbox, Statistics and Machine Learning Toolbox, 2 other tools

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.