From eb3d2280bb3e09f5a8df1d8c88e28ca9136e977c Mon Sep 17 00:00:00 2001 From: Daniel Vedder <daniel.vedder@idiv.de> Date: Thu, 8 Aug 2024 17:26:59 +0200 Subject: [PATCH] Added `@areaof()` macro and `isgrassland()` function --- src/core/utils.jl | 10 ++++++++++ src/crop/farmplot.jl | 31 +++++++++++++++++++++++++------ src/nature/populations.jl | 4 ++-- src/nature/species/skylark.jl | 2 +- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/core/utils.jl b/src/core/utils.jl index ddffe48..27ef4d7 100644 --- a/src/core/utils.jl +++ b/src/core/utils.jl @@ -166,3 +166,13 @@ function bounds(x::Number; max::Number=Inf, min::Number=0) x < min ? min : x end + +""" + @areaof(npixels) + +Calculate the area of a given number of landscape pixels, knowing the resolution of the +world map (requires the `model` object to be available). +""" +macro areaof(npixels) + :($(esc(npixels)) * $(esc(:model)).settings["world.mapresolution"]^2) +end diff --git a/src/crop/farmplot.jl b/src/crop/farmplot.jl index 26eda95..d4b5787 100644 --- a/src/crop/farmplot.jl +++ b/src/crop/farmplot.jl @@ -12,7 +12,6 @@ mutable struct FarmPlot{T} <: ModelAgent const id::Int64 pixels::Vector{Tuple{Int64, Int64}} farmer::Int64 - croprotation::Vector{String} cropstate::T end @@ -53,19 +52,39 @@ function harvest!(farmplot::FarmPlot{T}, model::SimulationModel) where T harvest!(farmplot.cropstate, model) # TODO: multiply with area to return units of `g` 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 >90% of its pixels grass?) +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() == grass, farmplot.pixels) / length(farmplot.pixels) - if proportiongrass > 0.9 + proportiongrass = count(pos -> landcover(pos, model) == grass, farmplot.pixels) / + length(farmplot.pixels) + if proportiongrass > 0.8 return true - elseif proportiongrass > 0.1 + elseif proportiongrass > 0.2 @warn "Unclear classification: farm plot $(farmplot.id) has $(proportiongrass*100)% grass." + proportiongrass >= 0.5 && return true end return false end @@ -78,7 +97,7 @@ Calculate the average field size in hectares for the model landscape. function averagefieldsize(model::SimulationModel) sizes::Vector{Float64} = [] for fp in model.farmplots - push!(sizes, length(fp.pixels)*@param(world.mapresolution)^2) + push!(sizes, @areaof(length(fp.pixels))) end return sum(sizes)/length(sizes) |> ha end diff --git a/src/nature/populations.jl b/src/nature/populations.jl index 2f45c71..144f046 100644 --- a/src/nature/populations.jl +++ b/src/nature/populations.jl @@ -84,7 +84,7 @@ function initpopulation!(species::Type, p::PopInitParams, model::SimulationModel lastn = 0 width, height = size(model.landscape) if p.indarea > 0m² - pixelsperind = Int(round(p.indarea / @param(world.mapresolution)^2)) + pixelsperind = Int(round(p.indarea / @areaof(1))) end while n == 0 || n < p.popsize for x in @shuffle!(Vector(1:width)) @@ -160,7 +160,7 @@ return the size as a plain number. function territorysize(a::Union{Animal,Int64}, model::SimulationModel, units::Unitful.Units=ha, stripunits::Bool=false) a isa Int && (a = @animal(a)) - size = length(a.territory) * @param(world.mapresolution)^2 |> Float64 + size = length(a.territory) * @areaof(1) |> Float64 stripunits ? ustrip(units, size) : size |> units end diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl index ac582dc..feaa063 100644 --- a/src/nature/species/skylark.jl +++ b/src/nature/species/skylark.jl @@ -319,7 +319,7 @@ function findterritory(skylark::Skylark, model::SimulationModel) (isoccupied(model, "Skylark", c)) && continue push!(territory, c) quality = foragequality(skylark, model, c) - effectivesize += @param(world.mapresolution)^2*quality + effectivesize += @areaof(quality) (quality > 0) && (constrained = false) #XXX check for nesting habitats? end -- GitLab