I have a dataset which is a 4xN array of numbers corresponding to field values at (z,y,x)-positions, sampled sparsely in z. I am trying to use contourf!
in Makie to make a video of the evolution of these fields, which requires indexing into the array to find the subsets which correspond to each z-level.
The problem arises with the update, making use of Observable
, and how to implement the plotting both performantly and correctly. Thus far I have only managed “very slow and correct” or “slow and incorrect”. Using PyPlot.jl, I can make an equivalent plot using tricontourf
at 2 it/s, so my approach in CairoMakie is between 4x and 192x slower in this instance. I would really appreciate any insight about how to approach this a better way.
Code showing attempts below:
using CairoMakie, ProgressBars
const nts = 1:5
const zs = [1,24,50]
function generateObsData(; zs=[1,24,50])
obs = [];
for x in 1:5:200, y in 1:5:200, z in zs
push!(obs,[z, y, x, rand()])
end
obs = reduce(hcat,obs)
return obs
end
const obs = generateObsData(; zs=zs);
function main1()
iz = [findall(z.==obs[1,:]) for z in zs]
ys = [Observable(obs[2,z]) for z in iz]
xs = [Observable(obs[3,z]) for z in iz]
us = [Observable(obs[4,z]) for z in iz]
fig = Figure(resolution = (900, 400))
axs = [ Axis(fig[i, j], width = 200, height = 200) for i in 1:1, j in eachindex(zs) ]
for ax in axs
hidedecorations!(ax)
end
for j in eachindex(zs)
if length(us[j][]) > 0
contourf!(axs[1,j], ys[j], xs[j], us[j];levels=range(0,1,129),colormap=:Oranges,colorrange=(0,1),rasterize=true)
end
end
Colorbar(fig[1:1,length(zs)+1]; colorrange=(0,1), colormap=:Oranges, label=L"u")
tit = Label(fig[0,:], text = L"$t = 0$ []", textsize = 24)
resize_to_layout!(fig)
record(fig, "obsTest1.mp4", ProgressBar(nts); framerate=10) do n
obs .= generateObsData(; zs=zs);
for (j,z) in enumerate(iz)
ys[j][] = obs[2,z]
xs[j][] = obs[3,z]
us[j][] = obs[4,z]
end
tit.text[] = L"$t = %$(n-1)$ []"
end
return nothing
end
function main2()
OO = Observable(obs)
fig = Figure(resolution = (900, 400))
axs = [ Axis(fig[i, j], width = 200, height = 200) for i in 1:1, j in eachindex(zs) ]
for ax in axs
hidedecorations!(ax)
end
for (j,z) in enumerate(zs)
iz = findall(z.==obs[1,:])
contourf!(axs[1,j], OO[][2,iz], OO[][3,iz], OO[][4,iz];levels=range(0,1,129),colormap=:Oranges,colorrange=(0,1),rasterize=true)
end
Colorbar(fig[1:1,length(zs)+1]; colorrange=(0,1), colormap=:Oranges, label=L"u")
tit = Label(fig[0,:], text = L"$t = 0$ []", textsize = 24)
resize_to_layout!(fig)
record(fig, "obsTest2.mp4", ProgressBar(nts); framerate=10) do n
obs .= generateObsData(; zs=zs);
OO[] = obs;
tit.text[] = L"$t = %$(n-1)$ []"
end
return nothing
end
main1() # ~48s/it; very slow, but correctly updating contourf's
main2() # ~2s/it; still slow, but contourf's do not update