# ERP visualization -- how to plot confidence intervals/standard error of grand averaged ERP

**URL:** <https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747>\
**Category:** Support & Discussions\
**Tags:** eeg, visualization\
**Created:** [February 24, 2021, 3:10pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747 "2021-02-24T15:10:23Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![robpetrosino](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/robpetrosino/32/51_2.png) [@robpetrosino](https://mne.discourse.group/u/robpetrosino)\
**Post date:** [February 24, 2021, 3:10pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/1 "2021-02-24T15:10:23Z")

</div>

I can’t seem to find a way to plot grand-averaged ERPs together with shaded confidence intervals. The closest thing I could find is [here](https://mne.tools/stable/auto_tutorials/epochs/plot_20_visualize_epochs.html?highlight=confidence%20intervals#plotting-epochs-as-an-image-map), though I don’t want the image map.

Can anyone give me a hint? Thanks!

---

<div class="post-metadata">

**Author:** ![richard](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/richard/32/15_2.png) [@richard](https://mne.discourse.group/u/richard)\
**Post date:** [February 24, 2021, 3:47pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/2 "2021-02-24T15:47:37Z")

</div>

You can pass a dict of lists or a list of lists to [`plot_compare_evokeds`](https://mne.tools/stable/generated/mne.viz.plot_compare_evokeds.html) to produce (parametric) confidence bands.

---

<div class="post-metadata">

**Author:** ![robpetrosino](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/robpetrosino/32/51_2.png) [@robpetrosino](https://mne.discourse.group/u/robpetrosino)\
**Post date:** [March 2, 2021, 1:51pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/3 "2021-03-02T13:51:18Z")

</div>

> [@richard](#):
>
> a dict of lists or a list of lists

Could you give an example?

---

<div class="post-metadata">

**Author:** ![richard](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/richard/32/15_2.png) [@richard](https://mne.discourse.group/u/richard)\
**Post date:** [March 2, 2021, 3:41pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/4 "2021-03-02T15:41:49Z")

</div>

```python
# Load example data

import os
import mne

sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis_raw.fif')
raw = (mne.io.read_raw_fif(sample_data_raw_file, verbose=False)
       .pick_types(meg=False, eeg=True, stim=True)
       .load_data()
       .filter(l_freq=None, h_freq=40))
raw.set_eeg_reference('average')

events = mne.find_events(raw)
event_id = {'auditory/left': 1,
            'auditory/right': 2,
            'visual/left': 3,
            'visual/right': 4}
epochs = mne.Epochs(raw, events, event_id=event_id, preload=True)

orig_evoked_audio = epochs['auditory'].average()
orig_evoked_visual = epochs['visual'].average()

# Simulate 5 participants

all_evoked_audio = []
all_evoked_visual = []

cov = mne.make_ad_hoc_cov(raw.info)
iir_filter = [0.2, -0.2, 0.04]

for participant in range(5):
    evoked_audio = orig_evoked_audio.copy()
    evoked_visual = orig_evoked_visual.copy()

    mne.simulation.add_noise(evoked_audio, cov=cov,
                             iir_filter=iir_filter)
    mne.simulation.add_noise(evoked_visual, cov=cov,
                             iir_filter=iir_filter)
    
    all_evoked_audio.append(evoked_audio)
    all_evoked_visual.append(evoked_visual)

# Plot evokeds with 95% CIs

# list of lists
mne.viz.plot_compare_evokeds([all_evoked_audio,
                              all_evoked_visual],
                             ci=0.95)

# dict of lists
mne.viz.plot_compare_evokeds(dict(audio=all_evoked_audio,
                                  visual=all_evoked_visual),
                             ci=0.95)

```

---

<div class="post-metadata">

**Author:** ![robpetrosino](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/robpetrosino/32/51_2.png) [@robpetrosino](https://mne.discourse.group/u/robpetrosino)\
**Post date:** [March 2, 2021, 4:19pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/5 "2021-03-02T16:19:26Z")

</div>

Thanks, @richard!

I did a similar thing with my data, but I still don’t get shaded plotting of the CIs… do I also need to tweak the `color` and/or `cmap` arguments of the function?

---

<div class="post-metadata">

**Author:** ![richard](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/richard/32/15_2.png) [@richard](https://mne.discourse.group/u/richard)\
**Post date:** [March 2, 2021, 4:27pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/6 "2021-03-02T16:27:00Z")

</div>

> [@robpetrosino](#):
>
> do I also need to tweak the `color` and/or `cmap` arguments of the function?

No, it should work out of the box. You can try to request a different CI, e.g. 99%, by passing `ci=0.99`. This should make the confidence bands wider. If you still don’t see anything, then something is wrong with your data – maybe all evokeds are the same?

---

<div class="post-metadata">

**Author:** ![robpetrosino](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/robpetrosino/32/51_2.png) [@robpetrosino](https://mne.discourse.group/u/robpetrosino)\
**Post date:** [March 2, 2021, 4:47pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/7 "2021-03-02T16:47:03Z")

</div>

> [@richard](#):
>
> maybe all evokeds are the same?

Oops – I mistakenly plotted the grand-averages and not the evokeds. Thank you!!

---

<div class="post-metadata">

**Author:** ![robpetrosino](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/robpetrosino/32/51_2.png) [@robpetrosino](https://mne.discourse.group/u/robpetrosino)\
**Post date:** [April 5, 2021, 7:58am UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/8 "2021-04-05T07:58:54Z")

</div>

Quick question: how can I plot the grand average and its CIs of a _single_ condition?

Right now, I have all by-subjects evokeds of one condition listed in a single variable. I would like to plot the grand average of all evokeds for that condition? The module `mne.viz.plot_compare_evokeds()` seems to parse each subject as a different condition, but what I want is that the evokeds of all subjects were averaged together.

Thanks!

---

<div class="post-metadata">

**Author:** ![richard](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/richard/32/15_2.png) [@richard](https://mne.discourse.group/u/richard)\
**Post date:** [April 5, 2021, 10:02am UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/9 "2021-04-05T10:02:31Z")

</div>

Pass a list of your list of evokeds, or a dict of you lists of evokeds, as the first parameter of `plot_compare_evokeds()`.  
Quoting the documentation:

> … If a [dict/list] of lists, the unweighted mean is plotted as a time series and the parametric confidence interval is plotted as a shaded area. All instances must have the same shape - channel numbers, time points etc. If dict, keys must be of type str.

So you could do something like:

```python
mne.viz.plot_compare_evokeds({‘Mean’: list_of_evokeds}, ...)

```

---

<div class="post-metadata">

**Author:** ![robpetrosino](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/robpetrosino/32/51_2.png) [@robpetrosino](https://mne.discourse.group/u/robpetrosino)\
**Post date:** [April 5, 2021, 8:02pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/10 "2021-04-05T20:02:34Z")

</div>

Thanks!

Two follow-up questions, if I may:

1. Is there a way (within or outside `mne.viz.plot_compare_evokeds()`) to force tick labels of either axis. E.g., in my case the tick labels of the y-axis are printed by multiples of 2 (0, 2, 4, 6, etc.), but I would like to have all integers (0, 1, 2, 3, 4, etc.)

2. I am having trouble understanding how to plot multiple channels as subplots. The documentation says:

> [`Axes`](https://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes) object to plot into. If plotting multiple channel types (or multiple channels when `combine=None` ), `axes` should be a list of appropriate length containing [`Axes`](https://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes) objects. If `'topo'` , a new [`Figure`](https://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure) is created with one axis for each channel, in a topographical layout. If `None` , a new [`Figure`](https://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure) is created for each channel type. Defaults to `None` .

So, I tried to do the following:

```python
picks = ['E24', 'E36', 'E44', 'E69', 'E87']
    
axes = [plt.axes() for pick in picks]
    
mne.viz.plot_compare_evokeds({'mean': allEvokeds}, ylim=dict(eeg=[-5,5]), picks=picks,
                             title=None, axes=axes, ci=0.95, show_sensors=False, 
                             truncate_yaxis = False, truncate_xaxis=False, legend=False,
                             colors = {'mean': '#808080'}, combine=None)

```

But I must be doing something wrong, as no plot appears.

Thank you in advance!

---

<div class="post-metadata">

**Author:** ![drammock](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/drammock/32/4_2.png) [@drammock](https://mne.discourse.group/u/drammock)\
**Post date:** [April 5, 2021, 9:49pm UTC](https://mne.discourse.group/t/erp-visualization-how-to-plot-confidence-intervals-standard-error-of-grand-averaged-erp/2747/11 "2021-04-05T21:49:35Z")

</div>

For your second question, this part of the docstring is relevant:

> If `combine` is `None`, channels are combined by computing GFP,  
> unless `picks` is a single channel (not channel type) or  
> `axes='topo'`, in which cases no combining is performed.

In other words, you can’t pass in 5 picks and a list of 5 axes, and expect to get each channel on a separate subplot (it’s a reasonable thing to want to do, but it’s just not how the function is written).

Something like this ought to work:

```py
picks = ['E24', 'E36', 'E44', 'E69', 'E87']
fig, axes = plt.subplots(5, 1)
for pick, ax in zip(picks, axes):
    mne.viz.plot_compare_evokeds(evoked, combine=None, picks=pick, axes=ax)

```
