Skip to content

Commit

Permalink
Merge pull request #29 from kavir1698/new_ui
Browse files Browse the repository at this point in the history
New UI
  • Loading branch information
kavir1698 authored Aug 27, 2022
2 parents baadd4b + 8578da8 commit caa3bce
Show file tree
Hide file tree
Showing 20 changed files with 574 additions and 649 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "EvoDynamics"
uuid = "c8768967-421d-4a02-8523-37736f3dbe06"
authors = ["Ali R. Vahdati <[email protected]>", "Carlos Melian"]
version = "0.13.0"
version = "0.14.0"

[deps]
Agents = "46ada45e-f475-11e8-01d0-f70cc89e6671"
Expand Down
45 changes: 22 additions & 23 deletions docs/src/model_description.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@
Each species should have the following parameters. The order that you write these parameters does not matter.

* __name__: a name for the species.
* __number of genes__: An _integer_ for number of genes that the species has.
* __number\_of\_genes__: An _integer_ for number of genes that the species has.
* __ploidy__: Either 1 for haploid or 2 for diploid genomes. Diploids can have recombination.
* __number of phenotypes__: An _integer_ for the number of phenotypes that the species has.
* __abiotic phenotypes__: An _array of integers_ (e.g. "[1,2]") specifying abiotic phenotypes among all phenotypes. Abiotic phenotypes determine how the species interacts with the environment.
* __biotic phenotypes__: An _array of integers_ (e.g. "[3]") specifying biotic phenotypes among all phenotypes. Biotic phenotypes determine how the species interacts with other individuals from the same or different species.
* __migration phenotype__: An _integer_ specifying the phenotype that determines migration trait. If the species does not migrate, put 0.
* __migration threshold__: The phenotypic value of the migration phenotype after which an individual can migrate.
* __vision radius__: A _number_ determining the radius of neighboring sites that the agent can see before migration.
* __check fraction__: A _number_ between 0 and 1 showing the fraction of the visible sites to the agent that it can check and decide whether to migrate to.
* __epistasis matrix__: An epistasis matrix is of size $l \times l$, where _l_ is the product of _number of genes_ and _ploidy_. Epistasis matrix specifies the direction (positive or negative) and size of effect of one locus on other loci. For example, if at row 1 and column 2 is a value 0.2, it means that locus 1 affects locus 2 by increasing the effect of locus 2 (because its positive) with 20% of the effect of locus 1.
* __pleiotropy matrix__: A _binary matrix_ (0s and 1s) with size _number of phenotypes_ times _l_. The pleiotropy matrix specifies the phenotypes that each locus affects.
* __expression array__: A _vector_ of size _l_ that represent the expression amount of each locus determining its effect size.
* __growth rate__: Mean of a Poisson distribution for number of offsprings per reproduction. This number is the maximum mean when fitness of a haploid individual is 1, or the distance between the biotic phenotypes of two diploid individuals is 0.
* __selection coefficient__: A number between 0 and 1 that determines the importance of fitness. 0 would be a model without selection.
* __mutation probabilities__: A _vector of three numbers_ each of which specifies the probability for a different type of mutations: mutation probability of the _expression array_, _pleiotropy matrix_, and _epistasis matrix_, respectively.
* __mutation magnitudes__: A _vector of numbers_ with the same size as _mutation probabilities_ that determines the magnitude of mutation for each of the three categories. Specifically, the numbers are the variances of normal distributions with mean 0 for expression array and epistasis matrices, and probability of changing a 0 and 1 in in the pleiotropy matrix.
* __number\_of\_phenotypes__: An _integer_ for the number of phenotypes that the species has.
* __abiotic\_phenotypes__: An _array of integers_ (e.g. "[1,2]") specifying abiotic phenotypes among all phenotypes. Abiotic phenotypes determine how the species interacts with the environment.
* __biotic\_phenotypes__: An _array of integers_ (e.g. "[3]") specifying biotic phenotypes among all phenotypes. Biotic phenotypes determine how the species interacts with other individuals from the same or different species.
* __migration\_phenotype__: An _integer_ specifying the phenotype that determines migration trait. If the species does not migrate, put 0.
* __migration\_threshold__: The phenotypic value of the migration phenotype after which an individual can migrate.
* __vision\_radius__: A _number_ determining the radius of neighboring sites that the agent can see before migration.
* __check\_fraction__: A _number_ between 0 and 1 showing the fraction of the visible sites to the agent that it can check and decide whether to migrate to.
* __epistasis\_matrix__: An epistasis matrix is of size $l \times l$, where _l_ is the product of _number of genes_ and _ploidy_. Epistasis matrix specifies the direction (positive or negative) and size of effect of one locus on other loci. For example, if at row 1 and column 2 is a value 0.2, it means that locus 1 affects locus 2 by increasing the effect of locus 2 (because its positive) with 20% of the effect of locus 1.
* __pleiotropy\_matrix__: A _binary matrix_ (0s and 1s) with size _number of phenotypes_ times _l_. The pleiotropy matrix specifies the phenotypes that each locus affects.
* __expression\_array__: A _vector_ of size _l_ that represent the expression amount of each locus determining its effect size.
* __growth\_rate__: Mean of a Poisson distribution for number of offsprings per reproduction. This number is the maximum mean when fitness of a haploid individual is 1, or the distance between the biotic phenotypes of two diploid individuals is 0.
* __selection\_coefficient__: A number between 0 and 1 that determines the importance of fitness. 0 would be a model without selection.
* __mutation\_probabilities__: A _vector of three numbers_ each of which specifies the probability for a different type of mutations: mutation probability of the _expression array_, _pleiotropy matrix_, and _epistasis matrix_, respectively.
* __mutation\_magnitudes__: A _vector of numbers_ with the same size as _mutation probabilities_ that determines the magnitude of mutation for each of the three categories. Specifically, the numbers are the variances of normal distributions with mean 0 for expression array and epistasis matrices, and probability of changing a 0 and 1 in in the pleiotropy matrix.
* __N__: A _vector of integers_ for the initial number of individuals at each site.
* __environmental noise__: A number for the variance of a normal distribution with mean 0 that will be added to the phenotypes.
* __optimal phenotypes__: Name of a function that returns a _vector of integers_ for optimal phenotypes of the species at a specific site. The vector should be as long as there are `abiotic phenotypes`. The function should have two arguments: `site `of type `Tuple{Int, Int}`and `model `of type `ABM `from the `Agents.jl `package. The definition of the function should be in a file referred to in the `functions file` parameter (see blow). This function can be time dependent.
* __environmental\_noise__: A number for the variance of a normal distribution with mean 0 that will be added to the phenotypes.
* __optimal\_phenotypes__: Name of a function that returns a _vector of integers_ for optimal phenotypes of the species at a specific site. The vector should be as long as there are `abiotic phenotypes`. The function should have two arguments: `site `of type `Tuple{Int, Int}`and `model `of type `ABM `from the `Agents.jl `package. The definition of the function should be in a file referred to in the `functions file` parameter (see blow). This function can be time dependent.
* __age__: An _integer_ for maximum age of individuals of this species.
* __reproduction start age__: The age at which individuals can reproduce.
* __reproduction end age__: The age after which individuals cannot reproduce.
* __reproduction\_start\_age__: The age at which individuals can reproduce.
* __reproduction\_end\_age__: The age after which individuals cannot reproduce.
* __recombination__: Mean of a Poisson distributions for number of crossing overs per sexual reproduction.
* __initial energy__: A parameter for parental care of infants. Values more than 0 indicate that newly born individuals can survive for a number of times without requiring food from the environment/other species. The consumption rate (i.e. how many generations this initial energy suffices) is determined by the sum of the corresponding rows in "food sources" model parameter.
* __bottleneck function__: Name of a function in `functions file` that accepts two arguments: `agent` and `model`. It returns true or false, where true means the agent is killed. This function models killing agents due to a process above the dynamics of the model, for example, hunting or environmental disaster. Since it accepts both the agent and the model, there are information about the position of the agent, its properties, and the time step of the simulation to take into account.
* __initial\_energy__: A parameter for parental care of infants. Values more than 0 indicate that newly born individuals can survive for a number of times without requiring food from the environment/other species. The consumption rate (i.e. how many generations this initial energy suffices) is determined by the sum of the corresponding rows in "food sources" model parameter.
* __bottleneck\_function__: Name of a function in `functions file` that accepts two arguments: `agent` and `model`. It returns true or false, where true means the agent is killed. This function models killing agents due to a process above the dynamics of the model, for example, hunting or environmental disaster. Since it accepts both the agent and the model, there are information about the position of the agent, its properties, and the time step of the simulation to take into account.

### Model parameters

Expand All @@ -40,9 +40,8 @@ Each species should have the following parameters. The order that you write thes
* __metric__: Either "chebyshev" or "euclidian". Determines how many neighbors a space site has. "chebyshev" metric means that the r-neighborhood of a position are all positions within the hypercube having side length of 2*floor(r) and being centered in the origin position. "euclidean" metric means that the r-neighborhood of a position are all positions whose cartesian indices have Euclidean distance ≤ r from the cartesian index of the given position.
* __periodic__: _Boolean__ (true or false) to determine whether boundaries of the space are connected or not.
* __resources__: A function that returns a _vector of integers_ determining available resources (e.g. vegetation) per site. The function takes the `time_step` as its only argument. The function is defined in the functions file (parameter blow).
* __functions file__: Name of a file that contains the functions referred to in the `resources`, `bottleneck function` and `optimal phenotypes` parameters. If the file is in the same directory as this parameters file, writing its name is enough. Otherwise, a path should be given.
* __interactions__: A species-species interaction _matrix of numbers_ determining how individuals from different species interact. Each value is strength of interaction (between 0 and 1). Sign (+/-) is the direction of interaction where positive means similar individuals interact more strongly and negative is dissimilar ones tend to interact more.
* __food sources__: A species-species food _matrix of numbers_ determining what each species feeds on (consumption rate). Non-zero diagonal means the food resource is from the environment. Off-diagonals mean an species (in the rows) feeds on another species (in the columns). Numbers can be zero or any positive number. The magnitude of the number determines how many generations can an individual live off of given one unit of the food source. For example, if a diagonal is 2, it means that the species will eat one unit of the environmental resources and that is enough for it to live two steps.
* __food\_sources__: A species-species food _matrix of numbers_ determining what each species feeds on (consumption rate). Non-zero diagonal means the food resource is from the environment. Off-diagonals mean an species (in the rows) feeds on another species (in the columns). Numbers can be zero or any positive number. The magnitude of the number determines how many generations can an individual live off of given one unit of the food source. For example, if a diagonal is 2, it means that the species will eat one unit of the environmental resources and that is enough for it to live two steps.
* __seed__: Either an _integer_ or _Null_ for random number generator seed.

## Simulation outline
Expand Down
90 changes: 32 additions & 58 deletions docs/src/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,84 +10,45 @@ Install using the following command in a Julia REPL.

## Basic usage

Parameters of a model should be put in a YAML file with the structure below. Note that spaces and indentations are meaningful in YAML. Indentations should be spaces not tabs.
Parameters of a model should be put in a julia file (.jl format) with the structure below.

See [Simple Wright-Fisher](@ref) and [Predator prey](@ref) for complete examples of parameter files.

```yml
species:
1:
name: a
parameter 1: ...
parameter 2: ...
...
2:
name: b
parameter 1: ...
parameter 2: ...
...
model:
model parameter 1: ...
model parameter 2: ...
...
```

The file has two main levels: `species` and `model`. `species` stores species specific parameters as many different species as you want.

Since we cannot write a matrix in a YAML file, any parameter that is a matrix should be converted to a vector. In Julia, you can do this by `vec(yourmatrix)`.
```jl
## 1. Functions
...

First, define your model parameters in a YAML file (here, we call it `parameters.yml`). [Simple Wright-Fisher](@ref) and [Predator prey](@ref) have examples of initiation parameters. See [Model description](@ref) for a description of each parameter.
## 2. Species parameters. A dictionary for each species

We can the use the `runmodel` function to create a model from these parameters and run the simulation.
## 3. Model parameters as a dictionary.

```@docs
runmodel
```

```@example
using EvoDynamics
agentdata, modeldata, model = runmodel("parameters.yml")
```

## Creating simulation parameter files

EvoDynamics.jl reads simulation parameters ([Model description](@ref)) from a human-readable [YAML](https://github.com/JuliaData/YAML.jl) file. This file can be populated manually using a text editor or from within a Julia session.
The order of these sections is important because each section uses objects from its preceding sections.

To create parameters from within a Julia session and write them to a YAML file, you can follow the example below.
Functions are used to create parameters that may change temporally and spatially. The following parameters are functions: bottleneck function which kills certain agents at certain times and spaces, optimal phenotype values which returns the optimal phenotype for a species at a given time and space, and environmental resources that may change over time.

To define species parameters, create a dictionary whose keys are numbers starting from 1 for the number of species you have, and values are dictionaries themselves with the species parameter names and values. In the example below, for brevity, I only add a few parameters for each species (see [Model description](@ref) for the complete list of parameters).

You may create as many species as you want. Parameters of each species is a dictionary.

```julia
species_params = Dict(
1=>Dict("name" => "a", "number of genes" => 2, "number of phenotypes" => 2, "abiotic phenotypes" => [1]),
2=>Dict("name" => "b", "number of genes" => 2, "number of phenotypes" => 2, "abiotic phenotypes" => [1])
)

```
Model parameters is one dictionary that stores general parameters of the model, such as number of generations, space size, and species interaction parameters.

To define model parameters, create a new dictionary whose keys are the parameter names and values the parameter values. Here, again I only define a few parameters for brevity.
First, define your model parameters (here, we call it `parameters.jl`). [Simple Wright-Fisher](@ref) and [Predator prey](@ref) have examples of initiation parameters. See [Model description](@ref) for a description of each parameter.

```julia

model_params = Dict("generations"=> 100, "space"=> [6,10], "food sources" => [1.0, 0.7, 0.0, 0.0])
We can the use the `runmodel` function to create a model from these parameters and run the simulation.

```@docs
runmodel
```

Finally, create a dictionary mixing the two dictionaries before with keys "species" and "model".

```julia
data = Dict("species"=> species_params, "model"=> model_params)
```@example
using EvoDynamics
agentdata, modeldata, model = runmodel("parameters.jl")
```

This dictionary can be written as a YAML file in the correct format.

```julia
using YAML
f = "params.yml"
YAML.write_file(f, data)
```
## Creating simulation parameter files

EvoDynamics.jl reads simulation parameters ([Model description](@ref)) from a julia file containing dictionaries and functions. This file can be populated manually using a text editor or from within a Julia session.

## Collecting data

Expand Down Expand Up @@ -125,3 +86,16 @@ using EvoDynamics

agentdata, modeldata, model = runmodel("parameters.yml", mdata=[species_N])
```

## Running simulations in parallel

You can run replicate simulation in parallel. To that end, you need to add processors, and import EvoDynamics.jl and your parameters files on all cores:

```julia
using Distributed
addprocs(4)
@everywhere using EvoDynamics
@everywhere param_file = "params.jl"
@everywhere EvoDynamics.load_parameters(param_file)
adata, mdata, models = runmodel(param_file, replicates=10, parallel=true)
```
Loading

2 comments on commit caa3bce

@kavir1698
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/67218

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.14.0 -m "<description of version>" caa3bce29dccf0dbb094646fca7c4566257dc97e
git push origin v0.14.0

Please sign in to comment.