Plotting a circle while also changing the limits of the axes

Hello,

I am trying to plot some small circles in my plotting window, in addition to the curves I’m already plotting. If I don’t want to set my x- and y- axis scales equal to each other, a naive drawing of a circle results in an ellipse. To fix this problem I found some nice example code online here : http://stackoverflow.com/questions/9230389/why-is-matplotlib-plotting-my-circles-as-ovals, which solves the problem by basically plotting an ellipse, but an ellipse which will look like a circle in the display window.

That works all fine for me, but then, if I change my xlim or ylim using ax1.set_xlim((something1,something2)) then the solution no longer works, and I get an ellipse.

A minimal example showing the breaking behavior can be seen below.

import matplotlib.pyplot as plt

from matplotlib.patches import Ellipse, Circle

fig = plt.figure()
ax1 = fig.add_subplot(111)

uncomment the following line to see it break

#ax1.set_xlim((0.2,1))

calculate asymmetry of x and y axes:

x0, y0 = ax1.transAxes.transform((0, 0)) # lower left in pixels
x1, y1 = ax1.transAxes.transform((1, 1)) # upper right in pixes
dx = x1 - x0
dy = y1 - y0
maxd = max(dx, dy)
width = .15 * maxd / dx
height = .15 * maxd / dy

a circle you expect to be a circle, but it is not

ax1.add_artist(Circle((.5, .5), .15))

an ellipse you expect to be an ellipse, but it’s a circle

ax1.add_artist(Ellipse((.75, .75), width, height))

plt.show()

I suppose the problem is that ax1.transAxes.transform commands return the same numbers, regardless of whether I’ve changed the limits or not. Is there an easy and clean way to fix this (perhaps a different command for getting x0,y0,x1, and y1)?

Thanks for the help!

Best,

Brad

I am probably gonna reply to that stackoverflow question with a better response…

Essentially, you want a similar behavior to the markers in the scatter plots, right? As you zoom or resize the plot, the circle markers stay as circles and have the same size relative to the size of the figure. If that is what you want, the way to do that is very easy.

ax1.scatter([0.5], [0.5], s=30)

Or whatever size you want (units of points).

I hope that helps!
Ben Root

···

On Mon, Nov 5, 2012 at 3:51 PM, Brad Malone <brad.malone@…287…> wrote:

Hello,

I am trying to plot some small circles in my plotting window, in addition to the curves I’m already plotting. If I don’t want to set my x- and y- axis scales equal to each other, a naive drawing of a circle results in an ellipse. To fix this problem I found some nice example code online here : http://stackoverflow.com/questions/9230389/why-is-matplotlib-plotting-my-circles-as-ovals, which solves the problem by basically plotting an ellipse, but an ellipse which will look like a circle in the display window.

That works all fine for me, but then, if I change my xlim or ylim using ax1.set_xlim((something1,something2)) then the solution no longer works, and I get an ellipse.

A minimal example showing the breaking behavior can be seen below.

I think the units are points^2, i.e., area of the circle...

Thanks,

Jason

···

On 11/5/12 3:19 PM, Benjamin Root wrote:

On Mon, Nov 5, 2012 at 3:51 PM, Brad Malone <brad.malone@…287… > <mailto:brad.malone@…287…>> wrote:

    Hello,

    I am trying to plot some small circles in my plotting window, in
    addition to the curves I'm already plotting. If I don't want to set
    my x- and y- axis scales equal to each other, a naive drawing of a
    circle results in an ellipse. To fix this problem I found some nice
    example code online here :
    http://stackoverflow.com/questions/9230389/why-is-matplotlib-plotting-my-circles-as-ovals,
    which solves the problem by basically plotting an ellipse, but an
    ellipse which will look like a circle in the display window.

    That works all fine for me, but then, if I change my xlim or ylim
    using ax1.set_xlim((something1,something2)) then the solution no
    longer works, and I get an ellipse.

    A minimal example showing the breaking behavior can be seen below.

I am probably gonna reply to that stackoverflow question with a better
response...

Essentially, you want a similar behavior to the markers in the scatter
plots, right? As you zoom or resize the plot, the circle markers stay
as circles and have the same size relative to the size of the figure.
If that is what you want, the way to do that is very easy.

ax1.scatter([0.5], [0.5], s=30)

Or whatever size you want (units of points).

Right, thank you. I keep forgetting that.

Ben Root

···

On Mon, Nov 5, 2012 at 4:22 PM, Jason Grout <jason-sage@…2130…> wrote:

On 11/5/12 3:19 PM, Benjamin Root wrote:

On Mon, Nov 5, 2012 at 3:51 PM, Brad Malone <brad.malone@…287… > > mailto:brad.malone@...287...> wrote:

Hello,
I am trying to plot some small circles in my plotting window, in
addition to the curves I'm already plotting. If I don't want to set
my x- and y- axis scales equal to each other, a naive drawing of a
circle results in an ellipse.  To fix this problem I found some nice
example code online here :
[http://stackoverflow.com/questions/9230389/why-is-matplotlib-plotting-my-circles-as-ovals](http://stackoverflow.com/questions/9230389/why-is-matplotlib-plotting-my-circles-as-ovals),
which solves the problem by basically plotting an ellipse, but an
ellipse which will look like a circle in the display window.
That works all fine for me, but then, if I change my xlim or ylim
using ax1.set_xlim((something1,something2)) then the solution no
longer works, and I get an ellipse.
A minimal example showing the breaking behavior can be seen below.

I am probably gonna reply to that stackoverflow question with a better

response…

Essentially, you want a similar behavior to the markers in the scatter

plots, right? As you zoom or resize the plot, the circle markers stay

as circles and have the same size relative to the size of the figure.

If that is what you want, the way to do that is very easy.

ax1.scatter([0.5], [0.5], s=30)

Or whatever size you want (units of points).

I think the units are points^2, i.e., area of the circle…

Thanks,

Jason

Hi Brad,

I didn’t quite follow what it was that you were trying to achieve, but the following example may be of interest to you:

import matplotlib.pyplot as plt

from matplotlib.patches import Ellipse, Circle

import matplotlib.transforms as mtrans

fig = plt.figure()

ax1 = fig.add_subplot(111)

x_in_axes_coords, y_in_axes_coords = 0.5, 0.5

radius_in_axes = 0.3

coords = [[x_in_axes_coords, y_in_axes_coords],

[x_in_axes_coords + radius_in_axes, y_in_axes_coords]]

coords = ax1.transAxes.transform(coords)

x_device, y_device = coords[0, :]

radius = coords[1, 0] - x_device

circle = Circle((x_device, y_device), radius,

transform=mtrans.IdentityTransform())

fig.artists.append(circle)

plt.show()

Clearly, you will always have circles with this approach (the circle is defined in device coordinates, i.e. pixels),

but with the way this is implemented, it does not behave in the same way as axes coordinates do when you resize your window.

I am trying to plot some small circles in my plotting window, in addition to the curves I’m already plotting.

I wonder if you would mind expanding on that sentence? Does the example I provide do what you want?

Thanks,

Phil

···

On 5 November 2012 20:51, Brad Malone <brad.malone@…287…> wrote:

Hello,

I am trying to plot some small circles in my plotting window, in addition to the curves I’m already plotting. If I don’t want to set my x- and y- axis scales equal to each other, a naive drawing of a circle results in an ellipse. To fix this problem I found some nice example code online here : http://stackoverflow.com/questions/9230389/why-is-matplotlib-plotting-my-circles-as-ovals, which solves the problem by basically plotting an ellipse, but an ellipse which will look like a circle in the display window.

That works all fine for me, but then, if I change my xlim or ylim using ax1.set_xlim((something1,something2)) then the solution no longer works, and I get an ellipse.

A minimal example showing the breaking behavior can be seen below.

import matplotlib.pyplot as plt

from matplotlib.patches import Ellipse, Circle

fig = plt.figure()
ax1 = fig.add_subplot(111)

uncomment the following line to see it break

#ax1.set_xlim((0.2,1))

calculate asymmetry of x and y axes:

x0, y0 = ax1.transAxes.transform((0, 0)) # lower left in pixels
x1, y1 = ax1.transAxes.transform((1, 1)) # upper right in pixes
dx = x1 - x0
dy = y1 - y0
maxd = max(dx, dy)
width = .15 * maxd / dx
height = .15 * maxd / dy

a circle you expect to be a circle, but it is not

ax1.add_artist(Circle((.5, .5), .15))

an ellipse you expect to be an ellipse, but it’s a circle

ax1.add_artist(Ellipse((.75, .75), width, height))

plt.show()

I suppose the problem is that ax1.transAxes.transform commands return the same numbers, regardless of whether I’ve changed the limits or not. Is there an easy and clean way to fix this (perhaps a different command for getting x0,y0,x1, and y1)?

Thanks for the help!

Best,

Brad


LogMeIn Central: Instant, anywhere, Remote PC access and management.

Stay in control, update software, and manage PCs from one command center

Diagnose problems and improve visibility into emerging IT issues

Automate, monitor and manage. Do more in less time with Central

http://p.sf.net/sfu/logmein12331_d2d


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Essentially, you want a similar behavior to the markers in the scatter
plots, right? As you zoom or resize the plot, the circle markers stay as
circles and have the same size relative to the size of the figure. If that
is what you want, the way to do that is very easy.

ax1.scatter([0.5], [0.5], s=30)

Or whatever size you want (units of points).

I hope that helps!
Ben Root

Hi Ben,

Thanks. I actually tried this before and it didn't appear to work for me.
But I think the problem was that I thought s was the radius in units of my
axes, and so was simply not seeing the dot on top of the line that was
already there. I was just choosing values that were way too small to see.

This should meet my needs.

I wonder if you would mind expanding on that sentence? Does the example I

provide do what you want?

Thanks,
Phil

Phil, thanks for this example as well. It also would work for my purposes.
All I meant by that sentence is that, in my real script, I am plotting a
bunch of lines as well, and I just wanted these circles to also be present
in the plot (the example code I attached was simply the circles/ellipses).

Best,
Brad