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 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 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 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 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 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 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 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
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 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
#Create python dictionary from snps file dd = Misc.make_data_dict(snps) #************** #pop_ids is a list which should match the populations headers of your SNPs file columns pop_ids = ["North", "South"] #************** #projection sizes, in ALLELES not individuals proj = [16, 32] #Convert this dictionary into folded AFS object #[polarized = False] creates folded spectrum object fs = Spectrum.from_data_dict(dd, pop_ids=pop_ids, projections=proj, polarized=False) #print some useful information about the afs or jsfs print( "\n\n============================================================================" ) print("\nData for site frequency spectrum:\n") print("Projection: {}".format(proj)) print("Sample sizes: {}".format(fs.sample_sizes)) print("Sum of SFS: {}".format(numpy.around(fs.S(), 2))) print( "\n============================================================================\n" ) #================================================================================
def get_godambe(func_ex, grid_pts, all_boot, p0, data, eps, log=False, just_hess=False, boot_theta_adjusts=[]): """ Godambe information and Hessian matrices func_ex: Model function grid_pts: Number of grid points to evaluate the model function all_boot: List of bootstrap frequency spectra p0: Best-fit parameters for func_ex. data: Original data frequency spectrum eps: Fractional stepsize to use when taking finite-difference derivatives Note that if eps*param is < 1e-6, then the step size for that parameter will simply be eps, to avoid numerical issues with small parameter perturbations. log: If True, calculate derivatives in terms of log-parameters just_hess: If True, only evaluate and return the Hessian matrix boot_theta_adjusts: Factors by which to adjust theta for each bootstrap sample, relative to full data theta. """ ns = data.sample_sizes if not boot_theta_adjusts: boot_theta_adjusts = numpy.ones(len(all_boot)) # Cache evaluations of the frequency spectrum inside our hessian/J # evaluation function cache = {} def func(params, data, theta_adjust=1): key = (tuple(params), tuple(ns), tuple(grid_pts)) if key not in cache: cache[key] = func_ex(params, ns, grid_pts) # theta_adjust deals with bootstraps that need different thetas fs = theta_adjust * cache[key] return Inference.ll(fs, data) def log_func(logparams, data, theta_adjust=1): return func(numpy.exp(logparams), data, theta_adjust) # First calculate the observed hessian. # theta_adjust defaults to 1. if not log: hess = -get_hess(func, p0, eps, args=[data]) else: hess = -get_hess(log_func, numpy.log(p0), eps, args=[data]) if just_hess: return hess # Now the expectation of J over the bootstrap data J = numpy.zeros((len(p0), len(p0))) # cU is a column vector cU = numpy.zeros((len(p0), 1)) for ii, (boot, theta_adjust) in enumerate(zip(all_boot, boot_theta_adjusts)): boot = Spectrum(boot) if not log: grad_temp = get_grad(func, p0, eps, args=[boot, theta_adjust]) else: grad_temp = get_grad(log_func, numpy.log(p0), eps, args=[boot, theta_adjust]) J_temp = numpy.outer(grad_temp, grad_temp) J = J + J_temp cU = cU + grad_temp J = J / len(all_boot) cU = cU / len(all_boot) # G = H*J^-1*H J_inv = numpy.linalg.inv(J) godambe = numpy.dot(numpy.dot(hess, J_inv), hess) return godambe, hess, J, cU
def get_godambe(func_ex, grid_pts, all_boot, p0, data, eps, log=False, just_hess=False): """ Godambe information and Hessian matrices NOTE: Assumes that last parameter in p0 is theta. func_ex: Model function grid_pts: Number of grid points to evaluate the model function all_boot: List of bootstrap frequency spectra p0: Best-fit parameters for func_ex. data: Original data frequency spectrum eps: Fractional stepsize to use when taking finite-difference derivatives log: If True, calculate derivatives in terms of log-parameters just_hess: If True, only evaluate and return the Hessian matrix """ ns = data.sample_sizes # Cache evaluations of the frequency spectrum inside our hessian/J # evaluation function cache = {} def func(params, data): key = (tuple(params), tuple(ns), tuple(grid_pts)) if key not in cache: cache[key] = func_ex(params, ns, grid_pts) fs = cache[key] return Inference.ll(fs, data) def log_func(logparams, data): return func(numpy.exp(logparams), data) # First calculate the observed hessian if not log: hess = -get_hess(func, p0, eps, args=[data]) else: hess = -get_hess(log_func, numpy.log(p0), eps, args=[data]) if just_hess: return hess # Now the expectation of J over the bootstrap data J = numpy.zeros((len(p0), len(p0))) # cU is a column vector cU = numpy.zeros((len(p0), 1)) for ii, boot in enumerate(all_boot): boot = Spectrum(boot) if not log: grad_temp = get_grad(func, p0, eps, args=[boot]) else: grad_temp = get_grad(log_func, numpy.log(p0), eps, args=[boot]) J_temp = numpy.outer(grad_temp, grad_temp) J = J + J_temp cU = cU + grad_temp J = J / len(all_boot) cU = cU / len(all_boot) # G = H*J^-1*H J_inv = numpy.linalg.inv(J) godambe = numpy.dot(numpy.dot(hess, J_inv), hess) return godambe, hess, J, cU
""" 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