def generate_f_one(self, parental_id_pairs, offspring_per_pair): """ Crosses pairs of founders as they are listed in founder indices. using breed.PairwiseIDChooser :note: Data is specified as pairs. Testing for even-number unnecessary. """ founder_chooser = PairwiseIDChooser(parental_id_pairs, offspring_per_pair) number_of_pairs = len(parental_id_pairs) self.pop.evolve( preOps=[ # sim.PyEval(r'"Generation: %d\n" % gen',), ], matingScheme=sim.HomoMating( sim.PyParentsChooser(founder_chooser.by_id_pairs), sim.OffspringGenerator(ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=self.recombination_rates) ], numOffspring=1), subPopSize=[offspring_per_pair * number_of_pairs], ), gen=1, )
def createAge(pop): ageInitOps = [ # InitInfo(lambda: random.randint(0, cfg.ages-2), infoFields='age'), sp.IdTagger(), # PyOperator(func=outputAge,at=[0]), sp.PyOperator(func=setAge, at=[0]), ] agePreOps = [ sp.InfoExec("age += 1"), sp.InfoExec("mate = -1"), sp.InfoExec("force_skip = 0"), sp.PyOperator(func=outputAge), ] mySubPops = [] for age in range(cfg.ages - 2): mySubPops.append((0, age + 1)) mateOp = sp.HeteroMating([ sp.HomoMating( sp.PyParentsChooser(fitnessGenerator if cfg.doNegBinom else (litterSkipGenerator if cfg.Nb is None else restrictedGenerator)), sp.OffspringGenerator(numOffspring=1, ops=[ sp.MendelianGenoTransmitter(), sp.IdTagger(), sp.PedigreeTagger()], sexMode=(sp.PROB_OF_MALES, cfg.maleProb)), weight=1), sp.CloneMating(subPops=mySubPops, weight=-1)], subPopSize=calcDemo) agePostOps = [ sp.PyOperator(func=outputMega), sp.PyOperator(func=cull), ] pop.setVirtualSplitter(sp.InfoSplitter(field='age', cutoff=list(range(1, cfg.ages)))) return ageInitOps, agePreOps, mateOp, agePostOps
def expand_by_selfing(self, pop, recombination_rates): """ Specific for plant populations capable of selfing. Creates an F2 subpopulations generation by selfing the individuals of 'pop'. Works on a population with one or more subpopulations. :param pop: """ # self.odd_to_even(pop) num_sub_pops = pop.numSubPop() progeny_per_individual = int(self.operating_population_size / 2) return pop.evolve( preOps=[ sim.MergeSubPops(), sim.PyEval(r'"Generation: %d\n" % gen'), sim.SplitSubPops(sizes=[1] * num_sub_pops, randomize=False), ], matingScheme=sim.SelfMating( subPopSize=[progeny_per_individual] * num_sub_pops, numOffspring=progeny_per_individual, ops=[ sim.Recombinator(rates=recombination_rates), sim.IdTagger(), sim.PedigreeTagger() ], ), gen=1, )
def replicate_tuson_drift_simulation(self, pop, meta_population, meta_sample_size, recombination_rates): for replicate in pop.populations(): replicate.dvars().gen = 0 female_chooser = sim.RandomParentChooser( selectionField='female_fitness') male_chooser = sim.RandomParentChooser(selectionField='male_fitness') print("Beginning simulation of genetic drift with parameters:") breeding_params = { 'n_breeding_females': self.number_of_breeding_females, 'n_breeding_males': self.number_of_breeding_males, 'sample_sizes': meta_sample_size} print("Breeding females: {n_breeding_females}, breeding males: " "{n_breeding_males}, " "sample sizes: {sample_sizes}".format(**breeding_params)) return pop.evolve( initOps=[ operators.ReplicateMetaPopulation(meta_population, meta_sample_size), sim.PyEval( r'"Initial: Sampled %d individuals from generation %d Replicate: %d.\n" % (ss, gen_sampled_from, rep)'), ], preOps=[ sim.PyEval(r'"Generation: %d\n" % gen'), sim.InfoExec('generation=gen'), operators.ReplicateMetaPopulation(meta_population, meta_sample_size, at=[2, 4, 6, 8]), # Evaluation specifying the generations should be the same as the evaluation at every generation. sim.PyEval( r'"Sampled %d individuals from generation %d from replicate: %d.\n" % (ss, gen_sampled_from, rep)', at=[2, 4, 6, 8]), operators.RandomlyAssignFemaleFitness( self.number_of_breeding_females), operators.RandomlyAssignMaleFitness( self.number_of_breeding_males), ], matingScheme=sim.HomoMating( sim.CombinedParentsChooser(female_chooser, male_chooser, allowSelfing=True), sim.OffspringGenerator(ops=[ sim.ParentsTagger(), sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=recombination_rates)], ), ), finalOps=[ sim.InfoExec('generation=gen'), operators.ReplicateMetaPopulation(meta_population, meta_sample_size), sim.PyEval( r'"Final: Sampled %d individuals from generation %d\n" % (ss, gen_sampled_from)') ], gen=self.number_of_generations)
def create_self_crosses(self, existing_pop, offspring_per_individual): new_pop_size = offspring_per_individual * existing_pop.popSize() existing_pop.evolve( matingScheme=sim.SelfMating( replacement=False, numOffspring=offspring_per_individual, subPopSize=new_pop_size, ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=0.01) ], ), gen=1, )
def random_mating(self, generations_of_random_mating, pop_size): """ Randomly mates 'pop' for 'gens_of_random_mating' generations to further recombine founder genomes and dissolve population structure. """ print("Initiating random mating for {} generations.".format( generations_of_random_mating)) self.pop.evolve( matingScheme=sim.RandomMating( subPopSize=pop_size, ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=self.recombination_rates) ]), gen=generations_of_random_mating, )
def drawSample(self, pop, penet, nFamilies): self.pop = pop.clone() self.pop.addInfoFields(['ind_id', 'father_id', 'mother_id']) self.pop.setAncestralDepth(1) sim.tagID(self.pop, reset=True) self.pop.evolve( preOps = penet, matingScheme=sim.RandomMating(ops=[ sim.MendelianGenoTransmitter(), # pass genotype sim.IdTagger(), # assign new ID to offspring sim.PedigreeTagger(), # record the parent of each offspring penet, # determine offspring affection status sim.DiscardIf(cond=self._discardTrio) ], subPopSize=nFamilies), gen = 1 ) return self.pop
def recombinatorial_convergence(self, pop, recombination_rates): """ Implements the MAGIC breeding scheme of breeding single individuals in pairs determined by the offspring of the initial population. The initial population is given by generate_f_one. :param pop: :type pop: :param recombination_rates: :type recombination_rates: :return: :rtype: """ while pop.numSubPop() > 1: new_parents = list(pop.indInfo('ind_id')) new_parent_id_pairs = [(pid, pid + 1) for pid in new_parents[::2]] if len(new_parent_id_pairs) % 2 != 0 and \ len(new_parent_id_pairs) != 1: new_parent_id_pairs.append(random.choice(new_parent_id_pairs)) new_os_size = len(new_parent_id_pairs) new_founder_chooser = breed.PairwiseIDChooser(new_parent_id_pairs) pop.evolve( preOps=[ sim.PyEval(r'"Generation: %d\t" % gen', ), sim.Stat(popSize=True, numOfMales=True), sim.PyEval(r'"popSize: %d\n" % popSize', ), ], matingScheme=sim.HomoMating( sim.PyParentsChooser(new_founder_chooser.by_id_pairs), sim.OffspringGenerator(ops=[ sim.IdTagger(), sim.ParentsTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=recombination_rates) ], numOffspring=1), subPopSize=new_os_size, ), gen=1, )
def expansion_through_random_mating(self, pop, expanded_pop_size, recombination_rates): # The purpose of this function is to use the simuPOP pre-defined mating scheme # RandomMating to grow the population to an arbitrary size. # Self-pollination occurs frequently in maize so we need use HermaphroditicMating # instead of RandomMating. return pop.evolve( initOps=sim.InitSex(), preOps=[ sim.PyEval(r'"Generation: %d\n" % gen'), sim.InfoExec('generation=gen'), ], matingScheme=sim.HermaphroditicMating( ops=[sim.Recombinator(rates=recombination_rates), sim.IdTagger(), sim.PedigreeTagger()], subPopSize=expanded_pop_size), gen=1)
def recombinatorial_convergence(self, multi_replicate_populations, number_sub_populations, offspring_per_pair): """ Breeds individuals from different sub-populations together until a single hybrid sub-population is created. :note:`number_sub_populations*offspring_per_pair should equal operating_population_size.` :note:`For the time being only works with powers of 2.` :param sim.Simulator multi_replicate_populations: :param int number_sub_populations: :param int offspring_per_pair: :return: """ print("Start of recombinatorial convergence.") while number_sub_populations > 1: mrc = MultiRandomCross(multi_replicate_populations, number_sub_populations, offspring_per_pair) mothers, fathers = mrc.determine_random_cross() multi_snd_order_chooser = MultiSecondOrderPairIDChooser( mothers, fathers) print("Prior to convergence: {}".format(number_sub_populations)) multi_replicate_populations.evolve( matingScheme=sim.HomoMating( sim.PyParentsChooser( multi_snd_order_chooser.snd_ord_id_pairs), sim.OffspringGenerator(ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=self.recombination_rates) ], numOffspring=1), subPopSize=[ int(number_sub_populations * offspring_per_pair) ]), gen=1, ) number_sub_populations = int(number_sub_populations / 2) offspring_per_pair = int(2 * offspring_per_pair) self._convergence = True
def _mate_and_merge(self, pop: sim.Population): starting_gen = pop.vars()['gen'] print("Initiating recombinatorial convergence at generation: %d" % pop.dvars().gen) while pop.numSubPop() > 1: pop.vars()['generations'][pop.vars()['gen']] = 'IG'+str(pop.vars()['gen'] - starting_gen) self.pop_halver(pop) self.odd_to_even(pop) self.pairwise_merge_protocol(pop) sub_pop_sizes = list(pop.subPopSizes()) pop.evolve( preOps=[ sim.MergeSubPops(), sim.PyEval(r'"Generation: %d\n" % gen'), operators.CalcTripletFreq(), sim.PyExec('triplet_freq[gen]=tripletFreq'), sim.SplitSubPops(sizes=sub_pop_sizes, randomize=False), ], matingScheme=sim.RandomMating(ops=[sim.Recombinator(rates=0.01), sim.IdTagger(), sim.PedigreeTagger()]), gen=1, )
def genAffectedSibpairSample(pop, nFamilies, penetrance): '''Draw nFamilies affected sibpairs and their parents by producing siblings from pop repeatedly until enough affected sibpairs are collected. A penetrance operator is needed to assign affection status to each offspring. ''' pop1 = pop.clone() pop1.setAncestralDepth(1) pop1.addInfoFields(['ind_id', 'father_id', 'mother_id']) pop1.evolve(initOps=sim.IdTagger(), matingScheme=sim.RandomMating(ops=[ sim.MendelianGenoTransmitter(), penetrance, sim.IdTagger(), sim.PedigreeTagger(), ], numOffspring=2, subPopSize=pop.popSize() * 2), gen=1) sim.stat(pop1, numOfAffected=True) return drawAffectedSibpairSample(pop1, nFamilies)
def interim_random_mating(self, pop, recombination_rates): """ Randomly mates 'pop' for 'gens_of_random_mating' generations to further recombine founder genomes and dissolve population structure. :param pop: Founder population after mate_and_merge procedure :return: Population ready to be subjected to selection """ print("Initiating interim random mating for {} generations.".format( self.generations_of_random_mating)) pop.evolve( preOps=[ sim.PyEval(r'"Generation: %d\n" % gen'), ], matingScheme=sim.RandomMating( subPopSize=self.operating_population_size, ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=recombination_rates) ]), gen=self.generations_of_random_mating, )
def population_structure_guided_expansion(self, pop, recombination_rates): """ Uses a population structure matrix to determine the probability of selecting a second parent given the first parent's probability mass function. """ ps_pc = breed.ForcedPopulationStructureParentChooser( self.population_size) print( "Executing population expansion using estimated population structure.") return pop.evolve( initOps=sim.InitSex(), preOps=[ sim.InfoExec('generation=gen'), ], matingScheme=sim.HomoMating( sim.PyParentsChooser(ps_pc.forced_structure_parent_chooser), sim.OffspringGenerator(ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=recombination_rates), ]), subPopSize=self.population_size), gen=1)
# 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(4, loci=1, infoFields=['ind_id', 'father_id', 'mother_id'], ancGen=-1) pop.evolve(initOps=[ sim.InitSex(), sim.IdTagger(), sim.InitGenotype(freq=[0.5, 0.5]), sim.PedigreeTagger(output='>>pedigree.ped', outputLoci=0) ], matingScheme=sim.RandomMating(ops=[ sim.MendelianGenoTransmitter(), sim.IdTagger(), sim.PedigreeTagger(output='>>pedigree.ped', outputLoci=0) ], ), gen=2) # print(open('pedigree.ped').read()) pop.asPedigree() pop.save('pedigree1.ped', loci=0) print(open('pedigree1.ped').read()) # ped = sim.loadPedigree('pedigree1.ped') sim.dump(ped, ancGens=range(3))
def runSimulation(scenario_id, sub_population_size, minMatingAge, maxMatingAge, gen): ''' sub_population_size A vector giving the population sizes for each sub-population. The subpopulations determine which breeding ground an individual belongs to minMatingAge minimal mating age. maxMatingAge maximal mating age. Individuals older than this are effectively dead years number of years to simulate ''' # scenario_id describes the batch of files to load # The mitochondrial DNA will be in mtdna_<scenario_id> # The SNP DNA will be in snp_<scenario_id> # Read the mitochondrial haplotype frequencies. There's a bit to unpack here # We read the lines into an array, and for each one, call split() on it to get one element per column. # However, we do not want this - we want the transpose, where haplotype_frequencies[0] is a vector of # all the frequencies for population 0, and haplotype_frequencies[1] is the corresponding vector for # population 2. list(map(list, zip(*t))) will achieve this transformation for us. # While we are at it, we also convert the strings into floats. mitochondrial_file = "mtdna_" + scenario_id + ".txt" with open(mitochondrial_file, "r") as fd: haplotype_frequencies = list( map(list, zip(*[list(map(float, line[0:-1].split())) for line in fd]))) if len(haplotype_frequencies) != len(sub_population_size): raise ValueError( 'The number of populations in the population size vector and the number of populations deduced from the haplotype file are different' ) # Now read the SNP data. This builds a 2D array indexed as snp[locus][population] snp_file = "snp_" + scenario_id + ".txt" with open(snp_file, "r") as fd: snp = [list(map(float, line[0:-1].split())) for line in fd] sub_population_count = len(sub_population_size) print() print(sub_population_count, "subpopulations detected") # Now we can create the population. We want to give each population a population name, starting from A sub_population_names = list(map(chr, range(65, 65 + sub_population_count))) # We have two chromosomes. The first is an autosome with nb_loci loci, and the second is the mitochondrial chromosome with 1 locus pop = simuPOP.Population( sub_population_size, ploidy=2, loci=[nb_loci, 1], ancGen=2, infoFields=[ 'age', 'ind_id', 'father_id', 'mother_id', 'nitrogen', 'carbon', 'feeding_ground', 'native_breeding_ground', 'migrate_to' ], subPopNames=sub_population_names, chromTypes=[simuPOP.AUTOSOME, simuPOP.MITOCHONDRIAL]) sub_population_names = tuple(sub_population_names) # Create an attribute on each individual called 'age'. Set it to a random number between 0 and maxMatingAge # Note that size is a vector - the size of each population. We have to sum these to get the total number of individuals individual_count = sum(sub_population_size) # Assign a random age to each individual pop.setIndInfo( [random.randint(0, maxMatingAge) for x in range(individual_count)], 'age') # Assign a random feeding ground to each individual pop.setIndInfo([ random.randint(0, numberOfFeedingGrounds - 1) for x in range(individual_count) ], 'feeding_ground') # Currently we have these virtual subpopulations: # age < minMatingAge (juvenile) # age >= minMatingAge and age < maxMatingAge + 0.1 (age <= maxMatingAge) (mature) # age >= maxMatingAge (dead) # # Ideally we would want something like this: # 1) Immature # 2) Receptive female (every 3 years) # 3) Non-receptive female # 4) Mature male # 5) Dead # # Note that we use a cutoff InfoSplitter here, it is also possible to # provide a list of values, each corresponding to a virtual subpopulation. pop.setVirtualSplitter( simuPOP.CombinedSplitter([ simuPOP.ProductSplitter([ simuPOP.SexSplitter(), simuPOP.InfoSplitter('age', cutoff=[minMatingAge, maxMatingAge + 0.1], names=['juvenile', 'mature', 'dead']) ]) ], vspMap=[[0], [1], [2], [3], [4], [5], [0, 1, 3, 4], [1, 4]], names=[ 'Juvenile Male', 'Mature Male', 'Dead Male', 'Juvenile Female', 'Mature Female', 'Dead Female', 'Not dead yet', 'Active' ])) pop.evolve( initOps=[ simuPOP.InitSex(), simuPOP.IdTagger(), simuPOP.PyOperator(func=init_native_breeding_grounds) ] + [ simuPOP.InitGenotype(subPops=sub_population_names[i], freq=haplotype_frequencies[i], loci=[nb_loci]) for i in range(0, sub_population_count) ] + [ simuPOP.InitGenotype(subPops=sub_population_names[i], freq=[snp[n][i], 1 - snp[n][i]], loci=[n]) for i in range(0, sub_population_count) for n in range(0, nb_loci - 1) ], # increase age by 1 preOps=[simuPOP.InfoExec('age += 1')], matingScheme=simuPOP.HeteroMating( [ # age <= maxAge, copy to the next generation (weight=-1) # subPops is a list of tuples that will participate in mating. The tuple is a pair (subPopulation, virtualSubPopulation) # First, we propagate (clone) all individuals in all subpopulations (and all VSPs except the ones who are now in the VSP of deceased individuals) to the next generation simuPOP.CloneMating( ops=[simuPOP.CloneGenoTransmitter(chroms=[0, 1])], subPops=[ (sub_population, 6) for sub_population in range(0, sub_population_count) ], weight=-1), # Then we simulate random mating only in VSP 1 (ie reproductively mature individuals) within subpopulation (breeding/winter grounds) simuPOP.RandomMating( ops=[ simuPOP.MitochondrialGenoTransmitter(), simuPOP.MendelianGenoTransmitter(), simuPOP.IdTagger(), simuPOP.InheritTagger(mode=simuPOP.MATERNAL, infoFields=['feeding_ground']), simuPOP.InheritTagger( mode=simuPOP.MATERNAL, infoFields=['native_breeding_ground']), simuPOP.PedigreeTagger() ], subPops=[ (sub_population, 7) for sub_population in range(0, sub_population_count) ], weight=1) ], subPopSize=configure_new_population_size), postOps=[ # Determine the isotopic ratios in individuals simuPOP.PyOperator(func=postop_processing), simuPOP.Migrator(mode=simuPOP.BY_IND_INFO), # count the individuals in each virtual subpopulation #simuPOP.Stat(popSize=True, subPops=[(0,0), (0,1), (0,2), (1,0), (1, 1), (1, 2)]), # print virtual subpopulation sizes (there is no individual with age > maxAge after mating) #simuPOP.PyEval(r"'Size of age groups: %s\n' % (','.join(['%d' % x for x in subPopSize]))") # Alternatively, calculate the Fst # FIXME: How does this actually work? Does it work for > 2 populations? I don't really understand it yet # ELC: it is a calculation that partitions variance among and between populations, and can be calculated as a # global statistic or on a pairwise basis. We use it as an indication of genetic differentiation. simuPOP.Stat(structure=range(1), subPops=sub_population_names, suffix='_AB', step=10), simuPOP.PyEval(r"'Fst=%.3f \n' % (F_st_AB)", step=10) ], gen=years) #simuPOP.dump(pop, width=3, loci=[], subPops=[(simuPOP.ALL_AVAIL, simuPOP.ALL_AVAIL)], max=1000, structure=False); #return ped = simuPOP.Pedigree(pop) print("This is the pedigree stuff") simuPOP.dump(pop) # Now sample the individuals sample = drawRandomSample(pop, sizes=[sample_count] * sub_population_count) # Print out the allele frequency data simuPOP.stat(sample, alleleFreq=simuPOP.ALL_AVAIL) frequencies = sample.dvars().alleleFreq with open('freq.txt', 'w') as freqfile: index = 0 for locus in frequencies: if (locus == nb_loci): continue if (len(frequencies[locus]) < 2): continue print(index, end=' ', file=freqfile) index = index + 1 for allele in frequencies[locus]: print(frequencies[locus][allele], end=' ', file=freqfile) print(file=freqfile) # We want to remove monoallelic loci. This means a position in the genotype for which all individuals have the same value in both alleles # To implement this we will build up a list of loci that get ignored when we dump out the file. Generally speaking, if we add all the values up # then either they will sum to 0 (if all individuals have type 0) or to the number of individuals * 2 (if all individuals have type 1) geno_sum = [0] * (nb_loci + 1) * 2 for individual in sample.individuals(): geno_sum = list(map(add, geno_sum, individual.genotype())) final_sum = list( map(add, geno_sum[:(nb_loci + 1)], geno_sum[(nb_loci + 1):])) monoallelic_loci = [] for i in range(0, nb_loci): if final_sum[i] == 0 or final_sum[ i] == sample_count * sub_population_count * 2: monoallelic_loci = [i] + monoallelic_loci monoallelic_loci = sorted(monoallelic_loci, reverse=True) nb_ignored_loci = len(monoallelic_loci) # Generate the two files with open('mixfile.txt', 'w') as mixfile: with open('haploiso.txt', 'w') as haplofile: print(sub_population_count, nb_loci - nb_ignored_loci, 2, 1, file=mixfile) print("sex, haplotype, iso1, iso2, native_ground", file=haplofile) for i in range(0, nb_loci - nb_ignored_loci): print('Loc', i + 1, sep='_', file=mixfile) for individual in sample.individuals(): genotype = individual.genotype() print( 1 if individual.sex() == 1 else 0, genotype[nb_loci], individual.info('carbon'), individual.info('nitrogen'), # int(individual.info('native_breeding_ground')), file=haplofile, sep=' ') print(int(individual.info('native_breeding_ground') + 1), end=' ', file=mixfile) for i in range(0, nb_loci): if i not in monoallelic_loci: print(genotype[i] + 1, genotype[i + nb_loci + 1] + 1, ' ', end='', sep='', file=mixfile) print(file=mixfile) return sample
# 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(100, infoFields=['ind_id', 'father_id', 'mother_id']) pop.evolve( initOps=[ sim.InitSex(), sim.IdTagger(), sim.PedigreeTagger(output='>>pedigree.txt'), ], matingScheme=sim.RandomMating(ops=[ sim.IdTagger(), sim.PedigreeTagger(output='>>pedigree.txt'), sim.MendelianGenoTransmitter()] ), gen = 100 ) ped = open('pedigree.txt') lines = ped.readlines() ped.close() # first few lines, saved by the first PedigreeTagger print(''.join(lines[:3])) # last several lines, saved by the second PedigreeTagger print(''.join(lines[-3:]))
import simuPOP as sim pop = sim.Population(1000, ploidy=1, ancGen=-1, infoFields=['ind_id', 'father_id']) pop.evolve(initOps=[ sim.InitSex(), sim.IdTagger(), ], matingScheme=sim.RandomSelection(ops=[ sim.IdTagger(), sim.PedigreeTagger(infoFields='father_id') ], ), gen=1000) # a pedigree with only paternal information pop.asPedigree(motherField='') IDs = pop.identifyAncestors() allIDs = [ind.ind_id for ind in pop.allIndividuals()] removedIDs = list(set(allIDs) - set(IDs)) pop.removeIndividuals(IDs=removedIDs) # number of ancestors... sizes = [pop.popSize(ancGen=x) for x in range(pop.ancestralGens())] print(sizes[0], sizes[100], sizes[500], sizes[999])
# assign an unique ID to everyone. sim.IdTagger(), sim.PyOutput('Prevalence of disease in each age group:\n'), ], # increase the age of everyone by 1 before mating. preOps=sim.InfoExec('age += 1'), matingScheme=sim.HeteroMating([ # all individuals with age < 75 will be kept. Note that # CloneMating will keep individual sex, affection status and all # information fields (by default). sim.CloneMating(subPops=[(0,0), (0,1), (0,2)], weight=-1), # only individuals with age between 20 and 50 will mate and produce # offspring. The age of offspring will be zero. sim.RandomMating(ops=[ sim.IdTagger(), # give new born an ID sim.PedigreeTagger(), # track parents of each individual sim.MendelianGenoTransmitter(), # transmit genotype ], numOffspring=(sim.UNIFORM_DISTRIBUTION, 1, 3), subPops=[(0,1)]),], subPopSize=demoModel), # number of individuals? postOps=[ sim.PyPenetrance(func=pene, loci=0), sim.PyOperator(func=outputstat, step=20) ], gen = 200 ) # draw two Pedigrees from the last age-structured population from simuPOP import sampling
def _generate_f_two(self, pop: sim.Population) -> sim.Population: """ Creates an F2 subpopulations generation by selfing the individuals of 'pop'. Works on a population with one or more subpopulations. """ pop.vars()['generations'][2] = 'F_2' self.odd_to_even(pop) num_sub_pops = pop.numSubPop() progeny_per_individual = int(self.selected_population_size/2) print("Creating the F_two population.") return pop.evolve( preOps=[ sim.MergeSubPops(), sim.PyEval(r'"Generation: %d\n" % gen'), operators.CalcTripletFreq(), sim.PyExec('triplet_freq[gen]=tripletFreq'), sim.SplitSubPops(sizes=[1]*num_sub_pops, randomize=False), ], matingScheme=sim.SelfMating(subPopSize=[progeny_per_individual] * num_sub_pops, numOffspring=progeny_per_individual, ops=[sim.Recombinator(rates=0.01), sim.IdTagger(), sim.PedigreeTagger()], ), gen=1, )
sim.InitGenotype(freq=[0.5, 0.5]), # assign an unique ID to everyone. sim.IdTagger(), ], # increase the age of everyone by 1 before mating. preOps=sim.InfoExec('age += 1'), matingScheme=sim.HeteroMating([ # age 1, 2 will be copied sim.CloneMating( ops=[ # This will set offspring ID sim.CloneGenoTransmitter(), # new ID for offspring in order to track pedigree sim.IdTagger(), # both offspring and parental IDs will be the same sim.PedigreeTagger(output='>>structured.ped'), ], subPops=[(0,1), (0,2)], weight=-1 ), # age 2 produce offspring sim.RandomMating( ops=[ # new ID for offspring sim.IdTagger(), # record complete pedigree sim.PedigreeTagger(output='>>structured.ped'), sim.MendelianGenoTransmitter(), # transmit genotype ], subPops=[(0,2)] )]
def generate_f_one(self, pop: sim.Population): """ A very basic implementation of the F_1 cross between pairs of individuals. Relies on pre-formatting of desired mating pairs into an ordered list. [1, 3, 5, 11, 12, 9, 22, 2] The mating pattern would be: 1x3, 5x11, 12x9, 22x2. Rearranging the order of the indices would change the mating pairs. :param pop: :type pop: :return: :rtype: """ pop.dvars().generations[1] = 'F_1' pop.dvars().gen = 1 pairs_of_founders = int(pop.popSize() / 2) self.odd_to_even(pop) print("Creating the F_one population from selected founders.") return pop.evolve( preOps=[ sim.PyEval(r'"Generation: %d\n" % gen'), operators.CalcTripletFrequencies(), sim.PyExec('triplet_freq[gen]=tripletFreq'), sim.SplitSubPops(sizes=[2] * pairs_of_founders, randomize=False), ], matingScheme=sim.RandomMating(subPopSize=[1] * pairs_of_founders, ops=[sim.Recombinator(rates=0.01), sim.IdTagger(), sim.PedigreeTagger()]), gen=1, )
def replicate_recurrent_drift(self, multi_pop, meta_sample_library, qtl, allele_effects, recombination_rates): """ :param multi_pop: :param meta_pop_sample_library: :param qtl: :param allele_effects: :param recombination_rates: :return: """ for pop in multi_pop.populations(): pop.dvars().gen = 0 sizes = [self.individuals_per_breeding_subpop] \ * self.number_of_breeding_subpops + \ [self.number_of_nonbreeding_individuals] offspring_pops = [self.offspring_per_breeding_subpop] \ * self.number_of_breeding_subpops + [0] assert len(sizes) == len(offspring_pops), "Number of parental " \ "subpopulations must equal " \ "the number of offspring " \ "subpopulations" sampling_generations = [ i for i in range(2, self.generations_of_drift, 2) ] pc = breed.HalfSibBulkBalanceChooser( self.individuals_per_breeding_subpop, self.offspring_per_female) multi_pop.evolve( initOps=[ sim.InitInfo(0, infoFields=['generation']), sim.InfoExec('replicate=rep'), operators.GenoAdditiveArray(qtl, allele_effects), operators.CalculateErrorVariance(self.heritability), operators.PhenotypeCalculator( self.proportion_of_individuals_saved), operators.ReplicateMetaPopulation(meta_sample_library, self.meta_pop_sample_sizes), sim.PyEval(r'"Initial: Sampled %d individuals from generation ' r'%d Replicate: %d.\n" % (ss, gen_sampled_from, ' r'rep)'), ], preOps=[ sim.PyEval(r'"Generation: %d\n" % gen'), operators.GenoAdditiveArray(qtl, allele_effects, begin=1), sim.InfoExec('generation=gen'), sim.InfoExec('replicate=rep'), operators.PhenotypeCalculator( self.proportion_of_individuals_saved, begin=1), operators.ReplicateMetaPopulation(meta_sample_library, self.meta_pop_sample_sizes, at=sampling_generations), sim.SplitSubPops(sizes=sizes, randomize=False), ], matingScheme=sim.HomoMating( sim.PyParentsChooser(pc.recursive_pairwise_parent_chooser), sim.OffspringGenerator(ops=[ sim.IdTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=recombination_rates) ], numOffspring=1), subPopSize=offspring_pops, subPops=list(range(1, self.number_of_breeding_subpops, 1))), postOps=[ sim.MergeSubPops(), operators.DiscardRandomOffspring( self.number_of_offspring_discarded), ], finalOps=[ sim.InfoExec('generation=gen'), sim.InfoExec('replicate=rep'), operators.GenoAdditiveArray(qtl, allele_effects), operators.PhenotypeCalculator( self.proportion_of_individuals_saved), operators.ReplicateMetaPopulation(meta_sample_library, self.meta_pop_sample_sizes), sim.PyEval( r'"Final: Sampled %d individuals from generation %d\n" ' r'% (ss, gen_sampled_from)'), ], gen=self.generations_of_drift)
def simulateBySimuPOP(): #starting variables directory = '/data/new/javi/toxo/simulations4/' input_path = 'Toxo20.txt' output_path = 'SimulatedToxo.txt' input_path = directory + input_path output_path = directory + output_path parents_path = directory + '/parents.txt' pedigree_path = directory + 'pedigree.txt' number_of_ancestors = 3 expansion_pop_size = 15 offsprings_sampled = number_of_ancestors + expansion_pop_size gen = 3 translate_mode = 'toxoplasma' structure_mode = 'simupop' #parsing input init_info = parseSNPInput(input_path, number_of_ancestors) ancestral_genomes = init_info[0] ancestor_names = ancestral_genomes.keys() loci_positions = init_info[1] chromosome_names = sorted(loci_positions.keys(), key=lambda x: cns.getValue(x, translate_mode)) list_of_loci = [len(loci_positions[chr]) for chr in chromosome_names] lociPos = fc.reduce(lambda x, y: x + y, [loci_positions[x] for x in chromosome_names]) sp.turnOnDebug(code="DBG_GENERAL") #initializing print('Initializaing Population') population = sp.Population(size=[number_of_ancestors], loci=list_of_loci, ancGen = 5, lociPos = lociPos, \ chromNames = chromosome_names, lociNames = [], alleleNames = ['A','T','G','C'],\ infoFields=['name', 'ind_id', 'father_id', 'mother_id']) for individual, sample, ind_id in zip(population.individuals(), ancestral_genomes, range(len(ancestral_genomes))): individual.setInfo(ancestor_names.index(sample), 'name') individual.setInfo(ind_id, 'ind_id') for ind, chr in enumerate(chromosome_names): individual.setGenotype(ancestral_genomes[sample][chr], chroms=[ind]) #Alternating rounds of recombination with clonal expansion. Clonal expansion gives + 2. #Mutation prior to each round simulator = sp.Simulator(population) rate_matrix = createRateMatrix(len(ancestor_names), 0.0002) #10,000 times the mutation rate. id_tagger = sp.IdTagger() ped_tagger = sp.PedigreeTagger(output='>>' + pedigree_path, outputFields=['name', 'ind_id']) inherit_tagger = sp.InheritTagger(infoFields='name') initOps1 = [sp.PyExec('print("Starting random selection")'), ped_tagger] initOps2 = [sp.PyExec('print("Starting random mating")'), ped_tagger] preOps1 = [sp.MatrixMutator(rate=rate_matrix)] preOps2 = [sp.InitSex(sex=[sp.MALE, sp.FEMALE])] matingScheme1 = sp.RandomSelection( ops=[sp.CloneGenoTransmitter(), inherit_tagger, id_tagger, ped_tagger], subPopSize=expansion_pop_size) matingScheme2 = sp.RandomMating( ops=[ sp.Recombinator(intensity=0.01 / 105000, convMode=(sp.GEOMETRIC_DISTRIBUTION, 0.001, 0.01)), #10x normal sp.PyTagger(func=addNames), id_tagger, ped_tagger ], subPopSize=expansion_pop_size) postOps = [] finalOps = [] print('Starting Evolution Cycles.') try: os.remove(pedigree_path) except: pass simulator.evolve( initOps=[id_tagger, ped_tagger], matingScheme=sp.CloneMating(ops=[ sp.CloneGenoTransmitter(), ped_tagger, id_tagger, inherit_tagger ]), gen=1) for x in range(gen): simulator.evolve(initOps=initOps1, preOps=preOps1, matingScheme=matingScheme1, postOps=postOps, finalOps=finalOps, gen=1) simulator.evolve(initOps=initOps2, preOps=preOps2, matingScheme=matingScheme2, postOps=postOps, finalOps=finalOps, gen=1) offsprings = { ''.join([ str(int(x.info('name'))), generateID(3), str(int(x.info('ind_id'))) ]): x.info('ind_id') for x in simulator.population(0).individuals() } sampled_ones = rand.sample(offsprings.keys(), offsprings_sampled) #reorganizes the offspring genome. Extract info by chr. offspring_genomes = {name: {} for name in sampled_ones} for name in sampled_ones: for ind, chr in enumerate(chromosome_names): offspring_genomes[name][chr] = simulator.population(0).indByID( offsprings[name], idField='ind_id').genotype(ploidy=0, chroms=[ind]) offspring_genomes.update(ancestral_genomes) print('Parent Guide:') for ind, id in enumerate(ancestor_names): print(" : ".join([str(ind), str(id)])) print('Complete. Generating Output.') with open(parents_path, 'w') as parent_output: parent_output.write('Parent Guide:\n') for ind, id in enumerate(ancestor_names): parent_output.write(" : ".join([str(ind), str(id)]) + '\n') #output offspring_genomes = snp.restructure((offspring_genomes, loci_positions), structure_mode) snp.outputGriggFormat(offspring_genomes, output_path) print('Simulation Complete.')
sim.InitInfo([0], infoFields='age'), sim.InitInfo([1], infoFields='fitness'), sim.InitInfo([0], infoFields='birthday'), # At this point, even males are diploids! Only 1/1 and 1/0 (but not 0/1) males get 'a' increased. sim.InfoExec( "a = min_a + meffect if ind.sex() == 1 and ind.allele(0,0) == 1 else min_a", exposeInd='ind'), sim.InitInfo([args.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 (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.PedigreeTagger(output='>>{}.ped'.format(args.output), outputFields=['a', 'birthday'], outputLoci=[0]), sim.PyExec( "AccumAges = {1: {0: {x: 0 for x in range(maxAge)}, 1: {x: 0 for x in range(maxAge)}, 2: {x: 0 for x in range(maxAge)}}, 2: {0: {x: 0 for x in range (maxAge)}, 1: {x: 0 for x in range(maxAge)}, 2: {x: 0 for x in range(maxAge)}}}" ) ], preOps=[ sim.InfoExec("luck = random.random()"), sim.InfoExec( "smurf = 1.0 if (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(aging_model(args.model)), sim.InfoExec("age += 1"), # Here, ind.allele(0,1) is 0 for all males, except in first generation. sim.InfoExec( "AccumAges[ind.sex()][ind.allele(0,0) + ind.allele(0,1)][int(ind.age)] += 1",
# description of this example. # import simuPOP as sim pop = sim.Population(1000, ancGen=-1, infoFields=['ind_id', 'father_id', 'mother_id']) pop.evolve( initOps=[ sim.InitSex(), sim.IdTagger(), ], matingScheme=sim.RandomMating( numOffspring=(sim.UNIFORM_DISTRIBUTION, 2, 4), ops=[ sim.MendelianGenoTransmitter(), sim.IdTagger(), sim.PedigreeTagger() ], ), gen = 19 ) # we now have the complete pedigree of 20 generations pop.asPedigree() # total number of individuals should be 20 * 1000 # how many families do we have? fam = pop.identifyFamilies() len(fam) # but how many families with more than 1 individual? # The rest of them must be in the initial generation len([x for x in fam if x > 1]) # let us look backward. allAnc are the ancestors who have offspring in the # last generation. You can see this is a small number compared the number of
def test_generate_operating_population(): genetic_map = pd.read_csv('nam_prefounders_genetic_map.txt', index_col=None, sep='\t') pf_map = shelve.open('pf_map') misc_gmap = shelve.open('misc_gmap') uniparams = shelve.open('uniparams') locus_names = uniparams['locus_names'] pos_column = uniparams['pos_column'] allele_names = uniparams['allele_names'] snp_to_integer = uniparams['snp_to_integer'] integer_to_snp = uniparams['integer_to_snp'] alleles = misc_gmap['alleles'] chr_cM_positions = misc_gmap['chr_cM_positions'] cM_positions = misc_gmap['cM_positions'] integral_valued_loci = misc_gmap['integral_valued_loci'] relative_integral_valued_loci = misc_gmap['relative_integral_valued_loci'] recombination_rates = misc_gmap['recombination_rates'] nam = sim.loadPopulation(uniparams['prefounder_file_name']) sim.tagID(nam, reset=True) nam.setSubPopName('maize_nam_prefounders', 0) selection_statistics = { 'aggregate': {}, 'selected': {}, 'non-selected': {} } ind_names_for_gwas = {i: {} for i in range(uniparams[ 'number_of_replicates'])} uniparams['meta_pop_sample_sizes'] = {i: 100 for i in range(0, uniparams['generations_of_selection'] + 1, 2) } s = simulate.Truncation(uniparams['generations_of_selection'], uniparams['generations_of_random_mating'], uniparams['operating_population_size'], uniparams[ 'proportion_of_individuals_saved'], uniparams['overshoot_as_proportion'], uniparams['individuals_per_breeding_subpop'], uniparams['heritability'], uniparams['meta_pop_sample_sizes'], uniparams['number_of_replicates']) ind_names_for_gwas = {i: {} for i in range(uniparams[ 'number_of_replicates'])} founders = uniparams['founders'] replicated_nam = sim.Simulator(nam, rep=2, stealPops=False) pop = replicated_nam.extract(0) assert pop.popSize() == 26, "Population is too large." s.generate_f_one(pop, recombination_rates, founders, 100) assert pop.popSize() == 400, "Population should have size: {} after the F_1 mating " \ "procedure." \ "".format(len(founders) * 100) #pop.splitSubPop(0, [100] * 4) #subpop_list = list(range(pop.numSubPop())) intmd_os_struct = s.restructure_offspring(pop, 100, 4) snd_order = breed.SecondOrderPairIDChooser(intmd_os_struct, 1) pop.evolve( preOps=[sim.MergeSubPops()], matingScheme=sim.HomoMating( sim.PyParentsChooser(snd_order.snd_ord_id_pairs), sim.OffspringGenerator(ops=[ sim.IdTagger(), sim.ParentsTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=recombination_rates) ], numOffspring=1), subPopSize=[200], ), gen=1, ) assert pop.popSize() == 1, "Population does not have correct size after second round of mating." second_intmd_os_struct = s.restructure_offspring(pop, 100, 2) third_order = breed.SecondOrderPairIDChooser(second_intmd_os_struct, 1) pop.evolve( preOps=[sim.MergeSubPops()], matingScheme=sim.HomoMating( sim.PyParentsChooser(third_order.snd_ord_id_pairs), sim.OffspringGenerator(ops=[ sim.IdTagger(), sim.ParentsTagger(), sim.PedigreeTagger(), sim.Recombinator(rates=recombination_rates) ], numOffspring=1), subPopSize=[100], ), gen=1, ) assert pop.popSize() == 100, "Second merge of breeding sub-populations. Offspring population does not have " \ "correct size"
founder_chooser = breed.PairwiseIDChooser(founders, offspring_per_pair) number_of_pairs = len(founders) example_pop.evolve( initOps=[ sim.InitLineage( mode=sim.FROM_INFO ), #assigns lineage of each allele to be tracked through pop.evolve ], preOps=[], matingScheme=sim.HomoMating( sim.PyParentsChooser(founder_chooser.by_id_pairs), sim.OffspringGenerator( ops=[ sim.IdTagger(), sim.PedigreeTagger(output='>>pedigree0.ped' ), #outputs pedigree file for checking sim.Recombinator(rates=recom_map) ], numOffspring=1), subPopSize=[offspring_per_pair * number_of_pairs], ), gen=1, ) ### Generate Double Hybrids #Define mothers and fathers, this case is 3 crosses between each pair of hybrid mothers = np.array([8., 8., 8., 10., 10., 10.]) fathers = np.array([9., 9., 9., 11., 11., 11.]) second_order_chooser = breed.SecondOrderPairIDChooser( mothers, fathers ) #Defines parental pairs, 8 mated with 9 three times,10 mated with 11 three times
pop = sim.Population( size=[8, 16], ploidy=2, loci=[0, 1, 2], infoFields=['ind_id', 'father_id', 'mother_id', 'gen_id', 'sp_id'], lociPos=(1, 2, 3), ancGen=gen_evolve) pop.evolve( initOps=[ sim.IdTagger(begin=0, end=-1), sim.InitSex(maleProp=0.5), sim.InitGenotype(freq=[0.2, 0.2, 0.2, 0.2, 0.2], loci=[0, 1, 2]), sim.PedigreeTagger(output='>>simp_Pedigree.ped', outputLoci=[0, 1, 2], outputFields=['gen_id', 'sp_id']) ], #end of initOps preOps=[ PyOperator(lambda pop: [ pop.setIndInfo(x, "sp_id", x) for x in range(pop.numSubPop()) ] is not None), ], matingScheme=sim.MonogamousMating( subPopSize=censuscontrol, numOffspring=8, sexMode=(sim.NUM_OF_MALES, 2), ops=[ sim.InfoExec('gen_id = gen'), sim.MendelianGenoTransmitter(), sim.IdTagger(),
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