예제 #1
0
def _save_bads(*, bads, bids_path, verbose):
    """Update the set of channels marked as bad."""
    channels_tsv_fname = bids_path.copy().update(suffix='channels',
                                                 extension='.tsv')
    channels_tsv_data = _from_tsv(channels_tsv_fname)

    descriptions = []
    for ch_name in bads:
        idx = channels_tsv_data['name'].index(ch_name)
        if channels_tsv_data['status'][idx] == 'bad':
            # Channel was already marked as bad, retain existing description.
            description = channels_tsv_data['status_description'][idx]
        else:
            # Channel has been manually marked as bad during inspection, assign
            # default description.
            description = 'Manual inspection via MNE-BIDS'

        descriptions.append(description)

    # We pass overwrite=True, causing all channels not passed as bad here to
    # be marked as good.
    mark_bad_channels(ch_names=bads,
                      descriptions=descriptions,
                      bids_path=bids_path,
                      overwrite=True,
                      verbose=verbose)
예제 #2
0
def _handle_events_reading_core(events_fname, raw):
    """Read associated events.tsv and populate raw.
    Handle onset, duration, and description of each event.
    """
    events_dict = _from_tsv(events_fname)

    if ('value' in events_dict) and ('trial_type' in events_dict):
        events_dict = _drop(events_dict, 'n/a', 'trial_type')
        events_dict = _drop(events_dict, 'n/a', 'value')

        descriptions = np.asarray([
            a + ':' + b
            for a, b in zip(events_dict["trial_type"], events_dict["value"])
        ],
                                  dtype=str)

    # Get the descriptions of the events
    elif 'trial_type' in events_dict:

        # Drop events unrelated to a trial type
        events_dict = _drop(events_dict, 'n/a', 'trial_type')
        descriptions = np.asarray(events_dict['trial_type'], dtype=str)

    # If we don't have a proper description of the events, perhaps we have
    # at least an event value?
    elif 'value' in events_dict:
        # Drop events unrelated to value
        events_dict = _drop(events_dict, 'n/a', 'value')
        descriptions = np.asarray(events_dict['value'], dtype=str)
    # Worst case, we go with 'n/a' for all events
    else:
        descriptions = 'n/a'
    # Deal with "n/a" strings before converting to float
    ons = [np.nan if on == 'n/a' else on for on in events_dict['onset']]
    dus = [0 if du == 'n/a' else du for du in events_dict['duration']]
    onsets = np.asarray(ons, dtype=float)
    durations = np.asarray(dus, dtype=float)
    # Keep only events where onset is known
    good_events_idx = ~np.isnan(onsets)
    onsets = onsets[good_events_idx]
    durations = durations[good_events_idx]
    descriptions = descriptions[good_events_idx]
    del good_events_idx
    # Add Events to raw as annotations
    annot_from_events = mne.Annotations(onset=onsets,
                                        duration=durations,
                                        description=descriptions,
                                        orig_time=None)
    raw.set_annotations(annot_from_events)
    return raw
예제 #3
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
예제 #4
0
def test_count_no_events_column(tmpdir):
    """Test case where events.tsv doesn't contain [stim,trial]_type column."""
    subject, task, run, session, datatype = '01', 'task1', '01', '01', 'meg'
    root, events, event_id = _make_dataset(tmpdir, [subject], [task], [run],
                                           [session])

    # Delete the `stim_type` column.
    events_tsv_fpath = BIDSPath(root=root, subject=subject, task=task, run=run,
                                session=session, datatype=datatype,
                                suffix='events', extension='.tsv').fpath
    events_tsv = _from_tsv(events_tsv_fpath)
    events_tsv['stim_type'] = events_tsv['trial_type']
    del events_tsv['trial_type']
    _write_tsv(fname=events_tsv_fpath, dictionary=events_tsv, overwrite=True)

    counts = count_events(root)
    _check_counts(counts, events, event_id, [subject], [task], [run],
                  [session])
예제 #5
0
def _save_raw_if_changed(*, old_bads, new_bads, flat_chans, old_annotations,
                         new_annotations, bids_path, verbose):
    """Save bad channel selection if it has been changed.

    Parameters
    ----------
    old_bads : list
        The original bad channels.
    new_bads : list
        The updated set of bad channels (i.e. **all** of them, not only the
        changed ones).
    flat_chans : list
        The auto-detected flat channels. This is either an empty list or a
        subset of ``new_bads``.
    old_annotations : mne.Annotations
        The original Annotations.
    new_annotations : mne.Annotations
        The new Annotations.
    """
    assert set(flat_chans).issubset(set(new_bads))

    if set(old_bads) == set(new_bads):
        bads = None
        bad_descriptions = []
    else:
        bads = new_bads
        bad_descriptions = []

        # Generate entries for the `status_description` column.
        channels_tsv_fname = bids_path.copy().update(suffix='channels',
                                                     extension='.tsv')
        channels_tsv_data = _from_tsv(channels_tsv_fname)

        for ch_name in bads:
            idx = channels_tsv_data['name'].index(ch_name)
            if channels_tsv_data['status'][idx] == 'bad':
                # Channel was already marked as bad in the data, so retain
                # existing description.
                description = channels_tsv_data['status_description'][idx]
            elif ch_name in flat_chans:
                description = 'Flat channel, auto-detected via MNE-BIDS'
            else:
                # Channel has been manually marked as bad during inspection
                description = 'Interactive inspection via MNE-BIDS'

            bad_descriptions.append(description)
            del ch_name, description

        del channels_tsv_data, channels_tsv_fname,

    if _annotations_almost_equal(old_annotations, new_annotations):
        annotations = None
    else:
        annotations = new_annotations

    if bads is None and annotations is None:
        # Nothing has changed, so we can just exit.
        return None

    return _save_raw_dialog_box(bads=bads,
                                bad_descriptions=bad_descriptions,
                                annotations=annotations,
                                bids_path=bids_path,
                                verbose=verbose)