def recParent( self, pop, off, parent, ploidy ): nEvents = sim.getRNG().randPoisson( self.rate ) srcIdx = sim.getRNG().randInt( 2 ) if nEvents == 0: self.copier.copyChromosomes(parent, srcIdx , off, ploidy) else: seen = set() while len(seen) < nEvents: seen.add( sim.getRNG().randInt( self.chromLen ) ) breaks = list(seen) parent_ploidy = [ ((srcIdx + i) % 2) for i in range( nEvents + 1) ] lociIdx=0 for (x,y,z) in izip(parent.genotype(0), parent.genotype(1), pop.individual(0, pop.subPopByName( 'metadata' )).genotype(0)): if x == y or parent_ploidy[ bisect(breaks,z) ] == 0: off.setAllele( x, lociIdx, ploidy=ploidy) else: off.setAllele( y, lociIdx, ploidy=ploidy) lociIdx += 1 if lociIdx >= pop.dvars().max_locus: break return True
def func(): if sim.getRNG().randUniform() < selCoef[0]: return selCoef[1], selCoef[4] while True: s = sim.getRNG().randGamma(selCoef[2], selCoef[3]) if s > selCoef[5] and s < selCoef[6]: return s, selCoef[4]
def _newS(self, loc, alleles): if self.p > 0 and sim.getRNG().randUniform() < self.p: return self.a while True: s = sim.getRNG().randGamma(self.k, self.theta) if s >= self.lower and s <= self.upper: return s, self.h
def recParent( self, pop, off, parent, ploidy ): nEvents = sim.getRNG().randPoisson( self.rate ) srcIdx = sim.getRNG().randInt( 2 ) self.copier.copyChromosomes(parent, srcIdx , off, ploidy) if nEvents != 0: seen = set() while len(seen) < nEvents: seen.add( sim.getRNG().randInt( self.chromLen ) ) breaks = list(seen) parent_ploidy = [ ((srcIdx + i) % 2) for i in range( nEvents + 1) ] # This loop iterates over all possible loci which have a variable allele # The list of loci padded to be larger than the expected number of loci (segregation sites) # In effect, we iterate over a longer list than is actually necessary # Therefore, we slice off the portion of the list after the last locus to have a non-zero allele # Although, the benefit of this 'early breaking' may be limited, if the number of segregations # sites approaches the padded size # It may be more efficient, in general, to simply assume that the padding will always be 'small' # (ie. we have chosen the padding size such that it only increases the amount of work by a small # amount) # Therefore iterating over the padded portion, although unnecessary, is more efficient because # it removes any additional conditional checking performed to determine 'early break' case for lociIdx,(x,y,z) in enumerate(islice(izip(parent.genotype((srcIdx % 2)), parent.genotype((srcIdx + 1) % 2), pop.dvars().variable_sites), 0, pop.dvars().max_locus)): # skip locus if the locus is free (z == 0) or parent is homozygous at locus (x == y) if z == 0 or x == y: continue # if the allele falls within a recombination region not from the source chromosome if parent_ploidy[ bisect(breaks,z) ] != srcIdx: off.setAllele( y, lociIdx, ploidy=ploidy) return True
def myParentChooser(pop, subPop): psize = pop.subPopSize(subPop) while True: rank1 = sim.getRNG().randInt(psize) rank2 = sim.getRNG().randInt(psize) while rank2 == rank1: rank2 = sim.getRNG().randInt(psize) yield pop.individual(rank1, subPop), pop.individual(rank2, subPop)
def _newS(self): if self.p > 0 and sim.getRNG().randUniform() < self.p: return self.a s = sim.getRNG().randGamma(self.k, self.theta) if s >= self.lower and s <= self.upper: return s elif s < self.lower: return self.lower, self.h else: return self.upper, self.h
def mutate(self, pop): """Add mutations to organisms.""" rng = simu.getRNG() dvars = pop.dvars() rep = dvars.rep gen = dvars.gen - burnin for ind in pop.individuals(): for locus in range(loci): for ploidy in range(2): if rng.randUniform() < m_rate[locus]: try: idx = self.available[rep][locus].pop() except IndexError: if self.reclaim(pop, rep, locus): idx = self.available[rep][locus].pop() else: sys.stderr.write( '[ERROR] rep={}, gen={}: available sites exhausted.\n'. format(rep, gen - burnin)) return False # A site is represented by 1 bit. An # ancestral state is always represented by # 0, and mutated state is therefore always # 1. ind.setAllele(1, idx, ploidy=ploidy) return True
def mutate(self, pop): """Add mutations to organisms.""" rng = simu.getRNG() dvars = pop.dvars() rep = dvars.rep gen = dvars.gen - burnin for ind in pop.individuals(): for locus in range(loci): for ploidy in range(2): if rng.randUniform() < m_rate[locus]: try: idx = self.available[rep][locus].pop() except IndexError: if self.reclaim(pop, rep, locus): idx = self.available[rep][locus].pop() else: sys.stderr.write( '[ERROR] rep={}, gen={}: available sites exhausted.\n' .format(rep, gen - burnin)) return False # A site is represented by 1 bit. An # ancestral state is always represented by # 0, and mutated state is therefore always # 1. ind.setAllele(1, idx, ploidy=ploidy) return True
def trait(geno): ''' Define a quantitative trait model. geno is the genotype of each individual passed by pyQuanTrait. Note that this population is in mutational space so geno is the location instead of value of mutants. 0 values should be ignored. ''' # get number of mutants count = len(geno) - geno.count(0) # N(count, 1) using simuPOP's random number generator. return sim.getRNG().randNormal(count, 1)
def myDist(loc): '''Define a function that return fitness parameter of newly arising mutants. ''' if loc % 3 != 2: # h = 0.5 for an additive model return sim.getRNG().randGamma(0.184, 0.160), 0.5 else: # the last nucleotide of a condo is not selected return 0
def __init__(self, rate, *args, **kwargs): """Initialize Mutator object. Arguments: rate: mutation rates. All loci share the same rate. *args, **kwargs: pass to PyOperator. """ self._rate = rate self._unif = sim.getRNG().randUniform sim.PyOperator.__init__(self, func = self.mutate, *args, **kwargs)
def myDist(): '''Define a function that return fitness parameter of newly arising mutants. ''' rng = sim.getRNG() # positive selection if rng.randUniform() < 0.2: return -rng.randUniform() / 1000. # purifying selection else: return rng.randGamma(0.184, 0.160)
def infSitesMutate(pop, param): (startPos, endPos, rate) = param # determine the number of mutation events occurring in this generation nEvents = sim.getRNG().randPoisson( rate ) # print "Generating %d mutation events" % nEvents max_size = pop.popSize() if len( pop.dvars().variable_sites ) == 0: pop.dvars().variable_sites = [0] * pop.totNumLoci() lociset=set( pop.dvars().variable_sites ) while nEvents > 0: nEvents -= 1 # select an individual at random next_avail_idx = 0 try: next_avail_idx = pop.dvars().variable_sites.index(0) except ValueError: print('Insufficient loci allocated %d; %d; %d' % (pop.totNumLoci(), pop.ancestralGens(), nEvents) ) raise offset = sim.getRNG().randInt( max_size ) # randInt range: [0, max_size) indIdx = offset / pop.ploidy() pIdx= offset % pop.ploidy() loc = sim.getRNG().randInt( endPos ) + 1 # generate the location of a mutation event; range: [1, endPos] while loc in lociset: # generate a new location if mutation at location already mutated in population loc = sim.getRNG().randInt( endPos ) + 1 pop.individual( indIdx ).setAllele( 1, next_avail_idx, ploidy=pIdx ) # variable_sites serves a dual purpose # 1) it is a list of the genetic positions which have mutant alleles within the population # 2) those indices which are '0' in the list amount to 'free' loci within the population which can # be used for new alleles pop.dvars().variable_sites[ next_avail_idx ] = loc lociset.add(loc) return True
def infSitesMutate(pop, param): (startPos, endPos, rate) = param # determine the number of mutation events occurring in this generation nEvents = sim.getRNG().randPoisson( rate ) # print "Generating %d mutation events" % nEvents main_pop_idx = pop.subPopByName( "pop" ) sites_ind = pop.individual( 0, pop.subPopByName( "metadata" ) ) max_size = pop.subPopSize( main_pop_idx ) * pop.ploidy() lociset=set(sites_ind.genotype(0)) while nEvents > 0: nEvents -= 1 # select an individual at random next_avail_idx = 0 try: next_avail_idx = sites_ind.genotype(0).index(0) except ValueError: print('Insufficient loci allocated %d; %d; %d' % (pop.totNumLoci(), pop.ancestralGens(), nEvents) ) raise offset = sim.getRNG().randInt( max_size ) # randInt range: [0, max_size) indIdx = offset / pop.ploidy() pIdx= offset % pop.ploidy() loc = sim.getRNG().randInt( endPos ) + 1 # generate the location of a mutation event; range: [1, endPos] while loc in lociset: # generate a new location if mutation at location already mutated in population loc = sim.getRNG().randInt( endPos ) + 1 pop.individual( indIdx, main_pop_idx ).setAllele( 1, next_avail_idx, ploidy=pIdx ) sites_ind.setAllele( loc, next_avail_idx, ploidy=0) # use metadata population individual as a 'free list' tracker lociset.add(loc) if( next_avail_idx >= pop.dvars().max_locus ): pop.dvars().max_locus = next_avail_idx + 1 return True
def expandPop(logger): # Evolve the population to a population of 50,000 individuals, without a disease model. # # > simuGWAS.py --initPop=ex1_init.pop --DPL=[] --filename=ex1_expanded_1.pop --scale=1 --optimized --dumpRec=rec.log --haploCount='(0,100)' # > simuGWAS.py --initPop=ex1_init.pop --DPL=[] --expandSize=25000 --filename=ex1_expanded_2.pop --scale=2 --optimized --dumpRec=rec2.log --haploCount='(0,100)' # > simuGWAS.py --initPop=ex1_init.pop --DPL=[] --expandSize=10000 --filename=ex1_expanded_5.pop --scale=5 --optimized --dumpRec=rec5.log --haploCount='(0,100)' # > simuGWAS.py --initPop=ex1_init.pop --DPL=[] --expandSize=50000 --filename=ex1_expanded_55.pop --scale=5 --optimized --dumpRec=rec55.log --haploCount='(0,100)' # from simuPOP import getRNG getRNG().set(seed=1355) # for scale, popSize, name in [(1, 50000, '1'), (2, 25000, '2'), (5, 10000, '5'), (5, 50000, '55')]: filename = 'ex1_expanded_%s.pop' % name if os.path.isfile(filename): if logger: logger.info( '%s already exists. Please remove this file if you would like to regenerate an expanded population.' % filename) continue else: if logger: logger.info( 'Simulating an expanded population with scaling factor %d and ending population size %d' % (scale, popSize)) pop = loadPopulation('ex1_init.pop') pars = simuOpt.Params(simuGWAS.options, migrRate=0.0001, scale=scale, DPL=[], expandSize=popSize, dumpRec='rec%d.log' % scale, haploCount=(0, 100)) pop = simuGWAS.simuGWAS(pars, pop, logger=logger) if logger: logger.info('Saving expanded population to %s' % filename) pop.save(filename)
def mutate(self, pop): """Add mutations to organisms.""" rng = simu.getRNG() dvars = pop.dvars() rep = dvars.rep gen = dvars.gen - burnin for i, ind in enumerate(pop.individuals()): for locus in range(loci): for ploidy in range(2): if rng.randUniform() < m_rate[locus]: ind.setAllele(self.idx[rep][locus], locus, ploidy=ploidy) self.idx[rep][locus] += 1 return True
def simuAssortativeMatingWithFitness(constant_pop_size, a, aa_fitness, aa_homogamy, deafness_freq, generations): ''' Accepts: constant_pop_size population size, which remains constant throughout. a starting frequency of the a allele. aa_fitness _relative_ fitness of deaf (aa) individuals. aa_homogamy the percent of assortative mating between deaf individuals. deafness_freq overall frequency of deaf individuals at the time of reproductive age, including from causes other than connexin 26. generations number of generations. Returns a dict containing the results from each gen of the simulation: gen generation number. A frequency of the A allele. a frequency of the a allele. AA frequency of AA individuals. Aa frequency of Aa individuals. aa frequency of aa individuals. AA_size size of the AA subpopulation. Aa_size size of the Aa subpopulation. aa_size size of the aa subpopulation. F calculated inbreeding coefficient. num_deaf size of the deaf subpopulation (incl adventitious). homogamy calculated actual homogamy. Adopted from: http://simupop.sourceforge.net/Cookbook/AssortativeMating ''' sim.setRNG(random.seed(sim.getRNG().seed())) pop = sim.Population(constant_pop_size*1000, loci=[1]) pop.dvars().constant_pop_size = constant_pop_size pop.dvars().a = a pop.dvars().aa_fitness = aa_fitness pop.dvars().aa_homogamy = aa_homogamy pop.dvars().deafness_freq = deafness_freq pop.dvars().generations = generations pop.dvars().headers = [] pop.dvars().row = [] pop.evolve( initOps= [sim.InitSex(), # Assigns individuals randomly to be male or female. # This can result in slightly more males or females, # which can cause errors if the wrong mating scheme is # selected. sim.InitGenotype(freq=[1-a, a]) ], matingScheme = sim.HomoMating( chooser = sim.PyParentsChooser(customChooser), generator = sim.OffspringGenerator(sim.MendelianGenoTransmitter())), postOps = [sim.Stat(alleleFreq=[0], genoFreq=[0]), sim.PyExec(r"headers += ['gen','A', 'a',"\ "'AA', 'Aa', 'aa',"\ "'AA_size', 'Aa_size', 'aa_size',"\ "'F', 'nm_deaf', 'homogmy']"), sim.PyExec(r"F = 1.0-((genoFreq[0][(0,1)]+genoFreq[0][(1,0)])/" # F \ "(2.0*alleleFreq[0][0]*alleleFreq[0][1]))"\ "if alleleFreq[0][0] != 0.0 and alleleFreq[0][1]"\ "!= 0.0 else 0.0"), sim.PyExec(r"row += [gen, "\ "alleleFreq[0][0]," # A \ "alleleFreq[0][1]," # a \ "genoFreq[0][(0,0)]," # AA \ "genoFreq[0][(0,1)]+genoFreq[0][(1,0)]," # Aa \ "genoFreq[0][(1,1)]," # aa \ "genoNum[0][(0,0)]," # AA_size \ "genoNum[0][(0,1)]+genoNum[0][(1,0)]," # Aa_size \ "genoNum[0][(1,1)]," # aa_size \ "F if F>0.0 else 0.0," # F \ "num_deaf," # nm_deaf \ "homogamy]") # homogmy ], gen = generations ) return {'headers':pop.dvars().headers, 'row':pop.dvars().row}
def simuAssortativeMatingWithFitness(e): ''' Accepts: e an Experiment object. Returns a dict containing the results from each gen of the simulation: gen generation number. A frequency of the A allele. a frequency of the a allele. AA frequency of AA individuals. Aa frequency of Aa individuals. aa frequency of aa individuals. deaf frequency of deaf individuals (incl adventitious). AA_size size of the AA subpopulation. Aa_size size of the Aa subpopulation. aa_size size of the aa subpopulation. deaf_size size of the deaf subpopulation (incl adventitious). homogamy calculated actual homogamy. F calculated inbreeding coefficient. Adopted from: http://simupop.sourceforge.net/Cookbook/AssortativeMating ''' sim.setRNG(random.seed(sim.getRNG().seed())) pop = sim.Population(e.constant_pop_size * 1000, loci=[1]) # These variables need to be set in order to be available to customChooser(). # There appears to be no way to directly pass variables to customChooser(). pop.dvars().constant_pop_size = e.constant_pop_size pop.dvars().a = e.a pop.dvars().aa_fitness = e.aa_fitness pop.dvars().aa_homogamy = e.aa_homogamy pop.dvars().deaf = e.deaf pop.dvars().adv_deaf_target = int( round((e.deaf - e.a**2) * e.constant_pop_size * 1000)) # These will hold the final data pop.dvars().headers = [] pop.dvars().row = [] pop.evolve( initOps= [sim.InitGenotype(freq=[1-e.a, e.a])], matingScheme = sim.HomoMating( chooser = sim.PyParentsChooser(customChooser), generator = sim.OffspringGenerator(sim.MendelianGenoTransmitter())), postOps = [sim.Stat(alleleFreq=[0], genoFreq=[0]), sim.PyExec(r"headers += ['gen','A', 'a',"\ "'AA', 'Aa', 'aa', 'deaf', 'AA_size', 'Aa_size', " \ "'aa_size', 'deaf_size', 'homogamy', 'F'] \n" \ "F = 1.0-((genoFreq[0][(0,1)]+genoFreq[0][(1,0)])/" # F \ "(2.0*alleleFreq[0][0]*alleleFreq[0][1])) "\ "if alleleFreq[0][0]*alleleFreq[0][1] > 0. "\ "else 0. \n" \ "deaf_size = min(genoNum[0][(1,1)] + adv_deaf_target, constant_pop_size*1000) \n"\ "row += [gen, " # generation \ "alleleFreq[0][0], " # A \ "alleleFreq[0][1], " # a \ "genoFreq[0][(0,0)]," # AA \ "genoFreq[0][(0,1)]+genoFreq[0][(1,0)], " # Aa \ "genoFreq[0][(1,1)], " # aa \ "deaf_size/(constant_pop_size*1000.), " # deaf \ "genoNum[0][(0,0)], " # AA_size \ "genoNum[0][(0,1)]+genoNum[0][(1,0)], " # Aa_size \ "genoNum[0][(1,1)], " # aa_size \ "deaf_size, " # deaf_size \ "homogamy, " # homogamy \ "F if F>0. else 0.]") # F \ ], gen = e.generations ) return {'headers': pop.dvars().headers, 'row': pop.dvars().row}
def run(args): """Run simulations with appropriate parameters. Arguments: args: Namespace object generated by argparse. """ # Set model parameters factors = args.factor if factors is not None: factors.sort() pop_sizes = args.pop_sizes init_genealogies(sum(pop_sizes), [AUTOSOME, CHROMOSOME_X, CHROMOSOME_Y, MITOCHONDRIA]) if factors is not None: # Neutral markers without incompatibility factors. len_factors = len(factors) if args.female_recombination is None or args.male_recombination is None: raise SizeError(len_factors, 0) else: female_recomb_rate = args.female_recombination male_recomb_rate = args.male_recombination if len(female_recomb_rate) != len_factors: raise SizeError(len_factors, len(female_recomb_rate)) if len(male_recomb_rate) != len_factors: raise SizeError(len_factors, len(male_recomb_rate)) female_mig_rates = args.female_migration male_mig_rates = args.male_migration sex_ratio = args.sex_ratio if args.male_selection is None: female_sel = None male_sel = None else: female_sel = args.female_selection male_sel = args.male_selection if len_factors != len(female_sel): raise SizeError(len_factors, len(female_sel)) if len_factors != len(male_sel): raise SizeError(len_factors, len(male_sel)) # Define basic mode of genetic transmission as the standard # diploid model. matingOps = [sim.MendelianGenoTransmitter(), sim.MitochondrialGenoTransmitter(chroms = 3)] # Define locations and rates of recombination. Recombination only # occurs between a neutral marker locus and an incompatibility # factor. In other words, there is no intro-locus recombination. # Moreover, choromosome Y and mitochondria do not recombine. for c in [AUTOSOME, CHROMOSOME_X]: if factors is not None and c in factors: index = factors.index(c) matingOps.append( sim.Recombinator(rates = male_recomb_rate[index], # No neutral mutation to consider loci = 0, subPops = [(0, 0), (1, 0)]) ) matingOps.append( sim.Recombinator(rates = female_recomb_rate[index], # No neutral mutation to consider loci = 0, subPops =[(0, 1), (1, 1)]) ) # Specify sex-ratio of offsprings. Because the sequence, from # which sex of offspring is determined, is ordered such that first # all males offspring then all female offspring, it is important # to realize that the correct sex-ratio is only achieved when # local population size is multple of the sequence. if sex_ratio == 50: sex_mode = [sim.MALE, sim.FEMALE] elif not sex_ratio % 25: times = sex_ratio / 25 sex_mode = [sim.MALE] * times + [sim.FEMALE] * (4 - times) elif not sex_ratio % 20: times = sex_ratio / 20 sex_mode = [sim.MALE] * times + [sim.FEMALE] * (5 - times) elif not sex_ratio % 10: times = sex_ratio / 10 sex_mode = [sim.MALE] * times + [sim.FEMALE] * (10 - times) elif not sex_ratio % 5: times = sex_ratio / 5 sex_mode = [sim.MALE] * times + [sim.FEMALE] * (20 - times) elif not sex_ratio % 2: times = sex_ratio / 2 sex_mode = [sim.MALE] * times + [sim.FEMALE] * (50 - times) else: sex_mode = [sim.MALE] * sex_ratio + [sim.FEMALE] * (100 - sex_ratio) # Test if population size is multiple of the sequence of # offspring. If not, terminate the simulation as there is no way # to gurantee the correct sex-ratio. if False in [not p % len(sex_mode) for p in pop_sizes]: raise SizeError(p, len(sex_mode)) sex_mode = tuple([sim.GLOBAL_SEQUENCE_OF_SEX] + sex_mode) # If seed is given, we perform only as much number of runs as the # number of supplied seed. This is intended to generate # reproducible results. # A variable indicating if seed is supplied via command line seed_provided = False if args.seed is not None: reps = args.seed seed_provided = True else: reps = range(args.reps) print('Pop Size: 0|{} 1|{}, Sex Ratio: F|{} M|{}'.format( pop_sizes[0], pop_sizes[1], 100 - sex_ratio, sex_ratio), end = '') print(', Mig Rate: F.M12|{} F.M21|{} M.M12|{} M.21|{}'.format( female_mig_rates[0], female_mig_rates[1], male_mig_rates[0], male_mig_rates[1]), end = '') if factors is not None: print(', Factors: {}, Sel Coeff: F|{} M|{}'.format( factors, female_sel, male_sel), end = '') print(', Recomb Rate: F|{} M|{}'.format( female_recomb_rate, male_recomb_rate)) else: print('') # Let simulation run! for r in reps: # Define population and genetic structure. pop = sim.Population(size = pop_sizes, # 1st locus is the tag to identify which # (ultimate) parent the 2nd locus was # descendent from. # The second locus is the actual locus. # loci = [2] * 4, # Right now, in order to speed up # simulations, mutations are not invoked # during simulation. loci = [1] * 4, # lociNames = ['marker.a', 'marker.a_', # 'marker.X', 'marker.X_', # 'marker.Y', 'marker.Y_', # 'marker.mt', 'marker.mt_'] chromTypes=[sim.AUTOSOME, sim.CHROMOSOME_X, sim.CHROMOSOME_Y, sim.CUSTOMIZED], infoFields = ['migrate_to', 'fitness']) # Add incompatibility factors on appropriate chromosomes. # Placing more than one factors on one chromosome is currently # not supported. if factors is not None: factor_pos = [2] * len(factors) for f in factors: # pop.addLoci(chrom = f, pos = 3) # neutral loci are at position 1. pop.addLoci(chrom = f, pos = 2) sel = SelectorProvider(pop, factors, factor_pos, female_sel, male_sel) # Sex-specific processes (selection and migration) require # setting up virtual populations based-on sex. pop.setVirtualSplitter(sim.SexSplitter()) # Set up simulator s = sim.Simulator(pop) if seed_provided: seed = r else: seed = sim.getRNG().randInt(2**31) sim.getRNG().set(name = 'mt19937', seed = seed) preOps = [sim.Migrator(rate = [[0, male_mig_rates[0]], [male_mig_rates[1], 0]], mode = sim.BY_PROBABILITY, subPops = [(0, 0), (1, 0)]), sim.Migrator(rate = [[0, female_mig_rates[0]], [female_mig_rates[1], 0]], mode = sim.BY_PROBABILITY, subPops = [(0, 1), (1, 1)])] if 'sel' in locals(): preOps += sel.setSelector() print("<<{}>>".format(sim.getRNG().seed())) s.evolve( initOps = [sim.InitSex(sex = [sim.MALE, sim.FEMALE], subPops = 0), sim.InitSex(sex = [sim.MALE, sim.FEMALE], subPops = 1), InitGenotype(factors = factors, mutation = False)], preOps = preOps, matingScheme = sim.RandomMating( ops = matingOps, subPopSize = pop_sizes, sexMode = sex_mode), postOps = [ GenealogyTracker([0] * 4, [AUTOSOME, CHROMOSOME_X, CHROMOSOME_Y, MITOCHONDRIA]), InitGenotype(factors = factors, mutation = False), ])
def random_shuffle(x): random.shuffle(x, getRNG().randUniform)
def extractRandomSeed(): # Define a function to print the random seed for the simulation seed = simuPOP.getRNG().seed() #random.seed(seed) return(seed)
""" Roger W. Doyle Two small subpopulations go through an acute bottleneck and other changes in census number. Pedigrees of all individuals are saved along with their generations, subpopulation membership and genotypes. (gen_id and sp_id are generation and subpopulation, respectively.) """ from simuPOP import * import simuPOP as sim gen_evolve = 20 #gens of evolution and retention #sim.setRNG(seed=12481632) #useful for repeating a simulation run seed_used = sim.getRNG().seed() print '\nThe random seed used in the simulation was', seed_used, '\n' def censuscontrol(gen): if gen >= 10 and gen < 13: return [10, 20] elif gen >= 13 and gen < 15: return [20, 40] elif gen == 15: return [22, 44] else: return [30, 60] pop = sim.Population( size=[8, 16], ploidy=2, loci=[0, 1, 2],
def _newS(self, loc, alleles): return sim.getRNG().randGamma(self.k, self.theta)