r"""Compute SSP/PCA projections for EOG artifacts.
Examples
--------
.. code-block:: console
$ mne compute_proj_eog -i sample_audvis_raw.fif -a \
--l-freq 1 --h-freq 35 \
--rej-grad 3000 --rej-mag 4000 --rej-eeg 100
or
.. code-block:: console
$ mne compute_proj_eog -i sample_audvis_raw.fif -a \
--l-freq 1 --h-freq 35 \
--rej-grad 3000 --rej-mag 4000 --rej-eeg 100 \
--proj sample_audvis_ecg-proj.fif
to exclude ECG artifacts from projection computation.
"""
# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
import os
import sys
import mne
def run():
"""Run command."""
from mne.commands.utils import get_optparser
parser = get_optparser(__file__)
parser.add_option(
"-i", "--in", dest="raw_in", help="Input raw FIF file", metavar="FILE"
)
parser.add_option(
"--tmin",
dest="tmin",
type="float",
help="Time before event in seconds",
default=-0.2,
)
parser.add_option(
"--tmax",
dest="tmax",
type="float",
help="Time after event in seconds",
default=0.2,
)
parser.add_option(
"-g",
"--n-grad",
dest="n_grad",
type="int",
help="Number of SSP vectors for gradiometers",
default=2,
)
parser.add_option(
"-m",
"--n-mag",
dest="n_mag",
type="int",
help="Number of SSP vectors for magnetometers",
default=2,
)
parser.add_option(
"-e",
"--n-eeg",
dest="n_eeg",
type="int",
help="Number of SSP vectors for EEG",
default=2,
)
parser.add_option(
"--l-freq",
dest="l_freq",
type="float",
help="Filter low cut-off frequency in Hz",
default=1,
)
parser.add_option(
"--h-freq",
dest="h_freq",
type="float",
help="Filter high cut-off frequency in Hz",
default=35,
)
parser.add_option(
"--eog-l-freq",
dest="eog_l_freq",
type="float",
help="Filter low cut-off frequency in Hz used for EOG event detection",
default=1,
)
parser.add_option(
"--eog-h-freq",
dest="eog_h_freq",
type="float",
help="Filter high cut-off frequency in Hz used for EOG event detection",
default=10,
)
parser.add_option(
"-p",
"--preload",
dest="preload",
help="Temporary file used during computation (to save memory)",
default=True,
)
parser.add_option(
"-a",
"--average",
dest="average",
action="store_true",
help="Compute SSP after averaging",
default=False,
)
parser.add_option(
"--proj", dest="proj", help="Use SSP projections from a fif file.", default=None
)
parser.add_option(
"--filtersize",
dest="filter_length",
type="int",
help="Number of taps to use for filtering",
default=2048,
)
parser.add_option(
"-j",
"--n-jobs",
dest="n_jobs",
type="int",
help="Number of jobs to run in parallel",
default=1,
)
parser.add_option(
"--rej-grad",
dest="rej_grad",
type="float",
help="Gradiometers rejection parameter in fT/cm (peak to peak amplitude)",
default=2000,
)
parser.add_option(
"--rej-mag",
dest="rej_mag",
type="float",
help="Magnetometers rejection parameter in fT (peak to peak amplitude)",
default=3000,
)
parser.add_option(
"--rej-eeg",
dest="rej_eeg",
type="float",
help="EEG rejection parameter in µV (peak to peak amplitude)",
default=50,
)
parser.add_option(
"--rej-eog",
dest="rej_eog",
type="float",
help="EOG rejection parameter in µV (peak to peak amplitude)",
default=1e9,
)
parser.add_option(
"--avg-ref",
dest="avg_ref",
action="store_true",
help="Add EEG average reference proj",
default=False,
)
parser.add_option(
"--no-proj",
dest="no_proj",
action="store_true",
help="Exclude the SSP projectors currently in the fiff file",
default=False,
)
parser.add_option(
"--bad",
dest="bad_fname",
help="Text file containing bad channels list (one per line)",
default=None,
)
parser.add_option(
"--event-id",
dest="event_id",
type="int",
help="ID to use for events",
default=998,
)
parser.add_option(
"--event-raw",
dest="raw_event_fname",
help="raw file to use for event detection",
default=None,
)
parser.add_option(
"--tstart",
dest="tstart",
type="float",
help="Start artifact detection after tstart seconds",
default=0.0,
)
parser.add_option(
"-c",
"--channel",
dest="ch_name",
type="string",
help="Custom EOG channel(s), comma separated",
default=None,
)
options, args = parser.parse_args()
raw_in = options.raw_in
if raw_in is None:
parser.print_help()
sys.exit(1)
tmin = options.tmin
tmax = options.tmax
n_grad = options.n_grad
n_mag = options.n_mag
n_eeg = options.n_eeg
l_freq = options.l_freq
h_freq = options.h_freq
eog_l_freq = options.eog_l_freq
eog_h_freq = options.eog_h_freq
average = options.average
preload = options.preload
filter_length = options.filter_length
n_jobs = options.n_jobs
reject = dict(
grad=1e-13 * float(options.rej_grad),
mag=1e-15 * float(options.rej_mag),
eeg=1e-6 * float(options.rej_eeg),
eog=1e-6 * float(options.rej_eog),
)
avg_ref = options.avg_ref
no_proj = options.no_proj
bad_fname = options.bad_fname
event_id = options.event_id
proj_fname = options.proj
raw_event_fname = options.raw_event_fname
tstart = options.tstart
ch_name = options.ch_name
if bad_fname is not None:
with open(bad_fname) as fid:
bads = [w.rstrip() for w in fid.readlines()]
print(f"Bad channels read : {bads}")
else:
bads = []
if raw_in.endswith("_raw.fif") or raw_in.endswith("-raw.fif"):
prefix = raw_in[:-8]
else:
prefix = raw_in[:-4]
eog_event_fname = prefix + "_eog-eve.fif"
if average:
eog_proj_fname = prefix + "_eog_avg-proj.fif"
else:
eog_proj_fname = prefix + "_eog-proj.fif"
raw = mne.io.read_raw_fif(raw_in, preload=preload)
if raw_event_fname is not None:
raw_event = mne.io.read_raw_fif(raw_event_fname)
else:
raw_event = raw
flat = None
projs, events = mne.preprocessing.compute_proj_eog(
raw=raw,
raw_event=raw_event,
tmin=tmin,
tmax=tmax,
n_grad=n_grad,
n_mag=n_mag,
n_eeg=n_eeg,
l_freq=l_freq,
h_freq=h_freq,
average=average,
filter_length=filter_length,
n_jobs=n_jobs,
reject=reject,
flat=flat,
bads=bads,
avg_ref=avg_ref,
no_proj=no_proj,
event_id=event_id,
eog_l_freq=eog_l_freq,
eog_h_freq=eog_h_freq,
tstart=tstart,
ch_name=ch_name,
copy=False,
)
raw.close()
if raw_event_fname is not None:
raw_event.close()
if proj_fname is not None:
print(f"Including SSP projections from : {proj_fname}")
# append the eog projs, so they are last in the list
projs = mne.read_proj(proj_fname) + projs
if isinstance(preload, str) and os.path.exists(preload):
os.remove(preload)
print(f"Writing EOG projections in {eog_proj_fname}")
mne.write_proj(eog_proj_fname, projs)
print(f"Writing EOG events in {eog_event_fname}")
mne.write_events(eog_event_fname, events)
is_main = __name__ == "__main__"
if is_main:
run()