예제 #1
0
def test_inspect_bads_and_annotations(tmp_path):
    """Test adding bads and Annotations in one go."""
    from mne.utils._testing import _click_ch_name
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use('Agg')
    plt.close('all')

    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    orig_bads = raw.info['bads'].copy()

    inspect_dataset(bids_path, find_flat=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']

    # Mark some channels as bad by clicking on their name.
    _click_ch_name(raw_fig, ch_index=0, button=1)

    # Add custom Annotation.
    _add_annotation(raw_fig)

    # Close window and save changes.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']
    fig_dialog.canvas.key_press_event('return')

    # Check that the changes were saved.
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    new_bads = raw.info['bads']
    expected_bads = orig_bads + ['MEG 0113']
    assert set(new_bads) == set(expected_bads)
    assert 'BAD_test' in raw.annotations.description
예제 #2
0
def test_inspect_single_file(return_bids_test_dir, save_changes):
    from mne.utils._testing import _click_ch_name
    import matplotlib
    matplotlib.use('Agg')

    bids_path = _bids_path.copy().update(root=return_bids_test_dir)
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    old_bads = raw.info['bads'].copy()

    inspect_dataset(bids_path)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']

    # Mark some channels as bad by clicking on their name.
    _click_ch_name(raw_fig, ch_index=0, button=1)
    _click_ch_name(raw_fig, ch_index=1, button=1)
    _click_ch_name(raw_fig, ch_index=4, button=1)

    # Closing the window should open a dialog box.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']

    if save_changes:
        key = 'return'
    else:
        key = 'escape'
    fig_dialog.canvas.key_press_event(key)

    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    new_bads = raw.info['bads'].copy()

    if save_changes:
        assert len(new_bads) > len(old_bads)
    else:
        assert old_bads == new_bads
예제 #3
0
def test_inspect_dont_show_annotations(tmp_path):
    """Test if show_annotations=False works."""
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use('Agg')
    plt.close('all')

    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)
    inspect_dataset(bids_path, find_flat=False, show_annotations=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    assert not raw_fig.mne.annotations
예제 #4
0
def test_inspect_annotations_remove_all(tmp_path):
    """Test behavior if all Annotations are removed by the user."""
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use('Agg')
    plt.close('all')

    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)
    events_tsv_fpath = (bids_path.copy().update(suffix='events',
                                                extension='.tsv').fpath)

    # Remove all Annotations.
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    raw.set_annotations(None)
    raw.load_data()
    raw.save(raw.filenames[0], overwrite=True)
    # Delete events.tsv sidecar.
    (bids_path.copy().update(suffix='events', extension='.tsv').fpath.unlink())

    # Add custom Annotation.
    inspect_dataset(bids_path, find_flat=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    _add_annotation(raw_fig)

    # Close window and save changes.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']
    fig_dialog.canvas.key_press_event('return')

    # events.tsv sidecar should have been created.
    assert events_tsv_fpath.exists()

    # Remove the Annotation.
    inspect_dataset(bids_path, find_flat=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    data_ax = raw_fig.mne.ax_main
    raw_fig.canvas.key_press_event('a')  # Toggle Annotation mode
    _fake_click(raw_fig,
                data_ax, [1., 1.],
                xform='data',
                button=3,
                kind='press')

    # Close window and save changes.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']
    fig_dialog.canvas.key_press_event('return')

    # events.tsv sidecar should not exist anymore.
    assert not events_tsv_fpath.exists()
예제 #5
0
def test_inspect_auto_flats(tmp_path, save_changes):
    """Test flat channel & segment detection."""
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use('Agg')
    plt.close('all')

    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)
    channels_tsv_fname = bids_path.copy().update(suffix='channels',
                                                 extension='.tsv')

    raw = read_raw_bids(bids_path=bids_path, verbose='error')

    # Inject an entirely flat channel.
    raw.load_data()
    raw._data[10] = np.zeros_like(raw._data[10], dtype=raw._data.dtype)
    # Add a a flat time segment (approx. 100 ms) to another channel
    raw._data[20, 500:500 + int(np.ceil(0.1 * raw.info['sfreq']))] = 0
    raw.save(raw.filenames[0], overwrite=True)
    old_bads = raw.info['bads'].copy()

    inspect_dataset(bids_path)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']

    # Closing the window should open a dialog box.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']

    if save_changes:
        key = 'return'
    else:
        key = 'escape'
    fig_dialog.canvas.key_press_event(key)

    raw = read_raw_bids(bids_path=bids_path, verbose='error')

    if save_changes:
        assert old_bads != raw.info['bads']
        assert raw.ch_names[10] in raw.info['bads']
        channels_tsv_data = _from_tsv(channels_tsv_fname)
        assert (channels_tsv_data['status_description'][10] ==
                'Flat channel, auto-detected via MNE-BIDS')
        # This channel should not have been added to `bads`, but produced a
        # flat annotation.
        assert raw.ch_names[20] not in raw.info['bads']
        assert 'BAD_flat' in raw.annotations.description
    else:
        assert old_bads == raw.info['bads']
        assert 'BAD_flat' not in raw.annotations.description
예제 #6
0
def test_inspect_multiple_files(return_bids_test_dir):
    import matplotlib
    matplotlib.use('Agg')

    bids_path = _bids_path.copy().update(root=return_bids_test_dir)

    # Create a second subject
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    write_raw_bids(raw, bids_path.copy().update(subject='02'))
    del raw

    # Inspection should end with the second subject.
    inspect_dataset(bids_path.copy().update(subject=None))
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    assert raw_fig.mne.info['subject_info']['participant_id'] == 'sub-02'
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
예제 #7
0
def test_inspect_annotations(tmp_path):
    """Test inspection of Annotations."""
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use('Agg')
    plt.close('all')

    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    orig_annotations = raw.annotations.copy()

    inspect_dataset(bids_path, find_flat=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    _add_annotation(raw_fig)

    # Close window and save changes.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']
    fig_dialog.canvas.key_press_event('return')

    # Ensure changes were saved.
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    assert 'BAD_test' in raw.annotations.description
    annot_idx = raw.annotations.description == 'BAD_test'
    assert raw.annotations.duration[annot_idx].squeeze() == 4

    # Remove the Annotation.
    inspect_dataset(bids_path, find_flat=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    data_ax = raw_fig.mne.ax_main
    raw_fig.canvas.key_press_event('a')  # Toggle Annotation mode
    _fake_click(raw_fig,
                data_ax, [1., 1.],
                xform='data',
                button=3,
                kind='press')

    # Close window and save changes.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']
    fig_dialog.canvas.key_press_event('return')

    # Ensure changes were saved.
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    assert 'BAD_test' not in raw.annotations.description
    assert raw.annotations == orig_annotations
예제 #8
0
def test_inspect_set_and_unset_bads(tmp_path):
    """Test marking channels as bad and later marking them as good again."""
    from mne.utils._testing import _click_ch_name
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use('Agg')
    plt.close('all')

    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    orig_bads = raw.info['bads'].copy()

    # Mark some channels as bad by clicking on their name.
    inspect_dataset(bids_path, find_flat=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    _click_ch_name(raw_fig, ch_index=0, button=1)
    _click_ch_name(raw_fig, ch_index=1, button=1)
    _click_ch_name(raw_fig, ch_index=4, button=1)

    # Close window and save changes.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']
    fig_dialog.canvas.key_press_event('return')

    # Inspect the data again, click on two of the bad channels to mark them as
    # good.
    inspect_dataset(bids_path, find_flat=False)
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    _click_ch_name(raw_fig, ch_index=1, button=1)
    _click_ch_name(raw_fig, ch_index=4, button=1)

    # Close window and save changes.
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
    fig_dialog = mne_bids.inspect._global_vars['dialog_fig']
    fig_dialog.canvas.key_press_event('return')

    # Check marking the channels as good has actually worked.
    expected_bads = orig_bads + ['MEG 0113']
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    new_bads = raw.info['bads']
    assert set(new_bads) == set(expected_bads)
예제 #9
0
def test_inspect_multiple_files(tmp_path):
    """Test inspecting a dataset consisting of more than one file."""
    import matplotlib
    import matplotlib.pyplot as plt
    matplotlib.use('Agg')
    plt.close('all')

    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)

    # Create a second subject
    raw = read_raw_bids(bids_path=bids_path, verbose='error')
    write_raw_bids(raw, bids_path.copy().update(subject='02'))
    del raw

    # Inspection should end with the second subject.
    inspect_dataset(bids_path.copy().update(subject=None))
    raw_fig = mne_bids.inspect._global_vars['raw_fig']
    assert raw_fig.mne.info['subject_info']['participant_id'] == 'sub-02'
    raw_fig.canvas.key_press_event(raw_fig.mne.close_key)
예제 #10
0
def run():
    """Run the mark_channels command."""
    from mne.commands.utils import get_optparser

    parser = get_optparser(__file__, usage="usage: %prog options args",
                           prog_prefix='mne_bids',
                           version=mne_bids.__version__)

    parser.add_option('--bids_root', dest='bids_root',
                      help='The path of the folder containing the BIDS '
                           'dataset')
    parser.add_option('--subject_id', dest='subject',
                      help=('Subject name'))
    parser.add_option('--session_id', dest='session',
                      help='Session name')
    parser.add_option('--task', dest='task',
                      help='Task name')
    parser.add_option('--acq', dest='acquisition',
                      help='Acquisition parameter')
    parser.add_option('--run', dest='run',
                      help='Run number')
    parser.add_option('--proc', dest='processing',
                      help='Processing label.')
    parser.add_option('--rec', dest='recording',
                      help='Recording name')
    parser.add_option('--type', dest='datatype',
                      help='Recording data type, e.g. meg, ieeg or eeg')
    parser.add_option('--suffix', dest='suffix',
                      help='The filename suffix, i.e. the last part before '
                           'the extension')
    parser.add_option('--ext', dest='extension',
                      help='The filename extension, including the leading '
                           'period, e.g. .fif')
    parser.add_option('--find_flat', dest='find_flat',
                      help='Whether to auto-detect flat channels and time '
                           'segments')
    parser.add_option('--l_freq', dest='l_freq',
                      help='The high-pass filter cutoff frequency')
    parser.add_option('--h_freq', dest='h_freq',
                      help='The low-pass filter cutoff frequency')
    parser.add_option('--verbose', dest='verbose', action='store_true',
                      help='Whether do generate additional diagnostic output')

    opt, args = parser.parse_args()
    if args:
        parser.print_help()
        parser.error(f'Please do not specify arguments without flags. '
                     f'Got: {args}.\n')

    if opt.bids_root is None:
        parser.print_help()
        parser.error('You must specify bids_root')

    bids_path = BIDSPath(subject=opt.subject, session=opt.session,
                         task=opt.task, acquisition=opt.acquisition,
                         run=opt.run, processing=opt.processing,
                         recording=opt.recording, datatype=opt.datatype,
                         suffix=opt.suffix, extension=opt.extension,
                         root=opt.bids_root)

    find_flat = True if opt.find_flat is None else bool(opt.find_flat)
    l_freq = None if opt.l_freq is None else float(opt.l_freq)
    h_freq = None if opt.h_freq is None else float(opt.h_freq)

    logger.info(f'Inspecting {bids_path.basename} …')
    inspect_dataset(bids_path=bids_path, find_flat=find_flat,
                    l_freq=l_freq, h_freq=h_freq,
                    verbose=opt.verbose)
예제 #11
0
raw.info['line_freq'] = 60  # Specify power line frequency as required by BIDS.
write_raw_bids(raw, bids_path=bids_path, overwrite=True, verbose=False)

###############################################################################
# Interactive use
# ---------------
#
# Using :func:`mne_bids.inspect_dataset`, we can interactively explore the raw
# data and toggle the channel status – ``bad`` or ``good`` – by clicking on the
# respective traces or channel names. If there are any SSP projectors stored
# with the data, a small popup window will allow you to toggle the projectors
# on and off. If you changed the selection of bad channels, you will be
# prompted whether you would like to save the changes when closing the main
# window.

inspect_dataset(bids_path)

###############################################################################
# You can even apply frequency filters when viewing the data: A high-pass
# filter can remove slow drifts, while a low-pass filter will get rid of
# high-frequency artifacts. This can make visual inspection easier. Let's
# apply filters with a 1-Hz high-pass cutoff, and a 30-Hz low-pass cutoff:

inspect_dataset(bids_path, l_freq=1., h_freq=30.)

###############################################################################
# Non-interactive (programmatic) bad channel selection
# ----------------------------------------------------
#
# Read the (now BIDS-formatted) data and print a list of channels currently
# marked as bad.
예제 #12
0
def test_inspect_freq_filter(return_bids_test_dir, l_freq, h_freq):
    bids_path = _bids_path.copy().update(root=return_bids_test_dir)
    inspect_dataset(bids_path, l_freq=l_freq, h_freq=h_freq)
예제 #13
0
def test_inspect_freq_filter(tmp_path, l_freq, h_freq):
    """Test frequency filter for Raw display."""
    bids_root = setup_bids_test_dir(tmp_path)
    bids_path = _bids_path.copy().update(root=bids_root)
    inspect_dataset(bids_path, l_freq=l_freq, h_freq=h_freq, find_flat=False)