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!().
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?
@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(...)
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.
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.