Hi,

In my attempt to get scroll wheel zooming working for this release I added
support for the scroll wheel to TkAgg, and added support for draw_idle to
the wx backend.

I'm attaching the wheel zoom demonstration code.  This is standalone code
which is not yet ready to go into backend_bases.  It only supports linear
and log axes.  Using transform magic would be better here.  Also, colormap
zooming is hacked (I don't know how to determine if the axes contain a
colorbar, and what the corresponding mappable is, so I put a list of
colorbars in the figure).

In the process of developing this code I noticed that a lot of the contains
tests are broken by the new transforms.  Try attaching onHilite to the
motion notify event on any canvas --- objects should turn light blue as you
hover over them.

E.g.,

  from pylab import plot, gcf, show
  plot([1,2,3],[1,5,2])
  cvs = gcf().canvas
  cvs.mpl_connect('motion_notify_event',cvs.onHilite)
  show()

I can fixes the axis hit test.  I'm not sure how many other problems there
are, but I'm pretty sure I won't get to them all before next Tuesday.

   - Paul

import math
import matplotlib
#matplotlib.use('WxAgg')
#matplotlib.use('TkAgg')
#matplotlib.use('GtkAgg')
import pylab
import matplotlib.colors as colors

def _rescale(lo,hi,step,pt=None,bal=None,scale='linear'):
    """
    Rescale (lo,hi) by step, returning the new (lo,hi)
    The scaling is centered on pt, with positive values of step
    driving lo/hi away from pt and negative values pulling them in.
    If bal is given instead of point, it is already in [0,1] coordinates.

    This is a helper function for step-based zooming.
    """
    # Convert values into the correct scale for a linear transformation
    # TODO: use proper scale transformers
    if scale=='log':
        lo,hi = math.log10(lo),math.log10(hi)
        if pt is not None: pt = math.log10(pt)

    # Compute delta from axis range * %, or 1-% if percent is negative
    if step > 0:
        delta = float(hi-lo)*step/100
    else:
        delta = float(hi-lo)*step/(100-step)

    # Add scale factor proportionally to the lo and hi values, preserving the
    # point under the mouse
    if bal is None:
        bal = float(pt-lo)/(hi-lo)
    lo = lo - bal*delta
    hi = hi + (1-bal)*delta

    # Convert transformed values back to the original scale
    if scale=='log':
        lo,hi = math.pow(10.,lo),math.pow(10.,hi)

    return (lo,hi)

def onWheel(event):
    """
    Process mouse wheel as zoom events
    """
    ax = event.inaxes
    try:
        step = event.step
    except:
        if event.button == 'up':
            step = 1
        else:
            step = -1
    print "zoom",step

    # Ick! Can't tell if the axes contains a colorbar.
    if hasattr(event.canvas,'_colorbars') and ax in event.canvas._colorbars:
        mappable = event.canvas._colorbars[ax].mappable
        # rescale colormap: the axes are already scaled to 0..1,
        # so use bal instead of pt for centering
        lo,hi = mappable.get_clim()
        if isinstance(mappable.norm,colors.LogNorm):
            vscale = 'log'
        else:
            vscale = 'linear'
        lo,hi = _rescale(lo,hi,step,bal=event.ydata,scale=vscale)
        mappable.set_clim(lo,hi)

    elif ax != None:
        # Event occurred inside a plotting area
        lo,hi = ax.get_xlim()
        lo,hi = _rescale(lo,hi,step,pt=event.xdata,scale=ax.get_xscale())
        ax.set_xlim((lo,hi))

        lo,hi = ax.get_ylim()
        lo,hi = _rescale(lo,hi,step,pt=event.ydata,scale=ax.get_yscale())
        ax.set_ylim((lo,hi))
    else:
        # Check if zoom happens in the axes
        xdata,ydata = None,None
        x,y = event.x,event.y
        for ax in event.canvas.figure.get_axes():
            if ax.xaxis.contains(event):
                xdata,_ = ax.transAxes.inverted().transform_point((x,y))
                #print "xaxis",x,"->",xdata
            if ax.yaxis.contains(event):
                _,ydata = ax.transAxes.inverted().transform_point((x,y))
                #print "yaxis",y,"->",ydata
        if xdata is not None:
            lo,hi = ax.get_xlim()
            lo,hi = _rescale(lo,hi,step,bal=xdata,scale=ax.get_xscale())
            ax.set_xlim((lo,hi))
        if ydata is not None:
            lo,hi = ax.get_ylim()
            lo,hi = _rescale(lo,hi,step,bal=ydata,scale=ax.get_yscale())
            ax.set_ylim((lo,hi))

    event.canvas.draw_idle()

def colorbar():
    cb = pylab.colorbar()
    canvas = pylab.gcf().canvas
    if not hasattr(canvas,'_colorbars'):
        canvas._colorbars = {}
    canvas._colorbars[cb.ax] = cb



pylab.gcf().canvas.mpl_connect('scroll_event',onWheel)
 
pylab.subplot(211)
pylab.imshow([[1,2,3],[2,1,3]])
colorbar()
pylab.subplot(212)
pylab.loglog([10,100,1000],[100,10,1000])
pylab.show()
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to