I am working on the file "0.24/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
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.24/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
Rejecting bad data spans and breaks
This tutorial covers:

manual marking of bad spans of data,
automated rejection of data spans based on signal amplitude, and
automated detection of breaks during an experiment.

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.24/_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.
Detecting and annotating breaks
Another useful function, albeit not related to artifact detection per se,
is mne.preprocessing.annotate_break: It will generate annotations for
segments of the data where no existing annotations (or, alternatively:
events) can be found. It can therefore be used to automatically detect and
mark breaks, e.g. between experimental blocks, when recording continued.
For the sake of this example, let's assume an experiment consisting of two
blocks, the first one stretching from 30 to 90, and the second from 120 to
180 seconds. We'll mark these blocks by annotations, and then use
mne.preprocessing.annotate_break to detect and annotate any breaks.

Note

We need to take ``raw.first_time`` into account, otherwise the
          onsets will be incorrect!

Can you write Python code for it?

onsets = [
    raw.first_time + 30,
    raw.first_time + 180
]
durations = [60, 60]
descriptions = ['block_1', 'block_2']

block_annots = mne.Annotations(onset=onsets,
                               duration=durations,
                               description=descriptions,
                               orig_time=raw.info['meas_date'])
raw.set_annotations(raw.annotations + block_annots)  # add to existing
raw.plot()


I am working on the file "0.24/_downloads/5bedf835c134d956a9b527dc8c5f488c/20_rejecting_bad_data.ipynb".
The first task is:
The values that are appropriate are dataset- and hardware-dependent, so some
trial-and-error may be necessary to find the correct balance between data
quality and loss of power due to too many dropped epochs. Here, we've set the
rejection criteria to be fairly stringent, for illustration purposes.
Two additional parameters, reject_tmin and reject_tmax, are used to
set the temporal window in which to calculate peak-to-peak amplitude for the
purposes of epoch rejection. These default to the same tmin and tmax
of the entire epoch. As one example, if you wanted to only apply the
rejection thresholds to the portion of the epoch that occurs before the
event marker around which the epoch is created, you could set
reject_tmax=0. A summary of the causes of rejected epochs can be
generated with the :meth:~mne.Epochs.plot_drop_log method:
Can you write Python code for it?

raw.set_annotations(blink_annot)  # restore the EOG annotations
epochs = mne.Epochs(raw, events, tmin=-0.2, tmax=0.5, reject_tmax=0,
                    reject=reject_criteria, flat=flat_criteria,
                    reject_by_annotation=False, preload=True)
epochs.plot_drop_log()


I am working on the file "0.24/_downloads/5f078eabe74f0448d3e1662c12313289/source_space_time_frequency.ipynb".
The first task is:
plot mean power
Can you write Python code for it?

plt.plot(stcs['alpha'].times, stcs['alpha'].data.mean(axis=0), label='Alpha')
plt.plot(stcs['beta'].times, stcs['beta'].data.mean(axis=0), label='Beta')
plt.xlabel('Time (ms)')
plt.ylabel('Power')
plt.legend()
plt.title('Mean source induced power')
plt.show()


I am working on the file "0.24/_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.24/_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.24/_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.24/_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.24/_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.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Aligning the T1 to ACPC
For intracranial electrophysiology recordings, the Brain Imaging Data
Structure (BIDS) standard requires that coordinates be aligned to the
anterior commissure and posterior commissure (ACPC-aligned). Therefore, it is
recommended that you do this alignment before finding the positions of the
channels in your recording. Doing this will make the "mri" (aka surface RAS)
coordinate frame an ACPC coordinate frame. This can be done using
Freesurfer's freeview:
.. code-block:: bash
$ freeview $MISC_PATH/seeg/sample_seeg_T1.mgz

And then interact with the graphical user interface:
First, it is recommended to change the cursor style to long, this can be done
through the menu options like so:
``Freeview -> Preferences -> General -> Cursor style -> Long``

Then, the image needs to be aligned to ACPC to look like the image below.
This can be done by pulling up the transform popup from the menu like so:
``Tools -> Transform Volume``

Note

Be sure to set the text entry box labeled RAS (not TkReg RAS) to
    ``0 0 0`` before beginning the transform.

Then translate the image until the crosshairs meet on the AC and
run through the PC as shown in the plot. The eyes should be in
the ACPC plane and the image should be rotated until they are symmetrical,
and the crosshairs should transect the midline of the brain.
Be sure to use both the rotate and the translate menus and save the volume
after you're finished using Save Volume As in the transform popup
:footcite:HamiltonEtAl2017.
Can you write Python code for it?

T1 = nib.load(op.join(misc_path, 'seeg', 'sample_seeg', 'mri', 'T1.mgz'))
viewer = T1.orthoview()
viewer.set_position(0, 9.9, 5.8)
viewer.figs[0].axes[0].annotate(
    'PC', (107, 108), xytext=(10, 75), color='white',
    horizontalalignment='center',
    arrowprops=dict(facecolor='white', lw=0.5, width=2, headwidth=5))
viewer.figs[0].axes[0].annotate(
    'AC', (137, 108), xytext=(246, 75), color='white',
    horizontalalignment='center',
    arrowprops=dict(facecolor='white', lw=0.5, width=2, headwidth=5))


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Finally, we'll apply the registrations to the electrode contact coordinates.
The brain image is warped to the template but the goal was to warp the
positions of the electrode contacts. To do that, we'll make an image that is
a lookup table of the electrode contacts. In this image, the background will
be 0 s all the bright voxels near the location of the first contact will
be 1 s, the second 2 s and so on. This image can then be warped by
the SDR transform. We can finally recover a position by averaging the
positions of all the voxels that had the contact's lookup number in
the warped image.
Can you write Python code for it?

# first we need our montage but it needs to be converted to "mri" coordinates
# using our ``subj_trans``
montage = raw.get_montage()
montage.apply_trans(subj_trans)

montage_warped, elec_image, warped_elec_image = mne.warp_montage_volume(
    montage, CT_aligned, reg_affine, sdr_morph, thresh=0.25,
    subject_from='sample_seeg', subjects_dir_from=op.join(misc_path, 'seeg'),
    subject_to='fsaverage', subjects_dir_to=subjects_dir)

fig, axes = plt.subplots(2, 1, figsize=(8, 8))
nilearn.plotting.plot_glass_brain(elec_image, axes=axes[0], cmap='Dark2')
fig.text(0.1, 0.65, 'Subject T1', rotation='vertical')
nilearn.plotting.plot_glass_brain(warped_elec_image, axes=axes[1],
                                  cmap='Dark2')
fig.text(0.1, 0.25, 'fsaverage', rotation='vertical')
fig.suptitle('Electrodes warped to fsaverage')

del CT_aligned


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Let's plot the electrode contact locations on the subject's brain.
MNE stores digitization montages in a coordinate frame called "head"
defined by fiducial points (origin is halfway between the LPA and RPA
see tut-source-alignment). For sEEG, it is convenient to get an
estimate of the location of the fiducial points for the subject
using the Talairach transform (see :func:mne.coreg.get_mni_fiducials)
to use to define the coordinate frame so that we don't have to manually
identify their location. The estimated head->mri trans was used
when the electrode contacts were localized so we need to use it again here.
Can you write Python code for it?

# plot the alignment
brain = mne.viz.Brain('sample_seeg', subjects_dir=op.join(misc_path, 'seeg'),
                      **brain_kwargs)
brain.add_sensors(raw.info, trans=subj_trans)
brain.show_view(**view_kwargs)


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Locating Intracranial Electrode Contacts
Analysis of intracranial electrophysiology recordings typically involves
finding the position of each contact relative to brain structures. In a
typical setup, the brain and the electrode locations will be in two places
and will have to be aligned; the brain is best visualized by a
pre-implantation magnetic resonance (MR) image whereas the electrode contact
locations are best visualized in a post-implantation computed tomography (CT)
image. The CT image has greater intensity than the background at each of the
electrode contacts and for the skull. Using the skull, the CT can be aligned
to MR-space. This accomplishes our goal of obtaining contact locations in
MR-space (which is where the brain structures are best determined using the
tut-freesurfer-reconstruction). Contact locations in MR-space can also
be warped to a template space such as fsaverage for group comparisons.
Can you write Python code for it?

# Authors: Alex Rockhill <aprockhill@mailbox.org>
#          Eric Larson <larson.eric.d@gmail.com>
#
# License: BSD-3-Clause

import os.path as op

import numpy as np
import matplotlib.pyplot as plt

import nibabel as nib
import nilearn.plotting
from dipy.align import resample

import mne
from mne.datasets import fetch_fsaverage

# paths to mne datasets - sample sEEG and FreeSurfer's fsaverage subject
# which is in MNI space
misc_path = mne.datasets.misc.data_path()
sample_path = mne.datasets.sample.data_path()
subjects_dir = op.join(sample_path, 'subjects')

# use mne-python's fsaverage data
fetch_fsaverage(subjects_dir=subjects_dir, verbose=True)  # downloads if needed


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Marking the Location of Each Electrode Contact
Now, the CT and the MR are in the same space, so when you are looking at a
point in CT space, it is the same point in MR space. So now everything is
ready to determine the location of each electrode contact in the
individual subject's anatomical space (T1-space). To do this, we can use the
MNE intracranial electrode location graphical user interface.
.. note: The most useful coordinate frame for intracranial electrodes is
         generally the surface RAS coordinate frame because that is
         the coordinate frame that all the surface and image files that
         Freesurfer outputs are in, see tut-freesurfer-mne. These are
         useful for finding the brain structures nearby each contact and
         plotting the results.
To operate the GUI:

Click in each image to navigate to each electrode contact
Select the contact name in the right panel
Press the "Mark" button or the "m" key to associate that
    position with that contact
Repeat until each contact is marked, they will both appear as circles
    in the plots and be colored in the sidebar when marked

.. note:: The channel locations are saved to the raw object every time
            a location is marked or removed so there is no "Save" button.
.. note:: Using the scroll or +/- arrow keys you can zoom in and out,
            and the up/down, left/right and page up/page down keys allow
            you to move one slice in any direction. This information is
            available in the help menu, accessible by pressing the "h" key.
.. note:: If "Snap to Center" is on, this will use the radius so be
            sure to set it properly.
Can you write Python code for it?

# load electrophysiology data to find channel locations for
# (the channels are already located in the example)
raw = mne.io.read_raw(op.join(misc_path, 'seeg', 'sample_seeg_ieeg.fif'))

gui = mne.gui.locate_ieeg(raw.info, subj_trans, CT_aligned,
                          subject='sample_seeg',
                          subjects_dir=op.join(misc_path, 'seeg'))
# The `raw` object is modified to contain the channel locations
# after closing the GUI and can now be saved
gui.close()  # close when done


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Now we need to align our CT image to the T1 image.
We want this to be a rigid transformation (just rotation + translation),
so we don't do a full affine registration (that includes shear) here.
This takes a while (~10 minutes) to execute so we skip actually running it
here::
reg_affine, _ = mne.transforms.compute_volume_registration(
        CT_orig, T1, pipeline='rigids')
And instead we just hard-code the resulting 4x4 matrix:
Can you write Python code for it?


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Now we need to estimate the "head" coordinate transform.
MNE stores digitization montages in a coordinate frame called "head"
defined by fiducial points (origin is halfway between the LPA and RPA
see tut-source-alignment). For sEEG, it is convenient to get an
estimate of the location of the fiducial points for the subject
using the Talairach transform (see :func:mne.coreg.get_mni_fiducials)
to use to define the coordinate frame so that we don't have to manually
identify their location.
Can you write Python code for it?

# estimate head->mri transform
subj_trans = mne.coreg.estimate_head_mri_t(
    'sample_seeg', op.join(misc_path, 'seeg'))


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
Now, we'll register the affine of the subject's brain to the template brain.
This aligns the two brains, preparing the subject's brain to be warped
to the template.

Warning

Here we use custom ``zooms`` just for speed, in general we
             recommend using ``zooms=None`` (default) for highest accuracy!

Can you write Python code for it?

zooms = dict(translation=4, rigid=4, affine=6, sdr=6)
reg_affine, sdr_morph = mne.transforms.compute_volume_registration(
    subject_brain, template_brain, zooms=zooms, verbose=True)
subject_brain_sdr = mne.transforms.apply_volume_registration(
    subject_brain, template_brain, reg_affine, sdr_morph)

# apply the transform to the subject brain to plot it
plot_overlay(template_brain, subject_brain_sdr,
             'Alignment with fsaverage after SDR Registration')

del subject_brain, template_brain


I am working on the file "0.24/_downloads/6608d2f46fa33fc4dfd4a7f07bd9bdc9/10_ieeg_localize.ipynb".
The first task is:
We can now see how the CT image looks properly aligned to the T1 image.

Note

The hyperintense skull is actually aligned to the hypointensity between
    the brain and the scalp. The brighter area surrounding the skull in the
    MR is actually subcutaneous fat.

Can you write Python code for it?

# make low intensity parts of the CT transparent for easier visualization
CT_data = CT_aligned.get_fdata().copy()
CT_data[CT_data < np.quantile(CT_data, 0.95)] = np.nan
T1_data = np.asarray(T1.dataobj)

fig, axes = plt.subplots(1, 3, figsize=(12, 6))
for ax in axes:
    ax.axis('off')
axes[0].imshow(T1_data[T1.shape[0] // 2], cmap='gray')
axes[0].set_title('MR')
axes[1].imshow(np.asarray(CT_aligned.dataobj)[CT_aligned.shape[0] // 2],
               cmap='gray')
axes[1].set_title('CT')
axes[2].imshow(T1_data[T1.shape[0] // 2], cmap='gray')
axes[2].imshow(CT_data[CT_aligned.shape[0] // 2], cmap='gist_heat', alpha=0.5)
for ax in (axes[0], axes[2]):
    ax.annotate('Subcutaneous fat', (110, 52), xytext=(100, 30),
                color='white', horizontalalignment='center',
                arrowprops=dict(facecolor='white'))
for ax in axes:
    ax.annotate('Skull (dark in MR, bright in CT)', (40, 175),
                xytext=(120, 246), horizontalalignment='center',
                color='white', arrowprops=dict(facecolor='white'))
axes[2].set_title('CT aligned to MR')
fig.tight_layout()
del CT_data, T1


I am working on the file "0.24/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
:meth:~mne.io.Raw.notch_filter also has parameters to control the notch
width, transition bandwidth and other aspects of the filter. See the
docstring for details.
It's also possible to try to use a spectrum fitting routine to notch filter.
In principle it can automatically detect the frequencies to notch, but our
implementation generally does not do so reliably, so we specify the
frequencies to remove instead, and it does a good job of removing the
line noise at those frequencies:
Can you write Python code for it?

raw_notch_fit = raw.copy().notch_filter(
    freqs=freqs, picks=meg_picks, method='spectrum_fit', filter_length='10s')
for title, data in zip(['Un', 'spectrum_fit '], [raw, raw_notch_fit]):
    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.24/_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?

raw.plot(duration=60, proj=False, n_channels=len(raw.ch_names),
         remove_dc=False)


I am working on the file "0.24/_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.24/_downloads/686e03eb7a01e30e026e3dd11e64df18/30_filtering_resampling.ipynb".
The first task is:
Filtering and resampling data
This tutorial covers filtering and resampling, and gives examples of how
filtering can be used for artifact repair.
We begin as always by importing the necessary Python modules and loading some
example data <sample-dataset>. We'll also crop the data to 60 seconds
(to save memory on the documentation server):
Can you write Python code for it?

import os
import numpy as np
import matplotlib.pyplot as plt
import mne

sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis_raw.fif')
raw = mne.io.read_raw_fif(sample_data_raw_file)
# use just 60 seconds of data and mag channels, to save memory
raw.crop(0, 60).pick_types(meg='mag', stim=True).load_data()


I am working on the file "0.24/_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.24/_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.24/_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.24/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
It's a good idea to spatially smooth the data, and for visualization
purposes, let's morph these to fsaverage, which is a grade 5 ICO source space
with vertices 0:10242 for each hemisphere. Usually you'd have to morph
each subject's data separately, but here since all estimates are on
'sample' we can use one morph matrix for all the heavy lifting.
Can you write Python code for it?

# Read the source space we are morphing to (just left hemisphere)
src = mne.read_source_spaces(src_fname)
fsave_vertices = [src[0]['vertno'], []]
morph_mat = mne.compute_source_morph(
    src=inverse_operator['src'], subject_to='fsaverage',
    spacing=fsave_vertices, subjects_dir=subjects_dir, smooth=20).morph_mat
morph_mat = morph_mat[:, :n_vertices_sample]  # just left hemi from src
n_vertices_fsave = morph_mat.shape[0]

#    We have to change the shape for the dot() to work properly
X = X.reshape(n_vertices_sample, n_times * n_subjects * 4)
print('Morphing data.')
X = morph_mat.dot(X)  # morph_mat is a sparse matrix
X = X.reshape(n_vertices_fsave, n_times, n_subjects, 4)


I am working on the file "0.24/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Now we need to prepare the group matrix for the ANOVA statistic. To make the
clustering function work correctly with the ANOVA function X needs to be a
list of multi-dimensional arrays (one per condition) of shape: samples
(subjects) x time x space.
First we permute dimensions, then split the array into a list of conditions
and discard the empty dimension resulting from the split using numpy squeeze.
Can you write Python code for it?

X = np.transpose(X, [2, 1, 0, 3])  #
X = [np.squeeze(x) for x in np.split(X, 4, axis=-1)]


I am working on the file "0.24/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.ipynb".
The first task is:
Prepare function for arbitrary contrast
As our ANOVA function is a multi-purpose tool we need to apply a few
modifications to integrate it with the clustering function. This
includes reshaping data, setting default arguments and processing
the return values. For this reason we'll write a tiny dummy function.
We will tell the ANOVA how to interpret the data matrix in terms of
factors. This is done via the factor levels argument which is a list
of the number factor levels for each factor.
Can you write Python code for it?


I am working on the file "0.24/_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.24/_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.24/_downloads/6965b7b1a563cc32b2b5388d95203d43/60_cluster_rmANOVA_spatiotemporal.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'
subjects_dir = data_path + '/subjects'
src_fname = subjects_dir + '/fsaverage/bem/fsaverage-ico-5-src.fif'

tmin = -0.2
tmax = 0.3  # Use a lower tmax to reduce multiple comparisons

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


I am working on the file "0.24/_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 = 6
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.24/_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(30).crop(0., None)
    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.24/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
Accepting a shallower roll-off of the filter in the frequency domain makes
our time-domain response potentially much better. We end up with a more
gradual slope through the transition region, but a much cleaner time
domain signal. Here again for the 1 s filter:
Can you write Python code for it?

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


I am working on the file "0.24/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
And now an example of a minimum-phase filter:
Can you write Python code for it?

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


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

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

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

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


I am working on the file "0.24/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
IIR filters
MNE-Python also offers IIR filtering functionality that is based on the
methods from :mod:scipy.signal. Specifically, we use the general-purpose
functions :func:scipy.signal.iirfilter and :func:scipy.signal.iirdesign,
which provide unified interfaces to IIR filter design.
Designing IIR filters
Let's continue with our design of a 40 Hz low-pass filter and look at
some trade-offs of different IIR filters.
Often the default IIR filter is a Butterworth filter_, which is designed
to have a maximally flat pass-band. Let's look at a few filter orders,
i.e., a few different number of coefficients used and therefore steepness
of the filter:

Note

Notice that the group delay (which is related to the phase) of
          the IIR filters below are not constant. In the FIR case, we can
          design so-called linear-phase filters that have a constant group
          delay, and thus compensate for the delay (making the filter
          non-causal) if necessary. This cannot be done with IIR filters, as
          they have a non-linear phase (non-constant group delay). As the
          filter order increases, the phase distortion near and in the
          transition band worsens. However, if non-causal (forward-backward)
          filtering can be used, e.g. with :func:`scipy.signal.filtfilt`,
          these phase issues can theoretically be mitigated.

Can you write Python code for it?

sos = signal.iirfilter(2, f_p / nyq, btype='low', ftype='butter', output='sos')
plot_filter(dict(sos=sos), sfreq, freq, gain, 'Butterworth order=2', flim=flim,
            compensate=True)
x_shallow = signal.sosfiltfilt(sos, x)
del sos


I am working on the file "0.24/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
If we can live with even more ripple, we can get it slightly steeper,
but the impulse response begins to ring substantially longer (note the
different x-axis scale):
Can you write Python code for it?

iir_params['rp'] = 6.
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=6 dB', flim=flim,
            compensate=True)


I am working on the file "0.24/_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.24/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
Let's also filter with the MNE-Python 0.13 default, which is a
long-duration, steep cutoff FIR that gets applied twice:
Can you write Python code for it?

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


I am working on the file "0.24/_downloads/6d98b103d247000f4433763dd76607c0/25_background_filtering.ipynb".
The first task is:
Let's make the stop-band tighter still with a longer filter (10 s),
with a resulting larger x-axis:
Can you write Python code for it?

n = int(round(10. * 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 (10.0 s)', flim=flim, compensate=True)


I am working on the file "0.24/_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.24/_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.24/_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.24/_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.24/_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.24/_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.24/_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.24/_downloads/709b65f447b790ec915e9d00176f0746/virtual_evoked.ipynb".
The first task is:
Remap MEG channel types
In this example, MEG data are remapped from one channel type to another.
This is useful to:
- visualize combined magnetometers and gradiometers as magnetometers
  or gradiometers.
- run statistics from both magnetometers and gradiometers while
  working with a single type of channels.
Can you write Python code for it?

# Author: Mainak Jas <mainak.jas@telecom-paristech.fr>

# License: BSD-3-Clause

import mne
from mne.datasets import sample

print(__doc__)

# read the evoked
data_path = sample.data_path()
fname = data_path + '/MEG/sample/sample_audvis-ave.fif'
evoked = mne.read_evokeds(fname, condition='Left Auditory', baseline=(None, 0))


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

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)


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)


I am working on the file "0.24/_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.24/_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_ple = ple_psf_emeg - ple_psf_meg

brain_ple_diff = diff_ple.plot('sample', 'inflated', 'lh',
                               subjects_dir=subjects_dir, figure=3,
                               clim=dict(kind='value', pos_lims=(0., .5, 1.)),
                               smoothing_steps=20)

brain_ple_diff.add_text(0.1, 0.9, 'PLE EMEG-MEG', 'title', font_size=16)


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.24/_downloads/72bb0e260a352fd7c21fee1dd2f83d79/decoding_spoc_CMC.ipynb".
The first task is:
Continuous Target Decoding with SPoC
Source Power Comodulation (SPoC) :footcite:DahneEtAl2014 allows to identify
the composition of
orthogonal spatial filters that maximally correlate with a continuous target.
SPoC can be seen as an extension of the CSP for continuous variables.
Here, SPoC is applied to decode the (continuous) fluctuation of an
electromyogram from MEG beta activity using data from
Cortico-Muscular Coherence example of FieldTrip
<http://www.fieldtriptoolbox.org/tutorial/coherence>_
Can you write Python code for it?

# Author: Alexandre Barachant <alexandre.barachant@gmail.com>
#         Jean-Remi King <jeanremi.king@gmail.com>
#
# License: BSD-3-Clause

import matplotlib.pyplot as plt

import mne
from mne import Epochs
from mne.decoding import SPoC
from mne.datasets.fieldtrip_cmc import data_path

from sklearn.pipeline import make_pipeline
from sklearn.linear_model import Ridge
from sklearn.model_selection import KFold, cross_val_predict

# Define parameters
fname = data_path() + '/SubjectCMC.ds'
raw = mne.io.read_raw_ctf(fname)
raw.crop(50., 200.)  # crop for memory purposes

# Filter muscular activity to only keep high frequencies
emg = raw.copy().pick_channels(['EMGlft']).load_data()
emg.filter(20., None)

# Filter MEG data to focus on beta band
raw.pick_types(meg=True, ref_meg=True, eeg=False, eog=False).load_data()
raw.filter(15., 30.)

# Build epochs as sliding windows over the continuous raw file
events = mne.make_fixed_length_events(raw, id=1, duration=0.75)

# Epoch length is 1.5 second
meg_epochs = Epochs(raw, events, tmin=0., tmax=1.5, baseline=None,
                    detrend=1, decim=12)
emg_epochs = Epochs(emg, events, tmin=0., tmax=1.5, baseline=None)

# Prepare classification
X = meg_epochs.get_data()
y = emg_epochs.get_data().var(axis=2)[:, 0]  # target is EMG power

# Classification pipeline with SPoC spatial filtering and Ridge Regression
spoc = SPoC(n_components=2, log=True, reg='oas', rank='full')
clf = make_pipeline(spoc, Ridge())
# Define a two fold cross-validation
cv = KFold(n_splits=2, shuffle=False)

# Run cross validaton
y_preds = cross_val_predict(clf, X, y, cv=cv)

# Plot the True EMG power and the EMG power predicted from MEG data
fig, ax = plt.subplots(1, 1, figsize=[10, 4])
times = raw.times[meg_epochs.events[:, 0] - raw.first_samp]
ax.plot(times, y_preds, color='b', label='Predicted EMG')
ax.plot(times, y, color='r', label='True EMG')
ax.set_xlabel('Time (s)')
ax.set_ylabel('EMG Power')
ax.set_title('SPoC MEG Predictions')
plt.legend()
mne.viz.tight_layout()
plt.show()


I am working on the file "0.24/_downloads/72bb0e260a352fd7c21fee1dd2f83d79/decoding_spoc_CMC.ipynb".
The first task is:
Plot the contributions to the detected components (i.e., the forward model)
Can you write Python code for it?


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
And we also view the HbR activity for the two conditions.
Can you write Python code for it?

epochs['Tapping/Left'].average(picks='hbr').plot_topomap(
    times=times, **topomap_args)
epochs['Tapping/Right'].average(picks='hbr').plot_topomap(
    times=times, **topomap_args)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
And we can plot the comparison at a single time point for two conditions.
Can you write Python code for it?

fig, axes = plt.subplots(nrows=2, ncols=4, figsize=(9, 5),
                         gridspec_kw=dict(width_ratios=[1, 1, 1, 0.1]))
vmin, vmax, ts = -8, 8, 9.0

evoked_left = epochs['Tapping/Left'].average()
evoked_right = epochs['Tapping/Right'].average()

evoked_left.plot_topomap(ch_type='hbo', times=ts, axes=axes[0, 0],
                         vmin=vmin, vmax=vmax, colorbar=False,
                         **topomap_args)
evoked_left.plot_topomap(ch_type='hbr', times=ts, axes=axes[1, 0],
                         vmin=vmin, vmax=vmax, colorbar=False,
                         **topomap_args)
evoked_right.plot_topomap(ch_type='hbo', times=ts, axes=axes[0, 1],
                          vmin=vmin, vmax=vmax, colorbar=False,
                          **topomap_args)
evoked_right.plot_topomap(ch_type='hbr', times=ts, axes=axes[1, 1],
                          vmin=vmin, vmax=vmax, colorbar=False,
                          **topomap_args)

evoked_diff = mne.combine_evoked([evoked_left, evoked_right], weights=[1, -1])

evoked_diff.plot_topomap(ch_type='hbo', times=ts, axes=axes[0, 2:],
                         vmin=vmin, vmax=vmax, colorbar=True,
                         **topomap_args)
evoked_diff.plot_topomap(ch_type='hbr', times=ts, axes=axes[1, 2:],
                         vmin=vmin, vmax=vmax, colorbar=True,
                         **topomap_args)

for column, condition in enumerate(
        ['Tapping Left', 'Tapping Right', 'Left-Right']):
    for row, chroma in enumerate(['HbO', 'HbR']):
        axes[row, column].set_title('{}: {}'.format(chroma, condition))
fig.tight_layout()


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Compare tapping of left and right hands
Finally we generate topo maps for the left and right conditions to view
the location of activity. First we visualise the HbO activity.
Can you write Python code for it?

times = np.arange(4.0, 11.0, 1.0)
epochs['Tapping/Left'].average(picks='hbo').plot_topomap(
    times=times, **topomap_args)
epochs['Tapping/Right'].average(picks='hbo').plot_topomap(
    times=times, **topomap_args)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Converting from raw intensity to optical density
The raw intensity values are then converted to optical density.
Can you write Python code for it?

raw_od = mne.preprocessing.nirs.optical_density(raw_intensity)
raw_od.plot(n_channels=len(raw_od.ch_names),
            duration=500, show_scrollbars=False)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Evaluating the quality of the data
At this stage we can quantify the quality of the coupling
between the scalp and the optodes using the scalp coupling index. This
method looks for the presence of a prominent synchronous signal in the
frequency range of cardiac signals across both photodetected signals.
In this example the data is clean and the coupling is good for all
channels, so we will not mark any channels as bad based on the scalp
coupling index.
Can you write Python code for it?

sci = mne.preprocessing.nirs.scalp_coupling_index(raw_od)
fig, ax = plt.subplots()
ax.hist(sci)
ax.set(xlabel='Scalp Coupling Index', ylabel='Count', xlim=[0, 1])


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Extract epochs
Now that the signal has been converted to relative haemoglobin concentration,
and the unwanted heart rate component has been removed, we can extract epochs
related to each of the experimental conditions.
First we extract the events of interest and visualise them to ensure they are
correct.
Can you write Python code for it?

events, event_dict = mne.events_from_annotations(raw_haemo)
fig = mne.viz.plot_events(events, event_id=event_dict,
                          sfreq=raw_haemo.info['sfreq'])
fig.subplots_adjust(right=0.7)  # make room for the legend


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Next we define the range of our epochs, the rejection criteria,
baseline correction, and extract the epochs. We visualise the log of which
epochs were dropped.
Can you write Python code for it?

reject_criteria = dict(hbo=80e-6)
tmin, tmax = -5, 15

epochs = mne.Epochs(raw_haemo, events, event_id=event_dict,
                    tmin=tmin, tmax=tmax,
                    reject=reject_criteria, reject_by_annotation=True,
                    proj=True, baseline=(None, 0), preload=True,
                    detrend=None, verbose=True)
epochs.plot_drop_log()


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Plot standard fNIRS response image
Next we generate the most common visualisation of fNIRS data: plotting
both the HbO and HbR on the same figure to illustrate the relation between
the two signals.
Can you write Python code for it?

evoked_dict = {'Tapping/HbO': epochs['Tapping'].average(picks='hbo'),
               'Tapping/HbR': epochs['Tapping'].average(picks='hbr'),
               'Control/HbO': epochs['Control'].average(picks='hbo'),
               'Control/HbR': epochs['Control'].average(picks='hbr')}

# Rename channels until the encoding of frequency in ch_name is fixed
for condition in evoked_dict:
    evoked_dict[condition].rename_channels(lambda x: x[:-4])

color_dict = dict(HbO='#AA3377', HbR='b')
styles_dict = dict(Control=dict(linestyle='dashed'))

mne.viz.plot_compare_evokeds(evoked_dict, combine="mean", ci=0.95,
                             colors=color_dict, styles=styles_dict)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Preprocessing functional near-infrared spectroscopy (fNIRS) data
This tutorial covers how to convert functional near-infrared spectroscopy
(fNIRS) data from raw measurements to relative oxyhaemoglobin (HbO) and
deoxyhaemoglobin (HbR) concentration, view the average waveform, and
topographic representation of the response.
Here we will work with the fNIRS motor data <fnirs-motor-dataset>.
Can you write Python code for it?

import os.path as op
import numpy as np
import matplotlib.pyplot as plt
from itertools import compress

import mne

fnirs_data_folder = mne.datasets.fnirs_motor.data_path()
fnirs_cw_amplitude_dir = op.join(fnirs_data_folder, 'Participant-1')
raw_intensity = mne.io.read_raw_nirx(fnirs_cw_amplitude_dir, verbose=True)
raw_intensity.load_data()


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Providing more meaningful annotation information
First, we attribute more meaningful names to the trigger codes which are
stored as annotations. Second, we include information about the duration of
each stimulus, which was 5 seconds for all conditions in this experiment.
Third, we remove the trigger code 15, which signaled the start and end
of the experiment and is not relevant to our analysis.
Can you write Python code for it?

raw_intensity.annotations.set_durations(5)
raw_intensity.annotations.rename({'1.0': 'Control',
                                  '2.0': 'Tapping/Left',
                                  '3.0': 'Tapping/Right'})
unwanted = np.nonzero(raw_intensity.annotations.description == '15.0')
raw_intensity.annotations.delete(unwanted)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Removing heart rate from signal
The haemodynamic response has frequency content predominantly below 0.5 Hz.
An increase in activity around 1 Hz can be seen in the data that is due to
the person's heart beat and is unwanted. So we use a low pass filter to
remove this. A high pass filter is also included to remove slow drifts
in the data.
Can you write Python code for it?

fig = raw_haemo.plot_psd(average=True)
fig.suptitle('Before filtering', weight='bold', size='x-large')
fig.subplots_adjust(top=0.88)
raw_haemo = raw_haemo.filter(0.05, 0.7, h_trans_bandwidth=0.2,
                             l_trans_bandwidth=0.02)
fig = raw_haemo.plot_psd(average=True)
fig.suptitle('After filtering', weight='bold', size='x-large')
fig.subplots_adjust(top=0.88)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
View consistency of responses across channels
Similarly we can view how consistent the response is across the optode
pairs that we selected. All the channels in this data are located over the
motor cortex, and all channels show a similar pattern in the data.
Can you write Python code for it?

fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(15, 6))
clims = dict(hbo=[-20, 20], hbr=[-20, 20])
epochs['Control'].average().plot_image(axes=axes[:, 0], clim=clims)
epochs['Tapping'].average().plot_image(axes=axes[:, 1], clim=clims)
for column, condition in enumerate(['Control', 'Tapping']):
    for ax in axes[:, column]:
        ax.set_title('{}: {}'.format(condition, ax.get_title()))


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
View consistency of responses across trials
Now we can view the haemodynamic response for our tapping condition.
We visualise the response for both the oxy- and deoxyhaemoglobin, and
observe the expected peak in HbO at around 6 seconds consistently across
trials, and the consistent dip in HbR that is slightly delayed relative to
the HbO peak.
Can you write Python code for it?

epochs['Tapping'].plot_image(combine='mean', vmin=-30, vmax=30,
                             ts_args=dict(ylim=dict(hbo=[-15, 15],
                                                    hbr=[-15, 15])))


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
View topographic representation of activity
Next we view how the topographic activity changes throughout the response.
Can you write Python code for it?

times = np.arange(-3.5, 13.2, 3.0)
topomap_args = dict(extrapolate='local')
epochs['Tapping'].average(picks='hbo').plot_joint(
    times=times, topomap_args=topomap_args)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
Viewing location of sensors over brain surface
Here we validate that the location of sources-detector pairs and channels
are in the expected locations. Source-detector pairs are shown as lines
between the optodes, channels (the mid point of source-detector pairs) are
optionally shown as orange dots. Source are optionally shown as red dots and
detectors as black.
Can you write Python code for it?

subjects_dir = op.join(mne.datasets.sample.data_path(), 'subjects')

brain = mne.viz.Brain(
    'fsaverage', subjects_dir=subjects_dir, background='w', cortex='0.5')
brain.add_sensors(
    raw_intensity.info, trans='fsaverage',
    fnirs=['channels', 'pairs', 'sources', 'detectors'])
brain.show_view(azimuth=20, elevation=60, distance=400)


I am working on the file "0.24/_downloads/758680cba517820dcb0b486577bea58f/70_fnirs_processing.ipynb".
The first task is:
We can also view the epoched data for the control condition and observe
that it does not show the expected morphology.
Can you write Python code for it?

epochs['Control'].plot_image(combine='mean', vmin=-30, vmax=30,
                             ts_args=dict(ylim=dict(hbo=[-15, 15],
                                                    hbr=[-15, 15])))


I am working on the file "0.24/_downloads/772492bca9aff751a357f5e3e0163e67/50_cluster_between_time_freq.ipynb".
The first task is:
Compute statistic
Can you write Python code for it?

threshold = 6.0
T_obs, clusters, cluster_p_values, H0 = \
    permutation_cluster_test([epochs_power_1, epochs_power_2], out_type='mask',
                             n_permutations=100, threshold=threshold, tail=0)


I am working on the file "0.24/_downloads/772492bca9aff751a357f5e3e0163e67/50_cluster_between_time_freq.ipynb".
The first task is:
Factor to downsample the temporal dimension of the TFR computed by
tfr_morlet. Decimation occurs after frequency decomposition and can
be used to reduce memory usage (and possibly comptuational time of downstream
operations such as nonparametric statistics) if you don't need high
spectrotemporal resolution.
Can you write Python code for it?

decim = 2
freqs = np.arange(7, 30, 3)  # define frequencies of interest
n_cycles = 1.5

tfr_epochs_1 = tfr_morlet(epochs_condition_1, freqs,
                          n_cycles=n_cycles, decim=decim,
                          return_itc=False, average=False)

tfr_epochs_2 = tfr_morlet(epochs_condition_2, freqs,
                          n_cycles=n_cycles, decim=decim,
                          return_itc=False, average=False)

tfr_epochs_1.apply_baseline(mode='ratio', baseline=(None, 0))
tfr_epochs_2.apply_baseline(mode='ratio', baseline=(None, 0))

epochs_power_1 = tfr_epochs_1.data[:, 0, :, :]  # only 1 channel as 3D matrix
epochs_power_2 = tfr_epochs_2.data[:, 0, :, :]  # only 1 channel as 3D matrix


I am working on the file "0.24/_downloads/772492bca9aff751a357f5e3e0163e67/50_cluster_between_time_freq.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'
event_fname = data_path + '/MEG/sample/sample_audvis_raw-eve.fif'
tmin, tmax = -0.2, 0.5

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

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

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

ch_name = 'MEG 1332'  # restrict example to one channel

# Load condition 1
reject = dict(grad=4000e-13, eog=150e-6)
event_id = 1
epochs_condition_1 = mne.Epochs(raw, events, event_id, tmin, tmax,
                                picks=picks, baseline=(None, 0),
                                reject=reject, preload=True)
epochs_condition_1.pick_channels([ch_name])

# Load condition 2
event_id = 2
epochs_condition_2 = mne.Epochs(raw, events, event_id, tmin, tmax,
                                picks=picks, baseline=(None, 0),
                                reject=reject, preload=True)
epochs_condition_2.pick_channels([ch_name])


I am working on the file "0.24/_downloads/78ad76ea5b03c29b4b851b8b64f74b68/linear_model_patterns.ipynb".
The first task is:
Decoding in sensor space using a LogisticRegression classifier
Can you write Python code for it?

clf = LogisticRegression(solver='lbfgs')
scaler = StandardScaler()

# create a linear model with LogisticRegression
model = LinearModel(clf)

# fit the classifier on MEG data
X = scaler.fit_transform(meg_data)
model.fit(X, labels)

# Extract and plot spatial filters and spatial patterns
for name, coef in (('patterns', model.patterns_), ('filters', model.filters_)):
    # We fitted the linear model onto Z-scored data. To make the filters
    # interpretable, we must reverse this normalization step
    coef = scaler.inverse_transform([coef])[0]

    # The data was vectorized to fit a single model across all time points and
    # all channels. We thus reshape it:
    coef = coef.reshape(len(meg_epochs.ch_names), -1)

    # Plot
    evoked = EvokedArray(coef, meg_epochs.info, tmin=epochs.tmin)
    evoked.plot_topomap(title='MEG %s' % name, time_unit='s')


I am working on the file "0.24/_downloads/78ad76ea5b03c29b4b851b8b64f74b68/linear_model_patterns.ipynb".
The first task is:
Set parameters
Can you write Python code for it?

raw_fname = sample_path + '/sample_audvis_filt-0-40_raw.fif'
event_fname = sample_path + '/sample_audvis_filt-0-40_raw-eve.fif'
tmin, tmax = -0.1, 0.4
event_id = dict(aud_l=1, vis_l=3)

# Setup for reading the raw data
raw = io.read_raw_fif(raw_fname, preload=True)
raw.filter(.5, 25, fir_design='firwin')
events = mne.read_events(event_fname)

# Read epochs
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, proj=True,
                    decim=2, baseline=None, preload=True)
del raw

labels = epochs.events[:, -1]

# get MEG and EEG data
meg_epochs = epochs.copy().pick_types(meg=True, eeg=False)
meg_data = meg_epochs.get_data().reshape(len(labels), -1)


I am working on the file "0.24/_downloads/7b89f7dac105a44e25d2fbdd898b911f/vector_mne_solution.ipynb".
The first task is:
Plotting the full vector-valued MNE solution
The source space that is used for the inverse computation defines a set of
dipoles, distributed across the cortex. When visualizing a source estimate, it
is sometimes useful to show the dipole directions in addition to their
estimated magnitude. This can be accomplished by computing a
:class:mne.VectorSourceEstimate and plotting it with
:meth:stc.plot <mne.VectorSourceEstimate.plot>, which uses
:func:~mne.viz.plot_vector_source_estimates under the hood rather than
:func:~mne.viz.plot_source_estimates.
It can also be instructive to visualize the actual dipole/activation locations
in 3D space in a glass brain, as opposed to activations imposed on an inflated
surface (as typically done in :meth:mne.SourceEstimate.plot), as it allows
you to get a better sense of the underlying source geometry.
Can you write Python code for it?

# Author: Marijn van Vliet <w.m.vanvliet@gmail.com>
#
# License: BSD-3-Clause

import numpy as np
import mne
from mne.datasets import sample
from mne.minimum_norm import read_inverse_operator, apply_inverse

print(__doc__)

data_path = sample.data_path()
subjects_dir = data_path + '/subjects'
smoothing_steps = 7

# Read evoked data
fname_evoked = data_path + '/MEG/sample/sample_audvis-ave.fif'
evoked = mne.read_evokeds(fname_evoked, condition=0, baseline=(None, 0))

# Read inverse solution
fname_inv = data_path + '/MEG/sample/sample_audvis-meg-oct-6-meg-inv.fif'
inv = read_inverse_operator(fname_inv)

# Apply inverse solution, set pick_ori='vector' to obtain a
# :class:`mne.VectorSourceEstimate` object
snr = 3.0
lambda2 = 1.0 / snr ** 2
stc = apply_inverse(evoked, inv, lambda2, 'dSPM', pick_ori='vector')

# Use peak getter to move visualization to the time point of the peak magnitude
_, peak_time = stc.magnitude().get_peak(hemi='lh')


I am working on the file "0.24/_downloads/7b89f7dac105a44e25d2fbdd898b911f/vector_mne_solution.ipynb".
The first task is:
The normal is very similar:
Can you write Python code for it?

brain_normal = stc.project('normal', inv['src'])[0].plot(
    initial_time=peak_time, hemi='lh', subjects_dir=subjects_dir,
    time_label='Normal', smoothing_steps=smoothing_steps)


I am working on the file "0.24/_downloads/7b89f7dac105a44e25d2fbdd898b911f/vector_mne_solution.ipynb".
The first task is:
You can also do this with a fixed-orientation inverse. It looks a lot like
the result above because the loose=0.2 orientation constraint keeps
sources close to fixed orientation:
Can you write Python code for it?

fname_inv_fixed = (
    data_path + '/MEG/sample/sample_audvis-meg-oct-6-meg-fixed-inv.fif')
inv_fixed = read_inverse_operator(fname_inv_fixed)
stc_fixed = apply_inverse(
    evoked, inv_fixed, lambda2, 'dSPM', pick_ori='vector')
brain_fixed = stc_fixed.plot(
    initial_time=peak_time, hemi='lh', subjects_dir=subjects_dir,
    smoothing_steps=smoothing_steps)


I am working on the file "0.24/_downloads/7ba58cd4e9bc2622d60527d21fc13577/decoding_spatio_temporal_source.ipynb".
The first task is:
Compute inverse solution
Can you write Python code for it?

snr = 3.0
noise_cov = mne.read_cov(fname_cov)
inverse_operator = read_inverse_operator(fname_inv)

stcs = apply_inverse_epochs(epochs, inverse_operator,
                            lambda2=1.0 / snr ** 2, verbose=False,
                            method="dSPM", pick_ori="normal")


I am working on the file "0.24/_downloads/7ba58cd4e9bc2622d60527d21fc13577/decoding_spatio_temporal_source.ipynb".
The first task is:
Decoding source space data
Decoding to MEG data in source space on the left cortical surface. Here
univariate feature selection is employed for speed purposes to confine the
classification to a small number of potentially relevant features. The
classifier then is trained to selected features of epochs in source space.
Can you write Python code for it?

# Author: Denis A. Engemann <denis.engemann@gmail.com>
#         Alexandre Gramfort <alexandre.gramfort@inria.fr>
#         Jean-Remi King <jeanremi.king@gmail.com>
#         Eric Larson <larson.eric.d@gmail.com>
#
# License: BSD-3-Clause

import numpy as np
import matplotlib.pyplot as plt

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.linear_model import LogisticRegression

import mne
from mne.minimum_norm import apply_inverse_epochs, read_inverse_operator
from mne.decoding import (cross_val_multiscore, LinearModel, SlidingEstimator,
                          get_coef)

print(__doc__)

data_path = mne.datasets.sample.data_path()
fname_fwd = data_path + 'MEG/sample/sample_audvis-meg-oct-6-fwd.fif'
fname_evoked = data_path + '/MEG/sample/sample_audvis-ave.fif'
subjects_dir = data_path + '/subjects'


I am working on the file "0.24/_downloads/7ca3f34c286b629113cbb522edf26a21/75_cluster_ftest_spatiotemporal.ipynb".
The first task is:
Compute permutation statistic
How does it work? We use clustering to "bind" together features which are
similar. Our features are the magnetic fields measured over our sensor
array at different times. This reduces the multiple comparison problem.
To compute the actual test-statistic, we first sum all F-values in all
clusters. We end up with one statistic for each cluster.
Then we generate a distribution from the data by shuffling our conditions
between our samples and recomputing our clusters and the test statistics.
We test for the significance of a given cluster by computing the probability
of observing a cluster of that size. For more background read:
Maris/Oostenveld (2007), "Nonparametric statistical testing of EEG- and
MEG-data" Journal of Neuroscience Methods, Vol. 164, No. 1., pp. 177-190.
doi:10.1016/j.jneumeth.2007.03.024
Can you write Python code for it?

# set cluster threshold
threshold = 50.0  # very high, but the test is quite sensitive on this data
# set family-wise p-value
p_accept = 0.01

cluster_stats = spatio_temporal_cluster_test(X, n_permutations=1000,
                                             threshold=threshold, tail=1,
                                             n_jobs=1, buffer_size=None,
                                             adjacency=adjacency)

T_obs, clusters, p_values, _ = cluster_stats
good_cluster_inds = np.where(p_values < p_accept)[0]


I am working on the file "0.24/_downloads/7ca3f34c286b629113cbb522edf26a21/75_cluster_ftest_spatiotemporal.ipynb".
The first task is:
Find the FieldTrip neighbor definition to setup sensor adjacency
Can you write Python code for it?

adjacency, ch_names = find_ch_adjacency(epochs.info, ch_type='mag')

print(type(adjacency))  # it's a sparse matrix!

plt.imshow(adjacency.toarray(), cmap='gray', origin='lower',
           interpolation='nearest')
plt.xlabel('{} Magnetometers'.format(len(ch_names)))
plt.ylabel('{} Magnetometers'.format(len(ch_names)))
plt.title('Between-sensor adjacency')


I am working on the file "0.24/_downloads/7ca3f34c286b629113cbb522edf26a21/75_cluster_ftest_spatiotemporal.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'
event_id = {'Aud/L': 1, 'Aud/R': 2, 'Vis/L': 3, 'Vis/R': 4}
tmin = -0.2
tmax = 0.5

# Setup for reading the raw data
raw = mne.io.read_raw_fif(raw_fname, preload=True)
raw.filter(1, 30, fir_design='firwin')
events = mne.read_events(event_fname)


I am working on the file "0.24/_downloads/7ca3f34c286b629113cbb522edf26a21/75_cluster_ftest_spatiotemporal.ipynb".
The first task is:
Spatiotemporal permutation F-test on full sensor data
Tests for differential evoked responses in at least
one condition using a permutation clustering test.
The FieldTrip neighbor templates will be used to determine
the adjacency between sensors. This serves as a spatial prior
to the clustering. Spatiotemporal clusters will then
be visualized using custom matplotlib code.
See the FieldTrip website_ for a caveat regarding
the possible interpretation of "significant" clusters.
Can you write Python code for it?

# Authors: Denis Engemann <denis.engemann@gmail.com>
#          Jona Sassenhagen <jona.sassenhagen@gmail.com>
#
# License: BSD-3-Clause

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

import mne
from mne.stats import spatio_temporal_cluster_test
from mne.datasets import sample
from mne.channels import find_ch_adjacency
from mne.viz import plot_compare_evokeds

print(__doc__)


I am working on the file "0.24/_downloads/81e58e463fcd949fd4ab7ab7ab8ef317/left_cerebellum_volume_source.ipynb".
The first task is:
Plot the positions of each source space
Can you write Python code for it?

fig = mne.viz.plot_alignment(subject=subject, subjects_dir=subjects_dir,
                             surfaces='white', coord_frame='mri',
                             src=src)
mne.viz.set_3d_view(fig, azimuth=180, elevation=90,
                    distance=0.30, focalpoint=(-0.03, -0.01, 0.03))


I am working on the file "0.24/_downloads/82d9c13e00105df6fd0ebed67b862464/ssp_projs_sensitivity_map.ipynb".
The first task is:
Sensitivity map of SSP projections
This example shows the sources that have a forward field
similar to the first SSP vector correcting for ECG.
Can you write Python code for it?

# Author: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#
# License: BSD-3-Clause

import matplotlib.pyplot as plt

from mne import read_forward_solution, read_proj, sensitivity_map

from mne.datasets import sample

print(__doc__)

data_path = sample.data_path()

subjects_dir = data_path + '/subjects'
fname = data_path + '/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif'
ecg_fname = data_path + '/MEG/sample/sample_audvis_ecg-proj.fif'

fwd = read_forward_solution(fname)

projs = read_proj(ecg_fname)
# take only one projection per channel type
projs = projs[::2]

# Compute sensitivity map
ssp_ecg_map = sensitivity_map(fwd, ch_type='grad', projs=projs, mode='angle')


I am working on the file "0.24/_downloads/82d9c13e00105df6fd0ebed67b862464/ssp_projs_sensitivity_map.ipynb".
The first task is:
Show sensitivity map
Can you write Python code for it?

plt.hist(ssp_ecg_map.data.ravel())
plt.show()

args = dict(clim=dict(kind='value', lims=(0.2, 0.6, 1.)), smoothing_steps=7,
            hemi='rh', subjects_dir=subjects_dir)
ssp_ecg_map.plot(subject='sample', time_label='ECG SSP sensitivity', **args)


I am working on the file "0.24/_downloads/84d68dbced84793d122fec3a2cf0cde5/source_power_spectrum.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'
fname_label = data_path + '/MEG/sample/labels/Aud-lh.label'

# Setup for reading the raw data
raw = io.read_raw_fif(raw_fname, verbose=False)
events = mne.find_events(raw, stim_channel='STI 014')
inverse_operator = read_inverse_operator(fname_inv)
raw.info['bads'] = ['MEG 2443', 'EEG 053']

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

tmin, tmax = 0, 120  # use the first 120s of data
fmin, fmax = 4, 100  # look at frequencies between 4 and 100Hz
n_fft = 2048  # the FFT size (n_fft). Ideally a power of 2
label = mne.read_label(fname_label)

stc = compute_source_psd(raw, inverse_operator, lambda2=1. / 9., method="dSPM",
                         tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax,
                         pick_ori="normal", n_fft=n_fft, label=label,
                         dB=True)

stc.save('psd_dSPM')


I am working on the file "0.24/_downloads/87ced9add160fc358769ef662f31e446/45_projectors_background.ipynb".
The first task is:
Computing the projection matrix from the trigger_effect vector is done
using singular value decomposition <svd_>_ (SVD); interested readers may
consult the internet or a linear algebra textbook for details on this method.
With the projection matrix in place, we can project our original vector
$(3, 2, 5)$ to remove the effect of the trigger, and then plot it:
Can you write Python code for it?

# compute the projection matrix
U, S, V = svd(trigger_effect, full_matrices=False)
trigger_projection_matrix = np.eye(3) - U @ U.T

# project the vector onto the orthogonal plane
projected_point = trigger_projection_matrix @ point
projected_vector = trigger_projection_matrix @ vector

# plot the trigger effect and its orthogonal plane
ax = setup_3d_axes()
ax.plot_trisurf(x, y, z, color='C2', shade=False, alpha=0.25)
ax.quiver3D(*np.concatenate([origin, trigger_effect]).flatten(),
            arrow_length_ratio=0.1, color='C2', alpha=0.5)

# plot the original vector
ax.plot(*vector, color='k')
ax.plot(*point, color='k', marker='o')
offset = np.full((3, 1), 0.1)
ax.text(*(point + offset).flat, '({}, {}, {})'.format(*point.flat), color='k')

# plot the projected vector
ax.plot(*projected_vector, color='C0')
ax.plot(*projected_point, color='C0', marker='o')
offset = np.full((3, 1), -0.2)
ax.text(*(projected_point + offset).flat,
        '({}, {}, {})'.format(*np.round(projected_point.flat, 2)),
        color='C0', horizontalalignment='right')

# add dashed arrow showing projection
arrow_coords = np.concatenate([point, projected_point - point]).flatten()
ax.quiver3D(*arrow_coords, length=0.96, arrow_length_ratio=0.1,
            color='C1', linewidth=1, linestyle='dashed')


I am working on the file "0.24/_downloads/87ced9add160fc358769ef662f31e446/45_projectors_background.ipynb".
The first task is:
In MNE-Python, the environmental noise vectors are computed using principal
component analysis <pca_>, usually abbreviated "PCA", which is why the SSP
projectors usually have names like "PCA-v1". (Incidentally, since the process
of performing PCA uses singular value decomposition <svd_> under the hood,
it is also common to see phrases like "projectors were computed using SVD" in
published papers.) The projectors are stored in the projs field of
raw.info:
Can you write Python code for it?


I am working on the file "0.24/_downloads/87ced9add160fc358769ef662f31e446/45_projectors_background.ipynb".
The first task is:
Just as before, the projection matrix will map any point in $x, y, z$
space onto that plane, and once a point has been projected onto that plane,
applying the projection again will have no effect. For that reason, it should
be clear that although the projected points vary in all three $x$,
$y$, and $z$ directions, the set of projected points have only
two effective dimensions (i.e., they are constrained to a plane).
.. sidebar:: Terminology
In MNE-Python, the matrix used to project a raw signal into a subspace is
usually called a :term:`projector` or a *projection
operator* — these terms are interchangeable with the term *projection
matrix* used above.

Projections of EEG or MEG signals work in very much the same way: the point
$x, y, z$ corresponds to the value of each sensor at a single time
point, and the projection matrix varies depending on what aspects of the
signal (i.e., what kind of noise) you are trying to project out. The only
real difference is that instead of a single 3-dimensional point $(x, y,
z)$ you're dealing with a time series of $N$-dimensional "points" (one
at each sampling time), where $N$ is usually in the tens or hundreds
(depending on how many sensors your EEG/MEG system has). Fortunately, because
projection is a matrix operation, it can be done very quickly even on signals
with hundreds of dimensions and tens of thousands of time points.
Signal-space projection (SSP)
We mentioned above that the projection matrix will vary depending on what
kind of noise you are trying to project away. Signal-space projection (SSP)
:footcite:UusitaloIlmoniemi1997 is a way of estimating what that projection
matrix should be, by
comparing measurements with and without the signal of interest. For example,
you can take additional "empty room" measurements that record activity at the
sensors when no subject is present. By looking at the spatial pattern of
activity across MEG sensors in an empty room measurement, you can create one
or more $N$-dimensional vector(s) giving the "direction(s)" of
environmental...
Can you write Python code for it?

sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis_raw.fif')
raw = mne.io.read_raw_fif(sample_data_raw_file)
raw.crop(tmax=60).load_data()


I am working on the file "0.24/_downloads/87ced9add160fc358769ef662f31e446/45_projectors_background.ipynb".
The first task is:
The :class:~mne.io.Raw, :class:~mne.Epochs, and :class:~mne.Evoked
objects all have a boolean :attr:~mne.io.Raw.proj attribute that indicates
whether there are any unapplied / inactive projectors stored in the object.
In other words, the :attr:~mne.io.Raw.proj attribute is True if at
least one :term:projector is present and all of them are active. In
addition, each individual projector also has a boolean active field:
Can you write Python code for it?


I am working on the file "0.24/_downloads/87ced9add160fc358769ef662f31e446/45_projectors_background.ipynb".
The first task is:
There is a corresponding :func:mne.write_proj function that can be used to
save projectors to disk in .fif format:
.. code-block:: python3
mne.write_proj('heartbeat-proj.fif', ecg_projs)

Note

By convention, MNE-Python expects projectors to be saved with a filename
    ending in ``-proj.fif`` (or ``-proj.fif.gz``), and will issue a warning
    if you forgo this recommendation.

Adding and removing projectors
Above, when we printed the ecg_projs list that we loaded from a file, it
showed two projectors for gradiometers (the first two, marked "planar"), two
for magnetometers (the middle two, marked "axial"), and two for EEG sensors
(the last two, marked "eeg"). We can add them to the :class:~mne.io.Raw
object using the :meth:~mne.io.Raw.add_proj method:
Can you write Python code for it?