Help with animations in Makie.jl

Hi Everyone,

I was using Observables in Makie to update my plots. Along with observables I was trying to animate the plots using record function. This is my code:

cbe_img_calib = zeros(156,400)
points1 = Observable(Point2f[]) #Declaring First Observable 
points2 = Observable(Point2f[]) #Declaring Second Observable 

f5 = Figure()
axis = f5[1,1]
scatterlines(f5[1, 1],mTime, mTemp, color=:red, marker=:x, markersize=20)
scatterlines!(f5[1, 1],mTime, mCBE_circ, color=:green, linestyle=:dot, marker=:x, markersize=20)
scatterlines!(f5[1, 1],mTime, mCBE_cont, color=:blue, linestyle=:dot, marker=:x, markersize=20)

file_no_iterator = range(start=1, stop=105)

	
function plot_graphs(file_no)

    cbe_img = cbe_data[file_no]
    global cbe_img_calib = (cbe_img * CBE_T) .+ T0

    #Steps to get circular_ROI_mask
    mask_inter = ((X .- circ_ROI_centre_x).^2 .+ (Y .- circ_ROI_centre_y).^2)

    circ_ROI_mask = zeros(size(mask_inter)[1], size(mask_inter)[2])
        
        
    for i = 1:size(mask_inter)[1]
        for j = 1:size(mask_inter)[2]
            if (mask_inter[i,j] < (circ_ROI_radius).^2)
                circ_ROI_mask[i,j] = 1
            else
                circ_ROI_mask[i,j] = 0
            end
        end
    end

    #Get the circ_ROI_img
    circ_ROI_img =cbe_img_calib .* circ_ROI_mask;

    #Get all values in cbe_img_calib where circ_ROI_mask is 1
    indices = (findall(x-> x==1, circ_ROI_mask))
    global cbe_mean[file_no] = mean(cbe_img_calib[indices])

    #Get values in cbe_mean_cont
    cont_thresh = maximum(circ_ROI_img)*0.95
    indices2 = findall(x->(x>cont_thresh), circ_ROI_img)
    global cbe_mean_cont[file_no] = mean(circ_ROI_img[indices2])

    p  = [mTime[file_no], cbe_mean[file_no]]
    q  = [mTime[file_no], cbe_mean_cont[file_no]]
    
    push!(points1[], p)
    push!(points2[], q)

    notify(points1)  
    scatter!(axis, points1, color=:pink, marker=:circle, markersize=20, overdraw=true)

    notify(points2)
    scatter!(axis, points2, color=:teal, marker=:circle, markersize=20, overdraw=true)
    sleep(1/60)
    
end
	
record(plot_graphs, f5, "Graphs_30.mp4", file_no_iterator, framerate=30)

However the mp4 file I get after recording does not display the plots in the plot_graphs function. The only plots I get are the three plots outside the plot_graphs function.


I tried running the same code in Pluto.jl and removed the record function. This is the exact output I need while using the record function:


Where am I going wrong? Any help would be greatly appreciated. Thanks.

You shouldn’t call scatter! each frame, just once at the beginning, then only update the observables.

I think you need to move the creation of the plots outside the animation loop. I would first create the two observables and the plots (outside the plot_graphs function).

points1 = Observable(Vector{Vector{Float32}}())
points2 = Observable(Vector{Vector{Float32}}())
scatter!(axis, points1, color=:pink, marker=:circle, markersize=20, overdraw=true)
scatter!(axis, points2, color=:teal, marker=:circle, markersize=20, overdraw=true)

Then inside plot_graphs, you should only need to do

    push!(points1, p)
    push!(points2, q)

to update the plots. Calling notify is only necessary if you modify the val property of the observable directly.

Hi,
Thanks for your quick response @contradict and @jules. As per your suggestions, I tried moving the scatter plot outside the function and then updated the two observables.
Still my graph isnt showing the plots. Here is my updated code:

tcbe_img_calib = zeros(156,400)
points1 = Observable(Point2f[])
points2 = Observable(Point2f[])

f5 = Figure()
ax = Axis(f5[1,1])

scatterlines!(ax,mTime, mTemp, color=:red, marker=:x, markersize=20)
scatterlines!(ax,mTime, mCBE_circ, color=:green, linestyle=:dot, marker=:x, markersize=20)
scatterlines!(ax,mTime, mCBE_cont, color=:blue, linestyle=:dot, marker=:x, markersize=20)

scatter!(ax, points1, color=:pink, marker=:circle, markersize=20, overdraw=true)
scatter!(ax, points2, color=:teal, marker=:circle, markersize=20, overdraw=true)

file_no_iterator = range(start=1, stop=105)

	
function plot_graphs(file_no)

    cbe_img = cbe_data[file_no]
    global cbe_img_calib = (cbe_img * CBE_T) .+ T0

    #Steps to get circular_ROI_mask
    mask_inter = ((X .- circ_ROI_centre_x).^2 .+ (Y .- circ_ROI_centre_y).^2)

    circ_ROI_mask = zeros(size(mask_inter)[1], size(mask_inter)[2])
        
        
    for i = 1:size(mask_inter)[1]
        for j = 1:size(mask_inter)[2]
            if (mask_inter[i,j] < (circ_ROI_radius).^2)
                circ_ROI_mask[i,j] = 1
            else
                circ_ROI_mask[i,j] = 0
            end
        end
    end

    #Get the circ_ROI_img
    circ_ROI_img =cbe_img_calib .* circ_ROI_mask;

    #Get all values in cbe_img_calib where circ_ROI_mask is 1
    indices = (findall(x-> x==1, circ_ROI_mask))
    global cbe_mean[file_no] = mean(cbe_img_calib[indices])

    #Get values in cbe_mean_cont
    cont_thresh = maximum(circ_ROI_img)*0.95
    indices2 = findall(x->(x>cont_thresh), circ_ROI_img)
    global cbe_mean_cont[file_no] = mean(circ_ROI_img[indices2])

    p  = [mTime[file_no], cbe_mean[file_no]]
    q  = [mTime[file_no], cbe_mean_cont[file_no]]
    
    push!(points1[], p)
    push!(points2[], q)

    sleep(1/60)
    
end
	
record(plot_graphs, f5, "Graphs_30.mp4", file_no_iterator, framerate=30)


My Output:

After push! you do need notify because the push! mutates the array within the observable without the observable knowing about it.

Thanks! That solved the problem.