7

If I plot a circle with this snippet

from sympy import *
x, y = symbols('x y')        
p1 = plot_implicit(Eq(x**2 +y**2, 1),aspect_ratio=(1.,1.))

I will get a figure window like this one

enter image description here

Now the aspect ratio is not what I was expecting because I see an ellipse instead of a circle. Moreover, if I change the aspect ratio of the window (dragging the bottom-right corner of the window) I get also a change in the aspect ratio of the plot... The following image is what I get after dragging the corner in order to see a circle:

enter image description here

I would like to get a plot like the one you get in Matlab when you set axis equal, see http://it.mathworks.com/help/matlab/creating_plots/aspect-ratio-for-2-d-axes.html when you plot an ellipse

enter image description here

What am I missing?

I am using Jupyter and the version of the notebook server is 4.1.0 and is running on: Python 2.7.11 |Anaconda 2.5.0 (64-bit)| (default, Dec 6 2015, 18:08:32) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]

Alessandro Jacopson
  • 18,047
  • 15
  • 98
  • 153
  • I tried on `window2010` and `python 2.7.x` and `sympy 1.0`, same issue as yours. I am wondering if there is a `bug` either in `python 2.7` or `sympy 1.0`. I dont have `python 3.x`, but it needs to be tried on that – Anil_M Apr 08 '16 at 20:39

3 Answers3

3

I'm not sure if this is covered in Sympy's stable API, but you can extract matplotlib's figure and axis instance and the use standard matplotlib calls to change the appearance of your plot:

import matplotlib.pyplot as plt
import sympy as sy

x, y = sy.symbols('x y')
p1 = sy.plot_implicit(sy.Eq(x**2 +y**2, 4))
fg, ax = p1._backend.fig, p1._backend.ax  # get matplotib's figure and ax

# Use matplotlib to change appearance: 
ax.axis('tight')  # list of float or {‘on’, ‘off’, ‘equal’, ‘tight’, ‘scaled’, ‘normal’, ‘auto’, ‘image’, ‘square’}
ax.set_aspect("equal") # 'auto', 'equal' or a positive integer is allowed
ax.grid(True)
fg.canvas.draw()


plt.show()  # enter matplotlib's event loop (not needed in Jupyter)

This gives: Tight Axis with equal aspect ratio

Dietrich
  • 5,241
  • 3
  • 24
  • 36
  • May you please write the version of your Python environment? I tested your code and I get a plot different from the one you attached. Thank you. – Alessandro Jacopson Apr 10 '16 at 16:02
  • @AlessandroJacopson I am using Debian/Sid with matplotlib 1.5, ipython 2.4, Sympy 0.7.6.1 and python 2.7/3.5. I reran it and got the desired results when using pylab (`%pylab` in the ipython shell or --pylab as parameter ) but not when not using it. I am a bit clueless concerning possible causes. – Dietrich Apr 10 '16 at 17:43
  • in Sympy 1.0 it does not work... function show() in plot.py call self.plt.show() instead self.fig.show(). As fast workaround/test replacing plt to fig give expected result. – kimstik May 22 '17 at 08:49
1

Within the help for plot_implicit, the x_var and y_var-arguments are mentioned. Using them allows you to manually set limits to the x and y axis. If you scale those limits appropriately, you can achieve an even aspect ratio.

from sympy import *

x, y = symbols('x y')

scal = 3840/2400 # corresponds to your screen resolution
a = 1.05

p1 = plot_implicit(Eq(x**2+y**2,1),title='with xlim and ylim\n',\
                   xlim=(-1,1), ylim=(-1,1),aspect_ratio='equal')

p2 = plot_implicit(Eq(x**2+y**2,1),title='with x_var and y_var\n',\
                   x_var=(x,-a*scal,a*scal), y_var=(y,-a,a))

(My Sympy-version: 1.1.1)

1

now in Sept 2019 this code works:

import matplotlib.pyplot as plt
import sympy

x, y = sympy.symbols('x y')

plt.ion() #interactive on 

p1 = sympy.plot_implicit(sympy.Eq(x**2 +y**2, 4), block = False)

fg, ax = p1._backend.fig, p1._backend.ax  # get matplotib's figure and axes

# Use matplotlib to change appearance:
ax.axis('tight')  # list of float or {‘on’, ‘off’, ‘equal’, ‘tight’, ‘scaled’, ‘normal’, ‘auto’, ‘image’, ‘square’}
ax.set_aspect("equal") # 'auto', 'equal' or a positive integer is allowed
ax.grid(True)
plt.ioff() #interactive off
plt.show()
Erhy
  • 92
  • 3
  • 8
  • Thank you for this code snippet, which might provide some limited short-term help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its long-term value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Toby Speight Sep 24 '19 at 14:50
  • 1
    It doesn't work for me AttributeError: 'Plot' object has no attribute '_backend' – G M Oct 11 '19 at 22:23
  • @GM, it doesn't work, except in Jupyter environment. – mins Sep 03 '22 at 11:43