Autoscaling one axis onyl

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