Running 'scatter' from withing a function does nothing

I’ve made a function to start my simulation. If I run the line scatter(x,y) outside of the function it works fine and new dots appear. Within the function it runs but nothing appears. Do I always have to start the plot from outside a function? thanks

function run(time)
xnext = xnow = xold = 0.0
ynext = ynow = yold = 10.0
g = -9.8

fps = 60
frames = fps*time
timestep = 1/fps
scatter(xnext,ynext) # nothing appears!
for i in range(1,1,frames)
    xnext, ynext = verlet_update(xnow,xold,ynow,yold,g,timestep)
    xold, yold = xnow, ynow
    xnow,ynow = xnext,ynext
    scatter!(xnow,ynow, markersize=20)
    sleep(timestep)
    println(ynext)
end

end

Most (all?) plotting commands return a “figure” object; the plot is produced when your function returns that object, or when it is displayed explicitly. Try doing either

scatter!(xnow,ynow, markersize=20) |> display

or

f = scatter!(xnow,ynow, markersize=20)

and then return f at the end.

1 Like

thanks. returning f shows me that plot at the end which is ok but I was hoping to display an empty plot first and then update with each loop iteration

|> display only prints the scatter type

to ask more generally, I want to make a simulation of a bouncing ball and watch the ball. How should I structure my code when using GLmakie?

I’m trying to have a function run(time) that initialises the variables and the plot and then loops my verlet_update function to move the ball.

The animation documentation has a good example of this. The general idea is

    # Create an observable for your point
    pt = Observable(Point2f(xnext, ynext))
    # Create your plot
    fig = Figure()
    # Maybe display the figure if this is in a function and not an interactive session
    # display(fig)
    ax = Axis(fig[1,1])
    # plot the initial condition
    scatter!(ax, pt)
    # run the loop, updating the observable on each iteration
    for i in range(1,1,frames)
        xnext, ynext = verlet_update(xnow,xold,ynow,yold,g,timestep)
        xold, yold = xnow, ynow
        xnow,ynow = xnext,ynext
        # This updates the value of the point which automatically updates the scatter
        pt[] = Point2f(xnow, ynow)
        sleep(timestep)
        println(ynext)
    end

thanks! and this has to be run at the root of the file or in a function? i’ll look through that page

This can be run in a function, in that case be sure to call display(fig) before entering the loop to open the window.

1 Like

Great, thanks! Should I be using geometrybasics whenever possible?

I would say whenever appropriate. In this case, updating separate x and y observables would result in two updates of the plot, updating the point once ensures there is one update of the plot.

It is even more important when adding new points. There is no way to keep the scatter plot valid while separately adding x and y coordinates but adding Point objects can expand the plot and keep it valid.