Makie object management / scene refresh

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?



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?



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?



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

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:

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)

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.

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?

I recently had occasion to revisit this, and I find myself still wishing for a way to clear the current plot(s). The background for this is that I am trying to create a simple GUI that allows me to pan through arrays of objects, where each object has its own plot function. Since the contents of those plot can vary between between objects (they could even be objects of very different types, hence very different plot elements), re-using the scene elements is not really feasible. It would be nice to have something like matplotlib’s plt.cla() which clear the contents of the current axes.
In theory I could just re-create the scene for every plot, but I am trying to use the Observables framework to do this, essentially treating the index into the array of objects as an observable that gets manipulated by e.g. button clicks. The suggestion by @piever above seems like it could be one solution to this.