From 47a4caf22f5e748c32673c2305d4ba476e38de92 Mon Sep 17 00:00:00 2001 From: George Datseris Date: Mon, 4 Apr 2022 14:24:46 +0200 Subject: [PATCH] Calculate OSM limits (#90) * explicitly calculate limits of OSM * make unknown space an error * GraphSpace plotting is not supported yet! * remove `isnothing(ax)` checks _ABMPlot recipe is internal. There is no (documented) way to call it with `nothing` as axis. * fix bug model property * Allow propagation of keyword arguments into osmmakie --- Project.toml | 2 +- examples/agents/agents_osm.jl | 19 +++++------------- src/agents/abmplot.jl | 37 ++++++++++++++++++++++------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Project.toml b/Project.toml index a91691f1..d37fa4cb 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "InteractiveDynamics" uuid = "ec714cd0-5f51-11eb-0b6e-452e7367ff84" repo = "https://github.com/JuliaDynamics/InteractiveDynamics.jl.git" -version = "0.20.1" +version = "0.20.2" [deps] DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" diff --git a/examples/agents/agents_osm.jl b/examples/agents/agents_osm.jl index 90e81f3a..dc401a1e 100644 --- a/examples/agents/agents_osm.jl +++ b/examples/agents/agents_osm.jl @@ -7,26 +7,17 @@ zombie_model, zombie_step!, zombie_model_step! = Models.zombies() aczombie(agent) = agent.infected ? (:green, 0.9) : (:purple, 0.75) aszombie(agent) = agent.infected ? 10 : 8 -## interactive app - axiskwargs = (; title = "Zombie outbreak", backgroundcolor = "#f3f3f3") - -fig = Figure() -ax = Axis(fig[1,1]; axiskwargs...) -abmobs = abmplot!(ax, zombie_model; agent_step! = zombie_step!, model_step! = zombie_model_step!, - ac = aczombie, as = aszombie) +fig, ax, abmobs = abmplot(zombie_model; axiskwargs, ac = aczombie, as = aszombie) fig -## with parameter sliders - -fig = Figure() -ax = Axis(fig[1,1]; axiskwargs...) -abmobs = abmplot!(ax, zombie_model; agent_step! = zombie_step!, model_step! = zombie_model_step!, - ac = aczombie, as = aszombie, params = Dict(:dt => 0.1:0.01:0.2)) +# %% with parameter sliders & time evolution +fig, ax, abmobs = abmplot!(zombie_model; agent_step! = zombie_step!, model_step! = zombie_model_step!, + ac = aczombie, as = aszombie, axiskwargs, params = Dict(:dt => 0.1:0.01:0.2)) fig -## abmexploration convenience function +# %% abmexploration convenience function zombie_share(model) = count(model[id].infected for id in allids(model)) / nagents(model) fig, abmobs = abmexploration(zombie_model; agent_step! = zombie_step!, model_step! = zombie_model_step!, diff --git a/src/agents/abmplot.jl b/src/agents/abmplot.jl index bbfe92b3..486dc980 100644 --- a/src/agents/abmplot.jl +++ b/src/agents/abmplot.jl @@ -66,6 +66,8 @@ Requires `Agents`. See also [`abmvideo`](@ref) and [`abmexploration`](@ref). translate!(obj, 0, 0, 5) # be sure that the teacher will be above students end ``` +* `osmkwargs = NamedTuple()` : keywords directly passed to + `osmplot!` from OSMMakie.jl if model space is `OpenStreetMapSpace`. The stand-alone function `abmplot` also takes two optional `NamedTuple`s named `figure` and `axis` which can be used to change the automatically created `Figure` and `Axis` objects. @@ -168,6 +170,7 @@ This is the internal recipe for creating an `_ABMPlot`. am = :circle, offset = nothing, scatterkwargs = NamedTuple(), + osmkwargs = NamedTuple(), # Preplot heatarray = nothing, @@ -193,13 +196,17 @@ function _default_add_controls(agent_step!, model_step!) (agent_step! != Agents.dummystep) || (model_step! != Agents.dummystep) end -const SUPPORTED_SPACES = Union{ - Agents.DiscreteSpace, +const SUPPORTED_SPACES = Union{ + Agents.GridSpace, Agents.ContinuousSpace, Agents.OpenStreetMapSpace, } -function Makie.plot!(abmplot::_ABMPlot{<:Tuple{<:Agents.ABM{<:SUPPORTED_SPACES}}}) +function Makie.plot!(abmplot::_ABMPlot) + if !(abmplot.model[].space isa SUPPORTED_SPACES) + error("Space type $(typeof(model.space)) is not supported for plotting.") + end + # Following attributes are all lifted from the recipe observables (specifically, # the model), see lifting.jl for source code. pos, color, marker, markersize, heatobs = lift_attributes(abmplot.abmobs[].model, @@ -207,15 +214,13 @@ function Makie.plot!(abmplot::_ABMPlot{<:Tuple{<:Agents.ABM{<:SUPPORTED_SPACES}} model = abmplot.abmobs[].model[] ax = abmplot.ax[] - if !isnothing(ax) - isnothing(ax.aspect[]) && (ax.aspect = DataAspect()) - set_axis_limits!(ax, model) - fig = ax.parent - end + isnothing(ax.aspect[]) && (ax.aspect = DataAspect()) + set_axis_limits!(ax, model) + fig = ax.parent # OpenStreetMapSpace preplot if model.space isa Agents.OpenStreetMapSpace - osm_plot = osmplot!(abmplot, model.space.map) + osm_plot = osmplot!(abmplot.ax[], model.space.map; abmplot.osmkwargs...) osm_plot.plots[1].plots[1].plots[1].inspectable[] = false osm_plot.plots[1].plots[3].inspectable[] = false end @@ -224,9 +229,8 @@ function Makie.plot!(abmplot::_ABMPlot{<:Tuple{<:Agents.ABM{<:SUPPORTED_SPACES}} if !isnothing(heatobs[]) hmap = heatmap!(abmplot, heatobs; colormap = JULIADYNAMICS_CMAP, abmplot.heatkwargs...) if abmplot.add_colorbar[] - @assert !isnothing(ax) "Need `ax` to add a colorbar for the heatmap." Colorbar(fig[1, 1][1, 2], hmap, width = 20) - rowsize!(fig[1,1].layout, 1, ax.scene.px_area[].widths[2]) + rowsize!(fig[1, 1].layout, 1, ax.scene.px_area[].widths[2]) # TODO: Set colorbar to be "glued" to axis end end @@ -262,7 +266,13 @@ end "Plot space and/or set axis limits." function set_axis_limits!(ax, model) if model.space isa Agents.OpenStreetMapSpace - return + o = [-Inf, -Inf] + e = [Inf, Inf] + for i ∈ Agents.positions(model) + x, y = Agents.OSM.lonlat(i, model) + o[1] = max(x, o[1]); o[2] = max(y, o[2]) + e[1] = min(x, e[1]); e[2] = min(y, e[2]) + end elseif model.space isa Agents.ContinuousSpace e = model.space.extent o = zero.(e) @@ -272,7 +282,6 @@ function set_axis_limits!(ax, model) end xlims!(ax, o[1], e[1]) ylims!(ax, o[2], e[2]) - is3d = length(o) == 3 - is3d && zlims!(ax, o[3], e[3]) + length(o) == 3 && zlims!(ax, o[3], e[3]) return end