def test_cmi_no_cond_correlated_gaussians(): """Test estimators on correlated Gaussian data without conditional.""" expected_mi, source, source_uncorr, target = _get_gauss_data() # Run OpenCL estimator. settings = {'debug': True} ocl_est = OpenCLKraskovCMI(settings=settings) mi_ocl, dist, n_range_var1, n_range_var2 = ocl_est.estimate(source, target) mi_ocl = mi_ocl[0] # Run JIDT estimator. jidt_est = JidtKraskovCMI(settings={}) mi_jidt = jidt_est.estimate(source, target) cov_effective = np.cov(np.squeeze(source), np.squeeze(target))[1, 0] expected_mi = math.log(1 / (1 - math.pow(cov_effective, 2))) print('JIDT MI result: {0:.4f} nats; OpenCL MI result: {1:.4f} nats; ' 'expected to be close to {2:.4f} nats for correlated ' 'Gaussians.'.format(mi_jidt, mi_ocl, expected_mi)) assert np.isclose(mi_jidt, expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'JIDT estimator failed (error larger 0.05).') assert np.isclose(mi_ocl, expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose(mi_ocl, mi_jidt, atol=0.0001), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).')
def test_analytical_surrogates(): # Test generation of analytical surrogates. # Generate data and discretise it such that we can use analytical # surrogates. expected_mi, source1, source2, target = _get_gauss_data(covariance=0.4) settings = {'discretise_method': 'equal', 'n_discrete_bins': 5} est = JidtDiscreteCMI(settings) source_dis, target_dis = est._discretise_vars(var1=source1, var2=target) data = Data(np.hstack((source_dis, target_dis)), dim_order='sp', normalise=False) settings = { 'cmi_estimator': 'JidtDiscreteCMI', 'n_discrete_bins': 5, # alphabet size of the variables analysed 'n_perm_max_stat': 100, 'n_perm_min_stat': 21, 'n_perm_omnibus': 21, 'n_perm_max_seq': 21, 'max_lag_sources': 5, 'min_lag_sources': 1, 'max_lag_target': 5 } nw = MultivariateTE() res = nw.analyse_single_target(settings, data, target=1) # Check if generation of analytical surrogates is documented in the # settings. assert res.settings.analytical_surrogates, ( 'Surrogates were not created analytically.')
def test_insufficient_no_points(): """Test if estimation aborts for too few data points.""" expected_mi, source1, source2, target = _get_gauss_data(n=4) settings = { 'kraskov_k': 4, 'theiler_t': 0, 'history': 1, 'history_target': 1, 'lag_mi': 1, 'source_target_delay': 1} # Test first settings combination with k==N est = OpenCLKraskovMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target) est = OpenCLKraskovCMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target, target) # Test a second combination with a Theiler-correction != 0 settings['theiler_t'] = 1 settings['kraskov_k'] = 2 est = OpenCLKraskovMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target) est = OpenCLKraskovCMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target, target)
def test_insufficient_no_points(): """Test if estimation aborts for too few data points.""" expected_mi, source1, source2, target = _get_gauss_data(n=4) settings = { 'kraskov_k': 4, 'theiler_t': 0, 'history': 1, 'history_target': 1, 'lag_mi': 1, 'source_target_delay': 1 } # Test first settings combination with k==N est = OpenCLKraskovMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target) est = OpenCLKraskovCMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target, target) # Test a second combination with a Theiler-correction != 0 settings['theiler_t'] = 1 settings['kraskov_k'] = 2 est = OpenCLKraskovMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target) est = OpenCLKraskovCMI(settings) with pytest.raises(RuntimeError): est.estimate(source1, target, target)
def test_cmi_correlated_gaussians(): """Test estimators on correlated Gaussian data with conditional.""" expected_mi, source, source_uncorr, target = _get_gauss_data() # Run OpenCL estimator. settings = {'debug': True, 'return_counts': True} ocl_est = OpenCLKraskovCMI(settings=settings) (mi_ocl, dist, n_range_var1, n_range_var2, n_range_cond) = ocl_est.estimate(source, target, source_uncorr) mi_ocl = mi_ocl[0] # Run JIDT estimator. jidt_est = JidtKraskovCMI(settings={}) mi_jidt = jidt_est.estimate(source, target, source_uncorr) print('JIDT MI result: {0:.4f} nats; OpenCL MI result: {1:.4f} nats; ' 'expected to be close to {2:.4f} nats for correlated ' 'Gaussians.'.format(mi_jidt, mi_ocl, expected_mi)) assert np.isclose( mi_jidt, expected_mi, atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'JIDT estimator failed (error larger 0.05).') assert np.isclose( mi_ocl, expected_mi, atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose( mi_ocl, mi_jidt, atol=0.0001), ('MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).')
def test_cmi_correlated_gaussians(): """Test estimators on correlated Gaussian data with conditional.""" expected_mi, source, source_uncorr, target = _get_gauss_data() # Run OpenCL estimator. settings = {'debug': True} ocl_est = OpenCLKraskovCMI(settings=settings) (mi_ocl, dist, n_range_var1, n_range_var2, n_range_cond) = ocl_est.estimate(source, target, source_uncorr) mi_ocl = mi_ocl[0] # Run JIDT estimator. jidt_est = JidtKraskovCMI(settings={}) mi_jidt = jidt_est.estimate(source, target, source_uncorr) print('JIDT MI result: {0:.4f} nats; OpenCL MI result: {1:.4f} nats; ' 'expected to be close to {2:.4f} nats for correlated ' 'Gaussians.'.format(mi_jidt, mi_ocl, expected_mi)) assert np.isclose(mi_jidt, expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'JIDT estimator failed (error larger 0.05).') assert np.isclose(mi_ocl, expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose(mi_ocl, mi_jidt, atol=0.0001), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).')
def test_multi_gpu(): """Test use of multiple GPUs.""" expected_mi, source, source_uncorr, target = _get_gauss_data() settings = {'debug': True, 'return_counts': True} # Get no. available devices on current platform. device_list, _, _ = OpenCLKraskovCMI()._get_device(gpuid=0) print(device_list) n_devices = len(device_list) # Try initialising estimator with unavailable GPU ID with pytest.raises(RuntimeError): settings['gpuid'] = n_devices + 1 OpenCLKraskovCMI(settings=settings) # Run OpenCL estimator on available device with highest available ID. settings['gpuid'] = n_devices - 1 ocl_est = OpenCLKraskovCMI(settings=settings) (mi_ocl, dist, n_range_var1, n_range_var2, n_range_cond) = ocl_est.estimate(source, target, source_uncorr) mi_ocl = mi_ocl[0] print('Expected MI: {0:.4f} nats; OpenCL MI result: {1:.4f} nats; ' 'expected to be close to 0 nats for uncorrelated ' 'Gaussians.'.format(expected_mi, mi_ocl)) assert np.isclose( mi_ocl, expected_mi, atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).')
def test_calculate_cmi_all_links(): """Test if the CMI is estimated correctly.""" 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, target)), dim_order='sp', normalise=False) res_0 = pickle.load( open(os.path.join(os.path.dirname(__file__), 'data/mute_results_0.p'), 'rb')) comp_settings = { 'cmi_estimator': 'JidtKraskovCMI', 'n_perm_max_stat': 50, 'n_perm_min_stat': 50, 'n_perm_omnibus': 200, 'n_perm_max_seq': 50, 'tail': 'two', 'n_perm_comp': 6, 'alpha_comp': 0.2, 'stats_type': 'dependent' } comp = NetworkComparison() comp._initialise(comp_settings) comp._create_union(res_0) # Set selected variable to the source, one sample in the past of the # current_value (1, 5). comp.union._single_target[1]['selected_vars_sources'] = [(0, 4)] cmi = comp._calculate_cmi_all_links(data) print('correlated Gaussians: TE result {0:.4f} bits; expected to be ' '{1:0.4f} bit for the copy'.format(cmi[1][0], expected_mi)) assert np.isclose(cmi[1][0], expected_mi, atol=0.05), ( 'Estimated TE {0:0.6f} differs from expected TE {1:0.6f}.'.format( cmi[1][0], expected_mi))
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.""" 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))
def test_estimate_parallel(): """Test estimate_parallel() against estimate().""" expected_mi, source1, source2, target = _get_gauss_data() source_chunks = np.vstack((source1, source1)) target_chunks = np.vstack((target, target)) # Compare MI-estimates from serial and parallel estimator. mi_estimator = JidtKraskovMI(settings={'noise_level': 0}) mi = mi_estimator.estimate(source1, target) with pytest.raises(AssertionError): mi_estimator.estimate_parallel( n_chunks=2, var1=source_chunks, var2=target) mi_parallel1 = mi_estimator.estimate_parallel( n_chunks=2, re_use=['var2'], var1=source_chunks, var2=target) mi_parallel2 = mi_estimator.estimate_parallel( n_chunks=2, var1=source_chunks, var2=target_chunks) assert (mi_parallel1 == mi_parallel2).all(), ( 'Results for stacked ({0}) and re-used ({1}) target differ.'.format( mi_parallel1, mi_parallel2)) assert mi_parallel1[0] == mi, ( 'Results for first chunk differ from serial estimate.') assert mi_parallel1[1] == mi, ( 'Results for second chunk differ from serial estimate.') assert np.isclose(mi, expected_mi, rtol=0.05), ( 'Estimated ({0}) and expected ({1}) MI differ.'.format( mi, expected_mi)) # Check if a single chunk is returned if all variables are defined as # reusable. mi_parallel3 = mi_estimator.estimate_parallel( n_chunks=2, re_use=['var1', 'var2'], var1=source1, var2=target) assert len(mi_parallel3) == 1, ( 'Single chunk data returned more than one estimate.') assert np.isclose(mi_parallel3[0], expected_mi, rtol=0.05), ( 'Estimated ({0}) and expected ({1}) MI differ.'.format( mi_parallel3[0], expected_mi)) # Check assertion for incorrect number of samples in data to be reused in # parallel estimator. with pytest.raises(AssertionError): mi_estimator.estimate_parallel( n_chunks=2, re_use=['var2'], var1=source_chunks, var2=target[:100])
def test_estimate_parallel(): """Test estimate_parallel() against estimate().""" expected_mi, source1, source2, target = _get_gauss_data() source_chunks = np.vstack((source1, source1)) target_chunks = np.vstack((target, target)) # Compare MI-estimates from serial and parallel estimator. mi_estimator = JidtKraskovMI(settings={'noise_level': 0}) mi = mi_estimator.estimate(source1, target) with pytest.raises(AssertionError): mi_estimator.estimate_parallel(n_chunks=2, var1=source_chunks, var2=target) mi_parallel1 = mi_estimator.estimate_parallel(n_chunks=2, re_use=['var2'], var1=source_chunks, var2=target) mi_parallel2 = mi_estimator.estimate_parallel(n_chunks=2, var1=source_chunks, var2=target_chunks) assert (mi_parallel1 == mi_parallel2).all(), ( 'Results for stacked ({0}) and re-used ({1}) target differ.'.format( mi_parallel1, mi_parallel2)) assert mi_parallel1[0] == mi, ( 'Results for first chunk differ from serial estimate.') assert mi_parallel1[1] == mi, ( 'Results for second chunk differ from serial estimate.') assert np.isclose( mi, expected_mi, rtol=0.05), ('Estimated ({0}) and expected ({1}) MI differ.'.format( mi, expected_mi)) # Check if a single chunk is returned if all variables are defined as # reusable. mi_parallel3 = mi_estimator.estimate_parallel(n_chunks=2, re_use=['var1', 'var2'], var1=source1, var2=target) assert len(mi_parallel3) == 1, ( 'Single chunk data returned more than one estimate.') assert np.isclose( mi_parallel3[0], expected_mi, rtol=0.05), ('Estimated ({0}) and expected ({1}) MI differ.'.format( mi_parallel3[0], expected_mi)) # Check assertion for incorrect number of samples in data to be reused in # parallel estimator. with pytest.raises(AssertionError): mi_estimator.estimate_parallel(n_chunks=2, re_use=['var2'], var1=source_chunks, var2=target[:100])
def test_amd_data_padding(): """Test padding necessary for AMD devices.""" expected_mi, source, source_uncorr, target = _get_gauss_data() settings = {'debug': True, 'return_counts': True} est_mi = OpenCLKraskovMI(settings=settings) est_cmi = OpenCLKraskovCMI(settings=settings) # Run OpenCL estimator for various data sizes. for n in [11, 13, 25, 64, 100, 128, 999, 10000, 3781, 50000]: for n_chunks in [1, 3, 10, 50, 99]: data_run_source = np.tile(source[:n], (n_chunks, 1)) data_run_target = np.tile(target[:n], (n_chunks, 1)) mi, dist, n_range_var1, n_range_var2 = est_mi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) cmi, dist, n_range_var1, n_range_var2 = est_cmi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) # Run OpenCL esitmator for various no. points and check result for # correctness. Note that for smaller sample sizes the error becomes too # large. n_chunks = 1 for n in [832, 999, 10000, 3781, 50000]: data_run_source = np.tile(source[:n], (n_chunks, 1)) data_run_target = np.tile(target[:n], (n_chunks, 1)) mi, dist, n_range_var1, n_range_var2 = est_mi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) cmi, dist, n_range_var1, n_range_var2 = est_cmi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) print('{0} points, {1} chunks: OpenCL MI result: {2:.4f} nats; ' 'expected to be close to {3:.4f} nats for correlated ' 'Gaussians.'.format(n, n_chunks, mi[0], expected_mi)) assert np.isclose(mi[0], expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the OpenCL ' 'estimator failed (error larger 0.05).') print('OpenCL CMI result: {0:.4f} nats; expected to be close to ' '{1:.4f} nats for correlated Gaussians.'.format( cmi[0], expected_mi)) assert np.isclose(cmi[0], expected_mi, atol=0.05), ( 'CMI estimation for uncorrelated Gaussians using the OpenCL ' 'estimator failed (error larger 0.05).') # Test debugging switched off settings = {'debug': False, 'return_counts': False} est_mi = OpenCLKraskovMI(settings=settings) est_cmi = OpenCLKraskovCMI(settings=settings) mi = est_mi.estimate(source, target) cmi = est_cmi.estimate(source, target) settings['local_values'] = True est_mi = OpenCLKraskovMI(settings=settings) est_cmi = OpenCLKraskovCMI(settings=settings) mi = est_mi.estimate(source, target) cmi = est_cmi.estimate(source, target)
def test_gauss_data(): """Test bivariate TE estimation from correlated Gaussians.""" # Generate data and add a delay one one sample. expected_mi, source, source_uncorr, target = _get_gauss_data(seed=SEED) source = source[1:] source_uncorr = source_uncorr[1:] target = target[:-1] data = Data(np.hstack((source, source_uncorr, target)), dim_order='sp', normalise=False, seed=SEED) 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': 1, 'min_lag_sources': 1, 'max_lag_target': 1 } nw = BivariateTE() results = nw.analyse_single_target(settings, data, target=2, sources=[0, 1]) te = results.get_single_target(2, fdr=False)['te'][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 BivarateTE() estimate to JIDT estimate. est = JidtKraskovTE({ 'history_target': 1, 'history_source': 1, 'source_target_delay': 1, 'normalise': False }) jidt_cmi = est.estimate(source=source, target=target) print('Estimated TE: {0:0.6f}, estimated TE using JIDT core estimator: ' '{1:0.6f} (expected: ~ {2:0.6f}).'.format(te, jidt_cmi, expected_mi)) assert np.isclose(te, jidt_cmi, atol=0.005), ( 'Estimated TE {0:0.6f} differs from JIDT estimate {1:0.6f} (expected: ' 'TE {2:0.6f}).'.format(te, jidt_cmi, expected_mi)) assert np.isclose(te, expected_mi, atol=0.05), ( 'Estimated TE {0:0.6f} differs from expected TE {1:0.6f}.'.format( te, expected_mi))
def test_amd_data_padding(): """Test padding necessary for AMD devices.""" expected_mi, source, source_uncorr, target = _get_gauss_data() settings = {'debug': True} est_mi = OpenCLKraskovMI(settings=settings) est_cmi = OpenCLKraskovCMI(settings=settings) # Run OpenCL estimator for various data sizes. for n in [11, 13, 25, 64, 100, 128, 999, 10000, 3781, 50000]: for n_chunks in [1, 3, 10, 50, 99]: data_run_source = np.tile(source[:n], (n_chunks, 1)) data_run_target = np.tile(target[:n], (n_chunks, 1)) mi, dist, n_range_var1, n_range_var2 = est_mi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) cmi, dist, n_range_var1, n_range_var2 = est_cmi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) # Run OpenCL esitmator for various no. points and check result for # correctness. Note that for smaller sample sizes the error becomes too # large. n_chunks = 1 for n in [832, 999, 10000, 3781, 50000]: data_run_source = np.tile(source[:n], (n_chunks, 1)) data_run_target = np.tile(target[:n], (n_chunks, 1)) mi, dist, n_range_var1, n_range_var2 = est_mi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) cmi, dist, n_range_var1, n_range_var2 = est_cmi.estimate( data_run_source, data_run_target, n_chunks=n_chunks) print('{0} points, {1} chunks: OpenCL MI result: {2:.4f} nats; ' 'expected to be close to {3:.4f} nats for correlated ' 'Gaussians.'.format(n, n_chunks, mi[0], expected_mi)) assert np.isclose(mi[0], expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the OpenCL ' 'estimator failed (error larger 0.05).') print('OpenCL CMI result: {0:.4f} nats; expected to be close to ' '{1:.4f} nats for correlated Gaussians.'.format( cmi[0], expected_mi)) assert np.isclose(cmi[0], expected_mi, atol=0.05), ( 'CMI estimation for uncorrelated Gaussians using the OpenCL ' 'estimator failed (error larger 0.05).') # Test debugging switched off settings['debug'] = False mi = est_mi.estimate(source, target) cmi = est_cmi.estimate(source, target) settings['local_values'] = True mi = est_mi.estimate(source, target) cmi = est_cmi.estimate(source, target)
def test_local_values(): """Test estimation of local MI and CMI using OpenCL estimators.""" # Get data n_chunks = 2 expec_mi, source, source_uncorr, target = _get_gauss_data(n=20000, seed=SEED) chunklength = int(source.shape[0] / n_chunks) # Estimate local values settings = {'local_values': True} est_cmi = OpenCLKraskovCMI(settings=settings) cmi = est_cmi.estimate(source, target, source_uncorr, n_chunks=n_chunks) est_mi = OpenCLKraskovMI(settings=settings) mi = est_mi.estimate(source, target, n_chunks=n_chunks) mi_ch1 = np.mean(mi[0:chunklength]) mi_ch2 = np.mean(mi[chunklength:]) cmi_ch1 = np.mean(cmi[0:chunklength]) cmi_ch2 = np.mean(cmi[chunklength:]) # Estimate non-local values for comparison settings = {'local_values': False} est_cmi = OpenCLKraskovCMI(settings=settings) mi = est_cmi.estimate(source, target, source_uncorr, n_chunks=n_chunks) est_mi = OpenCLKraskovMI(settings=settings) cmi = est_mi.estimate(source, target, n_chunks=n_chunks) # Report results print('OpenCL MI result: {0:.4f} nats (chunk 1); {1:.4f} nats (chunk 2) ' 'expected to be close to {2:.4f} nats for uncorrelated ' 'Gaussians.'.format(mi_ch1, mi_ch2, expec_mi)) print('OpenCL CMI result: {0:.4f} nats (chunk 1); {1:.4f} nats (chunk 2) ' 'expected to be close to {2:.4f} nats for uncorrelated ' 'Gaussians.'.format(cmi_ch1, cmi_ch2, expec_mi)) assert np.isclose(mi_ch1, expec_mi, atol=0.05) assert np.isclose(mi_ch2, expec_mi, atol=0.05) assert np.isclose(cmi_ch1, expec_mi, atol=0.05) assert np.isclose(cmi_ch2, expec_mi, atol=0.05) assert np.isclose(mi_ch1, mi_ch2, atol=0.05) assert np.isclose(mi_ch1, mi[0], atol=0.05) assert np.isclose(mi_ch2, mi[1], atol=0.05) assert np.isclose(cmi_ch1, cmi_ch2, atol=0.05) assert np.isclose(cmi_ch1, cmi[0], atol=0.05) assert np.isclose(cmi_ch2, cmi[1], atol=0.05)
def test_local_values(): """Test estimation of local MI and CMI using OpenCL estimators.""" # Get data n_chunks = 2 expec_mi, source, source_uncorr, target = _get_gauss_data(n=20000) chunklength = int(source.shape[0] / n_chunks) # Estimate local values settings = {'local_values': True} est_cmi = OpenCLKraskovCMI(settings=settings) cmi = est_cmi.estimate(source, target, source_uncorr, n_chunks=n_chunks) est_mi = OpenCLKraskovMI(settings=settings) mi = est_mi.estimate(source, target, n_chunks=n_chunks) mi_ch1 = np.mean(mi[0:chunklength]) mi_ch2 = np.mean(mi[chunklength:]) cmi_ch1 = np.mean(cmi[0:chunklength]) cmi_ch2 = np.mean(cmi[chunklength:]) # Estimate non-local values for comparison settings = {'local_values': False} est_cmi = OpenCLKraskovCMI(settings=settings) mi = est_cmi.estimate(source, target, source_uncorr, n_chunks=n_chunks) est_mi = OpenCLKraskovMI(settings=settings) cmi = est_mi.estimate(source, target, n_chunks=n_chunks) # Report results print('OpenCL MI result: {0:.4f} nats (chunk 1); {1:.4f} nats (chunk 2) ' 'expected to be close to {2:.4f} nats for uncorrelated ' 'Gaussians.'.format(mi_ch1, mi_ch2, expec_mi)) print('OpenCL CMI result: {0:.4f} nats (chunk 1); {1:.4f} nats (chunk 2) ' 'expected to be close to {2:.4f} nats for uncorrelated ' 'Gaussians.'.format(cmi_ch1, cmi_ch2, expec_mi)) assert np.isclose(mi_ch1, expec_mi, atol=0.05) assert np.isclose(mi_ch2, expec_mi, atol=0.05) assert np.isclose(cmi_ch1, expec_mi, atol=0.05) assert np.isclose(cmi_ch2, expec_mi, atol=0.05) assert np.isclose(mi_ch1, mi_ch2, atol=0.05) assert np.isclose(mi_ch1, mi[0], atol=0.05) assert np.isclose(mi_ch2, mi[1], atol=0.05) assert np.isclose(cmi_ch1, cmi_ch2, atol=0.05) assert np.isclose(cmi_ch1, cmi[0], atol=0.05) assert np.isclose(cmi_ch2, cmi[1], atol=0.05)
def test_gauss_data(): """Test bivariate TE 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, 'max_lag_target': 1 } nw = BivariateTE() results = nw.analyse_single_target(settings, data, target=2, sources=[0, 1]) te = results.get_single_target(2, fdr=False)['te'][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 BivarateTE() estimate to JIDT estimate. current_value = (2, 2) source_vars = results.get_single_target(2, False)['selected_vars_sources'] target_vars = results.get_single_target(2, False)['selected_vars_target'] var1 = data.get_realisations(current_value, source_vars)[0] var2 = data.get_realisations(current_value, [current_value])[0] cond = data.get_realisations(current_value, target_vars)[0] est = JidtKraskovCMI({}) jidt_cmi = est.estimate(var1=var1, var2=var2, conditional=cond) print('Estimated TE: {0:0.6f}, estimated TE using JIDT core estimator: ' '{1:0.6f} (expected: {2:0.6f}).'.format(te, jidt_cmi, expected_mi)) assert np.isclose(te, jidt_cmi, atol=0.005), ( 'Estimated TE {0:0.6f} differs from JIDT estimate {1:0.6f} (expected: ' 'TE {2:0.6f}).'.format(te, jidt_cmi, 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_gauss_data(): """Test bivariate TE 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, 'max_lag_target': 1} nw = BivariateTE() results = nw.analyse_single_target( settings, data, target=2, sources=[0, 1]) te = results.get_single_target(2, fdr=False)['te'][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 BivarateTE() estimate to JIDT estimate. current_value = (2, 2) source_vars = results.get_single_target(2, False)['selected_vars_sources'] target_vars = results.get_single_target(2, False)['selected_vars_target'] var1 = data.get_realisations(current_value, source_vars)[0] var2 = data.get_realisations(current_value, [current_value])[0] cond = data.get_realisations(current_value, target_vars)[0] est = JidtKraskovCMI({}) jidt_cmi = est.estimate(var1=var1, var2=var2, conditional=cond) print('Estimated TE: {0:0.6f}, estimated TE using JIDT core estimator: ' '{1:0.6f} (expected: {2:0.6f}).'.format(te, jidt_cmi, expected_mi)) assert np.isclose(te, jidt_cmi, atol=0.005), ( 'Estimated TE {0:0.6f} differs from JIDT estimate {1:0.6f} (expected: ' 'TE {2:0.6f}).'.format(te, jidt_cmi, expected_mi))
def test_mi_correlated_gaussians_two_chunks(): """Test estimators on two chunks of correlated Gaussian data.""" expected_mi, source, source_uncorr, target = _get_gauss_data(n=20000, seed=SEED) n_points = source.shape[0] # Run OpenCL estimator. n_chunks = 2 settings = {'debug': True, 'return_counts': True} ocl_est = OpenCLKraskovMI(settings=settings) mi_ocl, dist, n_range_var1, n_range_var2 = ocl_est.estimate( source, target, n_chunks=n_chunks) # Run JIDT estimator. jidt_est = JidtKraskovMI(settings={}) mi_jidt = jidt_est.estimate(source[0:int(n_points / 2), :], target[0:int(n_points / 2), :]) print('JIDT MI result: {0:.4f} nats; OpenCL MI result: [{1:.4f}, {2:.4f}] ' 'nats; expected to be close to {3:.4f} nats for correlated ' 'Gaussians.'.format(mi_jidt, mi_ocl[0], mi_ocl[1], expected_mi)) assert np.isclose( mi_jidt, expected_mi, atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'JIDT estimator failed (error larger 0.05).') assert np.isclose( mi_ocl[0], expected_mi, atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose( mi_ocl[0], mi_jidt, atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose( mi_ocl[1], mi_jidt, atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose( mi_ocl[0], mi_ocl[1], atol=0.05), ('MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).')
def test_compare_bivariate_and_multivariate_te(): """Compare bivariate to multivariate TE estimation.""" expected_mi, source, source_uncorr, target = _get_gauss_data(seed=SEED) source = source[1:] source_uncorr = source_uncorr[1:] target = target[:-1] data = Data(np.hstack((source, source_uncorr, target)), dim_order='sp', normalise=False, seed=SEED) 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': 1, 'min_lag_sources': 1, 'max_lag_target': 1 } nw_bivar = BivariateTE() results = nw_bivar.analyse_single_target(settings, data, target=2, sources=[0, 1]) te_bivar = results.get_single_target(2, fdr=False)['te'][0] nw_multivar = MultivariateTE() results = nw_multivar.analyse_single_target(settings, data, target=2, sources=[0, 1]) te_multivar = results.get_single_target(2, fdr=False)['te'][0] print('Estimated TE: {0:0.6f}, estimated TE using multivariate algorithm: ' '{1:0.6f} (expected: ~ {2:0.6f}).'.format(te_bivar, te_multivar, expected_mi)) assert np.isclose(te_bivar, te_multivar, atol=0.005), ( 'Estimated TE {0:0.6f} differs from multivariate estimate {1:0.6f} ' '(expected: TE {2:0.6f}).'.format(te_bivar, te_multivar, expected_mi))
def test_mi_correlated_gaussians_two_chunks(): """Test estimators on two chunks of correlated Gaussian data.""" expected_mi, source, source_uncorr, target = _get_gauss_data(n=20000) n_points = source.shape[0] # Run OpenCL estimator. n_chunks = 2 settings = {'debug': True} ocl_est = OpenCLKraskovMI(settings=settings) mi_ocl, dist, n_range_var1, n_range_var2 = ocl_est.estimate( source, target, n_chunks=n_chunks) # Run JIDT estimator. jidt_est = JidtKraskovMI(settings={}) mi_jidt = jidt_est.estimate(source[0:int(n_points/2), :], target[0:int(n_points/2), :]) print('JIDT MI result: {0:.4f} nats; OpenCL MI result: [{1:.4f}, {2:.4f}] ' 'nats; expected to be close to {3:.4f} nats for correlated ' 'Gaussians.'.format(mi_jidt, mi_ocl[0], mi_ocl[1], expected_mi)) assert np.isclose(mi_jidt, expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'JIDT estimator failed (error larger 0.05).') assert np.isclose(mi_ocl[0], expected_mi, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose(mi_ocl[0], mi_jidt, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose(mi_ocl[1], mi_jidt, atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).') assert np.isclose(mi_ocl[0], mi_ocl[1], atol=0.05), ( 'MI estimation for uncorrelated Gaussians using the ' 'OpenCL estimator failed (error larger 0.05).')
def test_multivariate_te_corr_gaussian(estimator=None): """Test multivariate TE estimation on correlated Gaussians. Run the multivariate TE algorithm on two sets of random Gaussian data with a given covariance. The second data set is shifted by one sample creating a source-target delay of one sample. This example is modeled after the JIDT demo 4 for transfer entropy. The resulting TE can be compared to the analytical result (but expect some error in the estimate). The simulated delay is 1 sample, i.e., the algorithm should find significant TE from sample (0, 1), a sample in process 0 with lag/delay 1. The final target sample should always be (1, 1), the mandatory sample at lat 1, because there is no memory in the process. Note: This test runs considerably faster than other system tests. This produces strange small values for non-coupled sources. TODO """ if estimator is None: estimator = 'JidtKraskovCMI' cov = 0.4 expected_mi, source1, source2, target = _get_gauss_data(covariance=cov) # n = 1000 # source = [rn.normalvariate(0, 1) for r in range(n)] # target = [sum(pair) for pair in zip( # [cov * y for y in source], # [(1 - cov) * y for y in [rn.normalvariate(0, 1) for r in range(n)]])] # # Cast everything to numpy so the idtxl estimator understands it. # source = np.expand_dims(np.array(source), axis=1) # target = np.expand_dims(np.array(target), axis=1) data = Data(normalise=True) data.set_data(np.vstack((source1[1:].T, target[:-1].T)), 'ps') settings = { 'cmi_estimator': estimator, 'discretise_method': 'max_ent', 'max_lag_sources': 5, 'min_lag_sources': 1, 'max_lag_target': 5, 'n_perm_max_stat': 21, 'n_perm_min_stat': 21, 'n_perm_omnibus': 21, 'n_perm_max_seq': 21, } random_analysis = MultivariateTE() results_max_ent = random_analysis.analyse_single_target(settings, data, 1) settings['discretise_method'] = 'equal' settings['n_discrete_bins'] = 5 results_equal = random_analysis.analyse_single_target(settings, data, 1) # Assert that there are significant conditionals from the source for target # 1. For 500 repetitions I got mean errors of 0.02097686 and 0.01454073 for # examples 1 and 2 respectively. The maximum errors were 0.093841 and # 0.05833172 repectively. This inspired the following error boundaries. corr_expected = cov / (1 * np.sqrt(cov**2 + (1-cov)**2)) expected_res = calculate_mi(corr_expected) estimated_res_max_ent = results_max_ent.get_single_target(1, fdr=False)['te'][0] estimated_res_equal = results_equal.get_single_target(1, fdr=False)['te'][0] diff_max_ent = np.abs(estimated_res_max_ent - expected_res) diff_equal = np.abs(estimated_res_equal - expected_res) print('Expected source sample: (0, 1)\nExpected target sample: (1, 1)') print(('Max. entropy binning - estimated TE: {0:5.4f}, analytical result: ' '{1:5.4f}, error: {2:2.2f} % ').format( estimated_res_max_ent, expected_res, diff_max_ent / expected_res)) print(('Equal binning - estimated TE: {0:5.4f}, analytical result: ' '{1:5.4f}, error: {2:2.2f} % ').format( estimated_res_equal, expected_res, diff_equal / expected_res)) assert diff_max_ent < 0.1, ( 'Multivariate TE calculation for correlated Gaussians using ' 'discretised data with max. entropy binning failed (error larger 0.1: ' '{0}, expected: {1}, actual: {2}).'.format( diff_max_ent, expected_res, results_max_ent['cond_sources_te'])) assert diff_equal < 0.1, ( 'Multivariate TE calculation for correlated Gaussians using ' 'discretised data with equal binning failed (error larger 0.1: {0}, ' 'expected: {1}, actual: {2}).'.format( diff_max_ent, expected_res, results_max_ent['cond_sources_te']))
def test_calculate_single_link(): """Test calculation of single link (conditional) MI and TE.""" 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') n = NetworkAnalysis() n._cmi_estimator = JidtKraskovCMI(settings={}) n.settings = {'local_values': False} current_value = (2, 1) # Test single link estimation for a single and multiple sources for # cases: no target vars, source vars/no source vars (tests if the # conditioning set is built correctly for conditioning='full'). source_realisations = data.get_realisations(current_value, [(0, 0)])[0] current_value_realisations = data.get_realisations(current_value, [current_value])[0] expected_mi = n._cmi_estimator.estimate(current_value_realisations, source_realisations) # cond. on second source cond_realisations = data.get_realisations(current_value, [(1, 0)])[0] expected_mi_cond1 = n._cmi_estimator.estimate(current_value_realisations, source_realisations, cond_realisations) for sources in ['all', [0]]: for conditioning in ['full', 'target', 'none']: for source_vars in [[(0, 0)], [(0, 0), (1, 0)]]: mi = n._calculate_single_link(data, current_value, source_vars, target_vars=None, sources=sources, conditioning=conditioning) if mi.shape[0] > 1: # array for source='all' mi = mi[0] if source_vars == [(0, 0)]: # no conditioning assert np.isclose(mi, expected_mi, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from expected ' 'MI ({1}).'.format(mi, expected_mi)) else: if conditioning == 'full': # cond. on second source assert np.isclose(mi, expected_mi_cond1, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi_cond1)) else: # no conditioning assert np.isclose(mi, expected_mi, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi)) # Test single link estimation for a single and multiple sources for # cases: target vars/no target vars, source vars (tests if the # conditioning set is built correctly for conditioning='full'). cond_realisations = np.hstack(( # cond. on second source and target data.get_realisations(current_value, [(1, 0)])[0], data.get_realisations(current_value, [(2, 0)])[0])) expected_mi_cond2 = n._cmi_estimator.estimate( current_value_realisations, source_realisations, cond_realisations) # cond. on target cond_realisations = data.get_realisations(current_value, [(2, 0)])[0] expected_mi_cond3 = n._cmi_estimator.estimate( current_value_realisations, source_realisations, cond_realisations) for target_vars in [None, [(2, 0)]]: for conditioning in ['full', 'target', 'none']: mi = n._calculate_single_link(data, current_value, source_vars=[(0, 0), (1, 0)], target_vars=target_vars, sources=sources, conditioning=conditioning) if mi.shape[0] > 1: # array for source='all' mi = mi[0] if conditioning == 'none': # no conditioning assert np.isclose(mi, expected_mi, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from expected ' 'MI ({1}).'.format(mi, expected_mi)) else: # target only if target_vars is not None and conditioning == 'target': assert np.isclose(mi, expected_mi_cond3, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi_cond3)) # target and 2nd source if target_vars is not None and conditioning == 'full': assert np.isclose(mi, expected_mi_cond2, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi_cond2)) # target is None, condition on second target else: if conditioning == 'full': assert np.isclose( mi, expected_mi_cond1, rtol=0.05 ), ('Estimated single-link MI ({0}) differs from expected ' 'MI ({1}).'.format(mi, expected_mi_cond1)) # Test requested sources not in source vars with pytest.raises(RuntimeError): mi = n._calculate_single_link(data, current_value, source_vars=[(0, 0), (3, 0)], target_vars=None, sources=4, conditioning='full') # Test source vars not in data/processes with pytest.raises(IndexError): mi = n._calculate_single_link(data, current_value, source_vars=[(0, 0), (10, 0)], target_vars=None, sources='all', conditioning='full') # Test unknown conditioning with pytest.raises(RuntimeError): mi = n._calculate_single_link(data, current_value, source_vars=[(0, 0)], conditioning='test')
def test_calculate_single_link(): """Test calculation of single link (conditional) MI and TE.""" 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') n = NetworkAnalysis() n._cmi_estimator = JidtKraskovCMI(settings={}) n.settings = { 'local_values': False } current_value = (2, 1) # Test single link estimation for a single and multiple sources for # cases: no target vars, source vars/no source vars (tests if the # conditioning set is built correctly for conditioning='full'). source_realisations = data.get_realisations(current_value, [(0, 0)])[0] current_value_realisations = data.get_realisations( current_value, [current_value])[0] expected_mi = n._cmi_estimator.estimate( current_value_realisations, source_realisations) # cond. on second source cond_realisations = data.get_realisations(current_value, [(1, 0)])[0] expected_mi_cond1 = n._cmi_estimator.estimate( current_value_realisations, source_realisations, cond_realisations) for sources in ['all', [0]]: for conditioning in ['full', 'target', 'none']: for source_vars in [[(0, 0)], [(0, 0), (1, 0)]]: mi = n._calculate_single_link( data, current_value, source_vars, target_vars=None, sources=sources, conditioning=conditioning) if mi.shape[0] > 1: # array for source='all' mi = mi[0] if source_vars == [(0, 0)]: # no conditioning assert np.isclose(mi, expected_mi, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from expected ' 'MI ({1}).'.format(mi, expected_mi)) else: if conditioning == 'full': # cond. on second source assert np.isclose(mi, expected_mi_cond1, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi_cond1)) else: # no conditioning assert np.isclose(mi, expected_mi, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi)) # Test single link estimation for a single and multiple sources for # cases: target vars/no target vars, source vars (tests if the # conditioning set is built correctly for conditioning='full'). cond_realisations = np.hstack(( # cond. on second source and target data.get_realisations(current_value, [(1, 0)])[0], data.get_realisations(current_value, [(2, 0)])[0] )) expected_mi_cond2 = n._cmi_estimator.estimate( current_value_realisations, source_realisations, cond_realisations) # cond. on target cond_realisations = data.get_realisations(current_value, [(2, 0)])[0] expected_mi_cond3 = n._cmi_estimator.estimate( current_value_realisations, source_realisations, cond_realisations) for target_vars in [None, [(2, 0)]]: for conditioning in ['full', 'target', 'none']: mi = n._calculate_single_link( data, current_value, source_vars=[(0, 0), (1, 0)], target_vars=target_vars, sources=sources, conditioning=conditioning) if mi.shape[0] > 1: # array for source='all' mi = mi[0] if conditioning == 'none': # no conditioning assert np.isclose(mi, expected_mi, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from expected ' 'MI ({1}).'.format(mi, expected_mi)) else: # target only if target_vars is not None and conditioning == 'target': assert np.isclose(mi, expected_mi_cond3, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi_cond3)) # target and 2nd source if target_vars is not None and conditioning == 'full': assert np.isclose(mi, expected_mi_cond2, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from ' 'expected MI ({1}).'.format(mi, expected_mi_cond2)) # target is None, condition on second target else: if conditioning == 'full': assert np.isclose(mi, expected_mi_cond1, rtol=0.05), ( 'Estimated single-link MI ({0}) differs from expected ' 'MI ({1}).'.format(mi, expected_mi_cond1)) # Test requested sources not in source vars with pytest.raises(RuntimeError): mi = n._calculate_single_link( data, current_value, source_vars=[(0, 0), (3, 0)], target_vars=None, sources=4, conditioning='full') # Test source vars not in data/processes with pytest.raises(IndexError): mi = n._calculate_single_link( data, current_value, source_vars=[(0, 0), (10, 0)], target_vars=None, sources='all', conditioning='full') # Test unknown conditioning with pytest.raises(RuntimeError): mi = n._calculate_single_link( data, current_value, source_vars=[(0, 0)], conditioning='test')