示例#1
0
def _cov_as_csd(cov, info):
    rng = np.random.RandomState(0)
    assert cov['data'].ndim == 2
    assert len(cov['data']) == len(cov['names'])
    # we need to make this have at least some complex structure
    data = cov['data'] + 1e-1 * _rand_csd(rng, info)
    assert data.dtype == np.complex128
    return CrossSpectralDensity(_sym_mat_to_vector(data), cov['names'], 0., 16)
示例#2
0
def _make_csd():
    """Make a simple CrossSpectralDensity object."""
    frequencies = [1., 2., 3., 4.]
    n_freqs = len(frequencies)
    names = ['CH1', 'CH2', 'CH3']
    tmin, tmax = (0., 1.)
    data = np.arange(6. * n_freqs).reshape(n_freqs, 6).T
    return CrossSpectralDensity(data, names, frequencies, 1, tmin, tmax)
示例#3
0
def test_plot_csd():
    """Test plotting of CSD matrices."""
    csd = CrossSpectralDensity([1, 2, 3], ['CH1', 'CH2'],
                               frequencies=[(10, 20)], n_fft=1,
                               tmin=0, tmax=1,)
    plot_csd(csd, mode='csd')  # Plot cross-spectral density
    plot_csd(csd, mode='coh')  # Plot coherence
    plt.close('all')
示例#4
0
def _make_rand_csd(info, csd):
    rng = np.random.RandomState(0)
    data = _rand_csd(rng, info)
    # now we need to have the same null space as the data csd
    s, u = np.linalg.eigh(csd.get_data(csd.frequencies[0]))
    mask = np.abs(s) >= s[-1] * 1e-7
    rank = mask.sum()
    assert rank == len(data) == len(info['ch_names'])
    noise_csd = CrossSpectralDensity(
        _sym_mat_to_vector(data), info['ch_names'], 0., csd.n_fft)
    return noise_csd, rank
示例#5
0
def test_csd():
    """Test constructing a CrossSpectralDensity."""
    csd = CrossSpectralDensity([1, 2, 3], ['CH1', 'CH2'], frequencies=1,
                               n_fft=1, tmin=0, tmax=1)
    assert_array_equal(csd._data, [[1], [2], [3]])  # Conversion to 2D array
    assert_array_equal(csd.frequencies, [1])  # Conversion to 1D array

    # Channels don't match
    raises(ValueError, CrossSpectralDensity, [1, 2, 3],
           ['CH1', 'CH2', 'Too many!'], tmin=0, tmax=1, frequencies=1, n_fft=1)
    raises(ValueError, CrossSpectralDensity, [1, 2, 3], ['too little'],
           tmin=0, tmax=1, frequencies=1, n_fft=1)

    # Frequencies don't match
    raises(ValueError, CrossSpectralDensity,
           [[1, 2], [3, 4], [5, 6]], ['CH1', 'CH2'],
           tmin=0, tmax=1, frequencies=1, n_fft=1)

    # Invalid dims
    raises(ValueError, CrossSpectralDensity, [[[1]]], ['CH1'], frequencies=1,
           n_fft=1, tmin=0, tmax=1)
示例#6
0
def test_make_dics(tmpdir, _load_forward, idx, whiten):
    """Test making DICS beamformer filters."""
    # We only test proper handling of parameters here. Testing the results is
    # done in test_apply_dics_timeseries and test_apply_dics_csd.

    fwd_free, fwd_surf, fwd_fixed, fwd_vol = _load_forward
    epochs, _, csd, _, label, vertices, source_ind = \
        _simulate_data(fwd_fixed, idx)
    with pytest.raises(ValueError, match='several sensor types'):
        make_dics(epochs.info, fwd_surf, csd, label=label, pick_ori=None)
    if whiten:
        rng = np.random.RandomState(0)
        scales = mne.make_ad_hoc_cov(epochs.info).data
        n = scales.size
        # Some random complex correlation structure (with channel scalings)
        data = rng.randn(n, n) + 1j * rng.randn(n, n)
        data = data @ data.conj().T
        data *= scales
        data *= scales[:, np.newaxis]
        data.flat[::n + 1] = scales
        noise_csd = CrossSpectralDensity(_sym_mat_to_vector(data),
                                         epochs.ch_names, 0., csd.n_fft)
    else:
        noise_csd = None
        epochs.pick_types(meg='grad')

    with pytest.raises(ValueError, match="Invalid value for the 'pick_ori'"):
        make_dics(epochs.info,
                  fwd_fixed,
                  csd,
                  pick_ori="notexistent",
                  noise_csd=noise_csd)
    with pytest.raises(ValueError, match='rank, if str'):
        make_dics(epochs.info, fwd_fixed, csd, rank='foo', noise_csd=noise_csd)
    with pytest.raises(TypeError, match='rank must be'):
        make_dics(epochs.info, fwd_fixed, csd, rank=1., noise_csd=noise_csd)

    # Test if fixed forward operator is detected when picking normal
    # orientation
    with pytest.raises(ValueError, match='forward operator with free ori'):
        make_dics(epochs.info,
                  fwd_fixed,
                  csd,
                  pick_ori="normal",
                  noise_csd=noise_csd)

    # Test if non-surface oriented forward operator is detected when picking
    # normal orientation
    with pytest.raises(ValueError, match='oriented in surface coordinates'):
        make_dics(epochs.info,
                  fwd_free,
                  csd,
                  pick_ori="normal",
                  noise_csd=noise_csd)

    # Test if volume forward operator is detected when picking normal
    # orientation
    with pytest.raises(ValueError, match='oriented in surface coordinates'):
        make_dics(epochs.info,
                  fwd_vol,
                  csd,
                  pick_ori="normal",
                  noise_csd=noise_csd)

    # Test invalid combinations of parameters
    with pytest.raises(ValueError, match='reduce_rank cannot be used with'):
        make_dics(epochs.info,
                  fwd_free,
                  csd,
                  inversion='single',
                  reduce_rank=True,
                  noise_csd=noise_csd)
    # TODO: Restore this?
    # with pytest.raises(ValueError, match='not stable with depth'):
    #     make_dics(epochs.info, fwd_free, csd, weight_norm='unit-noise-gain',
    #               inversion='single', depth=None)

    # Sanity checks on the returned filters
    n_freq = len(csd.frequencies)
    vertices = np.intersect1d(label.vertices, fwd_free['src'][0]['vertno'])
    n_verts = len(vertices)
    n_orient = 3

    n_channels = len(epochs.ch_names)
    # Test return values
    weight_norm = 'unit-noise-gain'
    inversion = 'single'
    filters = make_dics(epochs.info,
                        fwd_surf,
                        csd,
                        label=label,
                        pick_ori=None,
                        weight_norm=weight_norm,
                        depth=None,
                        noise_csd=noise_csd,
                        inversion=inversion)
    assert filters['weights'].shape == (n_freq, n_verts * n_orient, n_channels)
    assert np.iscomplexobj(filters['weights'])
    assert filters['csd'].ch_names == epochs.ch_names
    assert isinstance(filters['csd'], CrossSpectralDensity)
    assert filters['ch_names'] == epochs.ch_names
    assert_array_equal(filters['proj'], np.eye(n_channels))
    assert_array_equal(filters['vertices'][0], vertices)
    assert_array_equal(filters['vertices'][1], [])  # Label was on the LH
    assert filters['subject'] == fwd_free['src']._subject
    assert filters['pick_ori'] is None
    assert filters['is_free_ori']
    assert filters['inversion'] == inversion
    assert filters['weight_norm'] == weight_norm
    assert 'DICS' in repr(filters)
    assert 'subject "sample"' in repr(filters)
    assert str(len(vertices)) in repr(filters)
    assert str(n_channels) in repr(filters)
    assert 'rank' not in repr(filters)
    _, noise_cov = _prepare_noise_csd(csd, noise_csd, real_filter=False)
    _, _, _, _, G, _, _, _ = _prepare_beamformer_input(epochs.info,
                                                       fwd_surf,
                                                       label,
                                                       'vector',
                                                       combine_xyz=False,
                                                       exp=None,
                                                       noise_cov=noise_cov)
    G.shape = (n_channels, n_verts, n_orient)
    G = G.transpose(1, 2, 0).conj()  # verts, orient, ch
    _assert_weight_norm(filters, G)

    inversion = 'matrix'
    filters = make_dics(epochs.info,
                        fwd_surf,
                        csd,
                        label=label,
                        pick_ori=None,
                        weight_norm=weight_norm,
                        depth=None,
                        noise_csd=noise_csd,
                        inversion=inversion)
    _assert_weight_norm(filters, G)

    weight_norm = 'unit-noise-gain-invariant'
    inversion = 'single'
    filters = make_dics(epochs.info,
                        fwd_surf,
                        csd,
                        label=label,
                        pick_ori=None,
                        weight_norm=weight_norm,
                        depth=None,
                        noise_csd=noise_csd,
                        inversion=inversion)
    _assert_weight_norm(filters, G)

    # Test picking orientations. Also test weight norming under these different
    # conditions.
    weight_norm = 'unit-noise-gain'
    filters = make_dics(epochs.info,
                        fwd_surf,
                        csd,
                        label=label,
                        pick_ori='normal',
                        weight_norm=weight_norm,
                        depth=None,
                        noise_csd=noise_csd,
                        inversion=inversion)
    n_orient = 1
    assert filters['weights'].shape == (n_freq, n_verts * n_orient, n_channels)
    assert not filters['is_free_ori']
    _assert_weight_norm(filters, G)

    filters = make_dics(epochs.info,
                        fwd_surf,
                        csd,
                        label=label,
                        pick_ori='max-power',
                        weight_norm=weight_norm,
                        depth=None,
                        noise_csd=noise_csd,
                        inversion=inversion)
    n_orient = 1
    assert filters['weights'].shape == (n_freq, n_verts * n_orient, n_channels)
    assert not filters['is_free_ori']
    _assert_weight_norm(filters, G)

    # From here on, only work on a single frequency
    csd = csd[0]

    # Test using a real-valued filter
    filters = make_dics(epochs.info,
                        fwd_surf,
                        csd,
                        label=label,
                        pick_ori='normal',
                        real_filter=True,
                        noise_csd=noise_csd)
    assert not np.iscomplexobj(filters['weights'])

    # Test forward normalization. When inversion='single', the power of a
    # unit-noise CSD should be 1, even without weight normalization.
    if not whiten:
        csd_noise = csd.copy()
        inds = np.triu_indices(csd.n_channels)
        # Using [:, :] syntax for in-place broadcasting
        csd_noise._data[:, :] = np.eye(csd.n_channels)[inds][:, np.newaxis]
        filters = make_dics(epochs.info,
                            fwd_surf,
                            csd_noise,
                            label=label,
                            weight_norm=None,
                            depth=1.,
                            noise_csd=noise_csd,
                            inversion='single')
        w = filters['weights'][0][:3]
        assert_allclose(np.diag(w.dot(w.conjugate().T)),
                        1.0,
                        rtol=1e-6,
                        atol=0)

    # Test turning off both forward and weight normalization
    filters = make_dics(epochs.info,
                        fwd_surf,
                        csd,
                        label=label,
                        weight_norm=None,
                        depth=None,
                        noise_csd=noise_csd)
    w = filters['weights'][0][:3]
    assert not np.allclose(
        np.diag(w.dot(w.conjugate().T)), 1.0, rtol=1e-2, atol=0)

    # Test neural-activity-index weight normalization. It should be a scaled
    # version of the unit-noise-gain beamformer.
    filters_nai = make_dics(epochs.info,
                            fwd_surf,
                            csd,
                            label=label,
                            pick_ori='max-power',
                            weight_norm='nai',
                            depth=None,
                            noise_csd=noise_csd)
    w_nai = filters_nai['weights'][0]
    filters_ung = make_dics(epochs.info,
                            fwd_surf,
                            csd,
                            label=label,
                            pick_ori='max-power',
                            weight_norm='unit-noise-gain',
                            depth=None,
                            noise_csd=noise_csd)
    w_ung = filters_ung['weights'][0]
    assert_allclose(np.corrcoef(np.abs(w_nai).ravel(),
                                np.abs(w_ung).ravel()),
                    1,
                    atol=1e-7)

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

    fname = op.join(str(tmpdir), 'filters-dics.h5')
    filters.save(fname)
    filters_read = read_beamformer(fname)
    assert isinstance(filters, Beamformer)
    assert isinstance(filters_read, Beamformer)
    for key in ['tmin', 'tmax']:  # deal with strictness of object_diff
        setattr(filters['csd'], key, np.float64(getattr(filters['csd'], key)))
    assert object_diff(filters, filters_read) == ''