Hi, I’m running the following code to create an animation with two axes within a figure.
using Makie, GLMakie
using Distributions
fig = Figure(resolution=(1600,800))
ax1 = Axis(fig[1,1],
title="Sampling Locations",
titlesize=30,
xlabelsize=20,
xminorticksvisible = true,
)
xlims!(ax1,0,1)
ylims!(ax1,0,1)
hidexdecorations!(ax1)
hideydecorations!(ax1)
ax1.aspect = AxisAspect(1)
ax2 = Axis(fig[1,2],
xticks = 0:0.1:1,
yticks = 0:0.1:1,
xlabel= "Error in network structure",
ylabel= "Error in interaction prediction",
xlabelsize=20,
ylabelsize=20,
xminorticksvisible = true,
yminorticksvisible = true,
)
xlims!(ax2, 0,1)
ylims!(ax2, 0,1)
ax2.aspect = AxisAspect(1)
np = 10
movingframes = 30 # number of frames that we points move
numsecondsstill = 2.5 # number of seconds that we stay still and draw trade-off curve
framerate = 25
coords = [0.1 .+ 0.8rand(np, 2) for p in 1:np]
deltas = [zeros(np,2),[(coords[p] .- coords[p-1]) .* (1/movingframes) for p in 2:np]...]
t_i = Observable(1)
p_i = Observable(1)
paramsets =
[
(β=-2.5, α=1.8, ox=0,oy=0, S=-1),
(β=-2.5, α=4.2, ox=0,oy=0, S=-1),
(β=-7.8, α=8.1, ox=0.3, oy=0.8, S=-1),
(β= -1.2, α=5.8, ox= -0.2, oy=0.1, S=-3.6),
(S=0.7, oy=1.3, β=1.7, ox=-1.2, α=2.2),
(S=1.6, oy=1, β=1.5, ox=-1.2, α=2.2),
(S=1.6, oy=0.8, β=1.5, ox=-1.2, α=2.2)
]
curvebase(x; α=1.8, β=-2.5, ox=0, oy=0,S=-1) = (-β / (1+exp(-1*S*α*(x+ox)))) + oy
currentcoord = @lift(coords[$p_i] .+ (deltas[$p_i] .* $t_i))
scatter!(ax1, currentcoord, markersize=25, marker=:xcross)
points = Observable(Point2f[])
scatterlines!(ax2, points, label="")
translate!(ax2.scene.plots[2], 0,0,10)
ptsperline = 20
σ = 0.05
record(fig, "moving_points.mp4", framerate = framerate) do io
cursor = 1
for p in 2:np
points[] = Point2f[]
for f in 1:movingframes
recordframe!(io)
t_i[] = f
currentcoord[] = coords[p-1] .+ (deltas[p] .*f)
end
frameswaiting = (numsecondsstill*framerate)
framesperpoint = floor(frameswaiting/ptsperline)
params = paramsets[rand(1:length(paramsets))]
for pt in 1:ptsperline+1
for f in 1:framesperpoint
recordframe!(io)
end
nextpt = Point2f((1/ptsperline)*(pt-1), curvebase((1/ptsperline)*(pt-1); params...) + σ*rand())
points[] = push!(points[], nextpt)
end
scatterlines!(ax2, points[], label="", color="lightgrey")
for f in 1:10
recordframe!(io)
end
end
end
When I run this, in the GL output I get what I expect, which is at the end of every line animating on the right panel, a new grey line replaces it (via scatterlines!(ax2, points[], label="", color="lightgrey")
) after it has finished running.
However, in the resulting mp4, everything works the same, except there is no grey line replacing the lines after it animates, and as the Observable points gets overwritten with points[] = Point2f[]
, the points in blue disappear at the end of each iteration of the for p in 2:np
loop. See this for an example
Is this a bug, and/or is there a better way to get this behavior without using the scatterlines!
call within the animation loop?
EDIT
I’ve fixed this by using a different structure of Observables, which I think is closer to what Makie intends,
the resulting code is below. However this still may reflect an actual bug
fig = Figure(resolution=(1600,800))
ax1 = Axis(fig[1,1],
title="Sampling Locations",
titlesize=30,
xlabelsize=20,
xminorticksvisible = true,
)
xlims!(ax1,0,1)
ylims!(ax1,0,1)
hidexdecorations!(ax1)
hideydecorations!(ax1)
ax1.aspect = AxisAspect(1)
ax2 = Axis(fig[1,2],
xticks = 0:0.1:1,
yticks = 0:0.1:1,
xlabel= "Error in network structure",
ylabel= "Error in interaction prediction",
xlabelsize=20,
ylabelsize=20,
xminorticksvisible = true,
yminorticksvisible = true,
)
xlims!(ax2, 0,1)
ylims!(ax2, 0,1)
ax2.aspect = AxisAspect(1)
np = 10
movingframes = 30 # number of frames that we points move
numsecondsstill = 2.5 # number of seconds that we stay still and draw trade-off curve
framerate = 25
coords = [0.1 .+ 0.8rand(np, 2) for p in 1:np]
deltas = [zeros(np,2),[(coords[p] .- coords[p-1]) .* (1/movingframes) for p in 2:np]...]
t_i = Observable(1)
p_i = Observable(1)
paramsets =
[
(β=-2.5, α=1.8, ox=0,oy=0, S=-1),
(β=-2.5, α=4.2, ox=0,oy=0, S=-1),
(β=-7.8, α=8.1, ox=0.3, oy=0.8, S=-1),
(β= -1.2, α=5.8, ox= -0.2, oy=0.1, S=-3.6),
(S=0.7, oy=1.3, β=1.7, ox=-1.2, α=2.2),
(S=1.6, oy=1, β=1.5, ox=-1.2, α=2.2),
(S=1.6, oy=0.8, β=1.5, ox=-1.2, α=2.2)
]
curvebase(x; α=1.8, β=-2.5, ox=0, oy=0,S=-1) = (-β / (1+exp(-1*S*α*(x+ox)))) + oy
currentcoord = @lift(coords[$p_i] .+ (deltas[$p_i] .* $t_i))
scatter!(ax1, currentcoord, markersize=25, marker=:xcross)
points = [Observable(Point2f[]) for p in 1:np]
colors = [Observable(:dodgerblue) for p in 1:np]
for (i,p) in enumerate(points)
scatterlines!(ax2, p, color=colors[i], label="")
end
ptsperline = 20
σ = 0.05
models = [1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 2]
record(fig, "moving_points.mp4", framerate = framerate) do io
cursor = 1
for p in 2:np
for f in 1:movingframes
recordframe!(io)
t_i[] = f
currentcoord[] = coords[p-1] .+ (deltas[p] .*f)
end
frameswaiting = (numsecondsstill*framerate)
framesperpoint = floor(frameswaiting/ptsperline)
params = paramsets[rand(1:length(paramsets))]
for pt in 1:ptsperline+1
for f in 1:framesperpoint
recordframe!(io)
end
nextpt = Point2f((1/ptsperline)*(pt-1), curvebase((1/ptsperline)*(pt-1); params...) + σ*rand())
points[p][] = push!(points[p][], nextpt)
end
colors[p][] = :lightgrey
for f in 1:10
recordframe!(io)
end
end
end