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.

1 Like

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.

2 Likes

Thanks! That solved the problem.