Miscellaneous operators¶
An operator that does nothing (operator NoneOp
)¶
Operator NoneOp
does nothing when it is applied to a population. It
provides a placeholder when an operator is needed but no action is required.
Example NoneOp demonstrates a typical usage of this operator
if hasSelection:
sel = MapSelector(loci=[0], fitness=[1, 0.99, 0.98])
else:
sel = NoneOp()
#
simu.evolve(
preOps=[sel], # and other operators
matingScheme=RandomMating(),
gen=10
)
dump the content of a population (operator Dumper
)¶
Operator Dumper
and its function form dump
has been used
extensively in this guide. They are prefect for demonstration and debugging
purposes because they display all properties of a population in a human readable
format. They are, however, rarely used in realistic settings because outputting
a large population to your terminal can be disastrous.
Even with modestly-sized populations, it is a good idea to dump only parts of
the population that you are interested. For example, you can use parameter
genotype=False
to stop outputting individual genotype, structure=False
to stop outtputing genotypic and population structure information,
loci=range(5)
to output genotype only at the first five loci, max=N
to
output only the first N
individuals (default to 100
), subPops=[(0,
0)]
to output, for example, only the first virtual subpopulation in
subpopulation 0. Multiple virtual subpopulations are allowed and you can even
use subPops=[(ALL_AVAIL, 0)]
to go through a specific virtual subpopulation
of all subpopulations. This operator by default only dump the present generation
but you can set ancGens
to a list of generation numbers or ALL_AVAIL
to
dump part or all ancestral generations. Finally, if there are more than 10
alleles, you can set the width
at which each allele will be printed. The
following example (Example Dumper) presents a rather complicated
usage of this operator.
Example: dump the content of a population
>>> import simuPOP as sim
>>> pop = sim.Population(size=[10, 10], loci=[20, 30], infoFields='gen',
... ancGen=-1)
>>> sim.initSex(pop)
>>> pop.setVirtualSplitter(sim.SexSplitter())
>>> pop1 = pop.clone()
>>> sim.initGenotype(pop, freq=[0]*20 + [0.1]*10)
>>> pop.setIndInfo(1, 'gen')
>>> sim.initGenotype(pop1, freq=[0]*50 + [0.1]*10)
>>> pop1.setIndInfo(2, 'gen')
>>> pop.push(pop1)
>>> sim.dump(pop, width=3, loci=[5, 6, 30], subPops=([0, 0], [1, 1]),
... max=10, structure=False)
SubPopulation 0,0 (Male), 5 Individuals:
2: MU 56 54 52 | 58 54 51 | 2
3: MU 52 50 51 | 56 51 50 | 2
4: MU 50 53 52 | 52 59 56 | 2
5: MU 57 54 56 | 57 57 53 | 2
6: MU 59 54 54 | 57 51 50 | 2
SubPopulation 1,1 (Female), 7 Individuals:
10: FU 54 53 57 | 59 59 59 | 2
11: FU 55 59 51 | 59 51 58 | 2
12: FU 55 58 58 | 57 54 58 | 2
14: FU 53 57 52 | 51 54 58 | 2
15: FU 51 58 59 | 54 52 54 | 2
>>> # list all male individuals in all subpopulations
>>> sim.dump(pop, width=3, loci=[5, 6, 30], subPops=[(sim.ALL_AVAIL, 0)],
... max=10, structure=False)
SubPopulation 0,0 (Male), 5 Individuals:
2: MU 56 54 52 | 58 54 51 | 2
3: MU 52 50 51 | 56 51 50 | 2
4: MU 50 53 52 | 52 59 56 | 2
5: MU 57 54 56 | 57 57 53 | 2
6: MU 59 54 54 | 57 51 50 | 2
SubPopulation 1,0 (Male), 3 Individuals:
13: MU 55 52 53 | 57 56 52 | 2
17: MU 55 51 51 | 57 55 51 | 2
19: MU 56 54 53 | 58 58 56 | 2
now exiting runScriptInteractively...
Save a population during evolution (operator SavePopulation
)¶
Because it is usually not feasible to store all parental generations of an
evolving population, it is a common practise to save snapshots of a population
during an evolutionary process for further analysis. Operator
SavePopulation
is designed for this purpose. When it is applied to a
population, it will save the population to a file specified by parameter
output
.
The tricky part is that populations at different generations need to be saved to
different filenames so the expression version of parameter output
needs to
be used (see operator BaseOperator
for details). For example,
expression 'snapshot_%d_%d.pop' % (rep, gen)
is used in Example
SavePopulation to save population to files such as
snapshot_5_20.pop
during the evolution.
Example: Save snapshots of an evolving population
>>> import simuPOP as sim
>>> simu = sim.Simulator(sim.Population(100, loci=2),
... rep=5)
>>> simu.evolve(
... initOps=[
... sim.InitSex(),
... sim.InitGenotype(freq=[0.2, 0.8])
... ],
... matingScheme=sim.RandomMating(),
... postOps=sim.SavePopulation(output="!'snapshot_%d_%d.pop' % (rep, gen)",
... step = 10),
... gen = 50
... )
(50, 50, 50, 50, 50)
now exiting runScriptInteractively...
Pause and resume an evolutionary process (operator Pause
) *¶
If you are presenting an evolutinary process in public, you might want to
temporarily stop the evolution so that your audience can have a better look at
intermediate results or figures. If you have an exceptionally long evolutionary
process, you might want to examine the status of the evolution process from time
to time. These can be done using a Pause
operator.
The Pause
operator can stop the evolution at specified generations, or
when you press a key. In the first case, you usually specify the generations to
Pause (e.g. Pause
(step=1000
)) so that you can examine the status
of a simulation from time to time. In the second case, you can apply the
operator at each generation and Pause the simulation when you press a key (e.g.
Pause
(stopOnKeyStroke=True
)). A specific key can be specified so
that you can use different keys to stop different populations, as shown in
Example Pause.
Example: Pause the evolution of a simulation
>>> import simuPOP as sim
>>> simu = sim.Simulator(sim.Population(100), rep=10)
>>> simu.evolve(
... initOps=[
... sim.InitSex(),
... sim.InitGenotype(freq=[0.5, 0.5])
... ],
... matingScheme=sim.RandomMating(),
... postOps=[sim.Pause(stopOnKeyStroke=str(x), reps=x) for x in range(10)],
... gen = 100
... )
(100, 100, 100, 100, 100, 100, 100, 100, 100, 100)
now exiting runScriptInteractively...
When a simulation is Paused, you are given the options to resume evolution, stop
the evolution of the Paused population or all populations, or enter an
interactive Python shell to examine the status of a population, which will be
available in the Python shell as pop_X_Y
where X
and Y
are
generation and replicate number of the population, respectively. The evolution
will resume after you exit the Python shell.
Measuring execution time of operators (operator TicToc
) *¶
The TicToc
operator can be used to measure the time between two events
during an evolutionary process. It outputs the elapsed time since the last time
it is called, and the overall time since the operator is created. It is very
flexible in that you can measure the time spent for mating in an evolutionary
cycle if you apply it before and after mating, and you can measure time spent
for several evolutionary cycles using generation applicability parameters such
as step
and at
. The latter usage is demonstrated in Example TicToc.
Example: Monitor the performance of operators
>>> import simuPOP as sim
>>> simu = sim.Simulator(sim.Population(10000, loci=[100]*5), rep=2)
>>> simu.evolve(
... initOps=[
... sim.InitSex(),
... sim.InitGenotype(freq=[0.1, 0.9])
... ],
... matingScheme=sim.RandomMating(),
... postOps=[
... sim.Stat(alleleFreq=0),
... sim.TicToc(step=50, reps=-1),
... ],
... gen = 101
... )
Start stopwatch.
Elapsed time: 5.00s Overall time: 5.00s
Elapsed time: 4.00s Overall time: 9.00s
(101, 101)
now exiting runScriptInteractively...