.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/temporal-response-functions/alice-trf.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_temporal-response-functions_alice-trf.py: .. _exa-alice-trf: TRF for Alice EEG Dataset ========================= Estimate a TRF, starting with a ``*-raw.fif`` EEG file and stimulus ``*.wav`` files. The data used is one subject from the `Alice dataset `_. This assumes that the Alice dataset has already been downloded (see the repository `readme `_). .. contents:: Sections :local: :backlinks: top .. GENERATED FROM PYTHON SOURCE LINES 20-40 .. code-block:: Python # sphinx_gallery_thumbnail_number = 6 import eelbrain import eelbrain.datasets._alice from matplotlib import pyplot import mne # Define the dataset root; this will use ~/Data/Alice, replace it with the # proper path if you downloaded the dataset in a different location DATA_ROOT = eelbrain.datasets._alice.get_alice_path() # Define some paths that will be used throughout STIMULUS_DIR = DATA_ROOT / 'stimuli' EEG_DIR = DATA_ROOT / 'eeg' # Load one subject's raw EEG file SUBJECT = 'S18' LOW_FREQUENCY = 0.5 HIGH_FREQUENCY = 20 .. GENERATED FROM PYTHON SOURCE LINES 41-44 Load EEG data ------------- This section loads EEG data from one subject from the Alice dataset. .. GENERATED FROM PYTHON SOURCE LINES 44-61 .. code-block:: Python raw = mne.io.read_raw(EEG_DIR / SUBJECT / f'{SUBJECT}_alice-raw.fif', preload=True) # Filter the raw data to the desired band raw.filter(LOW_FREQUENCY, HIGH_FREQUENCY, n_jobs=1) # Interpolate bad channels # This is not structly necessary for a single subject. # However, when processing multiple subjects, it will allow comparing results across all sensors. raw.interpolate_bads() # Load the events embedded in the raw file as eelbrain.Dataset, a type of object that represents a data-table events = eelbrain.load.mne.events(raw) # Display the events table: events .. raw:: html
# i_start trigger event
0 6495 1 1
1 35304 5 2
2 65752 6 3
3 97408 7 4
4 132429 8 5
5 165593 9 6
6 197508 10 7
7 228988 11 8
8 257678 12 9
9 286316 2 10
10 316973 3 11
11 345086 4 12


.. GENERATED FROM PYTHON SOURCE LINES 62-63 Plot the first 5 seconds of the first trial .. GENERATED FROM PYTHON SOURCE LINES 63-68 .. code-block:: Python t0 = events[0, 'i_start'] / raw.info['sfreq'] xlim = [t0, t0 + 5] p = eelbrain.plot.TopoButterfly(raw, t=t0 + 1, xlim=xlim, vmax=1e-4, h=3, w=10, clip='circle') .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_001.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 69-71 Create a predictor ------------------ .. GENERATED FROM PYTHON SOURCE LINES 71-88 .. code-block:: Python # Load the sound file corresponding to trigger 1 wav = eelbrain.load.wav(STIMULUS_DIR / f'1.wav') # Compute the acoustic envelope envelope = wav.envelope() # Filter the envelope with the same parameters as the EEG data envelope = eelbrain.filter_data(envelope, LOW_FREQUENCY, HIGH_FREQUENCY, pad='reflect') envelope = eelbrain.resample(envelope, 100) # Visualize the first 5 seconds p = eelbrain.plot.UTS([wav, envelope * 2], axh=2, w=10, columns=1, xlim=5) # Add y=0 as reference p.add_hline(0, zorder=0) .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_002.png :alt: 1.wav, 1.wav :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 89-90 Generate the acoustic envelope for all trials in this dataset .. GENERATED FROM PYTHON SOURCE LINES 90-106 .. code-block:: Python envelopes = [] for stimulus_id in events['event']: wav = eelbrain.load.wav(STIMULUS_DIR / f'{stimulus_id}.wav') envelope = wav.envelope() envelope = eelbrain.filter_data(envelope, LOW_FREQUENCY, HIGH_FREQUENCY, pad='reflect') envelope = eelbrain.resample(envelope, 100) envelopes.append(envelope) # Add the envelopes to the events table events['envelope'] = envelopes # Add a second predictor corresponding to acoustic onsets events['onsets'] = [envelope.diff('time').clip(0) for envelope in envelopes] events .. raw:: html
# i_start trigger event envelope onsets
0 6495 1 1 <NDVar '1.wa... <NDVar '1.wa...
1 35304 5 2 <NDVar '2.wa... <NDVar '2.wa...
2 65752 6 3 <NDVar '3.wa... <NDVar '3.wa...
3 97408 7 4 <NDVar '4.wa... <NDVar '4.wa...
4 132429 8 5 <NDVar '5.wa... <NDVar '5.wa...
5 165593 9 6 <NDVar '6.wa... <NDVar '6.wa...
6 197508 10 7 <NDVar '7.wa... <NDVar '7.wa...
7 228988 11 8 <NDVar '8.wa... <NDVar '8.wa...
8 257678 12 9 <NDVar '9.wa... <NDVar '9.wa...
9 286316 2 10 <NDVar '10.w... <NDVar '10.w...
10 316973 3 11 <NDVar '11.w... <NDVar '11.w...
11 345086 4 12 <NDVar '12.w... <NDVar '12.w...


.. GENERATED FROM PYTHON SOURCE LINES 107-113 Add EEG trial data ------------------ Add EEG data for each trial. We specifically need the EEG data corresponding to each stimulus. Given that each stimulus had a slightly different duration, we need to extract EEG segments that are trimmed differently for each trial. .. GENERATED FROM PYTHON SOURCE LINES 113-118 .. code-block:: Python # Extract the stimulus duration (in seconds) from the envelopes events['duration'] = eelbrain.Var([envelope.time.tstop for envelope in events['envelope']]) events .. raw:: html
# i_start trigger event envelope onsets duration
0 6495 1 1 <NDVar '1.wa... <NDVar '1.wa... 57.54
1 35304 5 2 <NDVar '2.wa... <NDVar '2.wa... 60.85
2 65752 6 3 <NDVar '3.wa... <NDVar '3.wa... 63.26
3 97408 7 4 <NDVar '4.wa... <NDVar '4.wa... 69.99
4 132429 8 5 <NDVar '5.wa... <NDVar '5.wa... 66.27
5 165593 9 6 <NDVar '6.wa... <NDVar '6.wa... 63.78
6 197508 10 7 <NDVar '7.wa... <NDVar '7.wa... 62.9
7 228988 11 8 <NDVar '8.wa... <NDVar '8.wa... 57.31
8 257678 12 9 <NDVar '9.wa... <NDVar '9.wa... 57.23
9 286316 2 10 <NDVar '10.w... <NDVar '10.w... 61.27
10 316973 3 11 <NDVar '11.w... <NDVar '11.w... 56.17
11 345086 4 12 <NDVar '12.w... <NDVar '12.w... 46.98


.. GENERATED FROM PYTHON SOURCE LINES 119-120 Extract EEG data corresponding exactly to the timing of the envelopes .. GENERATED FROM PYTHON SOURCE LINES 120-124 .. code-block:: Python events['eeg'] = eelbrain.load.mne.variable_length_epochs(events, 0, tstop='duration', decim=5, adjacency='auto') events .. raw:: html
# i_start trigger event envelope onsets duration eeg
0 6495 1 1 <NDVar '1.wa... <NDVar '1.wa... 57.54 <NDVar: 61 s...
1 35304 5 2 <NDVar '2.wa... <NDVar '2.wa... 60.85 <NDVar: 61 s...
2 65752 6 3 <NDVar '3.wa... <NDVar '3.wa... 63.26 <NDVar: 61 s...
3 97408 7 4 <NDVar '4.wa... <NDVar '4.wa... 69.99 <NDVar: 61 s...
4 132429 8 5 <NDVar '5.wa... <NDVar '5.wa... 66.27 <NDVar: 61 s...
5 165593 9 6 <NDVar '6.wa... <NDVar '6.wa... 63.78 <NDVar: 61 s...
6 197508 10 7 <NDVar '7.wa... <NDVar '7.wa... 62.9 <NDVar: 61 s...
7 228988 11 8 <NDVar '8.wa... <NDVar '8.wa... 57.31 <NDVar: 61 s...
8 257678 12 9 <NDVar '9.wa... <NDVar '9.wa... 57.23 <NDVar: 61 s...
9 286316 2 10 <NDVar '10.w... <NDVar '10.w... 61.27 <NDVar: 61 s...
10 316973 3 11 <NDVar '11.w... <NDVar '11.w... 56.17 <NDVar: 61 s...
11 345086 4 12 <NDVar '12.w... <NDVar '12.w... 46.98 <NDVar: 61 s...


.. GENERATED FROM PYTHON SOURCE LINES 125-126 Plot the first 5 seconds of EEG of the first trial (compare above) .. GENERATED FROM PYTHON SOURCE LINES 126-129 .. code-block:: Python p = eelbrain.plot.TopoButterfly(events[0, 'eeg'], t=1.5, xlim=5, vmax=1e-4, h=3, w=10, clip='circle') .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_003.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 130-131 Plot EEG alongside the representations of the sound that was presented .. GENERATED FROM PYTHON SOURCE LINES 131-136 .. code-block:: Python fig, axes = pyplot.subplots(2, 1, sharex=True, figsize=(10, 4)) p = eelbrain.plot.UTS([[events[0, 'envelope'], events[0, 'onsets']]], xlim=5, axes=axes[0]) p = eelbrain.plot.Butterfly(events[0, 'eeg'], xlim=5, vmax=1e-4, axes=axes[1]) .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_004.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 137-140 TRF --- Estimate the brain's response function to acoustic onsets. .. GENERATED FROM PYTHON SOURCE LINES 140-143 .. code-block:: Python trf = eelbrain.boosting('eeg', 'onsets', -0.100, 0.500, data=events, basis=0.050, partitions=4) .. GENERATED FROM PYTHON SOURCE LINES 144-145 Plot the TRF, highlighting the topography at the global field power maximum .. GENERATED FROM PYTHON SOURCE LINES 145-149 .. code-block:: Python t = trf.h.std('sensor').argmax('time') p = eelbrain.plot.TopoButterfly(trf.h, t=t, w=10, h=4, clip='circle') .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_005.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 150-151 Alternative visualization as array image .. GENERATED FROM PYTHON SOURCE LINES 151-154 .. code-block:: Python p = eelbrain.plot.TopoArray(trf.h, t=[0.050, 0.120, 0.150], w=6, h=4, clip='circle') .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_006.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 155-164 Predictive power ---------------- In order to derive an unbiased estimate of predictive power, we can use cross-validation. That means part of the data is never used while estimating the TRF, and can be used in the end to calculate how well the TRF can predict neural data. The :func:`boosting` function uses *K*-fold cross-validation. Cross-validation is enabled with the ``test=True`` parameter, and *K* is set through the ``partitions`` parameter. .. GENERATED FROM PYTHON SOURCE LINES 164-167 .. code-block:: Python trf_cv = eelbrain.boosting('eeg', 'onsets', 0, 0.500, data=events, basis=0.050, partitions=4, test=True) .. GENERATED FROM PYTHON SOURCE LINES 168-170 Plot the predictive power across sensors, including the average across all sensors in each figure title. .. GENERATED FROM PYTHON SOURCE LINES 170-179 .. code-block:: Python title = f"Mean exp: {trf_cv.proportion_explained.mean('sensor'):.2%}" p = eelbrain.plot.Topomap(trf_cv.proportion_explained, clip='circle', title=title) pcb = p.plot_colorbar('Proportion explained') title = f"Mean r: {trf_cv.r.mean('sensor'):.2}" p = eelbrain.plot.Topomap(trf_cv.r, clip='circle', title=title) pcb = p.plot_colorbar() .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_007.png :alt: Mean exp: 0.25% :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_007.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_008.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_008.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_009.png :alt: Mean r: 0.046 :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_009.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_010.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_010.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 180-183 Decoding -------- Train an envelope decoder on the first 11 trials and use it to decode the envelope of the last trial. .. GENERATED FROM PYTHON SOURCE LINES 183-187 .. code-block:: Python # Use a larger delta to speed up training decoder = eelbrain.boosting('envelope', 'eeg', -0.500, 0, data=events[:11], partitions=5, delta=0.05) .. GENERATED FROM PYTHON SOURCE LINES 188-192 Now use the decoder to reconstruct the envelope of the last trial. Note that, when using the :func:`~eelbrain.convolve` function, the time alignment is handled automatically because the kernel, ``decoder.h``, includes a time axis (``decoder.h.time``) with relative delays between input and output. .. GENERATED FROM PYTHON SOURCE LINES 192-199 .. code-block:: Python # Normalize the EEG eeg_11 = events[11, 'eeg'] / decoder.x_scale # Predict the envelope by convolving the decoder with the EEG y_pred = eelbrain.convolve(decoder.h, eeg_11, name='predicted envelope') .. GENERATED FROM PYTHON SOURCE LINES 200-201 Extract the actual envelope and adjust the scale for visualization .. GENERATED FROM PYTHON SOURCE LINES 201-210 .. code-block:: Python y = events[11, 'envelope'] y = y - decoder.y_mean y /= decoder.y_scale / y_pred.std() y.name = 'envelope' r = eelbrain.correlation_coefficient(y, y_pred) p = eelbrain.plot.UTS([[y_pred, y]], w=10, h=3, xlim=10, title=f"{r=}") .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_011.png :alt: r=0.2309358350597969 :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_011.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 211-212 Visualize the decoder weights .. GENERATED FROM PYTHON SOURCE LINES 212-214 .. code-block:: Python p = eelbrain.plot.TopoArray(decoder.h, w=6, h=4, clip='circle', t=[-0.160, -0.130, -0.100]) .. image-sg:: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_012.png :alt: alice trf :srcset: /auto_examples/temporal-response-functions/images/sphx_glr_alice-trf_012.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 42.465 seconds) .. _sphx_glr_download_auto_examples_temporal-response-functions_alice-trf.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: alice-trf.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: alice-trf.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: alice-trf.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_