Nature
nature.jl
This file is responsible for managing the animal modules.
Persephone.Animal
— TypeAnimal
This is the generic agent type for all animals. Species are differentiated by trait dictionaries passed by them during initialisation.
Persephone.animalid
— Methodanimalid(animal)
A small utility function to return a string with the species name and ID of an animal.
Persephone.initnature!
— Methodinitnature!(model)
Initialise the model with all simulated animal populations.
Persephone.stepagent!
— Methodstepagent!(animal, model)
Update an animal by one day, executing it's currently active phase function.
Persephone.@countanimals
— Macro@countanimals(speciesname, radius=0)
Count the number of animals of the given species in this location. This is a utility wrapper that can only be used nested within @phase
or @habitat
.
Persephone.@cropheight
— Macro@cropheight
Return the height of the crop at this position, or 0 if there is no crop here. This is a utility wrapper that can only be used nested within @phase
or @habitat
.
Persephone.@croptype
— Macro@croptype
Return the local croptype, or nothing if there is no crop here. This is a utility wrapper that can only be used nested within @phase
or @habitat
.
Persephone.@distanceto
— Macro@distanceto(habitat)
Calculate the distance to the closest habitat of the specified type or descriptor. This is a utility wrapper that can only be used nested within @phase
or @habitat
.
Persephone.@distancetoedge
— Macro@distancetoedge
Calculate the distance to the closest neighbouring habitat. This is a utility wrapper that can only be used nested within @phase
or @habitat
.
Persephone.@habitat
— Macro@habitat
Specify habitat suitability for spatial ecological processes.
This macro works by creating an anonymous function that takes in a model object and a position, and returns true
or false
depending on the conditions specified in the macro body.
Several utility macros can be used within the body of @habitat
as a short-hand for common expressions: @landcover
, @croptype
, @cropheight
, @distanceto
, @distancetoedge
, @countanimals
. The variables model
and pos
can be used for checks that don't have a macro available.
Two example uses of @habitat
might look like this:
movementhabitat = @habitat(@landcover() in (grass agriculture soil))
nestinghabitat = @habitat((@landcover() == grass ||
(@landcover() == agriculture && @croptype() != maize &&
@cropheight() < 10)) &&
@distanceto(forest) > 20)
For more complex habitat suitability checks, the use of this macro can be circumvented by directly creating an equivalent function.
Persephone.@here
— Macro@here(property)
A utility macro to quickly access a property of the animal's current position. This can only be used nested within @phase
.
Persephone.@initialise!
— Macro@initialise!(habitatdescriptor; kwargs...)
This is a wrapper around initpopulation()
that can be called within the body of a @species
definition block. It saves the user having to define the required initialise!
variable by hand.
Persephone.@kill
— Macro@kill
Kill this animal. This is a thin wrapper around kill!()
, and passes on any arguments. This can only be used nested within @phase
.
Persephone.@landcover
— Macro@landcover
Returns the local landcover. This is a utility wrapper that can only be used nested within @phase
or @habitat
.
Persephone.@neighbours
— Macro@neighbours(radius)
Return an iterator over all animals in the given radius around this animal, excluding itself. This can only be used nested within @phase
.
Persephone.@phase
— Macro@phase(name, body)
This macro is designed to be used within a species definition block (i.e. within the body of a call to @species
).
The idea behind this is that species show very different behaviour during different phases of their lives. Therefore, @phase
can be used define the behaviour for one such phase, and the conditions under which the animal transitions to another phase.
@phase
works by creating a function that will be called by the model if the animal is in the relevant phase. When it is called, it has access to the following variables:
animal
a reference to the animal itself. This provides access toanimal.age
,animal.sex
, andanimal.traits
(a dict that gives access to all species parameters).pos
gives the animal's current position as a coordinate tuple.model
a reference to the model world (an object of typeAgentBasedModel
). This allows access tomodel.date
(the current simulation date) andmodel.landscape
(a two-dimensional array of pixels containing geographic information).
Several utility macros can be used within the body of @phase
as a short-hand for common expressions: @respond
, @trait
, @here
, @kill
, @reproduce
, @neighbours
.
To transition an individual to another phase, simply redefine its phase variable: @trait(phase) = "newphase"
.
Persephone.@reproduce
— Macro@reproduce
Let this animal reproduce. This is a thin wrapper around reproduce!()
, and passes on any arguments. This can only be used nested within @phase
.
Persephone.@respond
— Macro@respond(eventname, body)
Define how an animal responds to a landscape event that affects its current position. This can only be used nested within @phase
.
Persephone.@species
— Macro@species(name, body)
A macro used to create new species definitions for the nature model. This is effectively a simple domain-specific language, establishing a custom syntax to describe species' biology:
@species name begin
initialise! = initpopulation()
phase = "phase1"
...
@phase phase1 begin
...
end
end
The definition body (enclosed in the begin/end block) has two sections. First comes a list of species-specific parameters, which are assigned just like normal variables. Second come one or more phase definitions, that describe the behaviour of the species during various parts of its life cycle (see the documentation to @phase
for details).
There are two parameters that all species must define:
initialise!
should specify a function that will be used to create the starting population for this species. This function must take two arguments, a species dict and anAgentBasedModel
object. The easiest way to create this function is by usinginitpopulation()
. (To save typing,@initialise!()
can be called instead. It defines this variable and callsinitpopulation()
, all in one go.)phase
should be a string specifying the name of the first phase that individuals of this species will be assigned to on birth.
Access to the rest of the model is given by the model
variable (an object of type AgentBasedModel
).
Persephone.@trait
— Macro@trait(traitname)
A utility macro to quickly access an animal's trait value. This can only be used nested within @phase
.
populations.jl
This file contains a set of utility functions for species, including initialisation, reproduction, and mortality.
Persephone.countanimals
— Functioncountanimals(pos, model, speciesname, radius=0)
Count the number of animals of the given species in this location (optionally supplying a radius).
Persephone.initpopulation
— Methodinitpopulation(habitatdescriptor; popsize=-1, pairs=false, asexual=false)
Creates a function that initialises individuals at random locations across the landscape. This can be used to create the initialise!
variable in a species definition block.
habitatdescriptor
is a function that determines whether a given location is suitable or not (create this using@habitat
).popsize
determines the number of individuals that will be created. If this is zero or negative, one individual will be created in every suitable location in the landscape. Ifpopsize
is greater than the number of suitable locations, multiple individuals will be created in one place. (Maximum population density can be set in the habitat descriptor using the@countanimals
macro.)If
pairs
is true, a male and a female individual will be created in each selected location, otherwise, only one individual will be created at a time.If
asexual
is true, all created individuals are assigned the sexhermaphrodite
, otherwise, they are randomly assigned male of female. (Ifpairs
is true,asexual
is ignored.)
Persephone.initrandompopulation
— Methodinitrandompopulation(popsize; kwargs...)
A simplified version of initpopulation()
. Creates a function that initialises popsize
individuals, spread at random across the landscape.
Persephone.kill!
— Functionkill(animal, model, probability=1.0, cause="")
Kill this animal, optionally with a given percentage probability. Returns true if the animal dies, false if not.
Persephone.nearby_animals
— Methodnearby_animals(animal, model, radius)
Return an iterator over all animals in the given radius around this animal, excluding itself.
Persephone.nearby_animals
— Methodnearby_animals(pos, model, radius)
Return an iterator over all animals in the given radius around this position.
Persephone.reproduce!
— Functionreproduce!(animal, model, n=1)
Produce one or more offspring for the given animal at its current location.
ecologicaldata.jl
This file contains a set of life-history related utility functions needed by species.
Persephone.initecologicaldata
— Methodinitecologicaldata()
Create output files for each data group collected by the nature model.
Persephone.saveindividualdata
— Methodsaveindividualdata(model)
Print a comma-separated set of lines to individuals.csv
, listing all properties of all animal individuals in the model. May be called never, daily, monthly, yearly, or at the end of a simulation, depending on the parameter nature.indoutfreq
. WARNING: Produces very big files!
Persephone.savepopulationdata
— Methodsavepopulationdata(model)
Print a comma-separated set of lines to populations.csv
, giving the current date and population size for each animal species. May be called never, daily, monthly, yearly, or at the end of a simulation, depending on the parameter nature.popoutfreq
.