Hi all, Is there a trick hidden somewhere for autoscaling one

> axis only? I am frequently plotting data which has a series

> of narrow peaks and a large dynamic range. After zooming on

> the x-axis to the region of interest, I'd like to have an

> option to make the y axis rescale for the data in that range

Just to make sure you know, with the new toolbar2 (matplotlib-0.61)

you can selectively scale the yaxis interactively by pressing the

pan/zoom button, and clicking and dragging your right mouse button

over the y axis while holding down the 'y' key. Ditto for pan with

the left button.

> only. Having flailed around in the source I have the feeling

> that this is possible, but I haven't quite fathomed out how

> to do it (I'm using matplotlib for an interactive plot

> embedded in a tk application). Essentially I want the

> appropriate magic spell to give me a bounding box in y for

> the current x axis limits. The things I tried so far always

> seem to give the bounding box for all the data points,

> including the ones which are not currently being plotted on

> the x range. Sorry if I've missed something obvious!

No you're not missing anything. I can give you an idea of how to hack

this though. The autoscaling is controlled by a tick locator, found

in matplotlib.tickers. There are a number of locators which derive

from the Locator base class. You can access the major tick locator of

a given axis with, for example

locator = ax.yaxis.get_major_locator()

The locator has a method to compute the view limits

vmin, vmax = locator.autoscale()

It uses a _transforms.Interval instance under the hood to get the data

limits dmin, dmax which gives the min and max range for your data on

that axis. Of course, this is the min and max for all the y data, not

just the data in the current xrange, which is your problem.

In order to solve this, your need to: 1) compute the data limits in

the current viewport, 2) set the limited data lim on the axis interval

instance, 3) use it to get the new autoscale limits, and 4) reset the

old data lim interval instance back to its original setting. Assuming

you know the y data lim in the xrange of interest (more on that later)

you would do (untested but should work barring an obvious screw up)

interval = ax.yaxis.get_data_interval()

savemin, savemax = interval.get_bounds()

dmin, dmax = # compute the y data limits in this xrange as below

interval.set_bounds(dmin, dmax)

# the locator has a ref to the interval and so sees your changes

ax.set_ylim(locator.autoscale()) # autoscale returns (vmin, vmax)

# now reset the original data lim

interval.set_bounds(savemin, savemax)

The only remaining thing is to get the ydata in xrange. This depends

on the kind of data you plotted, but let's assume it is from 'plot'

and thus your data are stored in Line2D instances. With a single line

(eg returned by the call) 'line, = plot(x,y)' (note the comma for

tuple unpacking) you can do

import matplotlib.numerix as nx

xmin, xmax = ax.get_xlim()

xdata = line.get_xdata()

ydata = line.get_xdata()

ind = nx.nonzero(mx.logical_and(nx.greater_equal(xdata, xmin)

nx.less_equal(xdata, xmax)))

y = nx.take(ydata, ind)

dmin, dmax = min(y), max(y)

# and now set the data lim in the interval instance as indicated

# above

Now that's the process for a single line. For multiple lines, all you

need to do is keep a running total of all the data to get the min/max

of all the lines. The function ax.get_lines() will return all the

data lines matplotlib uses. If you have scatters, pcolors and other

kinds of plots which may use collections and other data structures,

then more work would be needed still. However, you may have direct

access to your data, in which case you can just use that to extract

the ydata in the range.

BTW, there has been some discussion on the devel list recently about a

plugin feature to support easy customization and extension of the

toolbar. This kind of thing is a perfect candidate for that, because

you could create a plugin for 'autoscale y in the current xrange' and

we could place it in a contrib plugin dir that others could add to

their toolbar when they want.

Hope this helps,

JDH