Animal submodel
There are two source files in the src/animal directory that are currently not used: insects.jl and energy.jl. The first defines a function insectbiomass() that provides a very rough estimate of insect population density in a given pixel. The second is a (still incomplete) implementation of Dynamic Energy Budgets. Both were begun in the expectation that they would be needed, but then set aside for the time being. We note their existence here should they become useful again (with the caveat that both require testing).
animal.jl
This file is responsible for managing the animal modules.
Persefone.Animal — Type
AnimalThis is the generic agent type for all animals. Animal behaviour is defined for each taxon using @create and @phase. Species-specific parameter values are loaded from data files, as specified using the animal.animaldirectory and animal.targetspecies configuration parameters.
In addition to the taxon-specific fields defined by @create, all animals have the following fields:
idAn integer unique identifier for this individual.speciesA string giving the name of the species.sexmale, female, or hermaphrodite.posAn (x, y) coordinate tuple of the individual's current position.landelemA pointer to the landscape element this individual currently occupies.ageThe age of the individual in days.phaseThe name of the update function to be called during the current life phase.homerangeA geometry delimiting this individual's home range or territory.
Persefone.addanimal! — Function
addanimal!(speciesname, sex, position, model, phase="")Initialise a new animal individual. Instantiates the object and calls the species' "create" function on it. If phase is empty, it is set to the configured birth phase. Then adds the new animal to the model and returns the animal object.
Persefone.initanimals! — Method
initanimals!(model)Initialise the model with all simulated animal populations.
Persefone.stepagent! — Method
stepagent!(animal, model)Update an animal by one day, executing it's currently active phase function.
Persefone.updateanimals! — Method
updateanimals!(model)Run processes that affect all animals.
taxa.jl
This file contains the constants, macros, and functions needed to define new animal taxa.
Persefone.PHASES — Constant
PHASES is a dict that is used to store all phases defined in the model code (by taxon).
Persefone.@create — Macro
@create(taxon, body)This is a special case of @phase that is used to instantiate animal individuals at birth. Use this to define taxon-specific variables and to initialise their values.
@create <name> begin
self.<var1> = <value>
self.<var2> = <value>
...
endAs for @phase, the body of this macro has access to the variables self (the individual being created) and model (the simulation world), and can thus use all macros available in @phase.
Persefone.@phase — Macro
@phase(taxon, name, body)Use this macro to describe a species' behaviour during a given phase of its life. The idea behind this is that species show very different behaviour at different times 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. Species sharing a similar life cycle are grouped together in a taxon. Each phase definition is used for all species belonging to this taxon, with species-specific behaviour encoded using user-configured parameters.
@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:
selfa reference to the animal itself. This provides access to all the variables defined in the species definition file, as well as all standardAnimalvariables (e.g.self.age,self.sex,self.offspring).modela reference to the model world (an object of typeSimulationModel). This allows access, amongst others, tomodel.date(the current simulation date) andmodel.landscape(a two-dimensional array of pixels containing geographic information).
Many macros are available to make the code within the body of @phase more succinct. Some of the most important of these are: @setphase, @respond, @kill, @reproduce, @neighbours, @migrate, @move, @occupy, @rand.
After the phase definition, use phasedoc to document which parameters this phase uses (this is needed to check the validity of species parameter files).
macros.jl
This file contains many of the macros that can be used by the taxa (i.e. within @phase).
Persefone.@animal — Macro
@animal(id)Return the animal object associated with this ID number. This can only be used in a context where the model object is available (e.g. nested within @phase).
Persefone.@checkhabitat — Macro
@checkhabitat(pos=self.landelem, habitatdescriptor)Check whether the given habitatdescriptor fits the given position. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@cropcover — Macro
@cropcover(pos=self.landelem)Returns the local cropcover. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@cropgroup — Macro
@cropgroup(pos=self.landelem)Returns the local cropgroup. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@cropheight — Macro
@cropheight(pos=self.landelem)Returns the local cropheight. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@cropname — Macro
@cropname(pos=self.landelem)Returns the local cropname. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@destroynest — Macro
@destroynest(reason)Utility wrapper for destroynest!() in the Skylark model.
Persefone.@directionto — Macro
@directionto(pos=self.pos)Calculate the direction to a position, an animal or the closest habitat of the specified type or descriptor. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@distanceto — Macro
@distanceto(pos=self.pos)Calculate the distance to a position, an animal or the closest habitat of the specified type or descriptor. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@distancetoedge — Macro
@distancetoedge(pos=self.pos)Calculate the distance to the closest neighbouring habitat. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@findnearest — Macro
@findnearest(pos=self.pos)Calculate the direction to a position, an animal or the closest habitat of the specified type or descriptor. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@follow — Macro
@follow(leader, distance)Move to a location within the given distance of the leading animal. This is a utility wrapper that can only be used nested within @phase.
Persefone.@inextent — Macro
@inextent(pos)Check whether the given position is within the extent of the landscape.
Persefone.@isalive — Macro
@isalive(id)Test whether the animal with the given ID is still alive. This can only be used in a context where the model object is available (e.g. nested within @phase).
Persefone.@isoccupied — Macro
@isoccupied(geom)Test whether this geometry is already occupied by an animal of this species. This can only be used nested within @phase.
Persefone.@kill — Macro
@killKill this animal (and immediately abort its current update if it dies). This is a thin wrapper around kill!, and passes on any arguments. This can only be used nested within @phase.
Persefone.@killother — Macro
@killotherKill another animal. This is a thin wrapper around kill!, and passes on any arguments. This can only be used nested within @phase.
Persefone.@landcover — Macro
@landcover(pos=self.landelem)Returns the local landcover. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@landelem — Macro
@landelem(pos=self.pos)Return the landscape element at this position, or the element with id == pos. This is a utility wrapper that can only be used nested within @phase (if used with no arguments), or wherever model is available.
Persefone.@migrate — Macro
@migrate(arrival)Remove this animal from the map and add it to the migrant species pool. It will be returned to its current location at the specified arrival date. This can only be used nested within @phase.
Persefone.@move — Macro
@move(position)Move the current individual to a new position. This is a utility wrapper that can only be used nested within @phase.
Persefone.@neighbours — Macro
@neighbours([radius], conspecifics=true)Return an iterator over all (by default conspecific) animals in the animal's landscape element or within a given radius around its position, excluding itself. This can only be used nested within @phase.
Persefone.@occupy — Macro
@occupy(geom)Set the given geometry as the animal's home range. Use @vacate to remove the home range again. This can only be used nested within @phase.
Persefone.@reproduce — Macro
@reproduceLet this animal reproduce. This is a thin wrapper around reproduce!, and passes on any arguments. This can only be used nested within @phase.
Persefone.@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.
Persefone.@setphase — Macro
@setphase(newphase)Switch this animal over to a different phase. This can only be used nested within @phase.
Persefone.@vacate — Macro
@vacate()Remove this animal's home range. This can only be used nested within @phase.
Persefone.@walk — Macro
@walk(direction, distance)Walk the animal in a given direction, which is either specified by a bearing (0-359°), or by a direction string (e.g. "northwest", or "random"). This is a utility wrapper that can only be used nested within @phase.
individuals.jl
This file contains life-history and other ecological functions that apply to all animal individuals, such reproduction, death, and movement.
Persefone.followanimal! — Method
followanimal!(follower, leader, distance, model)Move the following animal to a location at most distance away from the leading animal.
Persefone.isoccupied — Method
isoccupied(geometry, species, model)Check whether the given geometry could be inserted as a home range without overlapping any other home ranges of the given species.
Persefone.kill! — Function
kill!(animal, model, probability=1.0, cause="")Kill this animal, optionally with a given percentage probability. Returns true if the animal dies, false if not.
Persefone.migrate! — Method
migrate!(animal, model, arrival)Remove this animal from the map and add it to the migrant species pool. It will be returned to its current location at the specified arrival date.
Persefone.move! — Method
move!(animal, model, position)Move the animal to the given position, making sure that this is in-bounds. If the position is out of bounds, the animal stops at the map edge.
Persefone.occupy! — Function
occupy!(animal, model, geom, exclusive=true)Create a new HomeRange for the animal with the given geometry. If exclusive is true, this function fails if the given Geom overlaps with an existing HomeRange belonging to a conspecific. Returns true if successful, or false in case of conflicts.
Persefone.reproduce! — Function
reproduce!(animal, model, n=1, mate=-1)Produce one or more offspring for the given animal at its current location. The mate argument gives the ID of the reproductive partner.
Persefone.vacate! — Method
vacate!(animal, model)Remove the animal's home range.
Persefone.walk! — Method
walk!(animal, model, bearing, distance=-1)The animal moves to the point defined by the bearing and distance from its current location.
Persefone.walk! — Method
walk!(animal, model, direction, distance)Let the animal move the given distance in the given direction ("north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest", "random").
populations.jl
This file contains functions that apply to all animal populations, such as for initialisation, or querying for neighbours.
Persefone.animal — Method
animal(id, model)
Return the animal with the given ID, or nothing if it's no longer alive.
Persefone.countanimals — Function
countanimals(model, pos, radius, species="")Return the number of animals in the given radius around this position, optionally filtering by species.
Persefone.countanimals — Function
countanimals(model, landelem, species="")Return the number of animals in this landscape element, optionally filtering by species.
Persefone.homerangesize — Method
homerangesize(animal)Calculate the size of this animal's home range in m² (utility wrapper).
Persefone.initindividuals! — Method
initindividuals!(species, landelem, model)Initialise one or two individuals (depending on the initialiseas parameter) in the given location. Returns the number of created individuals. (Internal helper function for initpopulation!().)
Persefone.initpopulation! — Method
initpopulation!(speciestype, popinitparams, model)Initialise the population of the given species, based on the configured initialisation parameters.
Persefone.isalive — Method
isalive(id, model)
Test whether the animal with the given ID is still alive.
Persefone.isoccupied — Method
isoccupied(model, position, species)Test whether this location is part of the home range of an animal of the given species.
Persefone.nearby_animals — Function
nearby_animals(model, pos, radius, species="")Return a list of animals in the given radius around this position, optionally filtering by species.
Persefone.nearby_animals — Function
nearby_animals(model, landelem, species="")Return a list of animals in this landscape element, optionally filtering by species.
Persefone.neighbours — Function
neighbours(animal, model, conspecifics=true)Return a list of animals in the same landscape element as this animal, excluding itself. By default, only return conspecific animals.
Persefone.neighbours — Function
neighbours(animal, model, radius, conspecifics=true)Return a list of animals in the given radius around this animal, excluding itself. By default, only return conspecific animals.
Persefone.populationdensity — Function
populationdensity(landelem, model, species="")Calculate the population density for a given species ("" -> all animals) in a given patch. Returns individuals/hectare.
Persefone.populationdensity — Function
populationdensity(model, landelem, species="")Return the population density in individuals/ha of this landscape element, optionally filtering by species.
ecologicaldata.jl
This file contains the code to extract and summarise data from the animal submodel for later analysis.
Persefone.birdabundance — Method
birdabundance(speciesname, model)Save bird abundance data, including total abundance and demographic data (abundances of breeding/non-breeding/juvenile/migrated individuals).
Persefone.butterflyabundance — Method
butterflyabundance(speciesname, model)Save butterfly abundance data, including total abundance and demographic data (abundances of breeding/non-breeding/juvenile/migrated individuals).
Persefone.butterflytrends — Method
butterflytrends(speciesname, model)Save butterfly abundance data, including total abundance and demographic data (abundances of breeding/non-breeding/juvenile/migrated individuals).
Persefone.initecologicaldata — Method
initecologicaldata()Create output files for each data group collected by the animal model.
Persefone.saveindividualdata — Method
saveindividualdata(model)Return a data table (to be printed 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 animal.indoutfreq. WARNING: Produces very big files!
Persefone.savepopulationdata — Method
savepopulationdata(model)Return a data table (to be printed 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 animal.popoutfreq.
speciesparams.jl
This file handles the metadata associated with all possible species parameters.
Persefone.SPECIESPARAMS — Constant
SPECIESPARAMS is a dict that stores all species parameters used by phases in the code.
Persefone.SpeciesParameter — Type
SpeciesParameterA struct to define a species parameter. This contains not just the parameter name and a short docstring, but also information about the expected type and a function to convert the type as returned by the TOML input file into the required type. In addition, it can contain a dict that returns further species parameters that are required depending on the values chosen for this parameter, as well as a list of value options for this parameter.
Persefone.addspeciesparam! — Function
addspeciesparam!(name, docstring, type=String, convert=(x)->x; options=[])Add a new SpeciesParameter to the internal reference system.
Persefone.checkspeciesdict — Method
checkspeciesdict(params)Verify that the species dict contains all needed parameters. Returns a vector of missing parameters, or an empty vector if the check is successful. (Note: call this after convertparametertypes!(), as it needs the correct parameter types.)
Persefone.convertparametertypes! — Method
convertparametertypes!(speciedict)Convert all parameter values to their specified types, using the metadata stored in SpeciesParameter. Gives a warning when conversion fails. Returns the converted dict (with keys changed from strings to symbols for performance).
Persefone.initspeciesdicts — Method
initspeciesdicts(animaldir, targetspecies)Load the species definition files into a dict.
Persefone.requiredparams — Function
requiredparams(baseparam, value="")Return the list of parameters that must defined if the baseparam has the given value.
Persefone.requireparams! — Method
requireparams!(baseparam, value, requiredparams, condition=(x)->true)Stipulate species parameters that must be defined if the baseparam takes on the given value. Pass an empty string as the value to denote parameters that are always required.
habitatdescriptors.jl
This file implements a simple string format for describing habitats.
Persefone.HabitatExpression — Type
HabitatExpressionThe internal type representing habitat descriptors (as created by parsehabitat() and @h_str). Creates a tree structure, consisting of one or two branches joined by a boolean link. The nodes of the tree are HabitatPropertys or nothing.
Persefone.HabitatProperty — Type
HabitatPropertyA helper struct for HabitatExpression, storing information about which aspect of the environment is to be tested, what the reference value is, and which comparison to apply.
Persefone.checkhabitat — Method
checkhabitat(position, habitatexpression, model)Evaluate the given habitat expression with regards to a given position in the model landscape. Returns true or false.
Persefone.checkhabitat — Method
checkhabitat(landelem, habitatexpression)Evaluate the given habitat expression on a landscape element, recursively evaluating all component expressions and linking them with the relevant boolean operators. Returns true or false.
Persefone.checkhabitat — Method
checkhabitat(landelem, habitatproperty)Evaluate the given habitat property, returning true if it applies to the given position in the model landscape and false if not.
Persefone.directionto — Function
directionto(pos, model, habitattype)Calculate the direction from the given location to the closest habitat of the specified type. Returns a coordinate tuple (target - position), or nothing if no matching habitat is found. Caution: can be computationally expensive!
Persefone.distanceto — Function
distanceto(pos, model, habitattype)Calculate the distance from the given location to the closest habitat of the specified type. Caution: can be computationally expensive!
Persefone.parsehabitat — Method
parsehabitat(descriptor)Parse a habitat string and return the resulting HabitatExpression. HabitatExpressions can consist of multiple subexpressions, joined by either AND or OR. At the lowest level, each subexpression is parsed using parsehabitatproperty().
Examples: "Fallow", "Orchard OR FruitPlantation", "Grassland OR (GRAIN AND NATURAL)", "ExtensiveGrassland AND (cropheight<=50cm AND cropheight>20cm)", "GRAIN AND (!SilageMaize AND !CornMaize)"
Persefone.parsehabitatproperty — Method
parsehabitatproperty(descriptor)Parse a HabitatProperty from a string (helper function for parsehabitat()). HabitatProperties may consist of either a single word (which must be a valid instance of a LandCover, LandCoverCategory, CropName, or CropGroup), or a word specifying an aspect and the associated value, separated by one of ==, !=, >=, <=, >, < (and no spaces!). The aspect may be one of "landcover", "landcovercategory", "cropname", "cropgroup", "cropheight", "cropcover". If the property is a single word, a preceding exclamation point may be used to negate it.
Examples: "Arable", "!WinterWheat", "cropgroup==LEGUME", "cropheight<50"
Persefone.@h_str — Macro
@h_str(s)A string macro for constructing habitat descriptors. Allows syntax like the following: h"Arable OR Grassland", h"WinterWheat AND height>5cm" Calls parsehabitat().