Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

abmvideo not working for prey-predator example with WGLMakie #1081

Open
danvinci opened this issue Oct 5, 2024 · 5 comments
Open

abmvideo not working for prey-predator example with WGLMakie #1081

danvinci opened this issue Oct 5, 2024 · 5 comments
Labels
bug Something isn't working plotting

Comments

@danvinci
Copy link

danvinci commented Oct 5, 2024

Describe the bug

Screenshot 2024-10-06 at 00 38 01

Has this been encountered before?
(I'm testing it in Pluto with WGLMakie)

Minimal Working Example

begin

	@agent struct Sheep(GridAgent{2})
    energy::Float64
    reproduction_prob::Float64
    Δenergy::Float64
	end
	
	@agent struct Wolf(GridAgent{2})
	    energy::Float64
	    reproduction_prob::Float64
	    Δenergy::Float64
	end



	function eat!(sheep::Sheep, model)
	   
		if model.fully_grown[sheep.pos...]
	        sheep.energy += sheep.Δenergy
	        model.fully_grown[sheep.pos...] = false
	    end
	    
		return
	end
	
	function eat!(wolf::Wolf, sheep::Sheep, model)
	    remove_agent!(sheep, model)
	    wolf.energy += wolf.Δenergy
	    return
	end



	function sheepwolf_step!(sheep::Sheep, model)
	    
		randomwalk!(sheep, model)
	    sheep.energy -= 1
	    
		if sheep.energy < 0
	        remove_agent!(sheep, model)
	        return
	    end
	    
		eat!(sheep, model)
	    
		if rand(abmrng(model)) ≤ sheep.reproduction_prob
	        sheep.energy /= 2
	        replicate!(sheep, model)
	    end
	end
	
	function sheepwolf_step!(wolf::Wolf, model)
	    
		randomwalk!(wolf, model; ifempty=false)
	    wolf.energy -= 1
	   
		if wolf.energy < 0
	        remove_agent!(wolf, model)
	        return
	    end
	    
		# If there is any sheep on this grid cell, it's dinner time!
	    dinner = first_sheep_in_position(wolf.pos, model)
	    	!isnothing(dinner) && eat!(wolf, dinner, model)
	   
		if rand(abmrng(model)) ≤ wolf.reproduction_prob
	        wolf.energy /= 2
	        replicate!(wolf, model)
	    end
	end
	
	function first_sheep_in_position(pos, model)
	    ids = ids_in_position(pos, model)
	    j = findfirst(id -> model[id] isa Sheep, ids)
	    isnothing(j) ? nothing : model[ids[j]]::Sheep
	end



        function grass_step!(model)
            @inbounds for p in positions(model) # we don't have to enable bound checking
                if !(model.fully_grown[p...])
                    if model.countdown[p...] ≤ 0
                        model.fully_grown[p...] = true
                        model.countdown[p...] = model.regrowth_time
                    else
                        model.countdown[p...] -= 1
                    end
                end
            end
        end


        function initialize_model(;
                n_sheep = 100,
                n_wolves = 50,
                dims = (20, 20),
                regrowth_time = 30,
                Δenergy_sheep = 4,
                Δenergy_wolf = 20,
                sheep_reproduce = 0.04,
                wolf_reproduce = 0.05,
                seed = 23182,
            )
        
            rng = MersenneTwister(seed)
            space = GridSpace(dims, periodic = true)
            
	        
	        # Model properties contain the grass as two arrays: whether it is fully grown
            # and the time to regrow. Also have static parameter `regrowth_time`.
            # Notice how the properties are a `NamedTuple` to ensure type stability.
            properties = (
                fully_grown = falses(dims),
                countdown = zeros(Int, dims),
                regrowth_time = regrowth_time,
            )
            model = StandardABM(Union{Sheep, Wolf}, space;
                agent_step! = sheepwolf_step!, model_step! = grass_step!,
                properties, rng, scheduler = Schedulers.Randomly(), warn = false
            )
            
	        
	        # Add agents
            for _ in 1:n_sheep
                energy = rand(abmrng(model), 1:(Δenergy_sheep*2)) - 1
                add_agent!(Sheep, model, energy, sheep_reproduce, Δenergy_sheep)
            end
            for _ in 1:n_wolves
                energy = rand(abmrng(model), 1:(Δenergy_wolf*2)) - 1
                add_agent!(Wolf, model, energy, wolf_reproduce, Δenergy_wolf)
            end
            
	        # Add grass with random initial growth
            for p in positions(model)
                fully_grown = rand(abmrng(model), Bool)
                countdown = fully_grown ? regrowth_time : rand(abmrng(model), 1:regrowth_time) - 1
                model.countdown[p...] = countdown
                model.fully_grown[p...] = fully_grown
            end
        
	        
            return model
        end



	offset(a) = a isa Sheep ? (-0.1, -0.1*rand()) : (+0.1, +0.1*rand())
	ashape(a) = a isa Sheep ? :circle : :utriangle
	acolor(a) = a isa Sheep ? RGBAf(1.0, 1.0, 1.0, 0.8) : RGBAf(0.2, 0.2, 0.3, 0.8)


	grasscolor(model) = model.countdown ./ model.regrowth_time
	heatkwargs = (colormap = [:orange, :green], colorrange = (0, 0.75))
	


          plotkwargs = (;
              agent_color = acolor,
              agent_size = 25,
              agent_marker = ashape,
              offset,
              agentsplotkwargs = (strokewidth = 1.0, strokecolor = :black),
              heatarray = grasscolor,
              heatkwargs = heatkwargs,
          )


        sheepwolfgrass = initialize_model()


	fig, ax, abmobs = abmplot(sheepwolfgrass; plotkwargs...) 
	fig

	sheep(a) = a isa Sheep
	wolf(a) = a isa Wolf
	count_grass(model) = count(model.fully_grown)

	steps = 1000
	adata = [(sheep, count), (wolf, count)]
	mdata = [count_grass]
	adf, mdf = run!(sheepwolfgrass, steps; adata, mdata)

	function plot_population_timeseries(adf, mdf)
	    figure = Figure(size = (600, 400))
	    ax = figure[1, 1] = Axis(figure; xlabel = "Step", ylabel = "Population")
	    sheepl = lines!(ax, adf.time, adf.count_sheep, color = :cornsilk4)
	    wolfl = lines!(ax, adf.time, adf.count_wolf, color = RGBAf(0.2, 0.2, 0.3))
	    grassl = lines!(ax, mdf.time, mdf.count_grass, color = :green)
	    figure[1, 2] = Legend(figure, [sheepl, wolfl, grassl], ["Sheep", "Wolves", "Grass"])
	    figure
	end
	
	plot_population_timeseries(adf, mdf)

	stable_params = (;
	    n_sheep = 140,
	    n_wolves = 20,
	    dims = (30, 30),
	    Δenergy_sheep = 5,
	    sheep_reproduce = 0.31,
	    wolf_reproduce = 0.06,
	    Δenergy_wolf = 30,
	    seed = 71758,
	)
	
	sheepwolfgrass_2 = initialize_model(;stable_params...)
	adf_2, mdf_2 = run!(sheepwolfgrass_2, 2000; adata, mdata)
	plot_population_timeseries(adf_2, mdf_2)

	
        abmvideo(
	          "sheepwolf.mp4",
	          sheepwolfgrass_2;
	          frames = 100,
	          framerate = 8,
	          title = "Sheep Wolf Grass",
	          plotkwargs...,
        )

Agents.jl version v6.1.7

@Datseris
Copy link
Member

Datseris commented Oct 6, 2024

I haven't seen such an error before. Can you tell us whether you've changed any parts of the code you copied from the example? If so, which parts? If you haven't changed any parts then this is a problem with Makie not Agents. Can you make a simple video with record of Makie or GLMakie?

@Datseris Datseris added bug Something isn't working plotting labels Oct 6, 2024
@Datseris
Copy link
Member

Datseris commented Oct 6, 2024

Also, in the future, please paste the error stacktrace as well, not just the first line.

@danvinci
Copy link
Author

danvinci commented Oct 8, 2024

I used the examples as-is. If you use the code above, do you replicate the error?

this is the rest of the error message:

Stack trace
Here is what happened, the most recent locations are first:

display(screen::WGLMakie.Screen, scene::Makie.Scene; unused::@Kwargs{}) @ display.jl:277
display @ display.jl:267
colorbuffer(screen::WGLMakie.Screen) @ display.jl:301
colorbuffer(screen::WGLMakie.Screen, format::Makie.ImageStorageFormat) @ display.jl:392
recordframe!(io::Makie.VideoStream) @ ffmpeg-util.jl:285
(::AgentsVisualizations.var"#77#80"{Int64, Agents.StandardABM{Agents.GridSpace{2, true}, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}, Dict{Int64, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}}, Tuple{DataType, DataType}, typeof(Main.var"workspace#11".sheepwolf_step!), typeof(Main.var"workspace#11".grass_step!), Agents.Schedulers.Randomly, @NamedTuple{fully_grown::BitMatrix, countdown::Matrix{Int64}, regrowth_time::Int64}, Random.MersenneTwister}, Agents.ABMObservable{Observables.Observable{Agents.StandardABM{Agents.GridSpace{2, true}, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}, Dict{Int64, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}}, Tuple{DataType, DataType}, typeof(Main.var"workspace#11".sheepwolf_step!), typeof(Main.var"workspace#11".grass_step!), Agents.Schedulers.Randomly, @NamedTuple{fully_grown::BitMatrix, countdown::Matrix{Int64}, regrowth_time::Int64}, Random.MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observables.Observable{Int64}, Observables.Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}, Observables.Observable{Int64}})(io::Makie.VideoStream) @ convenience.jl:122
Record(func::AgentsVisualizations.var"#77#80"{Int64, Agents.StandardABM{Agents.GridSpace{2, true}, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}, Dict{Int64, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}}, Tuple{DataType, DataType}, typeof(Main.var"workspace#11".sheepwolf_step!), typeof(Main.var"workspace#11".grass_step!), Agents.Schedulers.Randomly, @NamedTuple{fully_grown::BitMatrix, countdown::Matrix{Int64}, regrowth_time::Int64}, Random.MersenneTwister}, Agents.ABMObservable{Observables.Observable{Agents.StandardABM{Agents.GridSpace{2, true}, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}, Dict{Int64, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}}, Tuple{DataType, DataType}, typeof(Main.var"workspace#11".sheepwolf_step!), typeof(Main.var"workspace#11".grass_step!), Agents.Schedulers.Randomly, @NamedTuple{fully_grown::BitMatrix, countdown::Matrix{Int64}, regrowth_time::Int64}, Random.MersenneTwister}}, Nothing, Nothing, Nothing, Nothing, Bool, Observables.Observable{Int64}, Observables.Observable{Tuple{Base.RefValue{Int64}, Vector{Int64}}}}, Observables.Observable{Int64}}, figlike::Makie.Figure; kw_args::@Kwargs{format::SubString{String}, visible::Bool, framerate::Int64, compression::Int64}) @ recording.jl:166
record(func::Function, figlike::Makie.Figure, path::String; kw_args::@Kwargs{framerate::Int64, compression::Int64}) @ recording.jl:148
record @ recording.jl:146
abmvideo(file::String, model::Agents.StandardABM{Agents.GridSpace{2, true}, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}, Dict{Int64, Union{Main.var"workspace#11".Sheep, Main.var"workspace#11".Wolf}}, Tuple{DataType, DataType}, typeof(Main.var"workspace#11".sheepwolf_step!), typeof(Main.var"workspace#11".grass_step!), Agents.Schedulers.Randomly, @NamedTuple{fully_grown::BitMatrix, countdown::Matrix{Int64}, regrowth_time::Int64}, Random.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{resize_to::Int64, agent_color::typeof(Main.var"workspace#11".acolor), agent_size::Int64, agent_marker::typeof(Main.var"workspace#11".ashape), offset::typeof(Main.var"workspace#11".offset), agentsplotkwargs::@NamedTuple{strokewidth::Float64, strokecolor::Symbol}, heatarray::typeof(Main.var"workspace#11".grasscolor), heatkwargs::@NamedTuple{colormap::Vector{Symbol}, colorrange::Tuple{Int64, Float64}}}) @ convenience.jl:120
abmvideo @ convenience.jl:96

Not sure how I could record a video using Makie, I'm pretty new to the ecosystem - any pointers? 😓

@Tortar
Copy link
Member

Tortar commented Oct 8, 2024

mmmh WGLMakie has never been thoroughly tested, and in some of my experiments in the past it didn't work on some other model, can you use CairoMakie or GLMakie?

If someone wants to try to fix the problems with WGLMakie it would be fantastic

@Tortar Tortar changed the title abmvideo not working for prey-predator example abmvideo not working for prey-predator example with WGLMakie Oct 8, 2024
@Datseris
Copy link
Member

Datseris commented Oct 8, 2024

I've never used WGLMakie, sorry. I've missed the detail that you use this with Pluto and WGLMakie.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working plotting
Projects
None yet
Development

No branches or pull requests

3 participants