How to check if Plots.jl is installed and loaded?



I am writing a function that generates a plot. In case Plots.jl is not installed on the user’s machine or in case it is not loaded in the current Julia session I’d like to print a warning. What is a good way to achieve this?


Pkg.installed and isdefined(Main, :Plots) (although the latter will change with 0.7)


Are you sure that’s a good idea? Why not just put your function in a module, and put using Plots in the module? If a user does not have Plots installed, then they will already get an error from Julia, and if they haven’t loaded it then using Plots will fix that.


Thank you @mauro3, could you please explain how the latter will change in Julia v0.7?


All good suggestions @rdeits, my use case is as follows:


Compare solvers by plotting the results side by side.
struct VisualComparison <: AbstractSolverComparison

VisualComparison() = VisualComparison(nothing)
VisualComparison(; kwargs...) = VisualComparison(kwargs)

function compare(solvers::AbstractVector{S}, problem::AbstractProblem,
                 cmp::VisualComparison) where {S<:AbstractSolver}
  @eval using Plots

  plts = []
  for solver in solvers
    solution = solve(problem, solver)
    push!(plts, plot(solution))

  @show cmp.plotspecs
  plot(plts..., layout=(length(solvers),1))


Seems to me that’s a perfect case for a user recipe.


How would you reformulate this as a user recipe @ChrisRackauckas? You are probably right :slight_smile:


This is an example of a type recipe which plots the series of a bunch of solutions in an internal vector:

I think you just need to use the @series macro to build each series as well. That will make them all plot in the same window though, so you’ll need to have @mkborregaard fill in how you then format the plots to be separate windows in that layout you want.


Thank you @ChrisRackauckas, I am trying to find a solution that is general enough in the sense that not all comparison methods are visual. I am already very happy with the multiple dispatch on the comparison type. I pass in the solvers themselves rather than the solution (data) because some comparisons require calling the solvers multiple times for example (e.g. cross-validation).

For now I think I will just show a warning to the user and redesign this in the future if necessary.


Related to that code snippet I posted, how one can save the kwargs passed to the VisualComparison(; kwargs) constructor and use it later in the final plot call? Right now, I am saving the kwargs in a field of type Any inside of the VisualComparison object and it is missing the correct type by the time I use the field in the plot command:

plot(plts..., plotspecs...) # plotspecs from kwargs


You shouldn’t have to check whether Plots is installed - just write a user recipe like @chrisrackauckas suggests, and use the subplot keyword to place the series in the correct subplot (check the MarginalHist recipe here for how to do it). It will work if the user has Plots loaded and not affect the user’s system otherwise.


@mkborregaard I already have type recipes defined for the solution type, I only need the function plot available inside of the compare call. That is why I am checking if Plots.jl is installed, makes sense? This function that I am defining (i.e. compare) is in fact creating a plot out of a recipe that I already have defined in the package.


In other words, I could rename the function compare to something like execute_plots_on_solutions. Is there a way to achieve this without adding the @eval using Plots inside of the function body?

I am tempted to just check if Plots.jl is loaded, and if not, I print a warning.


You can use RecipesBase.plot if you just need the plot function and wrap the plot call in try-catch, but it’s a bit of a hack.