From: <dmk...@us...> - 2008-07-18 08:43:07
|
Revision: 5786 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5786&view=rev Author: dmkaplan Date: 2008-07-18 08:43:03 +0000 (Fri, 18 Jul 2008) Log Message: ----------- Making a number of changes related to "blocking" stuff: 1) Adding to cbook.py a method is_sequence_of_strings that is then used in BlockingInput to test for a tuple-like sequence of event names 2) Modified the use of *fmt* in clabel so that it an also be a dictionary matching contour levels to arbitrary strings. 3) Removing the extraneous np.array or np.asarray commands in ContourLabeler as they were forcing linecontour to array, but linecontour should already be an array. 4) In blocking_input.py replacing all print commands with calls to matplotlib.verbose.report 5) Removing extra cleanup call from BlockingInput as finally is always executed, regardless of exception status. 6) Removing what appears to be a "patch" command screwup - there were two versions of several of the Blocking* classes in blocking_input.py Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/blocking_input.py trunk/matplotlib/lib/matplotlib/cbook.py trunk/matplotlib/lib/matplotlib/contour.py trunk/matplotlib/lib/matplotlib/figure.py Modified: trunk/matplotlib/lib/matplotlib/blocking_input.py =================================================================== --- trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-17 21:06:17 UTC (rev 5785) +++ trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-18 08:43:03 UTC (rev 5786) @@ -19,7 +19,8 @@ import time import numpy as np -import matplotlib.path as path +from matplotlib import path, verbose +from cbook import is_sequence_of_strings class BlockingInput(object): """ @@ -28,7 +29,7 @@ """ def __init__(self, fig, eventslist=()): self.fig = fig - assert isinstance(eventslist, tuple), "Requires a tuple of event name strings" + assert is_sequence_of_strings(eventslist), "Requires a sequence of event name strings" self.eventslist = eventslist def on_event(self, event): @@ -41,8 +42,7 @@ # subclasses self.add_event(event) - if self.verbose: - print "Event %i" % len(self.events) + verbose.report("Event %i" % len(self.events)) # This will extract info from events self.post_event() @@ -80,7 +80,7 @@ self.pop_event(index) pop.__doc__=pop_event.__doc__ - def __call__(self, n=1, timeout=30, verbose=False ): + def __call__(self, n=1, timeout=30 ): """ Blocking call to retrieve n events """ @@ -90,7 +90,6 @@ self.events = [] self.done = False - self.verbose = verbose self.callbacks = [] # Ensure that the figure is shown @@ -112,12 +111,10 @@ if timeout > 0 and counter > timeout/0.01: print "Timeout reached"; break; - finally: # Activated on exception like ctrl-c + finally: # Run even on exception like ctrl-c + # Disconnect the callbacks self.cleanup() - # Disconnect the callbacks - self.cleanup() - # Return the events in this case return self.events @@ -196,10 +193,10 @@ This add the coordinates of an event to the list of clicks """ self.clicks.append((event.xdata,event.ydata)) - if self.verbose: - print "input %i: %f,%f" % (len(self.clicks), - event.xdata, event.ydata) + verbose.report("input %i: %f,%f" % + (len(self.clicks),event.xdata, event.ydata)) + # If desired plot up click if self.show_clicks: self.marks.extend( @@ -238,7 +235,7 @@ # Call base class to remove callbacks BlockingInput.cleanup(self) - def __call__(self, n=1, timeout=30, verbose=False, show_clicks=True): + def __call__(self, n=1, timeout=30, show_clicks=True): """ Blocking call to retrieve n coordinate pairs through mouse clicks. @@ -246,7 +243,7 @@ self.show_clicks = show_clicks self.clicks = [] self.marks = [] - BlockingInput.__call__(self,n=n,timeout=timeout,verbose=verbose) + BlockingInput.__call__(self,n=n,timeout=timeout) return self.clicks @@ -324,7 +321,7 @@ def __call__(self,inline,n=-1,timeout=-1): self.inline=inline - BlockingMouseInput.__call__(self,n=n,timeout=timeout,verbose=False, + BlockingMouseInput.__call__(self,n=n,timeout=timeout, show_clicks=False) class BlockingKeyMouseInput(BlockingInput): @@ -343,198 +340,13 @@ self.keyormouse = self.events[-1].name == 'key_press_event' - def __call__(self, timeout=30, verbose=False): + def __call__(self, timeout=30): """ Blocking call to retrieve a single mouse or key click Returns True if key click, False if mouse, or None if timeout """ self.keyormouse = None - BlockingInput.__call__(self,n=1,timeout=timeout,verbose=verbose) + BlockingInput.__call__(self,n=1,timeout=timeout) return self.keyormouse -""" -This provides several classes used for interaction with figure windows: - -:class:`BlockingInput` - creates a callable object to retrieve events in a blocking way for interactive sessions - -:class:`BlockingKeyMouseInput` - creates a callable object to retrieve key or mouse clicks in a blocking way for interactive sessions. - Note: Subclass of BlockingInput. Used by waitforbuttonpress - -:class:`BlockingMouseInput` - creates a callable object to retrieve mouse clicks in a blocking way for interactive sessions. - Note: Subclass of BlockingInput. Used by ginput -""" - -import time - -class BlockingInput(object): - """ - Class that creates a callable object to retrieve events in a - blocking way. - """ - def __init__(self, fig, eventslist=()): - self.fig = fig - assert isinstance(eventslist, tuple), \ - "Requires a tuple of event name strings" - self.eventslist = eventslist - - def on_event(self, event): - """ - Event handler that will be passed to the current figure to - retrieve events. - """ - self.events.append(event) - - if self.verbose: - print "Event %i" % len(self.events) - - # This will extract info from events - self.post_event() - - if len(self.events) >= self.n and self.n > 0: - self.done = True - - def post_event(self): - """For baseclass, do nothing but collect events""" - pass - - def cleanup(self): - """Remove callbacks""" - for cb in self.callbacks: - self.fig.canvas.mpl_disconnect(cb) - - self.callbacks=[] - - def __call__(self, n=1, timeout=30, verbose=False ): - """ - Blocking call to retrieve n events - """ - - assert isinstance(n, int), "Requires an integer argument" - self.n = n - - self.events = [] - self.done = False - self.verbose = verbose - self.callbacks = [] - - # Ensure that the figure is shown - self.fig.show() - - # connect the events to the on_event function call - for n in self.eventslist: - self.callbacks.append( self.fig.canvas.mpl_connect(n, self.on_event) ) - - try: - # wait for n clicks - counter = 0 - while not self.done: - self.fig.canvas.flush_events() - time.sleep(0.01) - - # check for a timeout - counter += 1 - if timeout > 0 and counter > timeout/0.01: - print "Timeout reached"; - break; - finally: # Activated on exception like ctrl-c - self.cleanup() - - # Disconnect the callbacks - self.cleanup() - - # Return the events in this case - return self.events - -class BlockingMouseInput(BlockingInput): - """ - Class that creates a callable object to retrieve mouse clicks in a - blocking way. - """ - def __init__(self, fig): - BlockingInput.__init__(self, fig=fig, eventslist=('button_press_event',) ) - - def post_event(self): - """ - This will be called to process events - """ - assert len(self.events)>0, "No events yet" - - event = self.events[-1] - - if event.button == 3: - # If it's a right click, pop the last coordinates. - if len(self.clicks) > 0: - self.clicks.pop() - del self.events[-2:] # Remove button=3 event and previous event - - if self.show_clicks: - mark = self.marks.pop() - mark.remove() - self.fig.canvas.draw() - elif event.button == 2 and self.n < 0: - # If it's a middle click, and we are in infinite mode, finish - self.done = True - elif event.inaxes: - # If it's a valid click, append the coordinates to the list - self.clicks.append((event.xdata, event.ydata)) - if self.verbose: - print "input %i: %f,%f" % (len(self.clicks), - event.xdata, event.ydata) - if self.show_clicks: - self.marks.extend( - event.inaxes.plot([event.xdata,], [event.ydata,], 'r+') ) - self.fig.canvas.draw() - - def cleanup(self): - # clean the figure - if self.show_clicks: - for mark in self.marks: - mark.remove() - self.marks = [] - self.fig.canvas.draw() - - # Call base class to remove callbacks - BlockingInput.cleanup(self) - - def __call__(self, n=1, timeout=30, verbose=False, show_clicks=True): - """ - Blocking call to retrieve n coordinate pairs through mouse - clicks. - """ - self.show_clicks = show_clicks - self.clicks = [] - self.marks = [] - BlockingInput.__call__(self,n=n,timeout=timeout,verbose=verbose) - - return self.clicks - -class BlockingKeyMouseInput(BlockingInput): - """ - Class that creates a callable object to retrieve a single mouse or - keyboard click - """ - def __init__(self, fig): - BlockingInput.__init__(self, fig=fig, eventslist=('button_press_event','key_press_event') ) - - def post_event(self): - """ - Determines if it is a key event - """ - assert len(self.events)>0, "No events yet" - - self.keyormouse = self.events[-1].name == 'key_press_event' - - def __call__(self, timeout=30, verbose=False): - """ - Blocking call to retrieve a single mouse or key click - Returns True if key click, False if mouse, or None if timeout - """ - self.keyormouse = None - BlockingInput.__call__(self,n=1,timeout=timeout,verbose=verbose) - - return self.keyormouse - Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2008-07-17 21:06:17 UTC (rev 5785) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2008-07-18 08:43:03 UTC (rev 5786) @@ -270,6 +270,15 @@ except (TypeError, ValueError): return 0 return 1 +def is_sequence_of_strings(obj): + """ + Returns true if *obj* is iterable and contains strings + """ + if not iterable(obj): return False + for o in obj: + if not is_string_like(o): return False + return True + def is_writable_file_like(obj): 'return true if *obj* looks like a file object with a *write* method' return hasattr(obj, 'write') and callable(obj.write) Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2008-07-17 21:06:17 UTC (rev 5785) +++ trunk/matplotlib/lib/matplotlib/contour.py 2008-07-18 08:43:03 UTC (rev 5786) @@ -71,6 +71,9 @@ *fmt*: a format string for the label. Default is '%1.3f' + Alternatively, this can be a dictionary matching contour + levels with arbitrary strings to use for each contour level + (i.e., fmt[level]=string) *manual*: if *True*, contour labels will be placed manually using @@ -158,10 +161,10 @@ if lcsize > 10 * labelwidth: return 1 - xmax = np.amax(np.array(linecontour)[:,0]) - xmin = np.amin(np.array(linecontour)[:,0]) - ymax = np.amax(np.array(linecontour)[:,1]) - ymin = np.amin(np.array(linecontour)[:,1]) + xmax = np.amax(linecontour[:,0]) + xmin = np.amin(linecontour[:,0]) + ymax = np.amax(linecontour[:,1]) + ymin = np.amin(linecontour[:,1]) lw = labelwidth if (xmax - xmin) > 1.2* lw or (ymax - ymin) > 1.2 * lw: @@ -210,7 +213,7 @@ if cbook.is_string_like(lev): lw = (len(lev)) * fsize else: - lw = (len(fmt%lev)) * fsize + lw = (len(self.get_text(lev,fmt))) * fsize return lw @@ -227,9 +230,11 @@ if cbook.is_string_like(lev): return lev else: - return fmt%lev + if isinstance(fmt,dict): + return fmt[lev] + else: + return fmt%lev - def break_linecontour(self, linecontour, rot, labelwidth, ind): "break a contour in two contours at the location of the label" lcsize = len(linecontour) @@ -243,8 +248,8 @@ slc = trans.transform(linecontour) x,y = slc[ind] - xx= np.asarray(slc)[:,0].copy() - yy=np.asarray(slc)[:,1].copy() + xx=slc[:,0].copy() + yy=slc[:,1].copy() #indices which are under the label inds, = np.nonzero(((xx < x+xlabel) & (xx > x-xlabel)) & @@ -325,8 +330,8 @@ else: ysize = labelwidth - XX = np.resize(np.asarray(linecontour)[:,0],(xsize, ysize)) - YY = np.resize(np.asarray(linecontour)[:,1],(xsize, ysize)) + XX = np.resize(linecontour[:,0],(xsize, ysize)) + YY = np.resize(linecontour[:,1],(xsize, ysize)) #I might have fouled up the following: yfirst = YY[:,0].reshape(xsize, 1) ylast = YY[:,-1].reshape(xsize, 1) Modified: trunk/matplotlib/lib/matplotlib/figure.py =================================================================== --- trunk/matplotlib/lib/matplotlib/figure.py 2008-07-17 21:06:17 UTC (rev 5785) +++ trunk/matplotlib/lib/matplotlib/figure.py 2008-07-18 08:43:03 UTC (rev 5786) @@ -1017,11 +1017,11 @@ ax.update_params() ax.set_position(ax.figbox) - def ginput(self, n=1, timeout=30, verbose=False, show_clicks=True): + def ginput(self, n=1, timeout=30, show_clicks=True): """ call signature:: - ginput(self, n=1, timeout=30, verbose=False, show_clicks=True) + ginput(self, n=1, timeout=30, show_clicks=True) Blocking call to interact with the figure. @@ -1038,7 +1038,7 @@ blocking_mouse_input = BlockingMouseInput(self) return blocking_mouse_input(n=n, timeout=timeout, - verbose=verbose, show_clicks=show_clicks) + show_clicks=show_clicks) def waitforbuttonpress(self, timeout=-1): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |