To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

README.md 6.48 KB
Newer Older
Victor's avatar
Victor committed
1
2
# EvoId.jl
<!-- [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://vboussange.github.io/EvoId.jl/stable) -->
Victor's avatar
Victor committed
3
<!-- For now we only direct to dev documentation. In the future, one will need to deploy a ssh key to and use TagBot. -->
Victor's avatar
Victor committed
4
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://vboussange.github.io/EvoId.jl/dev)
Victor's avatar
Victor committed
5
<!-- [![Build Status](https://github.com/vboussange/EvoId.jl/workflows/CI/badge.svg)](https://github.com/vboussange/EvoId.jl/actions) -->
Victor's avatar
Victor committed
6

Victor's avatar
Victor committed
7
<div align="center"> <img
Victor's avatar
Victor committed
8
src="https://vboussange.github.io/images/research/gif_evoid.gif"
Victor's avatar
Victor committed
9
alt="" width="400"></img> </div>
Victor's avatar
Victor committed
10

Victor's avatar
Victor committed
11
EvoId.jl (for **Evo**lutionary **I**n**d**ividual-based models) is a package aimed at simulating the eco-evolutionary dynamics of a population in a multidimensional space, at the individual level. The dynamics is specified under the framework of [stochastic models for structured populations](https://arxiv.org/abs/1506.04165).
Victor's avatar
Victor committed
12

Victor's avatar
Victor committed
13
Individuals are characterised by **a set of traits** in some **combination of evolutionary spaces**. An evolutionary space can represent for example a geographical landscape, a trait space, or genetic structure. Spaces can be of any dimensions, discrete or continuous, bounded or unbounded. They can equally consist of graphs. Individuals give birth at a rate given by the birth function `b`, and die at a rate given by the death function `d`. When an individual give birth, its offspring can move on the underlying evolutionary spaces. The movement can capture whether migration or mutation processes, and is characterised by a probability `m` and movement range `D`.
Victor's avatar
Victor committed
14

Victor's avatar
Victor committed
15
The user can provide **any birth and death functions**, which should depend on the system state and the individuals' trait. Together with the **movement rate and movement range**, this defines the dynamics of the system.
Victor's avatar
Victor committed
16

Victor's avatar
Victor committed
17
EvoId.jl provides a **numerical laboratory** for eco-evolutionary dynamics, supplying
Victor's avatar
Victor committed
18

19
20
- flexible types for **individuals**, which can
    - evolve over any combination of space,
Victor's avatar
Victor committed
21
    - [store ancestors trait](https://vboussange.github.io/EvoId.jl/dev/examples/gradient.html#lineages),
Victor's avatar
Victor committed
22
23
- flexible types for **evolutionary spaces**, that can consist of multidimensional **discrete or continuous domains**, as well as **graphs**,
- the possibility to use **callback functions** to save the state of the system at any time step
Victor's avatar
Victor committed
24
- several **algorithms** for the simulations ([Gillespie](https://en.wikipedia.org/wiki/Gillespie_algorithm),[Wright-Fisher](https://en.wikipedia.org/wiki/Moran_process), etc...),
Victor's avatar
Victor committed
25
- **utility functions** to analyse simulation results.
bvictor's avatar
bvictor committed
26

bvictor's avatar
bvictor committed
27
## Installation
Victor's avatar
Victor committed
28
Open Julia in your favorite REPL and type the following
Victor's avatar
Victor committed
29

bvictor's avatar
bvictor committed
30
31
```julia
using Pkg;
Victor's avatar
Victor committed
32
Pkg.add("https://github.com/vboussange/EvoId.jl")
bvictor's avatar
bvictor committed
33
```
Victor's avatar
Victor committed
34

bvictor's avatar
bvictor committed
35
This will download latest version from git repo and download all dependencies.
Victor's avatar
Victor committed
36

bvictor's avatar
bvictor committed
37
## Getting started
Victor's avatar
Victor committed
38
Check out the tutorial prodived below. You can also look at the `example` folder, or dive into the [documentation](https://vboussange.github.io/EvoId.jl/dev) if you want to use the advanced features of EvoId.jl. 
Victor's avatar
Victor committed
39
40
41

## Related papers
- [Topology and habitat assortativity drive neutral and adaptive diversification in spatial graphs](https://www.biorxiv.org/content/10.1101/2021.07.06.451404v2), Boussange et al. 2021.
Victor's avatar
Victor committed
42
43

## Similar packages
Victor's avatar
Victor committed
44
[Agents.jl](https://juliadynamics.github.io/Agents.jl/) is a library oriented towards general ABM modelling, and thus is not as easy to deploy as EvoId.jl for simulating stochastic models of structured populations.
Victor's avatar
Victor committed
45

Victor's avatar
Victor committed
46
47
48
49
## Contributing 
Please feel free to contact me! :)


Victor's avatar
Victor committed
50
-----
Victor's avatar
Victor committed
51
## Tutorial
52
We provide here a tutorial that sums up the 5 steps necessary to launch a simulation. For the sake of the tutorial, we propose to model a population that is structured over the vertices of a graph and characterised by a trait under selection.
Victor's avatar
Victor committed
53

54
### 0. Import the relevant libraries
Victor's avatar
Victor committed
55
Let's import EvoId.jl, and LightGraphs.jl
bvictor's avatar
bvictor committed
56
```julia
Victor's avatar
Victor committed
57
using EvoId
bvictor's avatar
bvictor committed
58
```
Victor's avatar
Victor committed
59

Victor's avatar
Victor committed
60
### 1. Define the evolutionary spaces
61
We define the geographical space as star graph with 7 vertices (i.e. the abstraction of the landscape), and a continuous trait space.
Victor's avatar
Victor committed
62
63
64
65
66
67
68
69
70

```julia
nodes = 7
g = star_graph(nodes)
landscape = GraphSpace(g)
traitspace = RealSpace(1)
evolspace = (landscape,traitspace)
```

Victor's avatar
Victor committed
71
### 2. Define birth and death function
Victor's avatar
Victor committed
72
Birth and death functions depend on individuals position in the combination of spaces defined above, i.e. position on the graph and the adaptive trait.
Victor's avatar
Victor committed
73
74
75
76
77
78
79
We decide that each vertex selects for an optimal trait value $`\theta_i \in \{-1,1\}`$.

```julia
K = 1000 # carrying capacity
θ = [rand([-1,1]) for i in 1:nodes] # optimal trait values
# X[1] is the geographical position
# X[2] corresponds to the adaptive traits
80
81
b(X,t) = max(1 - 0.5 * (θ[X[1]] - X[2])^2,0.)
d(X,Y,t) = (X[1]  Y[1]) / K
Victor's avatar
Victor committed
82
```
83
> :warning: birth and death functions should have the same number of
Victor's avatar
Victor committed
84
85
86
87
arguments as above.

### 3. Define how individuals move over the evolutionary space
Individual movements correspond to migration and mutation processes. On continuous spaces, one should specify a migration range and a migration rate. On discrete spaces, only a migration rate is needed (one assumes that indivuals can migrate only to neighbour patches).
Victor's avatar
Victor committed
88
89

```julia
Victor's avatar
Victor committed
90
91
D = [nothing,5e-1] # movement ranges
mu = [1.,1.] # movement rates
Victor's avatar
Victor committed
92
93
NMax = 2000 # maximum number of individuals allowed
p = Dict("D"=> D, "mu" => mu, "NMax" => NMax) # storing above parameters
Victor's avatar
Victor committed
94
95
```

Victor's avatar
Victor committed
96
97
### 4. Define the initial population state

Victor's avatar
Victor committed
98
```julia
Victor's avatar
Victor committed
99
100
101
102
103
104
105
myagents = [] # array containing the founder individuals
for i in 1:K
    push!(myagents,Agent(evolspace, #evolutionary spaces
                        [rand(1:nodes), # random position on the graph
                        randn() * D[2]]) # random position on the trait space centered around 0
                        )
end
Victor's avatar
Victor committed
106
w0 = World(myagents, evolspace, p) # the initial world, defined at time 0.
Victor's avatar
Victor committed
107
108
```

Victor's avatar
Victor committed
109
### 5. Run
Victor's avatar
Victor committed
110
111
Simulation time, and callback function

Victor's avatar
Victor committed
112
```julia
Victor's avatar
Victor committed
113
tend = 500
Victor's avatar
Victor committed
114
t_saving_cb = collect(range(0.,tend,length=300))
Victor's avatar
Victor committed
115
cb(w) = Dict("N" => size(w))
Victor's avatar
Victor committed
116
117
118
```


Victor's avatar
Victor committed
119
120
121
122
123
124
125
126
And off we go

```julia
sim = run!(w0,
            Gillepsie(), # gillepsie algorithm
            tend,
            b,
            d,
127
            cb = cb,
Victor's avatar
Victor committed
128
129
130
            t_saving_cb = t_saving_cb)
```
### Plotting
Victor's avatar
Victor committed
131
```julia
Victor's avatar
Victor committed
132
using Plots
Victor's avatar
Victor committed
133
plot(sim.tspan, sim["N"])
Victor's avatar
Victor committed
134
135
```

Victor's avatar
Victor committed
136
137
138
![](docs/src/assets/tutorials/delta_comp_wsize.png)

With a few more tricks, one can also plot the population trait density over time, for example the local trait density for individuals living on vertex 1.
Victor's avatar
Victor committed
139

Victor's avatar
Victor committed
140
![](docs/src/assets/ABM_local_trait_dens_adapt.png)
Victor's avatar
Victor committed
141
142

Check out the folder `examples` in the git repo to see this tutorial in a julia file, as well as plenty others!