From: John H. <jdh...@ac...> - 2004-12-01 04:30:50
|
>>>>> "seberino" == seberino <seb...@sp...> writes: seberino> I noticed when I pass the mouse pointer over a point on seberino> a graph that the (X, Y) values are displayed. This is seberino> *great*. Glad you like it. Fernando Perez pushed me into getting this implemented by repeatedly glowing about how nice this was in gnuplot ... No better way to get me to implement a feature than favorably compare gnuplot to matplotlib :-) seberino> What if I wanted to customize/extend what gets printed seberino> in response to mouse pointer position? Is this seberino> possible? Yes, you can use the fmt_xdata and fmt_ydata attributes of the axes instance to set a custom function. If these are not set, matplotlib will fall back on the default tick formatter -- these are explained at http://matplotlib.sf.net/matplotlib.ticker.html . See examples/date_demo1.py for an example of setting your own coordinate formatter functions with fmt_xdata and fmt_ydata. The basic usage is def price(x): return '$%1.2f'%x ax.fmt_xdata = DateFormatter('%Y-%m-%d') ax.fmt_ydata = price Here fmt_xdata is set to a callable instance (a DateFormatter instance) and fmt_ydata is a plain old function that takes y as a value and returns a string. seberino> e.g. If you had say 5 graphs on one plot, could you seberino> display all "Y values" for every X value?? seberino> (X, Y1, Y2, Y3, Y4, Y5)?? This is a harder problem. You need to capture the mouse location (see examples/coords_demo.py) to get the x location and use this information in your y formatter function . Basically, you want to ignore the actual value passed to your y format function and use the y values of your time series at a given x index which you capture with a mouse move event. In the example below I use a class to store the x location and communicate between the mouse position and the y format function. The variable self.ind is the index into the x, y1 and y2 vectors that is closest to the mouse x position. The example assumes your xdata are monotonic, though you could do it for non-monotonic x with minor modifications. Note in principle the example below should work on all matplotlib backends and os platforms. In practice, with a little testing, I found that this example reveals some bugs in matplotlib event handling which we are looking into. So for now, it appears to only work properly on the GTK* backends (sigh), though it doesn't use any gtk specific code. from matplotlib.matlab import * class MyFormatter: def __init__(self, x, y1, y2): self.x = x self.y1 = y1 self.y2 = y2 self.ind = None def on_move(self, event): 'save the last x coord and get the index' if event.inaxes: # get the index into x closest to self.ind = searchsorted(self.x, event.xdata) else: self.ind = None def fmty(self, y): 'ignore y and format the value of y1 and y2 at ind' if self.ind is None: return '' thisy1 = self.y1[self.ind] thisy2 = self.y2[self.ind] return '%1.2f, %1.2f'%(thisy1, thisy2) t = arange(0, 2.0, 0.01) s1 = sin(2*pi*t) s2 = 2*sin(3*pi*t) plot(t, s1, t, s2) canvas = get_current_fig_manager().canvas ax = gca() o = MyFormatter(t, s1, s2) canvas.mpl_connect('motion_notify_event', o.on_move) ax.fmt_ydata = o.fmty show() |