diff --git a/src/GUI.jl b/src/GUI.jl index a136a1dc3ea4740dad77516ab1c8f2fcae968d13..be70fbc04a6e9135973d5db46c09a543491d33af 100644 --- a/src/GUI.jl +++ b/src/GUI.jl @@ -96,7 +96,7 @@ function render_plot(screen) dates = @param(core.startdate):@param(core.enddate) axlimits = @lift((1, length(dates), 0, maximum($pops[!,:Abundance]))) ax = Axis(plotimage[1,1], xlabel="Date", ylabel="Population size", - limits=axlimits, xticks=Persefone.gettickmarks(dates)) + limits=axlimits, xticks=Persefone.datetickmarks(dates)) for s in @param(nature.targetspecies) points = @lift(Vector{Float32}(@subset($pops, :Species .== s).Abundance)) iszero(size(points[])[1]) && continue @@ -108,6 +108,65 @@ function render_plot(screen) display(screen, plotimage.scene) end +#TODO adapt the next two functions to QML and integrate them into the interface + +""" + skylarkpopulation(model) + +Plot a line graph of total population size and individual demographics of skylarks over time. +Returns a Makie figure object. +""" +function skylarkpopulation(model::SimulationModel) + !("Skylark" in @param(nature.targetspecies)) && return nothing + pops = @data("skylark_abundance") + f = Figure() + dates = @param(core.startdate):@param(core.enddate) + axlimits = (1, length(dates), 0, maximum(pops[!,:TotalAbundance])) + ax = Axis(f[1,1], xlabel="Date", ylabel="Population size", + limits=axlimits, xticks=Persefone.datetickmarks(dates)) + lines!(f[1,1], Vector{Float32}(pops.TotalAbundance), linewidth=3, label="Total abundance") + lines!(f[1,1], Vector{Float32}(pops.Mating), linewidth=3, label="Mating") + lines!(f[1,1], Vector{Float32}(pops.Breeding), linewidth=3, label="Breeding") + lines!(f[1,1], Vector{Float32}(pops.Nonbreeding), linewidth=3, label="Non-breeding") + lines!(f[1,1], Vector{Float32}(pops.Juvenile), linewidth=3, label="Juvenile") + lines!(f[1,1], Vector{Float32}(pops.Migrants), linewidth=3, label="Migrants") + axislegend("Demographic"; position=:lt) + f +end + +""" + croptrends(model) + +Plot a dual line graph of cropped area and average plant height per crop over time. +Returns a Makie figure object. +""" +function croptrends(model::SimulationModel) + cropdata = @data("fields") + f = Figure(size=(1200,1000)) + dates = @param(core.startdate):@param(core.enddate) + # plot cropped area over time + axlimitsarea = (1, length(dates), 0, maximum(cropdata[!,:Area])*1.1) + ax1 = Axis(f[1,1], xlabel="Date", ylabel="Cropped area (ha)", + limits=axlimitsarea, xticks=Persefone.datetickmarks(dates)) + for c in unique(cropdata.Crop) + points = @select!(@subset(cropdata, :Crop .== c), :Area) + (iszero(size(points)[1]) || iszero(sum(points.Area))) && continue + lines!(f[1,1], Vector{Float32}(points.Area), linewidth=3, label=c) + end + axislegend("Crop"; position=:rt) + # plot average crop height over time + axlimitsheight = (1, length(dates), 0, maximum(cropdata[!,:Height])*1.1) + ax2 = Axis(f[2,1], xlabel="Date", ylabel="Average plant height (cm)", + limits=axlimitsheight, xticks=datetickmarks(dates)) + for c in unique(cropdata.Crop) + points = @select!(@subset(cropdata, :Crop .== c), :Height) + (iszero(size(points)[1]) || iszero(sum(points.Height))) && c != "no growth" && continue + lines!(f[2,1], Vector{Float32}(points.Height), linewidth=3, label=c) + end + axislegend("Crop"; position=:rt) + f +end + on(delay) do d println("Delay is now $(round(d, digits=1)) seconds.") #XXX DEBUG end @@ -153,6 +212,8 @@ The main function that creates the application. function launch() global model, timer + println("NOTE: this software is in development. Expect bugs.") + activateqmlfunctions() timer = QTimer() diff --git a/src/main.qml b/src/main.qml index 8ebfc9ea2c31f9194896ec3acd68af768b83ef1e..d4fdc457b5b150199e51337dab9309a086d6c58c 100644 --- a/src/main.qml +++ b/src/main.qml @@ -92,14 +92,14 @@ ApplicationWindow { Button { id: backButton text: "<" - ToolTip.text: "Back" + ToolTip.text: "Step back" ToolTip.visible: hovered onClicked: { Julia.previousstep() } } Button { id: stepButton text: ">" - ToolTip.text: "Step" + ToolTip.text: "Step forward" ToolTip.visible: hovered onClicked: { Julia.nextstep() } } @@ -142,10 +142,19 @@ ApplicationWindow { text: "Persefone.jl Desktop" informativeText: "A mechanistic model of agricultural landscapes \ and ecosystems in Europe.\n\n\ -© 2023 Daniel Vedder, Lea Kolb, Guy Pe'er\n\ +© 2024 Daniel Vedder, Guy Pe'er\n\ Distributed under the MIT license." } + MessageDialog { + id: devDialog + text: "In Development" + informativeText: "Please note that this model and the desktop software \ +are still in active development. Expect bugs and unfinished functionality.\n\n\ +If you have questions, contact daniel.vedder@idiv.de." + visible: true + } + FileDialog { id: loadFileChooser defaultSuffix: "dat"