Makie:When should we use @lift macro?

  • if we want to change the line’s shape based on time,we can use @lift to track the time, like this:

time = Observable(0.0)

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

ys_1 = @lift(sin.(xs .- $time))     # if I change this to `ys_1 = sin.(xs.-time[])`,this line can't move
ys_2 = @lift(cos.(xs .- $time) .+ 3)

fig = lines(xs, ys_1, color = :blue, linewidth = 4,
    axis = (title = @lift("t = $(round($time, digits = 1))"),))
scatter!(xs, ys_2, color = :red, markersize = 15)

framerate = 30
timestamps = range(0, 2, step=1/framerate)

record(fig, "time_animation.mp4", timestamps;
        framerate = framerate) do t
    time[] = t
  • but when we appending data to a plot,we don’t need @lift,we can do like this:

points = Observable(Point2f[(0, 0)])

fig, ax = scatter(points)
limits!(ax, 0, 30, 0, 30)

frames = 1:30

record(fig, "append_animation.mp4", frames;
        framerate = 30) do frame
    new_point = Point2f(frame, frame)
    points[] = push!(points[], new_point)

Can someone tell we why ?

The key difference is if there is dependency between observables or not.

In the first example you have time and then there is ys_1, ys_2 which need to be updated whenever time changes (see reactive programming). In principle you could just define ys_1 = Observable(...) (same for ys_2) and then, each time you want to update the plot you write the corresponding data (probably like ys_1.val = <new data> and ys_2[] = <new data> such that you only redraw once.)

In the second example there is no dependency, so you don’t to declare any dependencies with @lift.

1 Like