Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
makieplots.jl 2.56 KiB
### Persefone.jl - a model of agricultural landscapes and ecosystems in Europe.
###
### This file visualises model output using Makie.
###

"""
    visualisemap(model, date, landcovermap)

Draw the model's land cover map and plot all individuals as points on it at
the specified date. If no date is passed, use the last date for which data
are available. Optionally, you can pass a landcover map image (this is needed
to reduce the frequency of disk I/O for Persefone Desktop).
Returns a Makie figure object.
"""
function visualisemap(model::AgentBasedModel,date=nothing,landcover=nothing)
    # load and plot the map
    isnothing(landcover) && (landcover = load(@param(world.landcovermap)))
    f = Figure()
    ax = Axis(f[1,1])
    hidedecorations!(ax)
    image!(f[1,1], rotr90(landcover))
    ax.aspect = DataAspect()
    # check if there are individuals and plot them
    inds = model.datatables["individuals"]
    if iszero(size(inds)[1])
        @debug "No individual data to map"
        return f
    end
    isnothing(date) && (date = inds.Date[end])
    for s in unique(inds.Species)
        points = @select!(@subset(inds, :Species .== s, :Date .== date),
                          :X, :Y)
        # The origin in Makie is in the bottom-left rather than in the top-left as
        # on the model map, so we have to invert the Y coordinates
        @transform!(points, :Y = size(model.landscape)[2] .- :Y)
        scatter!(f[1,1], Matrix{Float32}(points), markersize=8)
    end
    f
end

"""
    populationtrends(model)

Plot a line graph of population sizes of each species over time.
Returns a Makie figure object.
"""
function populationtrends(model::AgentBasedModel)
    pops = model.datatables["populations"]
    # create the labels needed for the ticks on the X axis
    dates = @param(core.startdate):@param(core.enddate)
    ticks = (Int[], String[])
    for i in 1:length(dates)
        if Day(dates[i]) == Day(1)
            push!(ticks[1], i)
            push!(ticks[2], Dates.format(dates[i], "u yy"))
        end
    end
    while length(ticks[1]) > 12
        deleteat!(ticks[1], 2:2:length(ticks[1]))
        deleteat!(ticks[2], 2:2:length(ticks[2]))            
    end
        
    f = Figure()
    ax = Axis(f[1,1], xlabel="Date", ylabel="Population size",
              limits=((1, length(dates)), nothing), xticks = ticks)
    for s in unique(pops.Species)
        points = @select!(@subset(pops, :Species .== s), :Abundance)
        lines!(f[1,1], Vector{Float32}(points.Abundance), linewidth=3, label=s)
    end
    size(pops)[1] > 0 && axislegend("Species"; position=:lt)
    f
end