def test_from_product(): d1 = MultiNorm(mean=[0, 0]) d2 = MultiNorm(mean=[2, 4]) mn = MultiNorm.from_product([d1, d2]) assert_allclose(mn.mean, [1, 2]) assert_allclose(mn.cov, [[0.5, 0], [0, 0.5]])
def test_from_stack(): d1 = MultiNorm(mean=[1, 2], cov=np.full((2, 2), 2)) d2 = MultiNorm(mean=[3, 4, 5], cov=np.full((3, 3), 3)) mn = MultiNorm.from_stack([d1, d2]) assert_allclose(mn.mean, [1, 2, 3, 4, 5]) assert_allclose(mn.cov[0], [2, 2, 0, 0, 0]) assert_allclose(mn.cov[4], [0, 0, 3, 3, 3])
def test_init_singular(): # It should be possible to create a MultiNorm # with a singular cov matrix, because e.g. # when fixing parameters, that is what comes out. cov = [[1, 0], [0, 0]] mn = MultiNorm(cov=cov) assert_allclose(mn.cov, cov)
def test_from_err(): # Test with default: no correlation mean = [10, 20, 30] err = [1, 2, 3] correlation = None mn = MultiNorm.from_error(mean, err, correlation) assert_allclose(mn.mean, mean) assert_allclose(mn.cov, [[1, 0, 0], [0, 4, 0], [0, 0, 9]]) # Test with given correlation correlation = [[1, 0.8, 0], [0.8, 1, 0.1], [0.0, 0.1, 1]] mn = MultiNorm.from_error(error=err, correlation=correlation) assert_allclose(mn.correlation, correlation) with pytest.raises(ValueError): MultiNorm.from_error(mean)
def test_conditional_vs_fix(): # Conditional and fix should be the same (up to numerical errors) mn = MultiNorm.make_example(n_par=5) a = mn.conditional([1, 2, 3]) b = mn.fix([1, 2, 3]) assert_multinorm_allclose(a, b)
def mn3(): """Example test case with very large and small numbers. This is numerically challenging for several computations. Ideally all methods in `MultiNorm` should be able to handle this case and give accurate results, because it's quite common. """ mean = np.array([1e-10, 1, 1e10]) error = 1.0 * mean return MultiNorm.from_error(mean, error)
def mn2(): """Example test case with correlations. - [0, 1] correlation: 0.89442719 (large correlation) - [0, 2] correlation: 0.0 (uncorrelated) - [1, 2] correlation: 0.12909944 (small correlation) These are pretty much arbitrary numbers, when used in tests outputs will only establish current behaviour or allow testing against other codes. This is the same test case as used in scipy here: https://github.com/scipy/scipy/blob/23a648dd5a99de93901abb431885948cd4df14ff/scipy/stats/tests/test_multivariate.py#L349-L350 """ mean = [1, 3, 2] cov = [[1, 2, 0], [2, 5, 0.5], [0, 0.5, 3]] return MultiNorm(mean, cov)
""" Check the numpy / scipy methods we use. Mostly the question at the moment is how to get numerically stable `from_product`, i.e. which matrix inverse function to use, or how to rewrite `from_product` in a better way. """ import numpy as np from multinorm import MultiNorm mean = np.array([1e-20, 1, 1e20]) err = 1 * mean names = ["a", "b", "c"] mn = MultiNorm.from_error(mean, err, names=names) print(mn) print(mn.cov.values) # BAD try: print(mn.precision.values) except np.linalg.LinAlgError: print("SINGULAR m3.precision") # GOOD print(np.linalg.inv(mn.cov.values))
def test_init_bad(): with pytest.raises(ValueError): MultiNorm(mean=[0, 0, 0], cov=[[1, 2], [3, 4]])
def test_init_empty(): mn = MultiNorm() assert mn.mean.shape == (1, ) assert mn.cov.shape == (1, 1)
def test_init_partially(): mn = MultiNorm(mean=[1, 2]) assert_allclose(mn.error, [1, 1]) mn = MultiNorm(cov=[[1, 0], [0, 1]]) assert_allclose(mn.mean, [0, 0])
def test_init_dtype(dtype): # Make sure we always get float64 and good precision mn = MultiNorm(np.zeros(2, dtype=dtype), np.eye(2, dtype=dtype)) assert mn.mean.dtype == np.float64 assert mn.cov.dtype == np.float64
def test_make_example(): mn = MultiNorm.make_example(n_par=2, n_fix=1, random_state=0) assert_allclose(mn.mean, [1.76405235, 0.40015721, 0.97873798]) expected = [[8.50937518, -0.41563014, 0], [-0.41563014, 1.85774006, 0], [0, 0, 0]] assert_allclose(mn.cov, expected)
def test_from_product_numerics(mn3): # Check that `from_product` gives good results # even if some parameters are very small and others very large # Product of 10 measurements should reduce variance by factor 10 mn = MultiNorm.from_product([mn3] * 10) assert_allclose(mn.cov, np.diag([1e-21, 0.1, 1e19]))
def mn1(): """Example test case without correlations.""" mean = [10, 20, 30] covariance = [[1, 0, 0], [0, 4, 0], [0, 0, 9]] return MultiNorm(mean, covariance)
def test_from_samples(): points = [(10, 20, 30), (12, 20, 30)] mn = MultiNorm.from_samples(points) assert_allclose(mn.mean, [11, 20, 30]) assert_allclose(mn.cov, [[2, 0, 0], [0, 0, 0], [0, 0, 0]])