Nemo
2.3.56
Simulate forward-in-time genetic evolution in a spatially explicit, individual-based stochastic simulator
|
Adding a trait to the framework is in fact pretty straightforward. You will have to derive the TraitPrototype class to build your prototype and the TTrait interface to specify what the trait is actually doing.
Why having these two classes? The TraitPrototype class is a SimComponent and is thus used to implement the trait's parameters. It is then used by the Metapop class (or its IndFactory base) at the simulation setup time to generate the Individual prototype. This Individual prototype is then cloned each time a new individual is needed in the population. The TraitPrototype implements a method called TraitPrototype::hatch() that creates (instantiates) a trait with all its variables set to the input (user defined) parameter values when a new individual is created.
The TTrait class encapsulates the way the trait behaves, that is how it is inherited, how it mutates, and how its phenotype is given by its genotype. However, the interface does not provide any structure to implement its precise genetic architecture leaving it completely to the implementer. Futhermore, as it is also a StorableComponent, the implementer must thus define the StorableComponent::store_data and StorableComponent::retrieve_data routines.
The way the genetic architecture of a trait has been implemented so far is rather simple. The current traits usually declare a double array as a private member, which type varies from trait to trait. For instance, the neutral markers are coded on unsigned char while the deleterious mutations are coded on char (in version 2.0.1) or bitstring (i.e. strings of bits coded on arrays of long int as in version 2.0.2), and the dispersal genes are double precision variables with values between 0 and 1.
Here is an example of a basic TTrait and TraitPrototype implementation. The MyTrait derived class implements a trait coded on a double array of unsigned char (unsigned char *_sequence[2]
) as this trait is supposed to be diploid. The number of locus present in each individual will be given by a parameter called "mytrait_loci" present in the implementation of the trait prototype. The same is true for the number of alleles per locus and the mutation rate (parameters "mytrait_alleles" and "mytrait_mutation_rate"). In order to allow the trait prototype to transmit the parameters values to the traits, the MyTrait class must define the accessors functions to its private members _nb_locus
, _nb_allele
, and _mutation_rate
(see the example below). It must also define the copy constructor, operator =, and operator == to copy these values when cloning itself or when the assignment operator is called, and to compare two of its instances. The two later operators are used when loading individuals from binary files, in which case the trait settings from the binary source must be compared to the current simulation settings (c.f. Metapop::loadPopFromBinarySource() for more details).
The mytrait.h file looks like this:
The mytrait.cpp file looks like this: