Something went wrong on our end
-
Marco Matthies authored
- no majority counting of Pixels implemented yet, soil type is currently still determined by the first pixel of a FarmPlot
Marco Matthies authored- no majority counting of Pixels implemented yet, soil type is currently still determined by the first pixel of a FarmPlot
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
farmplot.jl 4.32 KiB
### Persefone.jl - a model of agricultural landscapes and ecosystems in Europe.
###
### This file contains code for the fields that farmers manage.
###
"""
FarmPlot
A struct representing a single field, on which a crop can be grown.
"""
mutable struct FarmPlot{T} <: ModelAgent
const id::Int64
pixels::Vector{Tuple{Int64, Int64}}
farmer::Int64
soiltype::SoilType
cropstate::T
end
croptype(f::FarmPlot{T}) where {T} = croptype(f.cropstate)
cropname(f::FarmPlot{T}) where {T} = cropname(croptype(f))
cropheight(f::FarmPlot{T}) where {T} = cropheight(f.cropstate)
cropcover(f::FarmPlot{T}) where {T} = cropcover(f.cropstate)
cropyield(f::FarmPlot{T}) where {T} = cropyield(f.cropstate)
isharvestable(f::FarmPlot{T}) where {T} = isharvestable(f.cropstate)
"""
stepagent!(farmplot, model)
Update a farm plot by one day.
"""
function stepagent!(farmplot::FarmPlot{T}, model::SimulationModel) where T
stepagent!(farmplot.cropstate, model)
end
"""
sow!(farmplot, model, cropname)
Sow the specified crop on the farmplot.
"""
function sow!(farmplot::FarmPlot, model::SimulationModel, cropname::String)
createevent!(model, farmplot.pixels, sowing)
sow!(farmplot.cropstate, model, cropname)
@debug "Farmer $(farmplot.farmer) sowed $(cropname) on farmplot $(farmplot.id)."
end
"""
harvest!(farmplot, model)
Harvest the crop of this farmplot.
"""
function harvest!(farmplot::FarmPlot{T}, model::SimulationModel) where T
createevent!(model, farmplot.pixels, harvesting)
harvest!(farmplot.cropstate, model) # TODO: multiply with area to return units of `g`
@debug "Farmer $(farmplot.farmer) harvested $(cropname(farmplot)) from farmplot $(farmplot.id)."
end
"""
@sow(cropname)
Sow the named crop on the current field. Requires the variables `field` and `model`.
"""
macro sow(cropname)
:(sow!($(esc(:field)), $(esc(:model)), $(esc(cropname))))
end
"""
@harvest()
Harvest the current field. Requires the variables `field` and `model`.
"""
macro harvest()
:(harvest!($(esc(:field)), $(esc(:model))))
end
## UTILITY FUNCTIONS
"""
isgrassland(farmplot, model)
Classify a farmplot as grassland or not (i.e., is the landcover of >80% of its pixels grass?)
"""
function isgrassland(farmplot::FarmPlot, model::SimulationModel)
proportiongrass = count(pos -> landcover(pos, model) == grass, farmplot.pixels) /
length(farmplot.pixels)
if proportiongrass > 0.8
return true
elseif proportiongrass > 0.2
@debug "Unclear classification: farm plot $(farmplot.id) has $(proportiongrass*100)% grass."
proportiongrass >= 0.5 && return true
end
return false
end
"""
averagefieldsize(model)
Calculate the average field size in hectares for the model landscape.
"""
function averagefieldsize(model::SimulationModel)
area_sum = sum(@areaof(length(fp.pixels)) for fp in model.farmplots; init=0.0u"m^2")
area_avg = area_sum / length(model.farmplots)
return area_avg |> ha
end
"""
croptype(model, position)
Return the crop at this position, or nothing if there is no crop here (utility wrapper).
"""
function croptype(pos::Tuple{Int64,Int64}, model::SimulationModel)
ismissing(model.landscape[pos...].fieldid) ? nothing :
croptype(model.farmplots[model.landscape[pos...].fieldid])
end
"""
cropname(model, position)
Return the name of the crop at this position, or an empty string if there is no crop here
(utility wrapper).
"""
function cropname(pos::Tuple{Int64,Int64}, model::SimulationModel)
field = model.landscape[pos...].fieldid
ismissing(field) ? "NA" : cropname(model.farmplots[field])
end
"""
cropheight(model, position)
Return the height of the crop at this position, or nothing if there is no crop here
(utility wrapper).
"""
function cropheight(pos::Tuple{Int64,Int64}, model::SimulationModel)
ismissing(model.landscape[pos...].fieldid) ? 0.0cm : # TODO: 0.0cm correct here?
cropheight(model.farmplots[model.landscape[pos...].fieldid])
end
"""
cropcover(model, position)
Return the crop cover of the crop at this position, or nothing if
there is no crop here (utility wrapper).
"""
function cropcover(pos::Tuple{Int64,Int64}, model::SimulationModel)
ismissing(model.landscape[pos...].fieldid) ? 0.0 : # TODO: 0.0 correct here?
cropcover(model.farmplots[model.landscape[pos...].fieldid])
end