Skip to content
Snippets Groups Projects
Commit 4ad42b92 authored by xo30xoqa's avatar xo30xoqa
Browse files

Big rearrange in the nature model to accommodate the @species syntax

Not yet functional!
parent ab698d68
No related branches found
No related tags found
No related merge requests found
...@@ -16,7 +16,7 @@ using ...@@ -16,7 +16,7 @@ using
Agents, Agents,
ArgParse, ArgParse,
Dates, Dates,
GeoArrays, GeoArrays, #XXX this is a big dependency - can we get rid of it?
Logging, Logging,
LoggingExtras, LoggingExtras,
Random, Random,
...@@ -24,6 +24,7 @@ using ...@@ -24,6 +24,7 @@ using
## define exported functions and variables ## define exported functions and variables
export export
param,
simulate, simulate,
initialise, initialise,
stepsimulation!, stepsimulation!,
...@@ -42,9 +43,11 @@ include("core/landscape.jl") ...@@ -42,9 +43,11 @@ include("core/landscape.jl")
include("farm/farm.jl") include("farm/farm.jl")
include("crop/crops.jl") include("crop/crops.jl")
include("nature/nature.jl") include("nature/nature.jl")
include("nature/lifehistory.jl")
include("nature/ecologicaldata.jl") include("nature/ecologicaldata.jl")
include("nature/wolpertinger.jl") #include("nature/species/skylark.jl")
include("nature/wyvern.jl") #include("nature/species/wolpertinger.jl")
#include("nature/species/wyvern.jl")
include("core/simulation.jl") include("core/simulation.jl")
end end
...@@ -17,6 +17,7 @@ in a single object. The model landscape consists of a matrix of pixels. ...@@ -17,6 +17,7 @@ in a single object. The model landscape consists of a matrix of pixels.
struct Pixel struct Pixel
landcover::LandCover landcover::LandCover
fieldid::Union{Missing, UInt32} fieldid::Union{Missing, UInt32}
events::Vector{Symbol} #TODO implement the rest of the events system
#FIXME actually this is stupid - I don't want a field ID, I want a field object #FIXME actually this is stupid - I don't want a field ID, I want a field object
end end
......
...@@ -6,6 +6,18 @@ ...@@ -6,6 +6,18 @@
const POPFILE = "populations.csv" const POPFILE = "populations.csv"
const INDFILE = "individuals.csv" const INDFILE = "individuals.csv"
"""
initecologicaldata()
Create output files for each data group collected by the nature model.
"""
function initecologicaldata()
newdataoutput(POPFILE, "Date;Species;Abundance", savepopulationdata,
param("nature.popoutfreq"))
newdataoutput(INDFILE, "Date;ID;X;Y;Species;Sex;Age;Energy",
saveindividualdata, param("nature.indoutfreq"))
end
""" """
savepopulationdata(model) savepopulationdata(model)
......
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file contains a set of utility functions needed by species.
###
#TODO initrandompopulation
#TODO killanimal!
#TODO reproduce!
#TODO parentsalive?
...@@ -6,78 +6,46 @@ ...@@ -6,78 +6,46 @@
## An enum used to assign a sex to each animal ## An enum used to assign a sex to each animal
@enum Sex hermaphrodite male female @enum Sex hermaphrodite male female
"""
Species
Species are differentiated by their name, and the functions used to
initialise their population and update each individual.
"""
struct Species
name::String
initpop!::Function # takes one argument: model
update!::Function # takes two arguments: animal, model
traits::Dict{String,Any} # a collection of species-specific traits
end
#TODO convert species into dicts
""" """
Animal Animal
This is the generic agent type for all animals. Species are differentiated This is the generic agent type for all animals. Species are differentiated
by the `species` struct passed by them during initialisation. by trait dictionaries passed by them during initialisation.
""" """
#XXX fix the @agent docstring issue (https://github.com/JuliaDynamics/Agents.jl/issues/715)
@agent Animal GridAgent{2} begin @agent Animal GridAgent{2} begin
species::Species #XXX is it (performance-)wise to use a dict for the traits?
# Doesn't this rather obviate the point of having an agent struct?
traits::Dict{String,Any}
sex::Sex sex::Sex
age::Int32 age::Int32
energy::Int32
end end
# This dict stores the definitions for all species that can be simulated.
# (The definitions are created in separate files and registered here.)
##TODO this needs to be rewritten to deal with the new @species macro
let specieslist = Dict{String, Species}()
"""
registerspecies(species)
This function has to be called by every species definition file
in order for the species to be used.
"""
global function registerspecies(s::Species)
specieslist[s.name] = s
end
"""
getspecies(name)
Returns the definition struct for the named species. ### MACROS IMPLEMENTING THE DOMAIN-SPECIFIC LANGUAGE FOR DEFINING SPECIES
"""
global function getspecies(name::String) macro species(name, body)
specieslist[name] funcname = "speciesfunction_"*name
quote
Core.@__doc__ function $(esc(funcname))()
$(esc(:name)) = string($(QuoteNode(name)))
$(esc(body))
vardict = Base.@locals
speciesdict = Dict{String,Any}()
for k in keys(vardict)
speciesdict[string(k)] = vardict[k]
end
return speciesdict
end
end end
end end
""" macro phase(name, body)
newspecies(properties...) :($(esc(name)) = function(animal::Animal, model::AgentBasedModel) $body end)
A utility function to create and register a new species.
All function arguments are passed on to Species().
"""
function newspecies(properties...)
registerspecies(Species(properties...))
end end
"""
trait(animal, trait)
A utility function to return a trait value for this animal's species. ### FUNCTIONS INTEGRATING THE NATURE MODEL WITH THE REST OF PERSEPHONE
Returns nothing if the trait is not defined.
"""
function trait(animal::Animal, trait::String)
!(trait in keys(animal.species.traits)) && (return nothing)
return animal.species.traits[trait]
end
""" """
stepagent!(animal, model) stepagent!(animal, model)
...@@ -86,11 +54,7 @@ Update an animal by one day. ...@@ -86,11 +54,7 @@ Update an animal by one day.
""" """
function stepagent!(animal::Animal, model::AgentBasedModel) function stepagent!(animal::Animal, model::AgentBasedModel)
animal.age += 1 animal.age += 1
animal.species.update!(animal,model) animal.traits[animal.traits["phase"]](animal,model)
if animal.energy <= 0
@debug "$(animal.species.name) $(animal.id) has died."
kill_agent!(animal, model)
end
end end
""" """
...@@ -101,11 +65,10 @@ Initialise the model with all simulated animal populations. ...@@ -101,11 +65,10 @@ Initialise the model with all simulated animal populations.
function initnature!(model::AgentBasedModel) function initnature!(model::AgentBasedModel)
# The config file determines which species are simulated in this run # The config file determines which species are simulated in this run
for s in param("nature.targetspecies") for s in param("nature.targetspecies")
getspecies(s).initpop!(model) funcname = Symbol("speciesfunction_"*s)
species = @eval $funcname()
species["initialise!"](model)
end end
# Initialise the data output # Initialise the data output
newdataoutput(POPFILE, "Date;Species;Abundance", savepopulationdata, initecologicaldata()
param("nature.popoutfreq"))
newdataoutput(INDFILE, "Date;ID;X;Y;Species;Sex;Age;Energy",
saveindividualdata, param("nature.indoutfreq"))
end end
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file implements the macros needed for the species DSL.
###
#XXX configure species traits via a separate TOML file?
##TODO replace the current registerspecies()
function registerspecies(speciesdict)
println(speciesdict)
processeddict = Dict{String,Any}()
for k in keys(speciesdict)
processeddict[string(k)] = speciesdict[k]
end
processeddict["testphase"]()
end
##TODO docstring
macro species(name, body)
speciesfun = gensym()
quote
Core.@__doc__ $speciesfun = function()
$(esc(:name)) = string($(QuoteNode(name)))
$(esc(body))
return Base.@locals
end
registerspecies($speciesfun())
end
end
##TODO docstring
macro phase(name, body)
:($(esc(name)) = function(animal::Animal, model::AgentBasedModel) $body end)
#:($(esc(name)) = function() $body end) #for testing
end
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
### Although I dare say the Wolpertinger is probably rather endangered... ### Although I dare say the Wolpertinger is probably rather endangered...
### ###
##TODO convert to @species syntax
""" """
initwolpertinger!(model) initwolpertinger!(model)
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
### Thankfully, wyverns are not a species we have to manage for... ### Thankfully, wyverns are not a species we have to manage for...
### ###
##TODO convert to @species syntax
""" """
initwyvern!(model) initwyvern!(model)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment