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

[BUG] savefig not honoring size=() and dpi=() attributes with PlotlyJS backend #3199

Open
nbsmokee opened this issue Dec 23, 2020 · 7 comments

Comments

@nbsmokee
Copy link

I think this has not been reported before. I found that, when using the PlotlyJS backend, the size and dpi kwargs seem to be ingored and thus don't produce the expected results.

Details

  • Considering size, with the following MWE the plot shows up correctly in the plot pane (I use vscode, if that's important), but when I call savefig, the created image will always have a resolution of 700 * 500, as if the size keyword was not there. This is particularly annoying since obviously I need the plots to have a certain non-standard aspect ratio.
# size
using Plots
plotlyjs()

y = randn(20, 4)
plot(y, size=(300,400), show=true)
savefig("test.png")
  • Considering dpi, this value seems to be ignored at all, since the plot that shows up in the plot pane has the same size as it has when omitting the dpi kwarg (contrary to GR, where the size of the plot in the plot pane will adjust accordingly (which I don't find helpful, but that's another topic 😅 )) and the resulting image file always ends up having the standard resolution of 700 * 500.
# dpi
using Plots
plotlyjs()

y = randn(20, 4)
plot(y, dpi=1200, show=true)
savefig("test.png")

Backends

This bug occurs on ( insert x below )

Backend yes no untested
gr (default) x
pyplot x
plotly x
plotlyjs x
pgfplotsx x
inspectdr x

Versions

Plots.jl version: v1.9.1
Backend version (]st -m): PlotlyJS v0.14.0
Output of versioninfo():

Julia Version 1.5.3
Commit 788b2c77c1* (2020-11-09 13:37 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-10.0.1 (ORCJIT, skylake)
Environment:
  JULIA_EDITOR = "/usr/lib/electron9/electron"
  JULIA_NUM_THREADS = 
@nbsmokee nbsmokee added the bug label Dec 23, 2020
@Ezequiel92
Copy link

pgfplotsx has the same problem with the size parameter., it somewhat ignores it. Setting a size changes the saved image, but the result is not the one chosen and appears to depend on the data to be plotted.

Default size

GR defaults to 600x400 px, while PGFPlotsX default to 914x539 px, using the following MWE

using Plots, LaTeXStrings  
data = rand(10) 

plot(data) 
savefig("size_gr.png") 

pgfplotsx() 
plot(data) 
savefig("size_pgfplotsx.png")  

The result is difficult to replicate, because with random data each run can end (or not) in a different final image size for PGFPlotsX.

The aspect ratio of the actual plot (everything but the legend) seems similar enough though, doing

using Plots, LaTeXStrings  
data = rand(10) 

plot(data) 
savefig("size_gr.png") 

pgfplotsx() 
plot(data, legend=false) 
savefig("size_pgfplotsx.png")  

I get 600x400 px (600/400 = 1.5) for GR, as it should, and 860x546 px (860/546 = 1.575) for PGFPlotsX. So, in the ballpark.

Personalized size

The fact that kind of tries to respect the aspect ratio can be seen again doing

using Plots, LaTeXStrings  
pgfplotsx() 

for i in 1:30
    plot(rand(10), size=(600,600)) 
    savefig("size_pgfplotsx_" * string(i) * ".png") 
end 

I get 30 images with varying sizes: 914x849 px (x2), 914x841 px (x1), 914x839 px (x26), 923x839 px (x1), but all close to 1:1, if it weren’t for the legend. A different run would give different results, obviously. Clearly is taking the input size, the data and then choosing the final size, but as far as I know it is not documented which algorithm is used, as to reversed it and control effectively the final size.

In practice this is "solved" by trying different inputs until you get one output you like/can use. What is especially annoying is the preference for odd values making impossible to use a series of images for a video with VideoIO.jl (in the example above not a single one got an even x even value).

This is maybe tangentially related to #2303, where GR produces results off by one pixel.

Versions

From julia> versioninfo()

Julia Version 1.5.3 
Commit 788b2c77c1 (2020-11-09 13:37 UTC) 
Platform Info: 
  OS: Windows (x86_64-w64-mingw32) 
  CPU: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz 
  WORD_SIZE: 64 
  LIBM: libopenlibm 
  LLVM: libLLVM-9.0.1 (ORCJIT, skylake) 

From (@v1.5) pkg> status

[b964fa9f] LaTeXStrings v1.2.0 
[8314cec4] PGFPlotsX v1.2.10 
[91a5bcdd] Plots v1.9.1 
[f3b207a7] StatsPlots v0.14.17 

@tamits60
Copy link

tamits60 commented Jul 8, 2021

I had this problem too.
For Plotly, this works for me as a workaround.

using Plots
import Plotly
plotlyjs()

y = randn(20, 4)
plt = plot(y, size=(300,400), show=true)

width, height = plt.attr[:size]
Plots.prepare_output(plt)
Plotly.savefig(Plots.plotlybase_syncplot(plt), "test.png", width=width, height=height)

@ultrapoci
Copy link

I'm trying to use PlotlyJS in Pluto, but I cannot save files using the desired resolution. I've tried the above method but it doesn't work. I'm forced to use the GR backend to save files, but it lacks the nice interactive features plotlyjs has.

@ranocha
Copy link
Contributor

ranocha commented Dec 8, 2022

For reference, a similar workaround for PlotlyJS in Pluto is

import PlotlyJS
width, height = plt.attr[:size]
Plots.prepare_output(plt)
PlotlyJS.savefig(Plots.plotlyjs_syncplot(plt), "plot.pdf", width=width, height=height)

@mattcbro
Copy link

This problem definitely occurs using the Plotly backend in Plots.jl . Unfortunately the savefig exported in Plots.jl does NOT have width and height arguments. I haven't yet tried @ranocha solution.

This is an important issue for automating and creating plots for documents. I hope that the Plots.jl crew can remedy this. Interestingly, if you save the figure directly from within the vscode Julia plots pane, the svg file will have the correct sizing.

@eduardkieser
Copy link

eduardkieser commented Feb 26, 2024

This is still a problem for my setup, but I can also not use the work proposed by @ranocha because plotlybase_syncplot is not available:

Julia Version 1.9.2

Plotly v0.4.1
PlotlyBase v0.8.19
PlotlyJS v0.18.13
PlotlyKaleido v2.2.2
Plots v1.39.0

using Plots
import Plotly
plotlyjs()

function save_pdf(p, filename)
    width, height = p.attr[:size]
    Plots.prepare_output(p)
    Plotly.savefig(Plots.plotlybase_syncplot(p), filename, width=width, height=height)
end

p = plot(...)
save_pdf(p, filename)

Results in

ERROR: UndefVarError: `plotlybase_syncplot` not defined

Any suggestion or alternative work around would be greatly appreciated.

@axla-io
Copy link

axla-io commented Sep 3, 2024

It's now called plotlyjs_syncplot

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

No branches or pull requests

10 participants