Makie - Massive growth of memory usage when updating an image

I have spent a week on this issue and need help. My application is to generate a file of images that I later massage and make into a movie. All works great EXCEPT the memory usage limits my number of frames before it crashes. The guilty command is on line 29 of my simple test program: “image!(ax, img)”.
My Code:
using GLMakie, Images, Random
const PROG_NAME = “simple_img_2.jl”
println(“Starting $PROG_NAME”)
cSize = 1200; rSize = 1000
rand_array = rand(Float64, (cSize, rSize))
function make_image(cSize, rSize)
points = Array{HSV{Float64},2}(undef, rSize, cSize)
for c = 1:cSize, r = 1:rSize
m = rand_array[c, r]
hue = (m * 360.0) % 360.0
saturation = 225.0 / 255.0
value = m < 1 ? 1.0 : 0.0
global points[r, c] = HSV(hue, saturation, value)
end
img = n0f8.(RGB.(points))
return img
end # make_image

f = Figure(resolution = (cSize, rSize), figure_padding = 1, backgroundcolor = :gray80)
ax = GLMakie.Axis(f[1, 1], aspect = DataAspect(), yreversed = true, title = “Simple Test 6’”)
println(“starting loop”); sleep(1)
for i in 1:300
if i % 30 == 0; println("$i"); end
local img = make_image(cSize, rSize)
image!(ax, img’)
# filename = update_sequential_filename(); save(filename, f) # saves as a png
display(f)
end
println(“Leaving $PROG_NAME”)

My indentation got boogered. Better way to submit my code?

Well, image!(ax, img’) is adding a new plot to the axis, so it adds 300 images in the loop to the axis… So, it will surely get bigger with every step!

Efficient animations in Makie are done via Nodes, you just update your plot, you don’t add new things to your current plot.

See for example: Animations
There, instead of:

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

you could have your image, i.e.

imgNode = Node(img)

and then simply updated it at recording time. For examples and inspiration can be found here:

https://lazarusa.github.io/BeautifulMakie/animations/animScatters/

1 Like

I very much appreciate the feedback. I have a great GUI built using Makie with various layoutables. However the memory issue kills my longer runs. I’m about to give up on Makie and go back to GtkReactive to build a GUI. My GtkReactive interaction is totally keyboard/mouse based.

Re sdanisch comment: I tried empty!(ax) but it had no effect.

Re lazarusA comments: I successfully got to where my listener is called with my new img but I’m stuck there. In all the examples of listeners, I could find, they all using various plotting functions like your “scatter” or line, etc. Is there a function that can plot my img? Or, better yet, a function that can plot the points HSV array from my make_image function? Or the RGB version?

Also I do not want to use the record function to generate the mp4 video. I massage (with Julia) the list of frames and then use ffmpeg to make my videos. Example: I take a series of frames that zoom from in to out and build a movie that starts from out to in, pauses, and then from in back out. Works great.

Following is my latest code showing where I’m stuck in the imgNode listener.

using GLMakie, Images, Random
const PROG_NAME = “simple_img_4.jl”
println(“Starting $PROG_NAME”)
cSize = 1200; rSize = 1000
rand_array = rand(Float64, (cSize, rSize))
function make_image(cSize, rSize)
points = Array{HSV{Float64},2}(undef, rSize, cSize)
for c = 1:cSize, r = 1:rSize
m = rand_array[c, r]
hue = (m * 360.0) % 360.0
saturation = 225.0 / 255.0
value = m < 1 ? 1.0 : 0.0
global points[r, c] = HSV(hue, saturation, value)
end

img = n0f8.(RGB.(points))
return img

end # make_image

img = make_image(cSize, rSize)
imgNode = Node(img) # imgNode is my observable

on(imgNode) do x
println(“In imgNode listner, now what???”)
# How do I update and save the figure?
end

f = Figure(resolution = (cSize, rSize), figure_padding = 1, backgroundcolor = :gray80)
ax = GLMakie.Axis(f[1, 1], aspect = DataAspect(), yreversed = true, title = “Simple Test 7’”)
println(“starting loop”); sleep(1)
for i in 1:3
global imgNode = make_image(cSize, rSize)
end
println(“Leaving $PROG_NAME”)

Here’s a fixed version, I would recommend to read some of the tutorials and explanations in the docs, because this is about the fundamentals of Makie and Observables:

https://makie.juliaplots.org/stable/documentation/animation/
https://makie.juliaplots.org/stable/documentation/nodes/

using GLMakie, Random
using Makie.Colors

const PROG_NAME = "simple_img_4.jl"

println("Starting $PROG_NAME")

cSize = 1200; rSize = 1000

function make_image(cSize, rSize)
    rand_array = rand(Float64, (cSize, rSize))

    points = Array{HSV{Float64},2}(undef, rSize, cSize)

    for c = 1:cSize, r = 1:rSize
        m = rand_array[c, r]
        hue = (m * 360.0) % 360.0
        saturation = 225.0 / 255.0
        value = m < 1 ? 1.0 : 0.0
        points[r, c] = HSV(hue, saturation, value)
    end

    img = RGBf.(points)
    return img
end # make_image

imgObservable = Observable(make_image(cSize, rSize))

f = Figure(resolution = (cSize, rSize), figure_padding = 1, backgroundcolor = :gray80)
ax = Axis(f[1, 1], aspect = DataAspect(), yreversed = true, title = "Simple Test 7’")

image!(ax, imgObservable)

# show the plot here, just for this interactive example
display(f)

for i in 1:3
    # update the image observable and therefore the plot
    imgObservable[] = make_image(cSize, rSize)
    # wait to be able to see the changing plot
    sleep(1)
    # you could save the figure here if you wanted to
end

println("Leaving $PROG_NAME")
3 Likes

Thank you very much jules. Somehow I missed your fantastical solution to my issue. I had given up, temporarily, on Makie and went back to GtkReactive.

I decided it was time to go back to Makie and see if I could achieve a break thru by studying, searching, etc. and perhaps by rephrasing my question.

Going back to this topic I found your reply/fix. It works great. I increased the loop size to 10,000, no memory growth. :smiley:

I am now studying your suggested references and Makie in general and plan to devote considerable time & effort to coming up to speed on Makie.

Again, thank you for your great response and sorry for the delay in seeing and responding to it.

1 Like