Plots.jl icon indicating copy to clipboard operation
Plots.jl copied to clipboard

[FR] rework limits when `aspect_ratio=:equal` for pyplot

Open jamblejoe opened this issue 2 years ago • 26 comments

Details

aspect_ratio=:equal is broken for pyplot. Works for GR. See images below. Code:

using Plots; pyplot()
plot([1,2,3], [1,100,1000]; aspect_ratio=:equal)

GR: image pyplot: image

Backends

This bug occurs on ( insert x below )

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

Versions

Plots.jl version: v1.36.2 Backend version (]st -m <backend(s)>): GR v0.69.5, PyPlot v2.11.0, Output of versioninfo():

julia> versioninfo()
Julia Version 1.8.0
Commit 5544a0fab76 (2022-08-17 13:38 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 1 on 8 virtual cores

jamblejoe avatar Nov 21 '22 12:11 jamblejoe

This does not happen in vscode jupyter notebooks rendering. But is seen if I save the figure (to pdf, png, svg). I can provide versioninfos if requested.

jamblejoe avatar Nov 21 '22 12:11 jamblejoe

Would be helpful to see if previous versions (1.35, 1.34, ...) are affected or not.

t-bltg avatar Nov 21 '22 14:11 t-bltg

Its in versions 1.32-1.35 with PyPlot version 2.11. I will test other pyplot versions.

jamblejoe avatar Nov 21 '22 17:11 jamblejoe

Plots 1.36.2 is not working with PyPlot 2.6.3 although it should according to compat. But this is another issue

jamblejoe avatar Nov 21 '22 17:11 jamblejoe

IIUC, you say that Plots 1.32-1.35 are not broken in terms of aspect_ratio ?

~~Can you post a mwe ? You posted only images.~~

t-bltg avatar Nov 21 '22 17:11 t-bltg

Wait I don't think it is broken.

The pyplot behavior is just different from gr, which fills the window.

pyplot()
plot(1:100, 1:2:200; aspect_ratio=:equal)

t-bltg avatar Nov 21 '22 17:11 t-bltg

@t-bltg I don't think so. I tried

using PyPlot
axis("equal")
plot([1,2,3],[1,10,100])

and it shows grafik compared to

using Plots; pyplot()
plot([1,2,3], [1,10,100]; aspect_ratio=:equal)

grafik

Please add the bug label again.

jamblejoe avatar Nov 21 '22 20:11 jamblejoe

I don't think we are doing the same thing here.

The pyplot output is similar to plain matplotlib commands:

>>> import pylab as plt
>>> fig, ax = plt.subplots()
>>> ax.plot([1,2,3],[1,10,100])
>>> ax.set_aspect('equal')
>>> plt.show()

foo_ar

t-bltg avatar Nov 21 '22 20:11 t-bltg

I can confirm this for python as well. That is odd.

jamblejoe avatar Nov 21 '22 20:11 jamblejoe

is axis("equal") doing something differently than ax.set_aspect('equal')?

jamblejoe avatar Nov 21 '22 20:11 jamblejoe

Probably, but I don't know if this is specific to PyCall or if there is an equivalent in python.

t-bltg avatar Nov 21 '22 20:11 t-bltg

It's explained here: https://matplotlib.org/stable/gallery/subplots_axes_and_figures/axis_equal_demo.html

jamblejoe avatar Nov 21 '22 20:11 jamblejoe

How do I get the "GR"-behavior of aspect_ratio=:equal in pyplot() ?

jamblejoe avatar Nov 21 '22 20:11 jamblejoe

This does not happen in vscode jupyter notebooks rendering. But is seen if I save the figure (to pdf, png, svg). I can provide versioninfos if requested.

This seems to do something different as well. Somehow I feel very confused about what is going right now.

jamblejoe avatar Nov 21 '22 20:11 jamblejoe

We use ax.set_axpect, so the valid choices are explained here: https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.set_aspect.html.

t-bltg avatar Nov 21 '22 20:11 t-bltg

I you want the GR behaviour why not set xlims and ylims ?

plot([1,2,3], [1,10,100], xlims=(-600, 600))

t-bltg avatar Nov 21 '22 20:11 t-bltg

It says in the documenation of matplotlib:

'auto' automatic; fill the position rectangle with data

But the :auto keyword to aspect_ratio in Plots.jl seems to do something different - namely nothing (with pyplot)? grafik

code: plot([1,2,3],[1,10,100]; aspect_ratio=:auto)

Setting xlims/ylims is tedious. Shouldn't the behaviour between backends be consistent?

jamblejoe avatar Nov 21 '22 21:11 jamblejoe

:auto does what is says, it just fills the window: this is the default yes.

t-bltg avatar Nov 21 '22 21:11 t-bltg

ok. I misread that in the documentation. So then there is no way of getting axis('equal') behavior of pyplot with Plots.jl?

jamblejoe avatar Nov 21 '22 21:11 jamblejoe

The plotly behavior of aspect_ratio=:equal is the same as GR.

newplot

Shall I test the other backends as well or will they all show the same behavior as GR? If so, I heavily vote for changing pyplot standard behavior of aspect_ratio=:equal.

jamblejoe avatar Nov 21 '22 21:11 jamblejoe

Aspect ratio set to :equal means 1 unit on the x axis equals 1 unit on the y axis.

This is exactly what pyplot does currently, so I fail to see how this is incorrect.

However, we can maybe automatically change the limits in that case, approaching something similar to:

julia> plot([1,2,3], [1,10,100]; aspect_ratio=:equal, xlims=(-70, 70), ylims=(0, 100))

t-bltg avatar Nov 21 '22 21:11 t-bltg

Sorry for the misunderstanding. I see that Plots.jl is using matplotlibs default behavior. It is just very different from the default behavior of GR or plotly. Question: Should the behavior be consistent across backends or should aspect_ratio resemble the default behavior of the backends?

jamblejoe avatar Nov 21 '22 21:11 jamblejoe

You are missing the point: aspect_ratio is correct.

Someone should work on adjusting the axes limits to fill the window using Plots.pyplot() backend, when aspect_ratio is set to :equal.

For example, gr does this here: https://github.com/JuliaPlots/Plots.jl/blob/master/src/backends/gr.jl#L1298-L1315 (adjusting the viewport to fill the window).

Something similar should be done for Plots.pyplot(), I guess.

t-bltg avatar Nov 21 '22 21:11 t-bltg

Great thanks! That makes sense! You changed the issue already, thanks!

jamblejoe avatar Nov 21 '22 21:11 jamblejoe

For the record: Pluto.jl with Plots.jl and PyPlot.jl will automatically have nice limits for aspect_ratio=:equal. E.g.

plot([1,2,3], [1,100,1000]; aspect_ratio=:equal)

results in the browser in image

Saving the figure in another (!) cell

savefig(dir)

will correctly keep the aspect ratio. But executing the following code in a single (!) cell

begin
plot([1,2,3], [1,100,1000]; aspect_ratio=:equal)
savefig(dir)
end

will result in what is observed in e.g. vscode or plotting via Qt: pyplot_aspectratio

jamblejoe avatar Jan 24 '23 13:01 jamblejoe

@t-bltg I roughly understand the code following https://github.com/JuliaPlots/Plots.jl/blob/42244b6aea99327acb07055d57bff2da41104555/src/backends/gr.jl#L1335C36-L1335C36. But where would this be implemented in the python plot backend? Around here

https://github.com/JuliaPlots/Plots.jl/blob/42244b6aea99327acb07055d57bff2da41104555/src/backends/pythonplot.jl#L848 ?

jamblejoe avatar Nov 20 '23 16:11 jamblejoe