Skip to content

Conversation

@hbsmith
Copy link
Contributor

@hbsmith hbsmith commented Apr 28, 2025

Currently there's a bug in Agents where trying to hover inspect a 2D continuous plot throws a DimensionMismatch error. This seems analogous to #1090 , fixed in #1092 .

You can reproduce the bug by doing something like:

using Agents
using GLMakie
using AgentsExampleZoo

model = AgentsExampleZoo.flocking()

fig, abmobs = abmexploration(model)

fig

And trying to hover over any agent. You'll get an error like:

nested task error: DimensionMismatch: arrays could not be broadcast to a common size
    Stacktrace:
      [1] _bcs1(a::StaticArrays.SOneTo{2}, b::StaticArrays.SOneTo{3})
        @ StaticArrays ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:77
      [2] _bcs(shape::Tuple{StaticArrays.SOneTo{2}}, newshape::Tuple{StaticArrays.SOneTo{3}})
        @ Base.Broadcast ./broadcast.jl:522
      [3] broadcast_shape(::Tuple{StaticArrays.SOneTo{2}}, ::Tuple{StaticArrays.SOneTo{3}})
        @ Base.Broadcast ./broadcast.jl:516
      [4] static_combine_axes
        @ ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:20 [inlined]
      [5] _axes(bc::Base.Broadcast.Broadcasted{StaticArraysCore.StaticArrayStyle{1}, Nothing, typeof(-), Tuple{SVector{2, Float64}, Tuple{Float64, Float64, Float64}}}, ::Nothing)
        @ StaticArrays ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:25
      [6] axes
        @ ./broadcast.jl:234 [inlined]
      [7] static_axes(A::Base.Broadcast.Broadcasted{StaticArraysCore.StaticArrayStyle{1}, Nothing, typeof(-), Tuple{SVector{2, Float64}, Tuple{Float64, Float64, Float64}}})
        @ StaticArrays ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:22
      [8] static_combine_axes(A::Base.Broadcast.Broadcasted{StaticArraysCore.StaticArrayStyle{1}, Nothing, typeof(-), Tuple{SVector{2, Float64}, Tuple{Float64, Float64, Float64}}})
        @ StaticArrays ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:21
      [9] static_combine_axes
        @ ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:20 [inlined]
     [10] _axes(bc::Base.Broadcast.Broadcasted{StaticArraysCore.StaticArrayStyle{1}, Nothing, typeof(min), Tuple{Tuple{Float64, Float64, Float64}, Base.Broadcast.Broadcasted{StaticArraysCore.StaticArrayStyle{1}, Nothing, typeof(-), Tuple{SVector{2, Float64}, Tuple{Float64, Float64, Float64}}}}}, ::Nothing)
        @ StaticArrays ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:25
     [11] axes
        @ ./broadcast.jl:234 [inlined]
     [12] static_axes(A::Base.Broadcast.Broadcasted{StaticArraysCore.StaticArrayStyle{1}, Nothing, typeof(min), Tuple{Tuple{Float64, Float64, Float64}, Base.Broadcast.Broadcasted{StaticArraysCore.StaticArrayStyle{1}, Nothing, typeof(-), Tuple{SVector{2, Float64}, Tuple{Float64, Float64, Float64}}}}})
        @ StaticArrays ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:22
     [13] static_combine_axes (repeats 2 times)
        @ ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:20 [inlined]
     [14] instantiate
        @ ~/.julia/packages/StaticArrays/LSPcF/src/broadcast.jl:32 [inlined]
     [15] materialize
        @ ./broadcast.jl:872 [inlined]
     [16] euclidean_distance(p1::Tuple{Float64, Float64, Float64}, p2::Tuple{Float64, Float64, Float64}, space::ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)})
        @ Agents ~/.julia/dev/Agents/src/spaces/utilities.jl:42
     [17] euclidean_distance(p1::Tuple{Float64, Float64, Float64}, p2::Tuple{Float64, Float64, Float64}, model::StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG})
        @ Agents ~/.julia/dev/Agents/src/spaces/utilities.jl:26
     [18] distance_from_cell_center(pos::Tuple{Float64, Float64, Float64}, model::StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG})
        @ Agents ~/.julia/dev/Agents/src/spaces/continuous.jl:119
     [19] nearby_ids_approx(pos::Tuple{Float64, Float64, Float64}, model::StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG}, r::Float64)
        @ Agents ~/.julia/dev/Agents/src/spaces/continuous.jl:217
     [20] nearby_ids_exact(pos::Tuple{Float64, Float64, Float64}, model::StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG}, r::Float64)
        @ Agents ~/.julia/dev/Agents/src/spaces/continuous.jl:231
     [21] ids_to_inspect(model::StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG}, pos::Tuple{Float64, Float64, Float64})
        @ AgentsVisualizations ~/.julia/dev/Agents/ext/AgentsVisualizations/src/spaces/continuous.jl:43
     [22] agent2string(model::StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG}, pos::Tuple{Float64, Float64, Float64})
        @ AgentsVisualizations ~/.julia/dev/Agents/ext/AgentsVisualizations/src/spaces/abstract.jl:143
     [23] show_data(inspector::DataInspector, p::Plot{AgentsVisualizations._abmplot, Tuple{ABMObservable{Observable{StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}}}, idx::UInt32, source::Scatter{Tuple{Vector{Point{2, Float32}}}})
        @ AgentsVisualizations ~/.julia/dev/Agents/ext/AgentsVisualizations/src/spaces/abstract.jl:101
     [24] show_data_recursion(inspector::DataInspector, plot::Plot{AgentsVisualizations._abmplot, Tuple{ABMObservable{Observable{StandardABM{ContinuousSpace{2, true, Float64, typeof(Agents.no_vel_update)}, AgentsExampleZoo.Bird, Vector{AgentsExampleZoo.Bird}, Tuple{DataType}, typeof(AgentsExampleZoo.flocking_agent_step!), typeof(dummystep), Agents.Schedulers.Randomly, Nothing, TaskLocalRNG}}, Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}, Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}}}, idx::UInt32, source::Scatter{Tuple{Vector{Point{2, Float32}}}})
        @ Makie ~/.julia/packages/Makie/6KcTF/src/interaction/inspector.jl:373
     [25] show_data_recursion(inspector::DataInspector, plot::Scatter{Tuple{Vector{Point{2, Float32}}}}, idx::UInt32)
        @ Makie ~/.julia/packages/Makie/6KcTF/src/interaction/inspector.jl:343
     [26] on_hover(inspector::DataInspector)
        @ Makie ~/.julia/packages/Makie/6KcTF/src/interaction/inspector.jl:326
     [27] (::Makie.var"#1338#1342"{Scene, DataInspector})(ch::Channel{Nothing})
        @ Makie ~/.julia/packages/Makie/6KcTF/src/interaction/inspector.jl:291
     [28] (::Base.var"#739#740"{Makie.var"#1338#1342"{Scene, DataInspector}, Channel{Nothing}})()
        @ Base ./channels.jl:142
Error in callback:
TaskFailedException
Stacktrace:
  [1] check_channel_state
    @ ./channels.jl:188 [inlined]
  [2] put!
    @ ./channels.jl:356 [inlined]
  [3] (::Makie.var"#1339#1343"{Channel{Nothing}})(::Tuple{Float64, Float64}, ::Tuple{Float64, Float64})
    @ Makie ~/.julia/packages/Makie/6KcTF/src/interaction/inspector.jl:301
  [4] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::@Kwargs{})
    @ Base ./essentials.jl:1055
  [5] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:1052
  [6] (::Observables.OnAny)(value::Any)
    @ Observables ~/.julia/packages/Observables/YdEbO/src/Observables.jl:420
  [7] #invokelatest#2
    @ ./essentials.jl:1055 [inlined]
  [8] invokelatest
    @ ./essentials.jl:1052 [inlined]
  [9] notify
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:206 [inlined]
 [10] setindex!(observable::Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/YdEbO/src/Observables.jl:123
 [11] (::GLMakie.MousePositionUpdater)(::Makie.TickState)
    @ GLMakie ~/.julia/packages/GLMakie/YAome/src/events.jl:6
 [12] #invokelatest#2
    @ ./essentials.jl:1055 [inlined]
 [13] invokelatest
    @ ./essentials.jl:1052 [inlined]
 [14] notify
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:206 [inlined]
 [15] setindex!
    @ ~/.julia/packages/Observables/YdEbO/src/Observables.jl:123 [inlined]
 [16] pollevents(screen::GLMakie.Screen{GLFW.Window}, frame_state::Makie.TickState)
    @ GLMakie ~/.julia/packages/GLMakie/YAome/src/screen.jl:547
 [17] on_demand_renderloop(screen::GLMakie.Screen{GLFW.Window})
    @ GLMakie ~/.julia/packages/GLMakie/YAome/src/screen.jl:1038
 [18] renderloop(screen::GLMakie.Screen{GLFW.Window})
    @ GLMakie ~/.julia/packages/GLMakie/YAome/src/screen.jl:1066
 [19] (::GLMakie.var"#79#80"{GLMakie.Screen{GLFW.Window}})()
    @ GLMakie ~/.julia/packages/GLMakie/YAome/src/screen.jl:927

This pull request fixes that.

@codecov-commenter
Copy link

codecov-commenter commented Apr 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 85.23%. Comparing base (8b5b456) to head (b042605).
Report is 187 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #1159       +/-   ##
===========================================
+ Coverage   70.12%   85.23%   +15.10%     
===========================================
  Files          42       38        -4     
  Lines        2718     2614      -104     
===========================================
+ Hits         1906     2228      +322     
+ Misses        812      386      -426     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@Datseris Datseris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Developer's Docs subsection for spaces, can you put a note that spacesize also needs to be implemented if one wants plotting to work out of the box?

@hbsmith hbsmith mentioned this pull request May 20, 2025
@Datseris
Copy link
Member

@hbsmith can you put a note in the dev docs and then we merge this? or is anything else missing?

@hbsmith
Copy link
Contributor Author

hbsmith commented May 20, 2025

It's not clear to me what you want me to write or where exactly in the dev docs you want it to go. If you tell me what you want exactly, I can add it.

@Datseris
Copy link
Member

I don't understand the error and how this PR solves it. The positions in the flocking model are 2D. If you make a tuple out of them it is still 2D. What is the point if accessing them with 1:length(...)? Which is also a very expensive operation, we need to find a more performant way to do this.

@Tortar
Copy link
Member

Tortar commented May 28, 2025

if I remember correctly the problem is that pos contains some more dimensions than what you would expect for some reason. So I trust that this commit fixes the problem. I would specialize the function for ContinuousSpace though for safety.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants