def test_zero_lag():
    """Test analysis for 0 lag."""
    expected_mi, source, source_uncorr, target = _get_gauss_data()
    data = Data(np.hstack((source, target)), dim_order='sp', normalise=False)
    settings = {
        'cmi_estimator': 'JidtKraskovCMI',
        'n_perm_max_stat': 21,
        'n_perm_min_stat': 21,
        'n_perm_max_seq': 21,
        'n_perm_omnibus': 21,
        'tau_sources':
        0,  # this is not required, but shouldn't throw an error if provided
        'max_lag_sources': 0,
        'min_lag_sources': 0
    }
    nw = MultivariateMI()
    results = nw.analyse_single_target(settings, data, target=1, sources='all')
    mi_estimator = JidtKraskovMI(settings={'normalise': False})
    jidt_mi = mi_estimator.estimate(source, target)
    omnibus_mi = results.get_single_target(1, fdr=False).omnibus_mi
    print('Estimated omnibus MI: {0:0.6f}, estimated MI using JIDT core '
          'estimator: {1:0.6f} (expected: {2:0.6f}).'.format(
              omnibus_mi, jidt_mi, expected_mi))
    assert np.isclose(omnibus_mi, jidt_mi, atol=0.005), (
        'Zero-lag omnibus MI ({0:0.6f}) differs from JIDT estimate '
        '({1:0.6f}).'.format(omnibus_mi, jidt_mi))
    assert np.isclose(
        omnibus_mi, expected_mi,
        atol=0.05), ('Zero-lag omnibus MI ({0:0.6f}) differs from expected MI '
                     '({1:0.6f}).'.format(omnibus_mi, expected_mi))
Example #2
0
def test_zero_lag():
    """Test analysis for 0 lag."""
    covariance = 0.4
    n = 10000
    source = np.random.normal(0, 1, size=n)
    target = (covariance * source +
              (1 - covariance) * np.random.normal(0, 1, size=n))
    # expected_corr = covariance / (np.sqrt(covariance**2 + (1-covariance)**2))
    corr = np.corrcoef(source, target)[0, 1]
    expected_mi = -0.5 * np.log(1 - corr**2)

    data = Data(np.vstack((source, target)), dim_order='ps', normalise=False)
    settings = {
        'cmi_estimator': 'JidtKraskovCMI',
        'n_perm_max_stat': 21,
        'n_perm_min_stat': 21,
        'n_perm_max_seq': 21,
        'n_perm_omnibus': 21,
        'max_lag_sources': 0,
        'min_lag_sources': 0
    }
    nw = MultivariateMI()
    results = nw.analyse_single_target(settings, data, target=1, sources='all')
    mi_estimator = JidtKraskovMI(settings={})
    jidt_mi = mi_estimator.estimate(source, target)
    omnibus_mi = results.get_single_target(1, fdr=False).omnibus_mi
    print('Estimated omnibus MI: {0:0.6f}, estimated MI using JIDT core '
          'estimator: {1:0.6f} (expected: {2:0.6f}).'.format(
              omnibus_mi, jidt_mi, expected_mi))
    assert np.isclose(omnibus_mi, jidt_mi, rtol=0.05), (
        'Zero-lag omnibus MI ({0:0.6f}) differs from JIDT estimate ({1:0.6f}).'
        .format(omnibus_mi, jidt_mi))
    assert np.isclose(omnibus_mi, expected_mi, rtol=0.05), (
        'Zero-lag omnibus MI ({0:0.6f}) differs from expected MI ({1:0.6f}).'.
        format(omnibus_mi, expected_mi))
Example #3
0
def test_discrete_input():
    """Test multivariate MI estimation from discrete data."""
    # Generate Gaussian test data
    covariance = 0.4
    data = _get_discrete_gauss_data(covariance=covariance,
                                    n=10000,
                                    delay=1,
                                    normalise=False,
                                    seed=SEED)
    corr_expected = covariance / (1 * np.sqrt(covariance**2 +
                                              (1 - covariance)**2))
    expected_mi = calculate_mi(corr_expected)
    settings = {
        'cmi_estimator': 'JidtDiscreteCMI',
        'discretise_method': 'none',
        'n_discrete_bins': 5,  # alphabet size of the variables analysed
        'n_perm_max_stat': 21,
        'n_perm_omnibus': 30,
        'n_perm_max_seq': 30,
        'min_lag_sources': 1,
        'max_lag_sources': 2
    }
    nw = MultivariateMI()
    res = nw.analyse_single_target(settings=settings, data=data, target=1)
    assert np.isclose(
        res._single_target[1].omnibus_mi, expected_mi, atol=0.05), (
            'Estimated MI for discrete variables is not correct. Expected: '
            '{0}, Actual results: {1}.'.format(expected_mi,
                                               res['selected_sources_te'][0]))
def test_gauss_data():
    """Test bivariate MI estimation from correlated Gaussians."""
    # Generate data and add a delay one one sample.
    expected_mi, source, source_uncorr, target = _get_gauss_data()
    source = source[1:]
    source_uncorr = source_uncorr[1:]
    target = target[:-1]
    data = Data(np.hstack((source, source_uncorr, target)), dim_order='sp')
    settings = {
        'cmi_estimator': 'JidtKraskovCMI',
        'n_perm_max_stat': 21,
        'n_perm_min_stat': 21,
        'n_perm_max_seq': 21,
        'n_perm_omnibus': 21,
        'max_lag_sources': 2,
        'min_lag_sources': 1}
    nw = MultivariateMI()
    results = nw.analyse_single_target(
        settings, data, target=2, sources=[0, 1])
    mi = results.get_single_target(2, fdr=False)['mi'][0]
    sources = results.get_target_sources(2, fdr=False)

    # Assert that only the correlated source was detected.
    assert len(sources) == 1, 'Wrong no. inferred sources: {0}.'.format(
        len(sources))
    assert sources[0] == 0, 'Wrong inferred source: {0}.'.format(sources[0])
    # Compare BivarateMI() estimate to JIDT estimate.
    est = JidtKraskovMI({'lag_mi': 1})
    jidt_mi = est.estimate(var1=source, var2=target)
    print('Estimated MI: {0:0.6f}, estimated MI using JIDT core estimator: '
          '{1:0.6f} (expected: {2:0.6f}).'.format(mi, jidt_mi, expected_mi))
    assert np.isclose(mi, jidt_mi, atol=0.005), (
        'Estimated MI {0:0.6f} differs from JIDT estimate {1:0.6f} (expected: '
        'MI {2:0.6f}).'.format(mi, jidt_mi, expected_mi))
def test_zero_lag():
    """Test analysis for 0 lag."""
    covariance = 0.4
    n = 10000
    source = np.random.normal(0, 1, size=n)
    target = (covariance * source + (1 - covariance) *
              np.random.normal(0, 1, size=n))
    # expected_corr = covariance / (np.sqrt(covariance**2 + (1-covariance)**2))
    corr = np.corrcoef(source, target)[0, 1]
    expected_mi = -0.5 * np.log(1 - corr**2)

    data = Data(np.vstack((source, target)), dim_order='ps', normalise=False)
    settings = {
        'cmi_estimator': 'JidtKraskovCMI',
        'n_perm_max_stat': 21,
        'n_perm_min_stat': 21,
        'n_perm_max_seq': 21,
        'n_perm_omnibus': 21,
        'max_lag_sources': 0,
        'min_lag_sources': 0}
    nw = MultivariateMI()
    results = nw.analyse_single_target(
        settings, data, target=1, sources='all')
    mi_estimator = JidtKraskovMI(settings={})
    jidt_mi = mi_estimator.estimate(source, target)
    omnibus_mi = results.get_single_target(1, fdr=False).omnibus_mi
    print('Estimated omnibus MI: {0:0.6f}, estimated MI using JIDT core '
          'estimator: {1:0.6f} (expected: {2:0.6f}).'.format(
              omnibus_mi, jidt_mi, expected_mi))
    assert np.isclose(omnibus_mi, jidt_mi, rtol=0.05), (
        'Zero-lag omnibus MI ({0:0.6f}) differs from JIDT estimate ({1:0.6f}).'.format(
                omnibus_mi, jidt_mi))
    assert np.isclose(omnibus_mi, expected_mi, rtol=0.05), (
        'Zero-lag omnibus MI ({0:0.6f}) differs from expected MI ({1:0.6f}).'.format(
                omnibus_mi, expected_mi))
def test_gauss_data():
    """Test multivariate MI estimation from correlated Gaussians."""
    # Generate data and add a delay one one sample.
    expected_mi, source, source_uncorr, target = _get_gauss_data()
    source = source[1:]
    source_uncorr = source_uncorr[1:]
    target = target[:-1]
    data = Data(np.hstack((source, source_uncorr, target)),
                dim_order='sp',
                normalise=False)
    settings = {
        'cmi_estimator': 'JidtKraskovCMI',
        'n_perm_max_stat': 21,
        'n_perm_min_stat': 21,
        'n_perm_max_seq': 21,
        'n_perm_omnibus': 21,
        'max_lag_sources': 2,
        'min_lag_sources': 1
    }
    nw = MultivariateMI()
    results = nw.analyse_single_target(settings,
                                       data,
                                       target=2,
                                       sources=[0, 1])
    mi = results.get_single_target(2, fdr=False)['mi'][0]
    sources = results.get_target_sources(2, fdr=False)

    # Assert that only the correlated source was detected.
    assert len(sources) == 1, 'Wrong no. inferred sources: {0}.'.format(
        len(sources))
    assert sources[0] == 0, 'Wrong inferred source: {0}.'.format(sources[0])
    # Compare BivarateMI() estimate to JIDT estimate. Mimick realisations used
    # internally by the algorithm.
    est = JidtKraskovMI({'lag_mi': 0, 'normalise': False})
    jidt_mi = est.estimate(var1=source[1:-1], var2=target[2:])
    print('Estimated MI: {0:0.6f}, estimated MI using JIDT core estimator: '
          '{1:0.6f} (expected: {2:0.6f}).'.format(mi, jidt_mi, expected_mi))
    assert np.isclose(mi, jidt_mi, atol=0.005), (
        'Estimated MI {0:0.6f} differs from JIDT estimate {1:0.6f} (expected: '
        'MI {2:0.6f}).'.format(mi, jidt_mi, expected_mi))
    assert np.isclose(mi, expected_mi, atol=0.05), (
        'Estimated MI {0:0.6f} differs from expected MI {1:0.6f}.'.format(
            mi, expected_mi))
def test_discrete_input():
    """Test multivariate MI estimation from discrete data."""
    # Generate Gaussian test data
    covariance = 0.4
    n = 10000
    delay = 1
    source = np.random.normal(0, 1, size=n)
    target = (covariance * source +
              (1 - covariance) * np.random.normal(0, 1, size=n))
    corr_expected = covariance / (1 * np.sqrt(covariance**2 +
                                              (1 - covariance)**2))
    expected_mi = calculate_mi(corr_expected)
    source = source[delay:]
    target = target[:-delay]

    # Discretise data
    settings = {'discretise_method': 'equal', 'n_discrete_bins': 5}
    est = JidtDiscreteCMI(settings)
    source_dis, target_dis = est._discretise_vars(var1=source, var2=target)
    data = Data(np.vstack((source_dis, target_dis)),
                dim_order='ps',
                normalise=False)
    settings = {
        'cmi_estimator': 'JidtDiscreteCMI',
        'discretise_method': 'none',
        'n_discrete_bins': 5,  # alphabet size of the variables analysed
        'n_perm_max_stat': 21,
        'n_perm_omnibus': 30,
        'n_perm_max_seq': 30,
        'min_lag_sources': 1,
        'max_lag_sources': 2
    }
    nw = MultivariateMI()
    res = nw.analyse_single_target(settings=settings, data=data, target=1)
    assert np.isclose(
        res._single_target[1].omnibus_mi, expected_mi, atol=0.05), (
            'Estimated MI for discrete variables is not correct. Expected: '
            '{0}, Actual results: {1}.'.format(expected_mi,
                                               res['selected_sources_te'][0]))
def test_discrete_input():
    """Test multivariate MI estimation from discrete data."""
    # Generate Gaussian test data
    covariance = 0.4
    n = 10000
    delay = 1
    source = np.random.normal(0, 1, size=n)
    target = (covariance * source + (1 - covariance) *
              np.random.normal(0, 1, size=n))
    corr_expected = covariance / (
        1 * np.sqrt(covariance**2 + (1-covariance)**2))
    expected_mi = calculate_mi(corr_expected)
    source = source[delay:]
    target = target[:-delay]

    # Discretise data
    settings = {'discretise_method': 'equal',
                'n_discrete_bins': 5}
    est = JidtDiscreteCMI(settings)
    source_dis, target_dis = est._discretise_vars(var1=source, var2=target)
    data = Data(np.vstack((source_dis, target_dis)),
                dim_order='ps', normalise=False)
    settings = {
        'cmi_estimator': 'JidtDiscreteCMI',
        'discretise_method': 'none',
        'n_discrete_bins': 5,  # alphabet size of the variables analysed
        'n_perm_max_stat': 21,
        'n_perm_omnibus': 30,
        'n_perm_max_seq': 30,
        'min_lag_sources': 1,
        'max_lag_sources': 2}
    nw = MultivariateMI()
    res = nw.analyse_single_target(settings=settings, data=data, target=1)
    assert np.isclose(
        res._single_target[1].omnibus_mi, expected_mi, atol=0.05), (
            'Estimated MI for discrete variables is not correct. Expected: '
            '{0}, Actual results: {1}.'.format(
                expected_mi, res['selected_sources_te'][0]))
def test_return_local_values():
    """Test estimation of local values."""
    max_lag = 5
    data = Data()
    data.generate_mute_data(500, 5)
    settings = {
        'cmi_estimator': 'JidtKraskovCMI',
        'noise_level': 0,
        'local_values': True,  # request calculation of local values
        'n_perm_max_stat': 21,
        'n_perm_min_stat': 21,
        'n_perm_max_seq': 21,
        'n_perm_omnibus': 21,
        'max_lag_sources': max_lag,
        'min_lag_sources': 4,
        'max_lag_target': max_lag
    }
    target = 3
    sources = [0, 4]
    mi = MultivariateMI()
    results = mi.analyse_single_target(settings,
                                       data,
                                       target=target,
                                       sources=sources)
    settings['local_values'] = False
    results_avg = mi.analyse_single_target(settings,
                                           data,
                                           target=target,
                                           sources=sources)

    # Test if any sources were inferred. If not, return (this may happen
    # sometimes due to too few samples, however, a higher no. samples is not
    # feasible for a unit test).
    if results.get_single_target(target, fdr=False)['mi'] is None:
        return
    if results_avg.get_single_target(target, fdr=False)['mi'] is None:
        return

    lmi = results.get_single_target(target, fdr=False)['mi']
    n_sources = len(results.get_target_sources(target, fdr=False))
    assert type(lmi) is np.ndarray, (
        'LMI estimation did not return an array of values: {0}'.format(lmi))
    assert lmi.shape[0] == n_sources, (
        'Wrong dim (no. sources) in LMI estimate: {0}'.format(lmi.shape))
    assert lmi.shape[1] == data.n_realisations_samples(
        (0, max_lag)), ('Wrong dim (no. samples) in LMI estimate: {0}'.format(
            lmi.shape))
    assert lmi.shape[2] == data.n_replications, (
        'Wrong dim (no. replications) in LMI estimate: {0}'.format(lmi.shape))

    # Check if average and mean local values are the same. Test each source
    # separately. Inferred sources and variables may differ between the two
    # calls to analyse_single_target() due to low number of surrogates used in
    # unit testing.
    mi_single_link = results_avg.get_single_target(target, fdr=False)['mi']
    sources_local = results.get_target_sources(target, fdr=False)
    sources_avg = results_avg.get_target_sources(target, fdr=False)
    for s in list(set(sources_avg).intersection(sources_local)):
        i1 = np.where(sources_avg == s)[0][0]
        i2 = np.where(sources_local == s)[0][0]
        # Skip comparison if inferred variables differ between links.
        vars_local = [
            v for v in results.get_single_target(
                target, fdr=False).selected_vars_sources if v[0] == s
        ]
        vars_avg = [
            v for v in results_avg.get_single_target(
                target, fdr=False).selected_vars_sources if v[0] == s
        ]
        if vars_local != vars_avg:
            continue
        print('Compare average ({0:.4f}) and local values ({1:.4f}).'.format(
            mi_single_link[i1], np.mean(lmi[i2, :, :])))
        assert np.isclose(
            mi_single_link[i1], np.mean(lmi[i2, :, :]), rtol=0.00005), (
                'Single link average MI ({0:.6f}) and mean LMI ({1:.6f}) '
                ' deviate.'.format(mi_single_link[i1], np.mean(lmi[i2, :, :])))
def test_multivariate_mi_init():
    """Test instance creation for MultivariateMI class."""
    # Test error on missing estimator
    settings = {
        'n_perm_max_stat': 21,
        'n_perm_omnibus': 30,
        'max_lag_sources': 7,
        'min_lag_sources': 2
    }
    nw = MultivariateMI()
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=Data(), target=1)

    # Test setting of min and max lags
    settings['cmi_estimator'] = 'JidtKraskovCMI'
    data = Data()
    data.generate_mute_data(n_samples=10, n_replications=5)

    # Invalid: min lag sources bigger than max lag
    settings['min_lag_sources'] = 8
    settings['max_lag_sources'] = 7
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: tau bigger than lags
    settings['min_lag_sources'] = 2
    settings['max_lag_sources'] = 4
    settings['tau_sources'] = 10
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: negative lags or taus
    settings['tau_sources'] = 1
    settings['min_lag_sources'] = 1
    settings['max_lag_sources'] = -7
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['max_lag_sources'] = 7
    settings['min_lag_sources'] = -4
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['min_lag_sources'] = 4
    settings['tau_sources'] = -1
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: lags or taus are no integers
    settings['min_lag_sources'] = 1.5
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['min_lag_sources'] = 1
    settings['max_lag_sources'] = 1.5
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['max_lag_sources'] = 7
    settings['tau_sources'] = 1.5
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: sources or target is no int
    with pytest.raises(RuntimeError):  # no int
        nw.analyse_single_target(settings=settings, data=data, target=1.5)
    with pytest.raises(RuntimeError):  # negative
        nw.analyse_single_target(settings=settings, data=data, target=-1)
    with pytest.raises(RuntimeError):  # not in data
        nw.analyse_single_target(settings=settings, data=data, target=10)
    with pytest.raises(RuntimeError):  # wrong type
        nw.analyse_single_target(settings=settings, data=data, target={})
    with pytest.raises(RuntimeError):  # negative
        nw.analyse_single_target(settings=settings,
                                 data=data,
                                 target=0,
                                 sources=-1)
    with pytest.raises(RuntimeError):  # negative
        nw.analyse_single_target(settings=settings,
                                 data=data,
                                 target=0,
                                 sources=[-1])
    with pytest.raises(RuntimeError):  # not in data
        nw.analyse_single_target(settings=settings,
                                 data=data,
                                 target=0,
                                 sources=20)
    with pytest.raises(RuntimeError):  # not in data
        nw.analyse_single_target(settings=settings,
                                 data=data,
                                 target=0,
                                 sources=[20])
def test_multivariate_mi_init():
    """Test instance creation for MultivariateMI class."""
    # Test error on missing estimator
    settings = {
        'n_perm_max_stat': 21,
        'n_perm_omnibus': 30,
        'max_lag_sources': 7,
        'min_lag_sources': 2}
    nw = MultivariateMI()
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=Data(), target=1)

    # Test setting of min and max lags
    settings['cmi_estimator'] = 'JidtKraskovCMI'
    data = Data()
    data.generate_mute_data(n_samples=10, n_replications=5)

    # Invalid: min lag sources bigger than max lag
    settings['min_lag_sources'] = 8
    settings['max_lag_sources'] = 7
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: tau bigger than lags
    settings['min_lag_sources'] = 2
    settings['max_lag_sources'] = 4
    settings['tau_sources'] = 10
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: negative lags or taus
    settings['tau_sources'] = 1
    settings['min_lag_sources'] = 1
    settings['max_lag_sources'] = -7
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['max_lag_sources'] = 7
    settings['min_lag_sources'] = -4
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['min_lag_sources'] = 4
    settings['tau_sources'] = -1
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: lags or taus are no integers
    settings['min_lag_sources'] = 1.5
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['min_lag_sources'] = 1
    settings['max_lag_sources'] = 1.5
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)
    settings['max_lag_sources'] = 7
    settings['tau_sources'] = 1.5
    with pytest.raises(RuntimeError):
        nw.analyse_single_target(settings=settings, data=data, target=1)

    # Invalid: sources or target is no int
    with pytest.raises(RuntimeError):  # no int
        nw.analyse_single_target(settings=settings, data=data, target=1.5)
    with pytest.raises(RuntimeError):  # negative
        nw.analyse_single_target(settings=settings, data=data, target=-1)
    with pytest.raises(RuntimeError):  # not in data
        nw.analyse_single_target(settings=settings, data=data, target=10)
    with pytest.raises(RuntimeError):  # wrong type
        nw.analyse_single_target(settings=settings, data=data, target={})
    with pytest.raises(RuntimeError):  # negative
        nw.analyse_single_target(settings=settings, data=data, target=0,
                                 sources=-1)
    with pytest.raises(RuntimeError):   # negative
        nw.analyse_single_target(settings=settings, data=data, target=0,
                                 sources=[-1])
    with pytest.raises(RuntimeError):  # not in data
        nw.analyse_single_target(settings=settings, data=data, target=0,
                                 sources=20)
    with pytest.raises(RuntimeError):  # not in data
        nw.analyse_single_target(settings=settings, data=data, target=0,
                                 sources=[20])