JuliaDynamics / Agents.jl

Agent-based modeling framework in Julia
https://juliadynamics.github.io/Agents.jl/stable/
MIT License
725 stars 117 forks source link

Add GraphMakie dependency #863

Closed asgolovin closed 1 year ago

asgolovin commented 1 year ago

Fixes #827

The plotting recipe for graphs uses the graphplot! function from GraphMakie, but GraphMakie is not listed in dependencies and is never imported. This very short PR fixes this.

I added GraphMakie as a weak dependency since this is how other Makie libraries are listed, hope that's okay. :)

codecov-commenter commented 1 year ago

Codecov Report

Merging #863 (623e1d7) into main (e2e4384) will decrease coverage by 0.06%. The diff coverage is 0.00%.

@@            Coverage Diff             @@
##             main     #863      +/-   ##
==========================================
- Coverage   70.94%   70.89%   -0.06%     
==========================================
  Files          42       42              
  Lines        2795     2797       +2     
==========================================
  Hits         1983     1983              
- Misses        812      814       +2     
Files Changed Coverage Δ
ext/AgentsVisualizations/src/abmplot.jl 0.00% <0.00%> (ø)

:mega: We’re building smart automated test selection to slash your CI/CD build times. Learn more

Tortar commented 1 year ago

Thanks a lot for the fix, very much appreciated!!

But this doesn't seem to solve the issue entirely, on my computer running the code in #827 gives, when finally calling fig, this error:

julia> fig
Error showing value of type Figure:
ERROR: Buffer thickness does not have the same length as the other buffers.
        color has length 56
        vertex has length 56
        thickness has length 84
Stacktrace ```julia [1] error(s::String) @ Base ./error.jl:35 [2] GLMakie.GLAbstraction.GLVertexArray(bufferdict::Dict{Symbol, Any}, program::GLMakie.GLAbstraction.GLProgram) @ GLMakie.GLAbstraction ~/.julia/packages/GLMakie/toRaR/src/GLAbstraction/GLTypes.jl:233 [3] GLMakie.GLAbstraction.RenderObject(data::Dict{Symbol, Any}, program::GLMakie.GLVisualizeShader, pre::GLMakie.GLAbstraction.StandardPrerender, post::GLFW.Window, context::GLFW.Window) @ GLMakie.GLAbstraction ~/.julia/packages/GLMakie/toRaR/src/GLAbstraction/GLTypes.jl:445 [4] GLMakie.GLAbstraction.RenderObject(data::Dict{Symbol, Any}, program::GLMakie.GLVisualizeShader, pre::GLMakie.GLAbstraction.StandardPrerender, post::GLFW.Window) @ GLMakie.GLAbstraction ~/.julia/packages/GLMakie/toRaR/src/GLAbstraction/GLTypes.jl:404 [5] assemble_shader(data::Dict{Symbol, Any}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/glshaders/visualize_interface.jl:108 [6] draw_linesegments(screen::Any, positions::Observable{Vector{Point{2, Float32}}}, data::Dict) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/glshaders/lines.jl:156 [7] (::GLMakie.var"#209#210"{GLMakie.Screen{GLFW.Window}, LineSegments{Tuple{Vector{Point{2, Float32}}}}})(gl_attributes::Dict{Symbol, Any}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:331 [8] (::GLMakie.var"#177#180"{GLMakie.var"#209#210"{GLMakie.Screen{GLFW.Window}, LineSegments{Tuple{Vector{Point{2, Float32}}}}}, GLMakie.Screen{GLFW.Window}, Scene, LineSegments{Tuple{Vector{Point{2, Float32}}}}})() @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:135 [9] get!(default::GLMakie.var"#177#180"{GLMakie.var"#209#210"{GLMakie.Screen{GLFW.Window}, LineSegments{Tuple{Vector{Point{2, Float32}}}}}, GLMakie.Screen{GLFW.Window}, Scene, LineSegments{Tuple{Vector{Point{2, Float32}}}}}, h::Dict{UInt64, GLMakie.GLAbstraction.RenderObject}, key::UInt64) @ Base ./dict.jl:468 [10] cached_robj!(robj_func::GLMakie.var"#209#210"{GLMakie.Screen{GLFW.Window}, LineSegments{Tuple{Vector{Point{2, Float32}}}}}, screen::GLMakie.Screen{GLFW.Window}, scene::Scene, x::LineSegments{Tuple{Vector{Point{2, Float32}}}}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:103 [11] draw_atomic @ ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:314 [inlined] [12] insert!(screen::GLMakie.Screen{GLFW.Window}, scene::Scene, x::LineSegments{Tuple{Vector{Point{2, Float32}}}}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:151 [13] (::GLMakie.var"#183#184"{GLMakie.Screen{GLFW.Window}, Scene})(x::LineSegments{Tuple{Vector{Point{2, Float32}}}}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:156 [14] foreach(f::GLMakie.var"#183#184"{GLMakie.Screen{GLFW.Window}, Scene}, itr::Vector{AbstractPlot}) @ Base ./abstractarray.jl:3075 [15] insert! @ ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:153 [inlined] [16] (::GLMakie.var"#183#184"{GLMakie.Screen{GLFW.Window}, Scene})(x::Combined{GraphMakie.edgeplot, Tuple{Vector{GraphMakie.Line{Point{2, Float32}}}}}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:156 [17] foreach(f::GLMakie.var"#183#184"{GLMakie.Screen{GLFW.Window}, Scene}, itr::Vector{AbstractPlot}) @ Base ./abstractarray.jl:3075 [18] insert! @ ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:153 [inlined] [19] (::GLMakie.var"#183#184"{GLMakie.Screen{GLFW.Window}, Scene})(x::Combined{GraphMakie.graphplot, Tuple{SimpleGraph{Int64}}}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:156 [20] foreach(f::GLMakie.var"#183#184"{GLMakie.Screen{GLFW.Window}, Scene}, itr::Vector{AbstractPlot}) @ Base ./abstractarray.jl:3075 [21] insert!(screen::GLMakie.Screen{GLFW.Window}, scene::Scene, x::Combined{AgentsVisualizations._abmplot, Tuple{ABMObservable{Observable{StandardABM{GraphSpace{SimpleGraph{Int64}}, Agents.Models.PoorSoul, typeof(Agents.Schedulers.fastest), Dict{Symbol, Any}, Random.Xoshiro}}, typeof(Agents.Models.sir_agent_step!), typeof(dummystep), Nothing, Nothing, Nothing, Nothing, Bool, Observable{Int64}}}}) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/drawing_primitives.jl:153 [22] insertplots!(screen::GLMakie.Screen{GLFW.Window}, scene::Scene) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/screen.jl:447 [23] insertplots!(screen::GLMakie.Screen{GLFW.Window}, scene::Scene) (repeats 2 times) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/screen.jl:450 [24] display_scene!(screen::GLMakie.Screen{GLFW.Window}, scene::Scene) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/screen.jl:379 [25] GLMakie.Screen(scene::Scene, config::GLMakie.ScreenConfig; visible::Nothing, start_renderloop::Bool) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/screen.jl:396 [26] GLMakie.Screen(scene::Scene, config::GLMakie.ScreenConfig) @ GLMakie ~/.julia/packages/GLMakie/toRaR/src/screen.jl:392 [27] getscreen(::Module, ::Scene; screen_config::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}) @ Makie ~/.julia/packages/Makie/Ylh0P/src/display.jl:408 [28] getscreen @ ~/.julia/packages/Makie/Ylh0P/src/display.jl:391 [inlined] [29] display(figlike::Figure; backend::Module, inline::Bool, update::Bool, screen_config::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}) @ Makie ~/.julia/packages/Makie/Ylh0P/src/display.jl:161 [30] display(figlike::Figure) @ Makie ~/.julia/packages/Makie/Ylh0P/src/display.jl:131 [31] #invokelatest#2 @ ./essentials.jl:819 [inlined] [32] invokelatest @ ./essentials.jl:816 [inlined] [33] print_response(errio::IO, response::Any, show_value::Bool, have_color::Bool, specialdisplay::Union{Nothing, AbstractDisplay}) @ REPL ~/julia-1.9.3/share/julia/stdlib/v1.9/REPL/src/REPL.jl:305 [34] (::REPL.var"#57#58"{REPL.LineEditREPL, Pair{Any, Bool}, Bool, Bool})(io::Any) @ REPL ~/julia-1.9.3/share/julia/stdlib/v1.9/REPL/src/REPL.jl:287 [35] with_repl_linfo(f::Any, repl::REPL.LineEditREPL) @ REPL ~/julia-1.9.3/share/julia/stdlib/v1.9/REPL/src/REPL.jl:557 [36] print_response(repl::REPL.AbstractREPL, response::Any, show_value::Bool, have_color::Bool) @ REPL ~/julia-1.9.3/share/julia/stdlib/v1.9/REPL/src/REPL.jl:285 [37] (::REPL.var"#do_respond#80"{Bool, Bool, REPL.var"#93#103"{REPL.LineEditREPL, REPL.REPLHistoryProvider}, REPL.LineEditREPL, REPL.LineEdit.Prompt})(s::REPL.LineEdit.MIState, buf::Any, ok::Bool) @ REPL ~/julia-1.9.3/share/julia/stdlib/v1.9/REPL/src/REPL.jl:899 [38] #invokelatest#2 @ ./essentials.jl:819 [inlined] [39] invokelatest @ ./essentials.jl:816 [inlined] [40] run_interface(terminal::REPL.Terminals.TextTerminal, m::REPL.LineEdit.ModalInterface, s::REPL.LineEdit.MIState) @ REPL.LineEdit ~/julia-1.9.3/share/julia/stdlib/v1.9/REPL/src/LineEdit.jl:2647 [41] run_frontend(repl::REPL.LineEditREPL, backend::REPL.REPLBackendRef) @ REPL ~/julia-1.9.3/share/julia/stdlib/v1.9/REPL/src/REPL.jl:1300 [42] (::REPL.var"#62#68"{REPL.LineEditREPL, REPL.REPLBackendRef})() @ REPL ./task.jl:514 ```

Does it happen also on your computer or the graph is showed correctly?

AldoGl commented 1 year ago

Thanks a lot for the fix, very much appreciated!!

But this doesn't seem to solve the issue entirely, on my computer running the code in #827 gives, when finally calling fig, this error:

julia> fig
Error showing value of type Figure:
ERROR: Buffer thickness does not have the same length as the other buffers.
        color has length 56
        vertex has length 56
        thickness has length 84

Stacktrace Does it happen also on your computer or the graph is showed correctly?

@Tortar, I can confirm that I also get this new problem after the fix from @asgolovin.

But the new error is easy to solve: you can just comment out the edge_width variable from the graphplotkwargs within the example I provided in #827.

I think this PR should be accepted! Thank you @asgolovin

Tortar commented 1 year ago

thanks @AldoGl to have tried it out!

Tortar commented 1 year ago

I actually fixed the code without commenting out that section:

using Agents
using ColorTypes
using Graphs
using GLMakie

using Graphs: edges
using GraphMakie: Shell
using GraphMakie: graphplot!
using GraphMakie: graphplot

sir_model, sir_agent_step!, sir_model_step! = Models.sir()
city_size(agents_here) = 0.005 * length(agents_here)

function city_color(agents_here)
    return RGB(0.5 , 0.5, 0)
end

edge_color(model) = fill((:grey, 0.25), ne(model.space.graph))

function edge_width(model)
    w = zeros(ne(model.space.graph))
    for e in edges(model.space.graph)
        w[e.src] = 0.004 * length(model.space.stored_ids[e.src])
        w[e.dst] = 0.004 * length(model.space.stored_ids[e.dst])
    end
    return w
end

graphplotkwargs = (
    layout = Shell(), # node positions
    arrow_show = false, # hide directions of graph edges
    edge_color = edge_color, # change edge colors and widths with own functions
    edge_width = edge_width,
    edge_plottype = :linesegments # needed for tapered edge widths
)

fig, ax, abmobs = abmplot(sir_model;
    agent_step! = sir_agent_step!, model_step! = sir_model_step!,
    as = city_size, ac = city_color, graphplotkwargs)

fig

Indeed this was a problem in the example itself :-)

so the example can be fixed in another PR anyway