{ "nbformat_minor": 0, "nbformat": 4, "cells": [ { "execution_count": null, "cell_type": "code", "source": [ "%matplotlib inline" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "\n\nEEG processing and Event Related Potentials (ERPs)\n==================================================\n\nFor a generic introduction to the computation of ERP and ERF\nsee `tut_epoching_and_averaging`. Here we cover the specifics\nof EEG, namely:\n\n - setting the reference\n - using standard montages :func:`mne.channels.Montage`\n - Evoked arithmetic (e.g. differences)\n\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "import mne\nfrom mne.datasets import sample" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "Setup for reading the raw data\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "data_path = sample.data_path()\nraw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'\nevent_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif'\nraw = mne.io.read_raw_fif(raw_fname, preload=True)\nraw.set_eeg_reference() # set EEG average reference" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "Let's restrict the data to the EEG channels\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw.pick_types(meg=False, eeg=True, eog=True)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "By looking at the measurement info you will see that we have now\n59 EEG channels and 1 EOG channel\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "print(raw.info)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "In practice it's quite common to have some EEG channels that are actually\nEOG channels. To change a channel type you can use the\n:func:`mne.io.Raw.set_channel_types` method. For example\nto treat an EOG channel as EEG you can change its type using\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw.set_channel_types(mapping={'EOG 061': 'eeg'})\nprint(raw.info)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "And to change the nameo of the EOG channel\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw.rename_channels(mapping={'EOG 061': 'EOG'})" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "Let's reset the EOG channel back to EOG type.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw.set_channel_types(mapping={'EOG': 'eog'})" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "The EEG channels in the sample dataset already have locations.\nThese locations are available in the 'loc' of each channel description.\nFor the first channel we get\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "print(raw.info['chs'][0]['loc'])" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "And it's actually possible to plot the channel locations using\nthe :func:`mne.io.Raw.plot_sensors` method\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw.plot_sensors()\nraw.plot_sensors('3d') # in 3D" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "Setting EEG montage\n-------------------\n\nIn the case where your data don't have locations you can set them\nusing a :func:`mne.channels.Montage`. MNE comes with a set of default\nmontages. To read one of them do:\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "montage = mne.channels.read_montage('standard_1020')\nprint(montage)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "To apply a montage on your data use the ``set_montage`` method.\nfunction. Here don't actually call this function as our demo dataset\nalready contains good EEG channel locations.\n\nNext we'll explore the definition of the reference.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "source": [ "Setting EEG reference\n---------------------\n\nLet's first remove the reference from our Raw object.\n\nThis explicitly prevents MNE from adding a default EEG average reference\nrequired for source localization.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw_no_ref, _ = mne.set_eeg_reference(raw, [])" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "We next define Epochs and compute an ERP for the left auditory condition.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "reject = dict(eeg=180e-6, eog=150e-6)\nevent_id, tmin, tmax = {'left/auditory': 1}, -0.2, 0.5\nevents = mne.read_events(event_fname)\nepochs_params = dict(events=events, event_id=event_id, tmin=tmin, tmax=tmax,\n reject=reject)\n\nevoked_no_ref = mne.Epochs(raw_no_ref, **epochs_params).average()\ndel raw_no_ref # save memory\n\ntitle = 'EEG Original reference'\nevoked_no_ref.plot(titles=dict(eeg=title))\nevoked_no_ref.plot_topomap(times=[0.1], size=3., title=title)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "**Average reference**: This is normally added by default, but can also\nbe added explicitly.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw_car, _ = mne.set_eeg_reference(raw)\nevoked_car = mne.Epochs(raw_car, **epochs_params).average()\ndel raw_car # save memory\n\ntitle = 'EEG Average reference'\nevoked_car.plot(titles=dict(eeg=title))\nevoked_car.plot_topomap(times=[0.1], size=3., title=title)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "**Custom reference**: Use the mean of channels EEG 001 and EEG 002 as\na reference\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "raw_custom, _ = mne.set_eeg_reference(raw, ['EEG 001', 'EEG 002'])\nevoked_custom = mne.Epochs(raw_custom, **epochs_params).average()\ndel raw_custom # save memory\n\ntitle = 'EEG Custom reference'\nevoked_custom.plot(titles=dict(eeg=title))\nevoked_custom.plot_topomap(times=[0.1], size=3., title=title)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "Evoked arithmetics\n------------------\n\nTrial subsets from Epochs can be selected using 'tags' separated by '/'.\nEvoked objects support basic arithmetic.\nFirst, we create an Epochs object containing 4 conditions.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "event_id = {'left/auditory': 1, 'right/auditory': 2,\n 'left/visual': 3, 'right/visual': 4}\nepochs_params = dict(events=events, event_id=event_id, tmin=tmin, tmax=tmax,\n reject=reject)\nepochs = mne.Epochs(raw, **epochs_params)\n\nprint(epochs)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "Next, we create averages of stimulation-left vs stimulation-right trials.\nWe can use basic arithmetic to, for example, construct and plot\ndifference ERPs.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "left, right = epochs[\"left\"].average(), epochs[\"right\"].average()\n\n# create and plot difference ERP\nmne.combine_evoked([left, -right], weights='equal').plot_joint()" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "This is an equal-weighting difference. If you have imbalanced trial numbers,\nyou could also consider either equalizing the number of events per\ncondition (using\n:meth:`epochs.equalize_event_counts `).\nAs an example, first, we create individual ERPs for each condition.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "aud_l = epochs[\"auditory\", \"left\"].average()\naud_r = epochs[\"auditory\", \"right\"].average()\nvis_l = epochs[\"visual\", \"left\"].average()\nvis_r = epochs[\"visual\", \"right\"].average()\n\nall_evokeds = [aud_l, aud_r, vis_l, vis_r]\nprint(all_evokeds)" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "This can be simplified with a Python list comprehension:\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "all_evokeds = [epochs[cond].average() for cond in sorted(event_id.keys())]\nprint(all_evokeds)\n\n# Then, we construct and plot an unweighted average of left vs. right trials\n# this way, too:\nmne.combine_evoked(all_evokeds,\n weights=(0.25, -0.25, 0.25, -0.25)).plot_joint()" ], "outputs": [], "metadata": { "collapsed": false } }, { "source": [ "Often, it makes sense to store Evoked objects in a dictionary or a list -\neither different conditions, or different subjects.\n\n" ], "cell_type": "markdown", "metadata": {} }, { "execution_count": null, "cell_type": "code", "source": [ "# If they are stored in a list, they can be easily averaged, for example,\n# for a grand average across subjects (or conditions).\ngrand_average = mne.grand_average(all_evokeds)\nmne.write_evokeds('/tmp/tmp-ave.fif', all_evokeds)\n\n# If Evokeds objects are stored in a dictionary, they can be retrieved by name.\nall_evokeds = dict((cond, epochs[cond].average()) for cond in event_id)\nprint(all_evokeds['left/auditory'])\n\n# Besides for explicit access, this can be used for example to set titles.\nfor cond in all_evokeds:\n all_evokeds[cond].plot_joint(title=cond)" ], "outputs": [], "metadata": { "collapsed": false } } ], "metadata": { "kernelspec": { "display_name": "Python 2", "name": "python2", "language": "python" }, "language_info": { "mimetype": "text/x-python", "nbconvert_exporter": "python", "name": "python", "file_extension": ".py", "version": "2.7.13", "pygments_lexer": "ipython2", "codemirror_mode": { "version": 2, "name": "ipython" } } } }