I am trying to visualize a sequence of 2D scatter plots using the Node/Observable feature to achieve fast update rates. However, I run into errors if the number of points changes over time as the plotting function will fail in cases where the number of x and y coordinates is not the same. Is there a way lock the scene update until all Nodes are updated?
Here is a MWE
using Makie
px = Node(zeros(1))
py = Node(zeros(1))
scatter(px, py) |> display
for t in 1:10
# generate random dummy data (number of points may vary over time)
n_points = rand(5:10)
push!(px, rand(n_points))
push!(py, rand(n_points))
sleep(0.1)
end
Do I have to introduce fake-dependencies between nodes to make this work? Or is there some sort of mutex for Makie scenes?
You could use a Vector{Point} instead? That would make sure x and y update synchronously.
This does not really solve the issue. Sometimes, one might wish to also update other attributes (e.g. the color of each point in a scatter plot). Fake dependencies work but I was just wondering whether there is a more elegant solution.
Update: I have noticed that for rendering with arrows, even fake-dependencies between observables do not solve the issue. Furthermore, for arrows, Vector{Point} is not a helpful workaround because any method of arrows still requires multiple arguments who's dimensions must all match:
`arrows(points, directions; kwargs...)`
`arrows(x, y, u, v)`
`arrows(x::AbstractVector, y::AbstractVector, u::AbstractMatrix, v::AbstractMatrix)`
`arrows(x, y, z, u, v, w)`
Yeaah, this is annoying ...
I usually update the underlying vectors in place, and then just update one of the observable, once all vectors have the same length:
using Makie
px = zeros(1)
py = zeros(1)
px_n = Node(px)
py_n = Node(py)
scatter(px_n, py_n) |> display
for t in 1:10
# generate random dummy data (number of points may vary over time)
n_points = rand(5:10)
empty!(px); empty!(py);
append!(px, rand(n_points))
append!(py, rand(n_points))
py_n[] = py_n[]
sleep(0.1)
end
Thank you for your reply. I guess that is a workaround that should work. Are there any plans to support more synchronized update of nodes (e.g. by locking the scene)? Or are there other reasons not to support this?
I should have never allowed to update individual vectors :D This was a bad design decision... The plan is to support this in the future:
particles = Buffer(colors = colors, positions = positions)
scatter(particles)
# Or
particles = [(color=color, position=position), (...)]
scatter(particles)
... And internally map to this!
Yeaah, this is annoying ...
I usually update the underlying vectors in place, and then just update one of the observable, once all vectors have the same length:using Makie px = zeros(1) py = zeros(1) px_n = Node(px) py_n = Node(py) scatter(px_n, py_n) |> display for t in 1:10 # generate random dummy data (number of points may vary over time) n_points = rand(5:10) empty!(px); empty!(py); append!(px, rand(n_points)) append!(py, rand(n_points)) py_n[] = py_n[] sleep(0.1) end
This workaround does not seem to work for arrows for some reason I fail to understand. The code below fails with ERROR: DimensionMismatch("dimensions must match"):
using Makie
px = zeros(1)
py = zeros(1)
pu = zeros(1)
pv = zeros(1)
px_n = Node(px)
py_n = Node(py)
pu_n = Node(pu)
pv_n = Node(pv)
arrows(px_n, py_n, pu_n, pv_n) |> display
for t in 1:10
# generate random dummy data (number of points may vary over time)
n_points = rand(5:10)
empty!(px); empty!(py); empty!(pu); empty!(pv)
append!(px, rand(n_points))
append!(py, rand(n_points))
append!(pu, rand(n_points))
append!(pv, rand(n_points))
py_n[] = py_n[]
sleep(0.1)
end
Hm, that's because there is an extra level of indirection to construct the points out of x and y, I think...
Try:
using Makie
pxy = [Point2f0(0)]
puv = [Vec2f0(1)]
pxy_n = Node(pxy)
puv_n = Node(puv)
arrows(pxy_n, puv_n) |> display
for t in 1:10
# generate random dummy data (number of points may vary over time)
n_points = rand(5:10)
empty!(pxy); empty!(puv);
append!(pxy, rand(Point2f0, n_points))
append!(puv, rand(Vec2f0, n_points))
pxy_n[] = pxy_n[]
sleep(0.1)
end
Okay, that seems to work. Really subtle...
... bump this: I would like to update mesh coordinates and mesh connectivity at the same time. However what worked for arrows didn't work for mesh...
Most helpful comment
Hm, that's because there is an extra level of indirection to construct the points out of x and y, I think...
Try: