Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Options provided to plot(..., options=Dict) arent recognized when calling savefig #366

Open
jwintersinger opened this issue Feb 23, 2021 · 8 comments

Comments

@jwintersinger
Copy link

Hi! The options specified in P = plot(rand(10, 4), options=Dict(:staticPlot => true)) aren't recognized when I call savefig(P, "out.html") and view the resulting HTML file in my browser, as the plot isn't static. (This is the minimal example given in PlotlyJS.jl/docs/src/syncplots.md.)

Here's a more full example taken from #326:

using PlotlyJS

trace1 = scatter(
    x=[0, 1, 2, 3, 4, 5, 6],
    y= [1, 9, 4, 7, 5, 2, 4],
    mode= "markers",
    marker_size = [20, 40, 25, 10, 60, 90, 30]
)

layout = Layout(;
    title= "Download Chart as SVG instead of PNG",
    showlegend= false
);

config = Dict(
  :toImageButtonOptions => Dict(
    :format => "svg",
    :filename => "custom_image",
    :height => 500,
    :width => 700,
    :scale => 1 # Multiply title/legend/axis/canvas sizes by this factor
  )
);
P = plot(trace1,layout;options=config)
savefig(P, "out.html")

When I view out.html in my browser, the "download image" button still gives a PNG with the default dimensions, not an SVG. The options I specified are not present in the out.html source. The problem occurs for me on Julia 1.5.3 with PlotlyJS.jl v0.14.0 or the master HEAD.

Thanks for any help you can provide!

@empet
Copy link

empet commented Feb 23, 2021

Plotlyjs.jl, savefig is almost the equivalent of the Python function plotly.io.write_image(), that doesn't save a html file. I say almost, because savefig saves all image formats, as well as html.
Instead, Python version has a special function for saving the plot in html:

plotly.io.write_html(fig, "filename.html",  config=config)

It saves the plot with the config settings (I checked it).

PlotlyJS.jl savefig has the same paramters as plotly.io.write_image():

?savefig
savefig(
    io::IO,
    p::Plot;
    width::Union{Nothing,Int}=nothing,
    height::Union{Nothing,Int}=nothing,
    scale::Union{Nothing,Real}=nothing,
    format::String="png"
)

But

help(plotly.io.write_html) 

lists:

Help on function write_html in module plotly.io._html:

write_html(fig, file, config=None, auto_play=True, include_plotlyjs=True, include_mathjax=False, post_script=None, full_html=True, animation_opts=None, validate=True, default_width='100%', default_height='100%', auto_open=False)
    Write a figure to an HTML file representation
    
    Parameters
    ----------
    fig:
        Figure object or dict representing a figure
    file: str or writeable
        A string representing a local file path or a writeable object
        (e.g. an open file descriptor)
    config: dict or None (default None)
        Plotly.js figure config options
    auto_play: bool (default=True)
        Whether to automatically start the animation sequence on page load
        if the figure contains frames. Has no effect if the figure does not
        contain frames.
    include_plotlyjs: bool or string (default True)
        Specifies how the plotly.js library is included/loaded in the output
        div string.

I think that saving a plot with config settings is not implemented in PlotlyJS.jl. @sglyon can confirm this?

@jvkerckh
Copy link

jvkerckh commented Sep 7, 2021

A closely related problem, so I didn't open a new issue for it: the size keyword argument is also not recognised when calling savefig.

Minimal example:

plt = plot( 1:5, size=(1600,900) )
savefig( plt, "test.svg" )

The resulting SVG file has width="700" and height="500" instead of 1600 and 900.

This occurs in Julia v1.6.2, with Plots v1.21.3 and PlotlyJS v0.18.7.

@empet
Copy link

empet commented Sep 7, 2021

@jvkerckh
There is no size keyword in the trace definition or Layout definition. It's width and/or height that must be set.

Just run these lines, and see the difference:

plt = plot( scatter(y=1:5, Layout(width=750, height=600)) 
savefig( plt, "test1.svg", width=600, height=300, scale=1 )#although the width/height is set in layout, 
                                                                                            #    the image is saved with these new   sizes

plt = plot( scatter(y=1:5) )#  width and height  for displaying plot are  the default values here
savefig( plt, "test2.svg", width=1000, height=800, scale=1 ) # the image is saved with 1000 x 800 

@sglyon
Copy link
Member

sglyon commented Sep 8, 2021

Thanks @empet good help!

There is a pretty recent function called to_html that implements more of the options from Python's write_html:

help?> PlotlyBase.to_html
  to_html(
      io::IO,
      p::Plot;
      autoplay::Bool=true,
      include_plotlyjs::Union{String,Missing}="cdn",
      include_mathjax::Union{String,Missing}="cdn",
      post_script::Union{String,Missing}=missing,
      full_html::Bool=true,
      animation_opts::Union{Dict,Missing}=missing,
      default_width::String="100%",
      default_height::String="100%"
  )

    •  io: IO stream to write to

    •  p: Plot to save

    •  autoplay: Should animations start automatically

    •  include_plotlyjs: How to include plotly.js. Options are
       • cdn: include a <script> tag to load plotly.js from cdn. Output will be standalone
       • require: load using requirejs. Useful in Jupyter notebooks
       • require-loaded: assume a plotly statement has already loaded via requirejs (don't load it in context
       of this plot)
       • directory: hardcode <script src="plotly.min.js> – will only work when the plotly.min.js file is in
       the same directory as the output file
       • anything ending in js: we assume you give us the path to the plotly.js file. We will read it in and
       include it inline in the output. Works best when points to a minified file (plotly.min.js)

    •  include_mathjax: How mathjax should be included. Options are
       • string ending in .js: we load via <script src="$(include_mathjax)">. You are responsible for making
       sure it resolves
       • anything else: we load via cdn for you

    •  post_script: arbitrary javascript to run after plotly.js finishes drawing the plot

    •  full_html: include all parts necessary for standalone html file

    •  animation_opts: extra options used to control animation. included in addFrames call after the actual frames.
       See plotly.js docs for more info on addFrames

    •  default_width: valid css specifier for width

    •  default_height: valid css specifier for height


@StefanPofahl
Copy link

StefanPofahl commented Dec 22, 2022

I am not sure, if I use it correctly. Here my snippet:

using PlotlyJS
hdl_plt = PlotlyJS.Plot([1,2,3])
PlotlyJS.savefig(hdl_plt, raw"c:\tmp\plt\online_html.html")
# --- include a script tag containing the plotly.js source code (~3MB) ---
open(raw"c:\tmp\plt\offline_html.html", "w") do io
    PlotlyJS.PlotlyBase.to_html(io, hdl_plt, include_plotlyjs = "cdn")
end

The strange thing is, both html-files have the identical size.

@empet
Copy link

empet commented Dec 22, 2022

They are identical because you did not set width and height. For the first version it saves the file with the default settlngs (width=600, height=450, for example, has no effect).
But this one works:

open(raw"c:\tmp\plt\offline_html.html", "w") do io
    PlotlyJS.PlotlyBase.to_html(io, hdl_plt, include_plotlyjs = "cdn", default_width="75%", default_height="60%")
end

@StefanPofahl
Copy link

StefanPofahl commented Dec 22, 2022

Thanks for your reply! Sorry, I mean the file-size in kB.
I saw here that the file-size will grow approx 3MB

@StefanPofahl
Copy link

via PyCall I can generate an offline ready HTML:

    using PyCall
    go = PyCall.pyimport("plotly.graph_objects")
    # ---
    fig = go.Figure()
    fig.add_trace(go.Scatter(y=[1,2,3]))
    # fig.show()
    fig.write_html(raw"c:\tmp\plt\test_offline.html")
    fig.write_html(raw"c:\tmp\plt\test_online.html", include_plotlyjs = false)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants