automatic format of y-axis limits for small changes with large offset

Hi,

is it possible to change the default y-axis scaling so that the
ticks/label are not with respect to the large offset?

For example:

import scipy
import pylab

x = scipy.arange(100)
y = scipy.rand(100) + 1000006

pylab.figure()
pylab.plot(x,y)
pylab.grid()

pylab.show()

This gives the y-limits as (0,1) with respect to 1000006. This makes
it very hard to read. I'd like to be able to configure this manually.

Thanks in advance,
Daniel

Maybe I should mention that there are actually two reasons why I don't
like this behavior:

1) it's sometimes very hard to read what's going on,
2) there also seems to be a bug when the limits are changed later, see
attached results: the upper subplot is default, the lower subplot uses
the padding.

2011-03-10_110734__TSensPosCheck.png

···

##--------------------------
def update_ax2(ax1):
  '''
  Automatically update ylim of ax2 when ylim of ax1 changes.
  '''
  y1, y2 = ax1.get_ylim()
  ## modify the limits
  ax2.set_ylim((Tc(y1), Tc(y2)))
  ax2.figure.canvas.draw()

Both plots are actually identical but use a different x-axis. In
ordert to create a nicely padded plot, I use the following function,
which breaks the scaling information AND the calculation of the second
axis limits:

##--------------------------
def axispaddingAX(ax):
  '''
  Saubere bzw. schoene Achsenskalierung für MPL-Skripten.
  '''
  lines = ax.get_lines()
  xtemp = []
  ytemp = []
  for line in lines:
    xtemp.append(min(line.get_xdata()))
    xtemp.append(max(line.get_xdata()))
    ytemp.append(min(line.get_ydata()))
    ytemp.append(max(line.get_ydata()))
  xmin,xmax = min(xtemp),max(xtemp)
  ymin,ymax = min(ytemp),max(ytemp)
  span = 0.05
  rangex = (xmin-span*(xmax-xmin), xmax+span*(xmax-xmin))
  rangey = (ymin-span*(ymax-ymin), ymax+span*(ymax-ymin))
  ax.set_xlim(rangex)
  ax.set_ylim(rangey)

Thanks a lot in advance for any hint or comment on this,
Daniel

2011/3/10 Daniel Mader <danielstefanmader@...982...>:

Hi,

is it possible to change the default y-axis scaling so that the
ticks/label are not with respect to the large offset?

For example:

import scipy
import pylab

x = scipy.arange(100)
y = scipy.rand(100) + 1000006

pylab.figure()
pylab.plot(x,y)
pylab.grid()

pylab.show()

This gives the y-limits as (0,1) with respect to 1000006. This makes
it very hard to read. I'd like to be able to configure this manually.

Thanks in advance,
Daniel

I tried to fix matplotlib to be smarter about choosing the offset value a while back, but I couldn’t come up with something that worked well in the general case. You can manually turn it off completely, and have the full value displayed (or even manually set the offset value). If you have a very recent matplotlib:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(100)
y = np.random.rand(100) + 1000006

plt.figure()
plt.plot(x, y)
plt.grid()
plt.ticklabel_format(useOffset=1000000, axis=‘y’)

plt.show()

Or you can turn it off by setting useOffset to False.

If you don’t have a recent enough matplotlib, you can turn it off completely by doing something like this:

import matplotlib.pyplot as plt

import numpy as np
from matplotlib.ticker import ScalarFormatter

x = np.arange(100)
y = np.random.rand(100) + 1000006

fig = plt.figure()
ax = fig.gca()
ax.plot(x, y)
ax.grid()
ax.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))

plt.show()

I hope this helps!
Ben Root

···

On Thu, Mar 10, 2011 at 4:54 AM, Daniel Mader <danielstefanmader@…982…> wrote:

Hi,

is it possible to change the default y-axis scaling so that the

ticks/label are not with respect to the large offset?

For example:

import scipy

import pylab

x = scipy.arange(100)

y = scipy.rand(100) + 1000006

pylab.figure()

pylab.plot(x,y)

pylab.grid()

pylab.show()

This gives the y-limits as (0,1) with respect to 1000006. This makes

it very hard to read. I’d like to be able to configure this manually.

Thanks in advance,

Daniel

Hi Ben,

thanks a lot, this really helpes in the simple example, I'll try to
find out how to use it in the complex script. It seems 1.0.0 is recent
enough for this!

Thanks again,
Daniel

2011/3/10 Benjamin Root <ben.root@...1304...>:

···

On Thu, Mar 10, 2011 at 4:54 AM, Daniel Mader > <danielstefanmader@...982...> wrote:

Hi,

is it possible to change the default y-axis scaling so that the
ticks/label are not with respect to the large offset?

For example:

import scipy
import pylab

x = scipy.arange(100)
y = scipy.rand(100) + 1000006

pylab.figure()
pylab.plot(x,y)
pylab.grid()

pylab.show()

This gives the y-limits as (0,1) with respect to 1000006. This makes
it very hard to read. I'd like to be able to configure this manually.

Thanks in advance,
Daniel

I tried to fix matplotlib to be smarter about choosing the offset value a
while back, but I couldn't come up with something that worked well in the
general case. You can manually turn it off completely, and have the full
value displayed (or even manually set the offset value). If you have a very
recent matplotlib:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(100)
y = np.random.rand(100) + 1000006

plt.figure()
plt.plot(x, y)
plt.grid()
plt.ticklabel_format(useOffset=1000000, axis='y')

plt.show()

Or you can turn it off by setting useOffset to False.

If you don't have a recent enough matplotlib, you can turn it off completely
by doing something like this:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import ScalarFormatter

x = np.arange(100)
y = np.random.rand(100) + 1000006

fig = plt.figure()
ax = fig.gca()
ax.plot(x, y)
ax.grid()
ax.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))

plt.show()

I hope this helps!
Ben Root

Hi again,

unfortunately, the proposed solution breaks a second y-axis. Attached
is a script which demonstrates the problem in the third figure. The
second axis should be half of the first one.

import pylab
import scipy

pylab.close('all')

···

##------------------------------------------------------------------------------
## matplotlib.pyplot / pylab
x = scipy.arange(100)
y = scipy.rand(100) + 1000006

pylab.figure()
pylab.plot(x,y)
pylab.grid()

#pylab.ticklabel_format(useOffset=1000000, axis='y')
pylab.ticklabel_format(useOffset=False, axis='y')

##------------------------------------------------------------------------------
## matplotlib
fig = pylab.figure(figsize=(8,6))
ax = fig.add_subplot(111)
ax.plot(x,y)
ax.grid()

ax.ticklabel_format(useOffset=1000000, axis='y')
#ax.ticklabel_format(useOffset=False, axis='y')

##------------------------------------------------------------------------------
## matplotlib twinx()
fig = pylab.figure(figsize=(8,6))
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.plot(x,y)
ax1.grid()

## automatically update ylim of ax2 when ylim of ax1 changes:
def update_ax2(ax1):
  y1, y2 = ax1.get_ylim()
  ## modify the limits
  ax2.set_ylim((y1/2., y2/2.))
  ax2.figure.canvas.draw()
ax1.callbacks.connect("ylim_changed", update_ax2)

ax1.ticklabel_format(useOffset=False, axis='y')

##------------------------------------------------------------------------------
pylab.show()

2011/3/10 Daniel Mader <danielstefanmader@...982...>:

Hi Ben,

thanks a lot, this really helpes in the simple example, I'll try to
find out how to use it in the complex script. It seems 1.0.0 is recent
enough for this!

Thanks again,
Daniel

2011/3/10 Benjamin Root <ben.root@...1304...>:

On Thu, Mar 10, 2011 at 4:54 AM, Daniel Mader >> <danielstefanmader@...982...> wrote:

Hi,

is it possible to change the default y-axis scaling so that the
ticks/label are not with respect to the large offset?

For example:

import scipy
import pylab

x = scipy.arange(100)
y = scipy.rand(100) + 1000006

pylab.figure()
pylab.plot(x,y)
pylab.grid()

pylab.show()

This gives the y-limits as (0,1) with respect to 1000006. This makes
it very hard to read. I'd like to be able to configure this manually.

Thanks in advance,
Daniel

I tried to fix matplotlib to be smarter about choosing the offset value a
while back, but I couldn't come up with something that worked well in the
general case. You can manually turn it off completely, and have the full
value displayed (or even manually set the offset value). If you have a very
recent matplotlib:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(100)
y = np.random.rand(100) + 1000006

plt.figure()
plt.plot(x, y)
plt.grid()
plt.ticklabel_format(useOffset=1000000, axis='y')

plt.show()

Or you can turn it off by setting useOffset to False.

If you don't have a recent enough matplotlib, you can turn it off completely
by doing something like this:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import ScalarFormatter

x = np.arange(100)
y = np.random.rand(100) + 1000006

fig = plt.figure()
ax = fig.gca()
ax.plot(x, y)
ax.grid()
ax.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))

plt.show()

I hope this helps!
Ben Root

--
Zugallistr. 11/14
5020 Salzburg
M_at +43 699 10 54 54 53
T_at +43 662 841635
M_de +49 179 2300317
E danielstefanmader@...982...

Maybe I should mention that there are actually two reasons why I don't
like this behavior:

1) it's sometimes very hard to read what's going on,
2) there also seems to be a bug when the limits are changed later, see
attached results: the upper subplot is default, the lower subplot uses
the padding.

##--------------------------
def update_ax2(ax1):
   '''
   Automatically update ylim of ax2 when ylim of ax1 changes.
   '''
   y1, y2 = ax1.get_ylim()
   ## modify the limits
   ax2.set_ylim((Tc(y1), Tc(y2)))
   ax2.figure.canvas.draw()

  Both plots are actually identical but use a different x-axis. In
ordert to create a nicely padded plot, I use the following function,
which breaks the scaling information AND the calculation of the second
axis limits:

##--------------------------
def axispaddingAX(ax):
   '''
   Saubere bzw. schoene Achsenskalierung für MPL-Skripten.
   '''
   lines = ax.get_lines()
   xtemp = []
   ytemp = []
   for line in lines:
     xtemp.append(min(line.get_xdata()))
     xtemp.append(max(line.get_xdata()))
     ytemp.append(min(line.get_ydata()))
     ytemp.append(max(line.get_ydata()))
   xmin,xmax = min(xtemp),max(xtemp)
   ymin,ymax = min(ytemp),max(ytemp)
   span = 0.05
   rangex = (xmin-span*(xmax-xmin), xmax+span*(xmax-xmin))
   rangey = (ymin-span*(ymax-ymin), ymax+span*(ymax-ymin))
   ax.set_xlim(rangex)
   ax.set_ylim(rangey)

I don't know if it would help overall, but in place of your padding function, have you considered the pylab or pyplot margins() function?

Eric

···

On 03/10/2011 01:13 AM, Daniel Mader wrote:

Thanks a lot in advance for any hint or comment on this,
Daniel

2011/3/10 Daniel Mader<danielstefanmader@...982...>:

Hi,

is it possible to change the default y-axis scaling so that the
ticks/label are not with respect to the large offset?

For example:

import scipy
import pylab

x = scipy.arange(100)
y = scipy.rand(100) + 1000006

pylab.figure()
pylab.plot(x,y)
pylab.grid()

pylab.show()

This gives the y-limits as (0,1) with respect to 1000006. This makes
it very hard to read. I'd like to be able to configure this manually.

Thanks in advance,
Daniel

------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Hi Eric,

thank you so much for pointing this out! Didn't know about the
function before, it really helps me a lot!

However, for the current problem it doesn't help. The scaling of the
second axis broken without any margin or padding changes.

As a workaround, I could of course plot the data two times, first in
the first axis, and then in the second axis, and make sure the margins
are equal.

However, this would considerable increase the file size for vector
based formats as I plot *a lot* of data points :slight_smile:

Either way, thanks a lot for this hint!

2011/3/11 Eric Firing <efiring@...202...>:

···

On 03/10/2011 01:13 AM, Daniel Mader wrote:

Maybe I should mention that there are actually two reasons why I don't
like this behavior:

1) it's sometimes very hard to read what's going on,
2) there also seems to be a bug when the limits are changed later, see
attached results: the upper subplot is default, the lower subplot uses
the padding.

##--------------------------
def update_ax2(ax1):
'''
Automatically update ylim of ax2 when ylim of ax1 changes.
'''
y1, y2 = ax1.get_ylim()
## modify the limits
ax2.set_ylim((Tc(y1), Tc(y2)))
ax2.figure.canvas.draw()

Both plots are actually identical but use a different x-axis. In
ordert to create a nicely padded plot, I use the following function,
which breaks the scaling information AND the calculation of the second
axis limits:

##--------------------------
def axispaddingAX(ax):
'''
Saubere bzw. schoene Achsenskalierung für MPL-Skripten.
'''
lines = ax.get_lines()
xtemp = []
ytemp = []
for line in lines:
xtemp.append(min(line.get_xdata()))
xtemp.append(max(line.get_xdata()))
ytemp.append(min(line.get_ydata()))
ytemp.append(max(line.get_ydata()))
xmin,xmax = min(xtemp),max(xtemp)
ymin,ymax = min(ytemp),max(ytemp)
span = 0.05
rangex = (xmin-span*(xmax-xmin), xmax+span*(xmax-xmin))
rangey = (ymin-span*(ymax-ymin), ymax+span*(ymax-ymin))
ax.set_xlim(rangex)
ax.set_ylim(rangey)

I don't know if it would help overall, but in place of your padding
function, have you considered the pylab or pyplot margins() function?

Eric

Thanks a lot in advance for any hint or comment on this,
Daniel

2011/3/10 Daniel Mader<danielstefanmader@...982...>:

Hi,

is it possible to change the default y-axis scaling so that the
ticks/label are not with respect to the large offset?

For example:

import scipy
import pylab

x = scipy.arange(100)
y = scipy.rand(100) + 1000006

pylab.figure()
pylab.plot(x,y)
pylab.grid()

pylab.show()

This gives the y-limits as (0,1) with respect to 1000006. This makes
it very hard to read. I'd like to be able to configure this manually.

Thanks in advance,
Daniel