예제 #1
0
def test_raw_reject():
    """Test raw data getter with annotation reject."""
    info = create_info(['a', 'b', 'c', 'd', 'e'], 100, ch_types='eeg')
    raw = RawArray(np.ones((5, 15000)), info)
    with warnings.catch_warnings(record=True):  # one outside range
        raw.annotations = Annotations([2, 100, 105, 148], [2, 8, 5, 8], 'BAD')
    data = raw.get_data([0, 1, 3, 4], 100, 11200, 'omit')
    assert_array_equal(data.shape, (4, 9900))

    # with orig_time and complete overlap
    raw = read_raw_fif(fif_fname)
    raw.annotations = Annotations([44, 47, 48], [1, 3, 1], 'BAD',
                                  raw.info['meas_date'])
    data, times = raw.get_data(range(10), 0, 6000, 'omit', True)
    assert_array_equal(data.shape, (10, 4799))
    assert_equal(times[-1], raw.times[5999])
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])

    data, times = raw.get_data(range(10), 0, 6000, 'NaN', True)
    assert_array_equal(data.shape, (10, 6000))
    assert_equal(times[-1], raw.times[5999])
    assert_true(np.isnan(data[:, 313:613]).all())  # 1s -2s
    assert_true(not np.isnan(data[:, 614].any()))
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])
    assert_array_equal(raw.get_data(), raw[:][0])

    # Test _sync_onset
    times = [10, -88, 190]
    onsets = _sync_onset(raw, times)
    assert_array_almost_equal(onsets,
                              times - raw.first_samp / raw.info['sfreq'])
    assert_array_almost_equal(times, _sync_onset(raw, onsets, True))
예제 #2
0
def test_annotations():
    """Test annotation class."""
    raw = Raw(fif_fname)
    onset = np.array(range(10))
    duration = np.ones(10) + raw.first_samp
    description = np.repeat('test', 10)
    dt = datetime.utcnow()
    meas_date = raw.info['meas_date']
    # Test time shifts.
    for orig_time in [None, dt, meas_date[0], meas_date]:
        annot = Annotations(onset, duration, description, orig_time)

    assert_raises(ValueError, Annotations, onset, duration, description[:9])
    assert_raises(ValueError, Annotations, [onset, 1], duration, description)
    assert_raises(ValueError, Annotations, onset, [duration, 1], description)

    # Test combining annotations with concatenate_raws
    annot = Annotations(onset, duration, description, dt)
    sfreq = raw.info['sfreq']
    raw2 = raw.copy()
    raw2.annotations = annot
    concatenate_raws([raw, raw2])
    assert_array_equal(annot.onset, raw.annotations.onset)
    assert_array_equal(annot.duration, raw.annotations.duration)

    raw2.annotations = Annotations(onset, duration * 2, description, None)
    last_samp = raw.last_samp - 1
    concatenate_raws([raw, raw2])
    onsets = np.concatenate([onset,
                             onset + (last_samp - raw.first_samp) / sfreq])
    assert_array_equal(raw.annotations.onset, onsets)
    assert_array_equal(raw.annotations.onset[:10], onset)
    assert_array_equal(raw.annotations.duration[:10], duration)
    assert_array_equal(raw.annotations.duration[10:], duration * 2)
    assert_array_equal(raw.annotations.description, np.repeat('test', 20))
예제 #3
0
def test_raw_reject():
    """Test raw data getter with annotation reject."""
    sfreq = 100.
    info = create_info(['a', 'b', 'c', 'd', 'e'], sfreq, ch_types='eeg')
    raw = RawArray(np.ones((5, 15000)), info)
    with warnings.catch_warnings(record=True):  # one outside range
        raw.set_annotations(
            Annotations([2, 100, 105, 148], [2, 8, 5, 8], 'BAD'))
    data, times = raw.get_data(
        [0, 1, 3, 4],
        100,
        11200,  # 1-112 sec
        'omit',
        return_times=True)
    bad_times = np.concatenate([
        np.arange(200, 400),
        np.arange(10000, 10800),
        np.arange(10500, 11000)
    ])
    expected_times = np.setdiff1d(np.arange(100, 11200), bad_times) / sfreq
    assert_allclose(times, expected_times)

    # with orig_time and complete overlap
    raw = read_raw_fif(fif_fname)
    t_0 = raw.first_samp / raw.info['sfreq']
    raw.set_annotations(
        Annotations([t_0 + 1, t_0 + 4, t_0 + 5], [1, 3, 1], 'BAD',
                    raw.info['meas_date']))
    t_stop = 18.
    assert raw.times[-1] > t_stop
    n_stop = int(round(t_stop * raw.info['sfreq']))
    n_drop = int(round(4 * raw.info['sfreq']))
    assert len(raw.times) >= n_stop
    data, times = raw.get_data(range(10), 0, n_stop, 'omit', True)
    assert data.shape == (10, n_stop - n_drop)
    assert times[-1] == raw.times[n_stop - 1]
    assert_array_equal(data[:, -100:], raw[:10, n_stop - 100:n_stop][0])

    data, times = raw.get_data(range(10), 0, n_stop, 'NaN', True)
    assert_array_equal(data.shape, (10, n_stop))
    assert times[-1] == raw.times[n_stop - 1]
    t_1, t_2 = raw.time_as_index([1, 2], use_rounding=True)
    assert np.isnan(data[:, t_1:t_2]).all()  # 1s -2s
    assert not np.isnan(data[:, :t_1].any())
    assert not np.isnan(data[:, t_2:].any())
    assert_array_equal(data[:, -100:], raw[:10, n_stop - 100:n_stop][0])
    assert_array_equal(raw.get_data(), raw[:][0])

    # Test _sync_onset
    times = [10, -88, 190]
    onsets = _sync_onset(raw, times)
    assert_array_almost_equal(onsets,
                              times - raw.first_samp / raw.info['sfreq'])
    assert_array_almost_equal(times, _sync_onset(raw, onsets, True))
예제 #4
0
def test_annotations():
    """Test annotation class."""
    raw = read_raw_fif(fif_fname)
    onset = np.array(range(10))
    duration = np.ones(10)
    description = np.repeat('test', 10)
    dt = datetime.utcnow()
    meas_date = raw.info['meas_date']
    # Test time shifts.
    for orig_time in [None, dt, meas_date[0], meas_date]:
        annot = Annotations(onset, duration, description, orig_time)

    assert_raises(ValueError, Annotations, onset, duration, description[:9])
    assert_raises(ValueError, Annotations, [onset, 1], duration, description)
    assert_raises(ValueError, Annotations, onset, [duration, 1], description)

    # Test combining annotations with concatenate_raws
    raw2 = raw.copy()
    orig_time = (meas_date[0] + meas_date[1] * 0.000001 +
                 raw2.first_samp / raw2.info['sfreq'])
    annot = Annotations(onset, duration, description, orig_time)
    raw2.annotations = annot
    assert_array_equal(raw2.annotations.onset, onset)
    concatenate_raws([raw, raw2])
    assert_array_almost_equal(onset + 20., raw.annotations.onset, decimal=2)
    assert_array_equal(annot.duration, raw.annotations.duration)
    assert_array_equal(raw.annotations.description, np.repeat('test', 10))

    # Test combining with RawArray and orig_times
    data = np.random.randn(2, 1000) * 10e-12
    sfreq = 100.
    info = create_info(ch_names=['MEG1', 'MEG2'], ch_types=['grad'] * 2,
                       sfreq=sfreq)
    info['meas_date'] = 0
    raws = []
    for i, fs in enumerate([1000, 100, 12]):
        raw = RawArray(data.copy(), info, first_samp=fs)
        ants = Annotations([1., 2.], [.5, .5], 'x', fs / sfreq)
        raw.annotations = ants
        raws.append(raw)
    raw = concatenate_raws(raws)
    assert_array_equal(raw.annotations.onset, [1., 2., 11., 12., 21., 22.])
    raw.annotations.delete(2)
    assert_array_equal(raw.annotations.onset, [1., 2., 12., 21., 22.])
    raw.annotations.append(5, 1.5, 'y')
    assert_array_equal(raw.annotations.onset, [1., 2., 12., 21., 22., 5])
    assert_array_equal(raw.annotations.duration, [.5, .5, .5, .5, .5, 1.5])
    assert_array_equal(raw.annotations.description, ['x', 'x', 'x', 'x', 'x',
                                                     'y'])
예제 #5
0
def test_annotation_omit():
    """Test raw.get_data with annotations."""
    data = np.concatenate([np.ones((1, 1000)), 2 * np.ones((1, 1000))], -1)
    info = create_info(1, 1000., 'eeg')
    raw = RawArray(data, info)
    raw.annotations = Annotations([0.5], [1], ['bad'])
    expected = raw[0][0]
    assert_allclose(raw.get_data(reject_by_annotation=None), expected)
    # nan
    expected[0, 500:1500] = np.nan
    assert_allclose(raw.get_data(reject_by_annotation='nan'), expected)
    got = np.concatenate([
        raw.get_data(start=start, stop=stop, reject_by_annotation='nan')
        for start, stop in ((0, 1000), (1000, 2000))
    ], -1)
    assert_allclose(got, expected)
    # omit
    expected = expected[:, np.isfinite(expected[0])]
    assert_allclose(raw.get_data(reject_by_annotation='omit'), expected)
    got = np.concatenate([
        raw.get_data(start=start, stop=stop, reject_by_annotation='omit')
        for start, stop in ((0, 1000), (1000, 2000))
    ], -1)
    assert_allclose(got, expected)
    assert_raises(ValueError, raw.get_data, reject_by_annotation='foo')
예제 #6
0
def test_save():
    """ Test saving raw"""
    tempdir = _TempDir()
    raw = Raw(fif_fname, preload=False)
    # can't write over file being read
    assert_raises(ValueError, raw.save, fif_fname)
    raw = Raw(fif_fname, preload=True)
    # can't overwrite file without overwrite=True
    assert_raises(IOError, raw.save, fif_fname)

    # test abspath support and annotations
    annot = Annotations([10], [10], ['test'], raw.info['meas_date'])
    raw.annotations = annot
    new_fname = op.join(op.abspath(op.curdir), 'break-raw.fif')
    raw.save(op.join(tempdir, new_fname), overwrite=True)
    new_raw = Raw(op.join(tempdir, new_fname), preload=False)
    assert_raises(ValueError, new_raw.save, new_fname)
    assert_array_equal(annot.onset, new_raw.annotations.onset)
    assert_array_equal(annot.duration, new_raw.annotations.duration)
    assert_array_equal(annot.description, new_raw.annotations.description)
    assert_equal(annot.orig_time, new_raw.annotations.orig_time)
    # make sure we can overwrite the file we loaded when preload=True
    new_raw = Raw(op.join(tempdir, new_fname), preload=True)
    new_raw.save(op.join(tempdir, new_fname), overwrite=True)
    os.remove(new_fname)
def test_annotation_concat():
    """Test if two Annotations objects can be concatenated."""
    a = Annotations([1, 2, 3], [5, 5, 8], ["a", "b", "c"])
    b = Annotations([11, 12, 13], [1, 2, 2], ["x", "y", "z"])

    # test + operator (does not modify a or b)
    c = a + b
    assert_array_equal(c.onset, [1, 2, 3, 11, 12, 13])
    assert_array_equal(c.duration, [5, 5, 8, 1, 2, 2])
    assert_array_equal(c.description, ["a", "b", "c", "x", "y", "z"])
    assert_equal(len(a), 3)
    assert_equal(len(b), 3)
    assert_equal(len(c), 6)

    # test += operator (modifies a in place)
    a += b
    assert_array_equal(a.onset, [1, 2, 3, 11, 12, 13])
    assert_array_equal(a.duration, [5, 5, 8, 1, 2, 2])
    assert_array_equal(a.description, ["a", "b", "c", "x", "y", "z"])
    assert_equal(len(a), 6)
    assert_equal(len(b), 3)
예제 #8
0
def annotate_motion(raw, pos, thr=0.01):
    """Find and annotate periods of high HPI distance w.r.t the median HPI pos
        and readjust trans matrix dev->head - written originally by Luke Bloy"""
    annot = Annotations([], [], [])

    info = raw.info
    time = pos[:, 0]
    quats = pos[:, 1:7]

    # Get static head pos from file, used to convert quat to cartesian
    chpi_locs_dev = sorted([d for d in info['hpi_results'][-1]
                            ['dig_points']], key=lambda x: x['ident'])
    chpi_locs_dev = np.array([d['r'] for d in chpi_locs_dev])
    # chpi_locs_dev[0]-> LPA, chpi_locs_dev[1]-> NASION, chpi_locs_dev[2]-> RPA
    # Get head pos changes during recording
    chpi_mov_head = np.array([_apply_quat(quat, chpi_locs_dev, move=True)
                              for quat in quats])

    # get median position across all recording
    chpi_mov_head_f = chpi_mov_head.reshape([-1, 9])  # always 9 chans
    chpi_med_head_tmp = np.median(chpi_mov_head_f, axis=0).reshape([3, 3])

    # get movement displacement from median
    hpi_disp = chpi_mov_head - np.tile(chpi_med_head_tmp, (len(time), 1, 1))
    # get positions above threshold distance
    disp = np.sqrt((hpi_disp ** 2).sum(axis=2))
    disp_exes = np.any(disp > thr, axis=1)

    # Get median head pos during recording under threshold distance
    weights = np.append(time[1:] - time[:-1], 0)
    weights[disp_exes] = 0
    weights /= sum(weights)
    tmp_med_head = weighted_median(chpi_mov_head, weights)
    # Get closest real pos to estimated median
    hpi_disp_th = chpi_mov_head - np.tile(tmp_med_head, (len(time), 1, 1))
    hpi_dist_th = np.sqrt((hpi_disp_th.reshape(-1, 9) ** 2).sum(axis=1))
    chpi_median_pos = chpi_mov_head[hpi_dist_th.argmin(), :, :]

    # Compute displacements from final median head pos
    hpi_disp = chpi_mov_head - np.tile(chpi_median_pos, (len(time), 1, 1))
    hpi_disp = np.sqrt((hpi_disp**2).sum(axis=-1))

    art_mask_mov = np.any(hpi_disp > thr, axis=-1)  # hpi_disp > thr why?
    annot += _annotations_from_mask(time, art_mask_mov,
                                    'Bad-motion-dist>%0.3f' % thr)

    # Compute new dev->head transformation from median
    init_dev_head_t = _quaternion_align(info['dev_head_t']['from'],
                                        info['dev_head_t']['to'],
                                        chpi_locs_dev, chpi_median_pos)
    dev_head_t = init_dev_head_t
    return annot, hpi_disp, dev_head_t
예제 #9
0
def test_flat_bad_acq_skip():
    """Test that acquisition skips are handled properly."""
    # -- file with a couple of skip and flat channels --
    raw = read_raw_fif(skip_fname, preload=True)
    annots, bads = annotate_amplitude(raw, flat=0)
    assert len(annots) == 0
    assert bads == [  # MaxFilter finds the same 21 channels
        'MEG%04d' % (int(num),) for num in
        '141 331 421 431 611 641 1011 1021 1031 1241 1421 '
        '1741 1841 2011 2131 2141 2241 2531 2541 2611 2621'.split()]

    # -- overlap of flat segment with bad_acq_skip --
    n_ch, n_times = 11, 1000
    data = np.random.RandomState(0).randn(n_ch, n_times)
    assert not (np.diff(data, axis=-1) == 0).any()  # nothing flat at first
    info = create_info(n_ch, 1000., 'eeg')
    raw = RawArray(data, info, first_samp=0)
    raw.info['bads'] = [raw.ch_names[-1]]
    bad_acq_skip = Annotations([0.5], [0.2], ['bad_acq_skip'], orig_time=None)
    raw.set_annotations(bad_acq_skip)
    # add flat channel overlapping with the left edge of bad_acq_skip
    raw_ = raw.copy()
    raw_._data[0, 400:600] = 0.
    annots, bads = annotate_amplitude(raw_, peak=None, flat=0, bad_percent=25)
    assert len(annots) == 1
    assert len(bads) == 0
    # check annotation instance
    assert annots[0]['description'] == 'BAD_flat'
    _check_annotation(raw_, annots[0], None, 0, 400, 499)

    # add flat channel overlapping with the right edge of bad_acq_skip
    raw_ = raw.copy()
    raw_._data[0, 600:800] = 0.
    annots, bads = annotate_amplitude(raw_, peak=None, flat=0, bad_percent=25)
    assert len(annots) == 1
    assert len(bads) == 0
    # check annotation instance
    assert annots[0]['description'] == 'BAD_flat'
    _check_annotation(raw_, annots[0], None, 0, 700, 799)

    # add flat channel overlapping entirely with bad_acq_skip
    raw_ = raw.copy()
    raw_._data[0, 200:800] = 0.
    annots, bads = annotate_amplitude(raw_, peak=None, flat=0, bad_percent=41)
    assert len(annots) == 2
    assert len(bads) == 0
    # check annotation instance
    annots = sorted(annots, key=lambda x: x['onset'])
    assert all(annot['description'] == 'BAD_flat' for annot in annots)
    _check_annotation(raw_, annots[0], None, 0, 200, 500)
    _check_annotation(raw_, annots[1], None, 0, 700, 799)
예제 #10
0
def test_raw_reject():
    """Test raw data getter with annotation reject."""
    info = create_info(['a', 'b', 'c', 'd', 'e'], 100, ch_types='eeg')
    raw = RawArray(np.ones((5, 15000)), info)
    raw.annotations = Annotations([2, 100, 105, 148], [2, 8, 5, 8], 'BAD')
    data = raw.get_data([0, 1, 3, 4], 100, 11200, 'omit')
    assert_array_equal(data.shape, (4, 9900))

    # with orig_time and complete overlap
    raw = read_raw_fif(fif_fname)
    raw.annotations = Annotations([44, 47, 48], [1, 3, 1], 'BAD',
                                  raw.info['meas_date'])
    data, times = raw.get_data(range(10), 0, 6000, 'omit', True)
    assert_array_equal(data.shape, (10, 4799))
    assert_equal(times[-1], raw.times[5999])
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])

    data, times = raw.get_data(range(10), 0, 6000, 'NaN', True)
    assert_array_equal(data.shape, (10, 6000))
    assert_equal(times[-1], raw.times[5999])
    assert_true(np.isnan(data[:, 313:613]).all())  # 1s -2s
    assert_true(not np.isnan(data[:, 614].any()))
    assert_array_equal(data[:, -100:], raw[:10, 5900:6000][0])
    assert_array_equal(raw.get_data(), raw[:][0])
예제 #11
0
def _annotations_from_mask(times, art_mask, art_name):
    # make annotations - by Luke Bloy
    comps, num_comps = label(art_mask)
    onsets = []
    durations = []
    desc = []
    n_times = len(times)
    for l in range(1, num_comps+1):
        l_idx = np.nonzero(comps == l)[0]
        onsets.append(times[l_idx[0]])
        # duration is to the time after the last labeled time
        # or to the end of the times.
        if 1+l_idx[-1] < n_times:
            durations.append(times[1+l_idx[-1]] - times[l_idx[0]])
        else:
            durations.append(times[l_idx[-1]] - times[l_idx[0]])
        desc.append(art_name)
    return Annotations(onsets, durations, desc)
예제 #12
0
def read_annotations_besa_evt(evt_fname, time_0=0.0):
    """Read in evt file as annotations."""
    seg_info = dict()
    with open(evt_fname, 'r') as fid:
        fid.readline()
        for line in fid.readlines():
            parts = line.strip().split('\t')
            code = parts[1]
            time = time_0 + 1e-6 * float(parts[0].strip())
            if code not in seg_info:
                seg_info[code] = []
            seg_info[code].append(time)

    # build Annotations
    onsets = []
    durations = []
    desc = []
    for code, t_list in seg_info.iteritems():
        it = iter(t_list)
        for t_start in it:
            onsets.append(t_start)
            durations.append(next(it) - t_start)
            desc.append('besa_%s' % code)
    return Annotations(onsets, durations, desc)
예제 #13
0
def test_annotations_crop():
    """Test basic functionality of annotation crop."""
    onset = np.arange(1, 10)
    duration = np.full_like(onset, 10)
    description = ["yy"] * onset.shape[0]

    a = Annotations(onset=onset,
                    duration=duration,
                    description=description,
                    orig_time=0)

    # cropping window larger than annotations --> do not modify
    a_ = a.copy().crop(tmin=0, tmax=42)
    assert_array_equal(a_.onset, a.onset)
    assert_array_equal(a_.duration, a.duration)

    # cropping with left shifted window
    with pytest.warns(None) as w:
        a_ = a.copy().crop(tmin=0, tmax=4.2)
    assert_array_equal(a_.onset, [1., 2., 3., 4.])
    assert_allclose(a_.duration, [3.2, 2.2, 1.2, 0.2])
    assert len(w) == 0

    # cropping with right shifted window
    with pytest.warns(None) as w:
        a_ = a.copy().crop(tmin=17.8, tmax=22)
    assert_array_equal(a_.onset, [17.8, 17.8])
    assert_allclose(a_.duration, [0.2, 1.2])
    assert len(w) == 0

    # cropping with centered small window
    a_ = a.copy().crop(tmin=11, tmax=12)
    assert_array_equal(a_.onset, [11, 11, 11, 11, 11, 11, 11, 11, 11])
    assert_array_equal(a_.duration, [0, 1, 1, 1, 1, 1, 1, 1, 1])

    # cropping with out-of-bounds window
    with pytest.warns(None) as w:
        a_ = a.copy().crop(tmin=42, tmax=100)
    assert_array_equal(a_.onset, [])
    assert_array_equal(a_.duration, [])
    assert len(w) == 0

    # test error raising
    with pytest.raises(ValueError, match='tmax should be greater than tmin'):
        a.copy().crop(tmin=42, tmax=0)
    with pytest.raises(ValueError, match='tmin should be positive'):
        a.copy().crop(tmin=-10, tmax=0)

    # test warnings
    with pytest.warns(RuntimeWarning, match='Omitted .* were outside'):
        a.copy().crop(tmin=42, tmax=100, emit_warning=True)
    with pytest.warns(RuntimeWarning, match='Limited .* expanding outside'):
        a.copy().crop(tmin=0, tmax=12, emit_warning=True)
예제 #14
0
def test_crop():
    """Test cropping with annotations."""
    raw = read_raw_fif(fif_fname)
    events = mne.find_events(raw)
    onset = events[events[:, 2] == 1, 0] / raw.info['sfreq']
    duration = np.full_like(onset, 0.5)
    description = ['bad %d' % k for k in range(len(onset))]
    raw.annotations = mne.Annotations(onset,
                                      duration,
                                      description,
                                      orig_time=raw.info['meas_date'])

    split_time = raw.times[-1] / 2. + 2.
    split_idx = len(onset) // 2 + 1
    raw_cropped_left = raw.copy().crop(0., split_time - 1. / raw.info['sfreq'])
    assert_array_equal(raw_cropped_left.annotations.description,
                       raw.annotations.description[:split_idx])
    assert_allclose(raw_cropped_left.annotations.duration,
                    raw.annotations.duration[:split_idx])
    assert_allclose(raw_cropped_left.annotations.onset,
                    raw.annotations.onset[:split_idx])
    raw_cropped_right = raw.copy().crop(split_time, None)
    assert_array_equal(raw_cropped_right.annotations.description,
                       raw.annotations.description[split_idx:])
    assert_allclose(raw_cropped_right.annotations.duration,
                    raw.annotations.duration[split_idx:])
    assert_allclose(raw_cropped_right.annotations.onset,
                    raw.annotations.onset[split_idx:])
    raw_concat = mne.concatenate_raws([raw_cropped_left, raw_cropped_right],
                                      verbose='debug')
    assert_allclose(raw_concat.times, raw.times)
    assert_allclose(raw_concat[:][0], raw[:][0], atol=1e-20)
    # Get rid of the boundary events
    raw_concat.annotations.delete(-1)
    raw_concat.annotations.delete(-1)
    # Ensure we annotations survive round-trip crop->concat
    assert_array_equal(raw_concat.annotations.description,
                       raw.annotations.description)
    for attr in ('onset', 'duration'):
        assert_allclose(getattr(raw_concat.annotations, attr),
                        getattr(raw.annotations, attr),
                        err_msg='Failed for %s:' % (attr, ))

    raw.annotations = None  # undo

    # Test concatenating annotations with and without orig_time.
    last_time = raw.last_samp / raw.info['sfreq']
    raw2 = raw.copy()
    raw.annotations = Annotations([45.], [3], 'test', raw.info['meas_date'])
    raw2.annotations = Annotations([2.], [3], 'BAD', None)
    raw = concatenate_raws([raw, raw2])
    raw.annotations.delete(-1)  # remove boundary annotations
    raw.annotations.delete(-1)
    assert_array_almost_equal(raw.annotations.onset, [45., 2. + last_time],
                              decimal=2)

    # Test IO
    tempdir = _TempDir()
    fname = op.join(tempdir, 'test-annot.fif')
    raw.annotations.save(fname)
    annot_read = read_annotations(fname)
    for attr in ('onset', 'duration', 'orig_time'):
        assert_allclose(getattr(annot_read, attr),
                        getattr(raw.annotations, attr))
    assert_array_equal(annot_read.description, raw.annotations.description)
    annot = Annotations((), (), ())
    annot.save(fname)
    pytest.raises(IOError, read_annotations, fif_fname)  # none in old raw
    annot = read_annotations(fname)
    assert isinstance(annot, Annotations)
    assert len(annot) == 0
    # Test that empty annotations can be saved with an object
    fname = op.join(tempdir, 'test_raw.fif')
    raw.annotations = annot
    raw.save(fname)
    raw_read = read_raw_fif(fname)
    assert isinstance(raw_read.annotations, Annotations)
    assert len(raw_read.annotations) == 0
    raw.annotations = None
    raw.save(fname, overwrite=True)
    raw_read = read_raw_fif(fname)
    assert raw_read.annotations is None
예제 #15
0
def test_annotation_filtering():
    """Test that annotations work properly with filtering."""
    # Create data with just a DC component
    data = np.ones((1, 1000))
    info = create_info(1, 1000., 'eeg')
    raws = [RawArray(data * (ii + 1), info) for ii in range(4)]
    kwargs_pass = dict(l_freq=None, h_freq=50., fir_design='firwin')
    kwargs_stop = dict(l_freq=50., h_freq=None, fir_design='firwin')
    # lowpass filter, which should not modify the data
    raws_pass = [raw.copy().filter(**kwargs_pass) for raw in raws]
    # highpass filter, which should zero it out
    raws_stop = [raw.copy().filter(**kwargs_stop) for raw in raws]
    # concat the original and the filtered segments
    raws_concat = concatenate_raws([raw.copy() for raw in raws])
    raws_zero = raws_concat.copy().apply_function(lambda x: x * 0)
    raws_pass_concat = concatenate_raws(raws_pass)
    raws_stop_concat = concatenate_raws(raws_stop)
    # make sure we did something reasonable with our individual-file filtering
    assert_allclose(raws_concat[0][0], raws_pass_concat[0][0], atol=1e-14)
    assert_allclose(raws_zero[0][0], raws_stop_concat[0][0], atol=1e-14)
    # ensure that our Annotations cut up the filtering properly
    raws_concat_pass = raws_concat.copy().filter(skip_by_annotation='edge',
                                                 **kwargs_pass)
    assert_allclose(raws_concat[0][0], raws_concat_pass[0][0], atol=1e-14)
    raws_concat_stop = raws_concat.copy().filter(skip_by_annotation='edge',
                                                 **kwargs_stop)
    assert_allclose(raws_zero[0][0], raws_concat_stop[0][0], atol=1e-14)
    # one last test: let's cut out a section entirely:
    # here the 1-3 second window should be skipped
    raw = raws_concat.copy()
    raw.annotations.append(1., 2., 'foo')
    raw.filter(l_freq=50.,
               h_freq=None,
               fir_design='firwin',
               skip_by_annotation='foo')
    # our filter will zero out anything not skipped:
    mask = np.concatenate((np.zeros(1000), np.ones(2000), np.zeros(1000)))
    expected_data = raws_concat[0][0][0] * mask
    assert_allclose(raw[0][0][0], expected_data, atol=1e-14)

    # Let's try another one
    raw = raws[0].copy()
    raw.annotations = Annotations([0.], [0.5], ['BAD_ACQ_SKIP'])
    my_data, times = raw.get_data(reject_by_annotation='omit',
                                  return_times=True)
    assert_allclose(times, raw.times[500:])
    assert my_data.shape == (1, 500)
    raw_filt = raw.copy().filter(skip_by_annotation='bad_acq_skip',
                                 **kwargs_stop)
    expected = data.copy()
    expected[:, 500:] = 0
    assert_allclose(raw_filt[:][0], expected, atol=1e-14)

    raw = raws[0].copy()
    raw.annotations = Annotations([0.5], [0.5], ['BAD_ACQ_SKIP'])
    my_data, times = raw.get_data(reject_by_annotation='omit',
                                  return_times=True)
    assert_allclose(times, raw.times[:500])
    assert my_data.shape == (1, 500)
    raw_filt = raw.copy().filter(skip_by_annotation='bad_acq_skip',
                                 **kwargs_stop)
    expected = data.copy()
    expected[:, :500] = 0
    assert_allclose(raw_filt[:][0], expected, atol=1e-14)
예제 #16
0
def test_basics():
    """Test annotation class."""
    raw = read_raw_fif(fif_fname)
    assert raw.annotations is None
    pytest.raises(IOError, read_annotations, fif_fname)
    onset = np.array(range(10))
    duration = np.ones(10)
    description = np.repeat('test', 10)
    dt = datetime.utcnow()
    meas_date = raw.info['meas_date']
    # Test time shifts.
    for orig_time in [None, dt, meas_date[0], meas_date]:
        annot = Annotations(onset, duration, description, orig_time)

    pytest.raises(ValueError, Annotations, onset, duration, description[:9])
    pytest.raises(ValueError, Annotations, [onset, 1], duration, description)
    pytest.raises(ValueError, Annotations, onset, [duration, 1], description)

    # Test combining annotations with concatenate_raws
    raw2 = raw.copy()
    delta = raw.times[-1] + 1. / raw.info['sfreq']
    orig_time = (meas_date[0] + meas_date[1] * 1e-6 +
                 raw2.first_samp / raw2.info['sfreq'])
    annot = Annotations(onset, duration, description, orig_time)
    assert ' segments' in repr(annot)
    raw2.annotations = annot
    assert_array_equal(raw2.annotations.onset, onset)
    concatenate_raws([raw, raw2])
    raw.annotations.delete(-1)  # remove boundary annotations
    raw.annotations.delete(-1)

    assert_allclose(onset + delta, raw.annotations.onset, rtol=1e-5)
    assert_array_equal(annot.duration, raw.annotations.duration)
    assert_array_equal(raw.annotations.description, np.repeat('test', 10))

    # Test combining with RawArray and orig_times
    data = np.random.randn(2, 1000) * 10e-12
    sfreq = 100.
    info = create_info(ch_names=['MEG1', 'MEG2'],
                       ch_types=['grad'] * 2,
                       sfreq=sfreq)
    info['meas_date'] = np.pi
    raws = []
    for first_samp in [12300, 100, 12]:
        raw = RawArray(data.copy(), info, first_samp=first_samp)
        ants = Annotations([1., 2.], [.5, .5], 'x', np.pi + first_samp / sfreq)
        raw.annotations = ants
        raws.append(raw)
    raw = RawArray(data.copy(), info)
    raw.annotations = Annotations([1.], [.5], 'x', None)
    raws.append(raw)
    raw = concatenate_raws(raws, verbose='debug')
    boundary_idx = np.where(raw.annotations.description == 'BAD boundary')[0]
    assert len(boundary_idx) == 3
    raw.annotations.delete(boundary_idx)
    boundary_idx = np.where(raw.annotations.description == 'EDGE boundary')[0]
    assert len(boundary_idx) == 3
    raw.annotations.delete(boundary_idx)
    assert_array_equal(raw.annotations.onset,
                       [1., 2., 11., 12., 21., 22., 31.])
    raw.annotations.delete(2)
    assert_array_equal(raw.annotations.onset, [1., 2., 12., 21., 22., 31.])
    raw.annotations.append(5, 1.5, 'y')
    assert_array_equal(raw.annotations.onset, [1., 2., 12., 21., 22., 31., 5])
    assert_array_equal(raw.annotations.duration, [.5, .5, .5, .5, .5, .5, 1.5])
    assert_array_equal(raw.annotations.description,
                       ['x', 'x', 'x', 'x', 'x', 'x', 'y'])
예제 #17
0
def test_annotations():
    """Test annotation class."""
    raw = read_raw_fif(fif_fname)
    assert raw.annotations is None
    assert_raises(ValueError, read_annotations, fif_fname)
    onset = np.array(range(10))
    duration = np.ones(10)
    description = np.repeat('test', 10)
    dt = datetime.utcnow()
    meas_date = raw.info['meas_date']
    # Test time shifts.
    for orig_time in [None, dt, meas_date[0], meas_date]:
        annot = Annotations(onset, duration, description, orig_time)

    assert_raises(ValueError, Annotations, onset, duration, description[:9])
    assert_raises(ValueError, Annotations, [onset, 1], duration, description)
    assert_raises(ValueError, Annotations, onset, [duration, 1], description)

    # Test combining annotations with concatenate_raws
    raw2 = raw.copy()
    orig_time = (meas_date[0] + meas_date[1] * 0.000001 +
                 raw2.first_samp / raw2.info['sfreq'])
    annot = Annotations(onset, duration, description, orig_time)
    assert_true(' segments' in repr(annot))
    raw2.annotations = annot
    assert_array_equal(raw2.annotations.onset, onset)
    concatenate_raws([raw, raw2])
    raw.annotations.delete(-1)  # remove boundary annotations
    raw.annotations.delete(-1)
    assert_array_almost_equal(onset + 20., raw.annotations.onset, decimal=2)
    assert_array_equal(annot.duration, raw.annotations.duration)
    assert_array_equal(raw.annotations.description, np.repeat('test', 10))

    # Test combining with RawArray and orig_times
    data = np.random.randn(2, 1000) * 10e-12
    sfreq = 100.
    info = create_info(ch_names=['MEG1', 'MEG2'],
                       ch_types=['grad'] * 2,
                       sfreq=sfreq)
    info['meas_date'] = 0
    raws = []
    for i, fs in enumerate([12300, 100, 12]):
        raw = RawArray(data.copy(), info, first_samp=fs)
        ants = Annotations([1., 2.], [.5, .5], 'x', fs / sfreq)
        raw.annotations = ants
        raws.append(raw)
    raw = RawArray(data.copy(), info)
    raw.annotations = Annotations([1.], [.5], 'x', None)
    raws.append(raw)
    raw = concatenate_raws(raws)
    boundary_idx = np.where(raw.annotations.description == 'BAD boundary')[0]
    assert_equal(len(boundary_idx), 3)
    raw.annotations.delete(boundary_idx)
    boundary_idx = np.where(raw.annotations.description == 'EDGE boundary')[0]
    assert_equal(len(boundary_idx), 3)
    raw.annotations.delete(boundary_idx)
    assert_array_equal(raw.annotations.onset,
                       [1., 2., 11., 12., 21., 22., 31.])
    raw.annotations.delete(2)
    assert_array_equal(raw.annotations.onset, [1., 2., 12., 21., 22., 31.])
    raw.annotations.append(5, 1.5, 'y')
    assert_array_equal(raw.annotations.onset, [1., 2., 12., 21., 22., 31., 5])
    assert_array_equal(raw.annotations.duration, [.5, .5, .5, .5, .5, .5, 1.5])
    assert_array_equal(raw.annotations.description,
                       ['x', 'x', 'x', 'x', 'x', 'x', 'y'])

    # Test concatenating annotations with and without orig_time.
    raw = read_raw_fif(fif_fname)
    last_time = raw.last_samp / raw.info['sfreq']
    raw2 = raw.copy()
    raw.annotations = Annotations([45.], [3], 'test', raw.info['meas_date'])
    raw2.annotations = Annotations([2.], [3], 'BAD', None)
    raw = concatenate_raws([raw, raw2])
    raw.annotations.delete(-1)  # remove boundary annotations
    raw.annotations.delete(-1)
    assert_array_almost_equal(raw.annotations.onset, [45., 2. + last_time],
                              decimal=2)

    # Test IO
    tempdir = _TempDir()
    fname = op.join(tempdir, 'test-annot.fif')
    raw.annotations.save(fname)
    annot_read = read_annotations(fname)
    for attr in ('onset', 'duration', 'orig_time'):
        assert_allclose(getattr(annot_read, attr),
                        getattr(raw.annotations, attr))
    assert_array_equal(annot_read.description, raw.annotations.description)
예제 #18
0
def test_crop():
    """Test cropping with annotations."""
    raw = read_raw_fif(fif_fname)
    events = mne.find_events(raw)
    onset = events[events[:, 2] == 1, 0] / raw.info['sfreq']
    duration = np.full_like(onset, 0.5)
    description = ['bad %d' % k for k in range(len(onset))]
    raw.annotations = mne.Annotations(onset, duration, description,
                                      orig_time=raw.info['meas_date'])

    split_time = raw.times[-1] / 2. + 2.
    split_idx = len(onset) // 2 + 1
    raw_cropped_left = raw.copy().crop(0., split_time - 1. / raw.info['sfreq'])
    assert_array_equal(raw_cropped_left.annotations.description,
                       raw.annotations.description[:split_idx])
    assert_allclose(raw_cropped_left.annotations.duration,
                    raw.annotations.duration[:split_idx])
    assert_allclose(raw_cropped_left.annotations.onset,
                    raw.annotations.onset[:split_idx])
    raw_cropped_right = raw.copy().crop(split_time, None)
    assert_array_equal(raw_cropped_right.annotations.description,
                       raw.annotations.description[split_idx:])
    assert_allclose(raw_cropped_right.annotations.duration,
                    raw.annotations.duration[split_idx:])
    assert_allclose(raw_cropped_right.annotations.onset,
                    raw.annotations.onset[split_idx:])
    raw_concat = mne.concatenate_raws([raw_cropped_left, raw_cropped_right],
                                      verbose='debug')
    assert_allclose(raw_concat.times, raw.times)
    assert_allclose(raw_concat[:][0], raw[:][0], atol=1e-20)
    # Get rid of the boundary events
    raw_concat.annotations.delete(-1)
    raw_concat.annotations.delete(-1)
    # Ensure we annotations survive round-trip crop->concat
    assert_array_equal(raw_concat.annotations.description,
                       raw.annotations.description)
    for attr in ('onset', 'duration'):
        assert_allclose(getattr(raw_concat.annotations, attr),
                        getattr(raw.annotations, attr),
                        err_msg='Failed for %s:' % (attr,))

    raw.annotations = None  # undo

    # Test concatenating annotations with and without orig_time.
    last_time = raw.last_samp / raw.info['sfreq']
    raw2 = raw.copy()
    raw.annotations = Annotations([45.], [3], 'test', raw.info['meas_date'])
    raw2.annotations = Annotations([2.], [3], 'BAD', None)
    raw = concatenate_raws([raw, raw2])
    raw.annotations.delete(-1)  # remove boundary annotations
    raw.annotations.delete(-1)
    assert_array_almost_equal(raw.annotations.onset, [45., 2. + last_time],
                              decimal=2)

    # Test IO
    tempdir = _TempDir()
    fname = op.join(tempdir, 'test-annot.fif')
    raw.annotations.save(fname)
    annot_read = read_annotations(fname)
    for attr in ('onset', 'duration', 'orig_time'):
        assert_allclose(getattr(annot_read, attr),
                        getattr(raw.annotations, attr))
    assert_array_equal(annot_read.description, raw.annotations.description)
    annot = Annotations((), (), ())
    annot.save(fname)
    pytest.raises(IOError, read_annotations, fif_fname)  # none in old raw
    annot = read_annotations(fname)
    assert isinstance(annot, Annotations)
    assert len(annot) == 0
    # Test that empty annotations can be saved with an object
    fname = op.join(tempdir, 'test_raw.fif')
    raw.annotations = annot
    raw.save(fname)
    raw_read = read_raw_fif(fname)
    assert isinstance(raw_read.annotations, Annotations)
    assert len(raw_read.annotations) == 0
    raw.annotations = None
    raw.save(fname, overwrite=True)
    raw_read = read_raw_fif(fname)
    assert raw_read.annotations is None
예제 #19
0
def annotate_motion_artifacts(raw,
                              pos,
                              disp_thr=0.01,
                              velo_thr=0.03,
                              gof_thr=0.99,
                              return_stat_raw=False):
    """Find and annotate periods of high HPI velocity and high HPI distance."""
    annot = Annotations([], [], [])

    info = raw.info
    # grab initial cHPI locations
    # point sorted in hpi_results are in mne device coords
    chpi_locs_dev = sorted([d for d in info['hpi_results'][-1]['dig_points']],
                           key=lambda x: x['ident'])
    chpi_locs_dev = np.array([d['r'] for d in chpi_locs_dev])
    # chpi_locs_dev[0] -> LPA
    # chpi_locs_dev[1] -> NASION
    # chpi_locs_dev[2] -> RPA
    chpi_static_head = apply_trans(info['dev_head_t'], chpi_locs_dev)

    time = pos[:, 0]
    n_hpi = chpi_static_head.shape[0]
    quats = pos[:, 1:7]
    chpi_moving_head = np.array(
        [_apply_quat(quat, chpi_locs_dev, move=True) for quat in quats])

    # compute displacements
    hpi_disp = chpi_moving_head - np.tile(chpi_static_head, (len(time), 1, 1))
    hpi_disp = np.sqrt((hpi_disp**2).sum(axis=-1))
    # compute velocities
    hpi_velo = chpi_moving_head[1:, :, :] - chpi_moving_head[:-1, :, :]
    hpi_velo = np.sqrt((hpi_velo**2).sum(axis=-1))
    hpi_velo /= np.tile(time[1:] - time[:-1], (n_hpi, 1)).transpose()
    hpi_velo = np.concatenate((np.zeros((1, n_hpi)), hpi_velo), axis=0)

    if disp_thr is not None:
        art_mask = hpi_disp > disp_thr
        annot += _annotations_from_mask(time, art_mask,
                                        'Bad-motion-dist>%0.3f' % disp_thr)
    if velo_thr is not None:
        art_mask = hpi_velo > velo_thr
        annot += _annotations_from_mask(time, art_mask,
                                        'Bad-motion-velo>%0.3f' % velo_thr)

    if gof_thr is not None:
        art_mask = pos[:, 7] <= gof_thr
        annot += _annotations_from_mask(time, art_mask,
                                        'Bad-chpi_gof>%0.3f' % gof_thr)

    tmp = 1000 * hpi_disp.max(axis=0)
    _fmt = '\tHPI00 - %0.1f'
    for i in range(1, n_hpi):
        _fmt += '\n\tHPI%02d' % (i) + ' - %0.1f'
    logger.info('CHPI MAX Displacments (mm):')
    logger.info(_fmt % tuple(tmp))
    tmp = 1000 * hpi_velo.max(axis=0)
    logger.info('CHPI Velocity Displacments (mm/sec):')
    logger.info(_fmt % tuple(tmp))

    raw_hpi = None
    if return_stat_raw:
        n_times = len(raw.times)
        # build full time data arrays
        start_idx = raw.time_as_index(time, use_rounding=True)
        end_idx = raw.time_as_index(np.append(time[1:], raw.times[-1]),
                                    use_rounding=True)
        data_pos = np.zeros((2 * n_hpi, n_times))
        for t_0, t_1, disp_val, velo_val in zip(start_idx, end_idx, hpi_disp,
                                                hpi_velo):
            t_slice = slice(t_0, t_1)
            data_pos[:n_hpi, t_slice] = np.tile(disp_val, (t_1 - t_0, 1)).T
            data_pos[n_hpi:, t_slice] = np.tile(velo_val, (t_1 - t_0, 1)).T

        ch_names = []
        ch_names_ = []
        for i in range(n_hpi):
            ch_names.append('HPI%02d_disp_pos' % i)
            ch_names_.append('HPI%02d_velo_pos' % i)
        ch_names.extend(ch_names_)

        # build raw object!
        info = create_info(ch_names=ch_names,
                           ch_types=np.repeat('misc', len(ch_names)),
                           sfreq=raw.info['sfreq'])
        raw_hpi = RawArray(data_pos, info)

    return annot, raw_hpi