def No_mig(params, ns, pts): """ params = (nuPre,TPre,s,nu1,nu2,T) ns = (n1,n2) Isolation-with-migration model with exponential pop growth and a size change prior to split. nuPre: Size after first size change TPre: Time before split of first size change. s: Fraction of nuPre that goes to pop1. (Pop 2 has size nuPre*(1-s).) nu1: Final size of pop 1. nu2: Final size of pop 2. T: Time in the past of split (in units of 2*Na generations) n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nuPre, TPre, s, nu1, nu2, T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, TPre, nu=nuPre) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1_0 = nuPre * s nu2_0 = nuPre * (1 - s) nu1_func = lambda t: nu1_0 * (nu1 / nu1_0)**(t / T) nu2_func = lambda t: nu2_0 * (nu2 / nu2_0)**(t / T) phi = Integration.two_pops(phi, xx, T, nu1_func, nu2_func, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def CMG(params, ns, pts): nu1, nu2, b1, b2, m, T = params """ Model with migration during the divergence. nu1: Size of population 1 after split. nu2: Size of population 2 after split. b: Population growth coefficient m: Migration rate between populations (2*Na*m) T: The scaled time between the split (in units of 2*Na generations). """ # Define the grid we'll use xx = Numerics.default_grid(pts) # phi for the equilibrium ancestral population phi = PhiManip.phi_1D(xx) # Now do the divergence event phi = PhiManip.phi_1D_to_2D(xx, phi) # We start the population size change after the split and set the migration rates to m12 and m21 bnu1_func = lambda t: nu1 * b1**(t / T) bnu2_func = lambda t: nu2 * b2**(t / T) phi = Integration.two_pops(phi, xx, T, bnu1_func, bnu2_func, m12=m, m21=m) ### ## Finally, calculate the spectrum. fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def ancmig_adj_2(params, ns, pts): """ Model with split between pop 1 and (2,3), with gene flow. Split between pops 2 and 3, and all gene flow ceases. shorter isolation """ #7 parameters nu1, nuA, nu2, nu3, mA, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1=nu1, nu2=nuA, m12=mA, m21=mA) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) phi = Integration.three_pops(phi, xx, T2, nu1=nu1, nu2=nu2, nu3=nu3, m12=0, m21=0, m23=0, m32=0, m13=0, m31=0) fs = Spectrum.from_phi(phi, ns, (xx, xx, xx)) return fs
def split_symmig_all(params, ns, pts): """ Model with split between pop 1 and (2,3), then split between 2 and 3. Migration is symmetrical between all population pairs (ie 1<->2, 2<->3, and 1<->3). """ #10 parameters nu1, nuA, nu2, nu3, mA, m1, m2, m3, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1=nu1, nu2=nuA, m12=mA, m21=mA) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) phi = Integration.three_pops(phi, xx, T2, nu1=nu1, nu2=nu2, nu3=nu3, m12=m1, m21=m1, m23=m2, m32=m2, m13=m3, m31=m3) fs = Spectrum.from_phi(phi, ns, (xx, xx, xx)) return fs
def refugia_adj_3(params, ns, pts): """ Model with split between pop 1 and (2,3), gene flow does not occur, but then secondary contact occurs. Split between pops 2 and 3 occurs with gene flow, and gene flow happens between 1 and 2 as well. shortest isolation """ #10 parameters nu1, nuA, nu2, nu3, mA, m1, m2, T1a, T1b, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1a, nu1=nu1, nu2=nuA, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T1b, nu1=nu1, nu2=nuA, m12=mA, m21=mA) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) phi = Integration.three_pops(phi, xx, T2, nu1=nu1, nu2=nu2, nu3=nu3, m12=m1, m21=m1, m23=m2, m32=m2, m13=0, m31=0) fs = Spectrum.from_phi(phi, ns, (xx, xx, xx)) return fs
def ancmig_adj_3(params, ns, pts): """ Model with split between pop 1 and (2,3), with gene flow, which then stops. Split between pops 2 and 3, gene flow does not occur at all. longest isolation """ #8 parameters nu1, nuA, nu2, nu3, mA, T1a, T1b, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1a, nu1=nu1, nu2=nuA, m12=mA, m21=mA) phi = Integration.two_pops(phi, xx, T1b, nu1=nu1, nu2=nuA, m12=0, m21=0) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) phi = Integration.three_pops(phi, xx, T2, nu1=nu1, nu2=nu2, nu3=nu3, m12=0, m21=0, m23=0, m32=0, m13=0, m31=0) fs = Spectrum.from_phi(phi, ns, (xx, xx, xx)) return fs
def refugia_adj_2(params, ns, pts): """ Model with split between pop 1 and (2,3), gene flow does not occur. Split between pops 2 and 3, with gene flow. After appearance of 2 and 3, gene flow also occurs between 1 and 2. shorter isolation """ #8 parameters nu1, nuA, nu2, nu3, m1, m2, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1=nu1, nu2=nuA, m12=0, m21=0) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) phi = Integration.three_pops(phi, xx, T2, nu1=nu1, nu2=nu2, nu3=nu3, m12=m1, m21=m1, m23=m2, m32=m2, m13=0, m31=0) fs = Spectrum.from_phi(phi, ns, (xx, xx, xx)) return fs
def split_nomig(params, ns, pts): """ Model with split between pop 1 and (2,3), then split between 2 and 3. Migration does not occur between any population pair. """ #6 parameters nu1, nuA, nu2, nu3, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1=nu1, nu2=nuA, m12=0, m21=0) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) phi = Integration.three_pops(phi, xx, T2, nu1=nu1, nu2=nu2, nu3=nu3, m12=0, m21=0, m23=0, m32=0, m13=0, m31=0) fs = Spectrum.from_phi(phi, ns, (xx, xx, xx)) return fs
def split_ancient_symmig_size(params, ns, pts): """ Model with split and no gene flow, followed by period of size change and symmetrical gene flow. nu1b: Size of population 1 after split. nu2b: Size of population 2 after split. T1: Time in the past of split (in units of 2*Na generations) nu1r: Size of population 1 after time interval. nu2r: Size of population 2 after time interval. T2: The scale time between the ancient migration and present. m: Migration between pop 2 and pop 1. ns: Size of fs to generate. pts: Number of points to use in grid for evaluation. """ nu1b, nu2b, nu1r, nu2r, T1, T2, m = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1b, nu2b, m12=m, m21=m) phi = Integration.two_pops(phi, xx, T2, nu1r, nu2r, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def split_secondary_contact_sym_size(params, ns, pts): """ Model with split, complete isolation, followed by secondary contact with asymmetrical gene flow nu1b: Size of population 1 after split. nu2b: Size of population 2 after split. T1: The scaled time between the split and the secondary contact (in units of 2*Na generations). nu1r: Size of population 1 after time interval. nu2r: Size of population 2 after time interval. T2: The scale time between the secondary contact and present. m: Migration between pop 2 and pop 1. ns: Size of fs to generate. pts: Number of points to use in grid for evaluation. """ nu1b, nu2b, nu1r, nu2r, T1, T2, m = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1b, nu2b, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T2, nu1r, nu2r, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def split_no_mig_size(params, ns, pts): """ params = (nu1b,nu2b,nu1r,nu2r,T1,T2) ns = (n1,n2) Split into two populations of specifed size, with no migration, period of size change and no migration. nu1b: Size of population 1 after split. nu2b: Size of population 2 after split. T1: Time in the past of split (in units of 2*Na generations) nu1r: Size of population 1 after time interval. nu2r: Size of population 2 after time interval. T2: Time of population size change. n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nu1b, nu2b, nu1r, nu2r, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1b, nu2b, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T2, nu1r, nu2r, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def split_secondary_contact_sym(params, ns, pts): """ Model with split and no gene flow, followed by period of no size change and symmetrical gene flow nu1: Size of population 1 after split. nu2: Size of population 2 after split. m: Migration between pop 2 and pop 1. T: The scaled time between the split and the secondary contact (in units of 2*Na generations). Tsc: The scale time between the secondary contact and present. ns: Size of fs to generate. pts: Number of points to use in grid for evaluation. """ nu1, nu2, m, T, Tsc = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T, nu1, nu2, m12=0, m21=0) phi = Integration.two_pops(phi, xx, Tsc, nu1, nu2, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def split_mig(params, ns, pts): """ params = (nu1,nu2,T,m) ns = (n1,n2) Split into two populations of specifed size, with migration. nu1: Size of population 1 after split. nu2: Size of population 2 after split. T: Time in the past of split (in units of 2*Na generations) m: Migration rate between populations (2*Na*m) n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nu1,nu2,T,m = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T, nu1, nu2, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def split_symmig_adjacent(params, ns, pts): """ Model with split between pop 1 and (2,3), then split between 2 and 3. Assume 2 occurs in between populations 1 and 3, which do not come in to contact with one another. Migration is symmetrical between 'adjacent' population pairs (ie 1<->2, 2<->3, but not 1<->3). """ #9 parameters nu1, nuA, nu2, nu3, mA, m1, m2, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1=nu1, nu2=nuA, m12=mA, m21=mA) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) phi = Integration.three_pops(phi, xx, T2, nu1=nu1, nu2=nu2, nu3=nu3, m12=m1, m21=m1, m23=m2, m32=m2, m13=0, m31=0) fs = Spectrum.from_phi(phi, ns, (xx, xx, xx)) return fs
def priorsize_asym_mig(params, ns, pts): """ Size change followed by split with asymmetric migration nua: First Size of population before split. T1: Duration of first time before split nu1b: Size of population 1 after split. nu2b: Size of population 2 after split. T2: Time in the past of split (units of 2*Na generations) m12: Migration from pop 2 to pop 1 (2*Na*m12) m21: Migration from pop 1 to pop 2 """ nua, T1,nu1b, nu2b, T2, m12, m21 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, T1, nua) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T2, nu1b, nu2b, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def sec_contact_asym_mig_size_three_epoch(params, ns, pts): """ Split with no gene flow, followed by size change with asymmetrical gene flow, then isolation. nu1a: Size of population 1 after split. nu2a: Size of population 2 after split. T1: The scaled time between the split and the secondary contact (in units of 2*Na generations). nu1b: Size of population 1 after time interval. nu2b: Size of population 2 after time interval. T2: The scale time between the secondary contact and isolation. T3: The scaled time between the isolation and present. m12: Migration from pop 2 to pop 1 (2*Na*m12). m21: Migration from pop 1 to pop 2. """ nu1a, nu2a, nu1b, nu2b, m12, m21, T1, T2, T3 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1a, nu2a, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T2, nu1b, nu2b, m12=m12, m21=m21) phi = Integration.two_pops(phi, xx, T3, nu1b, nu2b, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def vic_sec_contact_asym_mig(params, ns, pts): """ Split with no gene flow, followed by period of asymmetrical gene flow. Populations are fractions of ancient population, where population 2 is represented by nuA*(s), and population 1 is represented by nuA*(1-s). nuA: Ancient population size s: Fraction of nuA that goes to pop2. (Pop 1 has size nuA*(1-s).) nu1: Size of population 1 after split. nu2: Size of population 2 after split. m12: Migration from pop 2 to pop 1 (2*Na*m12). m21: Migration from pop 1 to pop 2. T1: The scaled time between the split and the secondary contact (in units of 2*Na generations). T2: The scaled time between the secondary contact and present. """ nuA, nu1, nu2, m12, m21, T1, T2, s = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1 = nuA * (1 - s) nu2 = nuA * s phi = Integration.two_pops(phi, xx, T1, nu1, nu2, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T2, nu1, nu2, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def isolation_asym_mig_base(nu1a, nu2a, T1,nu1b, nu2b, T2, m12, m21, ns, pts): """ Split followed by two size changes with continuous asymmetric migration nu1a: Size of population 1 after split in first time interval. nu2a: Size of population 2 after split. T1: First time interval after split (units of 2*Na generations) nu1b: Size of population 1 after split in second time interval. nu2b: Size of population 2 after split. T2: Second time interval after split (units of 2*Na generations) m12: Migration from pop 2 to pop 1 (2*Na*m12) m21: Migration from pop 1 to pop 2 """ xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1a, nu2a, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T2, nu1b, nu2b, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def simple_iso(params, ns, pts): """ params = (nuPre,TPre,nu1,nu2,T) ns = (n1,n2) Simple migration model, the population size is constant nuPre: Size after first size change TPre: Time before split of first size change. nu1: size of pop 1. nu2: size of pop 2. T1: Time from divergence to migration end (in units of 2*Na generations) T2: Time from migration end to present n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nuPre,TPre,nu1,nu2,T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, TPre, nu=nuPre) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T, nu1, nu2, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def vic_two_epoch_admix(params, ns, pts): """ Split with no gene flow, followed by no migration but a discrete admixture event from pop 1 into pop 2 occurs. Populations are fractions of ancient population, where population 2 is represented by nuA*(s), and population 1 is represented by nuA*(1-s). nuA: Ancient population size s: Fraction of nuA that goes to pop2. (Pop 1 has size nuA*(1-s).) nu1: Size of population 1 after split. nu2: Size of population 2 after split. T1: The scaled time between the split and admixture event (in units of 2*Na generations). T2: The scaled time between the admixture event and present. f: Fraction of updated population 2 to be derived from population 1. """ nuA, nu1, nu2, T1, T2, s, f = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1 = nuA * (1 - s) nu2 = nuA * s phi = Integration.two_pops(phi, xx, T1, nu1, nu2, m12=0, m21=0) phi = PhiManip.phi_2D_admix_1_into_2(phi, f, xx, xx) phi = Integration.two_pops(phi, xx, T2, nu1, nu2, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def IM(params, ns, pts): """ ns = (n1,n2) params = (s,nu1,nu2,T,m12,m21) Isolation-with-migration model with exponential pop growth. s: Size of pop 1 after split. (Pop 2 has size 1-s.) nu1: Final size of pop 1. nu2: Final size of pop 2. T: Time in the past of split (in units of 2*Na generations) m12: Migration from pop 2 to pop 1 (2*Na*m12) m21: Migration from pop 1 to pop 2 n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ s, nu1, nu2, T, m12, m21 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1_func = lambda t: s * (nu1 / s)**(t / T) nu2_func = lambda t: (1 - s) * (nu2 / (1 - s))**(t / T) phi = Integration.two_pops(phi, xx, T, nu1_func, nu2_func, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def sec_contact_sym_mig_size(params, ns, pts): """ Split with no gene flow, followed by size change with symmetrical gene flow. nu1a: Size of population 1 after split. nu2a: Size of population 2 after split. T1: The scaled time between the split and the secondary contact (in units of 2*Na generations). nu1b: Size of population 1 after time interval. nu2b: Size of population 2 after time interval. T2: The scale time between the secondary contact and present. m: Migration between pop 2 and pop 1. """ nu1a, nu2a, nu1b, nu2b, m, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1a, nu2a, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T2, nu1b, nu2b, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def sec_contact_sym_mig_three_epoch(params, ns, pts): """ Split with no gene flow, followed by period of symmetrical gene flow, then isolation. nu1: Size of population 1 after split. nu2: Size of population 2 after split. m: Migration between pop 2 and pop 1. T1: The scaled time between the split and the secondary contact (in units of 2*Na generations). T2: The scaled time between the secondary contact and third epoch. T3: The scaled time between the isolation and present. """ nu1, nu2, m, T1, T2, T3 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1, nu2, m12=0, m21=0) phi = Integration.two_pops(phi, xx, T2, nu1, nu2, m12=m, m21=m) phi = Integration.two_pops(phi, xx, T3, nu1, nu2, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def asym_mig_size(params, ns, pts): """ Split with different migration rates, then size change with different migration rates. nu1a: Size of population 1 after split. nu2a: Size of population 2 after split. T1: Time in the past of split (in units of 2*Na generations) nu1b: Size of population 1 after time interval. nu2b: Size of population 2 after time interval. T2: Time of population size change. m12: Migration from pop 2 to pop 1 (2*Na*m12) m21: Migration from pop 1 to pop 2 """ nu1a, nu2a, nu1b, nu2b, m12, m21, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1a, nu2a, m12=m12, m21=m21) phi = Integration.two_pops(phi, xx, T2, nu1b, nu2b, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def anc_asym_mig_size(params, ns, pts): """ Split with asymmetrical gene flow, followed by size change with no gene flow. nu1a: Size of population 1 after split. nu2a: Size of population 2 after split. T1: Time in the past of split (in units of 2*Na generations) nu1b: Size of population 1 after time interval. nu2b: Size of population 2 after time interval. T2: The scale time between the ancient migration and present. m12: Migration from pop 2 to pop 1 (2*Na*m12). m21: Migration from pop 1 to pop 2. """ nu1a, nu2a, nu1b, nu2b, m12, m21, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1a, nu2a, m12=m12, m21=m21) phi = Integration.two_pops(phi, xx, T2, nu1b, nu2b, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def founder_asym(params, ns, pts): """ Split into two populations, with two migration rates. Populations are fractions of ancient population, where population 2 is represented by nuA*(s), and population 1 is represented by nuA*(1-s). Population two undergoes an exponential growth event, while population one is constant. nuA: Ancient population size s: Fraction of nuA that goes to pop2. (Pop 1 has size nuA*(1-s).) nu1: Final size of pop 1. nu2: Final size of pop 2. T: Time in the past of split (in units of 2*Na generations) m12: Migration from pop 2 to pop 1 (2*Na*m12) m21: Migration from pop 1 to pop 2 """ nuA, nu1, nu2, m12, m21, T, s = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx, nu=nuA) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1 = nuA * (1 - s) nu2_0 = nuA * s nu2_func = lambda t: nu2_0 * (nu2 / nu2_0)**(t / T) #note, the nu2_0 can be eliminated and the function can appear as: #nu2_func = lambda t: (nuA*(1-s)) * (nu2/(nuA*(1-s)))**(t/T) phi = Integration.two_pops(phi, xx, T, nu1, nu2_func, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def sym_mig_size(params, ns, pts): """ Split with symmetric migration, then size change with symmetric migration. nu1a: Size of population 1 after split. nu2a: Size of population 2 after split. T1: Time in the past of split (in units of 2*Na generations) nu1b: Size of population 1 after time interval. nu2b: Size of population 2 after time interval. T2: Time of population size change. m: Migration rate between populations (2*Na*m) """ nu1a, nu2a, nu1b, nu2b, m, T1, T2 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T1, nu1a, nu2a, m12=m, m21=m) phi = Integration.two_pops(phi, xx, T2, nu1b, nu2b, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def IM(params, ns, pts): """ ns = (n1,n2) params = (s,nu1,nu2,T,m12,m21) Isolation-with-migration model with exponential pop growth. s: Size of pop 1 after split. (Pop 2 has size 1-s.) nu1: Final size of pop 1. nu2: Final size of pop 2. T: Time in the past of split (in units of 2*Na generations) m12: Migration from pop 2 to pop 1 (2*Na*m12) m21: Migration from pop 1 to pop 2 n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ s,nu1,nu2,T,m12,m21 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1_func = lambda t: s * (nu1/s)**(t/T) nu2_func = lambda t: (1-s) * (nu2/(1-s))**(t/T) phi = Integration.two_pops(phi, xx, T, nu1_func, nu2_func, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def vic_no_mig_admix_late(params, ns, pts): """ Split into two populations, no migration but a discrete admixture event from pop 1 into pop 2 occurs. Populations are fractions of ancient population, where population 2 is represented by nuA*(s), and population 1 is represented by nuA*(1-s). nuA: Ancient population size s: Fraction of nuA that goes to pop2. (Pop 1 has size nuA*(1-s).) nu1: Size of population 1 after split. nu2: Size of population 2 after split. T: Time in the past of split (in units of 2*Na generations) f: Fraction of updated population 2 to be derived from population 1. """ nuA, nu1, nu2, T, s, f = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1 = nuA * (1 - s) nu2 = nuA * s phi = Integration.two_pops(phi, xx, T, nu1, nu2, m12=0, m21=0) phi = PhiManip.phi_2D_admix_1_into_2(phi, f, xx, xx) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def founder_nomig_admix_two_epoch(params, ns, pts): """ Split into two populations, with no migration. Populations are fractions of ancient population, where population 2 is represented by nuA*(s), and population 1 is represented by nuA*(1-s). Population two undergoes an exponential growth event, while population one is constant. nuA: Ancient population size s: Fraction of nuA that goes to pop2. (Pop 1 has size nuA*(1-s).) nu1: Final size of pop 1. nu2: Final size of pop 2. T1: Time in the past of split (in units of 2*Na generations) T2: The scaled time between the admixture event and present. f: Fraction of updated population 2 to be derived from population 1. """ nuA, nu1, nu2, T1, T2, s, f = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx, nu=nuA) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1 = nuA * (1 - s) nu2_0 = nuA * s nu2_func = lambda t: nu2_0 * (nu2 / nu2_0)**(t / T1) #note, the nu2_0 can be eliminated and the function can appear as: #nu2_func = lambda t: (nuA*(1-s)) * (nu2/(nuA*(1-s)))**(t/T) phi = Integration.two_pops(phi, xx, T1, nu1, nu2_func, m12=0, m21=0) phi = PhiManip.phi_2D_admix_1_into_2(phi, f, xx, xx) phi = Integration.two_pops(phi, xx, T2, nu1, nu2, m12=0, m21=0) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def split_mig(params, ns, pts): """ params = (nu1,nu2,T,m) ns = (n1,n2) Split into two populations of specifed size, with migration. nu1: Size of population 1 after split. nu2: Size of population 2 after split. T: Time in the past of split (in units of 2*Na generations) m: Migration rate between populations (2*Na*m) n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nu1, nu2, T, m = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T, nu1, nu2, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def bottlegrowth_split_mig(params, ns, pts): """ params = (nuB,nuF,m,T,Ts) ns = (n1,n2) Instantanous size change followed by exponential growth then split with migration. nuB: Ratio of population size after instantanous change to ancient population size nuF: Ratio of contempoary to ancient population size m: Migration rate between the two populations (2*Na*m). T: Time in the past at which instantaneous change happened and growth began (in units of 2*Na generations) Ts: Time in the past at which the two populations split. n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nuB, nuF, m, T, Ts = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) nu_func = lambda t: nuB * numpy.exp(numpy.log(nuF / nuB) * t / T) phi = Integration.one_pop(phi, xx, T - Ts, nu_func) phi = PhiManip.phi_1D_to_2D(xx, phi) nu0 = nu_func(T - Ts) nu_func = lambda t: nu0 * numpy.exp(numpy.log(nuF / nu0) * t / Ts) phi = Integration.two_pops(phi, xx, Ts, nu_func, nu_func, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx, xx)) return fs
def bottlegrowth_split_mig(params, ns, pts): """ params = (nuB,nuF,m,T,Ts) ns = (n1,n2) Instantanous size change followed by exponential growth then split with migration. nuB: Ratio of population size after instantanous change to ancient population size nuF: Ratio of contempoary to ancient population size m: Migration rate between the two populations (2*Na*m). T: Time in the past at which instantaneous change happened and growth began (in units of 2*Na generations) Ts: Time in the past at which the two populations split. n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nuB,nuF,m,T,Ts = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) nu_func = lambda t: nuB*numpy.exp(numpy.log(nuF/nuB) * t/T) phi = Integration.one_pop(phi, xx, T-Ts, nu_func) phi = PhiManip.phi_1D_to_2D(xx, phi) nu0 = nu_func(T-Ts) nu_func = lambda t: nu0*numpy.exp(numpy.log(nuF/nu0) * t/Ts) phi = Integration.two_pops(phi, xx, Ts, nu_func, nu_func, m12=m, m21=m) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def snm2(notused, ns, pts): """ ns = (n1,n2) Standard neutral model, populations never diverge. """ xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def bottlegrowth(params, ns, pts): """ Instantanous size change followed by exponential growth. params = (nuB,nuF,T) ns = (n1,) nuB: Ratio of population size after instantanous change to ancient population size nuF: Ratio of contemporary to ancient population size T: Time in the past at which instantaneous change happened and growth began (in units of 2*Na generations) n1: Number of samples in resulting Spectrum pts: Number of grid points to use in integration. """ nuB,nuF,T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) nu_func = lambda t: nuB*numpy.exp(numpy.log(nuF/nuB) * t/T) phi = Integration.one_pop(phi, xx, T, nu_func) fs = Spectrum.from_phi(phi, ns, (xx,)) return fs
def bottleneck_1d(params, n1, pts): nuC, T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, T, nuC) model_sfs = Spectrum.from_phi(phi, n1, (xx,)) return model_sfs
def snm(notused, ns, pts): """ Standard neutral model. ns = (n1,) n1: Number of samples in resulting Spectrum pts: Number of grid points to use in integration. """ xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) fs = Spectrum.from_phi(phi, ns, (xx,)) return fs
def IM_pre(params, ns, pts): """ params = (nuPre,TPre,s,nu1,nu2,T,m12,m21) ns = (n1,n2) Isolation-with-migration model with exponential pop growth and a size change prior to split. nuPre: Size after first size change TPre: Time before split of first size change. s: Fraction of nuPre that goes to pop1. (Pop 2 has size nuPre*(1-s).) nu1: Final size of pop 1. nu2: Final size of pop 2. T: Time in the past of split (in units of 2*Na generations) m12: Migration from pop 2 to pop 1 (2*Na*m12) m21: Migration from pop 1 to pop 2 n1,n2: Sample sizes of resulting Spectrum pts: Number of grid points to use in integration. """ nuPre,TPre,s,nu1,nu2,T,m12,m21 = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, TPre, nu=nuPre) phi = PhiManip.phi_1D_to_2D(xx, phi) nu1_0 = nuPre*s nu2_0 = nuPre*(1-s) nu1_func = lambda t: nu1_0 * (nu1/nu1_0)**(t/T) nu2_func = lambda t: nu2_0 * (nu2/nu2_0)**(t/T) phi = Integration.two_pops(phi, xx, T, nu1_func, nu2_func, m12=m12, m21=m21) fs = Spectrum.from_phi(phi, ns, (xx,xx)) return fs
def two_epoch(params, ns, pts): """ Instantaneous size change some time ago. params = (nu,T) ns = (n1,) nu: Ratio of contemporary to ancient population size T: Time in the past at which size change happened (in units of 2*Na generations) n1: Number of samples in resulting Spectrum pts: Number of grid points to use in integration. """ nu,T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, T, nu) fs = Spectrum.from_phi(phi, ns, (xx,)) return fs
def growth(params, ns, pts): """ Exponential growth beginning some time ago. params = (nu,T) ns = (n1,) nu: Ratio of contemporary to ancient population size T: Time in the past at which growth began (in units of 2*Na generations) n1: Number of samples in resulting Spectrum pts: Number of grid points to use in integration. """ nu,T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) nu_func = lambda t: numpy.exp(numpy.log(nu) * t/T) phi = Integration.one_pop(phi, xx, T, nu_func) fs = Spectrum.from_phi(phi, ns, (xx,)) return fs
def three_epoch(params, ns, pts): """ params = (nuB,nuF,TB,TF) ns = (n1,) nuB: Ratio of bottleneck population size to ancient pop size nuF: Ratio of contemporary to ancient pop size TB: Length of bottleneck (in units of 2*Na generations) TF: Time since bottleneck recovery (in units of 2*Na generations) n1: Number of samples in resulting Spectrum pts: Number of grid points to use in integration. """ nuB,nuF,TB,TF = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, TB, nuB) phi = Integration.one_pop(phi, xx, TF, nuF) fs = Spectrum.from_phi(phi, ns, (xx,)) return fs
""" Dadi demographic models for WY and CO populations of E. gillettii. """ import numpy from dadi import Numerics, PhiManip, Integration from dadi.Spectrum_mod import Spectrum #one ancestral population splits at time T ago with no migration def bottleneck_split(params, (n1,n2), pts): nuW, nuC, T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, T, nuW, nuC) model_sfs = Spectrum.from_phi(phi, (n1,n2), (xx,xx)) return model_sfs #one dimensional demographic inference of bottlneck size and timing def bottleneck_1d(params, n1, pts): nuC, T = params xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, T, nuC) model_sfs = Spectrum.from_phi(phi, n1, (xx,)) return model_sfs
import numpy from dadi import Numerics, PhiManip, Integration, Spectrum def OutOfAfrica((nuAf, nuB, nuEu0, nuEu, nuAs0, nuAs, mAfB, mAfEu, mAfAs, mEuAs, TAf, TB, TEuAs), (n1,n2,n3), pts): xx = Numerics.default_grid(pts) phi = PhiManip.phi_1D(xx) phi = Integration.one_pop(phi, xx, TAf, nu=nuAf) phi = PhiManip.phi_1D_to_2D(xx, phi) phi = Integration.two_pops(phi, xx, TB, nu1=nuAf, nu2=nuB, m12=mAfB, m21=mAfB) phi = PhiManip.phi_2D_to_3D_split_2(xx, phi) nuEu_func = lambda t: nuEu0*(nuEu/nuEu0)**(t/TEuAs) nuAs_func = lambda t: nuAs0*(nuAs/nuAs0)**(t/TEuAs) phi = Integration.three_pops(phi, xx, TEuAs, nu1=nuAf, nu2=nuEu_func, nu3=nuAs_func, m12=mAfEu, m13=mAfAs, m21=mAfEu, m23=mEuAs, m31=mAfAs, m32=mEuAs) fs = Spectrum.from_phi(phi, (n1,n2,n3), (xx,xx,xx)) return fs def OutOfAfrica_mscore((nuAf, nuB, nuEu0, nuEu, nuAs0, nuAs, mAfB, mAfEu, mAfAs, mEuAs, TAf, TB, TEuAs)): alphaEu = numpy.log(nuEu/nuEu0)/TEuAs alphaAs = numpy.log(nuAs/nuAs0)/TEuAs