I am working on the file "0.21/_downloads/7f0f8817512fdcca1eab8f4befa07ff9/plot_metadata_query.ipynb".
The first task is:
First we'll create our metadata object. This should be a
:class:pandas.DataFrame with each row corresponding to an event.

Warning

Do not set or change the Dataframe index of ``epochs.metadata``.
             It will be controlled by MNE to mirror ``epochs.selection``.
             Also, while some inplace operations on ``epochs.metadata`` are
             possible, do not manually drop or add rows, as this will
             create inconsistency between the metadata and actual data.

Can you write Python code for it?

metadata = {'event_time': events[:, 0] / raw.info['sfreq'],
            'trial_number': range(len(events)),
            'kind': kinds,
            'side': sides}
metadata = pd.DataFrame(metadata)
metadata.head()


I am working on the file "0.21/_downloads/7f0f8817512fdcca1eab8f4befa07ff9/plot_metadata_query.ipynb".
The first task is:
It is possible to chain these queries together, giving you more expressive
ways to select particular epochs:
Can you write Python code for it?

query = 'trial_number < 10 and side == "left"'
plot_query_results(query)


I am working on the file "0.21/_downloads/7f0f8817512fdcca1eab8f4befa07ff9/plot_metadata_query.ipynb".
The first task is:
We can use this metadata object in the construction of an :class:mne.Epochs
object. The metadata will then exist as an attribute:
Can you write Python code for it?

epochs = mne.Epochs(raw, events, metadata=metadata, preload=True)
print(epochs.metadata.head())


I am working on the file "0.21/_downloads/7f0f8817512fdcca1eab8f4befa07ff9/plot_metadata_query.ipynb".
The first task is:
You can select rows by passing various queries to the Epochs object. For
example, you can select a subset of events based on the value of a column.
Can you write Python code for it?

query = 'kind == "auditory"'
plot_query_results(query)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Accepting a shallower roll-off of the filter in the frequency domain makes
our time-domain response potentially much better. We end up with a more
gradual slope through the transition region, but a much cleaner time
domain signal. Here again for the 1 s filter:
Can you write Python code for it?

h = signal.firwin2(n, freq, gain, nyq=nyq)
plot_filter(h, sfreq, freq, gain, 'Windowed 10 Hz transition (1.0 s)',
            flim=flim, compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
And now an example of a minimum-phase filter:
Can you write Python code for it?

h = mne.filter.create_filter(x, sfreq, l_freq=None, h_freq=f_p,
                             phase='minimum', fir_design='firwin',
                             verbose=True)
x_min = np.convolve(h, x)
transition_band = 0.25 * f_p
f_s = f_p + transition_band
filter_dur = 6.6 / transition_band  # sec
n = int(sfreq * filter_dur)
freq = [0., f_p, f_s, sfreq / 2.]
gain = [1., 1., 0., 0.]
plot_filter(h, sfreq, freq, gain, 'Minimum-phase filter', flim=flim)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Applying FIR filters
Now lets look at some practical effects of these filters by applying
them to some data.
Let's construct a Gaussian-windowed sinusoid (i.e., Morlet imaginary part)
plus noise (random and line). Note that the original clean signal contains
frequency content in both the pass band and transition bands of our
low-pass filter.
Can you write Python code for it?

dur = 10.
center = 2.
morlet_freq = f_p
tlim = [center - 0.2, center + 0.2]
tticks = [tlim[0], center, tlim[1]]
flim = [20, 70]

x = np.zeros(int(sfreq * dur) + 1)
blip = morlet(sfreq, [morlet_freq], n_cycles=7)[0].imag / 20.
n_onset = int(center * sfreq) - len(blip) // 2
x[n_onset:n_onset + len(blip)] += blip
x_orig = x.copy()

rng = np.random.RandomState(0)
x += rng.randn(len(x)) / 1000.
x += np.sin(2. * np.pi * 60. * np.arange(len(x)) / sfreq) / 2000.


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Applying IIR filters
Now let's look at how our shallow and steep Butterworth IIR filters
perform on our Morlet signal from before:
Can you write Python code for it?

axes = plt.subplots(1, 2)[1]
yticks = np.arange(4) / -30.
yticklabels = ['Original', 'Noisy', 'Butterworth-2', 'Butterworth-8']
plot_signal(x_orig, offset=yticks[0])
plot_signal(x, offset=yticks[1])
plot_signal(x_shallow, offset=yticks[2])
plot_signal(x_steep, offset=yticks[3])
axes[0].set(xlim=tlim, title='IIR, Lowpass=%d Hz' % f_p, xticks=tticks,
            ylim=[-0.125, 0.025], yticks=yticks, yticklabels=yticklabels,)
for text in axes[0].get_yticklabels():
    text.set(rotation=45, size=8)
axes[1].set(xlim=flim, ylim=(-60, 10), xlabel='Frequency (Hz)',
            ylabel='Magnitude (dB)')
mne.viz.adjust_axes(axes)
mne.viz.tight_layout()
plt.show()


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Background information on filtering
Here we give some background information on filtering in general, and
how it is done in MNE-Python in particular.
Recommended reading for practical applications of digital
filter design can be found in Parks & Burrus (1987) [1] and
Ifeachor & Jervis (2002) [2], and for filtering in an
M/EEG context we recommend reading Widmann et al. (2015) [7]_.
To see how to use the default filters in MNE-Python on actual data, see
the tut-filter-resample tutorial.
Problem statement
Practical issues with filtering electrophysiological data are covered
in Widmann et al. (2012) [6]_, where they conclude with this statement:
Filtering can result in considerable distortions of the time course
(and amplitude) of a signal as demonstrated by VanRullen (2011) [[3]_].
Thus, filtering should not be used lightly. However, if effects of
filtering are cautiously considered and filter artifacts are minimized,
a valid interpretation of the temporal dynamics of filtered
electrophysiological data is possible and signals missed otherwise
can be detected with filtering.

In other words, filtering can increase signal-to-noise ratio (SNR), but if it
is not used carefully, it can distort data. Here we hope to cover some
filtering basics so users can better understand filtering trade-offs and why
MNE-Python has chosen particular defaults.
Filtering basics
Let's get some of the basic math down. In the frequency domain, digital
filters have a transfer function that is given by:
\begin{align}H(z) &= \frac{b_0 + b_1 z^{-1} + b_2 z^{-2} + \ldots + b_M z^{-M}}
                 {1 + a_1 z^{-1} + a_2 z^{-2} + \ldots + a_N z^{-M}} \
         &= \frac{\sum_{k=0}^Mb_kz^{-k}}{\sum_{k=1}^Na_kz^{-k}}\end{align}
In the time domain, the numerator coefficients $b_k$ and denominator
coefficients $a_k$ can be used to obtain our output data
$y(n)$ in terms of our input data $x(n)$ as:
\begin{align}:label: summations
y(n) &= b_0 x(n) + b_1 x(n-1) + \ldots + b_M x(n-M)
        - a_1 y(n-1) - a_2 y(n - 2) - \ldots - a_N y(n -...
Can you write Python code for it?

import numpy as np
from numpy.fft import fft, fftfreq
from scipy import signal
import matplotlib.pyplot as plt

from mne.time_frequency.tfr import morlet
from mne.viz import plot_filter, plot_ideal_filter

import mne

sfreq = 1000.
f_p = 40.
flim = (1., sfreq / 2.)  # limits for plotting


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Both the MNE-Python 0.13 and MNE-C filters have excellent frequency
attenuation, but it comes at a cost of potential
ringing (long-lasting ripples) in the time domain. Ringing can occur with
steep filters, especially in signals with frequency content around the
transition band. Our Morlet wavelet signal has power in our transition band,
and the time-domain ringing is thus more pronounced for the steep-slope,
long-duration filter than the shorter, shallower-slope filter:
Can you write Python code for it?

axes = plt.subplots(1, 2)[1]

def plot_signal(x, offset):
    """Plot a signal."""
    t = np.arange(len(x)) / sfreq
    axes[0].plot(t, x + offset)
    axes[0].set(xlabel='Time (s)', xlim=t[[0, -1]])
    X = fft(x)
    freqs = fftfreq(len(x), 1. / sfreq)
    mask = freqs >= 0
    X = X[mask]
    freqs = freqs[mask]
    axes[1].plot(freqs, 20 * np.log10(np.maximum(np.abs(X), 1e-16)))
    axes[1].set(xlim=flim)

yscale = 30
yticklabels = ['Original', 'Noisy', 'FIR-firwin (0.16)', 'FIR-firwin2 (0.14)',
               'FIR-steep (0.13)', 'FIR-steep (MNE-C)', 'Minimum-phase']
yticks = -np.arange(len(yticklabels)) / yscale
plot_signal(x_orig, offset=yticks[0])
plot_signal(x, offset=yticks[1])
plot_signal(x_v16, offset=yticks[2])
plot_signal(x_v14, offset=yticks[3])
plot_signal(x_v13, offset=yticks[4])
plot_signal(x_mne_c, offset=yticks[5])
plot_signal(x_min, offset=yticks[6])
axes[0].set(xlim=tlim, title='FIR, Lowpass=%d Hz' % f_p, xticks=tticks,
            ylim=[-len(yticks) / yscale, 1. / yscale],
            yticks=yticks, yticklabels=yticklabels)
for text in axes[0].get_yticklabels():
    text.set(rotation=45, size=8)
axes[1].set(xlim=flim, ylim=(-60, 10), xlabel='Frequency (Hz)',
            ylabel='Magnitude (dB)')
mne.viz.tight_layout()
plt.show()


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
But if we shorten the filter too much (2 cycles of 10 Hz = 0.2 s),
our effective stop frequency gets pushed out past 60 Hz:
Can you write Python code for it?

n = int(round(sfreq * 0.2)) + 1
h = signal.firwin2(n, freq, gain, nyq=nyq)
plot_filter(h, sfreq, freq, gain, 'Windowed 10 Hz transition (0.2 s)',
            flim=flim, compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Filter it with a different design method fir_design="firwin2", and also
compensate for the constant filter delay. This method does not produce
quite as sharp a transition compared to fir_design="firwin", despite
being twice as long:
Can you write Python code for it?

transition_band = 0.25 * f_p
f_s = f_p + transition_band
freq = [0., f_p, f_s, sfreq / 2.]
gain = [1., 1., 0., 0.]
# This would be equivalent:
# filter_dur = 6.6 / transition_band  # sec
# n = int(sfreq * filter_dur)
# h = signal.firwin2(n, freq, gain, nyq=sfreq / 2.)
h = mne.filter.create_filter(x, sfreq, l_freq=None, h_freq=f_p,
                             fir_design='firwin2', verbose=True)
x_v14 = np.convolve(h, x)[len(h) // 2:]

plot_filter(h, sfreq, freq, gain, 'MNE-Python 0.14 default', flim=flim,
            compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
If we want a filter that is only 0.1 seconds long, we should probably use
something more like a 25 Hz transition band (0.2 s = 5 cycles @ 25 Hz):
Can you write Python code for it?

trans_bandwidth = 25
f_s = f_p + trans_bandwidth
freq = [0, f_p, f_s, nyq]
h = signal.firwin2(n, freq, gain, nyq=nyq)
plot_filter(h, sfreq, freq, gain, 'Windowed 50 Hz transition (0.2 s)',
            flim=flim, compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
In response, Maess et al. (2016) [11]_ note that these simulations do not
address cases of pre-stimulus activity that is shared across conditions, as
applying baseline correction will effectively copy the topology outside the
baseline period. We can see this if we give our signal x with some
consistent pre-stimulus activity, which makes everything look bad.

Note

An important thing to keep in mind with these plots is that they
          are for a single simulated sensor. In multi-electrode recordings
          the topology (i.e., spatial pattern) of the pre-stimulus activity
          will leak into the post-stimulus period. This will likely create a
          spatially varying distortion of the time-domain signals, as the
          averaged pre-stimulus spatial pattern gets subtracted from the
          sensor time courses.

Putting some activity in the baseline period:
Can you write Python code for it?

n_pre = (t < 0).sum()
sig_pre = 1 - np.cos(2 * np.pi * np.arange(n_pre) / (0.5 * n_pre))
x[:n_pre] += sig_pre
baseline_plot(x)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Let's also filter it with the MNE-C default, which is a long-duration
steep-slope FIR filter designed using frequency-domain techniques:
Can you write Python code for it?

h = mne.filter.design_mne_c_filter(sfreq, l_freq=None, h_freq=f_p + 2.5)
x_mne_c = np.convolve(h, x)[len(h) // 2:]

transition_band = 5  # Hz (default in MNE-C)
f_s = f_p + transition_band
freq = [0., f_p, f_s, sfreq / 2.]
gain = [1., 1., 0., 0.]
plot_filter(h, sfreq, freq, gain, 'MNE-C default', flim=flim, compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Let's also filter with the MNE-Python 0.13 default, which is a
long-duration, steep cutoff FIR that gets applied twice:
Can you write Python code for it?

transition_band = 0.5  # Hz
f_s = f_p + transition_band
filter_dur = 10.  # sec
freq = [0., f_p, f_s, sfreq / 2.]
gain = [1., 1., 0., 0.]
# This would be equivalent
# n = int(sfreq * filter_dur)
# h = signal.firwin2(n, freq, gain, nyq=sfreq / 2.)
h = mne.filter.create_filter(x, sfreq, l_freq=None, h_freq=f_p,
                             h_trans_bandwidth=transition_band,
                             filter_length='%ss' % filter_dur,
                             fir_design='firwin2', verbose=True)
x_v13 = np.convolve(np.convolve(h, x)[::-1], h)[::-1][len(h) - 1:-len(h) - 1]
# the effective h is one that is applied to the time-reversed version of itself
h_eff = np.convolve(h, h[::-1])
plot_filter(h_eff, sfreq, freq, gain, 'MNE-Python 0.13 default', flim=flim,
            compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Similarly, in a P300 paradigm reported by Kappenman & Luck (2010) [12]_,
they found that applying a 1 Hz high-pass decreased the probability of
finding a significant difference in the N100 response, likely because
the P300 response was smeared (and inverted) in time by the high-pass
filter such that it tended to cancel out the increased N100. However,
they nonetheless note that some high-passing can still be useful to deal
with drifts in the data.
Even though these papers generally advise a 0.1 Hz or lower frequency for
a high-pass, it is important to keep in mind (as most authors note) that
filtering choices should depend on the frequency content of both the
signal(s) of interest and the noise to be suppressed. For example, in
some of the MNE-Python examples involving sample-data,
high-pass values of around 1 Hz are used when looking at auditory
or visual N100 responses, because we analyze standard (not deviant) trials
and thus expect that contamination by later or slower components will
be limited.
Baseline problems (or solutions?)
In an evolving discussion, Tanner et al. (2015) [8] suggest using baseline
correction to remove slow drifts in data. However, Maess et al. (2016) [9]
suggest that baseline correction, which is a form of high-passing, does
not offer substantial advantages over standard high-pass filtering.
Tanner et al. (2016) [10]_ rebutted that baseline correction can correct
for problems with filtering.
To see what they mean, consider again our old simulated signal x from
before:
Can you write Python code for it?

def baseline_plot(x):
    all_axes = plt.subplots(3, 2)[1]
    for ri, (axes, freq) in enumerate(zip(all_axes, [0.1, 0.3, 0.5])):
        for ci, ax in enumerate(axes):
            if ci == 0:
                iir_hp = signal.iirfilter(4, freq / sfreq, btype='highpass',
                                          output='sos')
                x_hp = signal.sosfiltfilt(iir_hp, x, padlen=0)
            else:
                x_hp -= x_hp[t < 0].mean()
            ax.plot(t, x, color='0.5')
            ax.plot(t, x_hp, color='k', linestyle='--')
            if ri == 0:
                ax.set(title=('No ' if ci == 0 else '') +
                       'Baseline Correction')
            ax.set(xticks=tticks, ylim=ylim, xlim=xlim, xlabel=xlabel)
            ax.set_ylabel('%0.1f Hz' % freq, rotation=0,
                          horizontalalignment='right')
        mne.viz.adjust_axes(axes)
    mne.viz.tight_layout()
    plt.suptitle(title)
    plt.show()

baseline_plot(x)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Since our lowpass is around 40 Hz with a 10 Hz transition, we can actually
use a shorter filter (5 cycles at 10 Hz = 0.5 s) and still get acceptable
stop-band attenuation:
Can you write Python code for it?

n = int(round(sfreq * 0.5)) + 1
h = signal.firwin2(n, freq, gain, nyq=nyq)
plot_filter(h, sfreq, freq, gain, 'Windowed 10 Hz transition (0.5 s)',
            flim=flim, compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
So far, we have only discussed non-causal filtering, which means that each
sample at each time point $t$ is filtered using samples that come
after ($t + \Delta t$) and before ($t - \Delta t$) the current
time point $t$.
In this sense, each sample is influenced by samples that come both before
and after it. This is useful in many cases, especially because it does not
delay the timing of events.
However, sometimes it can be beneficial to use causal filtering,
whereby each sample $t$ is filtered only using time points that came
after it.
Note that the delay is variable (whereas for linear/zero-phase filters it
is constant) but small in the pass-band. Unlike zero-phase filters, which
require time-shifting backward the output of a linear-phase filtering stage
(and thus becoming non-causal), minimum-phase filters do not require any
compensation to achieve small delays in the pass-band. Note that as an
artifact of the minimum phase filter construction step, the filter does
not end up being as steep as the linear/zero-phase version.
We can construct a minimum-phase filter from our existing linear-phase
filter with the :func:scipy.signal.minimum_phase function, and note
that the falloff is not as steep:
Can you write Python code for it?

h_min = signal.minimum_phase(h)
plot_filter(h_min, sfreq, freq, gain, 'Minimum-phase', flim=flim)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Some pitfalls of filtering
Multiple recent papers have noted potential risks of drawing
errant inferences due to misapplication of filters.
Low-pass problems
Filters in general, especially those that are non-causal (zero-phase), can
make activity appear to occur earlier or later than it truly did. As
mentioned in VanRullen (2011) [3], investigations of commonly (at the time)
used low-pass filters created artifacts when they were applied to simulated
data. However, such deleterious effects were minimal in many real-world
examples in Rousselet (2012) [5].
Perhaps more revealing, it was noted in Widmann & Schröger (2012) [6] that
the problematic low-pass filters from VanRullen (2011) [3]:

Used a least-squares design (like :func:scipy.signal.firls) that
      included "do-not-care" transition regions, which can lead to
      uncontrolled behavior.
Had a filter length that was independent of the transition bandwidth,
      which can cause excessive ringing and signal distortion.

High-pass problems
When it comes to high-pass filtering, using corner frequencies above 0.1 Hz
were found in Acunzo et al. (2012) [4]_ to:
"... generate a systematic bias easily leading to misinterpretations of
   neural activity.”
In a related paper, Widmann et al. (2015) [7] also came to suggest a
0.1 Hz highpass. More evidence followed in Tanner et al. (2015) [8] of
such distortions. Using data from language ERP studies of semantic and
syntactic processing (i.e., N400 and P600), using a high-pass above 0.3 Hz
caused significant effects to be introduced implausibly early when compared
to the unfiltered data. From this, the authors suggested the optimal
high-pass value for language processing to be 0.1 Hz.
We can recreate a problematic simulation from Tanner et al. (2015) [8]_:
"The simulated component is a single-cycle cosine wave with an amplitude
   of 5µV [sic], onset of 500 ms poststimulus, and duration of 800 ms. The
   simulated component was embedded in 20 s of zero values to avoid
   filtering edge effects... Distortions [were]...
Can you write Python code for it?

x = np.zeros(int(2 * sfreq))
t = np.arange(0, len(x)) / sfreq - 0.2
onset = np.where(t >= 0.5)[0][0]
cos_t = np.arange(0, int(sfreq * 0.8)) / sfreq
sig = 2.5 - 2.5 * np.cos(2 * np.pi * (1. / 0.8) * cos_t)
x[onset:onset + len(sig)] = sig

iir_lp_30 = signal.iirfilter(2, 30. / sfreq, btype='lowpass')
iir_hp_p1 = signal.iirfilter(2, 0.1 / sfreq, btype='highpass')
iir_lp_2 = signal.iirfilter(2, 2. / sfreq, btype='lowpass')
iir_hp_2 = signal.iirfilter(2, 2. / sfreq, btype='highpass')
x_lp_30 = signal.filtfilt(iir_lp_30[0], iir_lp_30[1], x, padlen=0)
x_hp_p1 = signal.filtfilt(iir_hp_p1[0], iir_hp_p1[1], x, padlen=0)
x_lp_2 = signal.filtfilt(iir_lp_2[0], iir_lp_2[1], x, padlen=0)
x_hp_2 = signal.filtfilt(iir_hp_2[0], iir_hp_2[1], x, padlen=0)

xlim = t[[0, -1]]
ylim = [-2, 6]
xlabel = 'Time (sec)'
ylabel = r'Amplitude ($\mu$V)'
tticks = [0, 0.5, 1.3, t[-1]]
axes = plt.subplots(2, 2)[1].ravel()
for ax, x_f, title in zip(axes, [x_lp_2, x_lp_30, x_hp_2, x_hp_p1],
                          ['LP$_2$', 'LP$_{30}$', 'HP$_2$', 'LP$_{0.1}$']):
    ax.plot(t, x, color='0.5')
    ax.plot(t, x_f, color='k', linestyle='--')
    ax.set(ylim=ylim, xlim=xlim, xticks=tticks,
           title=title, xlabel=xlabel, ylabel=ylabel)
mne.viz.adjust_axes(axes)
mne.viz.tight_layout()
plt.show()


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
Take for example an ideal low-pass filter, which would give a magnitude
response of 1 in the pass-band (up to frequency $f_p$) and a magnitude
response of 0 in the stop-band (down to frequency $f_s$) such that
$f_p=f_s=40$ Hz here (shown to a lower limit of -60 dB for simplicity):
Can you write Python code for it?

nyq = sfreq / 2.  # the Nyquist frequency is half our sample rate
freq = [0, f_p, f_p, nyq]
gain = [1, 1, 0, 0]

third_height = np.array(plt.rcParams['figure.figsize']) * [1, 1. / 3.]
ax = plt.subplots(1, figsize=third_height)[1]
plot_ideal_filter(freq, gain, ax, title='Ideal %s Hz lowpass' % f_p, flim=flim)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
The falloff of this filter is not very steep.

Note

Here we have made use of second-order sections (SOS)
          by using :func:`scipy.signal.sosfilt` and, under the
          hood, :func:`scipy.signal.zpk2sos` when passing the
          ``output='sos'`` keyword argument to
          :func:`scipy.signal.iirfilter`. The filter definitions
          given `above <tut_filtering_basics>` use the polynomial
          numerator/denominator (sometimes called "tf") form ``(b, a)``,
          which are theoretically equivalent to the SOS form used here.
          In practice, however, the SOS form can give much better results
          due to issues with numerical precision (see
          :func:`scipy.signal.sosfilt` for an example), so SOS should be
          used whenever possible.

Let's increase the order, and note that now we have better attenuation,
with a longer impulse response. Let's also switch to using the MNE filter
design function, which simplifies a few things and gives us some information
about the resulting filter:
Can you write Python code for it?

iir_params = dict(order=8, ftype='butter')
filt = mne.filter.create_filter(x, sfreq, l_freq=None, h_freq=f_p,
                                method='iir', iir_params=iir_params,
                                verbose=True)
plot_filter(filt, sfreq, freq, gain, 'Butterworth order=8', flim=flim,
            compensate=True)
x_steep = signal.sosfiltfilt(filt['sos'], x)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
There are other types of IIR filters that we can use. For a complete list,
check out the documentation for :func:scipy.signal.iirdesign. Let's
try a Chebychev (type I) filter, which trades off ripple in the pass-band
to get better attenuation in the stop-band:
Can you write Python code for it?

iir_params.update(ftype='cheby1',
                  rp=1.,  # dB of acceptable pass-band ripple
                  )
filt = mne.filter.create_filter(x, sfreq, l_freq=None, h_freq=f_p,
                                method='iir', iir_params=iir_params,
                                verbose=True)
plot_filter(filt, sfreq, freq, gain,
            'Chebychev-1 order=8, ripple=1 dB', flim=flim, compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
This filter hypothetically achieves zero ripple in the frequency domain,
perfect attenuation, and perfect steepness. However, due to the discontinuity
in the frequency response, the filter would require infinite ringing in the
time domain (i.e., infinite order) to be realized. Another way to think of
this is that a rectangular window in the frequency domain is actually a sinc_
function in the time domain, which requires an infinite number of samples
(and thus infinite time) to represent. So although this filter has ideal
frequency suppression, it has poor time-domain characteristics.
Let's try to naïvely make a brick-wall filter of length 0.1 s, and look
at the filter itself in the time domain and the frequency domain:
Can you write Python code for it?

n = int(round(0.1 * sfreq))
n -= n % 2 - 1  # make it odd
t = np.arange(-(n // 2), n // 2 + 1) / sfreq  # center our sinc
h = np.sinc(2 * f_p * t) / (4 * np.pi)
plot_filter(h, sfreq, freq, gain, 'Sinc (0.1 s)', flim=flim, compensate=True)


I am working on the file "0.21/_downloads/80342e62fc31882c2b53e38ec1ed14a6/plot_background_filtering.ipynb".
The first task is:
This is not so good! Making the filter 10 times longer (1 s) gets us a
slightly better stop-band suppression, but still has a lot of ringing in
the time domain. Note the x-axis is an order of magnitude longer here,
and the filter has a correspondingly much longer group delay (again equal
to half the filter length, or 0.5 seconds):
Can you write Python code for it?

n = int(round(1. * sfreq))
n -= n % 2 - 1  # make it odd
t = np.arange(-(n // 2), n // 2 + 1) / sfreq
h = np.sinc(2 * f_p * t) / (4 * np.pi)
plot_filter(h, sfreq, freq, gain, 'Sinc (1.0 s)', flim=flim, compensate=True)


I am working on the file "0.21/_downloads/82590448493c884f52ea0c7ddc5b446b/plot_publication_figure.ipynb".
The first task is:
A lot of figure settings can be adjusted after the figure is created, but
many can also be adjusted in advance by updating the
:data:~matplotlib.rcParams dictionary. This is especially useful when your
script generates several figures that you want to all have the same style:
Can you write Python code for it?

# Tweak the figure style
plt.rcParams.update({
    'ytick.labelsize': 'small',
    'xtick.labelsize': 'small',
    'axes.labelsize': 'small',
    'axes.titlesize': 'medium',
    'grid.color': '0.75',
    'grid.linestyle': ':',
})


I am working on the file "0.21/_downloads/82590448493c884f52ea0c7ddc5b446b/plot_publication_figure.ipynb".
The first task is:
During interactive plotting, we might see figures like this:
Can you write Python code for it?

evoked.plot()

stc.plot(views='lat', hemi='split', size=(800, 400), subject='sample',
         subjects_dir=subjects_dir, initial_time=max_t,
         time_viewer=False, show_traces=False)


I am working on the file "0.21/_downloads/82590448493c884f52ea0c7ddc5b446b/plot_publication_figure.ipynb".
The first task is:
Now let's crop out the white margins and the white gap between hemispheres.
The screenshot has dimensions (h, w, 3), with the last axis being R, G, B
values for each pixel, encoded as integers between 0 and 255. (255,
255, 255) encodes a white pixel, so we'll detect any pixels that differ
from that:
Can you write Python code for it?

nonwhite_pix = (screenshot != 255).any(-1)
nonwhite_row = nonwhite_pix.any(1)
nonwhite_col = nonwhite_pix.any(0)
cropped_screenshot = screenshot[nonwhite_row][:, nonwhite_col]

# before/after results
fig = plt.figure(figsize=(4, 4))
axes = ImageGrid(fig, 111, nrows_ncols=(2, 1), axes_pad=0.5)
for ax, image, title in zip(axes, [screenshot, cropped_screenshot],
                            ['Before', 'After']):
    ax.imshow(image)
    ax.set_title('{} cropping'.format(title))


I am working on the file "0.21/_downloads/82590448493c884f52ea0c7ddc5b446b/plot_publication_figure.ipynb".
The first task is:
Suppose we want a figure with an evoked plot on top, and the brain activation
below, with the brain subplot slightly bigger than the evoked plot. Let's
start by loading some example data <sample-dataset>.
Can you write Python code for it?

data_path = mne.datasets.sample.data_path()
subjects_dir = op.join(data_path, 'subjects')
fname_stc = op.join(data_path, 'MEG', 'sample', 'sample_audvis-meg-eeg-lh.stc')
fname_evoked = op.join(data_path, 'MEG', 'sample', 'sample_audvis-ave.fif')

evoked = mne.read_evokeds(fname_evoked, 'Left Auditory')
evoked.pick_types(meg='grad').apply_baseline((None, 0.))
max_t = evoked.get_peak()[1]

stc = mne.read_source_estimate(fname_stc)


I am working on the file "0.21/_downloads/82590448493c884f52ea0c7ddc5b446b/plot_publication_figure.ipynb".
The first task is:
To make a publication-ready figure, first we'll re-plot the brain on a white
background, take a screenshot of it, and then crop out the white margins.
While we're at it, let's change the colormap, set custom colormap limits and
remove the default colorbar (so we can add a smaller, vertical one later):
Can you write Python code for it?

colormap = 'viridis'
clim = dict(kind='value', lims=[4, 8, 12])

# Plot the STC, get the brain image, crop it:
brain = stc.plot(views='lat', hemi='split', size=(800, 400), subject='sample',
                 subjects_dir=subjects_dir, initial_time=max_t, background='w',
                 colorbar=False, clim=clim, colormap=colormap,
                 time_viewer=False, show_traces=False)
screenshot = brain.screenshot()
brain.close()


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
About the data
In the original LIMO experiment (see [2]), participants performed a
two-alternative forced choice task, discriminating between two face stimuli.
The same two faces were used during the whole experiment,
with varying levels of noise added, making the faces more or less
discernible to the observer (see Fig 1 in [3]_ for a similar approach).
The presented faces varied across a noise-signal (or phase-coherence)
continuum spanning from 0 to 85% in increasing steps of 5%.
In other words, faces with high phase-coherence (e.g., 85%) were easy to
identify, while faces with low phase-coherence (e.g., 5%) were hard to
identify and by extension very hard to discriminate.
Load the data
We'll begin by loading the data from subject 1 of the LIMO dataset.
Can you write Python code for it?

# This step can take a little while if you're loading the data for the
# first time.
limo_epochs = load_data(subject=subj)


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
As expected, no clear pattern appears when contrasting
Face A and Face B. However, we could narrow our search a little bit more.
Since this is a "visual paradigm" it might be best to look at electrodes
located over the occipital lobe, as differences between stimuli (if any)
might easier to spot over visual areas.
Can you write Python code for it?

# Create a dictionary containing the evoked responses
conditions = ["Face/A", "Face/B"]
evokeds = {condition: limo_epochs[condition].average()
           for condition in conditions}

# concentrate analysis an occipital electrodes (e.g. B11)
pick = evokeds["Face/A"].ch_names.index('B11')

# compare evoked responses
plot_compare_evokeds(evokeds, picks=pick, ylim=dict(eeg=(-15, 7.5)))


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
As it can be seen above, conditions are coded as Face/A and Face/B.
Information about the phase-coherence of the presented faces is stored in the
epochs metadata. These information can be easily accessed by calling
limo_epochs.metadata. As shown below, the epochs metadata also contains
information about the presented faces for convenience.
Can you write Python code for it?


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Conversely, there appears to be no (or very small) systematic effects when
comparing Face A and Face B stimuli. This is largely consistent with the
difference wave approach presented above.
Can you write Python code for it?

ts_args = dict(xlim=(-0.25, 0.5))

reg['face a - face b'].beta.plot_joint(ts_args=ts_args,
                                       title='Effect of Face A vs. Face B',
                                       times=[0.23])


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Define predictor variables and design matrix
To run the regression analysis,
we need to create a design matrix containing information about the
variables (i.e., predictors) we want to use for prediction of brain
activity patterns. For this purpose, we'll use the information we have in
limo_epochs.metadata: phase-coherence and Face A vs. Face B.
Can you write Python code for it?

# name of predictors + intercept
predictor_vars = ['face a - face b', 'phase-coherence', 'intercept']

# create design matrix
design = limo_epochs.metadata[['phase-coherence', 'face']].copy()
design['face a - face b'] = np.where(design['face'] == 'A', 1, -1)
design['intercept'] = 1
design = design[predictor_vars]


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Extract regression coefficients
The results are stored within the object reg,
which is a dictionary of evoked objects containing
multiple inferential measures for each predictor in the design matrix.
Can you write Python code for it?

print('predictors are:', list(reg))
print('fields are:', [field for field in getattr(reg['intercept'], '_fields')])


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Note that the result of the loading process is an
:class:mne.EpochsArray containing the data ready to interface
with MNE-Python.
Can you write Python code for it?


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Now let's take a closer look at the information in the epochs
metadata.
Can you write Python code for it?

# We want include all columns in the summary table
epochs_summary = limo_epochs.metadata.describe(include='all').round(3)
print(epochs_summary)


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Now we can set up the linear model to be used in the analysis using
MNE-Python's func:~mne.stats.linear_regression function.
Can you write Python code for it?

reg = linear_regression(limo_epochs,
                        design_matrix=design,
                        names=predictor_vars)


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Plot model results
Now we can access and plot the results of the linear regression analysis by
calling :samp:reg['{<name of predictor>}'].{<measure of interest>} and
using the
:meth:~mne.Evoked.plot_joint method just as we would do with any other
evoked object.
Below we can see a clear effect of phase-coherence, with higher
phase-coherence (i.e., better "face visibility") having a negative effect on
the activity measured at occipital electrodes around 200 to 250 ms following
stimulus onset.
Can you write Python code for it?

reg['phase-coherence'].beta.plot_joint(ts_args=ts_args,
                                       title='Effect of Phase-coherence',
                                       times=[0.23])


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Single trial linear regression analysis with the LIMO dataset
Here we explore the structure of the data contained in the
LIMO dataset.
This example replicates and extends some of the main analysis
and tools integrated in LIMO MEEG, a MATLAB toolbox originally designed
to interface with EEGLAB_.
In summary, the example:

Fetches epoched data files for a single subject of the LIMO dataset [1]_.
  If the LIMO files are not found on disk, the
  fetcher :func:mne.datasets.limo.load_data() will automatically download
  the files from a remote repository.

During import, information about the data (i.e., sampling rate, number of
  epochs per condition, number and name of EEG channels per subject, etc.) is
  extracted from the LIMO :file:.mat files stored on disk and added to the
  epochs structure as metadata.

Fits linear models on the single subject's data and visualizes inferential
  measures to evaluate the significance of the estimated effects.

References
.. [1] Guillaume, Rousselet. (2016). LIMO EEG Dataset, [dataset].
       University of Edinburgh, Centre for Clinical Brain Sciences.
       https://doi.org/10.7488/ds/1556.
.. [2] Rousselet, G. A., Gaspar, C. M., Pernet, C. R., Husk, J. S.,
       Bennett, P. J., & Sekuler, A. B. (2010). Healthy aging delays scalp EEG
       sensitivity to noise in a face discrimination task.
       Frontiers in psychology, 1, 19. https://doi.org/10.3389/fpsyg.2010.00019
.. [3] Rousselet, G. A., Pernet, C. R., Bennett, P. J., & Sekuler, A. B.
       (2008). Parametric study of EEG sensitivity to phase noise during face
       processing. BMC neuroscience, 9(1), 98.
       https://doi.org/10.1186/1471-2202-9-98
Can you write Python code for it?

# Authors: Jose C. Garcia Alanis <alanis.jcg@gmail.com>
#
# License: BSD (3-clause)

import numpy as np
import matplotlib.pyplot as plt

from mne.datasets.limo import load_data
from mne.stats import linear_regression
from mne.viz import plot_events, plot_compare_evokeds
from mne import combine_evoked

print(__doc__)

# subject to use
subj = 1


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
Visualize events
We can visualise the distribution of the face events contained in the
limo_epochs structure. Events should appear clearly grouped, as the
epochs are ordered by condition.
Can you write Python code for it?

fig = plot_events(limo_epochs.events, event_id=limo_epochs.event_id)
fig.suptitle("Distribution of events in LIMO epochs")


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
We can also plot the corresponding T values.
Can you write Python code for it?

# use unit=False and scale=1 to keep values at their original
# scale (i.e., avoid conversion to micro-volt).
ts_args = dict(xlim=(-0.25, 0.5),
               unit=False)
topomap_args = dict(scalings=dict(eeg=1),
                    average=0.05)

fig = reg['phase-coherence'].t_val.plot_joint(ts_args=ts_args,
                                              topomap_args=topomap_args,
                                              times=[0.23])
fig.axes[0].set_ylabel('T-value')


I am working on the file "0.21/_downloads/85b80d223414f32365a9175978a38cb4/plot_limo_data.ipynb".
The first task is:
We do see a difference between Face A and B, but it is pretty small.
Visualize effect of stimulus phase-coherence
Since phase-coherence
determined whether a face stimulus could be easily identified,
one could expect that faces with high phase-coherence should evoke stronger
activation patterns along occipital electrodes.
Can you write Python code for it?

phase_coh = limo_epochs.metadata['phase-coherence']
# get levels of phase coherence
levels = sorted(phase_coh.unique())
# create labels for levels of phase coherence (i.e., 0 - 85%)
labels = ["{0:.2f}".format(i) for i in np.arange(0., 0.90, 0.05)]

# create dict of evokeds for each level of phase-coherence
evokeds = {label: limo_epochs[phase_coh == level].average()
           for level, label in zip(levels, labels)}

# pick channel to plot
electrodes = ['C22', 'B11']
# create figures
for electrode in electrodes:
    fig, ax = plt.subplots(figsize=(8, 4))
    plot_compare_evokeds(evokeds,
                         axes=ax,
                         ylim=dict(eeg=(-20, 15)),
                         picks=electrode,
                         cmap=("Phase coherence", "magma"))


I am working on the file "0.21/_downloads/8763e6c899a8b9971980be1308b5f693/plot_dics.ipynb".
The first task is:
Now we put the signals at two locations on the cortex. We construct a
:class:mne.SourceEstimate object to store them in.
The timeseries will have a part where the signal is active and a part where
it is not. The techniques we'll be using in this tutorial depend on being
able to contrast data that contains the signal of interest versus data that
does not (i.e. it contains only noise).
Can you write Python code for it?

# The locations on the cortex where the signal will originate from. These
# locations are indicated as vertex numbers.
vertices = [[146374], [33830]]

# Construct SourceEstimates that describe the signals at the cortical level.
data = np.vstack((signal1, signal2))
stc_signal = mne.SourceEstimate(
    data, vertices, tmin=0, tstep=1. / sfreq, subject='sample')
stc_noise = stc_signal * 0.


I am working on the file "0.21/_downloads/8763e6c899a8b9971980be1308b5f693/plot_dics.ipynb".
The first task is:
Setup
We first import the required packages to run this tutorial and define a list
of filenames for various things we'll be using.
Can you write Python code for it?

import os.path as op
import numpy as np
from scipy.signal import welch, coherence, unit_impulse
from matplotlib import pyplot as plt

import mne
from mne.simulation import simulate_raw, add_noise
from mne.datasets import sample
from mne.minimum_norm import make_inverse_operator, apply_inverse
from mne.time_frequency import csd_morlet
from mne.beamformer import make_dics, apply_dics_csd

# We use the MEG and MRI setup from the MNE-sample dataset
data_path = sample.data_path(download=False)
subjects_dir = op.join(data_path, 'subjects')

# Filenames for various files we'll be using
meg_path = op.join(data_path, 'MEG', 'sample')
raw_fname = op.join(meg_path, 'sample_audvis_raw.fif')
fwd_fname = op.join(meg_path, 'sample_audvis-meg-eeg-oct-6-fwd.fif')
cov_fname = op.join(meg_path, 'sample_audvis-cov.fif')
fwd = mne.read_forward_solution(fwd_fname)

# Seed for the random number generator
rand = np.random.RandomState(42)


I am working on the file "0.21/_downloads/8763e6c899a8b9971980be1308b5f693/plot_dics.ipynb".
The first task is:
We create an :class:mne.Epochs object containing two trials: one with
both noise and signal and one with just noise
Can you write Python code for it?

events = mne.find_events(raw, initial_event=True)
tmax = (len(stc_signal.times) - 1) / sfreq
epochs = mne.Epochs(raw, events, event_id=dict(signal=1, noise=2),
                    tmin=0, tmax=tmax, baseline=None, preload=True)
assert len(epochs) == 2  # ensure that we got the two expected events

# Plot some of the channels of the simulated data that are situated above one
# of our simulated sources.
picks = mne.pick_channels(epochs.ch_names, mne.read_selection('Left-frontal'))
epochs.plot(picks=picks)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:

Note

Before applying ICA (or any artifact repair strategy), be sure to observe
    the artifacts in your data to make sure you choose the right repair tool.
    Sometimes the right tool is no tool at all — if the artifacts are small
    enough you may not even need to repair them to get good analysis results.
    See `tut-artifact-overview` for guidance on detecting and
    visualizing various types of artifact.

What is ICA?
Independent components analysis (ICA) is a technique for estimating
independent source signals from a set of recordings in which the source
signals were mixed together in unknown ratios. A common example of this is
the problem of blind source separation_: with 3 musical instruments playing
in the same room, and 3 microphones recording the performance (each picking
up all 3 instruments, but at varying levels), can you somehow "unmix" the
signals recorded by the 3 microphones so that you end up with a separate
"recording" isolating the sound of each instrument?
It is not hard to see how this analogy applies to EEG/MEG analysis: there are
many "microphones" (sensor channels) simultaneously recording many
"instruments" (blinks, heartbeats, activity in different areas of the brain,
muscular activity from jaw clenching or swallowing, etc). As long as these
various source signals are statistically independent_ and non-gaussian, it
is usually possible to separate the sources using ICA, and then re-construct
the sensor signals after excluding the sources that are unwanted.
ICA in MNE-Python
.. sidebar:: ICA and dimensionality reduction
If you want to perform ICA with *no* dimensionality reduction (other than
the number of Independent Components (ICs) given in ``n_components``, and
any subsequent exclusion of ICs you specify in ``ICA.exclude``), pass
``max_pca_components=None`` and ``n_pca_components=None`` (these are the
default values).

However, if you *do* want to reduce dimensionality, consider this
example: if you have 300 sensor channels...
Can you write Python code for it?

# pick some channels that clearly show heartbeats and blinks
regexp = r'(MEG [12][45][123]1|EEG 00.)'
artifact_picks = mne.pick_channels_regexp(raw.ch_names, regexp=regexp)
raw.plot(order=artifact_picks, n_channels=len(artifact_picks))


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
As a final note, it is possible to extract ICs numerically using the
:meth:~mne.preprocessing.ICA.get_components method of
:class:~mne.preprocessing.ICA objects. This will return a :class:NumPy
array <numpy.ndarray> that can be passed to
:func:~mne.preprocessing.corrmap instead of the :class:tuple of
(subject_index, component_index) we passed before, and will yield the
same result:
Can you write Python code for it?

template_eog_component = icas[0].get_components()[:, eog_inds[0]]
corrmap(icas, template=template_eog_component, threshold=0.9)
print(template_eog_component)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Filtering to remove slow drifts
Before we run the ICA, an important step is filtering the data to remove
low-frequency drifts, which can negatively affect the quality of the ICA fit.
The slow drifts are problematic because they reduce the independence of the
assumed-to-be-independent sources (e.g., during a slow upward drift, the
neural, heartbeat, blink, and other muscular sources will all tend to have
higher values), making it harder for the algorithm to find an accurate
solution. A high-pass filter with 1 Hz cutoff frequency is recommended.
However, because filtering is a linear operation, the ICA solution found from
the filtered signal can be applied to the unfiltered signal (see [2]_ for
more information), so we'll keep a copy of the unfiltered
:class:~mne.io.Raw object around so we can apply the ICA solution to it
later.
Can you write Python code for it?

filt_raw = raw.copy()
filt_raw.load_data().filter(l_freq=1., h_freq=None)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Fitting and plotting the ICA solution
.. sidebar:: Ignoring the time domain
The ICA algorithms implemented in MNE-Python find patterns across
channels, but ignore the time domain. This means you can compute ICA on
discontinuous :class:`~mne.Epochs` or :class:`~mne.Evoked` objects (not
just continuous :class:`~mne.io.Raw` objects), or only use every Nth
sample by passing the ``decim`` parameter to ``ICA.fit()``.

Now we're ready to set up and fit the ICA. Since we know (from observing our
raw data) that the EOG and ECG artifacts are fairly strong, we would expect
those artifacts to be captured in the first few dimensions of the PCA
decomposition that happens before the ICA. Therefore, we probably don't need
a huge number of components to do a good job of isolating our artifacts
(though it is usually preferable to include more components for a more
accurate solution). As a first guess, we'll run ICA with n_components=15
(use only the first 15 PCA components to compute the ICA decomposition) — a
very small number given that our data has over 300 channels, but with the
advantage that it will run quickly and we will able to tell easily whether it
worked or not (because we already know what the EOG / ECG artifacts should
look like).
ICA fitting is not deterministic (e.g., the components may get a sign
flip on different runs, or may not always be returned in the same order), so
we'll also specify a random seed_ so that we get identical results each
time this tutorial is built by our web servers.
Can you write Python code for it?

ica = ICA(n_components=15, random_state=97)
ica.fit(filt_raw)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
In the remaining sections, we'll look at different ways of choosing which ICs
to exclude prior to reconstructing the sensor signals.
Selecting ICA components manually
Once we're certain which components we want to exclude, we can specify that
manually by setting the ica.exclude attribute. Similar to marking bad
channels, merely setting ica.exclude doesn't do anything immediately (it
just adds the excluded ICs to a list that will get used later when it's
needed). Once the exclusions have been set, ICA methods like
:meth:~mne.preprocessing.ICA.plot_overlay will exclude those component(s)
even if no exclude parameter is passed, and the list of excluded
components will be preserved when using :meth:mne.preprocessing.ICA.save
and :func:mne.preprocessing.read_ica.
Can you write Python code for it?

ica.exclude = [0, 1]  # indices chosen based on various plots above


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Much better! Now we've captured both ICs that are reflecting the heartbeat
artifact (and as a result, we got two diagnostic plots: one for each IC that
reflects the heartbeat). This demonstrates the value of checking the results
of automated approaches like :meth:~mne.preprocessing.ICA.find_bads_ecg
before accepting them.
Can you write Python code for it?

# clean up memory before moving on
del raw, filt_raw, ica, new_ica


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Note that above we used :meth:~mne.preprocessing.ICA.plot_sources on both
the original :class:~mne.io.Raw instance and also on an
:class:~mne.Evoked instance of the extracted EOG artifacts. This can be
another way to confirm that :meth:~mne.preprocessing.ICA.find_bads_eog has
identified the correct components.
Using a simulated channel to select ICA components
If you don't have an EOG channel,
:meth:~mne.preprocessing.ICA.find_bads_eog has a ch_name parameter that
you can use as a proxy for EOG. You can use a single channel, or create a
bipolar reference from frontal EEG sensors and use that as virtual EOG
channel. This carries a risk however: you must hope that the frontal EEG
channels only reflect EOG and not brain dynamics in the prefrontal cortex (or
you must not care about those prefrontal signals).
For ECG, it is easier: :meth:~mne.preprocessing.ICA.find_bads_ecg can use
cross-channel averaging of magnetometer or gradiometer channels to construct
a virtual ECG channel, so if you have MEG channels it is usually not
necessary to pass a specific channel name.
:meth:~mne.preprocessing.ICA.find_bads_ecg also has two options for its
method parameter: 'ctps' (cross-trial phase statistics [3]_) and
'correlation' (Pearson correlation between data and ECG channel).
Can you write Python code for it?

ica.exclude = []
# find which ICs match the ECG pattern
ecg_indices, ecg_scores = ica.find_bads_ecg(raw, method='correlation',
                                            threshold='auto')
ica.exclude = ecg_indices

# barplot of ICA component "ECG match" scores
ica.plot_scores(ecg_scores)

# plot diagnostics
ica.plot_properties(raw, picks=ecg_indices)

# plot ICs applied to raw data, with ECG matches highlighted
ica.plot_sources(raw)

# plot ICs applied to the averaged ECG epochs, with ECG matches highlighted
ica.plot_sources(ecg_evoked)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Notice that subject 1 does seem to have an IC that looks like it reflects
blink artifacts (component ICA000). Notice also that subject 3 appears to
have two components that are reflecting ocular artifacts (ICA000 and
ICA002), but only one was caught by :func:~mne.preprocessing.corrmap.
Let's try setting the threshold manually:
Can you write Python code for it?

corrmap(icas, template=(0, eog_inds[0]), threshold=0.9)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Notice that the first subject has 3 different labels for the IC at index 0:
"eog/0/Fpz", "eog", and "blink". The first two were added by
:meth:~mne.preprocessing.ICA.find_bads_eog; the "blink" label was added by
the last call to :func:~mne.preprocessing.corrmap. Notice also that each
subject has at least one IC index labelled "blink", and subject 3 has two
components (0 and 2) labelled "blink" (consistent with the plot of IC sources
above). The labels_ attribute of :class:~mne.preprocessing.ICA objects
can also be manually edited to annotate the ICs with custom labels. They also
come in handy when plotting:
Can you write Python code for it?

icas[3].plot_components(picks=icas[3].labels_['blink'])
icas[3].exclude = icas[3].labels_['blink']
icas[3].plot_sources(raws[3])


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Now we get the message At least 1 IC detected for each subject (which is
good). At this point we'll re-run :func:~mne.preprocessing.corrmap with
parameters label=blink, show=False to label the ICs from each subject
that capture the blink artifacts (without plotting them again).
Can you write Python code for it?

corrmap(icas, template=(0, eog_inds[0]), threshold=0.9, label='blink',
        plot=False)
print([ica.labels_ for ica in icas])


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Repairing artifacts with ICA
This tutorial covers the basics of independent components analysis (ICA) and
shows how ICA can be used for artifact repair; an extended example illustrates
repair of ocular and heartbeat artifacts.
   :depth: 2
We begin as always by importing the necessary Python modules and loading some
example data <sample-dataset>. Because ICA can be computationally
intense, we'll also crop the data to 60 seconds; and to save ourselves from
repeatedly typing mne.preprocessing we'll directly import a few functions
and classes from that submodule:
Can you write Python code for it?

import os
import mne
from mne.preprocessing import (ICA, create_eog_epochs, create_ecg_epochs,
                               corrmap)

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)
raw.crop(tmax=60.)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
Some optional parameters that we could have passed to the
:meth:~mne.preprocessing.ICA.fit method include decim (to use only
every Nth sample in computing the ICs, which can yield a considerable
speed-up) and reject (for providing a rejection dictionary for maximum
acceptable peak-to-peak amplitudes for each channel type, just like we used
when creating epoched data in the tut-overview tutorial).
Now we can examine the ICs to see what they captured.
:meth:~mne.preprocessing.ICA.plot_sources will show the time series of the
ICs. Note that in our call to :meth:~mne.preprocessing.ICA.plot_sources we
can use the original, unfiltered :class:~mne.io.Raw object:
Can you write Python code for it?


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
The last of these plots is especially useful: it shows us that the heartbeat
artifact is coming through on two ICs, and we've only caught one of them.
In fact, if we look closely at the output of
:meth:~mne.preprocessing.ICA.plot_sources (online, you can right-click →
"view image" to zoom in), it looks like ICA014 has a weak periodic
component that is in-phase with ICA001. It might be worthwhile to re-run
the ICA with more components to see if that second heartbeat artifact
resolves out a little better:
Can you write Python code for it?

# refit the ICA with 30 components this time
new_ica = ICA(n_components=30, random_state=97)
new_ica.fit(filt_raw)

# find which ICs match the ECG pattern
ecg_indices, ecg_scores = new_ica.find_bads_ecg(raw, method='correlation',
                                                threshold='auto')
new_ica.exclude = ecg_indices

# barplot of ICA component "ECG match" scores
new_ica.plot_scores(ecg_scores)

# plot diagnostics
new_ica.plot_properties(raw, picks=ecg_indices)

# plot ICs applied to raw data, with ECG matches highlighted
new_ica.plot_sources(raw)

# plot ICs applied to the averaged ECG epochs, with ECG matches highlighted
new_ica.plot_sources(ecg_evoked)


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
We can also plot some diagnostics of each IC using
:meth:~mne.preprocessing.ICA.plot_properties:
Can you write Python code for it?


I am working on the file "0.21/_downloads/8f7e6dfc30a66795f2d4e4ae5ca6d23e/plot_40_artifact_correction_ica.ipynb".
The first task is:
We can get a summary of how the ocular artifact manifests across each channel
type using :func:~mne.preprocessing.create_eog_epochs like we did in the
tut-artifact-overview tutorial:
Can you write Python code for it?

eog_evoked = create_eog_epochs(raw).average()
eog_evoked.apply_baseline(baseline=(None, -0.2))
eog_evoked.plot_joint()


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
Dipole fits
For computing a dipole fit, we need to load the noise covariance, the BEM
solution, and the coregistration transformation files. Note that for the
other methods, these were already used to generate the inverse operator.
Can you write Python code for it?

fname_cov = os.path.join(data_path, 'MEG', 'sample', 'sample_audvis-cov.fif')
fname_bem = os.path.join(subjects_dir, 'sample', 'bem',
                         'sample-5120-bem-sol.fif')
fname_trans = os.path.join(data_path, 'MEG', 'sample',
                           'sample_audvis_raw-trans.fif')


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
Finally, we can visualize the dipole.
Can you write Python code for it?


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
The SourceEstimate object is in fact a surface source estimate. MNE also
supports volume-based source estimates but more on that later.
We can plot the source estimate using the
:func:stc.plot <mne.SourceEstimate.plot> just as in other MNE
objects. Note that for this visualization to work, you must have mayavi
and pysurfer installed on your machine.
Can you write Python code for it?

initial_time = 0.1
brain = stc.plot(subjects_dir=subjects_dir, initial_time=initial_time,
                 clim=dict(kind='value', lims=[3, 6, 9]))


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
This is a :class:SourceEstimate <mne.SourceEstimate> object
Can you write Python code for it?


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
This too comes with a convenient plot method.
Can you write Python code for it?


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
Visualize source time courses (stcs)
This tutorial focuses on visualization of
:term:stcs <source estimates (abbr. stc)>.
Surface Source Estimates
First, we get the paths for the evoked data and the time courses (stcs).
Can you write Python code for it?

import os
import os.path as op

import numpy as np
import matplotlib.pyplot as plt

import mne
from mne.datasets import sample
from mne.minimum_norm import apply_inverse, read_inverse_operator
from mne import read_evokeds

data_path = sample.data_path()
sample_dir = os.path.join(data_path, 'MEG', 'sample')
subjects_dir = os.path.join(data_path, 'subjects')

fname_evoked = data_path + '/MEG/sample/sample_audvis-ave.fif'
fname_stc = os.path.join(sample_dir, 'sample_audvis-meg')


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
You can also extract label time courses using volumetric atlases. Here we'll
use the built-in aparc.a2009s+aseg.mgz:
Can you write Python code for it?

fname_aseg = op.join(subjects_dir, 'sample', 'mri', 'aparc.a2009s+aseg.mgz')
label_names = mne.get_volume_labels_from_aseg(fname_aseg)
label_tc = stc.extract_label_time_course(
    fname_aseg, src=src, trans=mri_head_t)

lidx, tidx = np.unravel_index(np.argmax(label_tc), label_tc.shape)
fig, ax = plt.subplots(1)
ax.plot(stc.times, label_tc.T, 'k', lw=1., alpha=0.5)
xy = np.array([stc.times[tidx], label_tc[lidx, tidx]])
xytext = xy + [0.01, 1]
ax.annotate(
    label_names[lidx], xy, xytext, arrowprops=dict(arrowstyle='->'), color='r')
ax.set(xlim=stc.times[[0, -1]], xlabel='Time (s)', ylabel='Activation')
for key in ('right', 'top'):
    ax.spines[key].set_visible(False)
fig.tight_layout()


I am working on the file "0.21/_downloads/96cdfef13f5475e2f32b862fa94904b7/plot_visualize_stc.ipynb".
The first task is:
You can also morph it to fsaverage and visualize it using a flatmap:
Can you write Python code for it?

stc_fs = mne.compute_source_morph(stc, 'sample', 'fsaverage', subjects_dir,
                                  smooth=5, verbose='error').apply(stc)
brain = stc_fs.plot(subjects_dir=subjects_dir, initial_time=initial_time,
                    clim=dict(kind='value', lims=[3, 6, 9]),
                    surface='flat', hemi='split', size=(1000, 500),
                    smoothing_steps=5, time_viewer=False,
                    add_data_kwargs=dict(
                        colorbar_kwargs=dict(label_font_size=10)))
# You can save a movie like the one on our documentation website with:
# brain.save_movie(time_dilation=20, tmin=0.05, tmax=0.16,
#                  interpolation='linear', framerate=10)


I am working on the file "0.21/_downloads/974f822d2280f83b67727ee3355c7c2f/plot_sensor_connectivity.ipynb".
The first task is:
Set parameters
Can you write Python code for it?

data_path = sample.data_path()
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
event_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif'

# Setup for reading the raw data
raw = io.read_raw_fif(raw_fname)
events = mne.read_events(event_fname)

# Add a bad channel
raw.info['bads'] += ['MEG 2443']

# Pick MEG gradiometers
picks = mne.pick_types(raw.info, meg='grad', eeg=False, stim=False, eog=True,
                       exclude='bads')

# Create epochs for the visual condition
event_id, tmin, tmax = 3, -0.2, 1.5  # need a long enough epoch for 5 cycles
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=picks,
                    baseline=(None, 0), reject=dict(grad=4000e-13, eog=150e-6))

# Compute connectivity for band containing the evoked response.
# We exclude the baseline period
fmin, fmax = 3., 9.
sfreq = raw.info['sfreq']  # the sampling frequency
tmin = 0.0  # exclude the baseline period
epochs.load_data().pick_types(meg='grad')  # just keep MEG and no EOG now
con, freqs, times, n_epochs, n_tapers = spectral_connectivity(
    epochs, method='pli', mode='multitaper', sfreq=sfreq, fmin=fmin, fmax=fmax,
    faverage=True, tmin=tmin, mt_adaptive=False, n_jobs=1)

# Now, visualize the connectivity in 3D
plot_sensors_connectivity(epochs.info, con[:, :, 0])


I am working on the file "0.21/_downloads/995d3b6a9ece3566320943b2dcc13e22/plot_opm_data.ipynb".
The first task is:
Examine our coordinate alignment for source localization and compute a
forward operator:

Note

The Head<->MRI transform is an identity matrix, as the
          co-registration method used equates the two coordinate
          systems. This mis-defines the head coordinate system
          (which should be based on the LPA, Nasion, and RPA)
          but should be fine for these analyses.

Can you write Python code for it?

bem = mne.read_bem_solution(bem_fname)
trans = None

# To compute the forward solution, we must
# provide our temporary/custom coil definitions, which can be done as::
#
# with mne.use_coil_def(coil_def_fname):
#     fwd = mne.make_forward_solution(
#         raw.info, trans, src, bem, eeg=False, mindist=5.0,
#         n_jobs=1, verbose=True)

fwd = mne.read_forward_solution(fwd_fname)
# use fixed orientation here just to save memory later
mne.convert_forward_solution(fwd, force_fixed=True, copy=False)

with mne.use_coil_def(coil_def_fname):
    fig = mne.viz.plot_alignment(
        evoked.info, trans, subject, subjects_dir, ('head', 'pial'), bem=bem)

mne.viz.set_3d_view(figure=fig, azimuth=45, elevation=60, distance=0.4,
                    focalpoint=(0.02, 0, 0.04))


I am working on the file "0.21/_downloads/995d3b6a9ece3566320943b2dcc13e22/plot_opm_data.ipynb".
The first task is:
Optically pumped magnetometer (OPM) data
In this dataset, electrical median nerve stimulation was delivered to the
left wrist of the subject. Somatosensory evoked fields were measured using
nine QuSpin SERF OPMs placed over the right-hand side somatomotor area.
Here we demonstrate how to localize these custom OPM data in MNE.
Can you write Python code for it?

import os.path as op

import numpy as np
import mne

data_path = mne.datasets.opm.data_path()
subject = 'OPM_sample'
subjects_dir = op.join(data_path, 'subjects')
raw_fname = op.join(data_path, 'MEG', 'OPM', 'OPM_SEF_raw.fif')
bem_fname = op.join(subjects_dir, subject, 'bem',
                    subject + '-5120-5120-5120-bem-sol.fif')
fwd_fname = op.join(data_path, 'MEG', 'OPM', 'OPM_sample-fwd.fif')
coil_def_fname = op.join(data_path, 'MEG', 'OPM', 'coil_def.dat')


I am working on the file "0.21/_downloads/995d3b6a9ece3566320943b2dcc13e22/plot_opm_data.ipynb".
The first task is:
Perform dipole fitting
Can you write Python code for it?

# Fit dipoles on a subset of time points
with mne.use_coil_def(coil_def_fname):
    dip_opm, _ = mne.fit_dipole(evoked.copy().crop(0.015, 0.080),
                                cov, bem, trans, verbose=True)
idx = np.argmax(dip_opm.gof)
print('Best dipole at t=%0.1f ms with %0.1f%% GOF'
      % (1000 * dip_opm.times[idx], dip_opm.gof[idx]))

# Plot N20m dipole as an example
dip_opm.plot_locations(trans, subject, subjects_dir,
                       mode='orthoview', idx=idx)


I am working on the file "0.21/_downloads/995d3b6a9ece3566320943b2dcc13e22/plot_opm_data.ipynb".
The first task is:
Perform minimum-norm localization
Due to the small number of sensors, there will be some leakage of activity
to areas with low/no sensitivity. Constraining the source space to
areas we are sensitive to might be a good idea.
Can you write Python code for it?

inverse_operator = mne.minimum_norm.make_inverse_operator(
    evoked.info, fwd, cov, loose=0., depth=None)
del fwd, cov

method = "MNE"
snr = 3.
lambda2 = 1. / snr ** 2
stc = mne.minimum_norm.apply_inverse(
    evoked, inverse_operator, lambda2, method=method,
    pick_ori=None, verbose=True)

# Plot source estimate at time of best dipole fit
brain = stc.plot(hemi='rh', views='lat', subjects_dir=subjects_dir,
                 initial_time=dip_opm.times[idx],
                 clim=dict(kind='percent', lims=[99, 99.9, 99.99]))


I am working on the file "0.21/_downloads/995d3b6a9ece3566320943b2dcc13e22/plot_opm_data.ipynb".
The first task is:
Prepare data for localization
First we filter and epoch the data:
Can you write Python code for it?

raw = mne.io.read_raw_fif(raw_fname, preload=True)
raw.filter(None, 90, h_trans_bandwidth=10.)
raw.notch_filter(50., notch_widths=1)

# Set epoch rejection threshold a bit larger than for SQUIDs
reject = dict(mag=2e-10)
tmin, tmax = -0.5, 1

# Find Median nerve stimulator trigger
event_id = dict(Median=257)
events = mne.find_events(raw, stim_channel='STI101', mask=257, mask_type='and')
picks = mne.pick_types(raw.info, meg=True, eeg=False)
# we use verbose='error' to suppress warning about decimation causing aliasing,
# ideally we would low-pass and then decimate instead
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, verbose='error',
                    reject=reject, picks=picks, proj=False, decim=10,
                    preload=True)
evoked = epochs.average()
evoked.plot()
cov = mne.compute_covariance(epochs, tmax=0.)
del epochs, raw


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Creating the empty-room projectors
We create the SSP vectors using :func:~mne.compute_proj_raw, and control
the number of projectors with parameters n_grad and n_mag. Once
created, the field pattern of the projectors can be easily visualized with
:func:~mne.viz.plot_projs_topomap. We include the parameter
vlim='joint' so that the colormap is computed jointly for all projectors
of a given channel type; this makes it easier to compare their relative
smoothness. Note that for the function to know the types of channels in a
projector, you must also provide the corresponding :class:~mne.Info object:
Can you write Python code for it?

empty_room_projs = mne.compute_proj_raw(empty_room_raw, n_grad=3, n_mag=3)
mne.viz.plot_projs_topomap(empty_room_projs, colorbar=True, vlim='joint',
                           info=empty_room_raw.info)


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Just like we did with the heartbeat artifact, we can compute SSP projectors
for the ocular artifact using :func:~mne.preprocessing.compute_proj_eog,
which again takes a :class:~mne.io.Raw object as input and returns the
requested number of projectors for magnetometers, gradiometers, and EEG
channels (default is two projectors for each channel type). This time, we'll
pass no_proj parameter (so we get back only the new EOG projectors, not
also the existing projectors in the :class:~mne.io.Raw object), and we'll
ignore the events array by assigning it to _ (the conventional way of
handling unwanted return elements in Python).
Can you write Python code for it?

eog_projs, _ = compute_proj_eog(raw, n_grad=1, n_mag=1, n_eeg=1, reject=None,
                                no_proj=True)


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Just like with the empty-room and ECG projectors, we can visualize the scalp
distribution:
Can you write Python code for it?


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Just like with the empty-room projectors, we can visualize the scalp
distribution:
Can you write Python code for it?


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Notice that the empty room recording itself has the system-provided SSP
projectors in it — we'll remove those from the empty room file too.
Can you write Python code for it?


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Notice that the gradiometer-based projectors seem to reflect problems with
individual sensor units rather than a global noise source (indeed, planar
gradiometers are much less sensitive to distant sources). This is the reason
that the system-provided noise projectors are computed only for
magnetometers. Comparing the system-provided projectors to the
subject-specific ones, we can see they are reasonably similar (though in a
different order) and the left-right component seems to have changed
polarity.
Can you write Python code for it?

fig, axs = plt.subplots(2, 3)
for idx, _projs in enumerate([system_projs, empty_room_projs[3:]]):
    mne.viz.plot_projs_topomap(_projs, axes=axs[idx], colorbar=True,
                               vlim='joint', info=empty_room_raw.info)


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Notice that the small peaks in the first to magnetometer channels (MEG
1411 and MEG 1421) that occur at the same time as the large EEG
deflections have also been removed.
Choosing the number of projectors
In the examples above, we used 3 projectors (all magnetometer) to capture
empty room noise, and saw how projectors computed for the gradiometers failed
to capture global patterns (and thus we discarded the gradiometer
projectors). Then we computed 3 projectors (1 for each channel type) to
capture the heartbeat artifact, and 3 more to capture the ocular artifact.
How did we choose these numbers? The short answer is "based on experience" —
knowing how heartbeat artifacts typically manifest across the sensor array
allows us to recognize them when we see them, and recognize when additional
projectors are capturing something else other than a heartbeat artifact (and
thus may be removing brain signal and should be discarded).
Visualizing SSP sensor-space bias via signal reconstruction
.. sidebar:: SSP reconstruction
Internally, the reconstruction is performed by effectively using a
minimum-norm source localization to a spherical source space with the
projections accounted for, and then projecting the source-space data
back out to sensor space.

Because SSP performs an orthogonal projection, any spatial component in the
data that is not perfectly orthogonal to the SSP spatial direction(s) will
have its overall amplitude reduced by the projection operation. In other
words, SSP typically introduces some amount of amplitude reduction bias in
the sensor space data.
When performing source localization of M/EEG data, these projections are
properly taken into account by being applied not just to the M/EEG data
but also to the forward solution, and hence SSP should not bias the estimated
source amplitudes. However, for sensor space analyses, it can be useful to
visualize the extent to which SSP projection has biased the data. This can be
explored by using proj='reconstruct' in evoked plotting functions, for
example via...
Can you write Python code for it?

evoked = epochs.average()
# Apply the average ref first:
# It's how we typically view EEG data, and here we're really just interested
# in the effect of the EOG+ECG SSPs
evoked.del_proj().set_eeg_reference(projection=True).apply_proj()
evoked.add_proj(ecg_projs).add_proj(eog_projs)
fig, axes = plt.subplots(3, 3, figsize=(8, 6))
for ii in range(3):
    axes[ii, 0].get_shared_y_axes().join(*axes[ii])
for pi, proj in enumerate((False, True, 'reconstruct')):
    evoked.plot(proj=proj, axes=axes[:, pi], spatial_colors=True)
    if pi == 0:
        for ax in axes[:, pi]:
            parts = ax.get_title().split('(')
            ax.set(ylabel=f'{parts[0]} ({ax.get_ylabel()})\n'
                          f'{parts[1].replace(")", "")}')
    axes[0, pi].set(title=f'proj={proj}')
    axes[0, pi].texts = []
plt.setp(axes[1:, :].ravel(), title='')
plt.setp(axes[:, 1:].ravel(), ylabel='')
plt.setp(axes[:-1, :].ravel(), xlabel='')
mne.viz.tight_layout()


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Plotting the ERP/F using evoked.plot() or evoked.plot_joint() with
and without projectors applied can also be informative, as can plotting with
proj='reconstruct', which can reduce the signal bias introduced by
projections (see tut-artifact-ssp-reconstruction below).
Example: EOG and ECG artifact repair
Visualizing the artifacts
As mentioned in the ICA tutorial <tut-artifact-ica>, an important
first step is visualizing the artifacts you want to repair. Here they are in
the raw data:
Can you write Python code for it?

# pick some channels that clearly show heartbeats and blinks
regexp = r'(MEG [12][45][123]1|EEG 00.)'
artifact_picks = mne.pick_channels_regexp(raw.ch_names, regexp=regexp)
raw.plot(order=artifact_picks, n_channels=len(artifact_picks))


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Repairing ECG artifacts with SSP
MNE-Python provides several functions for detecting and removing heartbeats
from EEG and MEG data. As we saw in tut-artifact-overview,
:func:~mne.preprocessing.create_ecg_epochs can be used to both detect and
extract heartbeat artifacts into an :class:~mne.Epochs object, which can
be used to visualize how the heartbeat artifacts manifest across the sensors:
Can you write Python code for it?

ecg_evoked = create_ecg_epochs(raw).average()
ecg_evoked.plot_joint()


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Repairing artifacts with SSP
This tutorial covers the basics of signal-space projection (SSP) and shows
how SSP can be used for artifact repair; extended examples illustrate use
of SSP for environmental noise reduction, and for repair of ocular and
heartbeat artifacts.
   :depth: 2
We begin as always by importing the necessary Python modules. To save ourselves
from repeatedly typing mne.preprocessing we'll directly import a handful of
functions from that submodule:
Can you write Python code for it?

import os
import numpy as np
import matplotlib.pyplot as plt
import mne
from mne.preprocessing import (create_eog_epochs, create_ecg_epochs,
                               compute_proj_ecg, compute_proj_eog)


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
The effect is sometimes easier to see on averaged data. Here we use an
interactive feature of :func:mne.Evoked.plot_topomap to turn projectors on
and off to see the effect on the data. Of course, the interactivity won't
work on the tutorial website, but you can download the tutorial and try it
locally:
Can you write Python code for it?

events = mne.find_events(raw, stim_channel='STI 014')
event_id = {'auditory/left': 1}

# NOTE: appropriate rejection criteria are highly data-dependent
reject = dict(mag=4000e-15,     # 4000 fT
              grad=4000e-13,    # 4000 fT/cm
              eeg=150e-6,       # 150 µV
              eog=250e-6)       # 250 µV

# time range where we expect to see the auditory N100: 50-150 ms post-stimulus
times = np.linspace(0.05, 0.15, 5)

epochs = mne.Epochs(raw, events, event_id, proj='delayed', reject=reject)
fig = epochs.average().plot_topomap(times, proj='interactive')


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
The example data <sample-dataset> also includes an "empty room"
recording taken the same day as the recording of the subject. This will
provide a more accurate estimate of environmental noise than the projectors
stored with the system (which are typically generated during annual
maintenance and tuning). Since we have this subject-specific empty-room
recording, we'll create our own projectors from it and discard the
system-provided SSP projectors (saving them first, for later comparison with
the custom ones):
Can you write Python code for it?

system_projs = raw.info['projs']
raw.del_proj()
empty_room_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                               'ernoise_raw.fif')
empty_room_raw = mne.io.read_raw_fif(empty_room_file)


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
To compute SSP projectors for the heartbeat artifact, you can use
:func:~mne.preprocessing.compute_proj_ecg, which takes a
:class:~mne.io.Raw object as input and returns the requested number of
projectors for magnetometers, gradiometers, and EEG channels (default is two
projectors for each channel type).
:func:~mne.preprocessing.compute_proj_ecg also returns an :term:events
array containing the sample numbers corresponding to the onset of each
detected heartbeat.
Can you write Python code for it?

projs, events = compute_proj_ecg(raw, n_grad=1, n_mag=1, n_eeg=1, reject=None)


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Visualizing how projectors affect the signal
We could visualize the different effects these have on the data by applying
each set of projectors to different copies of the :class:~mne.io.Raw object
using :meth:~mne.io.Raw.apply_proj. However, the :meth:~mne.io.Raw.plot
method has a proj parameter that allows us to temporarily apply
projectors while plotting, so we can use this to visualize the difference
without needing to copy the data. Because the projectors are so similar, we
need to zoom in pretty close on the data to see any differences:
Can you write Python code for it?

mags = mne.pick_types(raw.info, meg='mag')
for title, projs in [('system', system_projs),
                     ('subject-specific', empty_room_projs[3:])]:
    raw.add_proj(projs, remove_existing=True)
    fig = raw.plot(proj=True, order=mags, duration=1, n_channels=2)
    fig.subplots_adjust(top=0.9)  # make room for title
    fig.suptitle('{} projectors'.format(title), size='xx-large', weight='bold')


I am working on the file "0.21/_downloads/99730d9046b115c3e40e7e01cb975635/plot_50_artifact_correction_ssp.ipynb".
The first task is:
Visualizing the empty-room noise
Let's take a look at the spectrum of the empty room noise. We can view an
individual spectrum for each sensor, or an average (with confidence band)
across sensors:
Can you write Python code for it?

for average in (False, True):
    empty_room_raw.plot_psd(average=average, dB=False, xscale='log')


I am working on the file "0.21/_downloads/9ae38deb3b38617e0444984e7140c666/plot_mne_cov_power.ipynb".
The first task is:
And visualize power is relative to the baseline:
Can you write Python code for it?

stc_data /= stc_base
brain = stc_data.plot(subject='sample', subjects_dir=subjects_dir,
                      clim=dict(kind='percent', lims=(50, 90, 98)))


I am working on the file "0.21/_downloads/9ae38deb3b38617e0444984e7140c666/plot_mne_cov_power.ipynb".
The first task is:
Apply inverse operator to covariance
Finally, we can construct an inverse using the empty-room noise covariance:
Can you write Python code for it?

# Read the forward solution and compute the inverse operator
fname_fwd = data_path + '/MEG/sample/sample_audvis-meg-oct-6-fwd.fif'
fwd = mne.read_forward_solution(fname_fwd)

# make an MEG inverse operator
info = evoked.info
inverse_operator = make_inverse_operator(info, fwd, noise_cov,
                                         loose=0.2, depth=0.8)


I am working on the file "0.21/_downloads/9ae38deb3b38617e0444984e7140c666/plot_mne_cov_power.ipynb".
The first task is:
Compute and plot covariances
In addition to the empty-room covariance above, we compute two additional
covariances:

Baseline covariance, which captures signals not of interest in our
   analysis (e.g., sensor noise, environmental noise, physiological
   artifacts, and also resting-state-like brain activity / "noise").
Data covariance, which captures our activation of interest (in addition
   to noise sources).
Can you write Python code for it?

base_cov = mne.compute_covariance(
    epochs, tmin=-0.2, tmax=0, method=['shrunk', 'empirical'], rank=None,
    verbose=True)
data_cov = mne.compute_covariance(
    epochs, tmin=0., tmax=0.2, method=['shrunk', 'empirical'], rank=None,
    verbose=True)

fig_noise_cov = mne.viz.plot_cov(noise_cov, epochs.info, show_svd=False)
fig_base_cov = mne.viz.plot_cov(base_cov, epochs.info, show_svd=False)
fig_data_cov = mne.viz.plot_cov(data_cov, epochs.info, show_svd=False)


I am working on the file "0.21/_downloads/9ae38deb3b38617e0444984e7140c666/plot_mne_cov_power.ipynb".
The first task is:
Compute empty-room covariance
First we compute an empty-room covariance, which captures noise from the
sensors and environment.
Can you write Python code for it?

raw_empty_room_fname = op.join(
    data_path, 'MEG', 'sample', 'ernoise_raw.fif')
raw_empty_room = mne.io.read_raw_fif(raw_empty_room_fname)
raw_empty_room.crop(0, 60)
raw_empty_room.info['bads'] = ['MEG 2443']
raw_empty_room.info['projs'] = raw.info['projs']
noise_cov = mne.compute_raw_covariance(
    raw_empty_room, method=['empirical', 'shrunk'])
del raw_empty_room


I am working on the file "0.21/_downloads/9ae38deb3b38617e0444984e7140c666/plot_mne_cov_power.ipynb".
The first task is:
Compute source power estimate by projecting the covariance with MNE
We can apply the MNE inverse operator to a covariance matrix to obtain
an estimate of source power. This is computationally more efficient than first
estimating the source timecourses and then computing their power.
Can you write Python code for it?

# Author: Denis A. Engemann <denis-alexander.engemann@inria.fr>
#         Luke Bloy <luke.bloy@gmail.com>
#
# License: BSD (3-clause)

import os.path as op
import numpy as np

import mne
from mne.datasets import sample
from mne.minimum_norm import make_inverse_operator, apply_inverse_cov

data_path = sample.data_path()
subjects_dir = data_path + '/subjects'
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
raw = mne.io.read_raw_fif(raw_fname)


I am working on the file "0.21/_downloads/9ae38deb3b38617e0444984e7140c666/plot_mne_cov_power.ipynb".
The first task is:
We can also look at the covariances using topomaps, here we just show the
baseline and data covariances, followed by the data covariance whitened
by the baseline covariance:
Can you write Python code for it?

evoked = epochs.average().pick('meg')
evoked.drop_channels(evoked.info['bads'])
evoked.plot(time_unit='s')
evoked.plot_topomap(times=np.linspace(0.05, 0.15, 5), ch_type='mag')
noise_cov.plot_topomap(evoked.info, 'grad', title='Noise')
data_cov.plot_topomap(evoked.info, 'grad', title='Data')
data_cov.plot_topomap(evoked.info, 'grad', noise_cov=noise_cov,
                      title='Whitened data')


I am working on the file "0.21/_downloads/a09c964ce37825f750704113fa863276/plot_mne_inverse_envelope_correlation_volume.ipynb".
The first task is:
Compute label time series and do envelope correlation
Can you write Python code for it?

epochs.apply_hilbert()  # faster to do in sensor space
stcs = apply_lcmv_epochs(epochs, filters, return_generator=True)
corr = envelope_correlation(stcs, verbose=True)


I am working on the file "0.21/_downloads/a09c964ce37825f750704113fa863276/plot_mne_inverse_envelope_correlation_volume.ipynb".
The first task is:
Compute the degree and plot it
Can you write Python code for it?

degree = mne.connectivity.degree(corr, 0.15)
stc = mne.VolSourceEstimate(degree, [src[0]['vertno']], 0, 1, 'bst_resting')
brain = stc.plot(
    src, clim=dict(kind='percent', lims=[75, 85, 95]), colormap='gnuplot',
    subjects_dir=subjects_dir, mode='glass_brain')


I am working on the file "0.21/_downloads/a09c964ce37825f750704113fa863276/plot_mne_inverse_envelope_correlation_volume.ipynb".
The first task is:
Compute the forward and inverse
Can you write Python code for it?

# This source space is really far too coarse, but we do this for speed
# considerations here
pos = 15.  # 1.5 cm is very broad, done here for speed!
src = mne.setup_volume_source_space('bst_resting', pos, bem=bem,
                                    subjects_dir=subjects_dir, verbose=True)
fwd = mne.make_forward_solution(epochs.info, trans, src, bem)
data_cov = mne.compute_covariance(epochs)
filters = make_lcmv(epochs.info, fwd, data_cov, 0.05, cov,
                    pick_ori='max-power', weight_norm='nai')
del fwd


I am working on the file "0.21/_downloads/a09c964ce37825f750704113fa863276/plot_mne_inverse_envelope_correlation_volume.ipynb".
The first task is:
Here we do some things in the name of speed, such as crop (which will
hurt SNR) and downsample. Then we compute SSP projectors and apply them.
Can you write Python code for it?

raw = mne.io.read_raw_ctf(raw_fname, verbose='error')
raw.crop(0, crop_to).pick_types(meg=True, eeg=False).load_data().resample(80)
raw.apply_gradient_compensation(3)
projs_ecg, _ = compute_proj_ecg(raw, n_grad=1, n_mag=2)
projs_eog, _ = compute_proj_eog(raw, n_grad=1, n_mag=2, ch_name='MLT31-4407')
raw.info['projs'] += projs_ecg
raw.info['projs'] += projs_eog
raw.apply_proj()
cov = mne.compute_raw_covariance(raw)  # compute before band-pass of interest


I am working on the file "0.21/_downloads/a09c964ce37825f750704113fa863276/plot_mne_inverse_envelope_correlation_volume.ipynb".
The first task is:
Now we band-pass filter our data and create epochs.
Can you write Python code for it?

raw.filter(14, 30)
events = mne.make_fixed_length_events(raw, duration=5.)
epochs = mne.Epochs(raw, events=events, tmin=0, tmax=5.,
                    baseline=None, reject=dict(mag=8e-13), preload=True)
del raw


I am working on the file "0.21/_downloads/a0b8e095ddf79d437494061b36af56fb/plot_resolution_metrics.ipynb".
The first task is:
Compute spatial resolution metrics in source space
Compute peak localisation error and spatial deviation for the point-spread
functions of dSPM and MNE. Plot their distributions and difference
distributions.
This example mimics some results from [1]_, namely Figure 3 (peak localisation
error for PSFs, L2-MNE vs dSPM) and Figure 4 (spatial deviation for PSFs,
L2-MNE vs dSPM).
Can you write Python code for it?

# Author: Olaf Hauk <olaf.hauk@mrc-cbu.cam.ac.uk>
#
# License: BSD (3-clause)

import mne
from mne.datasets import sample
from mne.minimum_norm import make_inverse_resolution_matrix
from mne.minimum_norm import resolution_metrics

print(__doc__)

data_path = sample.data_path()
subjects_dir = data_path + '/subjects/'
fname_fwd = data_path + '/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif'
fname_cov = data_path + '/MEG/sample/sample_audvis-cov.fif'
fname_evo = data_path + '/MEG/sample/sample_audvis-ave.fif'

# read forward solution
forward = mne.read_forward_solution(fname_fwd)
# forward operator with fixed source orientations
mne.convert_forward_solution(forward, surf_ori=True,
                             force_fixed=True, copy=False)

# noise covariance matrix
noise_cov = mne.read_cov(fname_cov)

# evoked data for info
evoked = mne.read_evokeds(fname_evo, 0)

# make inverse operator from forward solution
# free source orientation
inverse_operator = mne.minimum_norm.make_inverse_operator(
    info=evoked.info, forward=forward, noise_cov=noise_cov, loose=0.,
    depth=None)

# regularisation parameter
snr = 3.0
lambda2 = 1.0 / snr ** 2


I am working on the file "0.21/_downloads/a0b8e095ddf79d437494061b36af56fb/plot_resolution_metrics.ipynb".
The first task is:
Visualize results
Visualise peak localisation error (PLE) across the whole cortex for PSF
Can you write Python code for it?

brain_ple_mne = ple_mne_psf.plot('sample', 'inflated', 'lh',
                                 subjects_dir=subjects_dir, figure=1,
                                 clim=dict(kind='value', lims=(0, 2, 4)))
brain_ple_mne.add_text(0.1, 0.9, 'PLE MNE', 'title', font_size=16)

brain_ple_dspm = ple_dspm_psf.plot('sample', 'inflated', 'lh',
                                   subjects_dir=subjects_dir, figure=2,
                                   clim=dict(kind='value', lims=(0, 2, 4)))
brain_ple_dspm.add_text(0.1, 0.9, 'PLE dSPM', 'title', font_size=16)

# Subtract the two distributions and plot this difference
diff_ple = ple_mne_psf - ple_dspm_psf

brain_ple_diff = diff_ple.plot('sample', 'inflated', 'lh',
                               subjects_dir=subjects_dir, figure=3,
                               clim=dict(kind='value', pos_lims=(0., 1., 2.)))
brain_ple_diff.add_text(0.1, 0.9, 'PLE MNE-dSPM', 'title', font_size=16)


I am working on the file "0.21/_downloads/a1ab4842a5aa341564b4fa0a6bf60065/plot_dipole_orientations.ipynb".
The first task is:
Fixed dipole orientations
While the source space defines the position of the dipoles, the inverse
operator defines the possible orientations of them. One of the options is to
assign a fixed orientation. Since the neural currents from which MEG and EEG
signals originate flows mostly perpendicular to the cortex [1]_, restricting
the orientation of the dipoles accordingly places a useful restriction on the
source estimate.
By specifying fixed=True when calling
:func:mne.minimum_norm.make_inverse_operator, the dipole orientations are
fixed to be orthogonal to the surface of the cortex, pointing outwards. Let's
visualize this:
Can you write Python code for it?

fig = mne.viz.create_3d_figure(size=(600, 400))

# Plot the cortex
fig = mne.viz.plot_alignment(subject=subject, subjects_dir=subjects_dir,
                             trans=trans,
                             surfaces='white', coord_frame='head', fig=fig)

# Show the dipoles as arrows pointing along the surface normal
fig = mne.viz.plot_dipole_locations(dipoles=dipoles, trans=trans,
                                    mode='arrow', subject=subject,
                                    subjects_dir=subjects_dir,
                                    coord_frame='head',
                                    scale=7e-4, fig=fig)

mne.viz.set_3d_view(figure=fig, azimuth=180, distance=0.1)


I am working on the file "0.21/_downloads/a1ab4842a5aa341564b4fa0a6bf60065/plot_dipole_orientations.ipynb".
The first task is:
Limiting orientations, but not fixing them
Often, the best results will be obtained by allowing the dipoles to have
somewhat free orientation, but not stray too far from a orientation that is
perpendicular to the cortex. The loose parameter of the
:func:mne.minimum_norm.make_inverse_operator allows you to specify a value
between 0 (fixed) and 1 (unrestricted or "free") to indicate the amount the
orientation is allowed to deviate from the surface normal.
Can you write Python code for it?

# Set loose to 0.2, the default value
inv = make_inverse_operator(left_auditory.info, fwd, noise_cov, fixed=False,
                            loose=0.2)
stc = apply_inverse(left_auditory, inv, pick_ori='vector')

# Visualize it at the moment of peak activity.
_, time_max = stc.magnitude().get_peak(hemi='lh')
brain_loose = stc.plot(subjects_dir=subjects_dir, initial_time=time_max,
                       time_unit='s', size=(600, 400), overlay_alpha=0)


I am working on the file "0.21/_downloads/a1ab4842a5aa341564b4fa0a6bf60065/plot_dipole_orientations.ipynb".
The first task is:
The direction of the estimated current is now restricted to two directions:
inward and outward. In the plot, blue areas indicate current flowing inwards
and red areas indicate current flowing outwards. Given the curvature of the
cortex, groups of dipoles tend to point in the same direction: the direction
of the electromagnetic field picked up by the sensors.
Loose dipole orientations
Forcing the source dipoles to be strictly orthogonal to the cortex makes the
source estimate sensitive to the spacing of the dipoles along the cortex,
since the curvature of the cortex changes within each ~10 square mm patch.
Furthermore, misalignment of the MEG/EEG and MRI coordinate frames is more
critical when the source dipole orientations are strictly constrained [2]_.
To lift the restriction on the orientation of the dipoles, the inverse
operator has the ability to place not one, but three dipoles at each
location defined by the source space. These three dipoles are placed
orthogonally to form a Cartesian coordinate system. Let's visualize this:
Can you write Python code for it?

fig = mne.viz.create_3d_figure(size=(600, 400))

# Plot the cortex
fig = mne.viz.plot_alignment(subject=subject, subjects_dir=subjects_dir,
                             trans=trans,
                             surfaces='white', coord_frame='head', fig=fig)

# Show the three dipoles defined at each location in the source space
fig = mne.viz.plot_alignment(subject=subject, subjects_dir=subjects_dir,
                             trans=trans, fwd=fwd,
                             surfaces='white', coord_frame='head', fig=fig)

mne.viz.set_3d_view(figure=fig, azimuth=180, distance=0.1)