Beispiel #1
0
 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,
     )
Beispiel #2
0
 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,
         )
Beispiel #3
0
 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,
     )
Beispiel #4
0
# 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')
    ]
)
        

Beispiel #5
0
    pop = sim.Population(size=100, loci=1)

    #Define the demographic trajectory
    demo_function = serf.demo_dynamic(101, 100., np.log(2), 100000., 10., 30,
                                      sampling)

    #Initiate the simulation
    simu = sim.Simulator(pop, rep=100)

    #Evolve population
    simu.evolve(
        initOps=[
            sim.InitSex(),
            sim.InitGenotype(
                freq=[0.95, 0.05]),  #proportion of minor to major allele
            sim.PyExec(
                'traj=[]')  #Initiate a recipient list for frequency outputs
        ],
        matingScheme=sim.RandomSelection(
            subPopSize=demo_function),  #random binary fission
        postOps=[
            sim.Stat(alleleFreq=0),
            sim.PyExec('traj.append(alleleFreq[0][1])',
                       step=10),  #record state of the simulation
        ],
        gen=101  #number of generations over which to run the simulation
    )

    #Store simulation output, specifically the state of the alleles at the
    #last recorded simulated timepoint.
    simulation_outcome[sampling] = [simu.dvars(x).traj[-1] for x in range(100)]
Beispiel #6
0
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()])
Beispiel #7
0
###############################################################
#                         SIMULATION                          #
###############################################################

simu = sim.Simulator(pop, rep=args.replicates)

simu.evolve(
   initOps = [
      sim.InitInfo([0], infoFields = 'age'),
      sim.InitInfo([args.a], infoFields = 'a'),
      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 if (model == 'two_phases' and 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", exposeInd = 'ind'),
      sim.PyExec("Surviving = {'larvae': [], 'adults': [], 'smurfs': []}")
   ],
   preOps = [
      sim.InfoExec("luck = random.random()"),
      sim.InfoExec("smurf = 1 if ((ind.smurf == 1) or (model == 'two_phases' and 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", exposeInd='ind'),
      sim.DiscardIf(aging_model(args.model)),
      sim.InfoExec("age += 1")
   ],
   matingScheme = sim.CloneMating(subPops = sim.ALL_AVAIL, subPopSize = demo),
   postOps = [
      sim.Stat(popSize=True, subPops=[(0,0), (0,1), (0,2)]),
      sim.PyExec("Surviving['larvae'].append(subPopSize[0])"),
      sim.PyExec("Surviving['adults'].append(subPopSize[1])"),
      sim.PyExec("Surviving['smurfs'].append(subPopSize[2])"),
#      sim.PyEval(r'"{:d}\t{:d}\t{:d}\t{:d}\n".format(gen, subPopSize[0], subPopSize[1], subPopSize[2])', step=1),
      sim.TerminateIf('popSize == 0')
Beispiel #8
0
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}
Beispiel #9
0
    initOps=[
    ],
    preOps=[

                        ],
    matingScheme=sim.RandomMating(subPopSize=sizeChange,numOffspring=(sim.POISSON_DISTRIBUTION, Offspring_Poisson_dist_mean),ops=sim.Recombinator(loci=[0, 1, 2, 3, 4, 5, 6, 7], rates=[0.095162582,	0.075960076,	0.094257292,	0.154646165,	0.005,	0.104165865,	0.071328306,0.5]))

    ,
    postOps=[
            sim.PySelector(loci=[4], func=sel),
            sim.Stat(alleleFreq=[0,1,2,3,4,5,6,7],numOfMales=True,popSize=True),

            #Output H per replicate per generation to file
            sim.PyEval(r"'%d\t%d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\n' % (rep,gen, 1-sum([x*x for x in alleleFreq[0].values()]), 1-sum([x*x for x in alleleFreq[1].values()]), 1-sum([x*x for x in alleleFreq[2].values()]), 1-sum([x*x for x in alleleFreq[3].values()]), 1-sum([x*x for x in alleleFreq[4].values()]), 1-sum([x*x for x in alleleFreq[5].values()]), 1-sum([x*x for x in alleleFreq[6].values()]), 1-sum([x*x for x in alleleFreq[7].values()]))", step=1,reps=(range(0,Replicates,1)),output=Output_file),

            sim.PyExec('from math import log'),

            #sim.Dumper(output='!"./Simulation_output_pops/pop%d.pop"%rep',step=69,max=500,width=3),

            #allelic richness for given locus
            #sim.PyEval(r"'%d\n' % (len(alleleNum[0].keys()))"),

            #Output Shannon E per replicate per generation to file
            #sim.PyEval(r"'%d\t%d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\n' % (rep,gen, (0-sum([(x * log(x)) for x in alleleFreq[0].values()])/log(len(alleleNum[0].keys())) if len(alleleNum[0].keys()) > 1 else 0) , (0-sum([(x * log(x)) for x in alleleFreq[1].values()])/log(len(alleleNum[1].keys())) if len(alleleNum[1].keys()) > 1 else 0) , (0-sum([(x * log(x)) for x in alleleFreq[2].values()])/log(len(alleleNum[2].keys())) if len(alleleNum[2].keys()) > 1 else 0) , (0-sum([(x * log(x)) for x in alleleFreq[3].values()])/log(len(alleleNum[3].keys())) if len(alleleNum[3].keys()) > 1 else 0) , (0-sum([(x * log(x)) for x in alleleFreq[4].values()])/log(len(alleleNum[4].keys())) if len(alleleNum[4].keys()) > 1 else 0) , (0-sum([(x * log(x)) for x in alleleFreq[5].values()])/log(len(alleleNum[5].keys())) if len(alleleNum[5].keys()) > 1 else 0) , (0-sum([(x * log(x)) for x in alleleFreq[6].values()])/log(len(alleleNum[6].keys())) if len(alleleNum[6].keys()) > 1 else 0), (0-sum([(x * log(x)) for x in alleleFreq[7].values()])/log(len(alleleNum[7].keys())) if len(alleleNum[7].keys()) > 1 else 0))", step=1,reps=(range(0,Replicates,1)),output=Output_file2)

            #Output AlleleNum
            sim.PyEval(r"'%d\t%d\t%.d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n' % (rep,gen, len(alleleNum[0].keys()),len(alleleNum[1].keys()),len(alleleNum[2].keys()),len(alleleNum[3].keys()),len(alleleNum[4].keys()),len(alleleNum[5].keys()),len(alleleNum[6].keys()),len(alleleNum[7].keys()))", step=1,reps=(range(0,Replicates,1)),output=Output_file3)

            #Output sex ratio
            #sim.PyExec('ratio= (numOfMales/popSize)'),
            #sim.PyEval("'gen=%d' % gen", reps=0),
Beispiel #10
0
# 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(100, loci=1),
    rep=2)
simu.evolve(
    initOps=[
        sim.InitSex(),
        sim.InitGenotype(freq=[0.2, 0.8]),
        sim.PyExec('traj=[]')
    ],
    matingScheme=sim.RandomMating(),
    postOps=[
        sim.Stat(alleleFreq=0),
        sim.PyExec('traj.append(alleleFreq[0][1])'),
    ],
    gen=5
)
# print Trajectory
print(', '.join(['%.3f' % x for x in simu.dvars(0).traj]))

Beispiel #11
0
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.')
Beispiel #12
0
     # 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",
         usePopVars=True,
         exposeInd='ind'),
     sim.PySelector(loci=[0], func=fitness_func)
Beispiel #13
0
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