From 22268d3439f0e76ce7ed564f2aaa5a772257930c Mon Sep 17 00:00:00 2001 From: Daniel Vedder <daniel.vedder@idiv.de> Date: Fri, 6 Oct 2023 14:56:29 +0200 Subject: [PATCH] Activated Makie plotting Compile time still increased to 50s (from 15s), but at the moment I can just about live with that. --- Manifest.toml | 14 +++++++++++++- Project.toml | 1 + src/Persefone.jl | 10 +++++----- src/analysis/makieplots.jl | 11 ++++++++--- src/core/output.jl | 30 +++++++++++++++--------------- src/core/simulation.jl | 2 +- src/nature/ecologicaldata.jl | 4 ++-- src/world/landscape.jl | 14 +++++++------- 8 files changed, 52 insertions(+), 34 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 72340ca..77e1ea9 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.9.3" manifest_format = "2.0" -project_hash = "37a066281d4eb014f2c662ec23deb18c4d89d4e2" +project_hash = "ce171af7d57f8fcad6d5ea123349f467345ec803" [[deps.AbstractFFTs]] deps = ["LinearAlgebra"] @@ -165,6 +165,12 @@ git-tree-sha1 = "4435559dc39793d53a9e3d278e185e920b4619ef" uuid = "0e736298-9ec6-45e8-9647-e4fc86a2fe38" version = "0.2.8" +[[deps.BinaryProvider]] +deps = ["Libdl", "Logging", "SHA"] +git-tree-sha1 = "ecdec412a9abc8db54c0efc5548c64dfce072058" +uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232" +version = "0.5.10" + [[deps.BitFlags]] git-tree-sha1 = "43b1a4a8f797c1cddadf60499a8a077d4af2cd2d" uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" @@ -822,6 +828,12 @@ git-tree-sha1 = "bca20b2f5d00c4fbc192c3212da8fa79f4688009" uuid = "82e4d734-157c-48bb-816b-45c225c6df19" version = "0.6.7" +[[deps.ImageMagick]] +deps = ["BinaryProvider", "FileIO", "ImageCore", "InteractiveUtils", "Libdl", "Pkg", "Random"] +git-tree-sha1 = "54dfa264804aefc44630c96619474e683a522d78" +uuid = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" +version = "0.7.9" + [[deps.ImageMetadata]] deps = ["AxisArrays", "ImageAxes", "ImageBase", "ImageCore"] git-tree-sha1 = "355e2b974f2e3212a75dfb60519de21361ad3cb7" diff --git a/Project.toml b/Project.toml index 463fe12..d98f001 100644 --- a/Project.toml +++ b/Project.toml @@ -14,6 +14,7 @@ Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" GeoArrays = "2fb1d81b-e6a0-5fc5-82e6-8e06903437ab" +ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" diff --git a/src/Persefone.jl b/src/Persefone.jl index 165f399..a3550f2 100644 --- a/src/Persefone.jl +++ b/src/Persefone.jl @@ -25,7 +25,7 @@ using GeoArrays, #XXX this is a big dependency - can we get rid of it? Logging, LoggingExtras, - #CairoMakie, + CairoMakie, Random, Serialization, StableRNGs, @@ -80,9 +80,9 @@ export stepsimulation!, createevent!, finalise!, - #visualisemap, - #populationtrends, - #visualiseoutput, + visualisemap, + populationtrends, + visualiseoutput, savemodelobject, loadmodelobject @@ -90,7 +90,7 @@ export ## b references something from file a, it must be included later) include("core/input.jl") include("core/output.jl") -#include("analysis/makieplots.jl") +include("analysis/makieplots.jl") include("world/landscape.jl") include("world/weather.jl") diff --git a/src/analysis/makieplots.jl b/src/analysis/makieplots.jl index 00e871d..3422917 100644 --- a/src/analysis/makieplots.jl +++ b/src/analysis/makieplots.jl @@ -22,6 +22,8 @@ function visualisemap(model::AgentBasedModel, date::Union{Date,Nothing}=nothing) image!(f[1,1], rotr90(landcover)) ax.aspect = DataAspect() # plot individuals + #FIXME this function displays the individuals in a different location than the + # R script does - somewhere, I'm confusing coordinates... for s in unique(inds.Species) points = @select!(@subset(inds, :Species .== s, :Date .== date), :X, :Y) scatter!(f[1,1], Matrix{Float32}(points), markersize=10) @@ -38,8 +40,11 @@ Returns a Makie figure object. function populationtrends(model::AgentBasedModel) pops = model.datatables["populations"] f = Figure() - for s in unique(inds.Species) - points = @select!(@subset(pops, :Species .== s), :X, :Y) - lines!(f[1,1], Matrix{Float32}(points), markersize=10) + ax = Axis(f[1,1]) + for s in unique(pops.Species) + points = @select!(@subset(pops, :Species .== s), :Abundance) + lines!(f[1,1], Vector{Float32}(points.Abundance)) end + #TODO prettify, add legend & labels + f end diff --git a/src/core/output.jl b/src/core/output.jl index 0ce93ea..f9366bb 100644 --- a/src/core/output.jl +++ b/src/core/output.jl @@ -208,21 +208,21 @@ function outputdata(model::AgentBasedModel) end end -# """ -# visualiseoutput(model) - -# Cycle through all data outputs and call their respective plot functions, -# saving each figure as a PDF. -# """ -# function visualiseoutput(model::AgentBasedModel) -# #TODO write tests -# @debug "Visualising output." -# for output in model.dataoutputs -# isnothing(output.plotfunction) && continue -# figure = output.plotfunction(model) -# save(joinpath(@param(core.outdir), output.name*".pdf"), figure) -# end -# end +""" + visualiseoutput(model) + +Cycle through all data outputs and call their respective plot functions, +saving each figure as a PDF. +""" +function visualiseoutput(model::AgentBasedModel) + #TODO write tests + @debug "Visualising output." + for output in model.dataoutputs + isnothing(output.plotfunction) && continue + figure = output.plotfunction(model) + save(joinpath(@param(core.outdir), output.name*".pdf"), figure) + end +end """ savemodelobject(model, filename) diff --git a/src/core/simulation.jl b/src/core/simulation.jl index 21bff1a..51dfdbf 100644 --- a/src/core/simulation.jl +++ b/src/core/simulation.jl @@ -152,7 +152,7 @@ function finalise!(model::AgentBasedModel) with_logger(model.logger) do @info "Simulated $(model.date-@param(core.startdate))." @info "Simulation run completed at $(Dates.now()),\nwrote output to $(@param(core.outdir))." - #visualiseoutput(model) #TODO + visualiseoutput(model) model end end diff --git a/src/nature/ecologicaldata.jl b/src/nature/ecologicaldata.jl index 5f65954..99bb68d 100644 --- a/src/nature/ecologicaldata.jl +++ b/src/nature/ecologicaldata.jl @@ -14,9 +14,9 @@ Create output files for each data group collected by the nature model. """ function initecologicaldata(model::AgentBasedModel) newdataoutput!(model, "populations", ["Date", "Species", "Abundance"], - savepopulationdata, @param(nature.popoutfreq), visualisemap) + savepopulationdata, @param(nature.popoutfreq), populationtrends) newdataoutput!(model, "individuals", ["Date","ID","X","Y","Species","Sex","Age"], - saveindividualdata, @param(nature.indoutfreq), populationtrends) + saveindividualdata, @param(nature.indoutfreq), visualisemap) end """ diff --git a/src/world/landscape.jl b/src/world/landscape.jl index d97a91c..4d8e283 100644 --- a/src/world/landscape.jl +++ b/src/world/landscape.jl @@ -46,19 +46,19 @@ function initlandscape(landcovermap::String, farmfieldsmap::String) #TODO replace errors with exception !(isfile(landcovermap)) && Base.error("Landcover map $(landcovermap) doesn't exist.") !(isfile(farmfieldsmap)) && Base.error("Field map $(farmfieldsmap) doesn't exist.") - landcover = GeoArrays.read(landcovermap) - farmfields = GeoArrays.read(farmfieldsmap) + #XXX can I read the files in using FileIO, to avoid the GeoArrays dependency? + # read in TIFFs, replacing missing values with 0 + landcover = coalesce(GeoArrays.read(landcovermap), 0) + farmfields = coalesce(GeoArrays.read(farmfieldsmap), 0) (size(landcover) != size(farmfields)) && Base.error("Input map sizes don't match.") width, height = size(landcover)[1:2] landscape = Matrix{Pixel}(undef, width, height) for x in 1:width for y in 1:height # convert the numeric landcover value to LandCover, then create the Pixel object - lc = landcover[x,y][1] - (ismissing(lc)) && (lc = 0) - lcv = LandCover(Int(lc/10)) - ff = farmfields[x,y][1] - !(ismissing(ff)) && (ff = Int64(ff)) + lcv = LandCover(Int(landcover[x,y][1]/10)) + ff = Int64(farmfields[x,y][1]) + (iszero(ff)) && (ff = missing) landscape[x,y] = Pixel(lcv, ff, Vector{Symbol}()) end end -- GitLab