Skip to content

Plotting building data causes AgentsOSMVisualization to throw BoundsError  #1102

@Ardnys

Description

@Ardnys

Describe the bug
I need to plot buildings as well as road networks for my project so I checked out OSMMakie and followed the example provided in the README. I integrated it into Zombie Outbreak example to test it and it threw a BoundError trying to access 3rd element of a 2 element Vector.

Minimal Working Example
I changed the Zombie example to include building data

# # Zombie Outbreak in a City
using Agents
using Random

@agent struct Zombie(OSMAgent)
    infected::Bool
    speed::Float64
end

function initialise_zombies(; seed = 1234)
    map_path = OSM.test_map()
    properties = Dict(:dt => 1 / 60)
    model = StandardABM(
        Zombie,
        OpenStreetMapSpace(map_path);
        agent_step! = zombie_step!,
        properties = properties,
        rng = Random.MersenneTwister(seed)
    )

    for id in 1:100
        start = random_position(model) # At an intersection
        speed = rand(abmrng(model)) * 5.0 + 2.0 # Random speed from 2-7kmph
        human = add_agent!(start, Zombie, model, false, speed)
        OSM.plan_random_route!(human, model; limit = 50) # try 50 times to find a random route
    end
    ## We'll add patient zero at a specific (longitude, latitude)
    start = OSM.nearest_road((9.9351811, 51.5328328), model)
    finish = OSM.nearest_node((9.945125635913511, 51.530876112711745), model)

    speed = rand(abmrng(model)) * 5.0 + 2.0 # Random speed from 2-7kmph
    zombie = add_agent!(start, model, true, speed)
    plan_route!(zombie, finish, model)
    ## This function call creates & adds an agent, see `add_agent!`
    return model
end

function zombie_step!(agent, model)
    ## Each agent will progress along their route
    ## Keep track of distance left to move this step, in case the agent reaches its
    ## destination early
    distance_left = move_along_route!(agent, model, agent.speed * model.dt)

    if is_stationary(agent, model) && rand(abmrng(model)) < 0.1
        ## When stationary, give the agent a 10% chance of going somewhere else
        OSM.plan_random_route!(agent, model; limit = 50)
        ## Start on new route, moving the remaining distance
        move_along_route!(agent, model, distance_left)
    end

    if agent.infected
        ## Agents will be infected if they get too close (within 10m) to a zombie.
        map(i -> model[i].infected = true, nearby_ids(agent, model, 0.01))
    end
    return
end

# ## Visualising the fall of humanity

# Notice that to visualize Open Street Maps, the package OSMMakie.jl must be loaded
# as well, besides any Makie plotting backend such as CairoMakie.jl.
using CairoMakie, OSMMakie
zombie_color(agent) = agent.infected ? :green : :black
zombie_size(agent) = agent.infected ? 10 : 8
zombies = initialise_zombies()

# ====== begin changed lines ================
# add LightOSM for building data
using LightOSM

# load as Buildings Dict
buildings = buildings_from_file(OSM.test_map());

spaceplotkwargs = (;
    buildings = buildings
)
# ====== end changed lines ================

abmvideo("outbreak.mp4", zombies;
    title = "Zombie outbreak", framerate = 15, frames = 200,
    agent_color = zombie_color, agent_size = zombie_size,
    spaceplotkwargs = spaceplotkwargs # also here
)

Stacktrace

1-element ExceptionStack:
LoadError: BoundsError: attempt to access 2-element Vector{Plot} at index [3]
Stacktrace:
  [1] getindex(A::Vector{Plot}, i1::Int64)
    @ Base .\essentials.jl:13
  [2] osmplot!(ax::Axis, p::Plot{AgentsVisualizations._abmplot, Tuple{ABMObservable{Observable{StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}}}; kwargs::@Kwargs{buildings::Observable{Any}})
    @ AgentsOSMVisualizations C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsOSMVisualizations\AgentsOSMVisualizations.jl:20
  [3] osmplot!
    @ C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsOSMVisualizations\AgentsOSMVisualizations.jl:15 [inlined]
  [4] #spaceplot!#1
    @ C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsOSMVisualizations\src\spaces\openstreetmap.jl:25 [inlined]
  [5] plot!(p::Plot{AgentsVisualizations._abmplot, Tuple{ABMObservable{Observable{StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}}})
    @ AgentsVisualizations C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsVisualizations\src\abmplot.jl:153
  [6] connect_plot!(parent::Scene, plot::Plot{AgentsVisualizations._abmplot, Tuple{ABMObservable{Observable{StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}}})
    @ Makie C:\Users\ardnys\.julia\packages\Makie\XQfuO\src\interfaces.jl:395
  [7] plot!
    @ C:\Users\ardnys\.julia\packages\Makie\XQfuO\src\interfaces.jl:412 [inlined]
  [8] plot!(ax::Axis, plot::Plot{AgentsVisualizations._abmplot, Tuple{ABMObservable{Observable{StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}}})
    @ Makie C:\Users\ardnys\.julia\packages\Makie\XQfuO\src\figureplotting.jl:412
  [9] _create_plot!(::Function, ::Dict{Symbol, Any}, ::Axis, ::ABMObservable{Observable{StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}})
    @ Makie C:\Users\ardnys\.julia\packages\Makie\XQfuO\src\figureplotting.jl:381
 [10] _abmplot!(::Axis, ::Vararg{Any}; kw::@Kwargs{ax::Axis, add_controls::Bool, params::Dict{Any, Any}, warn_deprecation::Bool, agent_color::typeof(zombie_color), agent_size::typeof(zombie_size), spaceplotkwargs::@NamedTuple{buildings::Dict{Integer, Building}}})
    @ AgentsVisualizations C:\Users\ardnys\.julia\packages\MakieCore\NeQjl\src\recipes.jl:189
 [11] abmplot!(ax::Axis, abmobs::ABMObservable{Observable{StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}; params::Dict{Any, Any}, add_controls::Bool, enable_inspection::Bool, enable_space_checks::Bool, kwargs::@Kwargs{warn_deprecation::Bool, agent_color::typeof(zombie_color), agent_size::typeof(zombie_size), spaceplotkwargs::@NamedTuple{buildings::Dict{Integer, Building}}})
    @ AgentsVisualizations C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsVisualizations\src\abmplot.jl:80
 [12] abmplot!
    @ C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsVisualizations\src\abmplot.jl:61 [inlined]
 [13] #abmplot!#3
    @ C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsVisualizations\src\abmplot.jl:38 [inlined]
 [14] abmplot!
    @ C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsVisualizations\src\abmplot.jl:22 [inlined]
 [15] abmplot(model::StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}; figure::@NamedTuple{size::Tuple{Int64, Int64}}, axis::@NamedTuple{title::Observable{String}, titlealign::Symbol}, warn_deprecation::Bool, kwargs::@Kwargs{add_controls::Bool, agent_color::typeof(zombie_color), agent_size::typeof(zombie_size), spaceplotkwargs::@NamedTuple{buildings::Dict{Integer, Building}}})
    @ AgentsVisualizations C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsVisualizations\src\abmplot.jl:9
 [16] abmvideo(file::String, model::StandardABM{Agents.OSM.OpenStreetMapSpace, Zombie, Dict{Int64, Zombie}, Tuple{DataType}, typeof(zombie_step!), typeof(dummystep), typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}; spf::Nothing, dt::Int64, framerate::Int64, frames::Int64, title::String, showstep::Bool, figure::@NamedTuple{size::Tuple{Int64, Int64}}, axis::@NamedTuple{}, recordkwargs::@NamedTuple{compression::Int64}, kwargs::@Kwargs{agent_color::typeof(zombie_color), agent_size::typeof(zombie_size), spaceplotkwargs::@NamedTuple{buildings::Dict{Integer, Building}}})
    @ AgentsVisualizations C:\Users\ardnys\.julia\packages\Agents\W7Wee\ext\AgentsVisualizations\src\convenience.jl:115
 [17] top-level scope
    @ C:\Users\ardnys\Dev\AgentsTest\bug_issue\issue.jl:79
 [18] include(fname::String)
    @ Base.MainInclude .\client.jl:494
 [19] top-level scope
    @ REPL[1]:1
in expression starting at C:\Users\ardnys\Dev\AgentsTest\bug_issue\issue.jl:79

Agents.jl version
Julia version 1.10.6 (Precompile of AgentsVisualizations fail in 1.11.1)
Agents v6.1.11
CairoMakie v0.12.15
LightOSM v0.3.1
OSMMakie v0.0.10

My Workaround

    osm_plot.plots[1].plots[3].inspectable[] = false

Replacing 3 with 2 or commenting it out makes the code compile and display the buildings. I am not sure how inspectables work so that's my current solution to see some buildings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingopen street mapRelated to the Open Street Map spaceplotting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions