From 4c00f3c6bf241b468c2563f626972860651838b5 Mon Sep 17 00:00:00 2001 From: Olaf Dimigen Date: Thu, 12 Oct 2023 16:14:19 +0200 Subject: [PATCH] Minor updates for version 1.0 --- README.md | 2 +- _changelog_v0.99.txt | 231 ---------------------------- _changelog_v1.0.txt | 12 ++ eegplugin_eye_eeg.m | 16 +- eegplugin_eye_eeg.m.bak | 323 ---------------------------------------- 5 files changed, 23 insertions(+), 561 deletions(-) delete mode 100644 _changelog_v0.99.txt create mode 100644 _changelog_v1.0.txt delete mode 100644 eegplugin_eye_eeg.m.bak diff --git a/README.md b/README.md index f8f170a..0998635 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # EYE-EEG0.99 -Version 0.99 of the EYE-EEG extension for EEGLAB +Version 1.0 of the EYE-EEG extension for EEGLAB For more information on this software, visit https://www.eyetracking-eeg.org diff --git a/_changelog_v0.99.txt b/_changelog_v0.99.txt deleted file mode 100644 index 534718f..0000000 --- a/_changelog_v0.99.txt +++ /dev/null @@ -1,231 +0,0 @@ -%% EYE-EEG change log -% olaf@dimigen.de - -% Change log for version 0.99 - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2021-09-28: checksync(): bad_ET intevals are now ignored -% checksync() -% Intervals with a bad eye-track (inserted as bad_ET markers in EEG.event) -% are now ignored when computing the cross-correlation between eye-track -% and electro-oculogram (to check the synchronization) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2021-09-18: New function (Beta) to estimate saccade onsets without -% eye-tracking -pop_detecteogspikes, detecteogspikes -% New function to estimate saccade onsets based on a "radial" montage of -% the EOG channels. The radial EOG reflects emphasizes the saccadic spike -% potential, which reflects recruitment of the eye muscles at saccade onset. -% These events can therefore be used to estimate saccade onsets (but not -% fixation onsets) without concurrent eye-tracking. -% For references and more details, see Keren et al., 2010, NeuroImage and -% Dimigen, 2020, NeuroImage - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2021-09-17: Bugfix: Synchronize Eyelink data recorded with 2000 Hz -synchronize.m -% Eyelink trackers recording with 2000 Hz assign the same integer time stamp -% to two subsequent sampling points in the raw data, causing problems in -% the synchronization, which requires continuously increasing time stamps -% in the ET data. Built-in simple function by Richard Schweitzer (thanks!) -% which increments the second of the two time stamps by 0.5 ms. (Hotfix) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2021-09-17: Various smaller bug fixes and improvements of screen feedback - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2018-06-22 -% [pop_overweightevents.m],[overweightevents.m] -% Function to create optimized ICA training data (OPTICAT) for correcting -% (free viewing) EEG experiment with many ocular artifacts -% See Dimigen et al., 2018 for a description and evaluation - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2018-06-22 -% [pop_rejeyecontin.m],[rejeyecontin.m] -% Intervals with bad data must be marked or removed before saccade detection. -% Previously, it was only possible to remove intervals with out-of-range ET -% data from the continuous data or to remove whole epochs (in case of -% epoched data). The new pop_rejeyecontin.m functions allows to instead -% add a special marker ("bad_ET") to EEG.event for each bad data interval. -% These markers are considered by the eye movement detection function -% (pop_detecteyemovements.m); the dataset is not cut. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-10-18: Bug fix: Incorrect "urevent" latencies for eye movement events -% [addevents.m] [but see also: detecteyemovements.m] - -% This bugfix is relevant for (power)users who use the EEG.urevent -% structure of EEGLAB. During eye movement detection, new saccade and fixation -% events, added by function addevent, are also added to EEGLABs "urevent" -% structure (EEG.urevent). EEG.urevent contains a representation of the original -% event history of the dataset, before segmentation into epochs. -% This urevent info can be quite useful in some research contexts. -% When writing EYE-EEG we have decided that information about the (new) -% eye movement events should also be added to the EEG.urevent structure, -% because this is often quite helpful for advanced analyses. -% Previously however, the EEG.urevent.latency for new (eye movement) events -% added using function addevents() was wrong, if the dataset was already cut into -% epochs when the detecteyemovements and addevents functions were executed. -% The data stored in EEG.event.latency was always correct. -% This has now been fixed. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-00-00: Replace function smooth() in ploteventrate -% [ploteventrate.m] -% -% Replaced function smooth() in ploteventrate, because it requires -% the commerical Curve Fitting Toolbox - - -% As of EYE-EEG version 0.80 - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2016-10-28: New cross-correlation method to evaluate synch. quality -% [pop_checksynch.m] -% added pop_checksync() function which allows to assess synchronization -% quality by cross-correlation of eye tracker (gaze) and electro-oculogram -% (EOG) channels. We propose this as a new method to evaluate the synchronization -% of ET and EEG data based on the actual signals, rather than based only -% on common (trigger) events -% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2016-09-07: Support for "Tobii Pro" eye trackers -% [pop_parsetobii.m, parsetobii.m] -% -% Allows to read data recorded with "Tobii Pro" eye trackers. Please refer -% to the EYE-EEG website for details about this new function. -% Thanks to Estefania Dominguez from Tobii for developing this function -% with us. -% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-01-13: Automatic import of "other" ET messages -% [parseeyelink.m, parsesmi.m, pop_importeyetracker.m, synchronize.m] -% Messages are ASCII-text message lines in the raw eye tracking data. -% In the past, EYE-EEG only considered messages that contained a special -% keyword for the purpose of synchronization. -% -% Now, EYE-EEG also parses and imports other eye tracking messages -% (for Eyelink and SMI data), because sometimes, information about the -% experiment (e.g. trial, condition) is only contained in 'message lines', -% but not in the EEG triggers. In this case, it is helpful to also import -% the messages into the synchronized/resampled ET/EEG dataset with their -% new timestamp. -% Functions parseeyelink(), synchronize(), and pop_importeyetracker() were -% changed such that message information is now also imported. Messages are -% stored in field 'EEG.etc.othermessages' of EEGLAB's data structure -% together with their new latency in the synchronized dataset. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% MINOR FEATURES & BUG FIXES -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2015-03-27: Fixed problem with EEG from ANT systems -% [addevent.m] -% Problem: The ANT data importer does not fill the EEG.urevent structure, -% leading to a crash of this function. Solution: Fixed by calling -% eeg_checkset() to re-create ur-events as follows: -% -% if isempty(EEG.urevent) -% fprintf('\nWarning: EEG.urevent is empty. Recreating... -% urevents with eeg_checkset before adding new events...\n') -% EEG = eeg_checkset(EEG,'makeur') % recreate ur-events -% end -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2015-03-27: Minor bug fix -% [microsacc_plugin.m] -% fixed function call for function 'velthresh(vel)', which was misspelled -% as 'velthreshold(vel)' -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2015-09-17: User feedback -% [synchronize.m] -% improved clarity of wording in screen outputs about the quality of -% synchronization -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2015-09-17: ET channel names -% [pop_importeyetracker.m] -% Underscores and empty spaces in ET channel names are now replaced with -% '-' (rather than underscores) because underscores affect the -% text-formatting in MATLAB (e.g. in function > Plot > Continuous data). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2015-09-19: User feedback -% [ploteyemovements.m] -% Improved clarity of the wording of screen outputs -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-01-13: User-defined searchRadius to identify shared events -% [pop_importeyetracker.m, synchronize.m] -% -% Allow user to set 'searchRange' to identify shared events. -% Added additional function input searchRange in pop_importeyetracker. -% This input affects how EYE-EEG identifies instances of 'shared' events -% that are present in both recordings (but possibly not at the exact same -% latency due to some transmission time jitter). Around each -% event (trigger) in the EEG, EYE-EEG will search for plusminus -% searchRadius samples for an ET event of the same type (e.g. '123'). These -% shared events are then entered into the linear regression to optimize the -% clock drift/alignment between both recordings. However, in some cases, -% errors may occur if multiple events of the same type (e.g. '123') were -% send in close succession (e.g. only 5 ms apart) during the experiment, -% because then multiple ET events may be in the searchRange around the EEG -% trigger. In this case, it makes sense to decrease search range -% a little bit. Otherwise, stick to the default of 4 samples. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-01-14: User-feedback if ET file cannot be found -% [pop_importeyetracker.m] -% Previously, there was no feedback/errormessage if the specified .mat file -% for the eye tracker did not exist. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-02-15: Storage of information in EEG.etc.eyetracker -% [pop_importeyetracker.m], [pop_etica.m] -% -% Various useful information about the eye tracking data is now stored in -% the field EEG.etc.eyetracker... -% -- histogram of sync error informing about the datasets synchronization quality -% -- the content and new EEG latency of "other" messages contained in the ET -% raw data. -% -- saccade/fixation variance ratio of ICA-components -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-02-15: Bugfix: Estimated ET sampling rate was given as "0 Hz" -% [synchronize.m] -% -% Fixed bug with some ET setups. Due to the bug, the estimated ET sampling -% rate (relative to the EEG master clock) was reported as "0 Hz" during -% synchronization. Fixed this by adding exception for special cases in -% which parallel port inputs were send using separate INPUT lines in the -% raw ET data. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-02-15: Bugfix: pop_importeyetracker: wrong filename feedback -% [pop_importeyetracker] -% -% Fixed bug where the function did not produce an error message (just -% stayed silent and did nothing) if the user entered a wrong filename or a -% non-existing filepath. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-05-03 -% [pop_eyetrackerica.m, eyetrackerica.m] -% The pop_eyetrackerica uses the duration of saccades and fixations. -% Although the EEGLAB documentation is inconsistent regarding this issue, -% event durations in EEG.event appear to be given in SAMPLES rather than -% microsaccades. That is why the duration of eye movements and fixations is -% also stored as samples in EEG.event.duration. -% -% However, the values in EEG.event.duration were NOT updated by older versions -% of EEGLABs data resampling function pop_resample. This means that if user -% choses to resample their (synchronized) EEG data, the fixation duration and -% saccade duration values will be incorrect afterwards. Importantly, this -% will also compromise the outputs of the pop_eyetrackerica function, which -% uses the event duration information for saccades and fixations. -% -% A warning has now been added to the documentation of pop_eyetrackerica -% and eyetrackerica. Thanks to C. Huber-Huber for noticing this bug (in May -% 2017) and to the EEGLAB team for agreeing to fix it in new EEGLAB versions. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 2017-07-02 -% Various smaller bug fixes -% -% We thank everyone who made suggestions or contributed bug reportes, for -% example S. Oehlschlaeger, C. Huber-Huber, A. Andreev, M. Cantor, J. Leehr, -% J. Van Driehl and many more! \ No newline at end of file diff --git a/_changelog_v1.0.txt b/_changelog_v1.0.txt new file mode 100644 index 0000000..98c3664 --- /dev/null +++ b/_changelog_v1.0.txt @@ -0,0 +1,12 @@ +%% EYE-EEG change log +% science@dimigen.de + +% After more than 12 years of EYE-EEG, it is maybe time for a version 1.0! +% Change log for version 1.00 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% 1. small optimizations +%% 2. Includes a major bugfix for an issue the saccade detection that could +%% affect the properties of the last saccade detected in any epoch +%% Details here: https://github.com/olafdimigen/eye-eeg/issues/24 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ No newline at end of file diff --git a/eegplugin_eye_eeg.m b/eegplugin_eye_eeg.m index 8f86ab3..415d351 100644 --- a/eegplugin_eye_eeg.m +++ b/eegplugin_eye_eeg.m @@ -9,13 +9,12 @@ % microsaccades, eye tracker-supported ICA component selection, basic % oculomotor research, or computing fixation-related potentials (FRPs). % -% EYE-EEG was developed by Olaf Dimigen and Ulrich Reinacher, 2009-2021 +% EYE-EEG was developed by Olaf Dimigen and Ulrich Reinacher, 2009-2023 % -% >> web: http://www2.hu-berlin.de/eyetracking-eeg +% >> web: http://www.eyetracking-eeg.org % -% Copyright (C): Olaf Dimigen with major contributions by Ulrich Reinacher -% (until 2012) -% Any user feedback is highly welcome! Email: olaf@dimigen.de% +% Copyright (C): Olaf Dimigen with major contributions by Ulrich Reinacher (until 2012) +% Any user feedback is highly welcome! Email: science@dimigen.de % If you use functions of this toolbox, please cite this reference: % ------------------------------------------------------------------ % Dimigen, O., Sommer, W., Hohlfeld, A., Jacobs, A., & Kliegl, R. (2011). @@ -35,10 +34,15 @@ % eye movement artifacts in electroencephalographic data. Frontiers in % Human Neuroscience, doi: 10.3389/fnhum.2012.00278 % +% % Please clarify that you have used the implementation of these methods % in EYE-EEG, as they may differ from the original versions in some % regards % +% If you combined EYE-EEG with deconvolution modeling in "UNFOLD" please +% cite the unfold toolbox paper (Ehinger & Dimigen, 2019, PeerJ) as well +% as the specialized paper by Dimigen & Ehinger, 2021, Journal of Vision +% % Installation: % Simply copy the folder called "eye_eegX.XX" containing the toolbox's m-files % as a subdirectory into the EEGLAB plugin directory and restart EEGLAB. @@ -142,7 +146,7 @@ function vers = eegplugin_eye_eeg(fig,try_strings,catch_strings) -vers = 'eye_eeg_v0.99'; +vers = 'eye_eeg_v1.00'; % add subfolder for dialogues and other helpers addpath(fullfile(fileparts(which(mfilename)),'internal')); diff --git a/eegplugin_eye_eeg.m.bak b/eegplugin_eye_eeg.m.bak deleted file mode 100644 index 53962a7..0000000 --- a/eegplugin_eye_eeg.m.bak +++ /dev/null @@ -1,323 +0,0 @@ -% eegplugin_eye_eeg() - Preprocess, synchronize, and analyze simultaneously -% recorded eye tracking and EEG data -% -% Description: -% EYE-EEG is an extension for EEGLAB written to facilitate joint analyses -% of eye tracking and electroencephalographic (EEG) data. Among other -% things, it can be used for fixation control, objective eye artifact -% rejection, pupillometry, saccade and fixation detection, control of -% microsaccades, eye tracker-supported ICA component selection, basic -% oculomotor research, or computing fixation-related potentials (FRPs). -% -% EYE-EEG was developed by Olaf Dimigen and Ulrich Reinacher at -% Humboldt-University at Berlin, Germany, 2009-2021 -% -% >> web: http://www2.hu-berlin.de/eyetracking-eeg -% -% Copyright (C): Olaf Dimigen with Ulrich Reinacher, 2009-2021 -% User feedback welcome: email: olaf@dimigen.de% -% If you use functions of this toolbox, please cite this reference: -% ------------------------------------------------------------------ -% Dimigen, O., Sommer, W., Hohlfeld, A., Jacobs, A., & Kliegl, R. (2011). -% Coregistration of eye movements and EEG in natural reading: Analyses -% & Review, J Exp Psychol: General, Vol. 140 (4), 552-572. -% -% If you use the saccade/fixation detection, please additionally cite: -% -% Engbert, R., & Mergenthaler, K. (2006). Microsaccades are triggered -% by low retinal image slip, PNAS, Vol. 103 (18), 7192-7197 -% -% If you select independent components based on the sac/fix variance -% ratio criterion, make sure to also cite: -% -% Plöchl, M., Ossandon, J.P., & König, P. (2012). Combining EEG and -% eye tracking: identification, characterization, and correction of -% eye movement artifacts in electroencephalographic data. Frontiers in -% Human Neuroscience, doi: 10.3389/fnhum.2012.00278 -% -% Please clarify that you have used the implementation of these methods -% in EYE-EEG, as they may differ from the original versions in some -% regards -% -% Installation: -% Simply copy the folder called "eye_eegX.XX" containing the toolbox's m-files -% as a subdirectory into the EEGLAB plugin directory and restart EEGLAB. -% -% GUI functions -% ------------------------------------------------------------------ -% pop_applytochannels - apply EEGLAB functions to selected channels -% pop_detecteyemovements - detect saccades and fixations -% pop_ploteyemovements - plot properties of saccades and fixations -% pop_importeyetracker - import & synchronized eye tracking data -% pop_parseeyelink - preprocess eye tracking data from SR Research -% pop_parsesmi - preprocess eye tracking data from Sensomot. Instr. -% pop_parsetobii - preprocess eye tracking data from Tobii -% pop_rej_eyecontin - reject cont. data with out-of-range eye track -% pop_rej_eyeepochs - reject epochs with out-of-range eye track -% pop_checksync - assess quality of ET/EEG synchronization via cross-correlation -% pop_ploteventrate - plot rate of saccades or fixations relative to the epoch time-locking event -% pop_overweightevents - create optimized dataset for training the ICA -% pop_eyetrackerica - identify ICs that covary with eye tracker -% detecteogspikes - estimate saccade onsets based on spikes in the radial EOG - -% Non-GUI functions -% ---------------------------------------------------- -% addevents - add many events/urevents to cont. or epoched data -% applytochannels - see pop function -% detecteyemovements - see pop function -% detecteogspikes - see pop function -% eyetrackerica - see pop function -% geticvariance - compute IC variance inside/outside saccades -% parseeyelink - see pop function -% parsesmi - see pop function -% parsetobii - see pop function -% rej_eyecontin - see pop function -% hist2d - 2-dimensional histogram -% cleantrigger - helper function -% findmatchingevents - helper function -% findsequence2 - helper function -% ploteyemovements - plot properties of saccades & fixations -% synchronize - synchronize ET/EEG data -% checksync - assess quality of ET/EEG synchronization via cross-correlation -% overweightevents - create optimized dataset for training the ICA - -% Non-GUI functions for saccade & fixation detection -% ---------------------------------------------------- -% vecvel - compute eye velocities (*) -% velthresh - compute relative velocity-thresholds (*) -% microsacc_plugin - detect (micro)saccades (*) -% binsacc - identify binocular saccades (*) -% saccpar - compute saccade parameters (*) -% mergesacc - handle temporal saccade clusters -% filtSRP - filter% rEOG (by convolution with SP template) (**) -% -% (*) Copyright: Ralf Engbert et al., University of Potsdam -% http://mbd.psych.uni-potsdam.de/~ralfweb, included with permission -% Notes: -% vecvel() was modified to include different data smoothing options -% velthresh() outsources code that was originally part of microsacc(). -% microsacc() was therefore renamed to microsacc_plugin(). -% -% (**) function written by Alon Keren, see Keren et al., 2010, NeuroImage -% -% Third-party helper functions -% ---------------------------------------------------- -% parseq - Copyright: R. Kliegl & J. Laubrock, University of Potsdam -% searchclosest - Copyright: Jos van der Geest, see included license file -% -% Functions that control GUI dialogues -% ---------------------------------------------------- -% dlg_applytochannels -% dlg_calcvisangle -% dlg_detecteyenovements -% dlg_eyetrackerica -% dlg_loadeyetracker -% dlg_parser -% dlg_ploteyemovements -% dlg_rej_eyecontin -% dlg_rej_eyeepochs -% dlg_syncsettings -% dlg_ploteventrate -% dlg_checksync -% dlg_detecteogspikes -% ---------------------------------------------------- -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software -% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -% -% Eyelink (TM) is a trademark of SR Research Ltd., Mississauga, Canada -% SMI (TM) is a trademark of SensoMotoric Instruments GmbH, Germany -% Tobii (TM) is a trademark of Tobii AB, Stockholm, Sweden - -function vers = eegplugin_eye_eeg(fig,try_strings,catch_strings) - -vers = 'eye_eeg_v0.98'; - -% add subfolder for dialogues and other helpers -addpath(fullfile(fileparts(which(mfilename)),'internal')); - -%% callbacks for menu items - -% PARSE EYE TRACKER RAW DATA -cb_parsesmi = [try_strings.no_check, '[ET LASTCOM] = pop_parsesmi; clear ET;', catch_strings.add_to_hist]; -cb_parseeyelink = [try_strings.no_check, '[ET LASTCOM] = pop_parseeyelink; clear ET;', catch_strings.add_to_hist]; -cb_parsetobii = [try_strings.no_check, '[ET LASTCOM] = pop_parsetobii; clear ET;', catch_strings.add_to_hist]; - -% IMPORT & SYNCHRONIZE EYE TRACK -cb_importeyetracker = [try_strings.check_cont, '[EEG LASTCOM] = pop_importeyetracker(EEG);', catch_strings.new_and_hist]; -%cb_checksync = [try_strings.check_data, '[EEG LASTCOM] = pop_checksync(EEG);', catch_strings.add_to_hist]; - -% PREPROCESS EYE TRACK -cb_rej_eyeepochs = [try_strings.check_epoch, '[EEG LASTCOM] = pop_rej_eyeepochs(EEG);', catch_strings.new_and_hist]; -cb_rej_eyecontin = [try_strings.check_cont, '[EEG LASTCOM] = pop_rej_eyecontin(EEG);', catch_strings.new_and_hist]; - -% APPLY EEGLAB FUNCTION TO SELECTED CHANNELS ONLY -check4chanlocs = '[EEG LASTCOM] = eeg_checkset(EEG,''chanloc''); if ~isempty(LASTCOM), if LASTCOM(1) == -1, LASTCOM = ''''; return; end; end;'; - -cb_envelope_f1 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_eegfilt(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_f2 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_ERPLAB_butter1(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_f3 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_ERPLAB_polydetrend(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_f4 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_iirfilt(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_f5 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_eegfiltnew(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_f6 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_firma(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_f7 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_firpm(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_f8 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_firws(EEG);'');', catch_strings.new_and_hist]; -cb_envelope_2 = [try_strings.check_data, '[EEG tmp LASTCOM] = pop_epoch(EEG); clear tmp;' catch_strings.new_and_hist]; -cb_envelope_3 = [try_strings.check_data, '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_rmbase(EEG);'');' catch_strings.new_and_hist]; -cb_envelope_4 = [try_strings.check_data, check4chanlocs '[EEG LASTCOM] = pop_applytochannels(EEG,[],''pop_timtopo(EEG);'');' catch_strings.add_to_hist]; - -% DETECT SACCADES & FIXATIONS -cb_detectem_1 = [try_strings.no_check, '[EEG LASTCOM] = pop_detecteyemovements(EEG);', catch_strings.new_and_hist]; - -% PLOT SACCADES & FIXATIONS -cb_plotem_1 = [try_strings.no_check, '[EEG LASTCOM] = pop_ploteyemovements(EEG);', catch_strings.add_to_hist]; - -% PLOT SACCADES & FIXATIONS -cb_plotrate = [try_strings.no_check, '[LASTCOM] = pop_ploteventrate(EEG);', catch_strings.add_to_hist]; - -% CREATE OPTIMIZED ICA TRAINING DATA (OPTICAT) -% cb_overweight = [try_strings.no_check, '[EEG_overweighted LASTCOM] = pop_overweightevents(EEG);', catch_strings.add_to_hist]; -cb_overweight = [try_strings.no_check, 'EEG_overweighted = pop_eegfiltnew(EEG); [EEG_overweighted LASTCOM] = pop_overweightevents(EEG); [ALLEEG EEG CURRENTSET] = pop_newset(ALLEEG, EEG_overweighted, size(ALLEEG,2),''setname'',''Overweighted training data'',''gui'',''off''); eeglab redraw;', catch_strings.add_to_hist]; - -% EYETRACKER-SUPPORTED ICA -cb_etICA = [try_strings.check_ica, '[EEG vartable LASTCOM] = pop_eyetrackerica(EEG);', catch_strings.add_to_hist]; - -% ADVANCED -cb_checksync = [try_strings.check_data, '[EEG LASTCOM] = pop_checksync(EEG);', catch_strings.add_to_hist]; -cb_radialeog = [try_strings.check_data, '[EEG LASTCOM] = pop_detecteogspikes(EEG);', catch_strings.add_to_hist]; - -pause(0.001) -% Note: This pause is due to one of the weirdest bug I have ever tracked. -% If ERPLAB is also in the plugins folder, the menu order gets messed up -% of the main EEGLAB menus (File, ..., ..., Help etc.) causing EYE-EEG's -% EyeTracker menu (created below) to be also in the wrong place. Inserting this -% "pause" solves this issue, possible by forcing a display update (?) -% between addition of the ERPLAB menu and the "Eyetracker" menu -% OD, May 2020 - - -%% create GUI menus -W_MAIN = findobj('tag','EEGLAB'); - -% "EYETRACKER" -% attempt to make "Eyetracker" the last menu item before "Help" -% (note: menu position may change if more plugins are added, e.g. "ERPLAB") -eyetracker_m = uimenu( W_MAIN, 'Label', 'Eyetracker', 'tag','eyetracker'); - -try - nitems = get(eyetracker_m,'position'); - set(eyetracker_m,'position',nitems-1); -catch - set(eyetracker_m,'position',nitems); -end - -% set "Eyetracker" menu to default color for plugin menus -icadefs; % get PLUGINMENUCOLOR -set(eyetracker_m, 'foregroundcolor', PLUGINMENUCOLOR); - -% "PARSE EYETRACKER RAW DATA" -parseEyetracker_m = uimenu( eyetracker_m, 'Label', 'Parse eyetracker raw data', 'Separator', 'on'); -%uimenu( parseEyetracker_m, 'Label', 'EDF file from Eyelink', 'CallBack', cb_parseeyelink_edf); -uimenu( parseEyetracker_m, 'Label', 'text file from Eyelink', 'CallBack', cb_parseeyelink); -uimenu( parseEyetracker_m, 'Label', 'text file from SMI', 'CallBack', cb_parsesmi); -uimenu( parseEyetracker_m, 'Label', 'text file from Tobii', 'CallBack', cb_parsetobii); - -% "IMPORT & SYNCHRONIZE ET" -uimenu( eyetracker_m, 'Label', 'Import & synchronize ET', 'CallBack', cb_importeyetracker, 'Separator', 'off', 'userdata', 'epoch:off; '); -%uimenu(eyetracker_m, 'Label', 'Evaluate synchronization (cross-corr.)', 'CallBack', cb_checksync, 'Separator', 'off', 'userdata', 'startup:off;'); % epoch:off;' - -% APPLY FUNCTION TO SELECTED CHANNELS -helpers_m = uimenu( eyetracker_m, 'Label', 'Apply function to selected channels', 'Separator', 'on', 'userdata', 'startup:off;'); -filters_m = uimenu( helpers_m, 'Label', 'Filter the data (selected channels)', 'Separator', 'on', 'userdata', 'startup:off;'); -uimenu( filters_m, 'Label', 'Basic FIR filter (legacy)', 'CallBack', cb_envelope_f1, 'Separator', 'off', 'userdata', 'startup:off;'); - -% test whether filter functions from bundled plugins are available -% ...from ERPLAB -if exist('pop_ERPLAB_butter1','file') - uimenu( filters_m, 'Label', 'ERPLAB Butterworth filter' , 'CallBack', cb_envelope_f2, 'Separator', 'on', 'userdata', 'startup:off; '); -end -if exist('pop_ERPLAB_polydetrend','file') - uimenu( filters_m, 'Label', 'ERPLAB Polynomial Detrending', 'CallBack', cb_envelope_f3, 'Separator', 'off', 'userdata', 'startup:off; '); -end - -% ...from other plugins (not yet added to EEGLAB path) -eegplugpath = fullfile(fileparts(which('eeglab')),'/plugins'); -try - placeHolder = ''; - % placeHolder = ' '; % use this if error occurs with exotic MacOS/Unix versions - - % folders for IIR and FIR filter plugins - dir_iir = dir([eegplugpath placeHolder '/iirfilt*']); - dir_fir = dir([eegplugpath placeHolder '/firfilt*']); - - % iirfilt plugin installed? if so, add menu entry - if ~isempty(dir_iir) - filtName = 'iirfilt.m'; - if exist(fullfile(eegplugpath,dir_iir(1).name,filtName),'file') - uimenu( filters_m, 'Label', 'Short non-linear IIR filter', 'CallBack', cb_envelope_f4, 'Separator', 'on', 'userdata', 'startup:off; '); - end - else - %warning('iirfilt plugin not found in plugin folder)') - % #bugfix OD: removed this warning in v0.44, since iirfilt.m is not "shipped" with EEGLAB per default anymore - end - - % firfilt plugin installed? if so, add menu entries - if ~isempty(dir_fir) - filtName = { 'pop_eegfiltnew.m' 'pop_firws.m' 'pop_firpm.m' 'pop_firma.m'}; - filtMenuLabel = { 'Basic FIR filter (new)', 'Windowed sinc FIR filter' 'Parks-McClellan (equiripple) FIR filter' 'Moving average FIR filter'}; - filtMenuCb = { cb_envelope_f5 cb_envelope_f8 cb_envelope_f7 cb_envelope_f6 }; - for loop = 1:length(filtName) - if exist(fullfile(eegplugpath,dir_fir(1).name,filtName{loop}),'file') - uimenu( filters_m, 'Label', filtMenuLabel{loop}, 'CallBack', filtMenuCb{loop}, 'Separator', 'off', 'Position' , loop); - end - end - else - warning('firfilt plugin not found in plugin folder') - end - -catch dir_error - fprintf('\n%s(): Could not add filter functions to plugin menu. Skipping this step.\n',mfilename) -end - -uimenu( helpers_m, 'Label', 'Extract epochs (without baseline removal)', 'CallBack', cb_envelope_2, 'Separator', 'off', 'userdata', 'startup:off;'); -uimenu( helpers_m, 'Label', 'Remove baseline (selected channels)' , 'CallBack', cb_envelope_3, 'Separator', 'off', 'userdata', 'startup:off;'); -uimenu( helpers_m, 'Label', 'Channel ERPs - with scalp maps' , 'CallBack', cb_envelope_4, 'Separator', 'off', 'userdata', 'startup:off;'); - -% "REJECT DATA BASED ON ET" -rejectEyetrack_m = uimenu( eyetracker_m, 'Label', 'Reject data based on eye track' , 'Separator', 'on', 'userdata', 'startup:off; '); -uimenu( rejectEyetrack_m, 'Label', 'Reject bad cont. data', 'CallBack', cb_rej_eyecontin, 'Separator', 'off', 'userdata', 'startup:off; epoch:off;'); -uimenu( rejectEyetrack_m, 'Label', 'Reject bad epochs', 'CallBack', cb_rej_eyeepochs, 'Separator', 'off', 'userdata', 'startup:off; continuous:off;'); - -% "DETECT SACCADES & FIXATIONS" -uimenu( eyetracker_m, 'Label', 'Detect saccades & fixations', 'CallBack', cb_detectem_1, 'Separator', 'off', 'userdata', 'startup:off; '); - -% "PLOT SACCADES & FIXATIONS" -uimenu( eyetracker_m, 'Label', 'Plot eye movement properties', 'CallBack', cb_plotem_1, 'Separator', 'off', 'userdata', 'startup:off; '); - -% "PLOT SACCADES & FIXATIONS" -uimenu( eyetracker_m, 'Label', 'Plot eye movement rate', 'CallBack', cb_plotrate, 'Separator', 'off', 'userdata', 'startup:off; '); - -% "REJECT COMPONENTS WITH ET" -uimenu( eyetracker_m, 'Label', 'Create overweighted ICA training data (OPTICAT)', 'CallBack', cb_overweight, 'Separator', 'off', 'userdata', 'startup:off; '); - -% "REJECT COMPONENTS WITH ET" -uimenu( eyetracker_m, 'Label', 'Reject components with eyetracker', 'CallBack', cb_etICA, 'Separator', 'off', 'userdata', 'startup:off; '); - -% SPECIAL PURPOSE FUNCTIONS -advanced_m = uimenu( eyetracker_m, 'Label', 'Special-purpose functions', 'Separator', 'on', 'userdata', 'startup:off;'); -uimenu(advanced_m, 'Label', 'Evaluate ET/EEG synchronization (cross-corr.)', 'CallBack', cb_checksync, 'Separator', 'off', 'userdata', 'startup:off;'); % epoch:off;' -uimenu(advanced_m, 'Label', 'Detect saccade onsets based on (radial) EOG spikes', 'CallBack', cb_radialeog, 'Separator', 'off', 'userdata', 'startup:off;'); % epoch:off;' - -% "ABOUT THE TOOLBOX" -uimenu( eyetracker_m, 'Label', 'About this toolbox', 'CallBack', 'pophelp(''eegplugin_eye_eeg.m'');', 'Separator', 'on', 'userdata', 'startup:on;');