Plot! inside a function

So, to keep things on a plot (like Matlab’s “hold on”), you call plot as plot!(…).

If I make a function such as
function plotsomething(input)
intermediate result = do something with input
plot(intermediate result)
end

Is there an easy way to call plotsomething!() instead of plotsomething() and have it apply the “hold on” properties to the plot I used in the function?

There are two things I can think of, maybe one of them can fit your needs. The first is to write some separate function f(input) = # do something with input, and then you can have

function plotsomething(input)
    intermediate_result = f(input)
    plot(intermediate_result)
end

and

function plotsomething!(input)
    intermediate_result = f(input)
    plot!(intermediate_result)
end

(the definition of f is just to save on lines of code). The other possibility is something like

function plotsomething(input, hold_on = true)
    intermediate_result = f(input)
    if hold_on
        plot!(intermediate_result)
    else
        plot(intermediate_result)
end

You can also elect to make an empty plot with plt = plot() ahead of time and pass it into the function plotsomething, and then add what you want from the function with plot(plt, ...) where the ellipses indicate what you would put in plot! if you were simply adding to the last edited plot.

Hope something here helps!

In addition to the above comments, another thing that can help is to add variable arguments:

using Plots

function plotsomething!(p, input; args...)
    y = input .^ 2
    plot!(p, input, y; args...)
end

p = plot()
plotsomething!(p, -5:5)
plotsomething!(p, -7:2; ls=:dash)
plotsomething!(p, [-2,2]; ms=8, st=:scatter)
2 Likes

You could also use a callback:

using Plots

function plotsomething(input; pf = Plots.plot, args...)
    y = input .^ 2
    pf(input, y; args...)
end

plotsomething(-5:5)
plotsomething( -7:2; pf = plot!, ls=:dash)
3 Likes

Hi Simon, does the callback solution allow handling independently different plot objects p1, p2, … ?

I get the following error:

p2 = plotsomething([-10,2]; ms=8, st=:scatter)
plotsomething([2,2]; pf=p2, ms=8, st=:scatter)

ERROR: MethodError: objects of type Plots.Plot{Plots.GRBackend} are not callable

You could do it loke this:

using Plots

function plotsomething(input, p = nothing; pf = Plots.plot, kwargs...)
    y = input .^ 2
    if p === nothing
        pf(input, y; kwargs...)
    else
        pf(p, input, y; kwargs...)
    end
end

p1 = plotsomething(-5:5)
p2 = plotsomething(-7:7)
plotsomething( -7:2, p1; pf = plot!, ls=:dash)

Or create a one and a two argument method.

1 Like

Thank you everyone for the responses. They really helped get a sense of what all of the options are.