def HuberThreeEpoch(): id = "QC-African3Epoch_1H18" populations = [ stdpopsim.Population(id="SouthMiddleAtlas", description="A. thalina"), ] # Time of second epoch T_2 = 7420 T_3 = 14534 # population sizes N_ANC = 161744 N_2 = 24076 N_3 = 203077 return stdpopsim.DemographicModel( id=id, description=id, long_description=id, generation_time=_species.generation_time, populations=populations, population_configurations=[ msprime.PopulationConfiguration(initial_size=N_3, metadata=populations[0].asdict()), ], demographic_events=[ msprime.PopulationParametersChange(time=T_3, initial_size=N_2, population_id=0), msprime.PopulationParametersChange(time=T_2 + T_3, initial_size=N_ANC, population_id=0), ], population_id_map=[{ "SouthMiddleAtlas": 0 }] * 3, )
def _afr_2epoch(): N_A = 746148 N_0 = 100218 t_1 = 568344 populations = [ stdpopsim.Population( id="SouthMiddleAtlas", description="Arabidopsis Thaliana South Middle Atlas population") ] return stdpopsim.DemographicModel( id="African2Epoch_1H18", description="South Middle Atlas African two epoch model", long_description=""" Model estimated from site frequency spectrum of synonymous SNPs from African South Middle Atlas samples using Williamson et al. 2005 methodology. Values come from supplementary table 1 of Huber et al 2018. Sizes change from N_A -> N_0 and t_1 is time of the second epoch. """, populations=populations, citations=[stdpopsim.Citation( author="Huber et al.", year=2018, doi="https://doi.org/10.1038/s41467-018-05281-7", reasons={stdpopsim.CiteReason.DEM_MODEL}) ], generation_time=1, population_configurations=[ msprime.PopulationConfiguration( initial_size=N_0, metadata=populations[0].asdict()) ], demographic_events=[ msprime.PopulationParametersChange( time=t_1, initial_size=N_A, population_id=0) ] )
def _GAS_sp(): # the size during the interval times[k] to times[k+1] = sizes[k] times = np.array([ 1.08221472e01, 1.08221472e01, 1.77815418e01, 1.77815418e01, 2.43957877e01, 2.43957877e01, 2.62194838e01, 2.62194838e01, 2.80715527e01, 2.80715527e01, 2.99059882e01, 2.99059882e01, 3.17590591e01, 3.17590591e01, 3.36213534e01, 3.36213534e01, 3.55031410e01, 3.55031410e01, 3.74218265e01, 3.74218265e01, 3.93692837e01, 3.93692837e01, 4.13556900e01, 4.13556900e01, 4.33822257e01, 4.33822257e01, 4.54501193e01, 4.54501193e01, 4.75606499e01, 4.75606499e01, 4.97151498e01, 4.97151498e01, 5.19150077e01, 5.19150077e01, 5.41616710e01, 5.41616710e01, 5.64566497e01, 5.64566497e01, 5.88015192e01, 5.88015192e01, 6.11979243e01, 6.11979243e01, 6.36475829e01, 6.36475829e01, 6.61522900e01, 6.61522900e01, 6.87139222e01, 6.87139222e01, 7.13468519e01, 7.13468519e01, 7.40546632e01, 7.40546632e01, 7.69788992e01, 7.69788992e01, 8.00932536e01, 8.00932536e01, 8.33883683e01, 8.33883683e01, 9.33624771e01, 9.33624771e01, 1.05867180e02, 1.05867180e02, 1.19778311e02, 1.19778311e02, 1.34317538e02, 1.34317538e02, 1.49486416e02, 1.49486416e02, 1.65081438e02, 1.65081438e02, 1.81069660e02, 1.81069660e02, 1.96884420e02, 1.96884420e02, 2.13010501e02, 2.13010501e02, 2.28659684e02, 2.28659684e02, 2.43883726e02, 2.43883726e02, 2.58403062e02, 2.58403062e02, 2.70573820e02, 2.70573820e02, 2.75664382e02, 2.75664382e02, 2.80730912e02, 2.80730912e02, 2.85888999e02, 2.85888999e02, 2.91187697e02, 2.91187697e02, 2.96632655e02, 2.96632655e02, 3.02218199e02, 3.02218199e02, 3.07951917e02, 3.07951917e02, 3.13860240e02, 3.13860240e02, 3.19955507e02, 3.19955507e02, 3.26244790e02, 3.26244790e02, 3.32745865e02, 3.32745865e02, 3.39465956e02, 3.39465956e02, 3.46421839e02, 3.46421839e02, 3.53626147e02, 3.53626147e02, 3.61092430e02, 3.61092430e02, 3.68835241e02, 3.68835241e02, 3.76870235e02, 3.76870235e02, 3.85214266e02, 3.85214266e02, 3.93885515e02, 3.93885515e02, 4.02903613e02, 4.02903613e02, 4.12289797e02, 4.12289797e02, 4.22067072e02, 4.22067072e02, 4.32260401e02, 4.32260401e02, 4.42896919e02, 4.42896919e02, 4.54006170e02, 4.54006170e02, 4.65620388e02, 4.65620388e02, 4.77774801e02, 4.77774801e02, 4.90490498e02, 4.90490498e02, 5.03826473e02, 5.03826473e02, 5.17829247e02, 5.17829247e02, 5.32550112e02, 5.32550112e02, 5.48045759e02, 5.48045759e02, 5.64379009e02, 5.64379009e02, 5.81588679e02, 5.81588679e02, 5.99781759e02, 5.99781759e02, 6.19045020e02, 6.19045020e02, 6.39454764e02, 6.39454764e02, 6.61129552e02, 6.61129552e02, 6.84129309e02, 6.84129309e02, 7.08609246e02, 7.08609246e02, 7.34719738e02, 7.34719738e02, 7.62657505e02, 7.62657505e02, 7.92661043e02, 7.92661043e02, 8.24963147e02, 8.24963147e02, 8.59801339e02, 8.59801339e02, 8.97519058e02, 8.97519058e02, 9.38516578e02, 9.38516578e02, 9.83196252e02, 9.83196252e02, 1.03213113e03, 1.03213113e03, 1.08595950e03, 1.08595950e03, 1.14545402e03, 1.14545402e03, 1.21187638e03, 1.21187638e03, 1.42580467e03, 1.42580467e03, 1.66762718e03, 1.66762718e03, 1.94206662e03, 1.94206662e03, 2.25673855e03, 2.25673855e03, 2.61982155e03, 2.61982155e03, 3.04325043e03, 3.04325043e03, 3.54366638e03, 3.54366638e03, 4.14416552e03, 4.14416552e03, 4.86878040e03, 4.86878040e03, 5.74277111e03, 5.74277111e03, 6.06376420e03, 6.06376420e03, 6.48115044e03, 6.48115044e03, 7.16974182e03, 7.16974182e03, 9.94668728e03, 9.94668728e03, 1.08341379e04, 1.08341379e04, 1.12602248e04, 1.12602248e04, 1.80292683e04, ]) sizes = np.array([ 4069863.26413754, 2570469.78880419, 2570469.78880419, 2398970.46335773, 2398970.46335773, 649423.64089016, 649423.64089016, 647425.87204344, 647425.87204344, 629386.55333025, 629386.55333025, 623896.55036331, 623896.55036331, 615171.6634657, 615171.6634657, 609770.71698915, 609770.71698915, 609770.71698915, 609770.71698915, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 606896.78477367, 609770.71698915, 609770.71698915, 612860.29930411, 612860.29930411, 646628.97921259, 646628.97921259, 672653.84034255, 672653.84034255, 694949.57011815, 694949.57011815, 2053484.48904133, 2053484.48904133, 2512451.15337624, 2512451.15337624, 2726859.95574373, 2726859.95574373, 2779609.28386339, 2779609.28386339, 2827486.59107239, 2827486.59107239, 2833326.90480091, 2833326.90480091, 2830283.03259496, 2830283.03259496, 2726859.95574373, 2726859.95574373, 2707367.42825967, 2707367.42825967, 2557240.92209016, 2557240.92209016, 2420531.19687943, 2420531.19687943, 2245241.1128414, 2245241.1128414, 1829782.22978925, 1829782.22978925, 743769.25832605, 743769.25832605, 719107.79112942, 719107.79112942, 710882.47527273, 710882.47527273, 708782.9061541, 708782.9061541, 706605.83914068, 706605.83914068, 702884.83678823, 702884.83678823, 699330.14877435, 699330.14877435, 698106.79217618, 698106.79217618, 697332.03584512, 697332.03584512, 696317.93467906, 696317.93467906, 696167.64460966, 696167.64460966, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 695633.55941906, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 694677.60526595, 693429.24269629, 693429.24269629, 693429.24269629, 693429.24269629, 693429.24269629, 693429.24269629, 692716.93526192, 692716.93526192, 692379.41939462, 692379.41939462, 690176.6983718, 690176.6983718, 688681.83478372, 688681.83478372, 687162.86783629, 687162.86783629, 686235.36369922, 686235.36369922, 686150.90910499, 686150.90910499, 685951.34145025, 685951.34145025, 685005.95081601, 685005.95081601, 684576.59330447, 684576.59330447, 684576.59330447, 684576.59330447, 683889.43627665, 683889.43627665, 683889.43627665, 683889.43627665, 683889.43627665, 683889.43627665, 683889.43627665, 683889.43627665, 687172.58638815, 687172.58638815, 1980227.21562606, 1980227.21562606, 1989715.58702617, 1989715.58702617, 1992430.35210815, 1992430.35210815, 1998953.44050118, 1998953.44050118, 1998953.44050118, 1998953.44050118, 1998160.88128216, 1998160.88128216, 1998160.88128216, 1998160.88128216, 1998160.88128216, 1998160.88128216, 1972764.03439268, 1972764.03439268, 1903551.76041575, 1903551.76041575, 543762.2932594, 543762.2932594, 530289.21416049, 530289.21416049, 624896.67937685, 624896.67937685, 1680052.006021, 1680052.006021, 322144.56539297, 322144.56539297, 77334.77862527, 77334.77862527, 409527.12801416, 409527.12801416, ]) demographic_events = [] for sz, t in zip(sizes, times): demographic_events.append( msprime.PopulationParametersChange(time=t, initial_size=sz, population_id=0)) populations = [ stdpopsim.Population( id="GAS", description="Gabon gabiae population", ) ] return stdpopsim.DemographicModel( id="GAS_1A17", description="Stairwayplot estimates of N(t) for Gabon sample", long_description=""" These estimates were done as part of the Ag1000G 2017 Consortium paper. Stairwayplot was run with the addition of a misorientation parameter using SFS information from each population. """, populations=populations, citations=[ stdpopsim.Citation( doi="https://doi.org/10.1038/nature24995", year=2017, author="Ag1000G Consortium", reasons={stdpopsim.CiteReason.DEM_MODEL}, ) ], # generation times and mutation rate given at bottom of page 32 in supp info generation_time=1 / 11, mutation_rate=3.5e-9, demographic_events=demographic_events, population_configurations=[ msprime.PopulationConfiguration(initial_size=4069863, metadata=populations[0].asdict()) ], )
def _afr_3epoch(): id = "African3Epoch_1S16" description = "Three epoch African population" long_description = """ The three epoch (modern, bottleneck, ancestral) model estimated for a single African Drosophila Melanogaster population from Sheehan and Song (2016). Population sizes are estimated by a deep learning model trained on simulation data. NOTE: Due to differences in coalescence units between PSMC (2N) and msms (4N) the number of generations were doubled from PSMC estimates when simulating data from msms in the original publication. We have faithfully represented the published model here. """ populations = [_afr_population] citations = [ stdpopsim.Citation( author="Sheehan and Song", year=2016, doi="https://doi.org/10.1371/journal.pcbi.1004845", reasons={stdpopsim.CiteReason.DEM_MODEL}, ) ] generation_time = _species.generation_time mutation_rate = 8.4e-9 # Parameter values from "Simulating Data" section # these are assumptions, not estimates N_ref = 100000 t_1_coal = 0.5 t_2_coal = 5.0 # estimates from the ANN N_R = 544200 N_B = 145300 N_A = 652700 # Times are provided in 4N_ref generations, so we convert into generations. # generation_time = 10 / year t_1 = t_1_coal * 4 * N_ref t_2 = (t_1_coal + t_2_coal) * 4 * N_ref return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, mutation_rate=mutation_rate, population_configurations=[ msprime.PopulationConfiguration(initial_size=N_R, metadata=populations[0].asdict()) ], demographic_events=[ # Size change at bottleneck (back in time; BIT) msprime.PopulationParametersChange(time=t_1, initial_size=N_B, population_id=0), # Size change at recovery (BIT) msprime.PopulationParametersChange(time=t_2, initial_size=N_A, population_id=0), ], )
def LiStephanTwoPopulation(): id = "QC-OutOfAfrica_2L06" populations = [ stdpopsim.Population("AFR", ""), stdpopsim.Population("EUR", ""), ] # Parameters for the African population are taken from the section Demographic # History of the African Population generation_time = 0.1 # 10 generations per year N_A0 = 8.603e6 # modern African pop. size N_A1 = N_A0 / 5.0 # African pop. size before expansion # Parameters for the European population are taken from the section Demographic # History of the European Population N_E0 = 1.075e6 # modern European pop. size N_E1 = 2.2e3 # European founder pop. size # Times from from the section Demographic History of the * Population T_A0 = 6e4 / generation_time # time of 1st expansion in African pop. T_E_A = 15.8e3 / generation_time # European/African divergence time T_EE = T_E_A - 340 / generation_time # Time of European pop. re-expansion return stdpopsim.DemographicModel( id=id, description=id, long_description=id, generation_time=generation_time, populations=populations, # Set population sizes at T=0 # pop0 is Africa, pop1 is Europe population_configurations=[ msprime.PopulationConfiguration(initial_size=N_A0, growth_rate=0), msprime.PopulationConfiguration(initial_size=N_E0, growth_rate=0), ], # Now we add the demographic events working backwards in time. demographic_events=[ # OOA bottleneck msprime.PopulationParametersChange(time=T_EE, initial_size=N_E1, population_id=1), # E and A coalesce msprime.MassMigration(time=T_E_A, source=1, destination=0, proportion=1.0), # Pre-expansion Africa msprime.PopulationParametersChange(time=T_A0, initial_size=N_A1, population_id=0), ], population_id_map=[ { "AFR": 0, "EUR": 1 }, { "AFR": 0, "EUR": 1 }, { "AFR": 0, "EUR": 1 }, { "AFR": 0, "EUR": 1 }, ], )
class TestNoQCWarning: species = stdpopsim.get_species("EscCol") model = stdpopsim.DemographicModel( id="FakeModel", description="FakeModel", long_description="FakeModel", citations=[ stdpopsim.Citation( author="Farnsworth", year=3000, doi="https://doi.org/10.1000/xyz123", reasons={stdpopsim.CiteReason.DEM_MODEL}, ) ], generation_time=10, populations=[stdpopsim.Population("Omicronians", "Popplers, etc.")], population_configurations=[msprime.PopulationConfiguration(initial_size=1000)], ) @classmethod def setup_class(cls): cls.species.add_demographic_model(cls.model) @classmethod def teardown_class(cls): cls.species.demographic_models.remove(cls.model) def verify_noQC_warning(self, cmd): # setup_logging() interferes with pytest.warns(). with mock.patch("stdpopsim.cli.setup_logging", autospec=True): with pytest.warns(stdpopsim.QCMissingWarning): capture_output(stdpopsim.cli.stdpopsim_main, cmd.split()) def test_noQC_warning(self): self.verify_noQC_warning("EscCol -d FakeModel -D 10 -L 10") def test_noQC_warning_quiet(self): self.verify_noQC_warning("-q EscCol -d FakeModel -D 10 -L 10") def verify_noQC_citations_not_written(self, cmd, caplog): # Non-QCed models shouldn't be used in publications, so citations # shouldn't be offered to the user. out, err = capture_output(stdpopsim.cli.stdpopsim_main, cmd.split()) log_output = caplog.text for citation in self.model.citations: assert not (citation.author in out) assert not (citation.doi in out) assert not (citation.author in err) assert not (citation.doi in err) assert not (citation.author in log_output) assert not (citation.doi in log_output) # The following two tests use the "caplog" pytest fixture, which captures # the logging output. The caplog param is automatically passed to test_*() # methods by pytest, which we pass through to verify_noQC_citations_not_written(). @pytest.mark.filterwarnings("ignore::stdpopsim.QCMissingWarning") @pytest.mark.usefixtures("caplog") def test_noQC_citations_not_written(self, caplog): self.verify_noQC_citations_not_written( "EscCol -d FakeModel -D 10 -L 10", caplog ) @pytest.mark.filterwarnings("ignore::stdpopsim.QCMissingWarning") @pytest.mark.usefixtures("caplog") def test_noQC_citations_not_written_verbose(self, caplog): self.verify_noQC_citations_not_written( "-vv EscCol -d FakeModel -D 10 -L 10", caplog )
def hominin_composite(): id = "HomininComposite_4G20" description = "Four population out of Africa with Neandertal admixture" long_description = """ A composite of demographic parameters from multiple sources """ # samples: # T_Altai = 115e3 # T_Vindija = 55e3 # n_YRI = 108 # n_CEU = 99 populations = [ stdpopsim.Population(id="YRI", description="1000 Genomes YRI (Yorubans)"), stdpopsim.Population( id="CEU", description=( "1000 Genomes CEU (Utah Residents (CEPH) with Northern and " "Western European Ancestry" ), ), stdpopsim.Population(id="Nea", description="Neandertal lineage"), stdpopsim.Population( id="Anc", description="Ancestral hominins", sampling_time=None ), ] pop = {p.id: i for i, p in enumerate(populations)} citations = [ stdpopsim.Citation( author="Kuhlwilm et al.", year=2016, doi="https://doi.org/10.1038/nature16544", ), stdpopsim.Citation( author="Prüfer et al.", year=2017, doi="https://doi.org/10.1126/science.aao1887", ), stdpopsim.Citation( author="Ragsdale and Gravel", year=2019, doi="https://doi.org/10.1371/journal.pgen.1008204", ), ] generation_time = 29 # Kuhlwilm et al. 2016 N_YRI = 27000 N_Nea = 3400 N_Anc = 18500 # Ragsdale & Gravel 2019 N_CEU0 = 1450 r_CEU = 0.00202 T_CEU_exp = 31.9e3 / generation_time N_CEU = N_CEU0 * math.exp(r_CEU * T_CEU_exp) T_YRI_CEU_split = 65.7e3 / generation_time N_ooa_bottleneck = 1080 # Prüfer et al. 2017 T_Nea_human_split = 550e3 / generation_time T_Nea_CEU_mig = 55e3 / generation_time m_Nea_CEU = 0.0225 pop_meta = (p.asdict() for p in populations) population_configurations = [ msprime.PopulationConfiguration(initial_size=N_YRI, metadata=next(pop_meta)), msprime.PopulationConfiguration( initial_size=N_CEU, growth_rate=r_CEU, metadata=next(pop_meta) ), msprime.PopulationConfiguration(initial_size=N_Nea, metadata=next(pop_meta)), msprime.PopulationConfiguration(initial_size=N_Anc, metadata=next(pop_meta)), ] demographic_events = [ # out-of-Africa bottleneck msprime.PopulationParametersChange( time=T_CEU_exp, initial_size=N_ooa_bottleneck, growth_rate=0, population_id=pop["CEU"], ), # Neandertal -> CEU admixture msprime.MassMigration( time=T_Nea_CEU_mig, proportion=m_Nea_CEU, source=pop["CEU"], destination=pop["Nea"], ), # population splits msprime.MassMigration( time=T_YRI_CEU_split, source=pop["CEU"], destination=pop["Anc"] ), msprime.MassMigration( time=T_YRI_CEU_split, source=pop["YRI"], destination=pop["Anc"] ), msprime.MassMigration( time=T_Nea_human_split, source=pop["Nea"], destination=pop["Anc"] ), ] return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, population_configurations=population_configurations, demographic_events=demographic_events, )
def test_population_construction_no_popconfig(self): dm = stdpopsim.DemographicModel( id="A", description="A", long_description="A", generation_time=1 ) self.assertEqual(dm.populations, [])
def _ooa_archaic(): id = "OutOfAfricaArchaicAdmixture_5R19" description = "Three population out-of-Africa with archaic admixture" long_description = """ The three population out-of-African model popularized by Gutenkunst et al. (2009) and augmented by archaic contributions to both Eurasian and African populations. Two archaic populations split early in human history, before the African expansion, and contribute to Eurasian populations (putative Neanderthal branch) and to the African branch (a deep diverging branch within Africa). Admixture is modeled as symmetric migration between the archaic and modern human branches, with contribution ending at a given time in the past. """ populations = [ _yri_population, _ceu_population, _chb_population, stdpopsim.Population("Neanderthal", "Putative Neanderthals", sampling_time=None), stdpopsim.Population("ArchaicAFR", "Putative Archaic Africans", sampling_time=None), ] citations = [ stdpopsim.Citation(author="Ragsdale and Gravel", year=2019, doi="https://doi.org/10.1371/journal.pgen.1008204", reasons={stdpopsim.CiteReason.DEM_MODEL}) ] # First we set out the maximum likelihood values of the various parameters # given in Table 1 (under archaic admixture). N_0 = 3600 N_YRI = 13900 N_B = 880 N_CEU0 = 2300 N_CHB0 = 650 # Times are provided in years, so we convert into generations. # In the published model, the authors used a generation time of 29 years to # convert from genetic to physical units generation_time = 29 T_AF = 300e3 / generation_time T_B = 60.7e3 / generation_time T_EU_AS = 36.0e3 / generation_time T_arch_afr_split = 499e3 / generation_time T_arch_afr_mig = 125e3 / generation_time T_nean_split = 559e3 / generation_time T_arch_adm_end = 18.7e3 / generation_time # We need to work out the starting (diploid) population sizes based on # the growth rates provided for these two populations r_CEU = 0.00125 r_CHB = 0.00372 N_CEU = N_CEU0 / math.exp(-r_CEU * T_EU_AS) N_CHB = N_CHB0 / math.exp(-r_CHB * T_EU_AS) # Migration rates during the various epochs. m_AF_B = 52.2e-5 m_YRI_CEU = 2.48e-5 m_YRI_CHB = 0e-5 m_CEU_CHB = 11.3e-5 m_AF_arch_af = 1.98e-5 m_OOA_nean = 0.825e-5 # Population IDs correspond to their indexes in the population # configuration array. Therefore, we have 0=YRI, 1=CEU and 2=CHB # initially. # We also have two archaic populations, putative Neanderthals and # archaicAfrican, which are population indices 3=Nean and 4=arch_afr. # Their sizes are equal to the ancestral reference population size N_0. population_configurations = [ msprime.PopulationConfiguration(initial_size=N_YRI, metadata=populations[0].asdict()), msprime.PopulationConfiguration(initial_size=N_CEU, growth_rate=r_CEU, metadata=populations[1].asdict()), msprime.PopulationConfiguration(initial_size=N_CHB, growth_rate=r_CHB, metadata=populations[2].asdict()), msprime.PopulationConfiguration(initial_size=N_0, metadata=populations[3].asdict()), msprime.PopulationConfiguration(initial_size=N_0, metadata=populations[4].asdict()) ] migration_matrix = [ # noqa [0, m_YRI_CEU, m_YRI_CHB, 0, 0], # noqa [m_YRI_CEU, 0, m_CEU_CHB, 0, 0], # noqa [m_YRI_CHB, m_CEU_CHB, 0, 0, 0], # noqa [0, 0, 0, 0, 0], # noqa [0, 0, 0, 0, 0] # noqa ] # noqa demographic_events = [ # first event is migration turned on between modern and archaic humans msprime.MigrationRateChange(time=T_arch_adm_end, rate=m_AF_arch_af, matrix_index=(0, 4)), msprime.MigrationRateChange(time=T_arch_adm_end, rate=m_AF_arch_af, matrix_index=(4, 0)), msprime.MigrationRateChange(time=T_arch_adm_end, rate=m_OOA_nean, matrix_index=(1, 3)), msprime.MigrationRateChange(time=T_arch_adm_end, rate=m_OOA_nean, matrix_index=(3, 1)), msprime.MigrationRateChange(time=T_arch_adm_end, rate=m_OOA_nean, matrix_index=(2, 3)), msprime.MigrationRateChange(time=T_arch_adm_end, rate=m_OOA_nean, matrix_index=(3, 2)), # CEU and CHB merge into B with rate changes at T_EU_AS msprime.MassMigration(time=T_EU_AS, source=2, destination=1, proportion=1.0), msprime.MigrationRateChange(time=T_EU_AS, rate=0), msprime.MigrationRateChange(time=T_EU_AS, rate=m_AF_B, matrix_index=(0, 1)), msprime.MigrationRateChange(time=T_EU_AS, rate=m_AF_B, matrix_index=(1, 0)), msprime.MigrationRateChange(time=T_EU_AS, rate=m_AF_arch_af, matrix_index=(0, 4)), msprime.MigrationRateChange(time=T_EU_AS, rate=m_AF_arch_af, matrix_index=(4, 0)), msprime.MigrationRateChange(time=T_EU_AS, rate=m_OOA_nean, matrix_index=(1, 3)), msprime.MigrationRateChange(time=T_EU_AS, rate=m_OOA_nean, matrix_index=(3, 1)), msprime.PopulationParametersChange(time=T_EU_AS, initial_size=N_B, growth_rate=0, population_id=1), # Population B merges into YRI at T_B msprime.MassMigration(time=T_B, source=1, destination=0, proportion=1.0), msprime.MigrationRateChange(time=T_B, rate=0), msprime.MigrationRateChange(time=T_B, rate=m_AF_arch_af, matrix_index=(0, 4)), msprime.MigrationRateChange(time=T_B, rate=m_AF_arch_af, matrix_index=(4, 0)), # Beginning of migration between African and archaic African populations msprime.MigrationRateChange(time=T_arch_afr_mig, rate=0), # Size changes to N_0 at T_AF msprime.PopulationParametersChange(time=T_AF, initial_size=N_0, population_id=0), # Archaic African merges with moderns msprime.MassMigration(time=T_arch_afr_split, source=4, destination=0, proportion=1.0), # Neanderthal merges with moderns msprime.MassMigration(time=T_nean_split, source=3, destination=0, proportion=1.0) ] return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, population_configurations=population_configurations, migration_matrix=migration_matrix, demographic_events=demographic_events, )
def _america(): id = "AmericanAdmixture_4B11" description = "American admixture" long_description = """ Demographic model for American admixture, taken from Browning et al. 2011. This model extends the Gravel et al. (2011) model of African/European/Asian demographic history to simulate an admixed population with admixture occurring 12 generations ago. The admixed population had an initial size of 30,000 and grew at a rate of 5% per generation, with 1/6 of the population of African ancestry, 1/3 European, and 1/2 Asian. """ populations = [ stdpopsim.Population(id="AFR", description="Contemporary African population"), stdpopsim.Population(id="EUR", description="Contemporary European population"), stdpopsim.Population(id="ASIA", description="Contemporary Asian population"), stdpopsim.Population(id="ADMIX", description="Modern admixed population"), ] citations = [ stdpopsim.Citation( author="Browning et al.", year=2011, doi="http://dx.doi.org/10.1371/journal.pgen.1007385", reasons={stdpopsim.CiteReason.DEM_MODEL}) ] generation_time = 25 # Model code was ported from Supplementary File 1. N0 = 7310 # initial population size Thum = 5920 # time (gens) of advent of modern humans Naf = 14474 # size of african population Tooa = 2040 # number of generations back to Out of Africa Nb = 1861 # size of out of Africa population mafb = 1.5e-4 # migration rate Africa and Out-of-Africa Teu = 920 # number generations back to Asia-Europe split Neu = 1032 # bottleneck population sizes Nas = 554 mafeu = 2.5e-5 # mig. rates mafas = 7.8e-6 meuas = 3.11e-5 reu = 0.0038 # growth rate per generation in Europe ras = 0.0048 # growth rate per generation in Asia Tadmix = 12 # time of admixture Nadmix = 30000 # initial size of admixed population radmix = .05 # growth rate of admixed population # pop0 is Africa, pop1 is Europe, pop2 is Asia, pop3 is admixed population_configurations = [ msprime.PopulationConfiguration(initial_size=Naf, growth_rate=0.0, metadata=populations[0].asdict()), msprime.PopulationConfiguration(initial_size=Neu * math.exp(reu * Teu), growth_rate=reu, metadata=populations[1].asdict()), msprime.PopulationConfiguration(initial_size=Nas * math.exp(ras * Teu), growth_rate=ras, metadata=populations[2].asdict()), msprime.PopulationConfiguration(initial_size=Nadmix * math.exp(radmix * Tadmix), growth_rate=radmix, metadata=populations[3].asdict()) ] migration_matrix = [[0, mafeu, mafas, 0], [mafeu, 0, meuas, 0], [mafas, meuas, 0, 0], [0, 0, 0, 0]] # Admixture event, 1/6 Africa, 2/6 Europe, 3/6 Asia admixture_event = [ msprime.MassMigration(time=Tadmix, source=3, destination=0, proportion=1.0 / 6.0), msprime.MassMigration(time=Tadmix + 0.0001, source=3, destination=1, proportion=2.0 / 5.0), msprime.MassMigration(time=Tadmix + 0.0002, source=3, destination=2, proportion=1.0) ] # Asia and Europe split eu_event = [ msprime.MigrationRateChange(time=Teu, rate=0.0), msprime.MassMigration(time=Teu + 0.0001, source=2, destination=1, proportion=1.0), msprime.PopulationParametersChange(time=Teu + 0.0002, initial_size=Nb, growth_rate=0.0, population_id=1), msprime.MigrationRateChange(time=Teu + 0.0003, rate=mafb, matrix_index=(0, 1)), msprime.MigrationRateChange(time=Teu + 0.0003, rate=mafb, matrix_index=(1, 0)) ] # Out of Africa event ooa_event = [ msprime.MigrationRateChange(time=Tooa, rate=0.0), msprime.MassMigration(time=Tooa + 0.0001, source=1, destination=0, proportion=1.0) ] # initial population size init_event = [ msprime.PopulationParametersChange(time=Thum, initial_size=N0, population_id=0) ] demographic_events = admixture_event + eu_event + ooa_event + init_event return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, population_configurations=population_configurations, migration_matrix=migration_matrix, demographic_events=demographic_events, )
def _ooa_2(): id = "OutOfAfrica_2T12" description = "Two population out-of-Africa" long_description = """ The model is derived from the Tennesen et al. analysis of the jSFS from European Americans and African Americans. It describes the ancestral human population in Africa, the out of Africa event, and two distinct periods of subsequent European population growth over the past 23kya. Model parameters are taken from Fig. S5 in Fu et al. """ populations = [ stdpopsim.Population(id="AFR", description="African Americans"), stdpopsim.Population(id="EUR", description="European Americans") ] citations = [ _tennessen_et_al, stdpopsim.Citation(author="Fu et al.", year=2013, doi="https://doi.org/10.1038/nature11690", reasons={stdpopsim.CiteReason.DEM_MODEL}) ] generation_time = 25 T_AF = 148e3 / generation_time T_OOA = 51e3 / generation_time T_EU0 = 23e3 / generation_time T_EG = 5115 / generation_time # Growth rates r_EU0 = 0.00307 r_EU = 0.0195 r_AF = 0.0166 # population sizes N_A = 7310 N_AF1 = 14474 N_B = 1861 N_EU0 = 1032 N_EU1 = N_EU0 / math.exp(-r_EU0 * (T_EU0 - T_EG)) # migration rates m_AF_B = 15e-5 m_AF_EU = 2.5e-5 # present Ne N_EU = N_EU1 / math.exp(-r_EU * T_EG) N_AF = N_AF1 / math.exp(-r_AF * T_EG) return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, population_configurations=[ msprime.PopulationConfiguration(initial_size=N_AF, growth_rate=r_AF, metadata=populations[0].asdict()), msprime.PopulationConfiguration(initial_size=N_EU, growth_rate=r_EU, metadata=populations[1].asdict()) ], migration_matrix=[ [0, m_AF_EU], [m_AF_EU, 0], ], demographic_events=[ msprime.MigrationRateChange(time=T_EG, rate=m_AF_EU, matrix_index=(0, 1)), msprime.MigrationRateChange(time=T_EG, rate=m_AF_EU, matrix_index=(1, 0)), msprime.PopulationParametersChange(time=T_EG, growth_rate=r_EU0, initial_size=N_EU1, population_id=1), msprime.PopulationParametersChange(time=T_EG, growth_rate=0, initial_size=N_AF1, population_id=0), msprime.MigrationRateChange(time=T_EU0, rate=m_AF_B, matrix_index=(0, 1)), msprime.MigrationRateChange(time=T_EU0, rate=m_AF_B, matrix_index=(1, 0)), msprime.PopulationParametersChange(time=T_EU0, initial_size=N_B, growth_rate=0, population_id=1), msprime.MassMigration(time=T_OOA, source=1, destination=0, proportion=1.0), msprime.PopulationParametersChange(time=T_AF, initial_size=N_A, population_id=0) ], )
def _ooa_3(): id = "OutOfAfrica_3G09" description = "Three population out-of-Africa" long_description = """ The three population Out-of-Africa model from Gutenkunst et al. 2009. It describes the ancestral human population in Africa, the out of Africa event, and the subsequent European-Asian population split. Model parameters are the maximum likelihood values of the various parameters given in Table 1 of Gutenkunst et al. """ populations = [_yri_population, _ceu_population, _chb_population] citations = [ stdpopsim.Citation(author="Gutenkunst et al.", year=2009, doi="https://doi.org/10.1371/journal.pgen.1000695", reasons={stdpopsim.CiteReason.DEM_MODEL}) ] generation_time = 25 # First we set out the maximum likelihood values of the various parameters # given in Table 1. N_A = 7300 N_B = 2100 N_AF = 12300 N_EU0 = 1000 N_AS0 = 510 # Times are provided in years, so we convert into generations. T_AF = 220e3 / generation_time T_B = 140e3 / generation_time T_EU_AS = 21.2e3 / generation_time # We need to work out the starting (diploid) population sizes based on # the growth rates provided for these two populations r_EU = 0.004 r_AS = 0.0055 N_EU = N_EU0 / math.exp(-r_EU * T_EU_AS) N_AS = N_AS0 / math.exp(-r_AS * T_EU_AS) # Migration rates during the various epochs. m_AF_B = 25e-5 m_AF_EU = 3e-5 m_AF_AS = 1.9e-5 m_EU_AS = 9.6e-5 return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, # Population IDs correspond to their indexes in the population # configuration array. Therefore, we have 0=YRI, 1=CEU and 2=CHB # initially. population_configurations=[ msprime.PopulationConfiguration(initial_size=N_AF, metadata=populations[0].asdict()), msprime.PopulationConfiguration(initial_size=N_EU, growth_rate=r_EU, metadata=populations[1].asdict()), msprime.PopulationConfiguration(initial_size=N_AS, growth_rate=r_AS, metadata=populations[2].asdict()), ], migration_matrix=[ [0, m_AF_EU, m_AF_AS], # noqa [m_AF_EU, 0, m_EU_AS], # noqa [m_AF_AS, m_EU_AS, 0], # noqa ], demographic_events=[ # CEU and CHB merge into B with rate changes at T_EU_AS msprime.MassMigration(time=T_EU_AS, source=2, destination=1, proportion=1.0), msprime.MigrationRateChange(time=T_EU_AS, rate=0), msprime.MigrationRateChange(time=T_EU_AS, rate=m_AF_B, matrix_index=(0, 1)), msprime.MigrationRateChange(time=T_EU_AS, rate=m_AF_B, matrix_index=(1, 0)), msprime.PopulationParametersChange(time=T_EU_AS, initial_size=N_B, growth_rate=0, population_id=1), # Population B merges into YRI at T_B msprime.MassMigration(time=T_B, source=1, destination=0, proportion=1.0), # Size changes to N_A at T_AF msprime.PopulationParametersChange(time=T_AF, initial_size=N_A, population_id=0) ], )
def papuans_10j19(): id = "PapuansOutOfAfrica_10J19" description = "Out-of-Africa with archaic admixture into Papuans" long_description = """ A ten population model of out-of-Africa, including two pulses of Denisovan admixture into Papuans, and several pulses of Neandertal admixture into non-Africans. Most parameters are from Jacobs et al. (2019), Table S5 and Figure S5. This model is an extension of one from Malaspinas et al. (2016), thus some parameters are inherited from there. """ # sampling times T_DenA = 2203 T_NeaA = 3793 populations = [ # humans stdpopsim.Population(id="YRI", description="1000 Genomes YRI (Yorubans)"), stdpopsim.Population( id="CEU", description="1000 Genomes CEU (Utah Residents (CEPH) with Northern and Western European Ancestry", ), stdpopsim.Population( id="CHB", description="1000 Genomes CHB (Han Chinese in Beijing, China)" ), stdpopsim.Population("Papuan", "Papuans from Indonesia and New Guinea"), # archaics stdpopsim.Population( "DenA", "Altai Denisovan (sampling) lineage", sampling_time=T_DenA ), stdpopsim.Population( "NeaA", "Altai Neandertal (sampling) lineage", sampling_time=T_NeaA ), stdpopsim.Population( "Den1", "Denisovan D1 (introgressing) lineage", sampling_time=None ), stdpopsim.Population( "Den2", "Denisovan D2 (introgressing) lineage", sampling_time=None ), stdpopsim.Population( "Nea1", "Neandertal N1 (introgressing) lineage", sampling_time=1725 ), stdpopsim.Population("Ghost", "Out-of-Africa lineage", sampling_time=None), ] pop = {p.id: i for i, p in enumerate(populations)} citations = [ stdpopsim.Citation( author="Jacobs et al.", year=2019, doi="https://doi.org/10.1016/j.cell.2019.02.035", reasons={stdpopsim.CiteReason.DEM_MODEL}, ), stdpopsim.Citation( author="Malaspinas et al.", year=2016, doi="https://doi.org/10.1038/nature18299", reasons={stdpopsim.CiteReason.DEM_MODEL}, ), ] # Inherited from Malaspinas et al., which gives the following refs: generation_time = 29 # Fenner 2005 # mutation_rate = 1.25e-8 # per gen per site, Scally & Durbin 2012 N_YRI = 48433 N_Ghost = 8516 N_CEU = 6962 N_CHB = 9025 N_Papuan = 8834 N_DenA = 5083 N_Den1 = 13249 N_Den2 = 13249 N_NeaA = 826 N_Nea1 = 13249 pop_meta = {p.id: p.asdict() for p in populations} population_configurations = [ msprime.PopulationConfiguration(initial_size=N_YRI, metadata=pop_meta["YRI"]), msprime.PopulationConfiguration(initial_size=N_CEU, metadata=pop_meta["CEU"]), msprime.PopulationConfiguration(initial_size=N_CHB, metadata=pop_meta["CHB"]), msprime.PopulationConfiguration( initial_size=N_Papuan, metadata=pop_meta["Papuan"] ), msprime.PopulationConfiguration(initial_size=N_DenA, metadata=pop_meta["DenA"]), msprime.PopulationConfiguration(initial_size=N_NeaA, metadata=pop_meta["NeaA"]), msprime.PopulationConfiguration(initial_size=N_Den1, metadata=pop_meta["Den1"]), msprime.PopulationConfiguration(initial_size=N_Den2, metadata=pop_meta["Den2"]), msprime.PopulationConfiguration(initial_size=N_Nea1, metadata=pop_meta["Nea1"]), msprime.PopulationConfiguration( initial_size=N_Ghost, metadata=pop_meta["Ghost"] ), ] assert len(populations) == len(population_configurations) # initial migrations m_Ghost_Afr = 1.79e-4 m_Ghost_EU = 4.42e-4 m_EU_AS = 3.14e-5 m_AS_Papuan = 5.72e-5 # older migrations m_Eurasian_Papuan = 5.72e-4 m_Eurasian_Ghost = 4.42e-4 migration_matrix = [[0] * len(populations) for _ in range(len(populations))] migration_matrix[pop["Ghost"]][pop["YRI"]] = m_Ghost_Afr migration_matrix[pop["YRI"]][pop["Ghost"]] = m_Ghost_Afr migration_matrix[pop["Ghost"]][pop["CEU"]] = m_Ghost_EU migration_matrix[pop["CEU"]][pop["Ghost"]] = m_Ghost_EU migration_matrix[pop["CEU"]][pop["CHB"]] = m_EU_AS migration_matrix[pop["CHB"]][pop["CEU"]] = m_EU_AS migration_matrix[pop["CHB"]][pop["Papuan"]] = m_AS_Papuan migration_matrix[pop["Papuan"]][pop["CHB"]] = m_AS_Papuan # splits T_EU_AS_split = 1293 T_Eurasian_Ghost_split = 1758 T_Papuan_Ghost_split = 1784 T_Ghost_Afr_split = 2218 T_NeaA_Nea1_split = 3375 T_DenA_Den1_split = 9750 T_DenA_Den2_split = 12500 T_Den_Nea_split = 15090 T_Afr_Archaic_split = 20225 # bottlenecks Tb_Eurasia = 1659 Tb_Papua = 1685 Tb_Ghost = 2119 Nb_Eurasia = 2231 Nb_Papua = 243 Nb_Ghost = 1394 # internal branches N_EU_AS = 12971 N_Ghost_Afr = 41563 N_NeaA_Nea1 = 13249 N_Den_Anc = 100 # S10.i p. 31/45 N_DenA_Den1 = N_Den_Anc N_DenA_Den2 = N_Den_Anc N_Den_Nea = 13249 N_Afr_Archaic = 32671 # admixture pulses m_Den_Papuan = 0.04 p1 = 0.55 # S10.i p. 31/45 m_Den1_Papuan = p1 * m_Den_Papuan m_Den2_Papuan = (1 - p1) * m_Den_Papuan m_Nea1_Ghost = 0.024 m_Nea1_Eurasian = 0.011 m_Nea1_Papuan = 0.002 m_Nea1_AS = 0.002 T_Nea1_Ghost_mig = 1853 T_Nea1_Eurasian_mig = 1566 T_Nea1_Papuan_mig = 1412 T_Nea1_AS_mig = 883 # Fig. 4B, and S10.h p. 30/45 T_Den1_Papuan_mig = 29.8e3 / generation_time T_Den2_Papuan_mig = 45.7e3 / generation_time demographic_events = [ # human lineage splits msprime.MassMigration( time=T_EU_AS_split, source=pop["CEU"], destination=pop["CHB"] ), msprime.PopulationParametersChange( time=T_EU_AS_split, initial_size=N_EU_AS, population_id=pop["CHB"] ), msprime.MassMigration( time=T_Eurasian_Ghost_split, source=pop["CHB"], destination=pop["Ghost"] ), msprime.MassMigration( time=T_Papuan_Ghost_split, source=pop["Papuan"], destination=pop["Ghost"] ), msprime.MassMigration( time=T_Ghost_Afr_split, source=pop["Ghost"], destination=pop["YRI"] ), msprime.PopulationParametersChange( time=T_Ghost_Afr_split, initial_size=N_Ghost_Afr, population_id=pop["YRI"] ), # archaic lineage splits msprime.MassMigration( time=T_DenA_Den1_split, source=pop["Den1"], destination=pop["DenA"] ), msprime.PopulationParametersChange( time=T_DenA_Den1_split, initial_size=N_DenA_Den1, population_id=pop["DenA"] ), msprime.MassMigration( time=T_DenA_Den2_split, source=pop["Den2"], destination=pop["DenA"] ), msprime.PopulationParametersChange( time=T_DenA_Den2_split, initial_size=N_DenA_Den2, population_id=pop["DenA"] ), msprime.MassMigration( time=T_NeaA_Nea1_split, source=pop["Nea1"], destination=pop["NeaA"] ), msprime.PopulationParametersChange( time=T_NeaA_Nea1_split, initial_size=N_NeaA_Nea1, population_id=pop["NeaA"] ), msprime.MassMigration( time=T_Den_Nea_split, source=pop["NeaA"], destination=pop["DenA"] ), msprime.PopulationParametersChange( time=T_Den_Nea_split, initial_size=N_Den_Nea, population_id=pop["DenA"] ), msprime.MassMigration( time=T_Afr_Archaic_split, source=pop["DenA"], destination=pop["YRI"] ), msprime.PopulationParametersChange( time=T_Afr_Archaic_split, initial_size=N_Afr_Archaic, population_id=pop["YRI"], ), # bottlenecks msprime.PopulationParametersChange( time=Tb_Eurasia, initial_size=Nb_Eurasia, population_id=pop["CHB"] ), msprime.PopulationParametersChange( time=Tb_Papua, initial_size=Nb_Papua, population_id=pop["Papuan"] ), msprime.PopulationParametersChange( time=Tb_Ghost, initial_size=Nb_Ghost, population_id=pop["Ghost"] ), # migration changes msprime.MigrationRateChange( time=T_EU_AS_split, rate=0, matrix_index=(pop["CHB"], pop["CEU"]) ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=0, matrix_index=(pop["CEU"], pop["CHB"]) ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=0, matrix_index=(pop["Papuan"], pop["CHB"]) ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=0, matrix_index=(pop["CHB"], pop["Papuan"]) ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=0, matrix_index=(pop["Ghost"], pop["CEU"]) ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=0, matrix_index=(pop["CEU"], pop["Ghost"]) ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=m_Eurasian_Papuan, matrix_index=(pop["CHB"], pop["Papuan"]), ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=m_Eurasian_Papuan, matrix_index=(pop["Papuan"], pop["CHB"]), ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=m_Eurasian_Ghost, matrix_index=(pop["CHB"], pop["Ghost"]), ), msprime.MigrationRateChange( time=T_EU_AS_split, rate=m_Eurasian_Ghost, matrix_index=(pop["Ghost"], pop["CHB"]), ), # all migrations off msprime.MigrationRateChange(time=Tb_Eurasia, rate=0), # admixture pulses msprime.MassMigration( time=T_Den1_Papuan_mig, proportion=m_Den1_Papuan, source=pop["Papuan"], destination=pop["Den1"], ), msprime.MassMigration( time=T_Den2_Papuan_mig, proportion=m_Den2_Papuan, source=pop["Papuan"], destination=pop["Den2"], ), msprime.MassMigration( time=T_Nea1_Ghost_mig, proportion=m_Nea1_Ghost, source=pop["Ghost"], destination=pop["Nea1"], ), msprime.MassMigration( time=T_Nea1_Eurasian_mig, proportion=m_Nea1_Eurasian, source=pop["CHB"], destination=pop["Nea1"], ), msprime.MassMigration( time=T_Nea1_Papuan_mig, proportion=m_Nea1_Papuan, source=pop["Papuan"], destination=pop["Nea1"], ), msprime.MassMigration( time=T_Nea1_AS_mig, proportion=m_Nea1_AS, source=pop["CHB"], destination=pop["Nea1"], ), ] demographic_events.sort(key=lambda x: x.time) return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, population_configurations=population_configurations, migration_matrix=migration_matrix, demographic_events=demographic_events, )
def _HolsteinFriesan_1M13(): id = "HolsteinFriesian_1M13" description = "Piecewise size changes in Holstein-Friesian cattle." long_description = """ The piecewise-constant population size model of Holstein-Friesian cattle from MacLeod et al. 2013. Population sizes were estimated from inferred runs of homozygosity, with parameter values taken from Figure 4A by visual inspection of the plots. """ populations = [ stdpopsim.Population(id="Holstein-Friesian", description="Holstein-Friesian"), ] citations = [_MacLeodEtAl.because(stdpopsim.CiteReason.DEM_MODEL)] return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=_species.generation_time, population_configurations=[ msprime.PopulationConfiguration( initial_size=90, growth_rate=0.0166, metadata=populations[0].asdict() ) ], # Here 'time' should be in generation notation ie. how many # generations ago were that Ne (effective population size) # and growth rate. # Growth rate is "per generation exponential growth rate": # -alpha= [ln(initial_pop_size/next_stage_pop_size)/generation_span_in_years] # For example: ln(90/120)/3= -0.095894024 demographic_events=[ msprime.PopulationParametersChange( time=1, initial_size=90, growth_rate=-0.095894024, population_id=0, ), # Ne 90 to 120 msprime.PopulationParametersChange( time=4, growth_rate=-0.24465639, population_id=0 ), # Ne 120 to 250 msprime.PopulationParametersChange( time=7, growth_rate=-0.0560787, population_id=0 ), # Ne 250 to 350 msprime.PopulationParametersChange( time=13, growth_rate=-0.1749704, population_id=0 ), # Ne 350 to 1000 msprime.PopulationParametersChange( time=19, growth_rate=-0.0675775, population_id=0 ), # Ne 1000 to 1500 msprime.PopulationParametersChange( time=25, growth_rate=-0.0022129, population_id=0 ), # Ne 1500 to 2000 msprime.PopulationParametersChange( time=155, growth_rate=-0.0007438, population_id=0 ), # Ne 2000 to 2500 msprime.PopulationParametersChange( time=455, growth_rate=-0.0016824, population_id=0 ), # Ne 2500 to 3500 msprime.PopulationParametersChange( time=655, growth_rate=-0.0006301, population_id=0 ), # Ne 3500 to 7000 msprime.PopulationParametersChange( time=1755, growth_rate=-0.0005945, population_id=0 ), # Ne 7000 to 10000 msprime.PopulationParametersChange( time=2355, growth_rate=-0.0005306, population_id=0 ), # Ne 10000 to 17000 msprime.PopulationParametersChange( time=3355, growth_rate=-0.0000434, population_id=0 ), # Ne 17000 to 62000 msprime.PopulationParametersChange( time=33155, growth_rate=-0.0000, population_id=0 ), # Ne 62000 (model has "coalesced") msprime.PopulationParametersChange( time=933155, growth_rate=-0.0, population_id=0 ), ], )
def _zigzag(): id = "Zigzag_1S14" description = "Periodic growth and decline." long_description = """ A validation model used by Schiffels and Durbin (2014) and Terhorst and Terhorst, Kamm, and Song (2017) with periods of exponential growth and decline in a single population. """ populations = [ stdpopsim.Population("generic", "Generic expanding and contracting population"), ] citations = [ stdpopsim.Citation(author="Schiffels and Durbin", year=2014, doi="https://doi.org/10.1038/ng.3015", reasons={stdpopsim.CiteReason.DEM_MODEL}) ] generation_time = 29 N0 = 14312 g_1 = 0.023025 t_1 = 33.333 n_1 = N0 g_2 = -0.005756 t_2 = 133.33 n_2 = N0 / 10 g_3 = 0.0014391 t_3 = 533.33 n_3 = N0 g_4 = -0.00035977 t_4 = 2133.33 n_4 = N0 / 10 g_5 = 8.99448e-5 t_5 = 8533.33 n_5 = N0 n_ancient = N0 / 10 t_ancient = 34133.31 population_configurations = [ msprime.PopulationConfiguration(initial_size=N0, metadata=populations[0].asdict()) ] demographic_events = [ msprime.PopulationParametersChange(initial_size=n_1, time=t_1, growth_rate=g_1), msprime.PopulationParametersChange(initial_size=n_2, time=t_2, growth_rate=g_2), msprime.PopulationParametersChange(initial_size=n_3, time=t_3, growth_rate=g_3), msprime.PopulationParametersChange(initial_size=n_4, time=t_4, growth_rate=g_4), msprime.PopulationParametersChange(initial_size=n_5, time=t_5, growth_rate=g_5), msprime.PopulationParametersChange(time=t_ancient, initial_size=n_ancient, growth_rate=0) ] return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, population_configurations=population_configurations, demographic_events=demographic_events, )
def Durvasula2017MSMC(): id = "QC-SouthMiddleAtlas_1D17" populations = [stdpopsim.Population("SouthMiddleAtlas", "")] # Both of the following are directly # converted from MSMC output scaled by A.Thaliana # mutation rate 7e-9 and 1 generation # per year. times = np.array([ 6.990000e02, 2.796000e03, 6.068000e03, 9.894000e03, 1.437000e04, 1.960600e04, 2.573000e04, 3.289400e04, 4.127500e04, 5.107700e04, 6.254400e04, 7.595800e04, 9.164800e04, 1.100010e05, 1.314710e05, 1.565840e05, 1.859600e05, 2.203240e05, 2.605200e05, 3.075400e05, 3.625410e05, 4.268790e05, 5.021390e05, 5.901730e05, 6.931510e05, 8.136100e05, 9.545170e05, 1.119341e06, 1.312147e06, 1.537686e06, 1.801500e06, 2.110100e06, ]) sizes = np.array([ 4.2252426e07, 4.2252426e07, 6.0323000e04, 7.2174000e04, 4.0591000e04, 2.1158000e04, 2.1442000e04, 3.9942000e04, 7.8908000e04, 1.1113200e05, 1.1074500e05, 9.6283000e04, 8.7661000e04, 8.3932000e04, 8.3829000e04, 9.1813000e04, 1.1164400e05, 1.4345600e05, 1.8157100e05, 2.1733100e05, 2.4140000e05, 2.4698400e05, 2.3859300e05, 2.2822200e05, 2.1775200e05, 1.9801900e05, 1.6521000e05, 1.2179600e05, 1.2179600e05, 7.3989000e04, 7.3989000e04, 7.3989000e04, ]) # The first 8 epochs are "masked" to # the last Ne at 40kya due to # the limitations of MSMC to infer # population size in this range. # # Similarly, the last 2 entries # are set to equal the third last. # # Durvasula et al 2017 shows that # MSMC has power in A.Thaliana # between 40kya and 1.6Mya. sizes[:8] = sizes[8] sizes[30:32] = sizes[30] demographic_events = [] population_configurations = [ msprime.PopulationConfiguration(initial_size=sizes[0]) ] for i, t in enumerate(times): demographic_events.append( msprime.PopulationParametersChange(time=t, initial_size=sizes[i], population_id=0)) return stdpopsim.DemographicModel( id=id, description=id, long_description=id, generation_time=_species.generation_time, populations=populations, population_configurations=population_configurations, demographic_events=demographic_events, population_id_map=[{ "SouthMiddleAtlas": 0 }] * 33, mutation_rate=7.1e-9, )
def _kamm_ancient_eurasia(): id = "AncientEurasia_9K19" description = "Multi-population model of ancient Eurasia" long_description = """ This is the best-fitting model of a history of multiple ancient and present-day human populations sampled across Eurasia over the past 120,000 years. The fitting was performed using momi2 (Kamm et al. 2019), which uses the multi-population site-frequency spectrum as input data. The model includes a ghost admixture event (from unsampled basal Eurasians into early European farmers), and two admixture events where the source is approximately well-known (from Neanderthals into Non-Africans and from Western European hunter-gatherers into modern Sardinians. There are three present-day populations: Sardinians, Han Chinese and African Mbuti. Additionally, there are several ancient samples obtained from fossils dated at different times in the past: the Altai Neanderthal (Prufer et al. 2014), a Mesolithic hunter-gatherer (Lazaridis et al. 2014), a Neolithic early European sample (Lazaridis et al. 2014), and two Palaeolithic modern humans from Siberia - MA1 (Raghavan et al. 2014) and Ust'Ishim (Fu et al. 2014). All the ancient samples are represented by a single diploid genome. """ # Sampling times are assuming 25 years per generation populations = [ stdpopsim.Population(id="Mbuti", description="Present-day African Mbuti", sampling_time=0), # LBK: 8,000 years ago stdpopsim.Population(id="LBK", description="Early European farmer (EEF)", sampling_time=320), stdpopsim.Population(id="Sardinian", description="Present-day Sardinian", sampling_time=0), # Loschbour: 7,500 years ago stdpopsim.Population(id="Loschbour", description="Western hunter-gatherer (WHG)", sampling_time=300), # MA1: 24,000 years ago stdpopsim.Population(id="MA1", description="Upper Palaeolithic MAl'ta culture", sampling_time=960), stdpopsim.Population(id="Han", description="Present-day Han Chinese", sampling_time=0), # Ust Ishim: 45,000 years ago stdpopsim.Population(id="UstIshim", description="early Palaeolithic Ust'-Ishim", sampling_time=1800), # Altai Neanderthal: 50,000 years ago stdpopsim.Population(id="Neanderthal", description="Altai Neanderthal from Siberia", sampling_time=2000), stdpopsim.Population(id="BasalEurasian", description="Basal Eurasians", sampling_time=None), ] citations = [ stdpopsim.Citation(author="Kamm et al.", year=2019, doi="https://doi.org/10.1080/01621459.2019.1635482", reasons={stdpopsim.CiteReason.DEM_MODEL}) ] # Times are provided in years, so we convert into generations. generation_time = 25 # Mutation_rate in Kamm et al. = 1.22e-8 # Effective population sizes N_Losch = 1920 N_Mbu = 17300 N_Mbu_Losch = 29100 N_Han = 6300 N_Han_Losch = 2340 N_Nean_Losch = 18200 N_Nean = 86.9 N_LBK = 75.7 N_Sard = 15000 N_Sard_LBK = 12000 # Table A.1 has Altai at 50,000 years ago t_NeaPopSizeChange = 50000 / generation_time # Unknown but suspected parameters... N_Basal = N_Losch N_MA1 = N_Losch N_Ust = N_Losch # Population split times t_Mbu_Losch = 95800 / generation_time t_Han_Losch = 50400 / generation_time t_Ust_Losch = 51500 / generation_time t_Nean_Losch = 696000 / generation_time t_MA1_Losch = 44900 / generation_time t_LBK_Losch = 37700 / generation_time t_Basal_Losch = 79800 / generation_time t_Sard_LBK = 7690 / generation_time # Given that we're using best model estimate, # ghost WHG is directly descended from Loschbour, # so this parameter is not used # t_GhostWHG_Losch = 1560 / generation_time # Admixture times t_Nean_to_Eurasian = 56800 / generation_time t_Basal_to_EEF = 33700 / generation_time t_GhostWHG_to_Sard = 1230 / generation_time t_NeanGrowth = t_Mbu_Losch - t_NeaPopSizeChange logdiffNeanGrowth = math.log(N_Nean / N_Nean_Losch) r_NeanGrowth = logdiffNeanGrowth / t_NeanGrowth p_Nean_to_Eurasian = 0.0296 p_Basal_to_EEF = 0.0936 p_GhostWHG_to_Sard = 0.0317 # Population IDs: Mbuti = 0; LBK = 1; # Sardinian = 2; Loschbour = 3; MA1 = 4; # Han = 5; Ust Ishim = 6; Neanderthal = 7; # Basal Eurasian = 8 population_configurations = [ msprime.PopulationConfiguration(initial_size=N_Mbu, metadata=populations[0].asdict()), msprime.PopulationConfiguration(initial_size=N_LBK, metadata=populations[1].asdict()), msprime.PopulationConfiguration(initial_size=N_Sard, metadata=populations[2].asdict()), msprime.PopulationConfiguration(initial_size=N_Losch, metadata=populations[3].asdict()), msprime.PopulationConfiguration(initial_size=N_MA1, metadata=populations[4].asdict()), msprime.PopulationConfiguration(initial_size=N_Han, metadata=populations[5].asdict()), msprime.PopulationConfiguration(initial_size=N_Ust, metadata=populations[6].asdict()), msprime.PopulationConfiguration(initial_size=N_Nean, metadata=populations[7].asdict()), msprime.PopulationConfiguration(initial_size=N_Basal, metadata=populations[8].asdict()) ] demographic_events = [ # Sardinian receives admixture from Loschbour / WHG msprime.MassMigration(time=t_GhostWHG_to_Sard, source=2, destination=3, proportion=p_GhostWHG_to_Sard), # Sardinian merges into LBK / EEF # Now pop 1: Sardinian-LBK ancestral pop msprime.MassMigration(time=t_Sard_LBK, source=2, destination=1, proportion=1.0), # Sardinian-LBK ancestral pop size change msprime.PopulationParametersChange(time=t_Sard_LBK, initial_size=N_Sard_LBK, population_id=1), # LBK / EEF receives admixture from Basal Eurasians msprime.MassMigration(time=t_Basal_to_EEF, source=1, destination=8, proportion=p_Basal_to_EEF), # LBK / EEF merges into Loschbour msprime.MassMigration(time=t_LBK_Losch, source=1, destination=3, proportion=1.0), # MA1 merges into Loschbour msprime.MassMigration(time=t_MA1_Losch, source=4, destination=3, proportion=1.0), # Neanderthal start change in population size msprime.PopulationParametersChange(time=t_NeaPopSizeChange, initial_size=N_Nean, growth_rate=r_NeanGrowth, population_id=7), # Han merges into Loschbour msprime.MassMigration(time=t_Han_Losch, source=5, destination=3, proportion=1.0), # Change in population size in Han-Losch ancestral pop msprime.PopulationParametersChange(time=t_Han_Losch, initial_size=N_Han_Losch, population_id=3), # UstIshim merges into Loschbour msprime.MassMigration(time=t_Ust_Losch, source=6, destination=3, proportion=1.0), # Loschbour / Non-Africans receive admixture from Neanderthals msprime.MassMigration(time=t_Nean_to_Eurasian, source=3, destination=7, proportion=p_Nean_to_Eurasian), # Basal Eurasians merge into Loschbour / Non-Africans msprime.MassMigration(time=t_Basal_Losch, source=8, destination=3, proportion=1.0), # Mbuti merge into Loschbour / Non-Africans msprime.MassMigration(time=t_Mbu_Losch, source=0, destination=3, proportion=1.0), # Change in population size in Mbuti-Losch ancestral pop msprime.PopulationParametersChange(time=t_Mbu_Losch, initial_size=N_Mbu_Losch, population_id=3), # Change in population size in Neanderthal, growth rate 0 msprime.PopulationParametersChange(time=t_Mbu_Losch, initial_size=N_Nean_Losch, growth_rate=0, population_id=7), # Neanderthal merge into Loschbour / modern humans msprime.MassMigration(time=t_Nean_Losch, source=7, destination=3, proportion=1.0), # Ancestral hominin population size change msprime.PopulationParametersChange(time=t_Nean_Losch, initial_size=N_Nean_Losch, population_id=3), ] return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=generation_time, population_configurations=population_configurations, demographic_events=demographic_events, )
def _orangutan(): id = "TwoSpecies_2L11" description = "Two population orangutan model" long_description = """ The two orang-utan species, Sumatran (Pongo abelii) and Bornean (Pongo pygmaeus) inferred from the joint-site frequency spectrum with ten individuals from each population. This model is an isolation-with- migration model, with exponential growth or decay in each population after the split. The Sumatran population grows in size, while the Bornean population slightly declines. """ citations = [_locke2011.because(stdpopsim.CiteReason.DEM_MODEL)] populations = [ stdpopsim.Population("Bornean", "Pongo pygmaeus (Bornean) population"), stdpopsim.Population("Sumatran", "Pongo abelii (Sumatran) population"), ] # Parameters from paper: # ancestral size, before split Na = 17934 # time of split T_split_years = 403149 # get split time in units of generations generation_time = _species.generation_time T_split = T_split_years / generation_time # proportion of ancestral pop to branch B s = 0.592 # sizes at split Na_B = 17934 * s Na_S = 17934 * (1 - s) # present sizes N_B = 8805 N_S = 37661 # get growth rates r_B = -1 * math.log(Na_B / N_B) / T_split r_S = -1 * math.log(Na_S / N_S) / T_split # migration rates m_S_B = 0.395 / 2 / Na m_B_S = 0.239 / 2 / Na # Population IDs correspond to their indexes in the population # configuration array. Therefore, we have 0=B and 1=S # initially. return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, citations=citations, populations=populations, generation_time=generation_time, population_configurations=[ msprime.PopulationConfiguration( initial_size=N_B, growth_rate=r_B, metadata=populations[0].asdict()), # NOQA msprime.PopulationConfiguration( initial_size=N_S, growth_rate=r_S, metadata=populations[1].asdict()), # NOQA ], migration_matrix=[ [0, m_B_S], # NOQA [m_S_B, 0], # NOQA ], demographic_events=[ # Merge populations and turn off migration, change to size Na msprime.MassMigration(time=T_split, source=1, destination=0, proportion=1.0), msprime.MigrationRateChange(time=T_split, rate=0), msprime.PopulationParametersChange(time=T_split, initial_size=Na, growth_rate=0, population_id=0), ], )
def _HolsteinFriesian_1M13(): id = "HolsteinFriesian_1M13" description = "Piecewise size changes in Holstein-Friesian cattle." long_description = """ The piecewise-constant population size model of Holstein-Friesian cattle from MacLeod et al. (2013). Population sizes were estimated from inferred runs of homozygosity, with parameter values taken from Figure 4A and Table S1. """ populations = [ stdpopsim.Population(id="Holstein_Friesian", description="Holstein-Friesian"), ] citations = [ stdpopsim.Citation( author="MacLeod et al.", year=2013, doi="https://doi.org/10.1093/molbev/mst125", reasons={stdpopsim.CiteReason.DEM_MODEL}, ) ] return stdpopsim.DemographicModel( id=id, description=description, long_description=long_description, populations=populations, citations=citations, generation_time=_species.generation_time, mutation_rate=1e-8, population_configurations=[ # 3 generations at 90, 1- 3 msprime.PopulationConfiguration(initial_size=90, metadata=populations[0].asdict()) ], # Here 'time' should be in generation notation ie. how many # generations ago were that Ne (effective population size) demographic_events=[ # 3 generations at 120, 4- 6 msprime.PopulationParametersChange(time=4, initial_size=120, population_id=0), # 6 generations at 250, 7- 12 msprime.PopulationParametersChange(time=7, initial_size=250, population_id=0), # 6 generations at 350, 13- 18 msprime.PopulationParametersChange(time=13, initial_size=350, population_id=0), # 6 generations at 1000, 19- 24 msprime.PopulationParametersChange(time=19, initial_size=1000, population_id=0), # 130 generations at 1500, 25- 154 msprime.PopulationParametersChange(time=25, initial_size=1500, population_id=0), # 200 generations at 2000, 155- 454 msprime.PopulationParametersChange(time=155, initial_size=2000, population_id=0), # 200 generations at 2500, 455- 654 msprime.PopulationParametersChange(time=455, initial_size=2500, population_id=0), # 1100 generations at 3500, 655- 1754 msprime.PopulationParametersChange(time=655, initial_size=3500, population_id=0), # 600 generations at 7000, 1755- 2354 msprime.PopulationParametersChange(time=1755, initial_size=7000, population_id=0), # 1000 generations at 10000, 2355- 3354 msprime.PopulationParametersChange(time=2355, initial_size=10000, population_id=0), # 29800 generations at 17000, 3355- 33154 msprime.PopulationParametersChange(time=3355, initial_size=17000, population_id=0), # 900000 generations at 62000, 33155-933154 msprime.PopulationParametersChange(time=33155, initial_size=62000, population_id=0), ], )
def hominin_composite_archaic_africa(): dm = hominin_composite() id = "HomininComposite2_4G20" description = "HomininComposite2_4G20 plus archaic lineage in Africa" generation_time = 29 # Ragsdale & Gravel 2019 N_0 = 3600 T_arch_afr_split = 499e3 / generation_time T_arch_afr_mig = 125e3 / generation_time T_arch_adm_end = 18.7e3 / generation_time m_AF_arch_af = 1.98e-5 T_YRI_CEU_split = 65.7e3 / generation_time populations = dm.populations + [ stdpopsim.Population( "ArchaicAFR", "Putative Archaic Africans", sampling_time=None ), ] population_configurations = dm.population_configurations + [ msprime.PopulationConfiguration( initial_size=N_0, metadata=populations[-1].asdict() ), ] pop = {p.id: i for i, p in enumerate(populations)} demographic_events = dm.demographic_events + [ # migration turned on between Yoruban and archaic African populations msprime.MigrationRateChange( time=T_arch_adm_end, rate=m_AF_arch_af, matrix_index=(pop["YRI"], pop["ArchaicAFR"]), ), msprime.MigrationRateChange( time=T_arch_adm_end, rate=m_AF_arch_af, matrix_index=(pop["ArchaicAFR"], pop["YRI"]), ), # YRI merges into Anc: turn off migration between YRI and ArchaicAFR. msprime.MigrationRateChange( time=T_YRI_CEU_split, rate=0, matrix_index=(pop["YRI"], pop["ArchaicAFR"]), ), msprime.MigrationRateChange( time=T_YRI_CEU_split, rate=0, matrix_index=(pop["ArchaicAFR"], pop["YRI"]), ), # migration turned on between African and archaic African populations msprime.MigrationRateChange( time=T_YRI_CEU_split, rate=m_AF_arch_af, matrix_index=(pop["Anc"], pop["ArchaicAFR"]), ), msprime.MigrationRateChange( time=T_YRI_CEU_split, rate=m_AF_arch_af, matrix_index=(pop["ArchaicAFR"], pop["Anc"]), ), # Beginning of migration between African and archaic African populations msprime.MigrationRateChange( time=T_arch_afr_mig, rate=0, matrix_index=(pop["Anc"], pop["ArchaicAFR"]), ), msprime.MigrationRateChange( time=T_arch_afr_mig, rate=0, matrix_index=(pop["ArchaicAFR"], pop["Anc"]), ), # Archaic African merges with moderns msprime.MassMigration( time=T_arch_afr_split, source=pop["ArchaicAFR"], destination=pop["Anc"], proportion=1.0, ), ] demographic_events.sort(key=lambda x: x.time) return stdpopsim.DemographicModel( id=id, description=description, long_description=dm.long_description, populations=populations, citations=dm.citations.copy(), generation_time=generation_time, population_configurations=population_configurations, demographic_events=demographic_events, )
def LockePongo(): id = "QC-TwoSpecies_2L11" populations = [ stdpopsim.Population("Bornean", ""), stdpopsim.Population("Sumatran", ""), ] # This is a split-migration style model, with exponential growth or # decay allowed in each population after the split. They assumed a # generation time of 20 years and a mutation rate of 2e-8 per bp per gen generation_time = 20 mutation_rate = 2e-8 # Parameters given in Table S21-2 Ne = 17934 s = 0.592 NB0 = s * Ne NS0 = (1 - s) * Ne NBF = 8805 NSF = 37661 mSB = 0.395 / 2 / Ne mBS = 0.239 / 2 / Ne T = 403149 / generation_time rB = np.log(NBF / NB0) / T rS = np.log(NSF / NS0) / T return stdpopsim.DemographicModel( id=id, description=id, long_description=id, generation_time=generation_time, populations=populations, # pop 0 is Bornean, pop 1 is Sumatran population_configurations=[ msprime.PopulationConfiguration(initial_size=NBF, growth_rate=rB), msprime.PopulationConfiguration(initial_size=NSF, growth_rate=rS), ], migration_matrix=[[0, mBS], [mSB, 0]], demographic_events=[ # merge, turn off migration, change size and growth rate msprime.MassMigration(source=1, destination=0, time=T, proportion=1), msprime.MigrationRateChange(time=T, rate=0), msprime.PopulationParametersChange(time=T, initial_size=Ne, growth_rate=0, population_id=0), ], population_id_map=[ { "Bornean": 0, "Sumatran": 1 }, { "Bornean": 0, "Sumatran": 1 }, ], mutation_rate=mutation_rate, )
def _sma_1pop(): # the size during the interval times[k] to times[k+1] = sizes[k] times = np.array( [ 699, 2796, 6068, 9894, 14370, 19606, 25730, 32894, 41275, 51077, 62544, 75958, 91648, 110001, 131471, 156584, 185960, 220324, 260520, 307540, 362541, 426879, 502139, 590173, 693151, 813610, 954517, 1119341, 1312147, 1537686, 1801500, 2110100, ] ) sizes = np.array( [ 42252426, 42252426, 60323, 72174, 40591, 21158, 21442, 39942, 78908, 111132, 110745, 96283, 87661, 83932, 83829, 91813, 111644, 143456, 181571, 217331, 241400, 246984, 238593, 228222, 217752, 198019, 165210, 121796, 121796, 73989, 73989, 73989, ] ) # MSMC is accurate from 40Kya-1.6Mya for A.thaliana (Durvasula et al 2017) # set the first 7 sizes # equal to the size at 8 (~40Kya) sizes[:8] = sizes[8] # set the last 2 entries equal # to the size at 30 (~1.6Mya) sizes[30:32] = sizes[30] demographic_events = [] for sz, t in zip(sizes, times): demographic_events.append( msprime.PopulationParametersChange(time=t, initial_size=sz, population_id=0) ) populations = [ stdpopsim.Population( id="SouthMiddleAtlas", description="Arabidopsis Thaliana South Middle Atlas population", ) ] return stdpopsim.DemographicModel( id="SouthMiddleAtlas_1D17", description="South Middle Atlas piecewise constant size", long_description=""" This model comes from MSMC using two randomly sampled homozygous individuals (Khe32 and Ifr4) from the South Middle Atlas region from the Middle Atlas Mountains in Morocco. The model is estimated with 32 time periods. Because estimates from the recent and ancient past are less accurate, we set the population size in the first 7 time periods equal to the size at the 8th time period and the size during last 2 time periods equal to the size in the 30th time period. """, populations=populations, citations=[ stdpopsim.Citation( author="Durvasula et al.", year=2017, doi="https://doi.org/10.1073/pnas.1616736114", reasons={stdpopsim.CiteReason.DEM_MODEL}, ) ], generation_time=1, demographic_events=demographic_events, population_configurations=[ msprime.PopulationConfiguration( initial_size=sizes[0], metadata=populations[0].asdict() ) ], )
def test_population_construction_popconfig(self): pc = [msprime.PopulationConfiguration(initial_size=1, growth_rate=0.03)] dm = stdpopsim.DemographicModel( id="", description="", long_description="", generation_time=1, population_configurations=pc) self.assertEqual(dm.populations[0].id, "pop0")