{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n\n# Setting the EEG reference\n\nThis tutorial describes how to set or change the EEG reference in MNE-Python.\n\nAs usual we'll start by importing the modules we need, loading some\n`example data `, and cropping it to save memory. Since\nthis tutorial deals specifically with EEG, we'll also restrict the dataset to\njust a few EEG channels so the plots are easier to see:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Authors: The MNE-Python contributors.\n# License: BSD-3-Clause\n# Copyright the MNE-Python contributors." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import os\n\nimport mne\n\nsample_data_folder = mne.datasets.sample.data_path()\nsample_data_raw_file = os.path.join(\n sample_data_folder, \"MEG\", \"sample\", \"sample_audvis_raw.fif\"\n)\nraw = mne.io.read_raw_fif(sample_data_raw_file, verbose=False)\nraw.crop(tmax=60).load_data()\nraw.pick([f\"EEG 0{n:02}\" for n in range(41, 60)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Background\n\nEEG measures a voltage (difference in electric potential) between each\nelectrode and a reference electrode. This means that whatever signal is\npresent at the reference electrode is effectively subtracted from all the\nmeasurement electrodes. Therefore, an ideal reference signal is one that\ncaptures *none* of the brain-specific fluctuations in electric potential,\nwhile capturing *all* of the environmental noise/interference that is being\npicked up by the measurement electrodes.\n\nIn practice, this means that the reference electrode is often placed in a\nlocation on the subject's body and close to their head (so that any\nenvironmental interference affects the reference and measurement electrodes\nsimilarly) but as far away from the neural sources as possible (so that the\nreference signal doesn't pick up brain-based fluctuations). Typical reference\nlocations are the subject's earlobe, nose, mastoid process, or collarbone.\nEach of these has advantages and disadvantages regarding how much brain\nsignal it picks up (e.g., the mastoids pick up a fair amount compared to the\nothers), and regarding the environmental noise it picks up (e.g., earlobe\nelectrodes may shift easily, and have signals more similar to electrodes on\nthe same side of the head).\n\nEven in cases where no electrode is specifically designated as the reference,\nEEG recording hardware will still treat one of the scalp electrodes as the\nreference, and the recording software may or may not display it to you (it\nmight appear as a completely flat channel, or the software might subtract out\nthe average of all signals before displaying, making it *look like* there is\nno reference).\n\n\n## Setting or changing the reference channel\n\nIf you want to recompute your data with a different reference than was used\nwhen the raw data were recorded and/or saved, MNE-Python provides the\n:meth:`~mne.io.Raw.set_eeg_reference` method on :class:`~mne.io.Raw` objects\nas well as the :func:`mne.add_reference_channels` function. To use an\nexisting channel as the new reference, use the\n:meth:`~mne.io.Raw.set_eeg_reference` method; you can also designate multiple\nexisting electrodes as reference channels, as is sometimes done with mastoid\nreferences:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# code lines below are commented out because the sample data doesn't have\n# earlobe or mastoid channels, so this is just for demonstration purposes:\n\n# use a single channel reference (left earlobe)\n# raw.set_eeg_reference(ref_channels=['A1'])\n\n# use average of mastoid channels as reference\n# raw.set_eeg_reference(ref_channels=['M1', 'M2'])\n\n# use a bipolar reference (contralateral)\n# raw.set_bipolar_reference(anode='[F3'], cathode=['F4'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If a scalp electrode was used as reference but was not saved alongside the\nraw data (reference channels often aren't), you may wish to add it back to\nthe dataset before re-referencing. For example, if your EEG system recorded\nwith channel ``Fp1`` as the reference but did not include ``Fp1`` in the data\nfile, using :meth:`~mne.io.Raw.set_eeg_reference` to set (say) ``Cz`` as the\nnew reference will then subtract out the signal at ``Cz`` *without restoring\nthe signal at* ``Fp1``. In this situation, you can add back ``Fp1`` as a flat\nchannel prior to re-referencing using :func:`~mne.add_reference_channels`.\n(Since our example data doesn't use the `10-20 electrode naming system`_, the\nexample below adds ``EEG 999`` as the missing reference, then sets the\nreference to ``EEG 050``.) Here's how the data looks in its original state:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "raw.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, :func:`~mne.add_reference_channels` returns a copy, so we can go\nback to our original ``raw`` object later. If you wanted to alter the\nexisting :class:`~mne.io.Raw` object in-place you could specify\n``copy=False``.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# add new reference channel (all zero)\nraw_new_ref = mne.add_reference_channels(raw, ref_channels=[\"EEG 999\"])\nraw_new_ref.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. KEEP THESE BLOCKS SEPARATE SO FIGURES ARE BIG ENOUGH TO READ\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# set reference to `EEG 050`\nraw_new_ref.set_eeg_reference(ref_channels=[\"EEG 050\"])\nraw_new_ref.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the new reference (``EEG 050``) is now flat, while the original\nreference channel that we added back to the data (``EEG 999``) has a non-zero\nsignal. Notice also that ``EEG 053`` (which is marked as \"bad\" in\n``raw.info['bads']``) is not affected by the re-referencing.\n\n\n## Setting average reference\n\nTo set a \"virtual reference\" that is the average of all channels, you can use\n:meth:`~mne.io.Raw.set_eeg_reference` with ``ref_channels='average'``. Just\nas above, this will not affect any channels marked as \"bad\", nor will it\ninclude bad channels when computing the average. However, it does modify the\n:class:`~mne.io.Raw` object in-place, so we'll make a copy first, so we can\nstill go back to the unmodified :class:`~mne.io.Raw` object later:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# use the average of all channels as reference\nraw_avg_ref = raw.copy().set_eeg_reference(ref_channels=\"average\")\nraw_avg_ref.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n## Creating the average reference as a projector\n\nIf using an average reference, it is possible to create the reference as a\n:term:`projector` rather than subtracting the reference from the data\nimmediately by specifying ``projection=True``:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "raw.set_eeg_reference(\"average\", projection=True)\nprint(raw.info[\"projs\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creating the average reference as a projector has a few advantages:\n\n1. It is possible to turn projectors on or off when plotting, so it is easy\n to visualize the effect that the average reference has on the data.\n\n2. If additional channels are marked as \"bad\" or if a subset of channels are\n later selected, the projector will be re-computed to take these changes\n into account (thus guaranteeing that the signal is zero-mean).\n\n3. If there are other unapplied projectors affecting the EEG channels (such\n as SSP projectors for removing heartbeat or blink artifacts), EEG\n re-referencing cannot be performed until those projectors are either\n applied or removed; adding the EEG reference as a projector is not subject\n to that constraint. (The reason this wasn't a problem when we applied the\n non-projector average reference to ``raw_avg_ref`` above is that the\n empty-room projectors included in the sample data :file:`.fif` file were\n only computed for the magnetometers.)\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "for title, proj in zip([\"Original\", \"Average\"], [False, True]):\n with mne.viz.use_browser_backend(\"matplotlib\"):\n fig = raw.plot(proj=proj, n_channels=len(raw))\n # make room for title\n fig.subplots_adjust(top=0.9)\n fig.suptitle(f\"{title} reference\", size=\"xx-large\", weight=\"bold\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using an infinite reference (REST)\n\nTo use the \"point at infinity\" reference technique described in\n:footcite:`Yao2001` requires a forward model, which we can create in a few\nsteps. Here we use a fairly large spacing of vertices (``pos`` = 15 mm) to\nreduce computation time; a 5 mm spacing is more typical for real data\nanalysis:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "raw.del_proj() # remove our average reference projector first\nsphere = mne.make_sphere_model(\"auto\", \"auto\", raw.info)\nsrc = mne.setup_volume_source_space(sphere=sphere, exclude=30.0, pos=15.0)\nforward = mne.make_forward_solution(raw.info, trans=None, src=src, bem=sphere)\nraw_rest = raw.copy().set_eeg_reference(\"REST\", forward=forward)\n\nfor title, _raw in zip([\"Original\", \"REST (\u221e)\"], [raw, raw_rest]):\n with mne.viz.use_browser_backend(\"matplotlib\"):\n fig = _raw.plot(n_channels=len(raw), scalings=dict(eeg=5e-5))\n # make room for title\n fig.subplots_adjust(top=0.9)\n fig.suptitle(f\"{title} reference\", size=\"xx-large\", weight=\"bold\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using a bipolar reference\n\nTo create a bipolar reference, you can use :meth:`~mne.set_bipolar_reference`\nalong with the respective channel names for ``anode`` and ``cathode`` which\ncreates a new virtual channel that takes the difference between two\nspecified channels (anode and cathode) and drops the original channels by\ndefault. The new virtual channel will be annotated with the channel info of\nthe anode with location set to ``(0, 0, 0)`` and coil type set to\n``EEG_BIPOLAR`` by default. Here we use a contralateral/transverse bipolar\nreference between channels ``EEG 054`` and ``EEG 055`` as described in\n:footcite:`YaoEtAl2019` which creates a new virtual channel\nnamed ``EEG 054-EEG 055``.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "raw_bip_ref = mne.set_bipolar_reference(raw, anode=[\"EEG 054\"], cathode=[\"EEG 055\"])\nraw_bip_ref.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## EEG reference and source modeling\n\nIf you plan to perform source modeling (either with EEG or combined EEG/MEG\ndata), it is **strongly recommended** to use the\naverage-reference-as-projection approach. It is important to use an average\nreference because using a specific\nreference sensor (or even an average of a few sensors) spreads the forward\nmodel error from the reference sensor(s) into all sensors, effectively\namplifying the importance of the reference sensor(s) when computing source\nestimates. In contrast, using the average of all EEG channels as reference\nspreads the forward modeling error evenly across channels, so no one channel\nis weighted more strongly during source estimation. See also this `FieldTrip\nFAQ on average referencing`_ for more information.\n\nThe main reason for specifying the average reference as a projector was\nmentioned in the previous section: an average reference projector adapts if\nchannels are dropped, ensuring that the signal will always be zero-mean when\nthe source modeling is performed. In contrast, applying an average reference\nby the traditional subtraction method offers no such guarantee.\n\n.. important:: For these reasons, when performing inverse imaging, MNE-Python\n will raise a ``ValueError`` if there are EEG channels present\n and something other than an average reference projector strategy\n has been specified. To ensure correct functioning consider\n calling :meth:`set_eeg_reference(projection=True)\n ` to add an average\n reference as a projector.\n\n.. LINKS\n\n http://www.fieldtriptoolbox.org/faq/why_should_i_use_an_average_reference_for_eeg_source_reconstruction/\n https://en.wikipedia.org/wiki/10%E2%80%9320_system_(EEG)\n\n\n## References\n.. footbibliography::\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.2" } }, "nbformat": 4, "nbformat_minor": 0 }