.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/mass-univariate-statistics/sensor-ttest.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_mass-univariate-statistics_sensor-ttest.py: .. _exa-cluster-based-mu: T-test ====== .. currentmodule:: eelbrain This example show a cluster-based permutation test for a simple design (two conditions). The example uses simulated data meant to vaguely resemble data from an N400 experiment (not intended as a physiologically realistic simulation). .. contents:: Contents :local: .. GENERATED FROM PYTHON SOURCE LINES 19-22 .. code-block:: Python # sphinx_gallery_thumbnail_number = 3 from eelbrain import * .. GENERATED FROM PYTHON SOURCE LINES 23-28 Simulated data -------------- Each function call to :func:`datasets.simulate_erp` generates a dataset equivalent to an N400 experiment for one subject. The ``seed`` argument determines the random noise that is added to the data. .. GENERATED FROM PYTHON SOURCE LINES 28-31 .. code-block:: Python ds = datasets.simulate_erp(seed=0) print(ds.summary()) .. rst-class:: sphx-glr-script-out .. code-block:: none Key Type Values ------------------------------------------------------------------------- eeg NDVar 140 time, 65 sensor; -2.18933e-05 - 2.21674e-05 cloze Var 0.00563694 - 0.997675 predictability Factor high:40, low:40 n_chars Var 3:10, 4:20, 5:22, 6:16, 7:12 ------------------------------------------------------------------------- Dataset: 80 cases .. GENERATED FROM PYTHON SOURCE LINES 32-33 A singe trial of data: .. GENERATED FROM PYTHON SOURCE LINES 33-35 .. code-block:: Python p = plot.TopoButterfly('eeg[0]', data=ds, t=0.400) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_001.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 36-39 The :meth:`Dataset.aggregate` method computes condition averages when sorting the data into conditions of interest. In our case, the ``predictability`` variable specified conditions ``'high'`` and ``'low'`` cloze: .. GENERATED FROM PYTHON SOURCE LINES 39-41 .. code-block:: Python print(ds.aggregate('predictability')) .. rst-class:: sphx-glr-script-out .. code-block:: none # n cloze predictability n_chars ------------------------------------------- 0 40 0.88051 high 5 1 40 0.17241 low 5 ------------------------------------------- NDVars: eeg .. GENERATED FROM PYTHON SOURCE LINES 42-47 Group level data ---------------- This loop simulates a multi-subject experiment. It generates data and collects condition averages for 10 virtual subjects. For group level analysis, the collected data are combined in a :class:`Dataset`: .. GENERATED FROM PYTHON SOURCE LINES 47-62 .. code-block:: Python dss = [] for subject in range(10): # generate data for one subject ds = datasets.simulate_erp(seed=subject) # average across trials to get condition means ds_agg = ds.aggregate('predictability') # add the subject name as variable ds_agg[:, 'subject'] = f'S{subject:02}' dss.append(ds_agg) ds = combine(dss) # make subject a random factor (to treat it as random effect for ANOVA) ds['subject'].random = True ds.head() .. raw:: html
# n cloze predictability n_chars subject
0 40 0.88051 high 5 S00
1 40 0.17241 low 5 S00
2 40 0.89466 high 4.95 S01
3 40 0.13778 low 4.975 S01
4 40 0.90215 high 5.05 S02
5 40 0.12206 low 4.975 S02
6 40 0.88503 high 5.2 S03
7 40 0.14273 low 4.875 S03
8 40 0.90499 high 5.075 S04
9 40 0.15732 low 5.025 S04
NDVars: eeg


.. GENERATED FROM PYTHON SOURCE LINES 63-64 Re-reference the EEG data (i.e., subtract the mean of the two mastoid channels): .. GENERATED FROM PYTHON SOURCE LINES 64-66 .. code-block:: Python ds['eeg'] -= ds['eeg'].mean(sensor=['M1', 'M2']) .. GENERATED FROM PYTHON SOURCE LINES 67-74 Spatio-temporal cluster based test ---------------------------------- Cluster-based tests are based on identifying clusters of meaningful effects, i.e., groups of adjacent sensors that show the same effect (see :mod:`testnd` for references). In order to find clusters, the algorithm needs to know which channels are neighbors. This information is refered to as the sensor adjacency (i.e., which sensors are connected). The adjacency graph can be visualized to confirm that it is set correctly. .. GENERATED FROM PYTHON SOURCE LINES 74-76 .. code-block:: Python p = plot.SensorMap(ds['eeg'], adjacency=True) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_002.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 77-79 With the correct adjacency, we can now compute a cluster-based permutation test for a related measures *t*-test: .. GENERATED FROM PYTHON SOURCE LINES 79-86 .. code-block:: Python res = testnd.TTestRelated( 'eeg', 'predictability', 'low', 'high', match='subject', data=ds, pmin=0.05, # Use uncorrected p = 0.05 as threshold for forming clusters tstart=0.100, # Find clusters in the time window from 100 ... tstop=0.600, # ... to 600 ms ) .. rst-class:: sphx-glr-script-out .. code-block:: none Permutation test: 0%| | 0/1023 [00:00
# id tstart tstop duration n_sensors v p sig
0 54 0.33 0.48 0.15 58 -2268.3 0 ***


.. GENERATED FROM PYTHON SOURCE LINES 100-102 Retrieve the cluster map using its ID and visualize the spatio-temporal extent of the cluster: .. GENERATED FROM PYTHON SOURCE LINES 102-108 .. code-block:: Python cluster_id = clusters[0, 'id'] cluster = res.cluster(cluster_id) p = plot.TopoArray(cluster, interpolation='nearest', t=[0.350, 0.400, 0.450, None]) # plot the colorbar next to the right-most sensor plot p_cb = p.plot_colorbar(right_of=p.axes[3]) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_004.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 109-116 Using a cluster as functional ROI --------------------------------- Often it is desirable to summarize values in a cluster. This is especially useful in more complex designs. For example, after finding a signficant interaction effect in an ANOVA, one might want to follow up with a pairwise test of the value in the cluster. This can often be achieved using binary masks based on the cluster. Using the cluster identified above, generate a binary mask: .. GENERATED FROM PYTHON SOURCE LINES 116-119 .. code-block:: Python mask = cluster != 0 p = plot.TopoArray(mask, cmap='Wistia', t=[0.350, 0.400, 0.450]) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_005.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 120-125 Such a spatio-temporal boolean mask can be used to extract the value in the cluster for each condition/participant. Since ``mask`` contains both time and sensor dimensions, using it with the :meth:`NDVar.mean` method collapses across these dimensions and returns a scalar for each case (i.e., for each condition/subject). .. GENERATED FROM PYTHON SOURCE LINES 125-128 .. code-block:: Python ds['cluster_mean'] = ds['eeg'].mean(mask) p = plot.Barplot('cluster_mean', 'predictability', match='subject', data=ds, test=False) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_006.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 129-133 Similarly, a mask consisting of a cluster of sensors can be used to visualize the time course in that region of interest. A straight forward choice is to use all sensors that were part of the cluster (``mask``) at any point in time: .. GENERATED FROM PYTHON SOURCE LINES 133-136 .. code-block:: Python roi = mask.any('time') p = plot.Topomap(roi, cmap='Wistia') .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_007.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_007.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 137-140 When using a mask that ony contains a sensor dimension (``roi``), :meth:`NDVar.mean` collapses across sensors and returns a value for each time point, i.e. the time course in sensors involved in the cluster: .. GENERATED FROM PYTHON SOURCE LINES 140-145 .. code-block:: Python ds['cluster_timecourse'] = ds['eeg'].mean(roi) p = plot.UTSStat('cluster_timecourse', 'predictability', match='subject', data=ds, frame='t') # mark the duration of the spatio-temporal cluster p.set_clusters(clusters, y=0.25e-6) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_008.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_008.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 146-147 Now visualize the cluster topography, marking significant sensors: .. GENERATED FROM PYTHON SOURCE LINES 147-154 .. code-block:: Python time_window = (clusters[0, 'tstart'], clusters[0, 'tstop']) c1_topo = res.c1_mean.mean(time=time_window) c0_topo = res.c0_mean.mean(time=time_window) diff_topo = res.difference.mean(time=time_window) p = plot.Topomap([c1_topo, c0_topo, diff_topo], axtitle=['Low cloze', 'High cloze', 'Low - high'], columns=3) p.mark_sensors(roi, -1) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_009.png :alt: Low cloze, High cloze, Low - high :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_009.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 155-160 Temporal cluster based test --------------------------- Alternatively, if a spatial region of interest exists, a univariate time course can be extracted and submitted to a temporal cluster based test. For example, the N400 is typically expected to be strong at sensor ``Cz``: .. GENERATED FROM PYTHON SOURCE LINES 160-172 .. code-block:: Python ds['eeg_cz'] = ds['eeg'].sub(sensor='Cz') res_timecoure = testnd.TTestRelated( 'eeg_cz', 'predictability', 'low', 'high', match='subject', data=ds, pmin=0.05, # Use uncorrected p = 0.05 as threshold for forming clusters tstart=0.100, # Find clusters in the time window from 100 ... tstop=0.600, # ... to 600 ms ) clusters = res_timecoure.find_clusters(0.05) clusters p = plot.UTSStat('eeg_cz', 'predictability', match='subject', data=ds, frame='t') p.set_clusters(clusters, y=0.25e-6) .. image-sg:: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_010.png :alt: sensor ttest :srcset: /auto_examples/mass-univariate-statistics/images/sphx_glr_sensor-ttest_010.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Permutation test: 0%| | 0/1023 [00:00` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: sensor-ttest.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: sensor-ttest.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_