# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # This script is an example in the simuPOP user's guide. Please refer to # the user's guide (http://simupop.sourceforge.net/manual) for a detailed # description of this example. # import simuPOP as sim import time pop = sim.Population(1000, loci=10) pop.dvars().init_time = time.time() pop.dvars().last_time = time.time() exec('import time', pop.vars(), pop.vars()) pop.evolve( initOps=sim.InitSex(), matingScheme=sim.RandomMating(), postOps=[ sim.IfElse('time.time() - last_time > 5', [ sim.PyEval(r'"Gen: %d\n" % gen'), sim.PyExec('last_time = time.time()') ]), sim.TerminateIf('time.time() - init_time > 20') ] )
import simuOpt simuOpt.setOptions(quiet=True, alleleType='long') import simuPOP as sim pop = sim.Population(size=1000, loci=[1]) simu = sim.Simulator(pop, 5) simu.evolve( initOps=[ sim.InitSex(), sim.PyExec('introGen=[]') ], preOps=[ sim.Stat(alleleFreq=0), sim.IfElse('alleleFreq[0][1] == 0', ifOps=[ sim.PointMutator(loci=0, allele=1, inds=0), sim.PyExec('introGen.append(gen)') ]), sim.TerminateIf('alleleFreq[0][1] >= 0.05') ], matingScheme=sim.RandomMating() ) # number of attempts print([len(x.dvars().introGen) for x in simu.populations()]) # age of mutant print([x.dvars().gen - x.dvars().introGen[-1] for x in simu.populations()])
# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # This script is an example in the simuPOP user's guide. Please refer to # the user's guide (http://simupop.sourceforge.net/manual) for a detailed # description of this example. # import simuPOP as sim simu = sim.Simulator(sim.Population(50, loci=[10], ploidy=1), rep=3) simu.evolve(gen = 5) simu.dvars(0).gen simu.evolve( initOps=[sim.InitGenotype(freq=[0.5, 0.5])], matingScheme=sim.RandomSelection(), postOps=[ sim.Stat(alleleFreq=5), sim.IfElse('alleleNum[5][0] == 0', sim.PyEval(r"'Allele 0 is lost in rep %d at gen %d\n' % (rep, gen)")), sim.IfElse('alleleNum[5][0] == 50', sim.PyEval(r"'Allele 0 is fixed in rep %d at gen %d\n' % (rep, gen)")), sim.TerminateIf('len(alleleNum[5]) == 1'), ], ) [simu.dvars(x).gen for x in range(3)]
def simuGWAS(pop, mutaRate=1.8e-8, recIntensity=1e-8, migrRate=0.0001, expandGen=500, expandSize=[10000], DPL=[], curFreq=[], fitness=[1, 1, 1], scale=1, logger=None): # handling scaling... mutaRate *= scale recIntensity *= scale migrRate *= scale expandGen = int(expandGen / scale) fitness = [1 + (x - 1) * scale for x in fitness] pop.dvars().scale = scale # Demographic function demoFunc = linearExpansion(pop.subPopSizes(), expandSize, expandGen) # define a trajectory function trajFunc = None introOps = [] if len(DPL) > 0: stat(pop, alleleFreq=DPL, vars='alleleFreq_sp') currentFreq = [] for sp in range(pop.numSubPop()): for loc in pop.lociByNames(DPL): currentFreq.append(pop.dvars(sp).alleleFreq[loc][1]) # if there is no existing mutants at DPL if sum(currentFreq) == 0.: endFreq = [(x - min(0.01, x / 5.), x + min(0.01, x / 5., (1 - x) / 5.)) for x in curFreq] traj = simulateForwardTrajectory(N=demoFunc, beginGen=0, endGen=expandGen, beginFreq=currentFreq, endFreq=endFreq, nLoci=len(DPL), fitness=fitness, maxAttempts=1000, logger=logger) introOps = [] else: traj = simulateBackwardTrajectory(N=demoFunc, endGen=expandGen, endFreq=curFreq, nLoci=len(DPL), fitness=fitness, minMutAge=1, maxMutAge=expandGen, logger=logger) introOps = traj.mutators(loci=DPL) if traj is None: raise SystemError( 'Failed to generated trajectory after 1000 attempts.') trajFunc = traj.func() if pop.numSubPop() > 1: pop.addInfoFields('migrate_to') pop.dvars().scale = scale pop.evolve( initOps=sim.InitSex(), preOps=[ sim.SNPMutator(u=mutaRate, v=mutaRate), sim.IfElse( pop.numSubPop() > 1, sim.Migrator( rate=migrSteppingStoneRates(migrRate, pop.numSubPop()))), ] + introOps, matingScheme=sim.ControlledRandomMating( loci=DPL, alleles=[1] * len(DPL), freqFunc=trajFunc, ops=sim.Recombinator(intensity=recIntensity), subPopSize=demoFunc), postOps=[ sim.Stat(popSize=True, structure=range(pop.totNumLoci())), sim.PyEval( r'"After %3d generations, size=%s\n" % ((gen + 1 )* scale, subPopSize)' ), sim.IfElse(pop.numSubPop() > 1, sim.PyEval(r"'F_st = %.3f\n' % F_st", step=10), step=10), ], gen=expandGen) return pop
# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # This script is an example in the simuPOP user's guide. Please refer to # the user's guide (http://simupop.sourceforge.net/manual) for a detailed # description of this example. # import simuPOP as sim pop = sim.Population(size=1000, loci=1) verbose = True pop.evolve( initOps=[ sim.InitSex(), sim.InitGenotype(freq=[0.5, 0.5]), ], matingScheme=sim.RandomMating(), postOps=sim.IfElse(verbose, ifOps=[ sim.Stat(alleleFreq=0), sim.PyEval(r"'Gen: %3d, allele freq: %.3f\n' % (gen, alleleFreq[0][1])", step=5) ], begin=10), gen = 30 )
# use a pedigree object recovered from a file saved by operator PedigreeTagger ped = sim.loadPedigree('structured.ped') # create a top most population, but we do not need all of them # so we record only used individuals IDs = [x.ind_id for x in ped.allIndividuals(ancGens=ped.ancestralGens())] sex = [x.sex() for x in ped.allIndividuals(ancGens=ped.ancestralGens())] # create a population, this time with genotype. Note that we do not need # populaton structure because PedigreeMating disregard population structure. pop = sim.Population(size=len(IDs), loci=1000, infoFields='ind_id') # manually initialize ID and sex sim.initInfo(pop, IDs, infoFields='ind_id') sim.initSex(pop, sex=sex) pop.evolve( initOps=sim.InitGenotype(freq=[0.4, 0.6]), # we do not need migration, or set number of offspring, # or demographic model, but we do need a genotype transmitter matingScheme=sim.PedigreeMating(ped, ops=sim.IfElse(lambda mom: mom is None, sim.CloneGenoTransmitter(), sim.MendelianGenoTransmitter()) ), gen=100 ) # print(pop.indInfo('ind_id')[:5]) print([pop.individual(x).sex() for x in range(5)]) # The pedigree object does not have population structure print(pop.subPopSizes())
def simuRareVariants(regions, N, G, mu, selDist, selCoef, selModel='exponential', recRate=0, splitTo=[1], splitAt=0, migrRate=0, steps=[100], mutationModel='finite_sites', initPop='', extMutantFile='', addMutantsAt=0, postHook=None, statFile='', popFile='', markerFile='', mutantFile='', genotypeFile='', verbose=1, logger=None): ''' Please refer to simuRareVariants.py -h for a detailed description of all parameters. Note that a user-defined function can be passed to parameter selDist to specify arbitrary distribution of fitness. A script-only feature is that a Python function can be provided through parameter postHook to process the population at each generation. ''' # # convert regions to start/end positions ranges = [] chromTypes = [] for region in regions: start, end = [int(x) for x in region.split(':')[1].split('..')] ranges.append((start, end + 1)) if region.split(':')[0] == 'chrX': chromTypes.append(sim.CHROMOSOME_X) if len(regions) > 1: raise ValueError( 'The current implementation only allows one region if it is on chromosome X' ) logger.info('Chromosome {} is on chromosome X'.format(region)) elif region.split(':')[0] == 'chrY': raise ValueError( 'The current implementation does not support chromosome Y') chromTypes.append(sim.CHROMOSOME_Y) logger.info('Chromosome {} is on chromosome Y'.format(region)) else: chromTypes.append(sim.AUTOSOME) if logger: logger.info('%s regions with a total length of %d basepair.' % (len(ranges), sum([x[1] - x[0] for x in ranges]))) # # set default parameter if selCoef is None: # set default parameters if selDist == 'mixed_gamma': selCoef = [0.0186, 0.0001, 0.184, 0.160 * 2, 0.5, 0.0001, 0.1] elif selDist == 'mixed_gamma1': selCoef = [0, -1, 0.562341, 0.01, 0.5, 0.00001, 0.1] elif selDist == 'gamma1': selCoef = [0.23, 0.185 * 2, 0.5] elif selDist == 'gamma2': selCoef = [0.184, 0.160 * 2, 0.5] elif selDist == 'gamma3': selCoef = [0.206, 0.146 * 2, 0.5] elif selDist == 'constant': selCoef = [0.01, 0.5] elif not isinstance(selDist, collections.Callable): raise ValueError("Unsupported random distribution") else: # force to list type selCoef = list(selCoef) if len(steps) == 0: # at the end of each stage steps = G elif len(steps) == 1: # save step for each stage steps = steps * len(G) # use a right selection operator. collector = fitnessCollector() mode = { 'multiplicative': sim.MULTIPLICATIVE, 'additive': sim.ADDITIVE, 'exponential': sim.EXPONENTIAL }[selModel] # if type(popFile) == str: popFile = [popFile, -1] # if isinstance(selDist, collections.Callable): mySelector = MutSpaceSelector(selDist=selDist, mode=mode, output=collector.getCoef) elif selDist == 'mixed_gamma': mySelector = MutSpaceSelector(selDist=mixedGamma(selCoef), mode=mode, output=collector.getCoef) elif selDist == 'mixed_gamma1': mySelector = MutSpaceSelector(selDist=mixedGamma1(selCoef), mode=mode, output=collector.getCoef) elif selDist.startswith('gamma'): mySelector = MutSpaceSelector(selDist=[sim.GAMMA_DISTRIBUTION] + selCoef, mode=mode, output=collector.getCoef) elif selDist == 'constant': if selCoef == 0: mySelector = sim.NoneOp() else: mySelector = MutSpaceSelector(selDist=[sim.CONSTANT] + selCoef, mode=mode, output=collector.getCoef) # # Evolve if os.path.isfile(initPop): if logger: logger.info('Loading initial population %s...' % initPop) pop = sim.loadPopulation(initPop) if pop.numChrom() != len(regions): raise ValueError( 'Initial population %s does not have specified regions.' % initPop) for ch, reg in enumerate(regions): if pop.chromName(ch) != reg: raise ValueError( 'Initial population %s does not have region %s' % (initPop, reg)) pop.addInfoFields(['fitness', 'migrate_to']) else: pop = sim.Population(size=N[0], loci=[10] * len(regions), chromNames=regions, infoFields=['fitness', 'migrate_to'], chromTypes=chromTypes) if logger: startTime = time.clock() # progGen = [] # 0, G[0], G[0]+G[1], ..., sum(G) Gens = [sum(G[:i]) for i in range(len(G) + 1)] for i in range(len(Gens) - 1): progGen += list(range(Gens[i], Gens[i + 1], steps[i])) pop.evolve( initOps=sim.InitSex(), preOps=[ sim.PyOutput('''Statistics outputted are 1. Generation number, 2. population size (a list), 3. number of segregation sites, 4. average number of segregation sites per individual 5. average allele frequency * 100 6. average fitness value 7. minimal fitness value of the parental population ''', at = 0)] + \ [sim.PyOutput('Starting stage %d\n' % i, at = Gens[i]) for i in range(0, len(Gens))] + \ # add alleles from an existing population [sim.IfElse(extMutantFile != '', ifOps = [ sim.PyOutput('Loading and converting population %s' % extMutantFile), sim.PyOperator(func=addMutantsFrom, param=(extMutantFile, regions, logger)), ], at = addMutantsAt), # revert alleles at fixed loci to wildtype MutSpaceRevertFixedSites(), # mutate in a region at rate mu, if verbose > 2, save mutation events to a file MutSpaceMutator(mu, ranges, {'finite_sites':1, 'infinite_sites':2}[mutationModel], output='' if verbose < 2 else '>>mutations.lst'), # selection on all loci mySelector, # output statistics in verbose mode sim.IfElse(verbose > 0, ifOps=[ sim.Stat(popSize=True, meanOfInfo='fitness', minOfInfo='fitness'), NumSegregationSites(), sim.PyEval(r'"%5d %s %5d %.6f %.6f %.6f %.6f\n" ' '% (gen, subPopSize, numSites, avgSites, avgFreq*100, meanOfInfo["fitness"], minOfInfo["fitness"])', output='>>' + statFile), ], at = progGen ), sim.IfElse(len(splitTo) > 1, sim.Migrator(rate=migrIslandRates(migrRate, len(splitTo)), begin=splitAt + 1) ), ], matingScheme=sim.RandomMating(ops=MutSpaceRecombinator(recRate, ranges), subPopSize=multiStageDemoFunc(N, G, splitTo, splitAt)), postOps = [ sim.NoneOp() if postHook is None else sim.PyOperator(func=postHook), sim.SavePopulation(popFile[0], at=popFile[1]), ], finalOps=[ # revert fixed sites so that the final population does not have fixed sites MutSpaceRevertFixedSites(), sim.IfElse(verbose > 0, ifOps=[ # statistics after evolution sim.Stat(popSize=True), NumSegregationSites(), sim.PyEval(r'"%5d %s %5d %.6f %.6f %.6f %.6f\n" ' '% (gen+1, subPopSize, numSites, avgSites, avgFreq*100, meanOfInfo["fitness"], minOfInfo["fitness"])', output='>>' + statFile), sim.PyEval(r'"Simulated population has %d individuals, %d segregation sites.' r'There are on average %.1f sites per individual. Mean allele frequency is %.4f%%.\n"' r'% (popSize, numSites, avgSites, avgFreq*100)'), ]), ], gen = Gens[-1] ) # record selection coefficients to population if len(collector.selCoef) == 0: # this must be the neutral case where a NonOp has been used. pop.dvars().selCoef = 0 else: pop.dvars().selCoef = collector.selCoef # re-save the file with the added selCoef if popFile[-1] == -1: pop.save(popFile[0]) # if logger: logger.info('Population simulation takes %.2f seconds' % (time.clock() - startTime)) if markerFile or genotypeFile: if logger: logger.info('Saving marker information to file %s' % markerFile) mutants = saveMarkerInfoToFile(pop, markerFile, logger) if genotypeFile: if logger: logger.info('Saving genotype in .ped format to file %s' % genotypeFile) saveGenotypeToFile(pop, genotypeFile, mutants, logger) if mutantFile: if logger: logger.info('Saving mutants to file %s' % mutantFile) saveMutantsToFile(pop, mutantFile, logger=logger) return pop
def evolvePop(model, N0, N1, G0, G1, initSpec, mu, k, fitness, m=1, migrRate=0, logfile='', sp_logfile='', **kwargs): '''Evolve a population with specified allele frequencies (parameter initSpec) using given demographic (model, N0, N1, G0, G1, m), mutation (a k-allele model with parameters mu and k) and natural selection models (a multi-locus selection model with fitness vector s). Total disease allele frequency and effective number of alleles in the population and in all subpopulations are recorded if names of log files are provided. This function returns a tuple of these two statistics at the end of the evolution. Additional keyword arguments could be used to control when and how often statisitcs are outputed. ''' L = len(fitness) // 3 if not hasattr(mu, '__iter__'): # if a single mutation rate is given mu = [mu] * L # Create expressions to output f_e and ne at all loci, which are # "%d\t%.4f\t%.4f\n" % (gen, 1-alleleFreq[x][0], ne[x]) # for locus x. statExpr = '"%d' + r'\t%.4f\t%.4f'*L + r'\n" % (gen,' + \ ', '.join(['1-alleleFreq[%d][0], ne[%d]' % (x, x) for x in range(L)]) + ')' demo_func = demoModel(model, N0, N1, G0, G1, m) pop = sim.Population(size=demo_func(0), loci=[1] * L, infoFields=['fitness', 'migrate_to']) pop.evolve( initOps=[sim.InitSex(), sim.InitGenotype(freq=initSpec)], preOps=[ sim.KAlleleMutator(k=k, rates=mu, loci=range(L)), sim.MlSelector([ sim.MaSelector(loci=i, fitness=fitness[3 * i:3 * (i + 1)]) for i in range(L) ], mode=sim.MULTIPLICATIVE), sim.Migrator(rate=migrIslandRates(migrRate, m), begin=G0 + 1), ], matingScheme=sim.RandomMating(subPopSize=demo_func), postOps=[ sim.IfElse( logfile != '' or sp_logfile != '', Ne(loci=sim.ALL_AVAIL, vars=['ne'] if m == 1 else ['ne', 'ne_sp']), **kwargs), sim.IfElse(logfile != '', sim.PyEval(statExpr, output='>>' + logfile), **kwargs), sim.IfElse( m > 1 and sp_logfile != '', sim.PyEval( statExpr, output='>>' + sp_logfile, # subPops=sim.ALL_AVAIL will evalulate the expression in each # subpopulation's local namespace (vars(sp)). subPops=sim.ALL_AVAIL, begin=G0), **kwargs), ], finalOps=Ne(loci=sim.ALL_AVAIL), gen=G0 + G1) return tuple([1-pop.dvars().alleleFreq[x][0] for x in range(L)] + \ [pop.dvars().ne[x] for x in range(L)])
# import simuPOP as sim # redirect system stderr import sys debugOutput = open('debug.txt', 'w') old_stderr = sys.stderr sys.stderr = debugOutput # start simulation simu = sim.Simulator(sim.Population(100, loci=1), rep=5) simu.evolve( initOps=[sim.InitSex(), sim.InitGenotype(freq=[0.1, 0.9])], matingScheme=sim.RandomMating(), postOps=[ sim.Stat(alleleFreq=0), sim.IfElse( 'alleleNum[0][0] == 0', ifOps=[ # the is None part makes the function return True sim.PyOperator(lambda: sim.turnOnDebug("DBG_MUTATOR") is None), sim.PointMutator(loci=0, allele=0, inds=0), ], elseOps=sim.PyOperator( lambda: sim.turnOffDebug("DBG_MUTATOR") is None)), ], gen=100) # replace standard stdandard error sys.stderr = old_stderr debugOutput.close() print(''.join(open('debug.txt').readlines()[:5]))
def MutationSelection(N=1000, generations=10000, X_loci=100, A_loci=0, AgingModel='two_phases', seed=2001, reps=1, InitMutFreq=0.001, aging_a1=0.003, aging_a2=0.05, aging_b=-0.019, aging_k=0.1911, MutRate=0.001, StatsStep=100, OutPopPrefix='z1', PrintFreqs=False, debug=False): '''Creates and evolves a population to reach mutation-selection balance.''' if debug: sim.turnOnDebug('DBG_ALL') else: sim.turnOffDebug('DBG_ALL') sim.setRNG('mt19937', seed) pop = sim.Population(N, loci=[X_loci, A_loci], ploidy=2, chromTypes=[sim.CHROMOSOME_X, sim.AUTOSOME], infoFields=[ 'age', 'a', 'b', 'smurf', 'ind_id', 'father_id', 'mother_id', 'luck', 't0', 'fitness' ]) pop.setVirtualSplitter( sim.CombinedSplitter( splitters=[ sim.ProductSplitter(splitters=[ sim.InfoSplitter(field='age', cutoff=9), sim.InfoSplitter(field='smurf', values=[0, 1]) ]), sim.SexSplitter(), sim.InfoSplitter(field='age', values=0) ], vspMap=[(0), (2), (1, 3), (4), (5), (6)], names=['larvae', 'adults', 'smurfs', 'males', 'females', 'zero'])) pop.dvars().k = aging_k pop.dvars().N = N pop.dvars().seed = seed pop.dvars().X_loci = X_loci pop.dvars().A_loci = A_loci pop.dvars().AgingModel = AgingModel exec("import random\nrandom.seed(seed)", pop.vars(), pop.vars()) exec("import math", pop.vars(), pop.vars()) simu = sim.Simulator(pop, rep=reps) simu.evolve( initOps=[ sim.InitSex(), sim.InitGenotype(freq=[1 - InitMutFreq, InitMutFreq]), sim.InitInfo([0], infoFields='age'), sim.InitInfo([aging_a1], infoFields='a'), sim.InitInfo([aging_b], infoFields='b'), sim.InitInfo(lambda: random.random(), infoFields='luck'), sim.InfoExec('t0 = -ind.b / ind.a', exposeInd='ind'), sim.InfoExec( 'smurf = 1.0 if AgingModel == "two_phases" and (ind.smurf == 1 or (ind.age > ind.t0 and ind.luck < 1.0 - math.exp(-ind.a * ind.age + ind.a * ind.t0 - ind.a / 2.0))) else 0.0', exposeInd='ind'), sim.IdTagger(), sim.PyExec('XFreqChange={}'), sim.PyExec('AFreqChange={}') ], preOps=[ sim.InfoExec('luck = random.random()'), sim.InfoExec( 'smurf = 1.0 if AgingModel == "two_phases" and (ind.smurf == 1 or (ind.age > ind.t0 and ind.luck < 1.0 - math.exp(-ind.a * ind.age + ind.a * ind.t0 - ind.a / 2.0))) else 0.0', exposeInd='ind'), sim.DiscardIf(natural_death(AgingModel)), sim.InfoExec('age += 1'), sim.PySelector(func=fitness_func1) ], matingScheme=sim.HeteroMating([ sim.CloneMating(subPops=[(0, 0), (0, 1), (0, 2)], weight=-1), sim.RandomMating(ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.InfoExec('smurf = 0.0'), sexSpecificRecombinator( rates=[0.75 / X_loci for x in range(X_loci)] + [2.07 / A_loci for x in range(A_loci)], maleRates=0.0), sim.PyQuanTrait(loci=sim.ALL_AVAIL, func=TweakAdditiveRecessive( aging_a1, aging_a2, aging_b, X_loci), infoFields=['a', 'b']) ], weight=1, subPops=[(0, 1)], numOffspring=1) ], subPopSize=demo), postOps=[ sim.SNPMutator(u=MutRate, subPops=[(0, 5)]), sim.Stat(alleleFreq=sim.ALL_AVAIL, step=StatsStep), sim.IfElse( 'X_loci > 0', ifOps=[ sim.PyExec( 'XFreqChange[gen] = [alleleFreq[x][1] for x in range(X_loci)]' ) ], elseOps=[sim.PyExec('XFreqChange[gen] = []')], step=StatsStep), sim.IfElse( 'A_loci > 0', ifOps=[ sim.PyExec( 'AFreqChange[gen] = [alleleFreq[a][1] for a in range(X_loci, pop.totNumLoci())]', exposePop='pop') ], elseOps=[sim.PyExec('AFreqChange[gen] = []')], step=StatsStep), sim.IfElse( PrintFreqs, ifOps=[ sim.PyEval( r"str(rep) + '\t' + str(gen) + '\t' + '\t'.join(map('{0:.4f}'.format, XFreqChange[gen])) + '\t\t' + '\t'.join(map('{0:.4f}'.format, AFreqChange[gen])) + '\n'" ) ], step=StatsStep), sim.TerminateIf( 'sum([alleleFreq[x][0] * alleleFreq[x][1] for x in range(X_loci + A_loci)]) == 0' ) ], gen=generations) i = 0 for pop in simu.populations(): pop.save('{}_{}.pop'.format(OutPopPrefix, i)) i += 1