Skip to content
Snippets Groups Projects
Commit 738e5bed authored by xo30xoqa's avatar xo30xoqa
Browse files

Farm plots are now created based on LPIS data

parent e0e81b2f
No related branches found
No related tags found
No related merge requests found
...@@ -15,9 +15,9 @@ A pixel is a simple data structure to combine land use and ownership information ...@@ -15,9 +15,9 @@ A pixel is a simple data structure to combine land use and ownership information
in a single object. The model landscape consists of a matrix of pixels. in a single object. The model landscape consists of a matrix of pixels.
(Note: further landscape information may be added here in future.) (Note: further landscape information may be added here in future.)
""" """
struct Pixel mutable struct Pixel
landcover::LandCover landcover::LandCover
fieldid::Union{Missing, UInt32} fieldid::Union{Missing,Int64}
events::Vector{Symbol} #TODO implement the rest of the events system 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
...@@ -41,7 +41,9 @@ function initlandscape() ...@@ -41,7 +41,9 @@ function initlandscape()
lc = landcover[x,y][1] lc = landcover[x,y][1]
(ismissing(lc)) && (lc = 0) (ismissing(lc)) && (lc = 0)
lcv = LandCover(Int(lc/10)) lcv = LandCover(Int(lc/10))
landscape[x,y] = Pixel(lcv, farmfields[x,y][1], Vector{Symbol}()) ff = farmfields[x,y][1]
!(ismissing(ff)) && (ff = Int64(ff))
landscape[x,y] = Pixel(lcv, ff, Vector{Symbol}())
end end
end end
return landscape return landscape
......
...@@ -19,8 +19,9 @@ function initialise(config::String=PARAMFILE) ...@@ -19,8 +19,9 @@ function initialise(config::String=PARAMFILE)
space = GridSpace(size(landscape), periodic=false) space = GridSpace(size(landscape), periodic=false)
properties = Dict{Symbol,Any}(:date=>param("core.startdate"), properties = Dict{Symbol,Any}(:date=>param("core.startdate"),
:landscape=>landscape) :landscape=>landscape)
model = AgentBasedModel(Union{Farmer,Animal,CropPlot}, space, properties=properties, @debug "Setting up model now"
rng=Random.Xoshiro(param("core.seed"))) model = AgentBasedModel(Union{Farmer,Animal,FarmPlot}, space, properties=properties,
rng=Random.Xoshiro(param("core.seed")), warn=false)
# initialise submodels # initialise submodels
initfarms!(model) initfarms!(model)
initfields!(model) initfields!(model)
...@@ -36,7 +37,7 @@ Execute one update of the model. ...@@ -36,7 +37,7 @@ Execute one update of the model.
""" """
function stepsimulation!(model::AgentBasedModel) function stepsimulation!(model::AgentBasedModel)
@info "Simulating day $(model.date)." @info "Simulating day $(model.date)."
for a in Schedulers.ByType((Farmer,Animal,CropPlot), true)(model) for a in Schedulers.ByType((Farmer,Animal,FarmPlot), true)(model)
#The animal may have been killed, so we need a try/catch #The animal may have been killed, so we need a try/catch
try stepagent!(getindex(model, a), model) catch keyerror end try stepagent!(getindex(model, a), model) catch keyerror end
end end
......
...@@ -6,24 +6,83 @@ ...@@ -6,24 +6,83 @@
#XXX not sure whether it makes sense to have this as an agent type, #XXX not sure whether it makes sense to have this as an agent type,
# or perhaps better a grid property? # or perhaps better a grid property?
@agent CropPlot GridAgent{2} begin """
This is a docstring
"""
@agent FarmPlot NoSpaceAgent begin
pixels::Vector{Tuple{Int64, Int64}}
croptype::String
height::Float64
biomass::Float64
#TODO #TODO
end end
""" """
stepagent!(cropplot, model) stepagent!(farmplot, model)
Update a crop plot by one day. Update a farm plot by one day.
""" """
function stepagent!(cropplot::CropPlot, model::AgentBasedModel) function stepagent!(farmplot::FarmPlot, model::AgentBasedModel)
#TODO #TODO
end end
""" """
initfields!(model) initfields!(model)
Initialise the model with its crop plots. Initialise the model with its farm plots.
""" """
function initfields!(model::AgentBasedModel) function initfields!(model::AgentBasedModel)
#TODO n = 0
convertid = Dict{Int64,Int64}()
width, height = size(model.landscape)
for x in 1:width
for y in 1:height
# for each pixel, we need to extract the field ID given by the map input file,
# and convert it into the internal object ID used by Agents.jl, creating a new
# agent object if necessary
rawid = model.landscape[x,y].fieldid
(ismissing(rawid)) && continue
if rawid in keys(convertid)
objectid = convertid[rawid]
model.landscape[x,y].fieldid = objectid
push!(model[objectid].pixels, (x,y))
else
fp = add_agent!(FarmPlot, model, [(x,y)], "fallow", 0.0, 0.0)
model.landscape[x,y].fieldid = fp.id
convertid[rawid] = fp.id
n += 1
end
end
end
@debug "Initialised $n farm plots."
end
#XXX only needed during development, can be deleted again
function countfields(model::AgentBasedModel)
ids::Vector{Int64} = []
width, height = size(model.landscape)
for x in 1:width
for y in 1:height
i = model.landscape[x,y].fieldid
(ismissing(i)) && continue
push!(ids, i)
end
end
ids |> sort! |> unique! |> length
end
"""
averagefieldsize(model)
Calculate the average field size in hectares for the model landscape.
"""
function averagefieldsize(model::AgentBasedModel)
conversionfactor = 100 #our pixels are currently 10x10m, so 100 pixels per hectare
sizes::Vector{Float64} = []
for a in allagents(model)
(typeof(a) != FarmPlot) && continue
push!(sizes, size(a.pixels)[1]/conversionfactor)
end
round(sum(sizes)/size(sizes)[1], digits=2)
#sizes
end end
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
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 trait dictionaries 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
#XXX is it (performance-)wise to use a dict for the traits? #XXX is it (performance-)wise to use a dict for the traits?
# Doesn't this rather obviate the point of having an agent struct? # Doesn't this rather obviate the point of having an agent struct?
...@@ -111,7 +110,7 @@ To transition an individual to another phase, simply redefine its phase variable ...@@ -111,7 +110,7 @@ To transition an individual to another phase, simply redefine its phase variable
`@trait(phase) = "newphase"`. `@trait(phase) = "newphase"`.
""" """
macro phase(name, body) macro phase(name, body)
#XXX Using an undeclared variable in the body doesn't throw an error? #FIXME Somehow, errors in the phase body are not shown?
:($(esc(name)) = function(animal::Animal, model::AgentBasedModel) $body end) :($(esc(name)) = function(animal::Animal, model::AgentBasedModel) $body end)
end end
...@@ -173,6 +172,8 @@ macro reproduce(args...) ...@@ -173,6 +172,8 @@ macro reproduce(args...)
:(reproduce!(animal, model, $(args...))) :(reproduce!(animal, model, $(args...)))
end end
#XXX add a macro @f to call a function with animal and model as first parameters?
# e.g. @f(nearby_agents, distance)
### FUNCTIONS INTEGRATING THE NATURE MODEL WITH THE REST OF PERSEPHONE ### FUNCTIONS INTEGRATING THE NATURE MODEL WITH THE REST OF PERSEPHONE
......
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