Using Plots.jl within a package _iteratively_

Hi, I am doing some optimization iteratively. I produce plots iteratively, updating the plot after each variable-update. I am trying to figure out how to avoid depending on Plots.jl in my package for cases when the plot is not requested in order to speed up compile/first-run time. Simplistically, this is like:

for i in 1:max_iter
  x = update_x(x)
  if make_plot
    plot(x)
  end
end

Because the procedure is a bit slow, I want to see the plots appear as the code runs – also produces a nice animation for demo/display.

I have seen the suggestion to use RecipesBase in Using Plots.jl within a package - #5 by jarvist, but this seems to work only for single static data set. Is there an approach to inject Plots into my optimization code so that it can be called iteratively during optimization?

using recipes is orthogonal to if you plot one or many plots. Generally speaking, the thing you have to do, is set up a recipe for whatever type x has, using a wrapper type if necessary. Also have a glance at the documentation.

1 Like

Thank you for the suggestion. I’ve reviewed the docs for RecipiesBase again, but I’m still not clear on how this solves my problem. I want to call the plot function from within my package to generate plots as the algorithm is running, on-the-fly. In contrast, it seems that recipies are designed to tell the plot function how to plot a new type of data – kinda-like defining a plot method but without requiring the Plots package. Please do correct me if I’m misunderstanding this.

I’m less interested in generating a custom type of plot and more interested in how to just run the plot function from within my package. I’m thinking of just having my optimization function take an optional argument of type Function so that I can pass-in plot as a way to inject it. Something like

function optimize(x, plot_function::Union{Function, nothing})
  ...
  for i in 1:max_iter
    x = update_x(x)
    if !isnothing(plot_function)
      plot_function(x)
    end
  end
end

I’m not sure I understand the problem, why can’t you just have the plot() call in an if branch and define optimize(x; plot = false)?

1 Like

I would like to avoid having Plots.jl as a dependency. It’s only needed for my local debugging, but not for wider use. Having Plots.jl as a dependency slows down compile-time quite a bit.

Ah sorry it’s all about the dependency - isn’t that then solved by RecipeBase? I.e. depend on RecipeBase and define a plot recipe in your package, and then when you want to plot you need to do using MyPackage, Plots and if you don’t you can leave it at using MyPackage?

I would like to plot from within a function in my package.

Seems like https://github.com/MikeInnes/Requires.jl is an option for me.

1 Like

Also havin a callback should work á la

function f(args...; make_plot = nothing)
    # ...
    if make_plot !== nothing
          make_plot(x)
    end
    # ...
end

and then pass make_plot = Plots.plot.

1 Like

Awesome, thanks for verifying that my “injection” idea is not crazy :wink: (Using Plots.jl within a package _iteratively_ - #3 by ianfiske)

This might be the most straightforward solution.

Just wanted to circle back and say that passing a plot_callback function method works great.