Commit a224d9f1 by Victor

### updated doc version

parent 984d5441
Pipeline #75176 passed with stage
in 26 minutes and 23 seconds

2.97 MB

231 KB

113 KB

 ... @@ -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)