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

Commit a224d9f1 authored by Victor's avatar Victor
Browse files

updated doc version

parent 984d5441
Pipeline #75176 passed with stage
in 26 minutes and 23 seconds
docs/build docs/build
docs/*.png docs/*.png
docs/uploads docs/uploads
*.jld2
...@@ -63,7 +63,8 @@ mu = [1.] ...@@ -63,7 +63,8 @@ mu = [1.]
D = (1.5,) D = (1.5,)
``` ```
## Running the world ## Running the world
We initialise the world with initial population of size ``K_0 / 9`` located on patch `5`. We keep track of individuals' ancestors by setting `ancestors=true`. Because we wish to use `Gillepsie` algorithm, we need `rates=true` as agents' internal birth and death rates are updated at every time step. We initialise the world with initial population of size ``K_0 / 9`` located on patch `5`. `NMax` corresponds to the maximum number of individuals that can be attained. If attained, then the programm stops.
We keep track of individuals' ancestors by setting `ancestors=true`. Because we wish to use `Gillepsie` algorithm, we need `rates=true` as agents' internal birth and death rates are updated at every time step.
!!! note "Warning" !!! note "Warning"
`rates` treatment is something we might implement in the library internals. `rates` treatment is something we might implement in the library internals.
......
# Modelling agents with a genetic structure # [Modelling agents with a genetic structure](@id genetic_structure)
In this example, we show how to model a population which evolve on a linear geographic space, and is defined by a genotype graph. Any two connected node in the genotype graph should be thought of as two neighbour genomes, i.e that are very similar in their alleles / nucleotide. In this example, we show how to model a population which evolve on a linear geographic space, and is defined by a genotype graph. Any two connected node in the genotype graph should be thought of as two neighbour genomes, i.e that are very similar in their alleles / nucleotide.
...@@ -35,3 +35,9 @@ The genotype space is inspired from the article [The architecture of an empirica ...@@ -35,3 +35,9 @@ The genotype space is inspired from the article [The architecture of an empirica
``` ```
## Plotting ## Plotting
Plotting animations of graphs is a bit involved. If you want to learn about that, consult `src/examples/genetic_structure.jl`.
### Geographical space
![](../assets/tutorials/space_genetic_struct.gif)
### Genetic space
![](../assets/tutorials/animated_gen_space.gif)
...@@ -42,7 +42,7 @@ Here we show how to plot a cool animated scatter plot of the trait space through ...@@ -42,7 +42,7 @@ Here we show how to plot a cool animated scatter plot of the trait space through
``` ```
![](../assets/tutorials/gradient_2Dtrait.gif) ![](../assets/tutorials/gradient_2Dtrait.gif)
## Plotting lineages ## [Plotting lineages](@id lineages)
A cool feature of ABMEv.jl is its ability to track agents ancestors traits (cf [Agent section](../manual/agent.md)) A cool feature of ABMEv.jl is its ability to track agents ancestors traits (cf [Agent section](../manual/agent.md))
On can plot it, to get an idea of the coalescence of the population. On can plot it, to get an idea of the coalescence of the population.
......
...@@ -5,16 +5,22 @@ This script aims at reproducing the 1999 article of Doebeli [On The Origin of Sp ...@@ -5,16 +5,22 @@ This script aims at reproducing the 1999 article of Doebeli [On The Origin of Sp
In this article, birth and death functions are defined as gaussian, with respective variance ``\sigma_b`` and ``\sigma_d``. It is shown that when ``\sigma_d < \sigma_b``, speciation in the trait space occurs. This is what we reproduce here. In this article, birth and death functions are defined as gaussian, with respective variance ``\sigma_b`` and ``\sigma_d``. It is shown that when ``\sigma_d < \sigma_b``, speciation in the trait space occurs. This is what we reproduce here.
## Running the world ## Running the world
![]() We need to run the simulation for a significant amount of time to observe sympatric speciation. As such, we set `ancestors=false`. The rest is pretty standard
```julia
## Plotting lineages myspace = (RealSpace{1,Float64}(),)
A cool feature of ABMEv.jl is its ability to track agents ancestors traits (cf [Agent section](../manual/agent.md)) σ_b = .9;
σ_d = .7;
On can plot it, to get an idea of the coalescence of the population. K0 = 1000
b(X,t) = 1.
![]() d(X,Y,t) = gaussian(X[1],Y[1],σ_d)/K0 / gaussian(X[1],0.,σ_b)
D = (1e-2,)
Beautiful, isn't it? mu = [.1]
NMax = 2000
!!! tip "Making sense of trait histories" tend = 1500
Some metrics are available (cf [Metrics section](../manual/metrics.md)) that summarize the divergence in trait value (or geographical position) through time). p = Dict{String,Any}();@pack! p = d,b,D,mu,NMax
myagents = [Agent(myspace,(1e-2 * randn(),),rates=true) for i in 1:K0]
w0 = World(myagents,myspace,p,0.)
@time sim = run!(w0,Gillepsie(),tend,dt_saving = 10)
Plots.plot(sim, ylabel = "Adaptive trait")
```
![](../assets/tutorials/sympatric_speciation.png)
...@@ -7,9 +7,13 @@ The purpose of this package is to provide a numerical laboratory for evolutionar ...@@ -7,9 +7,13 @@ The purpose of this package is to provide a numerical laboratory for evolutionar
- analysis tools to investigate the simulations. - analysis tools to investigate the simulations.
## Features ## Features
Agents consist of a set of traits in some combination of vector spaces. A vector space can represent for example a geographical landscape, or trait space. Spaces can be of any dimensions, discrete or continuous, bounded or unbounded. They can equally consist of graphs. Agents consist of sets of traits in some combination of vector spaces. A vector 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.
Vector spaces are used to define birth and death processes, as well as mutation processes. Vector spaces are used to define birth and death processes, as well as mutation processes.
### Specificities
- [ABMEv.jl allows to keep track of agents' trait lineages](@ref genetic_structure)
- [ABMEv.jl enables to run evolutionary dynamics on graphs!](@ref lineages)
## Getting started ## Getting started
```@repl ```@repl
using ABMEv using ABMEv
...@@ -22,14 +26,14 @@ Pages = [ ...@@ -22,14 +26,14 @@ Pages = [
"examples/delta_competition_example.md", "examples/delta_competition_example.md",
"examples/changing_environment.md", "examples/changing_environment.md",
"examples/sympatric_speciation.md", "examples/sympatric_speciation.md",
"examples/gradient_establishment.md", "examples/gradient.md",
"examples/genetic_structure.md", "examples/genetic_structure.md",
"" ""
] ]
Depth = 2 Depth = 2
``` ```
## How it works ## How it works
There general workflow to launch any simulation is the following General workflow to launch any simulation is the following
- [Define the combination of vector spaces you are interested in.](manual/space.md) - [Define the combination of vector spaces you are interested in.](manual/space.md)
- Define birth and death function, that depend on agents position in the space - Define birth and death function, that depend on agents position in the space
...@@ -40,9 +44,9 @@ There general workflow to launch any simulation is the following ...@@ -40,9 +44,9 @@ There general workflow to launch any simulation is the following
### Available algorithms ### Available algorithms
As of now, three types of simulation algorithm can be used: As of now, three types of simulation algorithm can be used:
- [Gillepsie](manual/gillepsie.md) - [Gillepsie](manual/gillepsie.md)
- [Wright-Fisher](manual/wright_fisher.md) - [Wright-Fisher](manual/wright_fisher.md)
- [CFM](CFM.md) - [CFM](CFM.md)
## References ## References
- [Champagnat and Ferriere founding article](https://linkinghub.elsevier.com/retrieve/pii/S0040580905001632) - [Champagnat and Ferriere founding article](https://linkinghub.elsevier.com/retrieve/pii/S0040580905001632)
......
...@@ -6,5 +6,30 @@ Indeed, at every time step, only the fitness of the individual picked at random ...@@ -6,5 +6,30 @@ Indeed, at every time step, only the fitness of the individual picked at random
In order to use it, you need to feed to the dictionary parameters `p` a constant `Cbar<:Real` that is the upperbound of the maximum of the sum of the birth and death rates (cf article). In order to use it, you need to feed to the dictionary parameters `p` a constant `Cbar<:Real` that is the upperbound of the maximum of the sum of the birth and death rates (cf article).
## An example on how to use it
```julia
using ABMEv,UnPack,Plots
myspace = (RealSpace{1,Float64}(),)
σ_b = .9;
σ_d = .7;
K0 = 1000
b(X,t) = 1.
d(X,Y,t) = gaussian(X[1],Y[1],σ_d)/K0 / gaussian(X[1],0.,σ_b)
Cbar = b([0],0.) + d([0],[0],0.)
D = (1e-2,)
mu = [.1]
NMax = 2000
tend = 1500
p = Dict{String,Any}();@pack! p = d,b,D,mu,NMax,Cbar
myagents = [Agent(myspace,(1e-2 * randn(),)) for i in 1:K0]
w0 = World(myagents,myspace,p,0.)
@time sim = run!(w0,CFM(),tend,dt_saving = 4)
```
!!! warning "Development" !!! warning "Development"
CFM gives an approximate time step. As of now, we do not manage to obtain qualitatively the same results as the Gillepsie algorithm. CFM gives an approximate time step. As of now, we do not manage to obtain qualitatively the same results as the Gillepsie algorithm.
```@autodocs
Modules = [ABMEv]
Pages = ["algo/ABMEv_CFM.jl"]
```
# Agent properties # Agent properties
## The `Agent` structure ## The `Agent` structure
The atomic structure is the `Agent`. It has four attributes `Agent` is the atomic structure of ABMEv.jl. It has four attributes
- the ancestors' history of traits, and the corresponding time where the traits have changed, - the ancestors' history of traits, and the corresponding time where the traits have changed,
- a death rate and a birth rate. - a death rate and a birth rate.
```julia ```julia
...@@ -16,15 +16,12 @@ mutable struct Agent{A<:Ancestors,R<:Rates,T<:Tuple,U,V} <: AbstractAgent{A,R} ...@@ -16,15 +16,12 @@ mutable struct Agent{A<:Ancestors,R<:Rates,T<:Tuple,U,V} <: AbstractAgent{A,R}
b::V b::V
end end
``` ```
!!! note Specificities !!! note "Specificities"
The type `Agent` has two important composite types The type `Agent` has two important composite types
- `Ancestors{bool}` : when `bool = true`, the ancestors traits are stored, - `Ancestors{bool}` : when `bool = true`, the ancestors traits are stored,
- `Rates{bool}` : when `bool = true`, the rates `d` and `b` of agents are updated at each time step. This is need in e.g. Gillepsie Algorithm - `Rates{bool}` : when `bool = true`, the rates `d` and `b` of agents are updated at each time step. This is need in e.g. Gillepsie Algorithm
#
```@autodocs ```@autodocs
Modules = [ABMEv] Modules = [ABMEv]
Pages = ["ABMEv_Agent.jl"] Pages = ["ABMEv_Agent.jl"]
......
# Plotting # Plotting
ABMEv comes with Plot recipes: ABMEv comes with Plot recipes.
`plot(world::Array{U},p;what=["x","H"],trait = 1) where U <: Union{Missing,Agent{T}} where T`.
An example to use it:
```julia ```julia
using Plots;pyplot() function plot(sim::Simulation;trait = 1)
Plots.plot(worldall,p_default,what=["x"],trait=2)
``` ```
You can specify what you want to plot in the array ```what```:
- ```"x"``` returns a scatter plot `(xaxis = time, yaxis = trait)` . Geotrait corresponds to `trait=0`
- `"xs"` only works for agent type `MixedAgent`, because it needs a discrete geographical space. It returns a scatter plot `(xaxis = geographical component, yaxis = trait value)`. Very similar to a `histogram2d` plot, with nicer look.
- ```"gs"``` returns a scatter plot `(xaxis = geotrait, yaxis = trait value)`
- ```"3dgeo"``` plots a 3d diagram with x axis as geotrait and y axis as the second component. :warning: this is probably weekend
- ```"3d"``` plots a 3d diagram with first and second component as x and y axis
- ```"var"``` plots the variance of the component specified by ```trait=2``` :question: with respect to time?
- ```"vargeo"``` plots the variance of the geotrait
```@autodocs ## Arguments
Modules = [ABMEv] - if `length(trait) == 1` then we scatter plot `trait` along time
Pages = ["ABMEv_plotting.jl"] - if `2 <= length(trait) <= 3` then we project world of the last time step in the two (three) dimensional trait space define by `trait`
```
!!! warning "To be implemented"
We might want to get a 3 dimensional scatter plot
with time, trait1 and trait2 as axis
# Run the World # Run the World
- ```NMax``` Maximum number of individuals that can be attained. If attained, then the programm stops. ```@docs
run!
```
For now three algorithms For now three algorithms
```@docs ```@docs
...@@ -10,7 +11,3 @@ CFM ...@@ -10,7 +11,3 @@ CFM
WF WF
``` ```
> Warning : `WF` not implemented yet > Warning : `WF` not implemented yet
```@autodocs
Modules = [ABMEv]
Pages = ["ABMEv_runworld.jl"]
```
# Space # Space
# Utils
```@autodocs ```@autodocs
Modules = [ABMEv] Modules = [ABMEv]
Pages = ["ABMEv_Space.jl"] Pages = ["ABMEv_Space.jl"]
......
...@@ -4,13 +4,13 @@ myspace = (RealSpace{1,Float16}(),) ...@@ -4,13 +4,13 @@ myspace = (RealSpace{1,Float16}(),)
sigma_K = .9; sigma_K = .9;
sigma_a = .7; sigma_a = .7;
K0 = 5000 K0 = 5000
b(X) = gaussian(X[1],0.,sigma_K) b(X,t) = gaussian(X[1],0.,sigma_K)
d(X,Y) = gaussian(X[1],Y[1],sigma_a)/K0 d(X,Y,t) = gaussian(X[1],Y[1],sigma_a)/K0
D = (Float16(1e-1),) D = (Float16(1e-1),)
mu = [1.] mu = [1.]
NMax = 7000 NMax = 7000
tend = 50 tend = 50
Cbar= b([0]) + d([0],[0]) Cbar= b([0],0.) + d([0],[0],0.)
p = Dict{String,Any}();@pack! p = d,b,D,mu,NMax,Cbar p = Dict{String,Any}();@pack! p = d,b,D,mu,NMax,Cbar
# myagents = [Agent(myspace,(- Float16(0.5) .+ .01 .* randn(Float16),)) for i in 1:K0] # myagents = [Agent(myspace,(- Float16(0.5) .+ .01 .* randn(Float16),)) for i in 1:K0]
myagents = [Agent(myspace,(0.,)) for i in 1:K0] myagents = [Agent(myspace,(0.,)) for i in 1:K0]
......
using ABMEv,UnPack using ABMEv,LightGraphs,UnPack
##### Genotype space##### ##### Genotype space#####
nodes = 9
dim_neutr = 1000 dim_neutr = 1000
magicprop = 523728 / 32896 magicprop = 523728 / 32896
g = SimpleGraph{Int16}(dim_neutr,round(Int16,dim_neutr * magicprop)) g = SimpleGraph{Int16}(dim_neutr,round(Int16,dim_neutr * magicprop))
...@@ -11,20 +12,20 @@ K0 = 1000 ...@@ -11,20 +12,20 @@ K0 = 1000
mu = [1.,1.] mu = [1.,1.]
b(X,t) = 1 / nodes b(X,t) = 1 / nodes
d(X,Y,t) = (X[1] Y[1]) / K0 d(X,Y,t) = (X[1] Y[1]) / K0
D = (5e-1,1.4825) D = (3e-1,5e-1)
NMax = 2000 NMax = 2000
# tend = 1.5 # tend = 1.5
tend = 100 tend = 200
p_default = Dict{String,Any}();@pack! p_default = d,b,NMax,mu,D p_default = Dict{String,Any}();@pack! p_default = d,b,NMax,mu,D
myagents = [Agent(myspace,(rand(Int8(1):Int8(nodes)),initnode),ancestors=true,rates=true) for i in 1:round(K0/nodes)] myagents = [Agent(myspace,(Int8(5),initnode),ancestors=true,rates=true) for i in 1:round(K0/nodes)]
w0 = World(myagents,myspace,p_default,0.) w0 = World(myagents,myspace,p_default,0.)
@time sim = run!(w0,Gillepsie(),tend,dt_saving=3.) @time sim = run!(w0,Gillepsie(),tend,dt_saving=3.)
using GraphPlot,StatsBase using GraphPlot,StatsBase
# Plotting genetic space ## Plotting genetic space
# This is to plot with consistency # This is to plot with consistency
locs_x, locs_y = spring_layout(g) locs_x, locs_y = spring_layout(g)
xarray,tspan = get_xnt(sim, trait=2) xarray,tspan = get_xnt(sim, trait=2)
...@@ -37,11 +38,49 @@ for x in xarray ...@@ -37,11 +38,49 @@ for x in xarray
push!(d_i,_d_i) push!(d_i,_d_i)
end end
# Here we normalize with respect to the max size of the whole world through time # Here we normalize with respect to the max size of the whole world through time
d_i = [ (_d_i .- minimum(_d_i)) ./ (maximum(_d_i) .- minimum(_d_i)) for _d_i in d_i ]anim = @animate for t in 1:size(worldall,2) d_i = [ (_d_i .- minimum(_d_i)) ./ (maximum(_d_i) .- minimum(_d_i)) for _d_i in d_i ]
Plots.plot(worldall,p_default,what=["gs"],trait=2,tplot=t, using Printf,Cairo,Compose
title = @sprintf(" t = %1.2f",p_default["tspan"][t]), for i in 1:length(d_i)
ylims = (1,p_default["nodes"]), gp =gplot(g,locs_x,locs_y,
xlims = (0,maximum(xgeo)) nodefillc=eth_grad_std[d_i][i])
) draw(PNG(joinpath(@__DIR__,"gen_struct/gif_genetic_structure_$i.png"), 16cm, 16cm), gp)
end
gif(anim,"gif_d2=$(p_default["D"][2])_d1=$(p_default["D"][1])_tend=$(p_default["tend"])_mu=1e0_1e0.gif",fps = 13) # Plots.plot(xarray,p_default,what=["gs"],trait=2,tplot=t,
# title = @sprintf(" t = %1.2f",p_default["tspan"][t]),
# ylims = (1,p_default["nodes"]),
# xlims = (0,maximum(xgeo))
# )
end
## Plotting spatial space
using Plots
# This is to plot with consistency
xarray,tspan = get_xnt(sim, trait=1)
# here we compute the number of individuals per genome, throught all the time steps
d_i = []
for x in xarray
_d_i = zeros(nv(g))
c = countmap(x)
_d_i[collect(keys(c))] .= values(c)
push!(d_i,_d_i)
end
# Here we normalize with respect to the max size of the whole world through time
d_i = [ (_d_i .- minimum(_d_i)) ./ (maximum(_d_i) .- minimum(_d_i)) for _d_i in d_i ]
anim = @animate for i in 1:length(d_i)
Plots.scatter(collect(1:nodes),ones(nodes),
markercolor=ABMEv.eth_grad_small[d_i][i],
markersize = 40,
grid = false,
xaxis = false,
yaxis = false,
label = "",
markerstrokewidth = 0.,
ylims = (-8,10),
xlims = (0,10)
)
# Plots.plot(xarray,p_default,what=["gs"],trait=2,tplot=t,
# title = @sprintf(" t = %1.2f",p_default["tspan"][t]),
# ylims = (1,p_default["nodes"]),
# xlims = (0,maximum(xgeo))
# )
end
gif(anim,joinpath(@__DIR__, "space_genetic_struct.gif"),fps = 13)
using Revise,ABMEv,Plots,UnPack
nodes = 9
dim_neutr = 30
geospace = DiscreteSegment(Int8(1),Int8(nodes))
adaptivespace = RealSpace{1,Float16}()
myspace = (geospace,adaptivespace)
sigma_K = 1.;
sigma_a = .8;
K0 = 1000;
mu = [1.,1.]
a = 1
b(X,t) = gaussian(X[2],X[1] * a,sigma_K) / nodes
d(X,Y,t) = (X[1] Y[1]) * gaussian(X[2],Y[2],sigma_a) / K0
NMax = 2000
D = (5e-1,5e-2)
# tend = 1.5
tend = 1500
p = Dict{String,Any}();@pack! p = d,b,NMax,mu,D
myagents = [Agent(myspace,(Int8(5),Float16(5) + Float16(5e-2) * randn(Float16),),ancestors=true,rates=true) for i in 1:round(K0/nodes)]
w0 = World(myagents,myspace,p,0.)
s = run!(w0,Gillepsie(),tend,dt_saving=5);
Plots.plot(s, ylabel = "Adaptive trait",trait=2)
savefig(joinpath(@__DIR__, "gradient_adaptive_trait.png"))
using Printf
anim = @animate for i in 1:get_size(s)
Plots.plot(s, ylabel = "Adaptive trait",
trait=(1,2),
time=i,
xaxis = "Position",
yaxis = "Adaptive trait",
title = @sprintf(" t = %1.2f",s.tspan[i]),
ylims = (0,11),
xlims = (1,11))
end
gif(anim,joinpath(@__DIR__, "gradient_2Dtrait.gif"),fps = 13)
world = get_world(s,get_size(s))
shistall = get_xhist.(world[:],2)
thist = get_thist.(world[:])
aplot = Plots.plot(thist,shistall,
linecolor = eth_grad_std[0.],
label = "",
# title = latexstring("\\sigma_\\mu=",@sprintf("%1.2f",world.p["D"][2]),", \\sigma_D=",@sprintf("%1.2f",world.p["D"][1])),
grid = false,
xlabel = "time",
ylabel = "Lineages adaptive trait",
ylims = (-0.5,10.5)
)
savefig(aplot,joinpath(@__DIR__, "gradient_lineages_adaptive_trait.png"))
# Plotting lineages
using Revise
using ABMEv,UnPack,Plots
myspace = (RealSpace{1,Float64}(),)
σ_b = .9;
σ_d = .7;
K0 = 1000
b(X,t) = 1.
d(X,Y,t) = gaussian(X[1],Y[1],σ_d)/K0 / gaussian(X[1],0.,σ_b)
Cbar = b([0],0.) + d([0],[0],0.)
D = (1e-2,)
mu = [.1]
NMax = 2000
tend = 1500
p = Dict{String,Any}();@pack! p = d,b,D,mu,NMax,Cbar
myagents = [Agent(myspace,(1e-2 * randn(),)) for i in 1:K0]
w0 = World(myagents,myspace,p,0.)
@time sim = run!(w0,CFM(),tend,dt_saving = 4)
using JLD2
@save joinpath(@__DIR__,"sim_sympatric_speciation_CFM.jld2") sim
Plots.plot(sim, ylabel = "Adaptive trait")
savefig(joinpath(@__DIR__, "sympatric_speciation_CFM.png"))
# plotting lineages
world = get_world(sim,get_size(sim))
xhistall = get_xhist.(world[:],1)
thist = get_thist.(world[:])
xplot = Plots.plot(thist,xhistall,
linecolor = eth_grad_std[0.],
label = "",
# title = latexstring("\\sigma_\\mu=",@sprintf("%1.2f",world.p["D"][2][1]),", \\sigma_D=",@sprintf("%1.2f",world.p["D"][1])),
grid = false,
xlabel = "time",
ylabel = "Historical adaptive trait"
)
savefig(joinpath(@__DIR__, "x_hist_sympatric_speciation_CFM.png"))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment