Search code examples
plotlyjuliapngfiguresave-image

Saving PlotlyJS plot as PNG (Julia)


I would like to save a PlotlyJS plot as a PNG using Julia, but I cannot figure out how. The PlotlyJS webpage for Julia states that "to save the chart for external viewing you can do so using the savefig(p, filename::String) method". However, the following code:

using PlotlyJS

p = plot(rand(10, 4))
PlotlyJS.savefig(p, filename="myimage.png")

results in an error due to "got unsupported keyword argument "filename", but using

PlotlyJS.savefig(p, "myimage.png")

results in an "access to undefined reference" error:

ERROR: UndefRefError: access to undefined reference
Stacktrace:
  [1] getproperty
    @ .\Base.jl:42 [inlined]
  [2] _kaleido_running
    @ C:\Users\apung\.julia\packages\PlotlyBase\NxSlF\src\kaleido.jl:176 [inlined]
  [3] _ensure_kaleido_running()
    @ PlotlyBase C:\Users\apung\.julia\packages\PlotlyBase\NxSlF\src\kaleido.jl:177
  [4] savefig(p::Plot{Vector{GenericTrace}, Layout{Dict{Symbol, Any}}, Vector{PlotlyFrame}}; width::Nothing, height::Nothing, scale::Nothing, format::String)
    @ PlotlyBase C:\Users\apung\.julia\packages\PlotlyBase\NxSlF\src\kaleido.jl:84
  [5] savefig(io::IOStream, p::Plot{Vector{GenericTrace}, Layout{Dict{Symbol, Any}}, Vector{PlotlyFrame}}; width::Nothing, height::Nothing, scale::Nothing, format::String)
    @ PlotlyBase C:\Users\apung\.julia\packages\PlotlyBase\NxSlF\src\kaleido.jl:139
  [6] (::PlotlyBase.var"#181#182"{Nothing, Nothing, Nothing, Plot{Vector{GenericTrace}, Layout{Dict{Symbol, Any}}, Vector{PlotlyFrame}}})(f::IOStream)
    @ PlotlyBase C:\Users\apung\.julia\packages\PlotlyBase\NxSlF\src\kaleido.jl:171
  [7] open(::PlotlyBase.var"#181#182"{Nothing, Nothing, Nothing, Plot{Vector{GenericTrace}, Layout{Dict{Symbol, Any}}, Vector{PlotlyFrame}}}, ::String, ::Vararg{String}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base .\io.jl:330
  [8] open
    @ .\io.jl:328 [inlined]
  [9] savefig(p::Plot{Vector{GenericTrace}, Layout{Dict{Symbol, Any}}, Vector{PlotlyFrame}}, fn::String; format::Nothing, width::Nothing, height::Nothing, scale::Nothing)
    @ PlotlyBase C:\Users\apung\.julia\packages\PlotlyBase\NxSlF\src\kaleido.jl:170
 [10] savefig(p::Plot{Vector{GenericTrace}, Layout{Dict{Symbol, Any}}, Vector{PlotlyFrame}}, fn::String)
    @ PlotlyBase C:\Users\apung\.julia\packages\PlotlyBase\NxSlF\src\kaleido.jl:165
 [11] savefig(p::PlotlyJS.SyncPlot, a::String; k::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ PlotlyJS C:\Users\apung\.julia\packages\PlotlyJS\WF333\src\PlotlyJS.jl:49
 [12] savefig(p::PlotlyJS.SyncPlot, a::String)
    @ PlotlyJS C:\Users\apung\.julia\packages\PlotlyJS\WF333\src\PlotlyJS.jl:49
 [13] top-level scope
    @ none:1

I have also tried defining a PyPlot figure, and opening/saving the image via PyPlot, but this did not work out.

Alternatively, based on this accepted SO answer, I can save the plot as an HTML file, but I still need to convert or save the HTML file to a PNG. A solution to this problem was proposed here, but this still feels messy.

Ultimately, I would like to save a PlotlyJS plot as a PNG file.


Solution

  • As Oskar says in his comment, there should be no issues with your second attempt on the current stable release of PlotlyJS, 0.18.8.

    Doing

    julia> using PlotlyJS
    
    julia> savefig(plot(rand(10)), "test.png")
    

    results in a png file being written to the current working directory for me.

    Your first attempt passing a filename keyword didn't work because, as the error says, this keyword doesn't exist. It's useful to look at a function's method signatures using the REPL help mode (accessible by pressing ?):

    help?> savefig
    search: savefig StackOverflowError
    
    (...)
    
      savefig(
          p::Plot, fn::AbstractString;
          format::Union{Nothing,String}=nothing,
          width::Union{Nothing,Int}=nothing,
          height::Union{Nothing,Int}=nothing,
          scale::Union{Nothing,Real}=nothing,
      )
    
      Save a plot p to a file named fn. If format is given and is one of png, jpeg, webp, svg, pdf, eps, json, or html; it will be the format of the file. By default the format is guessed from the extension of fn.
      scale sets the image scale. width and height set the dimensions, in pixels. Defaults are taken from p.layout, or supplied by plotly
    

    (Note that here I've ommitted the first method defined for savefig for brevity).

    This tells you that your second attempt, calling savefig(p, "myimage.png") is the correct usage of the function for your purpose. As an alternative to having Plotly guess the desired format from the file extension, you can pass format = "png" to create png outputs.