JuliaGeometry / MeshViz.jl

Makie.jl recipes for visualization of Meshes.jl

Home Page:https://github.com/JuliaGeometry/Meshes.jl

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Interaction with Observables is not working

lucifer1004 opened this issue · comments

The following code displays the window but the contents do not change, and the recorded video does not change, either.

time = GLMakie.Observable(0.0)
radius = GLMakie.@lift $time % 1.0 + 0.2
ball = GLMakie.@lift Meshes.Ball(rand(Meshes.Point3), $radius)
fig = MeshViz.viz(ball; color=GLMakie.@lift [:green, :blue, :red, :gray][Int(ceil($time * 11.2) % 4 + 1)])
framerate = 30
timestamps = range(0, 100, step=1/framerate)
GLMakie.display(fig)

GLMakie.record(fig, "time_animation.mp4", timestamps; framerate = framerate) do t
	time[] = t
end

In contrast, the following code works

time = GLMakie.Observable(0.0)

xs = range(0, 7, length=40)

ys_1 = GLMakie.@lift(sin.(xs .- $time))
ys_2 = GLMakie.@lift(cos.(xs .- $time) .+ 3)

fig = GLMakie.lines(xs, ys_1, color = :blue, linewidth = 4,
    axis = (title = GLMakie.@lift("t = $(round($time, digits = 1))"),))
GLMakie.scatter!(xs, ys_2, color = :red, markersize = 15)
	
framerate = 30
timestamps = range(0, 100, step=1/framerate)
GLMakie.display(fig)
	
GLMakie.record(fig, "time_animation.mp4", timestamps; framerate = framerate) do t
	time[] = t
end

Can you create a MWE with a slider where you change the observable interactively and the visualization doesn't change? That will facilitate investigating this further.

You can try this:

using GLMakie: GLMakie
using Meshes: Meshes
using MeshViz: MeshViz

time = GLMakie.Observable(0.0)
radius = GLMakie.@lift $time % 1.0 + 0.2
ball = GLMakie.@lift Meshes.Ball(rand(Meshes.Point3), $radius)
fig = MeshViz.viz(ball; color=GLMakie.@lift [:green, :blue, :red, :gray][Int(ceil($time * 11.2) % 4 + 1)])
framerate = 30
timestamps = range(0, 100, step=1 / framerate)
screen = GLMakie.display(fig)
GLMakie.on(fig.figure.scene.events.keyboardbutton) do event
    @show event
    if event.key == GLMakie.Keyboard._1
        time[] += 0.1
        @show time
    end
end

Press 1 on the popped window and the verbose information should tell that the event is triggered and the time is changed. But the scene does not change.

Remember to run it from the REPL.

The code you shared errors saying that Keyboard is not defined. Can you please share an example that you ran yourself? I've added the GLMakie.Keyboard prefix. Just wanted to double check that you ran the exact same code.

This issue seems to affect all recipes for all geometries, which indicates that maybe we are pre-processing the colors provided by the user in a way that inhibits Observables to take action. @jkrumbiegel do you see any issue with the following code?

color = plot[:color][]
alpha = plot[:alpha][]
colorscheme = plot[:colorscheme][]
facetcolor = plot[:facetcolor][]
showfacets = plot[:showfacets][]
# process color spec into colorant
colorant = process(color, colorscheme, alpha)

We are extracting the content of the color observable, doing some pre-processing and then passing a new vector of colorant objects to the low-level recipes.

The code you shared errors saying that Keyboard is not defined. Can you please share an example that you ran yourself? I've added the GLMakie.Keyboard prefix. Just wanted to double check that you ran the exact same code.

Yes, I did run the same code, but in the REPL I used there was using GLMakie before so the code ran without error and I did not notice.

This issue seems to affect all recipes for all geometries, which indicates that maybe we are pre-processing the colors provided by the user in a way that inhibits Observables to take action. @jkrumbiegel do you see any issue with the following code?

Well as you say, you unpack the observables and then continue on with the values. However, you only unpack them once. When the original observables change, nothing happens. You have to use lift or on or onany etc. to run callback functions whenever the observables change, or nothing will be passed forward. But this can be tricky to get right, especially if you have multiple array-observables that can desynchronize in length when one updates before another. It's something Makie struggles with itself.

So I understand that the rule of thumb is to never unpack observables unless strictly needed, just forward then to the low-level recipes. In the case of colors, we will need to unpack, pre-process and then lift it again so that observables are forwarded properly.

I looked into the code and experimented a bit, it seems that a major refactor is needed to support Observables since almost all code is related.

I'm willing to help modifying the recipes, but I am really newbie with Makie. I will try in on my own but if you can give me some advice it would be appreciated.
I need to do some time-animations with 2D unstructured meshes, so I have my own function triplot() as in MATLAB, which uses the Point2(), connect(), SimpleMesh() recipes from Meshes.jl and the MeshViz().
I will try with those first and hope to get the problem solved.

Thank you @AlvaroPY please let us know if you have any questions. Looking forward to review the PR.

I didn't succeed yet to do the animation, but I created a proper mesh object containing observables with Meshes.SimpleMesh(), I did that simply changing const Point2 = Point{2,Observable{Float64}} in points.jl. I know it's a bad workaround since I am converting even non-observable coordinates to an observable.

After that, I saw that simplemesh.jl from MeshViz.jl uses Makie.mesh!() at the end of viz2D(), but this doesn't work for my object with observables. Perhaps there's another way to handle observables for Makie.mesh(), but I didn't found that in the doc.

I have a small change which reactively handles changes to the mesh object through the Observables framework. It doesn't handle colors, since this would split the notification pipeline in two, and I'm not sure if that's a problem or not.

I posted it as #35, maybe it can be a small direction forward 🙂

Fixed all issues with the recipe attributes and they should work fine now with observables. The only missing feature now is the automatic update of the mesh/geometry itself when we modify the vertices, etc. Should be easy to fix as well.

Most issues are fixed now, except for the CartesianGrid case that I am planning to fix tomorrow.

Fixed on master.