Пример #1
0
def test_inverse_residual(evoked):
    """Test MNE inverse application."""
    # use fname_inv as it will be faster than fname_full (fewer verts and chs)
    evoked = evoked.pick_types()
    inv = read_inverse_operator(fname_inv_fixed_depth)
    fwd = read_forward_solution(fname_fwd)
    pick_channels_forward(fwd, evoked.ch_names, copy=False)
    fwd = convert_forward_solution(fwd, force_fixed=True, surf_ori=True)
    matcher = re.compile(r'.* ([0-9]?[0-9]?[0-9]?\.[0-9])% variance.*')
    for method in ('MNE', 'dSPM', 'sLORETA'):
        with catch_logging() as log:
            stc, residual = apply_inverse(evoked,
                                          inv,
                                          method=method,
                                          return_residual=True,
                                          verbose=True)
        log = log.getvalue()
        match = matcher.match(log.replace('\n', ' '))
        assert match is not None
        match = float(match.group(1))
        assert 45 < match < 50
        if method == 'MNE':  # must be first!
            recon = apply_forward(fwd, stc, evoked.info)
            proj_op = make_projector(evoked.info['projs'], evoked.ch_names)[0]
            recon.data[:] = np.dot(proj_op, recon.data)
            residual_fwd = evoked.copy()
            residual_fwd.data -= recon.data
        corr = np.corrcoef(residual_fwd.data.ravel(), residual.data.ravel())[0,
                                                                             1]
        assert corr > 0.999
    with catch_logging() as log:
        _, residual = apply_inverse(evoked,
                                    inv,
                                    0.,
                                    'MNE',
                                    return_residual=True,
                                    verbose=True)
    log = log.getvalue()
    match = matcher.match(log.replace('\n', ' '))
    assert match is not None
    match = float(match.group(1))
    assert match == 100.
    assert_array_less(np.abs(residual.data), 1e-15)

    # Degenerate: we don't have the right representation for eLORETA for this
    with pytest.raises(ValueError, match='eLORETA does not .* support .*'):
        apply_inverse(evoked, inv, method="eLORETA", return_residual=True)
Пример #2
0
def test_inverse_residual(evoked, method):
    """Test MNE inverse application."""
    # use fname_inv as it will be faster than fname_full (fewer verts and chs)
    evoked = evoked.pick_types(meg=True)
    inv = read_inverse_operator(fname_inv_fixed_depth)
    fwd = read_forward_solution(fname_fwd)
    pick_channels_forward(fwd, evoked.ch_names, copy=False)
    fwd = convert_forward_solution(fwd, force_fixed=True, surf_ori=True)
    matcher = re.compile(r'.* ([0-9]?[0-9]?[0-9]?\.[0-9])% variance.*')

    # make it complex to ensure we handle it properly
    evoked.data = 1j * evoked.data
    with catch_logging() as log:
        stc, residual = apply_inverse(
            evoked, inv, method=method, return_residual=True, verbose=True)
    # revert the complex-ification (except STC, allow that to be complex still)
    assert_array_equal(residual.data.real, 0)
    residual.data = (-1j * residual.data).real
    evoked.data = (-1j * evoked.data).real
    # continue testing
    log = log.getvalue()
    match = matcher.match(log.replace('\n', ' '))
    assert match is not None
    match = float(match.group(1))
    assert 45 < match < 50
    if method not in ('dSPM', 'sLORETA'):
        # revert effects of STC being forced to be complex
        recon = apply_forward(fwd, stc, evoked.info)
        recon.data = (-1j * recon.data).real
        proj_op = make_projector(evoked.info['projs'], evoked.ch_names)[0]
        recon.data[:] = np.dot(proj_op, recon.data)
        residual_fwd = evoked.copy()
        residual_fwd.data -= recon.data
        corr = np.corrcoef(residual_fwd.data.ravel(),
                           residual.data.ravel())[0, 1]
        assert corr > 0.999

    if method != 'sLORETA':  # XXX divide by zero error
        with catch_logging() as log:
            _, residual = apply_inverse(
                evoked, inv, 0., method, return_residual=True, verbose=True)
        log = log.getvalue()
        match = matcher.match(log.replace('\n', ' '))
        assert match is not None
        match = float(match.group(1))
        assert match == 100.
        assert_array_less(np.abs(residual.data), 1e-15)
Пример #3
0
def test_inverse_residual():
    """Test MNE inverse application."""
    # use fname_inv as it will be faster than fname_full (fewer verts and chs)
    evoked = _get_evoked().pick_types()
    inv = read_inverse_operator(fname_inv_fixed_depth)
    fwd = read_forward_solution(fname_fwd)
    fwd = convert_forward_solution(fwd, force_fixed=True, surf_ori=True)
    fwd = pick_channels_forward(fwd, evoked.ch_names)
    matcher = re.compile(r'.* ([0-9]?[0-9]?[0-9]?\.[0-9])% variance.*')
    for method in ('MNE', 'dSPM', 'sLORETA'):
        with catch_logging() as log:
            stc, residual = apply_inverse(
                evoked, inv, method=method, return_residual=True, verbose=True)
        log = log.getvalue()
        match = matcher.match(log.replace('\n', ' '))
        assert match is not None
        match = float(match.group(1))
        assert 45 < match < 50
        if method == 'MNE':  # must be first!
            recon = apply_forward(fwd, stc, evoked.info)
            proj_op = make_projector(evoked.info['projs'], evoked.ch_names)[0]
            recon.data[:] = np.dot(proj_op, recon.data)
            residual_fwd = evoked.copy()
            residual_fwd.data -= recon.data
        corr = np.corrcoef(residual_fwd.data.ravel(),
                           residual.data.ravel())[0, 1]
        assert corr > 0.999
    with catch_logging() as log:
        _, residual = apply_inverse(
            evoked, inv, 0., 'MNE', return_residual=True, verbose=True)
    log = log.getvalue()
    match = matcher.match(log.replace('\n', ' '))
    assert match is not None
    match = float(match.group(1))
    assert match == 100.
    assert_array_less(np.abs(residual.data), 1e-15)

    # Degenerate: we don't have the right representation for eLORETA for this
    with pytest.raises(ValueError, match='eLORETA does not .* support .*'):
        apply_inverse(evoked, inv, method="eLORETA", return_residual=True)
Пример #4
0
def simulate_evoked_osc(info,
                        fwd,
                        n_trials,
                        freq,
                        label,
                        loc_in_label=None,
                        picks=None,
                        loc_seed=None,
                        snr=None,
                        mu=None,
                        noise_type="white",
                        return_matrix=True,
                        filtering=None,
                        phase_lock=False):
    """Simulate evoked oscillatory data based on a given fwd model and dipole.

    Parameters:
    -----------
    info : MNE info object
        data info, e.g., from raw
    fwd : MNE forward object
        forward model object
    freq : float
        freq of simulated oscillation
    n_trials : int
        number of trials
    label : MNE label
        source space label to simulate data in
    loc_in_label : None | int
        Specify the random generator state for dipole simulation within the
        label. Defaults to np.random.RandomState if None.
    picks : None | string
        Channel types to pick from evoked, can be 'mag' or 'grad'. None
        defaults to all.
    seed : None | int
        Seed for the time series simulation, only relevant for location in
        label.
    snr : None | float
        If not None, signal-to-noise ratio in dB for resulting signal (adding
        noise).
    mu : None | float
        To directly manipulate noise level (e.g. to keep constant across
        conditions).
    noise_type : str
        Type of noise. Supported is at the moment: "white" and "brownian".
    return_matrix : bool
        If True, a matrix of epochs will be returned and the evoked object will
        be averaged across trials.
    filtering : None | dict
        If None (default), no filtering is done. If filtering should be done,
        the dictionary needs to contain the following keys:
            "hp" : high pass cutoff, float.
            "lp" : low pass cutoff, float.
            "fir_design" : FIR design, string, see evoked.filter()
            "lp_tw" : transition width for low pass, float, optional.
            "hp_tw" : transition width for high pass, float, optional.
    phase_lock : bool
        If True, the oscillation will be phase-locked across trials.

    Returns:
    --------
    evoked : MNE evoked object
        Simulated sensor data.
    stc : MNE source time course object
        Simulated source space data.
    epochs : np.array
        Matrix with epochs, if return_matrix is True.
    """
    if loc_seed is not None:
        np.random.seed(loc_seed)
    if loc_in_label is None:
        loc_in_label = np.random.RandomState()

    np.random.seed()  # reset to random seed to not get funky results for noise

    times = np.arange(0., n_trials, 1. / info['sfreq'])
    stc = simulate_sparse_stc(
        fwd['src'],
        n_dipoles=1,
        times=times,
        random_state=loc_in_label,
        labels=label,
        data_fun=lambda times: generate_signal(
            times, freq, n_trials, phase_lock=phase_lock))

    # go to sensor space
    evoked = apply_forward(fwd, stc, info, verbose=False, use_cps=False)

    # pick channel types if applicable
    if picks is not None:
        evoked.pick_types(meg=picks)

    if filtering is not None:
        if "lp_tw" not in filtering:
            filtering["lp_tw"] = "auto"
        if "hp_tw" not in filtering:
            filtering["hp_tw"] = "auto"

    if snr is not None:
        snr = 10**(snr / 20)  # convert dB to ratio
        if noise_type == "white":
            noise_data = np.random.randn(*evoked.data.shape)
        elif noise_type == "brownian":
            # make white noise first
            noise_data = np.random.randn(*evoked.data.shape)
        elif noise_type == "pink":
            noise_data = make_pink_noise(evoked.data.shape[1], 10,
                                         evoked.data.shape[0])
        else:
            raise ValueError('So far, only white, brownian, and pink noise is '
                             'implemented, got %s' % noise_type)

        if filtering is not None:
            # filter the noise
            noise_evoked = evoked.copy()
            noise_evoked.data[:] = noise_data
            noise_evoked.filter(filtering["hp"],
                                filtering["lp"],
                                fir_design=filtering["fir_design"],
                                l_trans_bandwidth=filtering["hp_tw"],
                                h_trans_bandwidth=filtering["lp_tw"],
                                verbose=False)
            noise_data = noise_evoked.data

        # scale the noise
        # shape: trials x sensor x time
        noise_matrix = noise_data.reshape([len(evoked.ch_names), n_trials,
                                           -1]).transpose(1, 0, 2)
        signal_matrix = evoked._data.reshape(
            [len(evoked.ch_names), n_trials, -1]).transpose(1, 0, 2)

        if mu is None:
            mu = np.linalg.norm(signal_matrix, 'fro', axis=(1, 2))
            mu /= (snr *
                   np.sqrt(len(evoked.ch_names) * (len(times) / n_trials)))

        if noise_type == 'brownian':
            noise_matrix = np.cumsum(mu[:, np.newaxis, np.newaxis] *
                                     noise_matrix,
                                     axis=1)
            signal_matrix += noise_matrix
        else:
            signal_matrix += (mu[:, np.newaxis, np.newaxis] * noise_matrix)

    evoked.data = signal_matrix.transpose(1, 0, 2).reshape(
        [len(evoked.ch_names),
         int(n_trials * (len(times) / n_trials))])
    # evoked.data *= 1e-11

    if filtering is not None:
        # filter all the data again
        evoked.filter(filtering["hp"],
                      filtering["lp"],
                      fir_design=filtering["fir_design"],
                      l_trans_bandwidth=filtering["hp_tw"],
                      h_trans_bandwidth=filtering["lp_tw"],
                      verbose=False)

    # take care of trials:
    if return_matrix is True:
        epochs = evoked._data
        epochs = epochs.reshape([len(evoked.ch_names), n_trials,
                                 -1]).transpose(1, 0, 2)

        evoked.crop(0., evoked.times[int((times.shape[0] / n_trials) - 1)])
        evoked._data[:, :] = epochs.mean(axis=0)

        return evoked, stc, epochs, mu

    else:
        return evoked, stc, mu