Makie does not update the plot during an animation

Multiple values are the achilles heel of the observable workflow. The problem is this:

Here, A triggers B and C, and both trigger D. In order to avoid a double update of D, A should first do B.val = new_value, then C[] = new_value.

     ┌─────┐
   ┌─┤  A  ├─┐
   │ └─────┘ │
   │         │
   │         │
┌──▼──┐   ┌──▼──┐
│  B  │   │  C  │
└──┬──┘   └──┬──┘
   │         │
   │         │
   │ ┌─────┐ │
   └►│  D  ◄─┘
     └─────┘

Now B has another listener, E. We can’t do B.val = ... anymore because E won’t be updated. But we can still do C.val = ... and B[] = ....

          ┌─────┐
        ┌─┤  A  ├─┐
        │ └─────┘ │
        │         │
        │         │
     ┌──▼──┐   ┌──▼──┐
   ┌─┤  B  │   │  C  │
   │ └──┬──┘   └──┬──┘
   │    │         │
   │    │         │
┌──▼──┐ │ ┌─────┐ │
│  E  │ └►│  D  ◄─┘
└─────┘   └─────┘

But if C also has a second listener, F this is impossible:

          ┌─────┐
        ┌─┤  A  ├─┐
        │ └─────┘ │
        │         │
        │         │
     ┌──▼──┐   ┌──▼──┐
   ┌─┤  B  │   │  C  ├─┐
   │ └──┬──┘   └──┬──┘ │
   │    │         │    │
   │    │         │    │
┌──▼──┐ │ ┌─────┐ │ ┌──▼──┐
│  E  │ └►│  D  ◄─┘ │  F  │
└─────┘   └─────┘   └─────┘

You cannot avoid updating both B and C if you want to trigger their listeners E and F, which means D is updated twice. But if B and C store arrays whose lengths change with the update of A, it can be that the first update of D, after B is triggered, errors because B and C have different lengths in that moment. In that case it’s impossible to update all observables correctly. We’re still trying to figure out ways in which we can make the updating process simpler, but it’s a thorny issue and observables are deeply ingrained in the whole codebase, so we must be careful not to break anything with a “fix”.

I say this because you asked what to do with a tuple resulting from lift. But this usually happens because one calculates multiple input arguments for an inner plot object from input observables. In that case, one has to define all the observables beforehand, and carefully update them inside an on or onany function with obs.val = ... and only once (if possible) with obs[] = ... so that one doesn’t trigger duplicate updates downstream. But as I showed, this is sometimes impossible. Here’s one example of such a thing: Makie.jl/contourf.jl at master · MakieOrg/Makie.jl · GitHub
The colors observable is not triggered, its content array is just mutated. This way the downstream poly will have access to the new colors when its input observable polys is triggered. This way polys and colors can always have the same length from the perspective of the poly plot. But this wouldn’t work if something internal to poly relied on the color observable actually triggering…

1 Like