I am working on the file "0.23/_downloads/524b9a6067f1a7bd3b66aa385465b921/20_source_alignment.ipynb".
The first task is:
Visualizing the transformations
Let's visualize these coordinate frames using just the scalp surface; this
will make it easier to see their relative orientations. To do this we'll
first load the Freesurfer scalp surface, then apply a few different
transforms to it. In addition to the three coordinate frames discussed above,
we'll also show the "mri_voxel" coordinate frame. Unlike MRI Surface RAS,
"mri_voxel" has its origin in the corner of the volume (the left-most,
posterior-most coordinate on the inferior-most MRI slice) instead of at the
center of the volume. "mri_voxel" is also not an RAS coordinate system:
rather, its XYZ directions are based on the acquisition order of the T1 image
slices.
Can you write Python code for it?

# The head surface is stored in "mri" coordinate frame
# (origin at center of volume, units=mm)
seghead_rr, seghead_tri = mne.read_surface(
    op.join(subjects_dir, 'sample', 'surf', 'lh.seghead'))

# To put the scalp in the "head" coordinate frame, we apply the inverse of
# the precomputed `trans` (which maps head → mri)
mri_to_head = linalg.inv(trans['trans'])
scalp_pts_in_head_coord = mne.transforms.apply_trans(
    mri_to_head, seghead_rr, move=True)

# To put the scalp in the "meg" coordinate frame, we use the inverse of
# raw.info['dev_head_t']
head_to_meg = linalg.inv(raw.info['dev_head_t']['trans'])
scalp_pts_in_meg_coord = mne.transforms.apply_trans(
    head_to_meg, scalp_pts_in_head_coord, move=True)

# The "mri_voxel"→"mri" transform is embedded in the header of the T1 image
# file. We'll invert it and then apply it to the original `seghead_rr` points.
# No unit conversion necessary: this transform expects mm and the scalp surface
# is defined in mm.
vox_to_mri = t1_mgh.header.get_vox2ras_tkr()
mri_to_vox = linalg.inv(vox_to_mri)
scalp_points_in_vox = mne.transforms.apply_trans(
    mri_to_vox, seghead_rr, move=True)


I am working on the file "0.23/_downloads/548b4fc45f1ed79527138879cd79d3c8/muscle_detection.ipynb".
The first task is:
Annotate muscle artifacts
Muscle contractions produce high frequency activity that can mask brain signal
of interest. Muscle artifacts can be produced when clenching the jaw,
swallowing, or twitching a cranial muscle. Muscle artifacts are most
noticeable in the range of 110-140 Hz.
This example uses :func:~mne.preprocessing.annotate_muscle_zscore to annotate
segments where muscle activity is likely present. This is done by band-pass
filtering the data in the 110-140 Hz range. Then, the envelope is taken using
the hilbert analytical signal to only consider the absolute amplitude and not
the phase of the high frequency signal. The envelope is z-scored and summed
across channels and divided by the square root of the number of channels.
Because muscle artifacts last several hundred milliseconds, a low-pass filter
is applied on the averaged z-scores at 4 Hz, to remove transient peaks.
Segments above a set threshold are annotated as BAD_muscle. In addition,
the min_length_good parameter determines the cutoff for whether short
spans of "good data" in between muscle artifacts are included in the
surrounding "BAD" annotation.
Can you write Python code for it?

# Authors: Adonay Nunes <adonay.s.nunes@gmail.com>
#          Luke Bloy <luke.bloy@gmail.com>
# License: BSD (3-clause)

import os.path as op
import matplotlib.pyplot as plt
import numpy as np
from mne.datasets.brainstorm import bst_auditory
from mne.io import read_raw_ctf
from mne.preprocessing import annotate_muscle_zscore

# Load data
data_path = bst_auditory.data_path()
raw_fname = op.join(data_path, 'MEG', 'bst_auditory', 'S01_AEF_20131218_01.ds')

raw = read_raw_ctf(raw_fname, preload=False)

raw.crop(130, 160).load_data()  # just use a fraction of data for speed here
raw.resample(300, npad="auto")


I am working on the file "0.23/_downloads/548b4fc45f1ed79527138879cd79d3c8/muscle_detection.ipynb".
The first task is:
Notch filter the data:

Note

If line noise is present, you should perform notch-filtering *before*
    detecting muscle artifacts. See `tut-section-line-noise` for an
    example.

Can you write Python code for it?

raw.notch_filter([50, 100])

# The threshold is data dependent, check the optimal threshold by plotting
# ``scores_muscle``.
threshold_muscle = 5  # z-score
# Choose one channel type, if there are axial gradiometers and magnetometers,
# select magnetometers as they are more sensitive to muscle activity.
annot_muscle, scores_muscle = annotate_muscle_zscore(
    raw, ch_type="mag", threshold=threshold_muscle, min_length_good=0.2,
    filter_freq=[110, 140])


I am working on the file "0.23/_downloads/548b4fc45f1ed79527138879cd79d3c8/muscle_detection.ipynb".
The first task is:
Plot muscle z-scores across recording
Can you write Python code for it?

fig, ax = plt.subplots()
ax.plot(raw.times, scores_muscle)
ax.axhline(y=threshold_muscle, color='r')
ax.set(xlabel='time, (s)', ylabel='zscore', title='Muscle activity')


I am working on the file "0.23/_downloads/568aae18ec92d284aff29cfb5f3c11e7/resolution_metrics.ipynb".
The first task is:
And dSPM:
Can you write Python code for it?

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)


brain_sd_dspm = sd_dspm_psf.plot('sample', 'inflated', 'lh',
                                 subjects_dir=subjects_dir, figure=5,
                                 clim=dict(kind='value', lims=(0, 2, 4)))
brain_sd_dspm.add_text(0.1, 0.9, 'SD dSPM', 'title', font_size=16)


I am working on the file "0.23/_downloads/568aae18ec92d284aff29cfb5f3c11e7/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 of
distributions. This example mimics some results from :footcite:HaukEtAl2019,
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.23/_downloads/568aae18ec92d284aff29cfb5f3c11e7/resolution_metrics.ipynb".
The first task is:
MNE
Compute resolution matrices, peak localisation error (PLE) for point spread
functions (PSFs), spatial deviation (SD) for PSFs:
Can you write Python code for it?

rm_mne = make_inverse_resolution_matrix(forward, inverse_operator,
                                        method='MNE', lambda2=lambda2)
ple_mne_psf = resolution_metrics(rm_mne, inverse_operator['src'],
                                 function='psf', metric='peak_err')
sd_mne_psf = resolution_metrics(rm_mne, inverse_operator['src'],
                                function='psf', metric='sd_ext')
del rm_mne


I am working on the file "0.23/_downloads/568aae18ec92d284aff29cfb5f3c11e7/resolution_metrics.ipynb".
The first task is:
dSPM
Do the same for dSPM:
Can you write Python code for it?

rm_dspm = make_inverse_resolution_matrix(forward, inverse_operator,
                                         method='dSPM', lambda2=lambda2)
ple_dspm_psf = resolution_metrics(rm_dspm, inverse_operator['src'],
                                  function='psf', metric='peak_err')
sd_dspm_psf = resolution_metrics(rm_dspm, inverse_operator['src'],
                                 function='psf', metric='sd_ext')
del rm_dspm, forward


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Alternatively, you can also create PSDs from Epochs objects with functions
that start with psd_ such as
:func:mne.time_frequency.psd_multitaper and
:func:mne.time_frequency.psd_welch.
Can you write Python code for it?

f, ax = plt.subplots()
psds, freqs = psd_multitaper(epochs, fmin=2, fmax=40, n_jobs=1)
psds = 10. * np.log10(psds)
psds_mean = psds.mean(0).mean(0)
psds_std = psds.mean(0).std(0)

ax.plot(freqs, psds_mean, color='k')
ax.fill_between(freqs, psds_mean - psds_std, psds_mean + psds_std,
                color='k', alpha=.5)
ax.set(title='Multitaper PSD (gradiometers)', xlabel='Frequency (Hz)',
       ylabel='Power Spectral Density (dB)')
plt.show()


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Frequency and time-frequency sensor analysis
The objective is to show you how to explore the spectral content
of your data (frequency and time-frequency). Here we'll work on Epochs.
We will use this dataset: somato-dataset. It contains so-called event
related synchronizations (ERS) / desynchronizations (ERD) in the beta band.
Can you write Python code for it?

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Stefan Appelhoff <stefan.appelhoff@mailbox.org>
#          Richard Höchenberger <richard.hoechenberger@gmail.com>
#
# License: BSD (3-clause)
import os.path as op

import numpy as np
import matplotlib.pyplot as plt

import mne
from mne.time_frequency import tfr_morlet, psd_multitaper, psd_welch
from mne.datasets import somato


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Inspect power

Note

The generated figures are interactive. In the topo you can click
    on an image to visualize the data for one sensor.
    You can also select a portion in the time-frequency plane to
    obtain a topomap for a certain time-frequency region.

Can you write Python code for it?

power.plot_topo(baseline=(-0.5, 0), mode='logratio', title='Average power')
power.plot([82], baseline=(-0.5, 0), mode='logratio', title=power.ch_names[82])

fig, axis = plt.subplots(1, 2, figsize=(7, 4))
power.plot_topomap(ch_type='grad', tmin=0.5, tmax=1.5, fmin=8, fmax=12,
                   baseline=(-0.5, 0), mode='logratio', axes=axis[0],
                   title='Alpha', show=False)
power.plot_topomap(ch_type='grad', tmin=0.5, tmax=1.5, fmin=13, fmax=25,
                   baseline=(-0.5, 0), mode='logratio', axes=axis[1],
                   title='Beta', show=False)
mne.viz.tight_layout()
plt.show()


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Joint Plot
You can also create a joint plot showing both the aggregated TFR
across channels and topomaps at specific times and frequencies to obtain
a quick overview regarding oscillatory effects across time and space.
Can you write Python code for it?

power.plot_joint(baseline=(-0.5, 0), mode='mean', tmin=-.5, tmax=2,
                 timefreqs=[(.5, 10), (1.3, 8)])


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Lastly, we can also retrieve the unaggregated segments by passing
average=None to :func:mne.time_frequency.psd_welch. The dimensions of
the returned array are (n_epochs, n_sensors, n_freqs, n_segments).
Can you write Python code for it?

psds_welch_unagg, freqs_unagg = psd_welch(epochs, average=None, **kwargs)
print(psds_welch_unagg.shape)


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Notably, :func:mne.time_frequency.psd_welch supports the keyword argument
average, which specifies how to estimate the PSD based on the individual
windowed segments. The default is average='mean', which simply calculates
the arithmetic mean across segments. Specifying average='median', in
contrast, returns the PSD based on the median of the segments (corrected for
bias relative to the mean), which is a more robust measure.
Can you write Python code for it?

# Estimate PSDs based on "mean" and "median" averaging for comparison.
kwargs = dict(fmin=2, fmax=40, n_jobs=1)
psds_welch_mean, freqs_mean = psd_welch(epochs, average='mean', **kwargs)
psds_welch_median, freqs_median = psd_welch(epochs, average='median', **kwargs)

# Convert power to dB scale.
psds_welch_mean = 10 * np.log10(psds_welch_mean)
psds_welch_median = 10 * np.log10(psds_welch_median)

# We will only plot the PSD for a single sensor in the first epoch.
ch_name = 'MEG 0122'
ch_idx = epochs.info['ch_names'].index(ch_name)
epo_idx = 0

_, ax = plt.subplots()
ax.plot(freqs_mean, psds_welch_mean[epo_idx, ch_idx, :], color='k',
        ls='-', label='mean of segments')
ax.plot(freqs_median, psds_welch_median[epo_idx, ch_idx, :], color='k',
        ls='--', label='median of segments')

ax.set(title='Welch PSD ({}, Epoch {})'.format(ch_name, epo_idx),
       xlabel='Frequency (Hz)', ylabel='Power Spectral Density (dB)')
ax.legend(loc='upper right')
plt.show()


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Now let's take a look at the spatial distributions of the PSD.
Can you write Python code for it?


I am working on the file "0.23/_downloads/58e35821e0f211b843d5ead3e33d8849/20_sensors_time_frequency.ipynb".
The first task is:
Time-frequency analysis: power and inter-trial coherence
We now compute time-frequency representations (TFRs) from our Epochs.
We'll look at power and inter-trial coherence (ITC).
To this we'll use the function :func:mne.time_frequency.tfr_morlet
but you can also use :func:mne.time_frequency.tfr_multitaper
or :func:mne.time_frequency.tfr_stockwell.

Note

The ``decim`` parameter reduces the sampling rate of the time-frequency
      decomposition by the defined factor. This is usually done to reduce
      memory usage. For more information refer to the documentation of
      :func:`mne.time_frequency.tfr_morlet`.

define frequencies of interest (log-spaced)
Can you write Python code for it?

freqs = np.logspace(*np.log10([6, 35]), num=8)
n_cycles = freqs / 2.  # different number of cycle per frequency
power, itc = tfr_morlet(epochs, freqs=freqs, n_cycles=n_cycles, use_fft=True,
                        return_itc=True, decim=3, n_jobs=1)


I am working on the file "0.23/_downloads/5ac2a3ff8baa6aba4bf6dd1d047703e2/spm_faces_dataset_sgskip.ipynb".
The first task is:
Compute forward model
Can you write Python code for it?

src = data_path + '/subjects/spm/bem/spm-oct-6-src.fif'
bem = data_path + '/subjects/spm/bem/spm-5120-5120-5120-bem-sol.fif'
forward = mne.make_forward_solution(contrast.info, trans_fname, src, bem)


I am working on the file "0.23/_downloads/5ac2a3ff8baa6aba4bf6dd1d047703e2/spm_faces_dataset_sgskip.ipynb".
The first task is:
Load and filter data, set up epochs
Can you write Python code for it?

raw_fname = data_path + '/MEG/spm/SPM_CTF_MEG_example_faces%d_3D.ds'

raw = io.read_raw_ctf(raw_fname % 1, preload=True)  # Take first run
# Here to save memory and time we'll downsample heavily -- this is not
# advised for real data as it can effectively jitter events!
raw.resample(120., npad='auto')

picks = mne.pick_types(raw.info, meg=True, exclude='bads')
raw.filter(1, 30, method='fir', fir_design='firwin')

events = mne.find_events(raw, stim_channel='UPPT001')

# plot the events to get an idea of the paradigm
mne.viz.plot_events(events, raw.info['sfreq'])

event_ids = {"faces": 1, "scrambled": 2}

tmin, tmax = -0.2, 0.6
baseline = None  # no baseline as high-pass is applied
reject = dict(mag=5e-12)

epochs = mne.Epochs(raw, events, event_ids, tmin, tmax, picks=picks,
                    baseline=baseline, preload=True, reject=reject)

# Fit ICA, find and remove major artifacts
ica = ICA(n_components=0.95, max_iter='auto', random_state=0)
ica.fit(raw, decim=1, reject=reject)

# compute correlation scores, get bad indices sorted by score
eog_epochs = create_eog_epochs(raw, ch_name='MRT31-2908', reject=reject)
eog_inds, eog_scores = ica.find_bads_eog(eog_epochs, ch_name='MRT31-2908')
ica.plot_scores(eog_scores, eog_inds)  # see scores the selection is based on
ica.plot_components(eog_inds)  # view topographic sensitivity of components
ica.exclude += eog_inds[:1]  # we saw the 2nd ECG component looked too dipolar
ica.plot_overlay(eog_epochs.average())  # inspect artifact removal
ica.apply(epochs)  # clean data, default in place

evoked = [epochs[k].average() for k in event_ids]

contrast = combine_evoked(evoked, weights=[-1, 1])  # Faces - scrambled

evoked.append(contrast)

for e in evoked:
    e.plot(ylim=dict(mag=[-400, 400]))

plt.show()

# estimate noise covarariance
noise_cov = mne.compute_covariance(epochs, tmax=0, method='shrunk',
                                   rank=None)


I am working on the file "0.23/_downloads/5b9edf9c05aec2b9bb1f128f174ca0f3/40_cluster_1samp_time_freq.ipynb".
The first task is:
Compute statistic
Can you write Python code for it?

threshold = 3.
n_permutations = 50  # Warning: 50 is way too small for real-world analysis.
T_obs, clusters, cluster_p_values, H0 = \
    permutation_cluster_1samp_test(epochs_power, n_permutations=n_permutations,
                                   threshold=threshold, tail=0,
                                   adjacency=adjacency,
                                   out_type='mask', verbose=True)


I am working on the file "0.23/_downloads/5b9edf9c05aec2b9bb1f128f174ca0f3/40_cluster_1samp_time_freq.ipynb".
The first task is:
Define adjacency for statistics
To compute a cluster-corrected value, we need a suitable definition
for the adjacency/adjacency of our values. So we first compute the
sensor adjacency, then combine that with a grid/lattice adjacency
assumption for the time-frequency plane:
Can you write Python code for it?

sensor_adjacency, ch_names = mne.channels.find_ch_adjacency(
    tfr_epochs.info, 'grad')
# Subselect the channels we are actually using
use_idx = [ch_names.index(ch_name.replace(' ', ''))
           for ch_name in tfr_epochs.ch_names]
sensor_adjacency = sensor_adjacency[use_idx][:, use_idx]
assert sensor_adjacency.shape == \
    (len(tfr_epochs.ch_names), len(tfr_epochs.ch_names))
assert epochs_power.data.shape == (
    len(epochs), len(tfr_epochs.ch_names),
    len(tfr_epochs.freqs), len(tfr_epochs.times))
adjacency = mne.stats.combine_adjacency(
    sensor_adjacency, len(tfr_epochs.freqs), len(tfr_epochs.times))

# our adjacency is square with each dim matching the data size
assert adjacency.shape[0] == adjacency.shape[1] == \
    len(tfr_epochs.ch_names) * len(tfr_epochs.freqs) * len(tfr_epochs.times)


I am working on the file "0.23/_downloads/5b9edf9c05aec2b9bb1f128f174ca0f3/40_cluster_1samp_time_freq.ipynb".
The first task is:
View time-frequency plots
Can you write Python code for it?

evoked_data = evoked.data
times = 1e3 * evoked.times

plt.figure()
plt.subplots_adjust(0.12, 0.08, 0.96, 0.94, 0.2, 0.43)

# Create new stats image with only significant clusters
T_obs_plot = np.nan * np.ones_like(T_obs)
for c, p_val in zip(clusters, cluster_p_values):
    if p_val <= 0.05:
        T_obs_plot[c] = T_obs[c]

# Just plot one channel's data
ch_idx, f_idx, t_idx = np.unravel_index(
    np.nanargmax(np.abs(T_obs_plot)), epochs_power.shape[1:])
# ch_idx = tfr_epochs.ch_names.index('MEG 1332')  # to show a specific one

vmax = np.max(np.abs(T_obs))
vmin = -vmax
plt.subplot(2, 1, 1)
plt.imshow(T_obs[ch_idx], cmap=plt.cm.gray,
           extent=[times[0], times[-1], freqs[0], freqs[-1]],
           aspect='auto', origin='lower', vmin=vmin, vmax=vmax)
plt.imshow(T_obs_plot[ch_idx], cmap=plt.cm.RdBu_r,
           extent=[times[0], times[-1], freqs[0], freqs[-1]],
           aspect='auto', origin='lower', vmin=vmin, vmax=vmax)
plt.colorbar()
plt.xlabel('Time (ms)')
plt.ylabel('Frequency (Hz)')
plt.title(f'Induced power ({tfr_epochs.ch_names[ch_idx]})')

ax2 = plt.subplot(2, 1, 2)
evoked.plot(axes=[ax2], time_unit='s')
plt.show()


I am working on the file "0.23/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
.. sidebar:: Annotating good spans
The default "BAD\_" prefix for new labels can be removed simply by
pressing the backspace key four times before typing your custom
annotation label.

You can see that default annotation label is "BAD_"; this can be edited
prior to pressing the "Add label" button to customize the label. The intent
is that users can annotate with as many or as few labels as makes sense for
their research needs, but that annotations marking spans that should be
excluded from the analysis pipeline should all begin with "BAD" or "bad"
(e.g., "bad_cough", "bad-eyes-closed", "bad door slamming", etc). When this
practice is followed, many processing steps in MNE-Python will automatically
exclude the "bad"-labelled spans of data; this behavior is controlled by a
parameter reject_by_annotation that can be found in many MNE-Python
functions or class constructors, including:

creation of epoched data from continuous data (:class:mne.Epochs)
many methods of the independent components analysis class
  (:class:mne.preprocessing.ICA)
functions for finding heartbeat and blink artifacts
  (:func:~mne.preprocessing.find_ecg_events,
  :func:~mne.preprocessing.find_eog_events)
covariance computations (:func:mne.compute_raw_covariance)
power spectral density computation (:meth:mne.io.Raw.plot_psd,
  :func:mne.time_frequency.psd_welch)

For example, when creating epochs from continuous data, if
reject_by_annotation=True the :class:~mne.Epochs constructor will drop
any epoch that partially or fully overlaps with an annotated span that begins
with "bad".
Generating annotations programmatically
The tut-artifact-overview tutorial introduced the artifact detection
functions :func:~mne.preprocessing.find_eog_events and
:func:~mne.preprocessing.find_ecg_events (although that tutorial mostly
relied on their higher-level wrappers
:func:~mne.preprocessing.create_eog_epochs and
:func:~mne.preprocessing.create_ecg_epochs). Here, for demonstration
purposes, we make use of the lower-level artifact detection function to get
an...
Can you write Python code for it?

eog_events = mne.preprocessing.find_eog_events(raw)
onsets = eog_events[:, 0] / raw.info['sfreq'] - 0.25
durations = [0.5] * len(eog_events)
descriptions = ['bad blink'] * len(eog_events)
blink_annot = mne.Annotations(onsets, durations, descriptions,
                              orig_time=raw.info['meas_date'])
raw.set_annotations(blink_annot)


I am working on the file "0.23/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
Annotating bad spans of data
The tutorial tut-events-vs-annotations describes how
:class:~mne.Annotations can be read from embedded events in the raw
recording file, and tut-annotate-raw describes in detail how to
interactively annotate a :class:~mne.io.Raw data object. Here, we focus on
best practices for annotating bad data spans so that they will be excluded
from your analysis pipeline.
The reject_by_annotation parameter
In the interactive raw.plot() window, the annotation controls can be
opened by pressing :kbd:a. Here, new annotation labels can be created or
existing annotation labels can be selected for use.
Can you write Python code for it?

fig = raw.plot()
fig.canvas.key_press_event('a')


I am working on the file "0.23/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
Finally, it should be noted that "dropped" epochs are not necessarily deleted
from the :class:~mne.Epochs object right away. Above, we forced the
dropping to happen when we created the :class:~mne.Epochs object by using
the preload=True parameter. If we had not done that, the
:class:~mne.Epochs object would have been memory-mapped_ (not loaded into
RAM), in which case the criteria for dropping epochs are stored, and the
actual dropping happens when the :class:~mne.Epochs data are finally loaded
and used. There are several ways this can get triggered, such as:

explicitly loading the data into RAM with the :meth:~mne.Epochs.load_data
  method
plotting the data (:meth:~mne.Epochs.plot,
  :meth:~mne.Epochs.plot_image, etc)
using the :meth:~mne.Epochs.average method to create an
  :class:~mne.Evoked object

You can also trigger dropping with the :meth:~mne.Epochs.drop_bad method;
if reject and/or flat criteria have already been provided to the
epochs constructor, :meth:~mne.Epochs.drop_bad can be used without
arguments to simply delete the epochs already marked for removal (if the
epochs have already been dropped, nothing further will happen):
Can you write Python code for it?


I am working on the file "0.23/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
Notice that we've passed reject_by_annotation=False above, in order to
isolate the effects of the rejection thresholds. If we re-run the epoching
with reject_by_annotation=True (the default) we see that the rejections
due to EEG and EOG channels have disappeared (suggesting that those channel
fluctuations were probably blink-related, and were subsumed by rejections
based on the "bad blink" label).
Can you write Python code for it?

epochs = mne.Epochs(raw, events, tmin=-0.2, tmax=0.5, reject_tmax=0,
                    reject=reject_criteria, flat=flat_criteria, preload=True)
epochs.plot_drop_log()


I am working on the file "0.23/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
Now we can confirm that the annotations are centered on the EOG events. Since
blinks are usually easiest to see in the EEG channels, we'll only plot EEG
here:
Can you write Python code for it?

eeg_picks = mne.pick_types(raw.info, meg=False, eeg=True)
raw.plot(events=eog_events, order=eeg_picks)


I am working on the file "0.23/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
Rejecting bad data spans
This tutorial covers manual marking of bad spans of data, and automated
rejection of data spans based on signal amplitude.
We begin as always by importing the necessary Python modules and loading some
example data <sample-dataset>; to save memory we'll use a pre-filtered
and downsampled version of the example data, and we'll also load an events
array to use when converting the continuous data to epochs:
Can you write Python code for it?

import os
import mne

sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis_filt-0-40_raw.fif')
raw = mne.io.read_raw_fif(sample_data_raw_file, verbose=False)
events_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                           'sample_audvis_filt-0-40_raw-eve.fif')
events = mne.read_events(events_file)


I am working on the file "0.23/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
See the section tut-section-programmatic-annotations for more details
on creating annotations programmatically.
Rejecting Epochs based on channel amplitude
Besides "bad" annotations, the :class:mne.Epochs class constructor has
another means of rejecting epochs, based on signal amplitude thresholds for
each channel type. In the overview tutorial
<tut-section-overview-epoching> we saw an example of this: setting maximum
acceptable peak-to-peak amplitudes for each channel type in an epoch, using
the reject parameter. There is also a related parameter, flat, that
can be used to set minimum acceptable peak-to-peak amplitudes for each
channel type in an epoch:
Can you write Python code for it?

reject_criteria = dict(mag=3000e-15,     # 3000 fT
                       grad=3000e-13,    # 3000 fT/cm
                       eeg=100e-6,       # 100 µV
                       eog=200e-6)       # 200 µV

flat_criteria = dict(mag=1e-15,          # 1 fT
                     grad=1e-13,         # 1 fT/cm
                     eeg=1e-6)           # 1 µV


I am working on the file "0.23/_downloads/5f078eabe74f0448d3e1662c12313289/source_space_time_frequency.ipynb".
The first task is:
Compute induced power in the source space with dSPM
Returns STC files ie source estimates of induced power
for different bands in the source space. The inverse method
is linear based on dSPM inverse operator.
Can you write Python code for it?

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#
# License: BSD (3-clause)

import matplotlib.pyplot as plt

import mne
from mne import io
from mne.datasets import sample
from mne.minimum_norm import read_inverse_operator, source_band_induced_power

print(__doc__)


I am working on the file "0.23/_downloads/5f078eabe74f0448d3e1662c12313289/source_space_time_frequency.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_raw.fif'
fname_inv = data_path + '/MEG/sample/sample_audvis-meg-oct-6-meg-inv.fif'
tmin, tmax, event_id = -0.2, 0.5, 1

# Setup for reading the raw data
raw = io.read_raw_fif(raw_fname)
events = mne.find_events(raw, stim_channel='STI 014')
inverse_operator = read_inverse_operator(fname_inv)

include = []
raw.info['bads'] += ['MEG 2443', 'EEG 053']  # bads + 2 more

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

# Load condition 1
event_id = 1
events = events[:10]  # take 10 events to keep the computation time low
# Use linear detrend to reduce any edge artifacts
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=picks,
                    baseline=(None, 0), reject=dict(grad=4000e-13, eog=150e-6),
                    preload=True, detrend=1)

# Compute a source estimate per frequency band
bands = dict(alpha=[9, 11], beta=[18, 22])

stcs = source_band_induced_power(epochs, inverse_operator, bands, n_cycles=2,
                                 use_fft=False, n_jobs=1)

for b, stc in stcs.items():
    stc.save('induced_power_%s' % b)


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Compute confusion matrix using ROC-AUC
Can you write Python code for it?

confusion = np.zeros((len(classes), len(classes)))
for ii, train_class in enumerate(classes):
    for jj in range(ii, len(classes)):
        confusion[ii, jj] = roc_auc_score(y == train_class, y_pred[:, jj])
        confusion[jj, ii] = confusion[ii, jj]


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Confusion matrix related to mental representations have been historically
summarized with dimensionality reduction using multi-dimensional scaling [1].
See how the face samples cluster together.
Can you write Python code for it?

fig, ax = plt.subplots(1)
mds = MDS(2, random_state=0, dissimilarity='precomputed')
chance = 0.5
summary = mds.fit_transform(chance - confusion)
cmap = plt.get_cmap('rainbow')
colors = ['r', 'b']
names = list(conds['condition'].values)
for color, name in zip(colors, set(names)):
    sel = np.where([this_name == name for this_name in names])[0]
    size = 500 if name == 'human face' else 100
    ax.scatter(summary[sel, 0], summary[sel, 1], s=size,
               facecolors=color, label=name, edgecolors='k')
ax.axis('off')
ax.legend(loc='lower right', scatterpoints=1, ncol=2)
plt.tight_layout()
plt.show()


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Define stimulus - trigger mapping
Can you write Python code for it?

conditions = []
for c in conds.values:
    cond_tags = list(c[:2])
    cond_tags += [('not-' if i == 0 else '') + conds.columns[k]
                  for k, i in enumerate(c[2:], 2)]
    conditions.append('/'.join(map(str, cond_tags)))
print(conditions[:10])


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Epoch data
Can you write Python code for it?

picks = mne.pick_types(raw.info, meg=True)
epochs = mne.Epochs(raw, events=events, event_id=event_id, baseline=None,
                    picks=picks, tmin=-.1, tmax=.500, preload=True)


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Let's make the event_id dictionary
Can you write Python code for it?

event_id = dict(zip(conditions, conds.trigger + 1))
event_id['0/human bodypart/human/not-face/animal/natural']


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Let's plot some conditions
Can you write Python code for it?


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Let's restrict the number of conditions to speed up computation
Can you write Python code for it?

max_trigger = 24
conds = conds[:max_trigger]  # take only the first 24 rows


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Read MEG data
Can you write Python code for it?

n_runs = 4  # 4 for full data (use less to speed up computations)
fname = op.join(data_path, 'sample_subject_%i_tsss_mc.fif')
raws = [read_raw_fif(fname % block, verbose='error')
        for block in range(n_runs)]  # ignore filename warnings
raw = concatenate_raws(raws)

events = mne.find_events(raw, min_duration=.002)

events = events[events[:, 2] <= max_trigger]


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Representational Similarity Analysis
Representational Similarity Analysis is used to perform summary statistics
on supervised classifications where the number of classes is relatively high.
It consists in characterizing the structure of the confusion matrix to infer
the similarity between brain responses and serves as a proxy for characterizing
the space of mental representations
:footcite:Shepard1980,LaaksoCottrell2000,KriegeskorteEtAl2008.
In this example, we perform RSA on responses to 24 object images (among
a list of 92 images). Subjects were presented with images of human, animal
and inanimate objects :footcite:CichyEtAl2014. Here we use the 24 unique
images of faces and body parts.

Note

this example will download a very large (~6GB) file, so we will not
          build the images below.

Can you write Python code for it?

# Authors: Jean-Remi King <jeanremi.king@gmail.com>
#          Jaakko Leppakangas <jaeilepp@student.jyu.fi>
#          Alexandre Gramfort <alexandre.gramfort@inria.fr>
#
# License: BSD (3-clause)

import os.path as op
import numpy as np
from pandas import read_csv
import matplotlib.pyplot as plt

from sklearn.model_selection import StratifiedKFold
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
from sklearn.manifold import MDS

import mne
from mne.io import read_raw_fif, concatenate_raws
from mne.datasets import visual_92_categories

print(__doc__)

data_path = visual_92_categories.data_path()

# Define stimulus - trigger mapping
fname = op.join(data_path, 'visual_stimuli.csv')
conds = read_csv(fname)
print(conds.head(5))


I am working on the file "0.23/_downloads/61268d5dc873438a743241ad21a989fd/decoding_rsa_sgskip.ipynb".
The first task is:
Representational Similarity Analysis (RSA) is a neuroimaging-specific
appelation to refer to statistics applied to the confusion matrix
also referred to as the representational dissimilarity matrices (RDM).
Compared to the approach from Cichy et al. we'll use a multiclass
classifier (Multinomial Logistic Regression) while the paper uses
all pairwise binary classification task to make the RDM.
Also we use here the ROC-AUC as performance metric while the
paper uses accuracy. Finally here for the sake of time we use
RSA on a window of data while Cichy et al. did it for all time
instants separately.
Can you write Python code for it?

# Classify using the average signal in the window 50ms to 300ms
# to focus the classifier on the time interval with best SNR.
clf = make_pipeline(StandardScaler(),
                    LogisticRegression(C=1, solver='liblinear',
                                       multi_class='auto'))
X = epochs.copy().crop(0.05, 0.3).get_data().mean(axis=2)
y = epochs.events[:, 2]

classes = set(y)
cv = StratifiedKFold(n_splits=5, random_state=0, shuffle=True)

# Compute confusion matrix for each cross-validation fold
y_pred = np.zeros((len(y), len(classes)))
for train, test in cv.split(X, y):
    # Fit
    clf.fit(X[train], y[train])
    # Probabilistic prediction (necessary for ROC-AUC scoring metric)
    y_pred[test] = clf.predict_proba(X[test])


I am working on the file "0.23/_downloads/64e3b6395952064c08d4ff33d6236ff3/evoked_whitening.ipynb".
The first task is:
Compute covariance using automated regularization
Can you write Python code for it?

method_params = dict(diagonal_fixed=dict(mag=0.01, grad=0.01, eeg=0.01))
noise_covs = compute_covariance(epochs, tmin=None, tmax=0, method='auto',
                                return_estimators=True, verbose=True, n_jobs=1,
                                projs=None, rank=None,
                                method_params=method_params)

# With "return_estimator=True" all estimated covariances sorted
# by log-likelihood are returned.

print('Covariance estimates sorted from best to worst')
for c in noise_covs:
    print("%s : %s" % (c['method'], c['loglik']))


I am working on the file "0.23/_downloads/64e3b6395952064c08d4ff33d6236ff3/evoked_whitening.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'

raw = io.read_raw_fif(raw_fname, preload=True)
raw.filter(1, 40, n_jobs=1, fir_design='firwin')
raw.info['bads'] += ['MEG 2443']  # bads + 1 more
events = mne.read_events(event_fname)

# let's look at rare events, button presses
event_id, tmin, tmax = 2, -0.2, 0.5
reject = dict(mag=4e-12, grad=4000e-13, eeg=80e-6)

epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=('meg', 'eeg'),
                    baseline=None, reject=reject, preload=True)

# Uncomment next line to use fewer samples and study regularization effects
# epochs = epochs[:20]  # For your data, use as many samples as you can!


I am working on the file "0.23/_downloads/64e3b6395952064c08d4ff33d6236ff3/evoked_whitening.ipynb".
The first task is:
Show the evoked data:
Can you write Python code for it?

evoked = epochs.average()

evoked.plot(time_unit='s')  # plot evoked response


I am working on the file "0.23/_downloads/64e3b6395952064c08d4ff33d6236ff3/evoked_whitening.ipynb".
The first task is:
We can then show whitening for our various noise covariance estimates.
Here we should look to see if baseline signals match the
assumption of Gaussian white noise. we expect values centered at
0 within 2 standard deviations for 95% of the time points.
For the Global field power we expect a value of 1.
Can you write Python code for it?


I am working on the file "0.23/_downloads/64e3b6395952064c08d4ff33d6236ff3/evoked_whitening.ipynb".
The first task is:
Whitening evoked data with a noise covariance
Evoked data are loaded and then whitened using a given noise covariance
matrix. It's an excellent quality check to see if baseline signals match
the assumption of Gaussian white noise during the baseline period.
Covariance estimation and diagnostic plots are based on
:footcite:EngemannGramfort2015.
References
.. footbibliography::
Can you write Python code for it?

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Denis A. Engemann <denis.engemann@gmail.com>
#
# License: BSD (3-clause)

import mne

from mne import io
from mne.datasets import sample
from mne.cov import compute_covariance

print(__doc__)


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
.. sidebar:: Info consistency
When assigning new values to the fields of an `~mne.Info` object, it is
important that the fields stay consistent. if there are ``N`` channels:

- The length of the channel information field ``chs`` must be ``N``.
- The length of the ``ch_names`` field must be ``N``.
- The ``ch_names`` field should be consistent with the ``name``
  field of the channel information contained in ``chs``.

Note the new field dig that includes our seven channel locations as well
as theoretical values for the three
:term:cardinal scalp landmarks <fiducial point>.
Additional fields can be added in the same way that Python dictionaries are
modified, using square-bracket key assignment:
Can you write Python code for it?

info['description'] = 'My custom dataset'
info['bads'] = ['O1']  # Names of bad channels
print(info)


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
Creating ~mne.Epochs objects
To create an ~mne.Epochs object from scratch, you can use the
mne.EpochsArray class constructor, which takes an ~mne.Info object and a
:class:NumPy array <numpy.ndarray> of shape (n_epochs, n_channels,
n_samples). Here we'll create 5 epochs of our 2-channel data, and plot it.
Notice that we have to pass picks='misc' to the ~mne.Epochs.plot
method, because by default it only plots :term:data channels.
Can you write Python code for it?

data = np.array([[0.2 * sine, 1.0 * cosine],
                 [0.4 * sine, 0.8 * cosine],
                 [0.6 * sine, 0.6 * cosine],
                 [0.8 * sine, 0.4 * cosine],
                 [1.0 * sine, 0.2 * cosine]])

simulated_epochs = mne.EpochsArray(data, info)
simulated_epochs.plot(picks='misc', show_scrollbars=False)


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
Creating ~mne.io.Raw objects
.. sidebar:: Units
The expected units for the different channel types are:

- Volts: eeg, eog, seeg, dbs, emg, ecg, bio, ecog
- Teslas: mag
- Teslas/meter: grad
- Molar: hbo, hbr
- Amperes: dipole
- Arbitrary units: misc

To create a ~mne.io.Raw object from scratch, you can use the
mne.io.RawArray class constructor, which takes an ~mne.Info object and a
:class:NumPy array <numpy.ndarray> of shape (n_channels, n_samples).
Here, we'll create some sinusoidal data and plot it:
Can you write Python code for it?

times = np.linspace(0, 1, sampling_freq, endpoint=False)
sine = np.sin(20 * np.pi * times)
cosine = np.cos(10 * np.pi * times)
data = np.array([sine, cosine])

info = mne.create_info(ch_names=['10 Hz sine', '5 Hz cosine'],
                       ch_types=['misc'] * 2,
                       sfreq=sampling_freq)

simulated_raw = mne.io.RawArray(data, info)
simulated_raw.plot(show_scrollbars=False, show_scalebars=False)


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
If the channel names follow one of the standard montage naming schemes, their
spatial locations can be automatically added using the
~mne.Info.set_montage method:
Can you write Python code for it?

ch_names = ['Fp1', 'Fp2', 'Fz', 'Cz', 'Pz', 'O1', 'O2']
ch_types = ['eeg'] * 7
info = mne.create_info(ch_names, ch_types=ch_types, sfreq=sampling_freq)
info.set_montage('standard_1020')


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
If we want to simulate having different experimental conditions, we can pass
an event array (and an event ID dictionary) to the constructor. Since our
epochs are 1 second long and have 200 samples/second, we'll put our events
spaced 200 samples apart, and pass tmin=-0.5, so that the events
land in the middle of each epoch (the events are always placed at time=0 in
each epoch).
Can you write Python code for it?

events = np.column_stack((np.arange(0, 1000, sampling_freq),
                          np.zeros(5, dtype=int),
                          np.array([1, 2, 1, 2, 1])))
event_dict = dict(condition_A=1, condition_B=2)
simulated_epochs = mne.EpochsArray(data, info, tmin=-0.5, events=events,
                                   event_id=event_dict)
simulated_epochs.plot(picks='misc', show_scrollbars=False, events=events,
                      event_id=event_dict)


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
Since we did not supply an events array, the ~mne.EpochsArray constructor
automatically created one for us, with all epochs having the same event
number:
Can you write Python code for it?


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
You can see in the output above that, by default, the channels are assigned
as type "misc" (where it says chs: 32 MISC). You can assign the channel
type when initializing the ~mne.Info object if you want:
Can you write Python code for it?

ch_names = [f'MEG{n:03}' for n in range(1, 10)] + ['EOG001']
ch_types = ['mag', 'grad', 'grad'] * 3 + ['eog']
info = mne.create_info(ch_names, ch_types=ch_types, sfreq=sampling_freq)
print(info)


I am working on the file "0.23/_downloads/6606225adee10a4b2296b56fd8513f72/10_array_objs.ipynb".
The first task is:
You could also create simulated epochs by using the normal ~mne.Epochs
(not ~mne.EpochsArray) constructor on the simulated ~mne.io.RawArray
object, by creating an events array (e.g., using
mne.make_fixed_length_events) and extracting epochs around those events.
Creating ~mne.Evoked Objects
If you already have data that was averaged across trials, you can use it to
create an ~mne.Evoked object using the ~mne.EvokedArray class
constructor.  It requires an ~mne.Info object and a data array of shape
(n_channels, n_times), and has an optional tmin parameter like
~mne.EpochsArray does. It also has a parameter nave indicating how many
trials were averaged together, and a comment parameter useful for keeping
track of experimental conditions, etc. Here we'll do the averaging on our
NumPy array and use the resulting averaged data to make our ~mne.Evoked.
Can you write Python code for it?

# Create the Evoked object
evoked_array = mne.EvokedArray(data.mean(axis=0), info, tmin=-0.5,
                               nave=data.shape[0], comment='simulated')
print(evoked_array)
evoked_array.plot()


I am working on the file "0.23/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
Background on filtering
A filter removes or attenuates parts of a signal. Usually, filters act on
specific frequency ranges of a signal — for example, suppressing all
frequency components above or below a certain cutoff value. There are many
ways of designing digital filters; see disc-filtering for a longer
discussion of the various approaches to filtering physiological signals in
MNE-Python.
Repairing artifacts by filtering
Artifacts that are restricted to a narrow frequency range can sometimes
be repaired by filtering the data. Two examples of frequency-restricted
artifacts are slow drifts and power line noise. Here we illustrate how each
of these can be repaired by filtering.
Slow drifts
Low-frequency drifts in raw data can usually be spotted by plotting a fairly
long span of data with the :meth:~mne.io.Raw.plot method, though it is
helpful to disable channel-wise DC shift correction to make slow drifts
more readily visible. Here we plot 60 seconds, showing all the magnetometer
channels:
Can you write Python code for it?

mag_channels = mne.pick_types(raw.info, meg='mag')
raw.plot(duration=60, order=mag_channels, proj=False,
         n_channels=len(mag_channels), remove_dc=False)


I am working on the file "0.23/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
Because resampling involves filtering, there are some pitfalls to resampling
at different points in the analysis stream:

Performing resampling on :class:~mne.io.Raw data (before epoching) will
  negatively affect the temporal precision of Event arrays, by causing
  jitter_ in the event timing. This reduced temporal precision will
  propagate to subsequent epoching operations.

Performing resampling after epoching can introduce edge artifacts on
  every epoch, whereas filtering the :class:~mne.io.Raw object will only
  introduce artifacts at the start and end of the recording (which is often
  far enough from the first and last epochs to have no affect on the
  analysis).

The following section suggests best practices to mitigate both of these
issues.
Best practices
To avoid the reduction in temporal precision of events that comes with
resampling a :class:~mne.io.Raw object, and also avoid the edge artifacts
that come with filtering an :class:~mne.Epochs or :class:~mne.Evoked
object, the best practice is to:

low-pass filter the :class:~mne.io.Raw data at or below
   $\frac{1}{3}$ of the desired sample rate, then

decimate the data after epoching, by either passing the decim
   parameter to the :class:~mne.Epochs constructor, or using the
   :meth:~mne.Epochs.decimate method after the :class:~mne.Epochs have
   been created.

Warning

The recommendation for setting the low-pass corner frequency at
   $\frac{1}{3}$ of the desired sample rate is a fairly safe rule of
   thumb based on the default settings in :meth:`raw.filter()
   <mne.io.Raw.filter>` (which are different from the filter settings used
   inside the :meth:`raw.resample() <mne.io.Raw.resample>` method). If you
   use a customized lowpass filter (specifically, if your transition
   bandwidth is wider than 0.5× the lowpass cutoff), downsampling to 3× the
   lowpass cutoff may still not be enough to avoid `aliasing`_, and
   MNE-Python will not warn you about it (because the :class:`raw.info
  ...
Can you write Python code for it?

current_sfreq = raw.info['sfreq']
desired_sfreq = 90  # Hz
decim = np.round(current_sfreq / desired_sfreq).astype(int)
obtained_sfreq = current_sfreq / decim
lowpass_freq = obtained_sfreq / 3.

raw_filtered = raw.copy().filter(l_freq=None, h_freq=lowpass_freq)
events = mne.find_events(raw_filtered)
epochs = mne.Epochs(raw_filtered, events, decim=decim)

print('desired sampling frequency was {} Hz; decim factor of {} yielded an '
      'actual sampling frequency of {} Hz.'
      .format(desired_sfreq, decim, epochs.info['sfreq']))


I am working on the file "0.23/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
It should be evident that MEG channels are more susceptible to this kind of
interference than EEG that is recorded in the magnetically shielded room.
Removing power-line noise can be done with a notch filter,
applied directly to the :class:~mne.io.Raw object, specifying an array of
frequencies to be attenuated. Since the EEG channels are relatively
unaffected by the power line noise, we'll also specify a picks argument
so that only the magnetometers and gradiometers get filtered:
Can you write Python code for it?

meg_picks = mne.pick_types(raw.info, meg=True)
freqs = (60, 120, 180, 240)
raw_notch = raw.copy().notch_filter(freqs=freqs, picks=meg_picks)
for title, data in zip(['Un', 'Notch '], [raw, raw_notch]):
    fig = data.plot_psd(fmax=250, average=True)
    fig.subplots_adjust(top=0.85)
    fig.suptitle('{}filtered'.format(title), size='xx-large', weight='bold')
    add_arrows(fig.axes[:2])


I am working on the file "0.23/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
Looks like 0.1 Hz was not quite high enough to fully remove the slow drifts.
Notice that the text output summarizes the relevant characteristics of the
filter that was created. If you want to visualize the filter, you can pass
the same arguments used in the call to :meth:raw.filter()
<mne.io.Raw.filter> above to the function :func:mne.filter.create_filter
to get the filter parameters, and then pass the filter parameters to
:func:mne.viz.plot_filter. :func:~mne.filter.create_filter also requires
parameters data (a :class:NumPy array <numpy.ndarray>) and sfreq
(the sampling frequency of the data), so we'll extract those from our
:class:~mne.io.Raw object:
Can you write Python code for it?

filter_params = mne.filter.create_filter(raw.get_data(), raw.info['sfreq'],
                                         l_freq=0.2, h_freq=None)


I am working on the file "0.23/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
Notice that the output is the same as when we applied this filter to the data
using :meth:raw.filter() <mne.io.Raw.filter>. You can now pass the filter
parameters (and the sampling frequency) to :func:~mne.viz.plot_filter to
plot the filter:
Can you write Python code for it?

mne.viz.plot_filter(filter_params, raw.info['sfreq'], flim=(0.01, 5))


I am working on the file "0.23/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
Resampling
EEG and MEG recordings are notable for their high temporal precision, and are
often recorded with sampling rates around 1000 Hz or higher. This is good
when precise timing of events is important to the experimental design or
analysis plan, but also consumes more memory and computational resources when
processing the data. In cases where high-frequency components of the signal
are not of interest and precise timing is not needed (e.g., computing EOG or
ECG projectors on a long recording), downsampling the signal can be a useful
time-saver.
In MNE-Python, the resampling methods (:meth:raw.resample()
<mne.io.Raw.resample>, :meth:epochs.resample() <mne.Epochs.resample> and
:meth:evoked.resample() <mne.Evoked.resample>) apply a low-pass filter to
the signal to avoid aliasing, so you don't need to explicitly filter it
yourself first. This built-in filtering that happens when using
:meth:raw.resample() <mne.io.Raw.resample>, :meth:epochs.resample()
<mne.Epochs.resample>, or :meth:evoked.resample() <mne.Evoked.resample> is
a brick-wall filter applied in the frequency domain at the Nyquist
frequency of the desired new sampling rate. This can be clearly seen in the
PSD plot, where a dashed vertical line indicates the filter cutoff; the
original data had an existing lowpass at around 172 Hz (see
raw.info['lowpass']), and the data resampled from 600 Hz to 200 Hz gets
automatically lowpass filtered at 100 Hz (the Nyquist frequency_ for a
target rate of 200 Hz):
Can you write Python code for it?

raw_downsampled = raw.copy().resample(sfreq=200)

for data, title in zip([raw, raw_downsampled], ['Original', 'Downsampled']):
    fig = data.plot_psd(average=True)
    fig.subplots_adjust(top=0.9)
    fig.suptitle(title)
    plt.setp(fig.axes, xlim=(0, 300))


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
A stat_fun must deal with a variable number of input arguments.
Inside the clustering function each condition will be passed as flattened
array, necessitated by the clustering procedure. The ANOVA however expects an
input array of dimensions: subjects X conditions X observations (optional).
The following function catches the list input and swaps the first and the
second dimension, and finally calls ANOVA.

Note

For further details on this ANOVA function consider the
          corresponding
          `time-frequency tutorial <tut-timefreq-twoway-anova>`.

Can you write Python code for it?

def stat_fun(*args):
    # get f-values only.
    return f_mway_rm(np.swapaxes(args, 1, 0), factor_levels=factor_levels,
                     effects=effects, return_pvals=return_pvals)[0]


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Compute clustering statistic
To use an algorithm optimized for spatio-temporal clustering, we
just pass the spatial adjacency matrix (instead of spatio-temporal).
Can you write Python code for it?

# as we only have one hemisphere we need only need half the adjacency
print('Computing adjacency.')
adjacency = mne.spatial_src_adjacency(src[:1])

#    Now let's actually do the clustering. Please relax, on a small
#    notebook and one single thread only this will take a couple of minutes ...
pthresh = 0.0005
f_thresh = f_threshold_mway_rm(n_subjects, factor_levels, effects, pthresh)

#    To speed things up a bit we will ...
n_permutations = 128  # ... run fewer permutations (reduces sensitivity)

print('Clustering.')
T_obs, clusters, cluster_p_values, H0 = clu = \
    spatio_temporal_cluster_test(X, adjacency=adjacency, n_jobs=1,
                                 threshold=f_thresh, stat_fun=stat_fun,
                                 n_permutations=n_permutations,
                                 buffer_size=None)
#    Now select the clusters that are sig. at p < 0.05 (note that this value
#    is multiple-comparisons corrected).
good_cluster_inds = np.where(cluster_p_values < 0.05)[0]


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Finally we will pick the interaction effect by passing 'A:B'.
(this notation is borrowed from the R formula language).
As an aside, note that in this particular example, we cannot use the A*B
notation which return both the main and the interaction effect. The reason
is that the clustering function expects stat_fun to return a 1-D array.
To get clusters for both, you must create a loop.
Can you write Python code for it?

effects = 'A:B'
# Tell the ANOVA not to compute p-values which we don't need for clustering
return_pvals = False

# a few more convenient bindings
n_times = X[0].shape[1]
n_conditions = 4


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Finally, let's investigate interaction effect by reconstructing the time
courses:
Can you write Python code for it?

inds_t, inds_v = [(clusters[cluster_ind]) for ii, cluster_ind in
                  enumerate(good_cluster_inds)][0]  # first cluster

times = np.arange(X[0].shape[1]) * tstep * 1e3

plt.figure()
colors = ['y', 'b', 'g', 'purple']
event_ids = ['l_aud', 'r_aud', 'l_vis', 'r_vis']

for ii, (condition, color, eve_id) in enumerate(zip(X, colors, event_ids)):
    # extract time course at cluster vertices
    condition = condition[:, :, inds_v]
    # normally we would normalize values across subjects but
    # here we use data from the same subject so we're good to just
    # create average time series across subjects and vertices.
    mean_tc = condition.mean(axis=2).mean(axis=0)
    std_tc = condition.std(axis=2).std(axis=0)
    plt.plot(times, mean_tc.T, color=color, label=eve_id)
    plt.fill_between(times, mean_tc + std_tc, mean_tc - std_tc, color='gray',
                     alpha=0.5, label='')

ymin, ymax = mean_tc.min() - 5, mean_tc.max() + 5
plt.xlabel('Time (ms)')
plt.ylabel('Activation (F-values)')
plt.xlim(times[[0, -1]])
plt.ylim(ymin, ymax)
plt.fill_betweenx((ymin, ymax), times[inds_t[0]],
                  times[inds_t[-1]], color='orange', alpha=0.3)
plt.legend()
plt.title('Interaction between stimulus-modality and location.')
plt.show()


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Read epochs for all channels, removing a bad one
Can you write Python code for it?

raw.info['bads'] += ['MEG 2443']
picks = mne.pick_types(raw.info, meg=True, eog=True, exclude='bads')
# we'll load all four conditions that make up the 'two ways' of our ANOVA

event_id = dict(l_aud=1, r_aud=2, l_vis=3, r_vis=4)
reject = dict(grad=1000e-13, mag=4000e-15, eog=150e-6)
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=picks,
                    baseline=(None, 0), reject=reject, preload=True)

#    Equalize trial counts to eliminate bias (which would otherwise be
#    introduced by the abs() performed below)
epochs.equalize_event_counts(event_id)


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Repeated measures ANOVA on source data with spatio-temporal clustering
This example illustrates how to make use of the clustering functions
for arbitrary, self-defined contrasts beyond standard t-tests. In this
case we will tests if the differences in evoked responses between
stimulation modality (visual VS auditory) depend on the stimulus
location (left vs right) for a group of subjects (simulated here
using one subject's data). For this purpose we will compute an
interaction effect using a repeated measures ANOVA. The multiple
comparisons problem is addressed with a cluster-level permutation test
across space and time.
Can you write Python code for it?

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Eric Larson <larson.eric.d@gmail.com>
#          Denis Engemannn <denis.engemann@gmail.com>
#
# License: BSD (3-clause)

import os.path as op
import numpy as np
from numpy.random import randn
import matplotlib.pyplot as plt

import mne
from mne.stats import (spatio_temporal_cluster_test, f_threshold_mway_rm,
                       f_mway_rm, summarize_clusters_stc)

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

print(__doc__)


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Transform to common cortical space
Normally you would read in estimates across several subjects and morph them
to the same cortical space (e.g. fsaverage). For example purposes, we will
simulate this by just having each "subject" have the same response (just
noisy in source space) here.
We'll only consider the left hemisphere in this tutorial.
Can you write Python code for it?

n_vertices_sample, n_times = conditions[0].lh_data.shape
n_subjects = 7
print('Simulating data for %d subjects.' % n_subjects)

#    Let's make sure our results replicate, so set the seed.
np.random.seed(0)
X = randn(n_vertices_sample, n_times, n_subjects, 4) * 10
for ii, condition in enumerate(conditions):
    X[:, :, :, ii] += condition.lh_data[:, :, np.newaxis]


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Transform to source space
Can you write Python code for it?

fname_inv = data_path + '/MEG/sample/sample_audvis-meg-oct-6-meg-inv.fif'
snr = 3.0
lambda2 = 1.0 / snr ** 2
method = "dSPM"  # use dSPM method (could also be MNE, sLORETA, or eLORETA)
inverse_operator = read_inverse_operator(fname_inv)

# we'll only use one hemisphere to speed up this example
# instead of a second vertex array we'll pass an empty array
sample_vertices = [inverse_operator['src'][0]['vertno'], np.array([], int)]

#    Let's average and compute inverse, then resample to speed things up
conditions = []
for cond in ['l_aud', 'r_aud', 'l_vis', 'r_vis']:  # order is important
    evoked = epochs[cond].average()
    evoked.resample(50, npad='auto')
    condition = apply_inverse(evoked, inverse_operator, lambda2, method)
    #    Let's only deal with t > 0, cropping to reduce multiple comparisons
    condition.crop(0, None)
    conditions.append(condition)

tmin = conditions[0].tmin
tstep = conditions[0].tstep * 1000  # convert to milliseconds


I am working on the file "0.23/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Visualize the clusters
Can you write Python code for it?

print('Visualizing clusters.')

#    Now let's build a convenient representation of each cluster, where each
#    cluster becomes a "time point" in the SourceEstimate
stc_all_cluster_vis = summarize_clusters_stc(clu, tstep=tstep,
                                             vertices=fsave_vertices,
                                             subject='fsaverage')

#    Let's actually plot the first "time point" in the SourceEstimate, which
#    shows all the clusters, weighted by duration

subjects_dir = op.join(data_path, 'subjects')
# The brighter the color, the stronger the interaction between
# stimulus modality and stimulus location

brain = stc_all_cluster_vis.plot(subjects_dir=subjects_dir, views='lat',
                                 time_label='temporal extent (ms)',
                                 clim=dict(kind='value', lims=[0, 1, 40]))
brain.save_image('cluster-lh.png')
brain.show_view('medial')


I am working on the file "0.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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) :footcite:ParksBurrus1987
and Ifeachor & Jervis (2002) :footcite:IfeachorJervis2002,
and for filtering in an M/EEG context we recommend reading
Widmann et al. (2015) :footcite:WidmannEtAl2015.

Note

This tutorial goes pretty deep into the mathematics of filtering and the
   design decisions that go into choosing a filter. If you just want to know
   how to apply the default filters in MNE-Python to your data, skip this
   tutorial and read `tut-filter-resample` instead (but someday, you
   should come back and read this one too 🙂).

Problem statement
Practical issues with filtering electrophysiological data are covered
in Widmann et al. (2012) :footcite:WidmannSchroger2012, 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)
:footcite:`VanRullen2011`.
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...
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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
Both groups seem to acknowledge that the choices of filtering cutoffs, and
perhaps even the application of baseline correction, depend on the
characteristics of the data being investigated, especially when it comes to:

The frequency content of the underlying evoked activity relative
      to the filtering parameters.
The validity of the assumption of no consistent evoked activity
      in the baseline period.

We thus recommend carefully applying baseline correction and/or high-pass
values based on the characteristics of the data to be analyzed.
Filtering defaults
Defaults in MNE-Python
Most often, filtering in MNE-Python is done at the :class:mne.io.Raw level,
and thus :func:mne.io.Raw.filter is used. This function under the hood
(among other things) calls :func:mne.filter.filter_data to actually
filter the data, which by default applies a zero-phase FIR filter designed
using :func:scipy.signal.firwin.
In Widmann et al. (2015) :footcite:WidmannEtAl2015, they
suggest a specific set of parameters to use for high-pass filtering,
including:
"... providing a transition bandwidth of 25% of the lower passband
edge but, where possible, not lower than 2 Hz and otherwise the
distance from the passband edge to the critical frequency.”

In practice, this means that for each high-pass value l_freq or
low-pass value h_freq below, you would get this corresponding
l_trans_bandwidth or h_trans_bandwidth, respectively,
if the sample rate were 100 Hz (i.e., Nyquist frequency of 50 Hz):
+------------------+-------------------+-------------------+
| l_freq or h_freq | l_trans_bandwidth | h_trans_bandwidth |
+==================+===================+===================+
|             0.01 |              0.01 |               2.0 |
+------------------+-------------------+-------------------+
|              0.1 |               0.1 |               2.0 |
+------------------+-------------------+-------------------+
|              1.0 |               1.0 |               2.0 |
+------------------+-------------------+-------------------+
|...
Can you write Python code for it?

# Use the same settings as when calling e.g., `raw.filter()`
fir_coefs = mne.filter.create_filter(
    data=None,  # data is only used for sanity checking, not strictly needed
    sfreq=1000.,  # sfreq of your data in Hz
    l_freq=None,
    h_freq=40.,  # assuming a lowpass of 40 Hz
    method='fir',
    fir_window='hamming',
    fir_design='firwin',
    verbose=True)

# See the printed log for the transition bandwidth and filter length.
# Alternatively, get the filter length through:
filter_length = fir_coefs.shape[0]


I am working on the file "0.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
In response, Maess et al. (2016) :footcite:MaessEtAl2016a
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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
Now we have very sharp frequency suppression, but our filter rings for the
entire 10 seconds. So this naïve method is probably not a good way to build
our low-pass filter.
Fortunately, there are multiple established methods to design FIR filters
based on desired response characteristics. These include:
1. The Remez_ algorithm (:func:`scipy.signal.remez`, `MATLAB firpm`_)
2. Windowed FIR design (:func:`scipy.signal.firwin2`,
   :func:`scipy.signal.firwin`, and `MATLAB fir2`_)
3. Least squares designs (:func:`scipy.signal.firls`, `MATLAB firls`_)
4. Frequency-domain design (construct filter in Fourier
   domain and use an :func:`IFFT <numpy.fft.ifft>` to invert it)

Note

Remez and least squares designs have advantages when there are
          "do not care" regions in our frequency response. However, we want
          well controlled responses in all frequency regions.
          Frequency-domain construction is good when an arbitrary response
          is desired, but generally less clean (due to sampling issues) than
          a windowed approach for more straightforward filter applications.
          Since our filters (low-pass, high-pass, band-pass, band-stop)
          are fairly simple and we require precise control of all frequency
          regions, we will primarily use and explore windowed FIR design.

If we relax our frequency-domain filter requirements a little bit, we can
use these functions to construct a lowpass filter that instead has a
transition band, or a region between the pass frequency $f_p$
and stop frequency $f_s$, e.g.:
Can you write Python code for it?

trans_bandwidth = 10  # 10 Hz transition band
f_s = f_p + trans_bandwidth  # = 50 Hz

freq = [0., f_p, f_s, nyq]
gain = [1., 1., 0., 0.]
ax = plt.subplots(1, figsize=third_height)[1]
title = '%s Hz lowpass with a %s Hz transition' % (f_p, trans_bandwidth)
plot_ideal_filter(freq, gain, ax, title=title, flim=flim)


I am working on the file "0.23/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
Similarly, in a P300 paradigm reported by
Kappenman & Luck (2010) :footcite:KappenmanLuck2010,
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 the sample-dataset dataset,
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) :footcite:TannerEtAl2015
suggest using baseline correction to remove slow drifts in data. However,
Maess et al. (2016) :footcite:MaessEtAl2016
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) :footcite:TannerEtAl2016
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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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) :footcite:VanRullen2011,
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) :footcite:Rousselet2012.
Perhaps more revealing, it was noted in Widmann & Schröger (2012)
:footcite:WidmannSchroger2012 that the problematic low-pass filters from
VanRullen (2011) :footcite:VanRullen2011:

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) :footcite:AcunzoEtAl2012 to:
"... generate a systematic bias easily leading to misinterpretations of
   neural activity.”
In a related paper, Widmann et al. (2015) :footcite:WidmannEtAl2015
also came to suggest a 0.1 Hz highpass. More evidence followed in
Tanner et al. (2015) :footcite:TannerEtAl2015 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) :footcite:TannerEtAl2015:
"The simulated component is a single-cycle cosine wave with an amplitude
   of 5µV [sic],...
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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/6d98b103d247000f4433763dd76607c0/25_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.23/_downloads/709b65f447b790ec915e9d00176f0746/virtual_evoked.ipynb".
The first task is:
First, let's call remap gradiometers to magnometers, and plot
the original and remapped topomaps of the magnetometers.
Can you write Python code for it?

# go from grad + mag to mag and plot original mag
virt_evoked = evoked.as_type('mag')
evoked.plot_topomap(ch_type='mag', title='mag (original)', time_unit='s')

# plot interpolated grad + mag
virt_evoked.plot_topomap(ch_type='mag', time_unit='s',
                         title='mag (interpolated from mag + grad)')


I am working on the file "0.23/_downloads/709b65f447b790ec915e9d00176f0746/virtual_evoked.ipynb".
The first task is:
Now, we remap magnometers to gradiometers, and plot
the original and remapped topomaps of the gradiometers
Can you write Python code for it?

# go from grad + mag to grad and plot original grad
virt_evoked = evoked.as_type('grad')
evoked.plot_topomap(ch_type='grad', title='grad (original)', time_unit='s')

# plot interpolated grad + mag
virt_evoked.plot_topomap(ch_type='grad', time_unit='s',
                         title='grad (interpolated from mag + grad)')


I am working on the file "0.23/_downloads/70e603ce6ceb1fd2cb094ccee99a1920/resolution_metrics_eegmeg.ipynb".
The first task is:
Compute spatial resolution metrics to compare MEG with EEG+MEG
Compute peak localisation error and spatial deviation for the point-spread
functions of dSPM and MNE. Plot their distributions and difference of
distributions. This example mimics some results from :footcite:HaukEtAl2019,
namely Figure 3 (peak localisation error for PSFs, L2-MNE vs dSPM) and Figure 4
(spatial deviation for PSFs, L2-MNE vs dSPM). It shows that combining MEG with
EEG reduces the point-spread function and increases the spatial resolution of
source imaging, especially for deeper sources.
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.resolution_matrix import make_inverse_resolution_matrix
from mne.minimum_norm.spatial_resolution import resolution_metrics

print(__doc__)

data_path = sample.data_path()
subjects_dir = data_path + '/subjects/'
fname_fwd_emeg = 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 with EEG and MEG
forward_emeg = mne.read_forward_solution(fname_fwd_emeg)
# forward operator with fixed source orientations
forward_emeg = mne.convert_forward_solution(forward_emeg, surf_ori=True,
                                            force_fixed=True)

# create a forward solution with MEG only
forward_meg = mne.pick_types_forward(forward_emeg, meg=True, eeg=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 for MEG and EEGMEG
inv_emeg = mne.minimum_norm.make_inverse_operator(
    info=evoked.info, forward=forward_emeg, noise_cov=noise_cov, loose=0.,
    depth=None)

inv_meg = mne.minimum_norm.make_inverse_operator(
    info=evoked.info, forward=forward_meg, 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.23/_downloads/70e603ce6ceb1fd2cb094ccee99a1920/resolution_metrics_eegmeg.ipynb".
The first task is:
For MEG only:
Can you write Python code for it?

brain_ple_meg = ple_psf_meg.plot('sample', 'inflated', 'lh',
                                 subjects_dir=subjects_dir, figure=2,
                                 clim=dict(kind='value', lims=(0, 2, 4)))

brain_ple_meg.add_text(0.1, 0.9, 'PLE PSF MEG', 'title', font_size=16)


brain_sd_meg = sd_psf_meg.plot('sample', 'inflated', 'lh',
                               subjects_dir=subjects_dir, figure=5,
                               clim=dict(kind='value', lims=(0, 2, 4)))

brain_sd_meg.add_text(0.1, 0.9, 'SD PSF MEG', 'title', font_size=16)


I am working on the file "0.23/_downloads/70e603ce6ceb1fd2cb094ccee99a1920/resolution_metrics_eegmeg.ipynb".
The first task is:
MEG
Do the same for MEG:
Can you write Python code for it?

rm_meg = make_inverse_resolution_matrix(forward_meg, inv_meg,
                                        method='MNE', lambda2=lambda2)
ple_psf_meg = resolution_metrics(rm_meg, inv_meg['src'],
                                 function='psf', metric='peak_err')
sd_psf_meg = resolution_metrics(rm_meg, inv_meg['src'],
                                function='psf', metric='sd_ext')
del rm_meg


I am working on the file "0.23/_downloads/70e603ce6ceb1fd2cb094ccee99a1920/resolution_metrics_eegmeg.ipynb".
The first task is:
Subtract the two distributions and plot this difference:
Can you write Python code for it?

diff_sd = sd_psf_emeg - sd_psf_meg

brain_sd_diff = diff_sd.plot('sample', 'inflated', 'lh',
                             subjects_dir=subjects_dir, figure=6,
                             clim=dict(kind='value', pos_lims=(0., .5, 1.)),
                             smoothing_steps=20)

brain_sd_diff.add_text(0.1, 0.9, 'SD EMEG-MEG', 'title', font_size=16)


I am working on the file "0.23/_downloads/70e603ce6ceb1fd2cb094ccee99a1920/resolution_metrics_eegmeg.ipynb".
The first task is:
These plots show that with respect to peak localization error, adding EEG to
MEG does not bring much benefit. Next let's visualise spatial deviation (SD)
across the whole cortex for PSF:
Can you write Python code for it?

brain_sd_emeg = sd_psf_emeg.plot('sample', 'inflated', 'lh',
                                 subjects_dir=subjects_dir, figure=4,
                                 clim=dict(kind='value', lims=(0, 2, 4)))

brain_sd_emeg.add_text(0.1, 0.9, 'SD PSF EMEG', 'title', font_size=16)


I am working on the file "0.23/_downloads/70e603ce6ceb1fd2cb094ccee99a1920/resolution_metrics_eegmeg.ipynb".
The first task is:
Visualization
Look at peak localisation error (PLE) across the whole cortex for PSF:
Can you write Python code for it?

brain_ple_emeg = ple_psf_emeg.plot('sample', 'inflated', 'lh',
                                   subjects_dir=subjects_dir, figure=1,
                                   clim=dict(kind='value', lims=(0, 2, 4)))

brain_ple_emeg.add_text(0.1, 0.9, 'PLE PSF EMEG', 'title', font_size=16)


I am working on the file "0.23/_downloads/7119b87595b4873e173edd147fee099b/dics_source_power.ipynb".
The first task is:
Computing DICS spatial filters using the CSD that was computed on the entire
timecourse.
Can you write Python code for it?

fwd = mne.read_forward_solution(fname_fwd)
filters = make_dics(info, fwd, csd, noise_csd=csd_baseline,
                    pick_ori='max-power', reduce_rank=True, real_filter=True)
del fwd


I am working on the file "0.23/_downloads/7119b87595b4873e173edd147fee099b/dics_source_power.ipynb".
The first task is:
To compute the source power for a frequency band, rather than each frequency
separately, we average the CSD objects across frequencies.
Can you write Python code for it?

csd = csd.mean()
csd_baseline = csd_baseline.mean()
csd_ers = csd_ers.mean()


I am working on the file "0.23/_downloads/7119b87595b4873e173edd147fee099b/dics_source_power.ipynb".
The first task is:
Visualizing source power during ERS activity relative to the baseline power.
Can you write Python code for it?

stc = beta_source_power / baseline_source_power
message = 'DICS source power in the 12-30 Hz frequency band'
brain = stc.plot(hemi='both', views='axial', subjects_dir=subjects_dir,
                 subject=subject, time_label=message)


I am working on the file "0.23/_downloads/7119b87595b4873e173edd147fee099b/dics_source_power.ipynb".
The first task is:
We are interested in the beta band. Define a range of frequencies, using a
log scale, from 12 to 30 Hz.
Can you write Python code for it?

freqs = np.logspace(np.log10(12), np.log10(30), 9)