|
45 | 45 | from tsdate.core import Likelihoods
|
46 | 46 | from tsdate.core import LogLikelihoods
|
47 | 47 | from tsdate.core import posterior_mean_var
|
| 48 | +from tsdate.demography import PopulationSizeHistory |
48 | 49 | from tsdate.prior import ConditionalCoalescentTimes
|
49 | 50 | from tsdate.prior import fill_priors
|
50 | 51 | from tsdate.prior import gamma_approx
|
51 | 52 | from tsdate.prior import PriorParams
|
52 | 53 | from tsdate.prior import SpansBySamples
|
53 |
| -from tsdate.util import change_time_measure |
54 | 54 | from tsdate.util import nodes_time_unconstrained
|
55 | 55 |
|
56 | 56 |
|
@@ -512,7 +512,7 @@ def test_two_tree_mutation_ts_intervals(self):
|
512 | 512 | class TestPriorVals:
|
513 | 513 | def verify_prior_vals(self, ts, prior_distr, **kwargs):
|
514 | 514 | span_data = SpansBySamples(ts, **kwargs)
|
515 |
| - Ne = np.array([[0, 0.5]]) |
| 515 | + Ne = PopulationSizeHistory(0.5) |
516 | 516 | priors = ConditionalCoalescentTimes(None, prior_distr=prior_distr)
|
517 | 517 | priors.add(ts.num_samples, approximate=False)
|
518 | 518 | grid = np.linspace(0, 3, 3)
|
@@ -1102,7 +1102,7 @@ def run_outside_algorithm(
|
1102 | 1102 | self, ts, prior_distr="lognorm", standardize=False, ignore_oldest_root=False
|
1103 | 1103 | ):
|
1104 | 1104 | span_data = SpansBySamples(ts)
|
1105 |
| - Ne = np.array([[0, 0.5]]) |
| 1105 | + Ne = PopulationSizeHistory(0.5) |
1106 | 1106 | priors = ConditionalCoalescentTimes(None, prior_distr)
|
1107 | 1107 | priors.add(ts.num_samples, approximate=False)
|
1108 | 1108 | grid = np.array([0, 1.2, 2])
|
@@ -1205,7 +1205,7 @@ class TestTotalFunctionalValueTree:
|
1205 | 1205 | def find_posterior(self, ts, prior_distr):
|
1206 | 1206 | grid = np.array([0, 1.2, 2])
|
1207 | 1207 | span_data = SpansBySamples(ts)
|
1208 |
| - Ne = np.array([[0, 0.5]]) |
| 1208 | + Ne = PopulationSizeHistory(0.5) |
1209 | 1209 | priors = ConditionalCoalescentTimes(None, prior_distr=prior_distr)
|
1210 | 1210 | priors.add(ts.num_samples, approximate=False)
|
1211 | 1211 | mixture_priors = priors.get_mixture_prior_params(span_data)
|
@@ -1269,7 +1269,7 @@ def test_gil_tree(self):
|
1269 | 1269 | ts = utility_functions.gils_example_tree()
|
1270 | 1270 | span_data = SpansBySamples(ts)
|
1271 | 1271 | prior_distr = "lognorm"
|
1272 |
| - Ne = np.array([[0, 0.5]]) |
| 1272 | + Ne = PopulationSizeHistory(0.5) |
1273 | 1273 | priors = ConditionalCoalescentTimes(None, prior_distr=prior_distr)
|
1274 | 1274 | priors.add(ts.num_samples, approximate=False)
|
1275 | 1275 | grid = np.array([0, 0.1, 0.2, 0.5, 1, 2, 5])
|
@@ -1978,45 +1978,95 @@ def test_historical_samples(self):
|
1978 | 1978 | )
|
1979 | 1979 |
|
1980 | 1980 |
|
1981 |
| -class TestRescaleTime: |
1982 |
| - def test_rescale(self): |
| 1981 | +class TestPopulationSizeHistory: |
| 1982 | + def test_change_time_measure_scalar(self): |
1983 | 1983 | Ne = 10000
|
1984 | 1984 | coaltime = np.array([0, 1, 2, 3])
|
1985 | 1985 | coalstart = np.array([0])
|
1986 | 1986 | coalrate = np.array([1 / (2 * Ne)])
|
1987 |
| - gens, _, _ = change_time_measure(coaltime, coalstart, coalrate) |
| 1987 | + gens, _, _ = PopulationSizeHistory._change_time_measure( |
| 1988 | + coaltime, coalstart, coalrate |
| 1989 | + ) |
1988 | 1990 | assert np.allclose(gens, 2 * coaltime * Ne)
|
1989 | 1991 |
|
1990 |
| - def test_piecewise(self): |
| 1992 | + def test_change_time_measure_piecewise(self): |
1991 | 1993 | Ne = np.array([2000, 3000, 5000])
|
1992 | 1994 | start = np.array([0, 4000, 10000])
|
1993 | 1995 | gens = np.array([2000, 7000, 15000])
|
1994 |
| - coaltime, coalstart, coalrate = change_time_measure(gens, start, 2 * Ne) |
| 1996 | + coaltime, coalstart, coalrate = PopulationSizeHistory._change_time_measure( |
| 1997 | + gens, start, 2 * Ne |
| 1998 | + ) |
1995 | 1999 | assert np.allclose(coalstart, np.array([0, 1, 2]))
|
1996 | 2000 | assert np.allclose(coaltime, np.array([0.5, 1.5, 2.5]))
|
1997 | 2001 | assert np.allclose(coalrate, 1 / (2 * Ne))
|
1998 | 2002 |
|
1999 |
| - def test_piecewise_bijection(self): |
| 2003 | + def test_change_time_measure_bijection(self): |
2000 | 2004 | hapNe = np.array([2000, 3000, 5000])
|
2001 | 2005 | start = np.array([0, 4000, 10000])
|
2002 | 2006 | gens = np.array([500, 7000, 15000])
|
2003 |
| - coaltime, coalstart, coalrate = change_time_measure(gens, start, hapNe) |
2004 |
| - gens_back, start_back, hapNe_back = change_time_measure( |
| 2007 | + coaltime, coalstart, coalrate = PopulationSizeHistory._change_time_measure( |
| 2008 | + gens, start, hapNe |
| 2009 | + ) |
| 2010 | + gens_back, start_back, hapNe_back = PopulationSizeHistory._change_time_measure( |
2005 | 2011 | coaltime, coalstart, coalrate
|
2006 | 2012 | )
|
2007 | 2013 | assert np.allclose(gens, gens_back)
|
2008 | 2014 | assert np.allclose(start, start_back)
|
2009 | 2015 | assert np.allclose(hapNe, hapNe_back)
|
2010 | 2016 |
|
2011 |
| - def test_piecewise_numerically(self): |
| 2017 | + def test_change_time_measure_numerically(self): |
2012 | 2018 | coalrate = np.array([0.001, 0.01, 0.1])
|
2013 | 2019 | coalstart = np.array([0, 1, 2])
|
2014 | 2020 | coaltime = np.linspace(0, 3, 10)
|
2015 |
| - gens, _, _ = change_time_measure(coaltime, coalstart, coalrate) |
| 2021 | + gens, _, _ = PopulationSizeHistory._change_time_measure( |
| 2022 | + coaltime, coalstart, coalrate |
| 2023 | + ) |
2016 | 2024 | for i in range(gens.size):
|
2017 | 2025 | x, _ = scipy.integrate.quad(
|
2018 | 2026 | lambda t: 1 / coalrate[np.digitize(t, coalstart) - 1],
|
2019 | 2027 | a=0,
|
2020 | 2028 | b=coaltime[i],
|
2021 | 2029 | )
|
2022 | 2030 | assert np.isclose(x, gens[i])
|
| 2031 | + |
| 2032 | + def test_to_coalescent_timescale(self): |
| 2033 | + demography = PopulationSizeHistory( |
| 2034 | + np.array([1000, 2000, 3000]), np.array([500, 2500]) |
| 2035 | + ) |
| 2036 | + coaltime = demography.to_coalescent_timescale(np.array([250, 1500])) |
| 2037 | + assert np.allclose(coaltime, [0.125, 0.5]) |
| 2038 | + |
| 2039 | + def test_to_natural_timescale(self): |
| 2040 | + demography = PopulationSizeHistory( |
| 2041 | + np.array([1000, 2000, 3000]), np.array([500, 2500]) |
| 2042 | + ) |
| 2043 | + time = demography.to_natural_timescale(np.array([0.125, 0.5])) |
| 2044 | + assert np.allclose(time, [250, 1500]) |
| 2045 | + |
| 2046 | + def test_single_epoch(self): |
| 2047 | + for Ne in [10000, np.array([10000])]: |
| 2048 | + demography = PopulationSizeHistory(Ne) |
| 2049 | + time = demography.to_natural_timescale(np.array([0, 1, 2, 3])) |
| 2050 | + assert np.allclose(time, [0.0, 20000, 40000, 60000]) |
| 2051 | + |
| 2052 | + def test_bad_arguments(self): |
| 2053 | + with pytest.raises(ValueError, match="a numpy array"): |
| 2054 | + PopulationSizeHistory([1]) |
| 2055 | + with pytest.raises(ValueError, match="a numpy array"): |
| 2056 | + PopulationSizeHistory(np.array([1, 1]), [1]) |
| 2057 | + with pytest.raises(ValueError, match="must be greater than 0"): |
| 2058 | + PopulationSizeHistory(0) |
| 2059 | + with pytest.raises(ValueError, match="must be greater than 0"): |
| 2060 | + PopulationSizeHistory(np.array([0, 0]), np.array([1])) |
| 2061 | + with pytest.raises(ValueError, match="must be greater than 0"): |
| 2062 | + PopulationSizeHistory(np.array([1, 1]), np.array([0])) |
| 2063 | + with pytest.raises(ValueError, match="one less than the number"): |
| 2064 | + PopulationSizeHistory(np.array([1]), np.array([1])) |
| 2065 | + with pytest.raises(ValueError, match="increasing order"): |
| 2066 | + PopulationSizeHistory(np.array([1, 1, 1]), np.array([2, 1])) |
| 2067 | + demography = PopulationSizeHistory(1) |
| 2068 | + for time in [1, [1]]: |
| 2069 | + with pytest.raises(ValueError, match="a numpy array"): |
| 2070 | + demography.to_natural_timescale(time) |
| 2071 | + with pytest.raises(ValueError, match="a numpy array"): |
| 2072 | + demography.to_coalescent_timescale(time) |
0 commit comments