def test_lcmv_fieldtrip():
    """Test LCMV vs fieldtrip output."""
    evoked, data_cov, fwd = _get_bf_data()

    # beamformer types to be tested: unit-gain (vector and scalar) and
    # unit-noise-gain
    bf_types = ['ug_vec', 'ug_scal', 'ung']
    weight_norms = [None, None, 'unit-noise-gain']
    pick_oris = [None, 'max-power', 'max-power']

    for bf_type, weight_norm, pick_ori in zip(bf_types, weight_norms,
                                              pick_oris):

        # run the MNE-Python beamformer
        filters = make_lcmv(evoked.info,
                            fwd,
                            data_cov=data_cov,
                            noise_cov=None,
                            pick_ori=pick_ori,
                            reg=0.05,
                            weight_norm=weight_norm)
        stc_mne = apply_lcmv(evoked, filters)
        # take the absolute value, since orientation is arbitrary by 180 degr.
        stc_mne.data[:, :] = np.abs(stc_mne.data)

        # load the FieldTrip output
        ft_fname = op.join(ft_data_path, 'ft_source_' + bf_type + '-vol.stc')
        stc_ft = mne.read_source_estimate(ft_fname)

        # calculate the Pearson correlation between the source solutions:
        pearson = np.corrcoef(np.concatenate(stc_mne.data),
                              np.concatenate(stc_ft.data))

        assert pearson[0, 1] >= 0.99
Exemple #2
0
def test_lcmv_fieldtrip(_get_bf_data, bf_type, weight_norm, pick_ori, pwr):
    """Test LCMV vs fieldtrip output."""
    evoked, data_cov, fwd = _get_bf_data

    # run the MNE-Python beamformer
    filters = make_lcmv(evoked.info,
                        fwd,
                        data_cov=data_cov,
                        noise_cov=None,
                        pick_ori=pick_ori,
                        reg=0.05,
                        weight_norm=weight_norm)
    if pwr is True:
        stc_mne = apply_lcmv_cov(data_cov, filters)
    else:
        stc_mne = apply_lcmv(evoked, filters)
        # take the absolute value, since orientation can be flipped
        stc_mne.data[:, :] = np.abs(stc_mne.data)

    # load the FieldTrip output
    ft_fname = op.join(ft_data_path, 'ft_source_' + bf_type + '-vol.stc')
    stc_ft = mne.read_source_estimate(ft_fname)

    # calculate the Pearson correlation between the source solutions:
    pearson = np.corrcoef(stc_mne.data.ravel(), stc_ft.data.ravel())[0, 1]
    assert pearson >= 0.99
Exemple #3
0
def run_lcmv_evoked(evoked, fwd, data_cov, reg, noise_cov=None,
                    pick_ori='max-power', weight_norm='nai'):
    """Run LCMV on average.

    Run weight-normalized LCMV beamformer on evoked data, will return an stc
    object.

    Parameters:
    -----------
    evoked : MNE evoked
        evoked data to source reconstruct.
    fwd : MNE forward model
        forward model.
    data_cov : MNE covariance estimate
        data covariance matrix.
    reg : float
        regularization parameter
    noise_cov : MNE covariance estimate
        noise covariance matrix, optional

    Returns
    -------
    stc : MNE stcs
        original output of apply_lcmv
    filters : dict
        spatial filter used in computation
    """
    filters = make_lcmv(evoked.info, fwd, data_cov=data_cov,
                        noise_cov=noise_cov, pick_ori=pick_ori, reg=reg,
                        weight_norm=weight_norm)

    # apply that filter to epochs
    stc = apply_lcmv(evoked, filters, max_ori_out='signed')

    return stc, filters
def test_lcmv_fieldtrip(_get_bf_data, bf_type, weight_norm, pick_ori, pwr):
    """Test LCMV vs fieldtrip output."""
    evoked, data_cov, fwd = _get_bf_data

    # run the MNE-Python beamformer
    filters = make_lcmv(evoked.info, fwd, data_cov=data_cov,
                        noise_cov=None, pick_ori=pick_ori, reg=0.05,
                        weight_norm=weight_norm)
    if pwr is True:
        stc_mne = apply_lcmv_cov(data_cov, filters)
    else:
        stc_mne = apply_lcmv(evoked, filters)
        # take the absolute value, since orientation can be flipped
        stc_mne.data[:, :] = np.abs(stc_mne.data)

    # load the FieldTrip output
    ft_fname = op.join(ft_data_path, 'ft_source_' + bf_type + '-vol.stc')
    stc_ft = mne.read_source_estimate(ft_fname)

    # calculate the Pearson correlation between the source solutions:
    pearson = np.corrcoef(stc_mne.data.ravel(), stc_ft.data.ravel())[0, 1]
    assert pearson >= 0.99
# matrix enables whitening of the data and forward solution. Source orientation
# is optimized by setting pick_ori to 'max-power'.
# weight_norm can also be set to 'unit-noise-gain'. Source orientation can also
# be 'normal' (but only when using a surface-based source space) or None,
# which computes a vector beamfomer. Note, however, that not all combinations
# of orientation selection and weight normalization are implemented yet.
filters = make_lcmv(evoked.info, forward, data_cov, reg=0.05,
                    noise_cov=noise_cov, pick_ori='max-power',
                    weight_norm='nai', rank=None)
print(filters)

# You can save these with:
# filters.save('filters-lcmv.h5')

# Apply this spatial filter to the evoked data.
stc = apply_lcmv(evoked, filters, max_ori_out='signed')

###############################################################################
# Plot source space activity:

# You can save result in stc files with:
# stc.save('lcmv-vol')

clim = dict(kind='value', pos_lims=[0.3, 0.6, 0.9])
stc.plot(src=forward['src'], subject='sample', subjects_dir=subjects_dir,
         clim=clim)

###############################################################################
# We can also visualize the activity on a "glass brain" (shown here with
# absolute values):
def test_make_lcmv(tmpdir):
    """Test LCMV with evoked data and single trials."""
    raw, epochs, evoked, data_cov, noise_cov, label, forward,\
        forward_surf_ori, forward_fixed, forward_vol = _get_data()

    for fwd in [forward, forward_vol]:
        filters = make_lcmv(evoked.info,
                            fwd,
                            data_cov,
                            reg=0.01,
                            noise_cov=noise_cov)
        stc = apply_lcmv(evoked, filters, max_ori_out='signed')
        stc.crop(0.02, None)

        stc_pow = np.sum(np.abs(stc.data), axis=1)
        idx = np.argmax(stc_pow)
        max_stc = stc.data[idx]
        tmax = stc.times[np.argmax(max_stc)]

        assert 0.09 < tmax < 0.12, tmax
        assert 0.9 < np.max(max_stc) < 3., np.max(max_stc)

        if fwd is forward:
            # Test picking normal orientation (surface source space only).
            filters = make_lcmv(evoked.info,
                                forward_surf_ori,
                                data_cov,
                                reg=0.01,
                                noise_cov=noise_cov,
                                pick_ori='normal',
                                weight_norm=None)
            stc_normal = apply_lcmv(evoked, filters, max_ori_out='signed')
            stc_normal.crop(0.02, None)

            stc_pow = np.sum(np.abs(stc_normal.data), axis=1)
            idx = np.argmax(stc_pow)
            max_stc = stc_normal.data[idx]
            tmax = stc_normal.times[np.argmax(max_stc)]

            assert 0.04 < tmax < 0.13, tmax
            assert 3e-7 < np.max(max_stc) < 5e-7, np.max(max_stc)

            # No weight normalization was applied, so the amplitude of normal
            # orientation results should always be smaller than free
            # orientation results.
            assert (np.abs(stc_normal.data) <= stc.data).all()

        # Test picking source orientation maximizing output source power
        filters = make_lcmv(evoked.info,
                            fwd,
                            data_cov,
                            reg=0.01,
                            noise_cov=noise_cov,
                            pick_ori='max-power')
        stc_max_power = apply_lcmv(evoked, filters, max_ori_out='signed')
        stc_max_power.crop(0.02, None)
        stc_pow = np.sum(np.abs(stc_max_power.data), axis=1)
        idx = np.argmax(stc_pow)
        max_stc = np.abs(stc_max_power.data[idx])
        tmax = stc.times[np.argmax(max_stc)]

        assert 0.08 < tmax < 0.12, tmax
        assert 0.8 < np.max(max_stc) < 3., np.max(max_stc)

        stc_max_power.data[:, :] = np.abs(stc_max_power.data)

        if fwd is forward:
            # Maximum output source power orientation results should be
            # similar to free orientation results in areas with channel
            # coverage
            label = mne.read_label(fname_label)
            mean_stc = stc.extract_label_time_course(label,
                                                     fwd['src'],
                                                     mode='mean')
            mean_stc_max_pow = \
                stc_max_power.extract_label_time_course(label, fwd['src'],
                                                        mode='mean')
            assert_array_less(np.abs(mean_stc - mean_stc_max_pow), 0.6)

        # Test NAI weight normalization:
        filters = make_lcmv(evoked.info,
                            fwd,
                            data_cov,
                            reg=0.01,
                            noise_cov=noise_cov,
                            pick_ori='max-power',
                            weight_norm='nai')
        stc_nai = apply_lcmv(evoked, filters, max_ori_out='signed')
        stc_nai.crop(0.02, None)

        # Test whether unit-noise-gain solution is a scaled version of NAI
        pearsoncorr = np.corrcoef(np.concatenate(np.abs(stc_nai.data)),
                                  np.concatenate(stc_max_power.data))
        assert_almost_equal(pearsoncorr[0, 1], 1.)

    # Test sphere head model with unit-noise gain beamformer and orientation
    # selection and rank reduction of the leadfield
    sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080)
    src = mne.setup_volume_source_space(subject=None,
                                        pos=15.,
                                        mri=None,
                                        sphere=(0.0, 0.0, 0.0, 80.0),
                                        bem=None,
                                        mindist=5.0,
                                        exclude=2.0)

    fwd_sphere = mne.make_forward_solution(evoked.info,
                                           trans=None,
                                           src=src,
                                           bem=sphere,
                                           eeg=False,
                                           meg=True)

    # Test that we get an error if not reducing rank
    with pytest.raises(ValueError):  # Singular matrix or complex spectrum
        make_lcmv(evoked.info,
                  fwd_sphere,
                  data_cov,
                  reg=0.1,
                  noise_cov=noise_cov,
                  weight_norm='unit-noise-gain',
                  pick_ori='max-power',
                  reduce_rank=False,
                  rank='full')

    # Now let's reduce it
    filters = make_lcmv(evoked.info,
                        fwd_sphere,
                        data_cov,
                        reg=0.1,
                        noise_cov=noise_cov,
                        weight_norm='unit-noise-gain',
                        pick_ori='max-power',
                        reduce_rank=True)
    stc_sphere = apply_lcmv(evoked, filters, max_ori_out='signed')
    stc_sphere = np.abs(stc_sphere)
    stc_sphere.crop(0.02, None)

    stc_pow = np.sum(stc_sphere.data, axis=1)
    idx = np.argmax(stc_pow)
    max_stc = stc_sphere.data[idx]
    tmax = stc_sphere.times[np.argmax(max_stc)]

    assert 0.08 < tmax < 0.15, tmax
    assert 0.4 < np.max(max_stc) < 2., np.max(max_stc)

    # Test if spatial filter contains src_type
    assert 'src_type' in filters

    # __repr__
    assert 'LCMV' in repr(filters)
    assert 'unknown subject' not in repr(filters)
    assert '484' in repr(filters)
    assert '20' in repr(filters)
    assert 'rank 17' in repr(filters)

    # I/O
    fname = op.join(str(tmpdir), 'filters.h5')
    with pytest.warns(RuntimeWarning, match='-lcmv.h5'):
        filters.save(fname)
    filters_read = read_beamformer(fname)
    assert isinstance(filters, Beamformer)
    assert isinstance(filters_read, Beamformer)
    # deal with object_diff strictness
    filters_read['rank'] = int(filters_read['rank'])
    filters['rank'] = int(filters['rank'])
    assert object_diff(filters, filters_read) == ''

    # Test if fixed forward operator is detected when picking normal or
    # max-power orientation
    pytest.raises(ValueError,
                  make_lcmv,
                  evoked.info,
                  forward_fixed,
                  data_cov,
                  reg=0.01,
                  noise_cov=noise_cov,
                  pick_ori='normal')
    pytest.raises(ValueError,
                  make_lcmv,
                  evoked.info,
                  forward_fixed,
                  data_cov,
                  reg=0.01,
                  noise_cov=noise_cov,
                  pick_ori='max-power')

    # Test if non-surface oriented forward operator is detected when picking
    # normal orientation
    pytest.raises(ValueError,
                  make_lcmv,
                  evoked.info,
                  forward,
                  data_cov,
                  reg=0.01,
                  noise_cov=noise_cov,
                  pick_ori='normal')

    # Test if volume forward operator is detected when picking normal
    # orientation
    pytest.raises(ValueError,
                  make_lcmv,
                  evoked.info,
                  forward_vol,
                  data_cov,
                  reg=0.01,
                  noise_cov=noise_cov,
                  pick_ori='normal')

    # Test if missing of noise covariance matrix is detected when more than
    # one channel type is present in the data
    pytest.raises(ValueError,
                  make_lcmv,
                  evoked.info,
                  forward_vol,
                  data_cov=data_cov,
                  reg=0.01,
                  noise_cov=None,
                  pick_ori='max-power')

    # Test if wrong channel selection is detected in application of filter
    evoked_ch = deepcopy(evoked)
    evoked_ch.pick_channels(evoked_ch.ch_names[1:])
    filters = make_lcmv(evoked.info,
                        forward_vol,
                        data_cov,
                        reg=0.01,
                        noise_cov=noise_cov)
    pytest.raises(ValueError,
                  apply_lcmv,
                  evoked_ch,
                  filters,
                  max_ori_out='signed')

    # Test if discrepancies in channel selection of data and fwd model are
    # handled correctly in apply_lcmv
    # make filter with data where first channel was removed
    filters = make_lcmv(evoked_ch.info,
                        forward_vol,
                        data_cov,
                        reg=0.01,
                        noise_cov=noise_cov)
    # applying that filter to the full data set should automatically exclude
    # this channel from the data
    # also test here that no warnings are thrown - implemented to check whether
    # src should not be None warning occurs
    with pytest.warns(None) as w:
        stc = apply_lcmv(evoked, filters, max_ori_out='signed')
    assert len(w) == 0
    # the result should be equal to applying this filter to a dataset without
    # this channel:
    stc_ch = apply_lcmv(evoked_ch, filters, max_ori_out='signed')
    assert_array_almost_equal(stc.data, stc_ch.data)

    # Test if non-matching SSP projection is detected in application of filter
    raw_proj = deepcopy(raw)
    raw_proj.del_proj()
    pytest.raises(ValueError,
                  apply_lcmv_raw,
                  raw_proj,
                  filters,
                  max_ori_out='signed')

    # Test if setting reduce_rank to True returns a NotImplementedError
    # when no orientation selection is done or pick_ori='normal'
    pytest.raises(NotImplementedError,
                  make_lcmv,
                  evoked.info,
                  forward_vol,
                  data_cov,
                  noise_cov=noise_cov,
                  pick_ori=None,
                  weight_norm='nai',
                  reduce_rank=True)
    pytest.raises(NotImplementedError,
                  make_lcmv,
                  evoked.info,
                  forward_surf_ori,
                  data_cov,
                  noise_cov=noise_cov,
                  pick_ori='normal',
                  weight_norm='nai',
                  reduce_rank=True)

    # Test if spatial filter contains src_type
    assert 'src_type' in filters

    # check whether a filters object without src_type throws expected warning
    del filters['src_type']  # emulate 0.16 behaviour to cause warning
    with pytest.warns(RuntimeWarning,
                      match='spatial filter does not contain '
                      'src_type'):
        apply_lcmv(evoked, filters, max_ori_out='signed')

    # Now test single trial using fixed orientation forward solution
    # so we can compare it to the evoked solution
    filters = make_lcmv(epochs.info,
                        forward_fixed,
                        data_cov,
                        reg=0.01,
                        noise_cov=noise_cov)
    stcs = apply_lcmv_epochs(epochs, filters, max_ori_out='signed')
    stcs_ = apply_lcmv_epochs(epochs,
                              filters,
                              return_generator=True,
                              max_ori_out='signed')
    assert_array_equal(stcs[0].data, advance_iterator(stcs_).data)

    epochs.drop_bad()
    assert (len(epochs.events) == len(stcs))

    # average the single trial estimates
    stc_avg = np.zeros_like(stcs[0].data)
    for this_stc in stcs:
        stc_avg += this_stc.data
    stc_avg /= len(stcs)

    # compare it to the solution using evoked with fixed orientation
    filters = make_lcmv(evoked.info,
                        forward_fixed,
                        data_cov,
                        reg=0.01,
                        noise_cov=noise_cov)
    stc_fixed = apply_lcmv(evoked, filters, max_ori_out='signed')
    assert_array_almost_equal(stc_avg, stc_fixed.data)

    # use a label so we have few source vertices and delayed computation is
    # not used
    filters = make_lcmv(epochs.info,
                        forward_fixed,
                        data_cov,
                        reg=0.01,
                        noise_cov=noise_cov,
                        label=label)
    stcs_label = apply_lcmv_epochs(epochs, filters, max_ori_out='signed')

    assert_array_almost_equal(stcs_label[0].data, stcs[0].in_label(label).data)

    # Test condition where the filters weights are zero. There should not be
    # any divide-by-zero errors
    zero_cov = data_cov.copy()
    zero_cov['data'][:] = 0
    filters = make_lcmv(epochs.info,
                        forward_fixed,
                        zero_cov,
                        reg=0.01,
                        noise_cov=noise_cov)
    assert_array_equal(filters['weights'], 0)
Exemple #7
0
            evoked = evoked_joint
        else:
            raise ValueError('Invalid sensor type: %s', sensor_type)

        filters = make_lcmv(evoked.info,
                            fwd,
                            data_cov,
                            reg=reg,
                            pick_ori=pick_ori,
                            weight_norm=weight_norm,
                            inversion=inversion,
                            depth=1. if normalize_fwd else None,
                            noise_cov=noise_cov if use_noise_cov else None,
                            reduce_rank=reduce_rank)

        stc_est = apply_lcmv(evoked, filters)

        if pick_ori == 'vector':
            # Combine vector time source
            if project_pca:
                stc_proj, _ = stc_est.project('pca', fwd['src'])
            else:
                stc_proj = stc_est.magnitude()
            stc_est_power = (stc_proj**2).sum()
            peak_vertex, peak_time = stc_est_power.get_peak(vert_as_index=True,
                                                            time_as_index=True)
            estimated_time_course = np.abs(stc_est.data[peak_vertex])
        else:
            stc_est_power = (stc_est**2).sum()
            peak_vertex, peak_time = stc_est_power.get_peak(vert_as_index=True,
                                                            time_as_index=True)
Exemple #8
0
def test_lcmv():
    """Test LCMV with evoked data and single trials."""
    raw, epochs, evoked, data_cov, noise_cov, label, forward,\
        forward_surf_ori, forward_fixed, forward_vol = _get_data()

    for fwd in [forward, forward_vol]:
        filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01,
                            noise_cov=noise_cov)
        stc = apply_lcmv(evoked, filters, max_ori_out='signed')
        stc.crop(0.02, None)

        stc_pow = np.sum(np.abs(stc.data), axis=1)
        idx = np.argmax(stc_pow)
        max_stc = stc.data[idx]
        tmax = stc.times[np.argmax(max_stc)]

        assert 0.09 < tmax < 0.12, tmax
        assert 0.9 < np.max(max_stc) < 3., np.max(max_stc)

        if fwd is forward:
            # Test picking normal orientation (surface source space only)
            filters = make_lcmv(evoked.info, forward_surf_ori, data_cov,
                                reg=0.01, noise_cov=noise_cov,
                                pick_ori='normal')
            stc_normal = apply_lcmv(evoked, filters, max_ori_out='signed')
            stc_normal.crop(0.02, None)

            stc_pow = np.sum(np.abs(stc_normal.data), axis=1)
            idx = np.argmax(stc_pow)
            max_stc = stc_normal.data[idx]
            tmax = stc_normal.times[np.argmax(max_stc)]

            assert 0.04 < tmax < 0.12, tmax
            assert 0.4 < np.max(max_stc) < 2., np.max(max_stc)

            # The amplitude of normal orientation results should always be
            # smaller than free orientation results
            assert (np.abs(stc_normal.data) <= stc.data).all()

        # Test picking source orientation maximizing output source power
        filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01,
                            noise_cov=noise_cov, pick_ori='max-power')
        stc_max_power = apply_lcmv(evoked, filters, max_ori_out='signed')
        stc_max_power.crop(0.02, None)
        stc_pow = np.sum(np.abs(stc_max_power.data), axis=1)
        idx = np.argmax(stc_pow)
        max_stc = np.abs(stc_max_power.data[idx])
        tmax = stc.times[np.argmax(max_stc)]

        assert 0.08 < tmax < 0.12, tmax
        assert 0.8 < np.max(max_stc) < 3., np.max(max_stc)

        stc_max_power.data[:, :] = np.abs(stc_max_power.data)

        if fwd is forward:
            # Maximum output source power orientation results should be
            # similar to free orientation results in areas with channel
            # coverage
            label = mne.read_label(fname_label)
            mean_stc = stc.extract_label_time_course(label, fwd['src'],
                                                     mode='mean')
            mean_stc_max_pow = \
                stc_max_power.extract_label_time_course(label, fwd['src'],
                                                        mode='mean')
            assert_array_less(np.abs(mean_stc - mean_stc_max_pow), 0.6)

        # Test NAI weight normalization:
        filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01,
                            noise_cov=noise_cov, pick_ori='max-power',
                            weight_norm='nai')
        stc_nai = apply_lcmv(evoked, filters, max_ori_out='signed')
        stc_nai.crop(0.02, None)

        # Test whether unit-noise-gain solution is a scaled version of NAI
        pearsoncorr = np.corrcoef(np.concatenate(np.abs(stc_nai.data)),
                                  np.concatenate(stc_max_power.data))
        assert_almost_equal(pearsoncorr[0, 1], 1.)

    # Test sphere head model with unit-noise gain beamformer and orientation
    # selection and rank reduction of the leadfield
    sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080)
    src = mne.setup_volume_source_space(subject=None, pos=15., mri=None,
                                        sphere=(0.0, 0.0, 0.0, 80.0),
                                        bem=None, mindist=5.0, exclude=2.0)

    fwd_sphere = mne.make_forward_solution(evoked.info, trans=None, src=src,
                                           bem=sphere, eeg=False, meg=True)

    # Test that we get an error if not reducing rank
    pytest.raises(ValueError, make_lcmv, evoked.info, fwd_sphere, data_cov,
                  reg=0.1, noise_cov=noise_cov, weight_norm='unit-noise-gain',
                  pick_ori='max-power', reduce_rank=False)

    # Now let's reduce it
    filters = make_lcmv(evoked.info, fwd_sphere, data_cov, reg=0.1,
                        noise_cov=noise_cov, weight_norm='unit-noise-gain',
                        pick_ori='max-power', reduce_rank=True)
    stc_sphere = apply_lcmv(evoked, filters, max_ori_out='signed')
    stc_sphere = np.abs(stc_sphere)
    stc_sphere.crop(0.02, None)

    stc_pow = np.sum(stc_sphere.data, axis=1)
    idx = np.argmax(stc_pow)
    max_stc = stc_sphere.data[idx]
    tmax = stc_sphere.times[np.argmax(max_stc)]

    assert 0.08 < tmax < 0.15, tmax
    assert 0.4 < np.max(max_stc) < 2., np.max(max_stc)

    # Test if spatial filter contains src_type
    assert 'src_type' in filters

    # Test if fixed forward operator is detected when picking normal or
    # max-power orientation
    pytest.raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov,
                  reg=0.01, noise_cov=noise_cov, pick_ori='normal')
    pytest.raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov,
                  reg=0.01, noise_cov=noise_cov, pick_ori='max-power')

    # Test if non-surface oriented forward operator is detected when picking
    # normal orientation
    pytest.raises(ValueError, make_lcmv, evoked.info, forward, data_cov,
                  reg=0.01, noise_cov=noise_cov, pick_ori='normal')

    # Test if volume forward operator is detected when picking normal
    # orientation
    pytest.raises(ValueError, make_lcmv, evoked.info, forward_vol, data_cov,
                  reg=0.01, noise_cov=noise_cov, pick_ori='normal')

    # Test if missing of noise covariance matrix is detected when more than
    # one channel type is present in the data
    pytest.raises(ValueError, make_lcmv, evoked.info, forward_vol,
                  data_cov=data_cov, reg=0.01, noise_cov=None,
                  pick_ori='max-power')

    # Test if not-yet-implemented orientation selections raise error with
    # neural activity index
    pytest.raises(NotImplementedError, make_lcmv, evoked.info,
                  forward_surf_ori, data_cov, reg=0.01, noise_cov=noise_cov,
                  pick_ori='normal', weight_norm='nai')
    pytest.raises(NotImplementedError, make_lcmv, evoked.info, forward_vol,
                  data_cov, reg=0.01, noise_cov=noise_cov, pick_ori=None,
                  weight_norm='nai')

    # Test if no weight-normalization and max-power source orientation throws
    # an error
    pytest.raises(NotImplementedError, make_lcmv, evoked.info, forward_vol,
                  data_cov, reg=0.01, noise_cov=noise_cov,
                  pick_ori='max-power', weight_norm=None)

    # Test if wrong channel selection is detected in application of filter
    evoked_ch = deepcopy(evoked)
    evoked_ch.pick_channels(evoked_ch.ch_names[1:])
    filters = make_lcmv(evoked.info, forward_vol, data_cov, reg=0.01,
                        noise_cov=noise_cov)
    pytest.raises(ValueError, apply_lcmv, evoked_ch, filters,
                  max_ori_out='signed')

    # Test if discrepancies in channel selection of data and fwd model are
    # handled correctly in apply_lcmv
    # make filter with data where first channel was removed
    filters = make_lcmv(evoked_ch.info, forward_vol, data_cov, reg=0.01,
                        noise_cov=noise_cov)
    # applying that filter to the full data set should automatically exclude
    # this channel from the data
    # also test here that no warnings are thrown - implemented to check whether
    # src should not be None warning occurs
    with pytest.warns(None) as w:
        stc = apply_lcmv(evoked, filters, max_ori_out='signed')
    assert len(w) == 0
    # the result should be equal to applying this filter to a dataset without
    # this channel:
    stc_ch = apply_lcmv(evoked_ch, filters, max_ori_out='signed')
    assert_array_almost_equal(stc.data, stc_ch.data)

    # Test if non-matching SSP projection is detected in application of filter
    raw_proj = deepcopy(raw)
    raw_proj.del_proj()
    pytest.raises(ValueError, apply_lcmv_raw, raw_proj, filters,
                  max_ori_out='signed')

    # Test if setting reduce_rank to True returns a NotImplementedError
    # when no orientation selection is done or pick_ori='normal'
    pytest.raises(NotImplementedError, make_lcmv, evoked.info, forward_vol,
                  data_cov, noise_cov=noise_cov, pick_ori=None,
                  weight_norm='nai', reduce_rank=True)
    pytest.raises(NotImplementedError, make_lcmv, evoked.info,
                  forward_surf_ori, data_cov, noise_cov=noise_cov,
                  pick_ori='normal', weight_norm='nai', reduce_rank=True)

    # Test if spatial filter contains src_type
    assert 'src_type' in filters

    # check whether a filters object without src_type throws expected warning
    del filters['src_type']  # emulate 0.16 behaviour to cause warning
    with pytest.warns(RuntimeWarning, match='spatial filter does not contain '
                      'src_type'):
        apply_lcmv(evoked, filters, max_ori_out='signed')

    # Now test single trial using fixed orientation forward solution
    # so we can compare it to the evoked solution
    filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01,
                        noise_cov=noise_cov)
    stcs = apply_lcmv_epochs(epochs, filters, max_ori_out='signed')
    stcs_ = apply_lcmv_epochs(epochs, filters, return_generator=True,
                              max_ori_out='signed')
    assert_array_equal(stcs[0].data, advance_iterator(stcs_).data)

    epochs.drop_bad()
    assert (len(epochs.events) == len(stcs))

    # average the single trial estimates
    stc_avg = np.zeros_like(stcs[0].data)
    for this_stc in stcs:
        stc_avg += this_stc.data
    stc_avg /= len(stcs)

    # compare it to the solution using evoked with fixed orientation
    filters = make_lcmv(evoked.info, forward_fixed, data_cov, reg=0.01,
                        noise_cov=noise_cov)
    stc_fixed = apply_lcmv(evoked, filters, max_ori_out='signed')
    assert_array_almost_equal(stc_avg, stc_fixed.data)

    # use a label so we have few source vertices and delayed computation is
    # not used
    filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01,
                        noise_cov=noise_cov, label=label)
    stcs_label = apply_lcmv_epochs(epochs, filters, max_ori_out='signed')

    assert_array_almost_equal(stcs_label[0].data, stcs[0].in_label(label).data)
Exemple #9
0
def test_lcmv_vector():
    """Test vector LCMV solutions."""
    info = mne.io.read_raw_fif(fname_raw).info
    # For speed and for rank-deficiency calculation simplicity,
    # just use grads:
    info = mne.pick_info(info, mne.pick_types(info, meg='grad', exclude=()))
    info.update(bads=[], projs=[])
    forward = mne.read_forward_solution(fname_fwd)
    forward = mne.pick_channels_forward(forward, info['ch_names'])
    vertices = [s['vertno'][::100] for s in forward['src']]
    n_vertices = sum(len(v) for v in vertices)
    assert 5 < n_vertices < 20
    amplitude = 100e-9
    stc = mne.SourceEstimate(amplitude * np.eye(n_vertices), vertices,
                             0, 1. / info['sfreq'])
    forward_sim = mne.convert_forward_solution(forward, force_fixed=True,
                                               use_cps=True, copy=True)
    forward_sim = mne.forward.restrict_forward_to_stc(forward_sim, stc)
    noise_cov = mne.make_ad_hoc_cov(info)
    noise_cov.update(data=np.diag(noise_cov['data']), diag=False)
    evoked = simulate_evoked(forward_sim, stc, info, noise_cov, nave=1)
    source_nn = forward_sim['source_nn']
    source_rr = forward_sim['source_rr']
    # Figure out our indices
    mask = np.concatenate([np.in1d(s['vertno'], v)
                           for s, v in zip(forward['src'], vertices)])
    mapping = np.where(mask)[0]
    assert_array_equal(source_rr, forward['source_rr'][mapping])
    # Don't check NN because we didn't rotate to surf ori
    del forward_sim

    #
    # Let's do minimum norm as a sanity check (dipole_fit is slower)
    #
    inv = make_inverse_operator(info, forward, noise_cov, loose=1.)
    stc_vector_mne = apply_inverse(evoked, inv, pick_ori='vector')
    mne_ori = stc_vector_mne.data[mapping, :, np.arange(n_vertices)]
    mne_ori /= np.linalg.norm(mne_ori, axis=-1)[:, np.newaxis]
    mne_angles = np.rad2deg(np.arccos(np.sum(mne_ori * source_nn, axis=-1)))
    assert np.mean(mne_angles) < 35

    #
    # Now let's do LCMV
    #
    data_cov = mne.make_ad_hoc_cov(info)  # just a stub for later
    with pytest.raises(ValueError, match='pick_ori must be one of'):
        make_lcmv(info, forward, data_cov, 0.05, noise_cov, pick_ori='bad')
    lcmv_ori = list()
    for ti in range(n_vertices):
        this_evoked = evoked.copy().crop(evoked.times[ti], evoked.times[ti])
        data_cov['data'] = (np.outer(this_evoked.data, this_evoked.data) +
                            noise_cov['data'])
        vals = linalg.svdvals(data_cov['data'])
        assert vals[0] / vals[-1] < 1e5  # not rank deficient
        filters = make_lcmv(info, forward, data_cov, 0.05, noise_cov)
        filters_vector = make_lcmv(info, forward, data_cov, 0.05, noise_cov,
                                   pick_ori='vector')
        stc = apply_lcmv(this_evoked, filters)
        assert isinstance(stc, mne.SourceEstimate)
        stc_vector = apply_lcmv(this_evoked, filters_vector)
        assert isinstance(stc_vector, mne.VectorSourceEstimate)
        assert_allclose(stc.data, stc_vector.magnitude().data)
        # Check the orientation by pooling across some neighbors, as LCMV can
        # have some "holes" at the points of interest
        idx = np.where(cdist(forward['source_rr'], source_rr[[ti]]) < 0.02)[0]
        lcmv_ori.append(np.mean(stc_vector.data[idx, :, 0], axis=0))
        lcmv_ori[-1] /= np.linalg.norm(lcmv_ori[-1])

    lcmv_angles = np.rad2deg(np.arccos(np.sum(lcmv_ori * source_nn, axis=-1)))
    assert np.mean(lcmv_angles) < 55
Exemple #10
0
            evoked = evoked_joint
        else:
            raise ValueError('Invalid sensor type: %s', sensor_type)

        filters = make_lcmv(evoked.info,
                            fwd_disc_true,
                            cov,
                            reg=reg,
                            pick_ori=pick_ori,
                            weight_norm=weight_norm,
                            inversion=inversion,
                            depth=1. if normalize_fwd else None,
                            noise_cov=noise_cov if use_noise_cov else None,
                            reduce_rank=reduce_rank)

        stc_est = apply_lcmv(evoked, filters).crop(0.001, 1)

        # Estimated source location is at peak power
        if pick_ori == 'vector':
            stc_est_power = (stc_est.magnitude()**2).sum().sqrt()
        else:
            stc_est_power = (stc_est**2).sum().sqrt()
        peak_vertex, _ = stc_est_power.get_peak(vert_as_index=True)

        # Compute distance between true and estimated source locations
        pos_est = fwd_disc_man['source_rr'][peak_vertex]
        pos_true = fwd_disc_man['source_rr'][config.vertex]
        dist = np.linalg.norm(pos_est - pos_true)

        # Ratio between estimated peak activity and all estimated activity.
        focality_score = stc_est_power.data[peak_vertex,
src = forward['src']
del forward

# %%
# Apply the spatial filter
# ------------------------
# The spatial filter can be applied to different data types: raw, epochs,
# evoked data or the data covariance matrix to gain a static image of power.
# The function to apply the spatial filter to :class:`~mne.Evoked` data is
# :func:`~mne.beamformer.apply_lcmv` which is
# what we will use here. The other functions are
# :func:`~mne.beamformer.apply_lcmv_raw`,
# :func:`~mne.beamformer.apply_lcmv_epochs`, and
# :func:`~mne.beamformer.apply_lcmv_cov`.

stc = apply_lcmv(evoked, filters)
stc_vec = apply_lcmv(evoked, filters_vec)
del filters, filters_vec

# %%
# Visualize the reconstructed source activity
# -------------------------------------------
# We can visualize the source estimate in different ways, e.g. as a volume
# rendering, an overlay onto the MRI, or as an overlay onto a glass brain.
#
# The plots for the scalar beamformer show brain activity in the right temporal
# lobe around 100 ms post stimulus. This is expected given the left-ear
# auditory stimulation of the experiment.

lims = [0.3, 0.45, 0.6]
kwargs = dict(src=src, subject='sample', subjects_dir=subjects_dir,
                                  mindist=5.0, n_jobs=2)

    # compute LCMV spatial filters
    filters_a = make_lcmv(evoked_a.info,
                          fwd_a, data_cov_a, reg=0.05,
                          noise_cov=noise_cov_a, pick_ori='max-power',
                          weight_norm='nai', rank=None)
    filters_b = make_lcmv(evoked_b.info, fwd_b, data_cov_b, reg=0.05,
                          noise_cov=noise_cov_b, pick_ori='max-power',
                          weight_norm='nai', rank=None)

    # delete forward solutions to free memory space
    del fwd_a, fwd_b

    # apply the spacial filters to the ERPs
    stc_a = apply_lcmv(evoked_a, filters_a, max_ori_out='signed')
    stc_b = apply_lcmv(evoked_b, filters_b, max_ori_out='signed')

    # store results in list
    stcs_a.append(stc_a)
    stcs_b.append(stc_b)

###############################################################################
# 2) save results

# create dictionary containing LCMV beamforming results
stcs = dict()
stcs['cue_a'] = stcs_a
stcs['cue_b'] = stcs_b

# save to disk