Makie object management / scene refresh


#1

Hi all (@sdanisch :stuck_out_tongue_winking_eye: ),

I have an existing scene, rendered to the screen, containing a DAG. As the execution of the Julia script progresses, the DAG changes. nodes are added, labels are moved, and (most importantly), nodes are deleted.

What is the correct way to handle this? I have the list of nodes stored in a dictionary of structs, which I can easily update as I receive events regarding changes to the DAG. However, The Makie functions, particularly, meshscatter!() don’t take dictionaries. I currently scan the dictionary, and build a series of arrays corresponding to the different elements in the rendering.

That works, but I’m unsure how to update it. I’d prefer not to rebuild all of the arrays each time, although, perhaps map(x->x.loc, collect(values(mydict))) might be tolerable in each call to meshscatter!().

How are others handling this?

Thanks,

Jason.


#2

Ok, I’ve made quite a bit of progress regarding this. I’m now detecting changes to my data source with FileWatcher. That kicks properly (although I haven’t figured out how to watch multiple directories simultaneously), I update my dictionaries based on the changes, and call a function to re-render. Which works for the most part.

My main sticking point at the moment is how to remove an item from the scene? e.g. on the initial render, I placed a text label at a given location (with text!(scene, ...). After the update, the label changed. I call text!(scene, ...) but I don’t get the new label. The old label doesn’t go away. Previously, with a non-refresh error, I’d get two text strings overlapping (due to a different error), so I know what that looks like.

How does one remove objects from an existing scene?

Thanks,

Jason.


#3

On this same track:

@sdanisch, others; how do I de-reference a Scene object without guessing?

I’m currently doing

scene = Scene(resolution = (500, 500))

...

objs = Dict{String, Any}()

...

objs[“uniqueid”] = meshscatter!(scene, Point3f0(0), ...)

...

# now I want to update position of uniqueid
objs[“uniqueid”][X][Y][Z] = Point3f0(...)

How do I deterministically know X, Y, and Z?

Thanks,

Jason.


#4

Hi!
Did you find a solution to this? I’m particularly interested in how to remove objects from a scene.


#5

Did you find a solution to this? I’m particularly interested in how to remove objects from a scene.

What kind of API do you imagine?
It should be relatively easy to implement :wink:


#6

Actually, it turns out I managed to solve my problem without having to delete objects. I’m working on a piece of code that will allow me to visualise how a set of multivariate normal distributions, represented by ellipsoids, evolve through time. Initially, I couldn’t work out how to update the position and shape of the ellipsoids “in-place”, hence the request for deleting objects. However, I was able to adapt this example for my use. I ended up with something like this:

         map(s2[end][:value]) do ss
             ii = searchsortedfirst(bins, ss)
            μf,Σf = get_3D_projection(G[ii,:], N)
            for jj in 1:length(Σf)
                X,Y,Z,q = get_ellipsoid(Σf[jj])
                X .+= μf[jj][1]
                Y .+= μf[jj][2]
                Z .+= μf[jj][3]
                drawscene.plots[jj+1][1] = X
                drawscene.plots[jj+1][2] = Y
                drawscene.plots[jj+1][3] = Z
                drawscene.plots[jj+1].model = Matrix(Diagonal(fill(1.0, 4)))
                rotate!(drawscene.plots[jj+1], q)
            end
        end

where s2 represents a slider to navigate through time slices and G is a Distributions.MvNormal type. At some point, I’ll isolate this from the rest of the code and try making it available as a package.


#7

I’ve also wanted this recently. Could we replace the p[end].plots array (p is a scene) with an observable array so that one can add or remove plots and the image updates automatically?