Advantages and artifacts of high-speed OLED monitors for vision, eye-tracking, and EEG research.
The 18 matches
- [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] § 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] § 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] § 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] § 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] § 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] § 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] § 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] § 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] § 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] § 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] § Methods › Stimulus presentation ↔ Fig10_saccadeTask/plotdata_intrasaccadic_Fig9.m, lines 21–38 · score 0.58 · parallel port, photodiode signal, trigger
- [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] § 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] § 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] § 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] § 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] § 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
- %% Test of 240 Hz OLED monitor: Analyzed eye-tracking & photodiode from experiment with intrasaccadic stimulation
- % This Matlab script generates Figure 6 of Dimigen & Stein, 2024
- % Code is provided solely to replicate our analysis, all rights reserved
- % The code is organized so that the analysis can be replicated without the need to download toolboxes
- %
- % [email hidden], 2024
- clear all, close all
- %% subfunctions needed
- addpath Violinplot-Matlab % from: https://github.com/bastibe/Violinplot-Matlab (DOI: 10.5281/zenodo.4559847)
- addpath eeglab_eyeeeg % EEGLAB (copy of version 2021.1) with the EYE-EEG extension (v1.0) installed
- eeglab; close % start EEGLAB % close the GUI window (not needed)
- % load custom colormap for plotting
- load colormap.mat cmap % cbrewer('seq','Blues', 256,[]);
- %% load logfile of the experiment (Matlab format)
- load('data_logfile/OLED_logfile_901.mat');
- %% Load integrated dataset (EEGLAB format) containing synchronized eye movement & photodiode data
- EEG = pop_loadset('filename','OLED_eeglab_synchronized_901.set','filepath','data_eeglab/');
- % Notes about this dataset
- % - integrated data was generated with the EYE-EEG toolbox (v.99)
- % - channel names should be self-explanatory
- % - photo didoe data was downsampled from the original 8000 Hz to now 2000 Hz
- % - eye-trackign data was upsampled from the original 1000 Hz to now 2000 Hz
- % - data is near-perfectly synchronized with error < 0.4 ms
- % Channels:
- % Channel 1: Photodiode signal (raw)
- % Channel 2: Left eye, horizontal gaze position (X)
- % Channel 3: Left eye, vertical gaze position (Y)
- % Channel 4: Received parallel port triggers
- % Channel 5: Eye velocity X (optional, only minimally smoothed)
- % Channel 6: Eye velocity Y (optional, only minimally smoothed)
- % Channel 7: eye velocity, 2D
- % Channel 8: Photodiode signal (normalized, range 0 to 1)
- %% Cut an initial set of epochs around the trigger marking that the saccade was detected online ("S99")
- % make the epoch long enough so it does not distort the median-based velocity
- % threshold computation by including predominantly saccade samples
- EEG = pop_epoch(EEG,{'s99'}, [-0.5 0.5], 'epochinfo', 'yes');
- EEG = pop_rmbase(EEG,[-200 -100],[],1); % note: remove baseline ONLY from photo channel not from eye-tracking data!
- %% Remove epochs with blinks (sub-zero gaze values)
- [~, ix_badepochs] = pop_eegthresh(EEG,1,[2 3],[1 1],[c.resx c.resy],EEG.xmin,EEG.xmax,0,0);
- %% Detect saccades with adaptive Engbert & Kliegl (2003) algorithm
- LAMBDA = 6; % velocity multiplier
- MINDUR = 20; % = 10 ms at 2000 Hz sampling rate
- SMOOTH = 1; % smooth velocity time series
- GLOABLTHRESH = 0; % compute velocity threshold individ. for each epoch
- MININTERVAL = 100; % has no effect here
- CLUSTERMODE = 1; % detect all saccades (can include post-sacc. oscillations)
- PLOTFIG = 0;
- ADDSACC = 1;
- ADDFIX = 1;
- degperpix = 0.0190; % degrees of visual angle per screen pixel
- % Note: since we have an upsampled 2 kHz sampling rate for the eye-tracking data,
- % even more velocity smoothing might be a good idea, the exact saccON to saccDETECT interval
- % will obviously always depend on the algorithm and parameters for offline
- % saccade detection, but this interval is not essential for the current
- % monitor test
- EEG = pop_detecteyemovements(EEG,[2 3],[],LAMBDA,MINDUR,degperpix,SMOOTH,GLOABLTHRESH,MININTERVAL,CLUSTERMODE,PLOTFIG,ADDSACC,ADDFIX);
- %% Plot the epoched data in EEGLAB
- pop_eegplot( EEG, 1, 1, 1); % note: click "Disply" --> "Remove DC Offset" to the gaze position channels properly
- %% Loop trough the epochs
- % - detect when OLED reaches 90% luminance in trial
- % - store epoch latencies
- for e = 1:size(EEG.data,3)
- % get onset of stim (onset = >90% of avg. sustained luminance of stimulus)
- epdata = squeeze(EEG.data(1,:,e));
- % normalize data using maximal peak (can be outlier due to flicker or noise)
- [epmx, mxsmp] = max(epdata);
- dataN = epdata ./ epmx;
- % now get actual sustained stim. luminance while the stim. is on (takes into account flicker/noise)
- ixstim = find(dataN > .80); % we define peak duration as values above 80% of "epmx"
- mlum = mean(dataN(ixstim)); % take mean luminance
- % stim onset: look for first point exceeding 90% of sustained stim. luminance
- LUMTHRESH_ON = 0.90;
- LUMTHRESH_OFF = 0.10;
- oled_on = find(dataN > LUMTHRESH_ON.*mlum);
- if ~isempty(oled_on)
- oled_on_ms = EEG.times(oled_on(1));
- else
- error('No onset found, there might be a problem')
- end
- % stimulus offset: once stim. has dropped below 10% again
- oled_off90 = oled_on(end);
- oled_below10 = dataN < LUMTHRESH_OFF.*mlum; % samples below 10%
- helpvec = false(1,size(EEG.data,2));
- helpvec(oled_off90:end) = true;
- oled_off10 = find(oled_below10 & helpvec); % get samples below 10% happening after lumin. has dropped again
- % get latency of last stimulus sample in ms
- oled_off90_ms = EEG.times(oled_off90);
- % did we find a proper offset?
- if ~isempty(oled_off10)
- oled_off10 = oled_off10(1);
- oled_off10_ms = EEG.times(oled_off10);
- else
- oled_off10 = NaN;
- oled_off10_ms = NaN;
- % warning('No offset <10 perc. found, maybe stim. was shown for too long?');
- end
- %% Control figure for onset/offset detection
- % figure; hold on; title(sprintf('Epoch: %i',e));
- % plot(EEG.times,epdata);
- % xline(oled_on_ms,'g')
- % xline(oled_off90_ms,'r')
- % xline(oled_off10_ms,'k:')
- % xlim([-30 80])
- fprintf('\nApprox. stim. lumin. in epoch %i was %.2f',e,mlum);
- %% Get infos for this epoch from EEG.epoch
- E = EEG.epoch(e);
- % E.eventtype
- ix_sac = find(ismember(E.eventtype,'saccade'));
- ix_bnd = find(ismember(E.eventtype,'s99'));
- ix_Son = find(ismember(E.eventtype,{'s20','s21'}));
- ix_Soff = find(ismember(E.eventtype,{'s30','s31'}));
- ix_fix = find(ismember(E.eventtype,'fixation'));
- % catch rare exception: ix_sac is empty
- if ~isempty(ix_sac)
- if length(ix_sac)>1
- lats = [E.eventlatency{ix_sac}];
- [~,ixs] = min(abs(lats)); % find saccade temporally closest to boundary trigger
- else
- ixs = 1;
- end
- ms_sac = E.eventlatency{ix_sac(ixs)};
- sacamp = E.eventsac_amplitude{ix_sac(ixs)};
- x_saccOn = E.eventsac_startpos_x{ix_sac(ixs)};
- y_saccOn = E.eventsac_startpos_y{ix_sac(ixs)};
- x_saccOff = E.eventsac_endpos_x{ix_sac(ixs)};
- y_saccOff = E.eventsac_endpos_y{ix_sac(ixs)};
- else % ix_sac empty?
- ms_sac = NaN;
- sacamp = NaN;
- x_saccOn = NaN;
- y_saccOn = NaN;
- x_saccOff = NaN;
- y_saccOff = NaN;
- end
- ms_bnd = E.eventlatency{ix_bnd(1)};
- ms_Son = E.eventlatency{ix_Son(1)};
- if ~isempty(ix_Soff)
- ms_Soff = E.eventlatency{ix_Soff(1)};
- else
- ms_Soff = NaN;
- end
- if ~isempty(ix_fix)
- ms_fix = E.eventlatency{ix_fix(2)};
- fix_x = E.eventfix_avgpos_x{ix_fix(2)};
- fix_y = E.eventfix_avgpos_y{ix_fix(2)};
- else
- ms_fix = NaN;
- fix_x = NaN;
- fix_y = NaN;
- end
- %% check for blinks in this epoch/trial
- xydata = EEG.data([2 3],:,e);
- isblink = any(xydata(:) < 0); % any blinks in this trial?
- %%
- trialinfo(e,1) = e;
- trialinfo(e,2) = ms_sac;
- trialinfo(e,3) = ms_bnd;
- trialinfo(e,4) = ms_Son; % on trigger
- trialinfo(e,5) = oled_on_ms; % actual on
- trialinfo(e,6) = ms_Soff; % off trigger
- trialinfo(e,7) = oled_off10_ms; % actual off
- trialinfo(e,8) = ms_fix;
- trialinfo(e,9) = fix_x;
- trialinfo(e,10) = fix_y;
- trialinfo(e,11) = sacamp;
- trialinfo(e,12) = fliplog(e,2); % trialnumber (just to check)
- trialinfo(e,13) = fliplog(e,12); % gaze X at saccade detection / bound. crossing
- trialinfo(e,14) = fliplog(e,13); % gaze Y at saccade detection / bound. crossing
- trialinfo(e,15) = fliplog(e,14); %
- trialinfo(e,16) = fliplog(e,15); %
- trialinfo(e,17) = isblink;
- trialinfo(e,18) = x_saccOn;
- trialinfo(e,19) = y_saccOn;
- trialinfo(e,20) = x_saccOff;
- trialinfo(e,21) = y_saccOff;
- if ~ismember(e,ix_badepochs)
- trialinfo(e,22) = 0; % good, gaze on screen
- else
- trialinfo(e,22) = 1; % bad, gaze temporarily lost or outside screen
- end
- % write normalized photo diode data into empty channel 8
- EEG.data(8,:,e) = dataN;
- end % go tru epochs
- % note: latencies for the stim. triggers have a temporal "pseudo-resolution" now, due
- % to the downsampling from 8K to 2K; round them again to nearest sample
- accu = 0.5;
- trialinfo(:,4) = round(trialinfo(:,4)./accu)*accu;
- % Add actual photo onsets and offsets as new EEG.event events
- % Example use of addevents:
- % EEG = addevents(EEG,[100 1 456 1; 200 1 789 2;],{'latency','duration','xxxx','epoch'},'ARRRRRRGGG');
- %% Get a subset of trials without problems (sanity checks)
- ixgood = trialinfo(:,11) > 16 ...
- & trialinfo(:,11) < 24 ... % sacc. amplitude not off by more than 4°
- & trialinfo(:,20) > c.boundary2xpix ... % sacc. of proper/sufficient amplitude to cross right boundary (at
- ...
- & trialinfo(:,2) < trialinfo(:,3) ... % saccOn before saccDetect (!)
- & trialinfo(:,7) > trialinfo(:,5) ... % stimOff after stimOn (!)
- & trialinfo(:,8) > trialinfo(:,2) ... % fixOn after saccOn (!)
- & ~isnan(trialinfo(:,2)) ... % at least 1 saccade event was found
- & ~isnan(trialinfo(:,8)) ... % at least 1 fixation event was found
- ...
- & ~isnan(trialinfo(:,6)) ... % a stim offset trigger was found
- & trialinfo(:,7) <= 198 ... % OLED offset (signal below 10% again) was detected within 200 ms of boundary crossing
- ...
- & trialinfo(:,2) > -30 ... % detected a saccade within -30 ms...
- & trialinfo(:,2) < 0 ... % ...to 0 ms relative to boundary trigger
- & trialinfo(:,22) == 0; % gaze data in epoch contains no out-of-monitor-area values
- %% Visualize the gaze and photo diode signal in "bad" trials
- % ixbad = find(~ismember(1:200, find(ixgood)))
- % for j = ixbad
- % EEG.epoch(j)
- % figure;
- % subplot(2,1,1); hold on, plot(EEG.data(2,:,j),'r-'); plot(EEG.data(3,:,j),'b-'); title(j) % gaze
- % subplot(2,1,2); hold on, plot(EEG.data(1,:,j),'k-'); title('Photodiode')
- % pause
- % close
- % end
- %% Make figure of single-trial latencies as dots
- figure;
- hold on; title('Critical latencies')
- plot(trialinfo(ixgood,2),'mo')
- plot(trialinfo(ixgood,3),'b.-')
- plot(trialinfo(ixgood,4),'cx')
- plot(trialinfo(ixgood,5),'ko')
- plot(trialinfo(ixgood,6),'m.')
- plot(trialinfo(ixgood,7),'b.')
- plot(trialinfo(ixgood,8),'r.')
- ylim([-20 60])
- yline(0,'k:')
- % #########################################################################
- %% Compute the most interesting latencies
- % #########################################################################
- fprintf('\n\nCritical latencies in the saccade-contingent experiment:\ns')
- % Interval (1): Saccade onset to saccade detected
- mean(trialinfo(ixgood,3)-trialinfo(ixgood,2)) % 444: 6.35 ms vs. 5.64 (445) vs. 4.714 ms (901)
- std(trialinfo(ixgood,3)-trialinfo(ixgood,2))
- % MS: 5.28 ms
- % SD: 1.84 ms
- % Interval (2): Saccade detected to flip command executed
- mean(trialinfo(ixgood,4)-trialinfo(ixgood,3)) % 444: 4.56 ms vs. 4.51 vs. 4.683
- std(trialinfo(ixgood,4)-trialinfo(ixgood,3))
- % MS: 4.69 ms
- % SD: 1.19 ms
- % Interval (3): Flip command executed to OLED reaches 90% luminance
- 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
- std(trialinfo(ixgood,5)-trialinfo(ixgood,4))
- % MS: 2.92 ms
- % SD: 0.29 ms
- % Interval (4): Saccade-contingent display change latency: Boundary to StimOn
- mean(trialinfo(ixgood,5))
- std(trialinfo(ixgood,5))
- % MS: 7.61 ms
- % SD: 1.18 ms
- median(trialinfo(ixgood,5))
- % median(trialinfo(ixgood,5))
- % min(trialinfo(ixgood,5))
- % max(trialinfo(ixgood,5))
- % Interval (5): Total time: Saccade onset until OLED reaches 90% luminance
- mean(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 444: 13.82 ms, 445: 13.07 ms, 901: 12.39 ms
- std(trialinfo(ixgood,5)-trialinfo(ixgood,2))
- % MS: 12.89 ms
- % SD: 2.25 ms
- median(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 901: 12 ms
- % min(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 444: 5 ms, 445: 5.5 ms, 901: 5.5
- % max(trialinfo(ixgood,5)-trialinfo(ixgood,2)) % 444: 20.5 ms, 445: 254 ms, 901: 21 ms
- % Extra-Time: 4: Fixation onset relative to OLED offset
- 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!
- std(trialinfo(ixgood,8)-trialinfo(ixgood,7))
- % MS: 8.13 ms
- % SD: 3.58 ms
- % min(trialinfo(ixgood,8)-trialinfo(ixgood,7)) % -8
- % max(trialinfo(ixgood,8)-trialinfo(ixgood,7)) % +9
- % how many offsets were well-timed and not too late?
- sum(trialinfo(ixgood,8)-trialinfo(ixgood,7) > 0) % 72 well-timed; 901: 155!
- sum(trialinfo(ixgood,8)-trialinfo(ixgood,7) <= 0) % 99 slightly too late, 901: 6!
- fprintf('\n\nPercentage of trials remaining: %.3f', 100 * (sum(ixgood) / 200))
- % percentage of false alarms = stimOn happened before saccOn
- nFalseAlarm = sum(trialinfo(:,5)-trialinfo(:,2) <= 0)
- fprintf('\n\nTrials with a false alarm (premature change): %.3f', 100 * (nFalseAlarm / 200))
- saccdur = mean(trialinfo(ixgood,8)-trialinfo(ixgood,2)); % 60.36 ms
- stimdur = mean(trialinfo(ixgood,7)-trialinfo(ixgood,5)); % 39.33 ms
- saccperc = (stimdur/saccdur).*100;
- fprintf('\n\nMean Saccade Duration and Stimulus Duration: %.3f and %.3f ms', saccdur, stimdur)
- fprintf('\n\nStimulus was shown for %.3f percent of the entire saccade duration (as detected offline)', saccperc)
- %% Remove bad epochs from the EEG.data (i.e., those not found in "ixgood")
- ixkill = find(~ixgood);
- EEG = pop_selectevent(EEG,'omitepoch',ixkill,'deleteevents','off','deleteepochs','on','invertepochs','off');
- %% Re-code critical saccade as "saccadeCrit" in EEG.event
- % (to distinguish them from microsaccades/refixations/overshoot saccades)
- for e = 1:size(EEG.data,3)
- EP = EEG.epoch(e);
- nsacc = sum(ismember(EP.eventtype,'saccade'));
- ix = find(ismember(EP.eventtype,'saccade'));
- if nsacc > 0
- % recode name of first saccade, which should always be the critical one
- eventindex = EP.event(ix(1));
- EEG.event(eventindex).type = 'saccadeCrit';
- latency_ms = EP.eventlatency{ix(1)};
- if latency_ms < -30 || latency_ms > 1
- error('Something wrong here, implausible latency for critical saccade')
- end
- else
- error('epoch without saccade event!: %i',e)
- end
- end
- EEG = eeg_checkset(EEG,'eventconsistency'); % rebuild/update EEG.epoch
- % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %% MAKE BIG FIGURE (Figure 6 of manuscript
- % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- SMOOTH = 1; % = do not do vertical smoothing across trials
- CHAN = 8;
- xLimits = [-20 65];
- LW = 1.5; % linewidth
- LW2 = 1.1;
- % EEG3: Cut new epochs around the (online) saccade detection event
- EEG3 = pop_epoch(EEG,{'s99'},[-0.030 0.070],'epochinfo','yes');
- % get ERPimage
- [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;
- % outdata: nsamples * epochs
- % outvar: sorting variable
- % ERP averages
- ERP_s99_hgaze_median = median(EEG3.data(2,:,:),3);
- ERP_s99_velo_median = median(EEG3.data(7,:,:),3);
- ERP_s99_horVelo_median = median(EEG3.data(5,:,:),3);
- %% Data for VIOLIN plot
- % trialinfo(e,2) = ms_sac;
- % trialinfo(e,3) = ms_bnd;
- % trialinfo(e,4) = ms_Son; % on trigger
- % trialinfo(e,5) = oled_on_ms; % actual on
- % trialinfo(e,6) = ms_Soff; % off trigger
- % trialinfo(e,7) = oled_off10_ms; % actual off
- % trialinfo(e,8) = ms_fix;
- % data for violin plots (from good trials)
- viodata = [trialinfo(ixgood,2),trialinfo(ixgood,4),trialinfo(ixgood,5), trialinfo(ixgood,7), trialinfo(ixgood,8)];
- % get median values
- medi(1) = nanmedian(viodata(:,1));
- medi(2) = nanmedian(viodata(:,2));
- medi(3) = nanmedian(viodata(:,3));
- medi(4) = nanmedian(viodata(:,4));
- medi(5) = nanmedian(viodata(:,5));
- xmean(1) = nanmean(viodata(:,1));
- xmean(2) = nanmean(viodata(:,2));
- xmean(3) = nanmean(viodata(:,3));
- xmean(4) = nanmean(viodata(:,4));
- xmean(5) = nanmean(viodata(:,5));
- xstd(1) = nanstd(viodata(:,1));
- xstd(2) = nanstd(viodata(:,2));
- xstd(3) = nanstd(viodata(:,3));
- xstd(4) = nanstd(viodata(:,4));
- xstd(5) = nanstd(viodata(:,5));
- % get colors
- viocolors = [cmap(50,:); cmap(101,:); cmap(152,:); cmap(203,:); cmap(255,:)];
- %% CREATE FIGURE 6 OF MANUSSRIPT
- figure('Name','OLED: Big Figure')
- %% 1. Violin plot (using violinplot.m from B. Bechtold)
- subplot(3,1,1); hold on;
- vs = violinplot(viodata,[],...
- 'Orientation', 'horizontal',...
- 'ViolinColor',viocolors,...
- 'DataStyle', 'scatter',... % histogram, none...
- 'ShowMedian', true,...
- 'ShowMean', true,...
- 'MedianMarkerSize',60,...
- 'MarkerSize',6,... % data points, default is 24
- 'BoxColor',[.1 .1 .1],... % color for box-and-whiskers
- 'ShowNotches', false,...
- 'QuartileStyle','boxplot',... % , none
- 'HalfViolin','full',... % left, full
- 'QuartileStyle','boxplot'); % shadow. boxplot, none
- ylim([0.5 5.5])
- yticks(1:5)
- yticklabels({'Sacc. onset','Flip','Stim. ON (>90%)','Stim. OFF (<5%)','Fixation'})
- xlabel('Time relative to sacc. detection [ms]');
- xline(0,'k-','linewidth',LW) % detection time = 0 ms
- xline(medi(1),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % sacc detection
- xline(medi(2),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % flip
- xline(medi(3),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim at 90%
- xline(medi(4),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim at 95%
- xline(medi(5),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % fixation onset
- grid on;
- xlim(xLimits);
- set(gca,'XTick',xLimits(1):5:xLimits(2));
- box off
- FIGSIZE = [650 10 1090 920];
- set(findall(gcf,'-property','FontName'),'FontName','Arial');
- set(findall(gcf,'-property','FontSize'),'FontSize',12);
- set(gcf,'color','white')
- set(gcf,'Position',FIGSIZE)
- nanmedian(viodata(:,3))
- nanmean(viodata(:,3))
- %% 2. Average saccadic gaze position trajectory
- subplot(3,1,2); hold on;
- % yyaxis left
- plot(EEG3.times,ERP_s99_hgaze_median,'Color',cmap(206,:),'LineWidth',LW)
- xlim(xLimits)
- xline(0,'k-','linewidth',LW)
- yline(30,'k:','LineWidth',LW/2) % 30°/sec line
- grid on
- % ylabel('Eye velocity (°/s)')
- ylabel('Horiz. gaze position [px]')
- xlabel('Time relative to saccade detection (ms)')
- set(gca,'XTick',[xLimits(1):5:xLimits(2)]);
- xline(medi(1),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % sacc detection
- xline(medi(2),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % flip
- xline(medi(3),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim at 90%
- xline(medi(4),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % stim off (< 5%)
- xline(medi(5),'Color',[.2 .2 .2],'linestyle',':','linewidth',LW2) % fixation onset
- % limits for gaze:
- ylim([c.fixposLx-100 c.fixposRx+100])
- 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)
- % yyaxis right
- % plot(EEG3.times,ERP_s99_horVelo_median,'Color',cmap(56,:),'LineWidth',LW)
- % ylim([0 500])
- % ylabel('Eye velocity [deg/s]')
- %% 3. ERPIMAGE of single-trial photo diode responses
- h1 = subplot(3,1,3); hold on;
- img = outdata';
- imagesc(EEG3.times,1:size(EEG3.data,3),img);
- % plot sorting line
- plot(outvar,1:size(EEG3.data,3),'k-','LineWidth',LW)
- xline(0,'k-','linewidth',LW)
- ylabel('Trials')
- xlabel('Time relative to saccade detection (ms)')
- orgSize = get(gca,'Position'); % add colorbar without resizing
- colorbar
- set(gca,'Position',orgSize);
- colormap(cmap)
- set(gca,'XTick',[xLimits(1):5:xLimits(2)]);
- axis tight
- xlim(xLimits)
- grid on
- % resize figure
- set(gcf,'Position',[10 10 975 980]);
- %% export
- % EXPORTFIG = false;
- % if EXPORTFIG
- % addpath M:/Dropbox/_subfunc_master/export_fig_2018
- % export_fig(gcf,sprintf('G:/Meine Ablage/2024_MonitorTest/_Results_Figures/ISS_simple/ISS_Figure6.eps'),'-painters','-transparent','-pdf')
- % end
- fprintf('\nDone.')
plotdata_intrasaccadic_Fig9.m, no license · at the source
Overview
- Department of Experimental Psychology, University of Groningen, Grote Kruisstraat 2/1, 9712 TS Groningen, The Netherlands
- Research School of Behavioural and Cognitive Neurosciences, Faculty of Science and Engineering, University of Groningen, Groningen, The Netherlands
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
bad52ff7ad164abf3795fbf6476f162d42535e25, 29 October 2024Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
13 files
- R/
detect_saccade_for_R.c , C, 392 lines, 1 match - R/
detect_saccade_for_R.h , C/C++, 19 lines - R/
microsacc.R , R, 113 lines - R/
online_sac_PSO_detect.R , R, 164 lines - R/
vecvel.R , R, 21 lines - matlab/
detect_saccade_2d_C_ONSE , C++, 448 lines, 2 matchesT.cpp - matlab/
test_demo_sac_Detection. , MATLAB, 45 linesm - matlab/
test_runtime_sac_Detecti , MATLAB, 35 lineson.m - python/
detect_saccade_pure_C_ON , C, 392 linesSET.c - python/
detect_saccade_pure_C_ON , C/C++, 15 linesSET.h - python/
online_sac_detect_module , Python, 272 lines.py - LICENSE, License, 674 lines
- README.md, Text, 16 lines
OSF 8h4fg
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
- 28 September 2026: the link answers (HTTP 200)
6 files
- Fig01_Fig06C_Fig08_photo
diodeData/ , MATLAB, 407 lines, 3 matchesplotdata_photodiode_Fig1 _Fig4_Fig5.m - Fig02_Gray2GrayTransisti
ons/ , MATLAB, 442 linesAnalyse_and_plot_G2G_tra nsitions_v3_OSF.m - Fig03_TLMflicker/
Figure3_quantifyTLM_osf. , MATLAB, 125 lines, 2 matchesm - Fig04_PairedPulsesTest/
code_analyze_PairedPulse , MATLAB, 400 lines, 4 matchesParadigm_OSF.m - Fig05_uniformity_angles_
operatingtime/ , MATLAB, 273 lines, 2 matchesplotdata_photometer_Fig2 .m - Fig10_saccadeTask/
plotdata_intrasaccadic_F , MATLAB, 521 lines, 4 matchesig9.m
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://
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://
BibTeX
@article{dimigen2026adva
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/
url = {https://
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/
VL - 58
IS - 6
SP - 161
SN - 1554-351X
PB - Springer Science+Business Media
DO - 10.3758/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.3758/
"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":
"volume": "58",
"issue": "6",
"page": "161",
"DOI": "10.3758/
"PMID": "42115564",
"PMCID": "PMC13161341",
"ISSN": "1554-351X",
"publisher": "Springer Science+Business Media",
"URL": "https://
"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 advancesIn 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 communicationsIn 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: PsychophysiologyIn 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 behaviourIn 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 communicationsIn 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 communicationsIn 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 communicationsIn 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 communicationsIn 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 mappingIn 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.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 2 repositories of the authors' code, each at its verified commit and with its license, 17 scripts, and 18 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:25e5eb78d9d02122…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
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.
