Commit bcbc425f authored by Victor's avatar Victor
Browse files

update docs tuts

parent 56d7ada2
Pipeline #75086 passed with stage
in 24 minutes and 10 seconds
......@@ -6,7 +6,7 @@ In this script, we model the evolution of a population where agents are simply d
Let's start by a linear landscape. We define a discrete segment of length `9`, with reflecting boundary conditions. In fact, reflecting boundary conditions are implemented for any finite space.
!!! warning "1D Reflections"
As of v1, only reflections on one dimensional space are implemented. We have a two dimensional reflection method that will be released in the future.
As of v1, only reflections on one dimensional space are implemented. We have a two dimensional reflection method that will be released in the future.
There are two ways of implementing a linear landscape. The first one uses a `DiscreteSegment` while the second relies on LightGraphs.jl library. Both are *almost* equivalent.
......@@ -15,6 +15,7 @@ There are two ways of implementing a linear landscape. The first one uses a `Dis
using ABMEv
nodes = 10
mysegment = DiscreteSegment(1,nodes)
wholespace = (mysegment,)
```
### grid
......@@ -23,12 +24,15 @@ using ABMEv, LightGraphs
nodes = 10
g = grid([nodes,1])
mysegmentgraph = GraphSpace(g)
wholespace = (mysegmentgraph,)
```
!!! warning "Space tuple"
Notice that the whole space should be a *tuple of spaces*. Even where there is only one sub vector space as here, you need to have brackets and comma around the unit vector space.
Here is how you can visualise the landscape.
```julia
using GraphPlots
gplot(g,locs_x = 1:nodes,locs_y=1:nodes)
using GraphPlot
gplot(g, collect(1:nodes), collect(1:nodes))
```
## Defining competition processes
......@@ -49,6 +53,9 @@ d(X,Y,t) = (X[1] ≈ Y[1]) / K0
```
At equilibrium, population size in each deme will reach `K0 / nodes`.
!!! warning "Time dependency"
Even though time is not used, you have to write birth and death functions with time dependency.
## Dispersal
We assume that anytime an offspring is born, it is given a chance to move (`\mu = 1`).
```julia
......@@ -58,31 +65,52 @@ D = (1.5,)
## 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.
!!! note "Warning"
`rates` treatment is something we might implement in the library internals.
`rates` treatment is something we might implement in the library internals.
```julia
using UnPack# useful macro @pack!
NMax = 2000
tend = 2
tend = 300.
p = Dict{String,Any}();@pack! p = d,b,D,mu,NMax
myagents = [Agent(myspace,(5,),ancestors=true,rates=true) for i in 1:K0/nodes]
w0 = World(myagents,myspace,p,0.)
@time sim = run!(w0,Gillepsie(),tend)
```
This is the simplest run you can do. Now time to more interesting things
## Analysis
### Size of the world
Let's verify that the population's growth is logistic. We will plot the population size over time.
To do so, one need to define `dt_saving`.
To do so, one need to define `dt_saving` < `tend` to save every `dt_saving` time steps of the world.
```julia
myagents = [Agent(wholespace,(5,),ancestors=true,rates=true) for i in 1:K0/nodes]
w0 = World(myagents,wholespace,p,0.) # we need to reinitialise the world
@time sim = run!(w0,Gillepsie(),tend,dt_saving=2.)
wsize = [length(w) for w in sim[:]]
using Plots
@time sim = run!(w0,Gillepsie(),tend,dt_saving=1)
Plots.plot()
@animate for (i,t) in tspan(sim)
Plots.
end
Plots.plot(get_tspan(sim),wsize,
label = "",
ylabel = "Metapopulation size",
xlabel ="time",
grid = false)
```
![](tutorials/delta_comp_wsize.png)
One might be tempted to plot the world for some time steps. This requires some knowledge of the library Plots.jl.
Agents values are accessed by `get_x(w::World)`.
!!! notes "Callbacks"
Note that one could also use a callback function to obtain time series of size of the world computed at simulation time. See [Simulation page](../manual/simulation.md).
!!! notes "Plotting"
This will be proposed as a blackbox with PlotRecipes.jl in the near future
### Position through time
One might be tempted to plot the agents position for some time steps.
```julia
Plots.plot(sim,
label = "",
ylabel = "Geographical position",
grid = false,
markersize = 10)
```
![](tutorials/delta_comp_pos.png)
using Revise,ABMEv
nodes = 10
mysegment = DiscreteSegment(1,nodes)
using ABMEv, LightGraphs
nodes = 10
g = grid([nodes,1])
mysegmentgraph = GraphSpace(g)
wholespace = (mysegmentgraph,)
using GraphPlot
gplot(g, collect(1:nodes), collect(1:nodes))
K0 = 1000 # We will have in total 1000 individuals
b(X,t) = 1 / nodes
d(X,Y,t) = (X[1] Y[1]) / K0
mu = [1.]
D = (1.5,)
using UnPack
NMax = 2000
tend = 300.
p = Dict{String,Any}();@pack! p = d,b,D,mu,NMax
myagents = [Agent(wholespace,(5,),ancestors=true,rates=true) for i in 1:K0/nodes]
w0 = World(myagents,wholespace,p,0.)
@time sim = run!(w0,Gillepsie(),tend)
### Plotting size of the world
myagents = [Agent(wholespace,(5,),ancestors=true,rates=true) for i in 1:K0/nodes]
w0 = World(myagents,wholespace,p,0.) # we need to reinitialise the world
@time sim = run!(w0,Gillepsie(),tend,dt_saving=2.)
wsize = [length(w) for w in sim[:]]
using Plots
Plots.plot(get_tspan(sim),wsize,
label = "",
ylabel = "Metapopulation size",
xlabel ="time",
grid = false)
savefig(joinpath(@__DIR__, "delta_comp_wsize.png"))
## plotting position through time
using Plots
Plots.plot(sim,
label = "",
ylabel = "Geographical position",
grid = false,
markersize = 10)
savefig(joinpath(@__DIR__, "delta_comp_pos.png"))
......@@ -54,7 +54,7 @@ function add_entry!(s::Simulation{A,S,T,F},w::World) where {A,S,T,F}
end
#TODO : code it
function get_xnt(s::Simulation;trait = i)
function get_xnt(s::Simulation;trait = 1)
return [getindex.(wa,trait) for wa in s.agentarray],[fill(t,size(s[j])) for (j,t) in enumerate(s.tspan)]
end
# get_x(agentarray::Array{T},t,trait::Integer) where {T <: AbstractAgent} = reshape(hcat(get_x.(agentarray,t,trait)),size(agentarray,1),size(agentarray,2))
......
......@@ -2,101 +2,48 @@ using RecipesBase
using Colors
import KernelDensity:kde,pdf
"""
function plot(world::Array{U},p;what=["x","H"],trait = 1,tplot = false) where U <: Union{Missing,Agent}
function plot(sim::Simulation;trait = 1)
Plot recipe for ABMEv.jl
# ARGS
- `what = ["x","H"]`: the plots you want to obtain
- `trait = 1`: the trait that will plotted regarding what you asked. `trait = 0` will plot the geotrait
- `tplot = 0` used when calling xs, as it plots a snapshot of the world at a particular time
It should correspond to an integer, as it indexes the column to plot
- if `length(trait) == 1` then we scatter plot `trait` along time
- if `2 <= length(trait) <= 3` then we project world of the
last time step in the two (three) dimensional trait space define by `trait`
# Options available
- `"x"`
- `"xs"`
!!! warning "To be implemented"
We might want to get a 3 dimensional scatter plot
with time, trait1 and trait2 as axis
"""
@recipe function plot(sim::Simulation;what=["x","H"],trait = 1,tplot = 0)
world = sim.agentarray
tot_dim = size(world,2)*size(world,1)
tspan = sim.tspan
p = sim.p
# We reduce time interval if it is too big
# if tot_dim > 1e6 && size(world,2) >= 200
# p = copy(p)
# idx_reduced = floor.(Int,range(1,size(world,2),length = 200))
# p["tspan" ] = tspan[idx_reduced]
# world = world[:,idx_reduced]
# end
# second condition is to make sure that the world corresponds to all the time steps
# If not, then we can not get "x"
if count(ismissing,world) > 0 && length(tspan) == size(world,2)
tspan_ar = vcat([tspan[i]*ones(Int(p["NMax"] - count(ismissing,world[:,i]))) for i in 1:length(tspan) ]...);
else
tspan_ar = repeat(tspan,inner = size(world,1))
end
# tspan = Float64.(tspan)
tend = tspan[tplot > 0 ? tplot : length(tspan)]
world_sm = clean_world(world)
if "x" in what
@recipe function plot(sim::Simulation;trait = 1,time = nothing)
# world = sim.agentarray
# tspan = sim.tspan
# p = sim.p
if length(trait) == 1
xarray,tspan = get_xnt(sim, trait=trait)
d_i = []
for i in 1:length(tspan)
x = get_x.(clean_world(world[:,i]),tspan[i],trait)[:]
append!(d_i,pdf(kde(x),x))
for x in xarray
push!(d_i,pdf(kde(x),x))
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 ]
@series begin
if length(world_sm) !== length(tspan_ar[:])
throw(DimensionMismatch("You want to plot a world with missing data"))
end
xarray = get_x.(world_sm,tspan_ar[:],trait)
seriestype := :scatter
markercolor := eth_grad_small[d_i ./ maximum(d_i)]
markercolor := eth_grad_std[vcat(d_i...)]
markerstrokewidth := 0
seriesalpha :=1.
seriesalpha := .2
# xlabel := "time"
# ylabel := "trait value"
label := ""
xlabel := "time"
grid := false
# markersize := 2.3/1000*size(world_sm,1)
tspan_ar[:],xarray[:]
vcat(tspan...),vcat(xarray...)
end
end
# we use this for discrete agents
# world should be a one dimensional vector, corresponding to one time step only
# if "xs" in what
# d_i = []; xt_array = []; x1_array = []
# world_df_all = world2df(clean_world(world[:, tplot > 0 ? tplot : size(world,2) ]),tend,true)
# world_df_g = groupby(world_df_all,:x1)
# for world_df in world_df_g
# if trait == 0
# x = Float64.(world_df.g)
# else
# # fitness occupies first spot
# x = world_df[:,trait+1] ;
# end
# x1 = world_df.x1;
# append!(d_i,pdf(kde(x),x))
# append!(xt_array,x)
# append!(x1_array,x1)
# end
# @series begin
# seriestype := :scatter
# markercolor := eth_grad_small[d_i ./ maximum(d_i)]
# # markercolor := :blue
# markerstrokewidth := 0
# # seriesalpha := 1.
# xaxis := "geographical position"
# xticks := sort!(unique(world_df_all.x1))
# yaxis := "trait value"
# label := ""
# grid := false
# # marker := (:rect,20,1.)
# x1_array[:],xt_array[:]
# end
# end
if "gs" in what
_world = clean_world(world[:, tplot > 0 ? tplot : length(tspan) ])
y = get_x(_world,tend,2)[:]
x = get_x(_world,tend,0)[:]
if length(trait) == 2
isnothing(time) ? w = get_world(sim[end]) : w = get_world(sim[time])
y = get_x(w,trait[1]);
x=get_x(w,trait[2])
X = hcat(x,y)
d = kde(X)
# by density
......@@ -119,100 +66,9 @@ It should correspond to an integer, as it indexes the column to plot
x,y
end
end
if "3dgeo" in what
d_i = []
for i in 1:size(world,2)
_world = clean_world(world[:,i])
x = get_x(_world,tspan[i],2)[:]
y = get_x(_world,tspan[i],0)[:]
X = hcat(x,y)
# d = kde(X)
# di_temp = diag(pdf(d,X[:,1],X[:,2]))
di_temp = y
di_temp = (di_temp .- minimum(di_temp)) ./ (maximum(di_temp) .- minimum(di_temp))
# here we normalise with respect to maximum value at each time step
append!(d_i,di_temp)
end
@series begin
xarray = get_geo.(world_sm,tspan_ar)
yarray = get_x(world_sm,2)
seriestype := :scatter3d
markercolor := eth_grad_std[d_i ./ 1.]
markerstrokewidth := 0
seriesalpha :=.1
xlabel := "time"
ylabel := "geotrait"
zlabel := "trait value"
label := ""
# markersize := 2.3/1000*size(world_sm,1)
tspan_ar,xarray[:],yarray[:]
end
end
if "3d" in what
d_i = []
for i in 1:size(world,2)
x = get_x(clean_world(world[:,i]),tspan[i],1)[:]
y = get_x(clean_world(world[:,i]),tspan[i],2)[:]
X = hcat(x,y)
d = kde(X)
di_temp = diag(pdf(d,X[:,1],X[:,2]))
di_temp = (di_temp .- minimum(di_temp)) ./ (maximum(di_temp) .- minimum(di_temp))
append!(d_i,di_temp)
end
@series begin
xarray = get_x(world_sm,1)
yarray = get_x(world_sm,2)
seriestype := :scatter3d
markercolor := eth_grad_small[d_i ./ maximum(d_i)]
markerstrokewidth := 0
seriesalpha :=.1
xlabel := "time"
ylabel := "position"
zlabel := "trait value"
label := ""
# markersize := 2.3/1000*size(world_sm,1)
tspan_ar,xarray[:],yarray[:]
end
end
# if "H" in what
# @series begin
# x = get_x.(world_sm,trait)
# linewidth := 2
# seriestype := :line
# label := "Interconnectedness"
# tspan,N^2 / 2 .* [H_discrete(x[:,i]) for i in tspan]
# end
# end
if "var" in what
@series begin
linewidth := 2
seriestype := :line
label := "Variance"
xlabel := "Time"
ylabel := "Variance"
tspan,var(world_sm,trait=trait)[:]
end
if length(trait) == 2
throw(ArgumentError("Plot for three traits not yet implemented"))
end
if "vargeo" in what
@series begin
linewidth := 2
seriestype := :line
label := "Variance of geotrait"
xlabel := "Time"
ylabel := "Variance"
tspan,i->first(covgeo(world_sm[:,Int(i)]))
end
end
# if "density_t" in what
# @series begin
# linewidth := 2
# seriestype := :plot3d
# label := "Variance of geotrait"
# xlabel := "Time"
# ylabel := "Variance"
# tspan,i->first(covgeo(world_sm[:,Int(i)]))
# end
# end
end
......@@ -221,3 +77,137 @@ import Plots:cgrad
const eth_grad_small = cgrad([colorant"#1F407A", RGB(0.671,0.851,0.914),RGB(1.0,1.0,0.749), RGB(0.992,0.682,0.38),RGB(0.647,0.0,0.149),],[.0,.1])
# symmetry between red and blue
const eth_grad_std = cgrad([colorant"#1F407A", RGB(0.671,0.851,0.914),RGB(1.0,1.0,0.749), RGB(0.992,0.682,0.38),RGB(0.647,0.0,0.149),],[.0,1.])
########## OLD PLOT RECIPES ##############
# To get some inspiration
# we use this for discrete agents
# world should be a one dimensional vector, corresponding to one time step only
# if "xs" in what
# d_i = []; xt_array = []; x1_array = []
# world_df_all = world2df(clean_world(world[:, tplot > 0 ? tplot : size(world,2) ]),tend,true)
# world_df_g = groupby(world_df_all,:x1)
# for world_df in world_df_g
# if trait == 0
# x = Float64.(world_df.g)
# else
# # fitness occupies first spot
# x = world_df[:,trait+1] ;
# end
# x1 = world_df.x1;
# append!(d_i,pdf(kde(x),x))
# append!(xt_array,x)
# append!(x1_array,x1)
# end
# @series begin
# seriestype := :scatter
# markercolor := eth_grad_small[d_i ./ maximum(d_i)]
# # markercolor := :blue
# markerstrokewidth := 0
# # seriesalpha := 1.
# xaxis := "geographical position"
# xticks := sort!(unique(world_df_all.x1))
# yaxis := "trait value"
# label := ""
# grid := false
# # marker := (:rect,20,1.)
# x1_array[:],xt_array[:]
# end
# end
##
# if "3dgeo" in what
# d_i = []
# for i in 1:size(world,2)
# _world = clean_world(world[:,i])
# x = get_x(_world,tspan[i],2)[:]
# y = get_x(_world,tspan[i],0)[:]
# X = hcat(x,y)
# # d = kde(X)
# # di_temp = diag(pdf(d,X[:,1],X[:,2]))
# di_temp = y
# di_temp = (di_temp .- minimum(di_temp)) ./ (maximum(di_temp) .- minimum(di_temp))
# # here we normalise with respect to maximum value at each time step
# append!(d_i,di_temp)
# end
# @series begin
# xarray = get_geo.(world_sm,tspan_ar)
# yarray = get_x(world_sm,2)
# seriestype := :scatter3d
# markercolor := eth_grad_std[d_i ./ 1.]
# markerstrokewidth := 0
# seriesalpha :=.1
# xlabel := "time"
# ylabel := "geotrait"
# zlabel := "trait value"
# label := ""
# # markersize := 2.3/1000*size(world_sm,1)
# tspan_ar,xarray[:],yarray[:]
# end
# end
# if "3d" in what
# d_i = []
# for i in 1:size(world,2)
# x = get_x(clean_world(world[:,i]),tspan[i],1)[:]
# y = get_x(clean_world(world[:,i]),tspan[i],2)[:]
# X = hcat(x,y)
# d = kde(X)
# di_temp = diag(pdf(d,X[:,1],X[:,2]))
# di_temp = (di_temp .- minimum(di_temp)) ./ (maximum(di_temp) .- minimum(di_temp))
# append!(d_i,di_temp)
# end
# @series begin
# xarray = get_x(world_sm,1)
# yarray = get_x(world_sm,2)
# seriestype := :scatter3d
# markercolor := eth_grad_small[d_i ./ maximum(d_i)]
# markerstrokewidth := 0
# seriesalpha :=.1
# xlabel := "time"
# ylabel := "position"
# zlabel := "trait value"
# label := ""
# # markersize := 2.3/1000*size(world_sm,1)
# tspan_ar,xarray[:],yarray[:]
# end
# end
# if "H" in what
# @series begin
# x = get_x.(world_sm,trait)
# linewidth := 2
# seriestype := :line
# label := "Interconnectedness"
# tspan,N^2 / 2 .* [H_discrete(x[:,i]) for i in tspan]
# end
# end
# if "var" in what
# @series begin
# linewidth := 2
# seriestype := :line
# label := "Variance"
# xlabel := "Time"
# ylabel := "Variance"
# tspan,var(world_sm,trait=trait)[:]
# end
# end
# if "vargeo" in what
# @series begin
# linewidth := 2
# seriestype := :line
# label := "Variance of geotrait"
# xlabel := "Time"
# ylabel := "Variance"
# tspan,i->first(covgeo(world_sm[:,Int(i)]))
# end
# end
# if "density_t" in what
# @series begin
# linewidth := 2
# seriestype := :plot3d
# label := "Variance of geotrait"
# xlabel := "Time"
# ylabel := "Variance"
# tspan,i->first(covgeo(world_sm[:,Int(i)]))
# end
# end
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