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. |
From: <ry...@us...> - 2008-07-20 02:59:07
|
Revision: 5794 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5794&view=rev Author: ryanmay Date: 2008-07-20 02:59:00 +0000 (Sun, 20 Jul 2008) Log Message: ----------- Move delete_masked_points() from axes.py to cbook.py so that it's available to more places. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/cbook.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-07-20 00:57:41 UTC (rev 5793) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-07-20 02:59:00 UTC (rev 5794) @@ -1,5 +1,5 @@ from __future__ import division, generators -import math, sys, warnings, datetime, new, types +import math, sys, warnings, datetime, new import numpy as np from numpy import ma @@ -31,45 +31,6 @@ is_string_like = cbook.is_string_like -def delete_masked_points(*args): - """ - Find all masked points in a set of arguments, and return - the arguments with only the unmasked points remaining. - - This will also delete any points that are not finite (nan or inf). - - The overall mask is calculated from any masks that are present. - If a mask is found, any argument that does not have the same - dimensions is left unchanged; therefore the argument list may - include arguments that can take string or array values, for - example. - - Array arguments must have the same length; masked arguments must - be one-dimensional. - - Written as a helper for scatter, but may be more generally - useful. - """ - masks = [ma.getmaskarray(x) for x in args if hasattr(x, 'mask')] - isfinite = [np.isfinite(x) for x in args] - masks.extend( [~x for x in isfinite if not isinstance(x,types.NotImplementedType)] ) - if len(masks) == 0: - return args - mask = reduce(np.logical_or, masks) - margs = [] - for x in args: - if (not is_string_like(x) - and iterable(x) - and len(x) == len(mask)): - if (hasattr(x, 'get_compressed_copy')): - compressed_x = x.get_compressed_copy(mask) - else: - compressed_x = ma.masked_array(x, mask=mask).compressed() - margs.append(compressed_x) - else: - margs.append(x) - return margs - def _process_plot_format(fmt): """ Process a matlab(TM) style color/line style format string. Return a @@ -4827,7 +4788,7 @@ self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) - x, y, s, c = delete_masked_points(x, y, s, c) + x, y, s, c = cbook.delete_masked_points(x, y, s, c) # The inherent ambiguity is resolved in favor of color # mapping, not interpretation as rgb or rgba. @@ -5091,7 +5052,7 @@ self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) - x, y = delete_masked_points(x, y) + x, y = cbook.delete_masked_points(x, y) # Set the size of the hexagon grid if iterable(gridsize): Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2008-07-20 00:57:41 UTC (rev 5793) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2008-07-20 02:59:00 UTC (rev 5794) @@ -3,9 +3,10 @@ from the Python Cookbook -- hence the name cbook """ from __future__ import generators -import re, os, errno, sys, StringIO, traceback, locale, threading +import re, os, errno, sys, StringIO, traceback, locale, threading, types import time, datetime import numpy as np +from numpy import ma from weakref import ref major, minor1, minor2, s, tmp = sys.version_info @@ -1165,8 +1166,46 @@ else: os.remove(path) +def delete_masked_points(*args): + """ + Find all masked points in a set of arguments, and return + the arguments with only the unmasked points remaining. + This will also delete any points that are not finite (nan or inf). + The overall mask is calculated from any masks that are present. + If a mask is found, any argument that does not have the same + dimensions is left unchanged; therefore the argument list may + include arguments that can take string or array values, for + example. + + Array arguments must have the same length; masked arguments must + be one-dimensional. + + Written as a helper for scatter, but may be more generally + useful. + """ + masks = [ma.getmaskarray(x) for x in args if hasattr(x, 'mask')] + isfinite = [np.isfinite(x) for x in args] + masks.extend( [~x for x in isfinite if not isinstance(x,types.NotImplementedType)] ) + if len(masks) == 0: + return args + mask = reduce(np.logical_or, masks) + margs = [] + for x in args: + if (not is_string_like(x) + and iterable(x) + and len(x) == len(mask)): + if (hasattr(x, 'get_compressed_copy')): + compressed_x = x.get_compressed_copy(mask) + else: + compressed_x = ma.masked_array(x, mask=mask).compressed() + margs.append(compressed_x) + else: + margs.append(x) + return margs + + # a dict to cross-map linestyle arguments _linestyles = [('-', 'solid'), ('--', 'dashed'), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <js...@us...> - 2008-07-23 00:24:58
|
Revision: 5814 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5814&view=rev Author: jswhit Date: 2008-07-23 00:24:55 +0000 (Wed, 23 Jul 2008) Log Message: ----------- add griddata to pylab, add griddata docstrings to mlab and pylab module docstrings. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/mlab.py trunk/matplotlib/lib/matplotlib/pylab.py Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-07-22 19:47:04 UTC (rev 5813) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-07-23 00:24:55 UTC (rev 5814) @@ -14,6 +14,8 @@ * find - Return the indices where some condition is true; numpy.nonzero is similar but more general. + * griddata - interpolate irregularly distributed data to a + regular grid. * prctile - find the percentiles of a sequence @@ -90,12 +92,6 @@ import matplotlib.nxutils as nxutils import matplotlib.cbook as cbook -try: - from mpl_toolkits.natgrid import _natgrid - _use_natgrid = True -except ImportError: - import matplotlib.delaunay as delaunay - _use_natgrid = False # set is a new builtin function in 2.4; delete the following when # support for 2.3 is dropped. @@ -2720,6 +2716,12 @@ this function will use the mpl_toolkits.natgrid algorithm, otherwise it will use the built-in matplotlib.delaunay package. """ + try: + from mpl_toolkits.natgrid import _natgrid + _use_natgrid = True + except ImportError: + import matplotlib.delaunay as delaunay + _use_natgrid = False if xi.ndim != yi.ndim: raise TypeError("inputs xi and yi must have same number of dimensions (1 or 2)") if xi.ndim != 1 and xi.ndim != 2: Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2008-07-22 19:47:04 UTC (rev 5813) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2008-07-23 00:24:55 UTC (rev 5814) @@ -184,6 +184,7 @@ _Other angle - the angle of a complex array + griddata - interpolate irregularly distributed data to a regular grid load - load ASCII data into array polyfit - fit x, y to an n-th order polynomial polyval - evaluate an n-th order polynomial @@ -219,7 +220,7 @@ from matplotlib.mlab import window_hanning, window_none,\ conv, detrend, detrend_mean, detrend_none, detrend_linear,\ - polyfit, polyval, entropy, normpdf,\ + polyfit, polyval, entropy, normpdf, griddata,\ levypdf, find, trapz, prepca, fix, rem, norm, orth, rank,\ sqrtm, prctile, center_matrix, rk4, exp_safe, amap,\ sum_flat, mean_flat, rms_flat, l1norm, l2norm, norm, frange,\ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <js...@us...> - 2008-07-23 01:15:24
|
Revision: 5815 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5815&view=rev Author: jswhit Date: 2008-07-23 01:15:22 +0000 (Wed, 23 Jul 2008) Log Message: ----------- implement some of JDH's suggestions for griddata. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/delaunay/__init__.py trunk/matplotlib/lib/matplotlib/mlab.py Modified: trunk/matplotlib/lib/matplotlib/delaunay/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/delaunay/__init__.py 2008-07-23 00:24:55 UTC (rev 5814) +++ trunk/matplotlib/lib/matplotlib/delaunay/__init__.py 2008-07-23 01:15:22 UTC (rev 5815) @@ -8,3 +8,4 @@ from matplotlib._delaunay import delaunay from triangulate import * from interpolate import * +__version__ = "0.1" Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-07-23 00:24:55 UTC (rev 5814) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-07-23 01:15:22 UTC (rev 5815) @@ -89,6 +89,7 @@ import numpy as np +from matplotlib import verbose import matplotlib.nxutils as nxutils import matplotlib.cbook as cbook @@ -2715,13 +2716,23 @@ that is not redistributable under a BSD-compatible license. When installed, this function will use the mpl_toolkits.natgrid algorithm, otherwise it will use the built-in matplotlib.delaunay package. + + The natgrid matplotlib toolkit can be checked out through SVN with the + following command: + + svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk/toolkits/natgrid natgrid """ try: - from mpl_toolkits.natgrid import _natgrid + from mpl_toolkits.natgrid import _natgrid, __version__ _use_natgrid = True except ImportError: import matplotlib.delaunay as delaunay + from matplotlib.delaunay import __version__ _use_natgrid = False + if _use_natgrid: + verbose.report('using natgrid version %s' % __version__) + else: + verbose.report('using delaunay version %s' % __version__) if xi.ndim != yi.ndim: raise TypeError("inputs xi and yi must have same number of dimensions (1 or 2)") if xi.ndim != 1 and xi.ndim != 2: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dmk...@us...> - 2008-07-24 10:02:20
|
Revision: 5831 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5831&view=rev Author: dmkaplan Date: 2008-07-24 10:02:13 +0000 (Thu, 24 Jul 2008) Log Message: ----------- Moving "event loop" stuff from blocking_input.py to backends. For backends without a GUI, the default is to throw a NotImplemented error. For backends with a GUI, I have implemented a "start/stop_event_loop_default" that does the default event loop using time.sleep. For WX, I have used the code supplied by Paul Kienzle, but I have been unable to check it because that backend currently doesn't work for me. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py trunk/matplotlib/lib/matplotlib/backends/backend_qt.py trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py trunk/matplotlib/lib/matplotlib/backends/backend_wx.py trunk/matplotlib/lib/matplotlib/blocking_input.py Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -23,7 +23,7 @@ """ from __future__ import division -import os, warnings +import os, warnings, time import numpy as np import matplotlib.cbook as cbook @@ -1391,7 +1391,76 @@ """ raise NotImplementedError + def start_event_loop(self,*args,**kwargs): + """ + Start an event loop. This is used to start a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. This should not be + confused with the main GUI event loop, which is always running + and has nothing to do with this. + This is implemented only for backends with GUIs. + """ + raise NotImplementedError + + def stop_event_loop(self,*args,**kwargs): + """ + Stop an event loop. This is used to stop a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. + + This is implemented only for backends with GUIs. + """ + raise NotImplementedError + + def start_event_loop_default(self,timeout=0): + """ + Start an event loop. This is used to start a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. This should not be + confused with the main GUI event loop, which is always running + and has nothing to do with this. + + This function provides default event loop functionality based + on time.sleep that is meant to be used until event loop + functions for each of the GUI backends can be written. As + such, it throws a deprecated warning. + + Call signature:: + + start_event_loop_default(self,timeout=0) + + This call blocks until a callback function triggers + stop_event_loop() or *timeout* is reached. If *timeout* is + <=0, never timeout. + """ + str = "Using default event loop until function specific" + str += " to this GUI is implemented" + warnings.warn(str,DeprecationWarning) + + if timeout <= 0: timeout = np.inf + timestep = 0.01 + counter = 0 + self._looping = True + while self._looping and counter*timestep < timeout: + self.flush_events() + time.sleep(timestep) + counter += 1 + + def stop_event_loop_default(self): + """ + Stop an event loop. This is used to stop a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. + + Call signature:: + + stop_event_loop_default(self) + """ + self._looping = False + + + class FigureManagerBase: """ Helper class for matlab mode, wraps everything up into a neat bundle Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -58,6 +58,16 @@ def blit(self, bbox): pass + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + + + NibClassBuilder.extractClasses('Matplotlib.nib', mplBundle) class MatplotlibController(NibClassBuilder.AutoBaseClass): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -247,6 +247,14 @@ def widget(self): return self.canvas + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + def destroy_figure(ptr,figman): figman.window.hide() Gcf.destroy(figman._num) @@ -491,7 +499,7 @@ default_filetype = base.canvas.get_default_filetype() sorted_filetypes = filetypes.items() sorted_filetypes.sort() - + selected_filter = 0 filters = [] for i, (ext, name) in enumerate(sorted_filetypes): @@ -518,7 +526,7 @@ lastDir = os.path.dirname(fname) file_chooser.directory(lastDir) format = sorted_filetypes[file_chooser.filter_value()][0] - + try: base.canvas.print_figure(fname, format=format) except IOError, msg: Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -396,7 +396,14 @@ gtk.gdk.flush() gtk.gdk.threads_leave() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerGTK(FigureManagerBase): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -177,6 +177,14 @@ def flush_events(self): qt.qApp.processEvents() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerQT( FigureManagerBase ): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -181,6 +181,14 @@ def flush_events(self): Qt.qApp.processEvents() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerQT( FigureManagerBase ): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -287,6 +287,14 @@ def flush_events(self): self._master.update() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerTkAgg(FigureManagerBase): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -1185,7 +1185,57 @@ if figManager is not None: figManager.canvas.draw() + def start_event_loop(self, timeout=0): + """ + Start an event loop. This is used to start a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. This should not be + confused with the main GUI event loop, which is always running + and has nothing to do with this. + Call signature:: + + start_event_loop(self,timeout=0) + + This call blocks until a callback function triggers + stop_event_loop() or *timeout* is reached. If *timeout* is + <=0, never timeout. + """ + root = self.GetTopLevelParent() + bind(root, wx.EVT_CLOSE, self.stop_event_loop) + + id = wx.NewId() + timer = wx.Timer(self, id=id) + if timeout > 0: + timer.Start(timeout*1000, oneShot=True) + bind(self, wx.EVT_TIMER, self.stop_event_loop, id=id) + self._event_loop.Run() + timer.Stop() + + def stop_event_loop(self, event=None): + """ + Stop an event loop. This is used to stop a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. + + Call signature:: + + stop_event_loop_default(self) + """ + if self._event_loop.IsRunning(): + self._event_loop.Exit() + +# Event binding code changed after version 2.5 +if wx.VERSION_STRING >= '2.5': + def bind(actor,event,action,**kw): + actor.Bind(event,action,**kw) +else: + def bind(actor,event,action,id=None): + if id is not None: + event(actor, id, action) + else: + event(actor,action) + def show(): """ Current implementation assumes that matplotlib is executed in a PyCrust Modified: trunk/matplotlib/lib/matplotlib/blocking_input.py =================================================================== --- trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -50,7 +50,7 @@ # Check if we have enough events already if len(self.events) >= self.n and self.n > 0: - self.done = True + self.fig.canvas.stop_event_loop() def post_event(self): """For baseclass, do nothing but collect events""" @@ -90,7 +90,6 @@ self.n = n self.events = [] - self.done = False self.callbacks = [] # Ensure that the figure is shown @@ -101,17 +100,8 @@ 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; + # Start event loop + self.fig.canvas.start_event_loop(timeout=timeout) finally: # Run even on exception like ctrl-c # Disconnect the callbacks self.cleanup() @@ -175,7 +165,7 @@ # consistent with matlab and sometimes quite useful, but will # require the user to test how many points were actually # returned before using data. - self.done = True + self.fig.canvas.stop_event_loop() def button3( self, event ): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-07-24 13:39:38
|
Revision: 5837 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5837&view=rev Author: jdh2358 Date: 2008-07-24 13:39:34 +0000 (Thu, 24 Jul 2008) Log Message: ----------- removed mlab fix from pylab -- previously deprecated Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/__init__.py trunk/matplotlib/lib/matplotlib/pylab.py Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2008-07-24 13:30:53 UTC (rev 5836) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2008-07-24 13:39:34 UTC (rev 5837) @@ -89,7 +89,7 @@ """ from __future__ import generators -__version__ = '0.98.3' +__version__ = '0.98.3rc1' __revision__ = '$Revision$' __date__ = '$Date$' Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2008-07-24 13:30:53 UTC (rev 5836) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2008-07-24 13:39:34 UTC (rev 5837) @@ -221,7 +221,7 @@ from matplotlib.mlab import window_hanning, window_none,\ conv, detrend, detrend_mean, detrend_none, detrend_linear,\ polyfit, polyval, entropy, normpdf, griddata,\ - levypdf, find, trapz, prepca, fix, rem, norm, orth, rank,\ + levypdf, find, trapz, prepca, rem, norm, orth, rank,\ sqrtm, prctile, center_matrix, rk4, exp_safe, amap,\ sum_flat, mean_flat, rms_flat, l1norm, l2norm, norm, frange,\ diagonal_matrix, base_repr, binary_repr, log2, ispower2,\ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dmk...@us...> - 2008-07-24 14:22:23
|
Revision: 5838 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5838&view=rev Author: dmkaplan Date: 2008-07-24 14:22:20 +0000 (Thu, 24 Jul 2008) Log Message: ----------- Minor changes in response to comments by John Hunter on empty lists in python args and avoiding unspecified argument lists. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py trunk/matplotlib/lib/matplotlib/backends/backend_qt.py trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py trunk/matplotlib/lib/matplotlib/blocking_input.py trunk/matplotlib/lib/matplotlib/contour.py Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -1391,7 +1391,7 @@ """ raise NotImplementedError - def start_event_loop(self,*args,**kwargs): + def start_event_loop(self,timeout): """ Start an event loop. This is used to start a blocking event loop so that interactive functions, such as ginput and @@ -1403,7 +1403,7 @@ """ raise NotImplementedError - def stop_event_loop(self,*args,**kwargs): + def stop_event_loop(self): """ Stop an event loop. This is used to stop a blocking event loop so that interactive functions, such as ginput and Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -58,12 +58,12 @@ def blit(self, bbox): pass - def start_event_loop(self,*args,**kwargs): - FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + def start_event_loop(self,timeout): + FigureCanvasBase.start_event_loop_default(self,timeout) start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ - def stop_event_loop(self,*args,**kwargs): - FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + def stop_event_loop(self): + FigureCanvasBase.stop_event_loop_default(self) stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ Modified: trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -247,12 +247,12 @@ def widget(self): return self.canvas - def start_event_loop(self,*args,**kwargs): - FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + def start_event_loop(self,timeout): + FigureCanvasBase.start_event_loop_default(self,timeout) start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ - def stop_event_loop(self,*args,**kwargs): - FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + def stop_event_loop(self): + FigureCanvasBase.stop_event_loop_default(self) stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ def destroy_figure(ptr,figman): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -396,12 +396,12 @@ gtk.gdk.flush() gtk.gdk.threads_leave() - def start_event_loop(self,*args,**kwargs): - FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + def start_event_loop(self,timeout): + FigureCanvasBase.start_event_loop_default(self,timeout) start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ - def stop_event_loop(self,*args,**kwargs): - FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + def stop_event_loop(self): + FigureCanvasBase.stop_event_loop_default(self) stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ class FigureManagerGTK(FigureManagerBase): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -177,12 +177,12 @@ def flush_events(self): qt.qApp.processEvents() - def start_event_loop(self,*args,**kwargs): - FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + def start_event_loop(self,timeout): + FigureCanvasBase.start_event_loop_default(self,timeout) start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ - def stop_event_loop(self,*args,**kwargs): - FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + def stop_event_loop(self): + FigureCanvasBase.stop_event_loop_default(self) stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ class FigureManagerQT( FigureManagerBase ): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -181,12 +181,12 @@ def flush_events(self): Qt.qApp.processEvents() - def start_event_loop(self,*args,**kwargs): - FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + def start_event_loop(self,timeout): + FigureCanvasBase.start_event_loop_default(self,timeout) start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ - def stop_event_loop(self,*args,**kwargs): - FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + def stop_event_loop(self): + FigureCanvasBase.stop_event_loop_default(self) stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ class FigureManagerQT( FigureManagerBase ): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -287,12 +287,12 @@ def flush_events(self): self._master.update() - def start_event_loop(self,*args,**kwargs): - FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + def start_event_loop(self,timeout): + FigureCanvasBase.start_event_loop_default(self,timeout) start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ - def stop_event_loop(self,*args,**kwargs): - FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + def stop_event_loop(self): + FigureCanvasBase.stop_event_loop_default(self) stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ class FigureManagerTkAgg(FigureManagerBase): Modified: trunk/matplotlib/lib/matplotlib/blocking_input.py =================================================================== --- trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -283,13 +283,11 @@ """ # Figure out label rotation. if self.inline: lcarg = lc - else: lcarg = [] + else: lcarg = None rotation,nlc = cs.calc_label_rot_and_inline( slc, imin, lw, lcarg, self.inline_spacing ) - - cs.add_label(xmin,ymin,rotation,cs.labelLevelList[lmin], cs.labelCValueList[lmin]) Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2008-07-24 13:39:34 UTC (rev 5837) +++ trunk/matplotlib/lib/matplotlib/contour.py 2008-07-24 14:22:20 UTC (rev 5838) @@ -485,7 +485,7 @@ x,y,ind = self.locate_label(slc, lw) if inline: lcarg = lc - else: lcarg = [] + else: lcarg = None rotation,new=self.calc_label_rot_and_inline( slc0, ind, lw, lcarg, inline_spacing ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-07-25 17:38:08
|
Revision: 5875 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5875&view=rev Author: jdh2358 Date: 2008-07-25 17:38:06 +0000 (Fri, 25 Jul 2008) Log Message: ----------- cleaned up a few rest doc warnings Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/cbook.py trunk/matplotlib/lib/matplotlib/figure.py Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2008-07-25 15:09:08 UTC (rev 5874) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2008-07-25 17:38:06 UTC (rev 5875) @@ -1167,10 +1167,6 @@ This is very inefficient linear interpolation meant to be used only for a small number of points in relatively non-intensive use cases. - - Call signature:: - - yi = less_simple_linear_interpolation(x,y,xi) """ if is_scalar(xi): xi = [xi] @@ -1348,21 +1344,15 @@ If you just want to see if the array has 1 axis, use X.ndim==1 - Call signature:: - isvector(X) """ return np.prod(X.shape)==np.max(X.shape) def vector_lengths( X, P=2., axis=None ): """ Finds the length of a set of vectors in n dimensions. This is - like the mlab.norm function for vectors, but has the ability to + like the numpy norm function for vectors, but has the ability to work over a particular axis of the supplied array or matrix. - Call signature:: - - vector_lengths( X, P=2., axis=None ) - Computes (sum((x_i)^P))^(1/P) for each {x_i} being the elements of X along the given axis. If *axis* is *None*, compute over all elements of X. """ @@ -1373,10 +1363,6 @@ """ Computes the distance between a set of successive points in N dimensions. - Call signature:: - - distances_along_curve(X) - where X is an MxN array or matrix. The distances between successive rows is computed. Distance is the standard Euclidean distance. """ @@ -1387,10 +1373,7 @@ """ Computes the distance travelled along a polygonal curve in N dimensions. - Call signature:: - path_length(X) - where X is an MxN array or matrix. Returns an array of length M consisting of the distance along the curve at each point (i.e., the rows of X). """ @@ -1403,9 +1386,6 @@ presumably coordinates on a polygonal curve, in which case this function tests if that curve is closed. - Call signature:: - - is_closed_polygon(X) """ return np.all(X[0] == X[-1]) Modified: trunk/matplotlib/lib/matplotlib/figure.py =================================================================== --- trunk/matplotlib/lib/matplotlib/figure.py 2008-07-25 15:09:08 UTC (rev 5874) +++ trunk/matplotlib/lib/matplotlib/figure.py 2008-07-25 17:38:06 UTC (rev 5875) @@ -846,9 +846,9 @@ def text(self, x, y, s, *args, **kwargs): """ - Call signature: + Call signature:: - figtext(x, y, s, fontdict=None, **kwargs) + figtext(x, y, s, fontdict=None, **kwargs) Add text to figure at location *x*, *y* (relative 0-1 coords). See :func:`~matplotlib.pyplot.text` for the meaning This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pki...@us...> - 2008-07-25 23:22:28
|
Revision: 5878 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5878&view=rev Author: pkienzle Date: 2008-07-25 23:22:26 +0000 (Fri, 25 Jul 2008) Log Message: ----------- Fix contains() for text and lines Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/lines.py trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-07-25 21:32:06 UTC (rev 5877) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-07-25 23:22:26 UTC (rev 5878) @@ -2350,8 +2350,7 @@ """ if callable(self._contains): return self._contains(self,mouseevent) - inside = self.patch.contains(mouseevent.x, mouseevent.y) - return inside,{} + return self.patch.contains(mouseevent) def pick(self, *args): """ Modified: trunk/matplotlib/lib/matplotlib/lines.py =================================================================== --- trunk/matplotlib/lib/matplotlib/lines.py 2008-07-25 21:32:06 UTC (rev 5877) +++ trunk/matplotlib/lib/matplotlib/lines.py 2008-07-25 23:22:26 UTC (rev 5878) @@ -236,10 +236,11 @@ if not is_numlike(self.pickradius): raise ValueError,"pick radius should be a distance" - # transform in backend + if self._invalid: + self.recache() if len(self._xy)==0: return False,{} - - xyt = self._transformed_path.get_fully_transformed_path().vertices + tpath, _ = self._transformed_path.get_transformed_path_and_affine() + xyt = tpath.vertices xt = xyt[:, 0] yt = xyt[:, 1] Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2008-07-25 21:32:06 UTC (rev 5877) +++ trunk/matplotlib/lib/matplotlib/text.py 2008-07-25 23:22:26 UTC (rev 5878) @@ -135,6 +135,8 @@ """ if callable(self._contains): return self._contains(self,mouseevent) + if not self.get_visible() or self._renderer is None: + return False,{} l,b,w,h = self.get_window_extent().bounds This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pki...@us...> - 2008-07-26 00:01:20
|
Revision: 5882 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5882&view=rev Author: pkienzle Date: 2008-07-26 00:01:18 +0000 (Sat, 26 Jul 2008) Log Message: ----------- Fix contains() for lines; don't redraw axis frame Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/lines.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-07-25 23:54:37 UTC (rev 5881) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-07-26 00:01:18 UTC (rev 5882) @@ -1503,8 +1503,6 @@ artists.extend(self.tables) if self.legend_ is not None: artists.append(self.legend_) - if self.axison and self._frameon: - artists.append(self.frame) dsu = [ (a.zorder, i, a) for i, a in enumerate(artists) if not a.get_animated() ] Modified: trunk/matplotlib/lib/matplotlib/lines.py =================================================================== --- trunk/matplotlib/lib/matplotlib/lines.py 2008-07-25 23:54:37 UTC (rev 5881) +++ trunk/matplotlib/lib/matplotlib/lines.py 2008-07-26 00:01:18 UTC (rev 5882) @@ -239,7 +239,7 @@ if self._invalid: self.recache() if len(self._xy)==0: return False,{} - tpath, _ = self._transformed_path.get_transformed_path_and_affine() + tpath = self._transformed_path.get_fully_transformed_path() xyt = tpath.vertices xt = xyt[:, 0] yt = xyt[:, 1] @@ -250,7 +250,7 @@ else: pixels = self.figure.dpi/72. * self.pickradius - if self._linestyle == 'None': + if self._linestyle in ['None',None]: # If no line, return the nearby point(s) d = np.sqrt((xt-mouseevent.x)**2 + (yt-mouseevent.y)**2) ind, = np.nonzero(np.less_equal(d, pixels)) @@ -258,10 +258,11 @@ # If line, return the nearby segment(s) ind = segment_hits(mouseevent.x,mouseevent.y,xt,yt,pixels) if 0: + print 'linestyle',self._linestyle print 'xt', xt, mouseevent.x print 'yt', yt, mouseevent.y - print 'd', (xt-mouseevent.x)**2., (yt-mouseevent.y)**2. - print d, pixels, ind + print 'dx,dy', (xt-mouseevent.x)**2., (yt-mouseevent.y)**2. + print 'ind',ind return len(ind)>0,dict(ind=ind) def get_pickradius(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2008-07-26 04:50:59
|
Revision: 5885 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5885&view=rev Author: ryanmay Date: 2008-07-26 04:50:56 +0000 (Sat, 26 Jul 2008) Log Message: ----------- Change to try to import md5 from hashlib, and fall back to md5. Change the uses of md5 to work with either. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/lib/matplotlib/backends/backend_svg.py trunk/matplotlib/lib/matplotlib/finance.py trunk/matplotlib/lib/matplotlib/texmanager.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2008-07-26 00:34:02 UTC (rev 5884) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2008-07-26 04:50:56 UTC (rev 5885) @@ -3,9 +3,14 @@ """ from __future__ import division -import glob, math, md5, os, shutil, sys, time +import glob, math, os, shutil, sys, time def _fn_name(): return sys._getframe(1).f_code.co_name +try: + from hashlib import md5 +except ImportError: + from md5 import md5 #Deprecated in 2.5 + from tempfile import gettempdir from cStringIO import StringIO from matplotlib import verbose, __version__, rcParams @@ -892,10 +897,10 @@ passed_in_file_object = False if is_string_like(outfile): title = outfile - tmpfile = os.path.join(gettempdir(), md5.md5(outfile).hexdigest()) + tmpfile = os.path.join(gettempdir(), md5(outfile).hexdigest()) elif is_writable_file_like(outfile): title = None - tmpfile = os.path.join(gettempdir(), md5.md5(str(hash(outfile))).hexdigest()) + tmpfile = os.path.join(gettempdir(), md5(str(hash(outfile))).hexdigest()) passed_in_file_object = True else: raise ValueError("outfile must be a path or a file-like object") @@ -1033,7 +1038,7 @@ title = outfile # write to a temp file, we'll move it to outfile when done - tmpfile = os.path.join(gettempdir(), md5.md5(outfile).hexdigest()) + tmpfile = os.path.join(gettempdir(), md5(outfile).hexdigest()) fh = file(tmpfile, 'w') self.figure.dpi = 72 # ignore the dpi kwarg Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008-07-26 00:34:02 UTC (rev 5884) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008-07-26 04:50:56 UTC (rev 5885) @@ -1,7 +1,12 @@ from __future__ import division -import os, codecs, base64, tempfile, urllib, gzip, md5, cStringIO +import os, codecs, base64, tempfile, urllib, gzip, cStringIO +try: + from hashlib import md5 +except ImportError: + from md5 import md5 #Deprecated in 2.5 + from matplotlib import verbose, __version__, rcParams from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\ FigureManagerBase, FigureCanvasBase @@ -127,7 +132,7 @@ id = self._clipd.get(path) if id is None: - id = 'p%s' % md5.new(path).hexdigest() + id = 'p%s' % md5(path).hexdigest() self._svgwriter.write('<defs>\n <clipPath id="%s">\n' % id) self._svgwriter.write(path) self._svgwriter.write('\n </clipPath>\n</defs>') @@ -191,7 +196,7 @@ key = self._convert_path(marker_path, marker_trans + Affine2D().scale(1.0, -1.0)) name = self._markers.get(key) if name is None: - name = 'm%s' % md5.new(key).hexdigest() + name = 'm%s' % md5(key).hexdigest() write('<defs><path id="%s" d="%s"/></defs>\n' % (name, key)) self._markers[key] = name @@ -223,7 +228,7 @@ transform = Affine2D(transform.get_matrix()).scale(1.0, -1.0) d = self._convert_path(path, transform) name = 'coll%x_%x_%s' % (self._path_collection_id, i, - md5.new(d).hexdigest()) + md5(d).hexdigest()) write('<path id="%s" d="%s"/>\n' % (name, d)) path_codes.append(name) write('</defs>\n') @@ -412,7 +417,7 @@ if step[0] != 4: currx, curry = step[-2], -step[-1] path_data = ''.join(path_data) - char_num = 'c_%s' % md5.new(path_data).hexdigest() + char_num = 'c_%s' % md5(path_data).hexdigest() path_element = '<path id="%s" d="%s"/>\n' % (char_num, ''.join(path_data)) self._char_defs[char_id] = char_num return path_element Modified: trunk/matplotlib/lib/matplotlib/finance.py =================================================================== --- trunk/matplotlib/lib/matplotlib/finance.py 2008-07-26 00:34:02 UTC (rev 5884) +++ trunk/matplotlib/lib/matplotlib/finance.py 2008-07-26 04:50:56 UTC (rev 5885) @@ -4,9 +4,13 @@ """ #from __future__ import division -import os, time, warnings, md5 +import os, time, warnings from urllib import urlopen +try: + from hashlib import md5 +except ImportError: + from md5 import md5 #Deprecated in 2.5 try: import datetime except ImportError: @@ -111,7 +115,7 @@ if cachename is None: - cachename = os.path.join(cachedir, md5.md5(url).hexdigest()) + cachename = os.path.join(cachedir, md5(url).hexdigest()) if os.path.exists(cachename): fh = file(cachename) verbose.report('Using cachefile %s for %s'%(cachename, ticker)) Modified: trunk/matplotlib/lib/matplotlib/texmanager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/texmanager.py 2008-07-26 00:34:02 UTC (rev 5884) +++ trunk/matplotlib/lib/matplotlib/texmanager.py 2008-07-26 04:50:56 UTC (rev 5885) @@ -33,7 +33,13 @@ """ -import copy, glob, md5, os, shutil, sys, warnings +import copy, glob, os, shutil, sys, warnings + +try: + from hashlib import md5 +except ImportError: + from md5 import md5 #Deprecated in 2.5 + import distutils.version import numpy as np import matplotlib as mpl @@ -166,7 +172,7 @@ self.get_custom_preamble(), str(dpi or '')]) # make sure hash is consistent for all strings, regardless of encoding: bytes = unicode(s).encode('utf-8') - return os.path.join(self.texcache, md5.md5(bytes).hexdigest()) + return os.path.join(self.texcache, md5(bytes).hexdigest()) def get_font_config(self): """Reinitializes self if relevant rcParams on have changed.""" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-07-29 18:34:14
|
Revision: 5924 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5924&view=rev Author: jdh2358 Date: 2008-07-29 18:34:11 +0000 (Tue, 29 Jul 2008) Log Message: ----------- trying in vein to get rid of acorr indent warning on doc build Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/__init__.py trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2008-07-29 18:01:16 UTC (rev 5923) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2008-07-29 18:34:11 UTC (rev 5924) @@ -89,7 +89,7 @@ """ from __future__ import generators -__version__ = '0.98.3rc1' +__version__ = '0.98.3rc2' __revision__ = '$Revision$' __date__ = '$Date$' Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-07-29 18:01:16 UTC (rev 5923) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-07-29 18:34:11 UTC (rev 5924) @@ -3317,7 +3317,7 @@ """ call signature:: - acorr(x, normed=False, detrend=mlab.detrend_none, usevlines=False, + acorr(x, normed=False, detrend=mlab.detrend_none, usevlines=False, maxlags=None, **kwargs) Plot the autocorrelation of *x*. If *normed* = *True*, @@ -3328,32 +3328,30 @@ Return value is a tuple (*lags*, *c*, *line*) where: - - *lags* are a length 2*maxlags+1 lag vector + - *lags* are a length 2*maxlags+1 lag vector - - *c* is the 2*maxlags+1 auto correlation vector + - *c* is the 2*maxlags+1 auto correlation vector - - *line* is a :class:`~matplotlib.lines.Line2D` instance - returned by :meth:`plot` + - *line* is a :class:`~matplotlib.lines.Line2D` instance + returned by :meth:`plot` The default *linestyle* is None and the default *marker* is ``'o'``, though these can be overridden with keyword args. The cross correlation is performed with :func:`numpy.correlate` with *mode* = 2. - If *usevlines* is *True*: + If *usevlines* is *True*, :meth:`~matplotlib.axes.Axes.vlines` + rather than :meth:`~matplotlib.axes.Axes.plot` is used to draw + vertical lines from the origin to the acorr. Otherwise, the + plot style is determined by the kwargs, which are + :class:`~matplotlib.lines.Line2D` properties. The return + value is a tuple (*lags*, *c*, *linecol*, *b*) where - :meth:`~matplotlib.axes.Axes.vlines` rather than - :meth:`~matplotlib.axes.Axes.plot` is used to draw - vertical lines from the origin to the acorr. Otherwise, - the plot style is determined by the kwargs, which are - :class:`~matplotlib.lines.Line2D` properties. The return - value is a tuple (*lags*, *c*, *linecol*, *b*) where + - *linecol* is the + :class:`~matplotlib.collections.LineCollection` - - *linecol* is the - :class:`~matplotlib.collections.LineCollection` + - *b* is the *x*-axis. - - *b* is the *x*-axis. - *maxlags* is a positive integer detailing the number of lags to show. The default value of *None* will return all ``(2*len(x)-1)`` lags. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-08-05 19:02:35
|
Revision: 5976 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5976&view=rev Author: mdboom Date: 2008-08-05 19:02:30 +0000 (Tue, 05 Aug 2008) Log Message: ----------- Fix RGBA arrays in collections. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/patches.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-08-05 17:44:55 UTC (rev 5975) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-08-05 19:02:30 UTC (rev 5976) @@ -3797,14 +3797,18 @@ # if color looks like a color string, an RGB tuple or a # scalar, then repeat it by nbars if (is_string_like(color) or - (iterable(color) and len(color)==3 and nbars!=3) or + (iterable(color) and + len(color) in (3, 4) and + nbars != len(color)) or not iterable(color)): color = [color]*nbars # if edgecolor looks like a color string, an RGB tuple or a # scalar, then repeat it by nbars if (is_string_like(edgecolor) or - (iterable(edgecolor) and len(edgecolor)==3 and nbars!=3) or + (iterable(edgecolor) and + len(edgecolor) in (3, 4) and + nbars != len(edgecolor)) or not iterable(edgecolor)): edgecolor = [edgecolor]*nbars Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-08-05 17:44:55 UTC (rev 5975) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-08-05 19:02:30 UTC (rev 5976) @@ -332,6 +332,7 @@ """ if c is None: c = mpl.rcParams['patch.facecolor'] self._facecolors = _colors.colorConverter.to_rgba_array(c, self._alpha) + self._facecolors_original = c set_facecolors = set_facecolor @@ -363,6 +364,7 @@ else: if c is None: c = mpl.rcParams['patch.edgecolor'] self._edgecolors = _colors.colorConverter.to_rgba_array(c, self._alpha) + self._edgecolors_original = c set_edgecolors = set_edgecolor @@ -378,11 +380,13 @@ else: artist.Artist.set_alpha(self, alpha) try: - self._facecolors[:, 3] = alpha + self._facecolors = _colors.colorConverter.to_rgba_array( + self._facecolors_original, self._alpha) except (AttributeError, TypeError, IndexError): pass try: - self._edgecolors[:, 3] = alpha + self._edgecolors = _colors.colorConverter.to_rgba_array( + self._edgecolors_original, self._alpha) except (AttributeError, TypeError, IndexError): pass Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2008-08-05 17:44:55 UTC (rev 5975) +++ trunk/matplotlib/lib/matplotlib/patches.py 2008-08-05 19:02:30 UTC (rev 5976) @@ -263,7 +263,6 @@ gc.set_linewidth(self._linewidth) gc.set_linestyle(self._linestyle) - gc.set_alpha(self._alpha) gc.set_antialiased(self._antialiased) self._set_gc_clip(gc) gc.set_capstyle('projecting') @@ -271,8 +270,11 @@ if (not self.fill or self._facecolor is None or (cbook.is_string_like(self._facecolor) and self._facecolor.lower()=='none')): rgbFace = None + gc.set_alpha(1.0) else: - rgbFace = colors.colorConverter.to_rgb(self._facecolor) + r, g, b, a = colors.colorConverter.to_rgba(self._facecolor, self._alpha) + rgbFace = (r, g, b) + gc.set_alpha(a) if self._hatch: gc.set_hatch(self._hatch ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-08-06 12:50:34
|
Revision: 5979 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5979&view=rev Author: mdboom Date: 2008-08-06 12:50:31 +0000 (Wed, 06 Aug 2008) Log Message: ----------- Fix no-fill bug introduced in r5976 Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/colors.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-08-06 00:28:03 UTC (rev 5978) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-08-06 12:50:31 UTC (rev 5979) @@ -5195,26 +5195,14 @@ ymax = 10**ymax self.set_yscale('log') - class HexagonBinCollection(mcoll.PolyCollection): - """A HexagonBinCollection is a PolyCollection where the edge - colors are always kept equal to the fill colors""" - def update_scalarmappable(self): - mcoll.PolyCollection.update_scalarmappable(self) - self._edgecolors = self._facecolors - if edgecolors=='none': - collection = HexagonBinCollection( - polygons, - linewidths = linewidths, - transOffset = self.transData, - ) - else: - collection = mcoll.PolyCollection( - polygons, - edgecolors = edgecolors, - linewidths = linewidths, - transOffset = self.transData, - ) + edgecolors = 'face' + collection = mcoll.PolyCollection( + polygons, + edgecolors = edgecolors, + linewidths = linewidths, + transOffset = self.transData, + ) # Transform accum if needed if bins=='log': Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2008-08-06 00:28:03 UTC (rev 5978) +++ trunk/matplotlib/lib/matplotlib/collections.py 2008-08-06 12:50:31 UTC (rev 5979) @@ -8,7 +8,7 @@ they are meant to be fast for common use cases (e.g. a bunch of solid line segemnts) """ -import math, warnings +import copy, math, warnings import numpy as np import numpy.ma as ma import matplotlib as mpl @@ -331,8 +331,8 @@ ACCEPTS: matplotlib color arg or sequence of rgba tuples """ if c is None: c = mpl.rcParams['patch.facecolor'] + self._facecolors_original = c self._facecolors = _colors.colorConverter.to_rgba_array(c, self._alpha) - self._facecolors_original = c set_facecolors = set_facecolor @@ -361,10 +361,11 @@ """ if c == 'face': self._edgecolors = 'face' + self._edgecolors_original = 'face' else: if c is None: c = mpl.rcParams['patch.edgecolor'] + self._edgecolors_original = c self._edgecolors = _colors.colorConverter.to_rgba_array(c, self._alpha) - self._edgecolors_original = c set_edgecolors = set_edgecolor @@ -385,8 +386,9 @@ except (AttributeError, TypeError, IndexError): pass try: - self._edgecolors = _colors.colorConverter.to_rgba_array( - self._edgecolors_original, self._alpha) + if self._edgecolors_original != 'face': + self._edgecolors = _colors.colorConverter.to_rgba_array( + self._edgecolors_original, self._alpha) except (AttributeError, TypeError, IndexError): pass @@ -809,7 +811,7 @@ pickradius=pickradius, **kwargs) - self._facecolors = np.array([]) + self.set_facecolors([]) self.set_segments(segments) def get_paths(self): Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2008-08-06 00:28:03 UTC (rev 5978) +++ trunk/matplotlib/lib/matplotlib/colors.py 2008-08-06 12:50:31 UTC (rev 5979) @@ -332,7 +332,7 @@ if len(c) == 0: return np.zeros((0,4), dtype=np.float_) try: - result = [self.to_rgba(c, alpha)] + result = np.array([self.to_rgba(c, alpha)], dtype=np.float_) except ValueError: # If c is a list it must be maintained as the same list # with modified items so that items can be appended to @@ -340,18 +340,10 @@ if isinstance(c, np.ndarray): if len(c.shape) != 2: raise ValueError("Color array must be two-dimensional") - if c.shape[1] != 4: - output = np.zeros((c.shape[0], 4)) - else: - output = c - elif not isinstance(c, list): - output = list(c) - else: - output = c + result = np.zeros((len(c), 4)) for i, cc in enumerate(c): - output[i] = self.to_rgba(cc, alpha) # change in place - result = output + result[i] = self.to_rgba(cc, alpha) # change in place return np.asarray(result, np.float_) colorConverter = ColorConverter() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2008-08-11 07:09:22
|
Revision: 6017 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6017&view=rev Author: efiring Date: 2008-08-11 07:09:16 +0000 (Mon, 11 Aug 2008) Log Message: ----------- Eliminate duplicate Path instantiation Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/transforms.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-08-10 23:49:21 UTC (rev 6016) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-08-11 07:09:16 UTC (rev 6017) @@ -1282,8 +1282,9 @@ line._remove_method = lambda h: self.lines.remove(h) def _update_line_limits(self, line): - xydata = line.get_xydata() - self.update_datalim( xydata ) + self.dataLim.update_from_path(line.get_path(), + self.ignore_existing_data_limits) + self.ignore_existing_data_limits = False def add_patch(self, p): """ @@ -1307,12 +1308,11 @@ # the auto-scaling if isinstance(p, mpatches.Rectangle) and (p.get_width()==0. or p.get_height()==0.): return - vertices = p.get_patch_transform().transform(p.get_path().vertices) if p.get_data_transform() != self.transData: transform = p.get_data_transform() + self.transData.inverted() xys = transform.transform(vertices) - + # Something is wrong--xys is never used. self.update_datalim(vertices) def add_table(self, tab): @@ -1327,6 +1327,8 @@ def relim(self): 'recompute the data limits based on current artists' + # Collections are deliberately not supported (yet); see + # the TODO note in artists.py. self.dataLim.ignore(True) self.ignore_existing_data_limits = True for line in self.lines: Modified: trunk/matplotlib/lib/matplotlib/transforms.py =================================================================== --- trunk/matplotlib/lib/matplotlib/transforms.py 2008-08-10 23:49:21 UTC (rev 6016) +++ trunk/matplotlib/lib/matplotlib/transforms.py 2008-08-11 07:09:16 UTC (rev 6017) @@ -786,12 +786,12 @@ xy = np.hstack((x.reshape((len(x), 1)), y.reshape((len(y), 1)))) return self.update_from_data_xy(xy, ignore) - def update_from_data_xy(self, xy, ignore=None): + def update_from_path(self, path, ignore=None): """ Update the bounds of the :class:`Bbox` based on the passed in data. - xy: a numpy array of 2D points + path: a Path instance ignore: - when True, ignore the existing bounds of the Bbox. @@ -801,20 +801,33 @@ if ignore is None: ignore = self._ignore - if len(xy) == 0: - return - xym = ma.masked_invalid(xy) # maybe add copy=False - if (xym.count(axis=1)!=2).all(): - return - points, minpos, changed = update_path_extents( - Path(xym), None, self._points, self._minpos, ignore) + path, None, self._points, self._minpos, ignore) if changed: self._points = points self._minpos = minpos self.invalidate() + + def update_from_data_xy(self, xy, ignore=None): + """ + Update the bounds of the :class:`Bbox` based on the passed in + data. + + xy: a numpy array of 2D points + + ignore: + - when True, ignore the existing bounds of the Bbox. + - when False, include the existing bounds of the Bbox. + - when None, use the last value passed to :meth:`ignore`. + """ + if len(xy) == 0: + return + + path = Path(xy) + self.update_from_path(path, ignore=ignore) + def _set_x0(self, val): self._points[0, 0] = val self.invalidate() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-08-12 16:03:22
|
Revision: 6022 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6022&view=rev Author: jdh2358 Date: 2008-08-12 16:03:19 +0000 (Tue, 12 Aug 2008) Log Message: ----------- some legend fixes Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/legend.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-08-11 15:34:30 UTC (rev 6021) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-08-12 16:03:19 UTC (rev 6022) @@ -6364,7 +6364,7 @@ for p in patch: p.update(kwargs) p.set_label(label) - label = '_nolegend' + label = '_nolegend_' if len(n)==1: Modified: trunk/matplotlib/lib/matplotlib/legend.py =================================================================== --- trunk/matplotlib/lib/matplotlib/legend.py 2008-08-11 15:34:30 UTC (rev 6021) +++ trunk/matplotlib/lib/matplotlib/legend.py 2008-08-12 16:03:19 UTC (rev 6022) @@ -520,7 +520,8 @@ if isinstance(handle, Line2D): ydata = y*np.ones(handle.get_xdata().shape, float) handle.set_ydata(ydata+h/2.) - handle._legmarker.set_ydata(ydata+h/2.) + if hasattr(handle, '_legmarker'): + handle._legmarker.set_ydata(ydata+h/2.) elif isinstance(handle, Rectangle): handle.set_y(y+1/4*h) handle.set_height(h/2) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-08-13 15:00:10
|
Revision: 6031 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6031&view=rev Author: mdboom Date: 2008-08-13 15:00:05 +0000 (Wed, 13 Aug 2008) Log Message: ----------- Raise ImportError rather than SystemExit -- that is, importing an improperly configured matplotlib should not quit the Python console. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/__init__.py trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py trunk/matplotlib/lib/matplotlib/finance.py Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2008-08-13 14:09:04 UTC (rev 6030) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2008-08-13 15:00:05 UTC (rev 6031) @@ -144,12 +144,12 @@ #else: _have_pkg_resources = True if not _python24: - raise SystemExit('matplotlib requires Python 2.4 or later') + raise ImportError('matplotlib requires Python 2.4 or later') import numpy nn = numpy.__version__.split('.') if not (int(nn[0]) >= 1 and int(nn[1]) >= 1): - raise SystemExit( + raise ImportError( 'numpy 1.1 or later is required; you have %s' % numpy.__version__) def is_string_like(obj): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2008-08-13 14:09:04 UTC (rev 6030) +++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2008-08-13 15:00:05 UTC (rev 6031) @@ -28,7 +28,7 @@ import cairo _version_required = (1,2,0) if cairo.version_info < _version_required: - raise SystemExit ("Pycairo %d.%d.%d is installed\n" + raise ImportError ("Pycairo %d.%d.%d is installed\n" "Pycairo %d.%d.%d or later is required" % (cairo.version_info + _version_required)) backend_version = cairo.version Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py 2008-08-13 14:09:04 UTC (rev 6030) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gdk.py 2008-08-13 15:00:05 UTC (rev 6031) @@ -11,7 +11,7 @@ import pango pygtk_version_required = (2,2,0) if gtk.pygtk_version < pygtk_version_required: - raise SystemExit ("PyGTK %d.%d.%d is installed\n" + raise ImportError ("PyGTK %d.%d.%d is installed\n" "PyGTK %d.%d.%d or later is required" % (gtk.pygtk_version + pygtk_version_required)) del pygtk_version_required Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-08-13 14:09:04 UTC (rev 6030) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-08-13 15:00:05 UTC (rev 6031) @@ -8,7 +8,7 @@ import pango pygtk_version_required = (2,2,0) if gtk.pygtk_version < pygtk_version_required: - raise SystemExit ("PyGTK %d.%d.%d is installed\n" + raise ImportError ("PyGTK %d.%d.%d is installed\n" "PyGTK %d.%d.%d or later is required" % (gtk.pygtk_version + pygtk_version_required)) del pygtk_version_required Modified: trunk/matplotlib/lib/matplotlib/finance.py =================================================================== --- trunk/matplotlib/lib/matplotlib/finance.py 2008-08-13 14:09:04 UTC (rev 6030) +++ trunk/matplotlib/lib/matplotlib/finance.py 2008-08-13 15:00:05 UTC (rev 6031) @@ -14,7 +14,7 @@ try: import datetime except ImportError: - raise SystemExit('The finance module requires datetime support (python2.3)') + raise ImportError('The finance module requires datetime support (python2.3)') import numpy as np @@ -415,7 +415,7 @@ # note this code assumes if any value open, close, low, high is # missing they all are missing - + delta = width/2. barVerts = [ ( (i-delta, open), (i-delta, close), (i+delta, close), (i+delta, open) ) for i, open, close in zip(xrange(len(opens)), opens, closes) if open != -1 and close!=-1 ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2008-08-13 18:25:32
|
Revision: 6035 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6035&view=rev Author: mdboom Date: 2008-08-13 18:25:26 +0000 (Wed, 13 Aug 2008) Log Message: ----------- [ 2029956 ] Fix documentation warnings. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/quiver.py Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-08-13 18:10:33 UTC (rev 6034) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-08-13 18:25:26 UTC (rev 6035) @@ -1464,7 +1464,7 @@ Call signature:: - stop_event_loop_default(self) + stop_event_loop_default(self) """ self._looping = False Modified: trunk/matplotlib/lib/matplotlib/quiver.py =================================================================== --- trunk/matplotlib/lib/matplotlib/quiver.py 2008-08-13 18:10:33 UTC (rev 6034) +++ trunk/matplotlib/lib/matplotlib/quiver.py 2008-08-13 18:25:26 UTC (rev 6035) @@ -40,10 +40,12 @@ Arguments: *X*, *Y*: - The x and y coordinates of the arrow locations - (default is tail of arrow; see *pivot* kwarg) + The x and y coordinates of the arrow locations (default is tail of + arrow; see *pivot* kwarg) + *U*, *V*: + give the *x* and *y* components of the arrow vectors *C*: @@ -61,28 +63,31 @@ Keyword arguments: *units*: ['width' | 'height' | 'dots' | 'inches' | 'x' | 'y' ] - arrow units; the arrow dimensions *except for length* are - in multiples of this unit. + arrow units; the arrow dimensions *except for length* are in + multiples of this unit. * 'width' or 'height': the width or height of the axes - * 'dots' or 'inches': pixels or inches, based on the figure dpi + + * 'dots' or 'inches': pixels or inches, based on the figure dpi + * 'x' or 'y': *X* or *Y* data units In all cases the arrow aspect ratio is 1, so that if *U*==*V* the - angle of the arrow on the plot is 45 degrees CCW from the *x*-axis. + angle of the arrow on the plot is 45 degrees CCW from the + *x*-axis. - The arrows scale differently depending on the units, however. - For 'x' or 'y', the arrows get larger as one zooms in; for other + The arrows scale differently depending on the units, however. For + 'x' or 'y', the arrows get larger as one zooms in; for other units, the arrow size is independent of the zoom state. For 'width or 'height', the arrow size increases with the width and height of the axes, respectively, when the the window is resized; for 'dots' or 'inches', resizing does not change the arrows. *scale*: [ None | float ] - data units per arrow unit, e.g. m/s per plot width; - a smaller scale parameter makes the arrow longer. - If *None*, a simple autoscaling algorithm is used, based - on the average vector length and the number of vectors. + data units per arrow unit, e.g. m/s per plot width; a smaller + scale parameter makes the arrow longer. If *None*, a simple + autoscaling algorithm is used, based on the average vector length + and the number of vectors. *width*: shaft width in arrow units; default depends on choice of units, @@ -109,8 +114,8 @@ Default is 1. *pivot*: [ 'tail' | 'middle' | 'tip' ] - The part of the arrow that is at the grid point; the arrow - rotates about this point, hence the name *pivot*. + The part of the arrow that is at the grid point; the arrow rotates + about this point, hence the name *pivot*. *color*: [ color | color sequence ] This is a synonym for the @@ -155,23 +160,23 @@ Keyword arguments: *coordinates* = [ 'axes' | 'figure' | 'data' | 'inches' ] - Coordinate system and units for *X*, *Y*: 'axes' and 'figure' - are normalized coordinate systems with 0,0 in the lower - left and 1,1 in the upper right; 'data' are the axes - data coordinates (used for the locations of the vectors - in the quiver plot itself); 'inches' is position in the - figure in inches, with 0,0 at the lower left corner. + Coordinate system and units for *X*, *Y*: 'axes' and 'figure' are + normalized coordinate systems with 0,0 in the lower left and 1,1 + in the upper right; 'data' are the axes data coordinates (used for + the locations of the vectors in the quiver plot itself); 'inches' + is position in the figure in inches, with 0,0 at the lower left + corner. *color*: overrides face and edge colors from *Q*. *labelpos* = [ 'N' | 'S' | 'E' | 'W' ] - Position the label above, below, to the right, to the left - of the arrow, respectively. + Position the label above, below, to the right, to the left of the + arrow, respectively. *labelsep*: - Distance in inches between the arrow and the label. - Default is 0.1 + Distance in inches between the arrow and the label. Default is + 0.1 *labelcolor*: defaults to default :class:`~matplotlib.text.Text` color. @@ -557,88 +562,100 @@ Default is 9 *pivot*: [ 'tip' | 'middle' ] - The part of the arrow that is at the grid point; the arrow - rotates about this point, hence the name *pivot*. - Default is 'tip' + The part of the arrow that is at the grid point; the arrow rotates + about this point, hence the name *pivot*. Default is 'tip' *barbcolor*: [ color | color sequence ] - Specifies the color all parts of the barb except any flags. - This parameter is analagous to the *edgecolor* parameter - for polygons, which can be used instead. However this parameter - will override facecolor. + Specifies the color all parts of the barb except any flags. This + parameter is analagous to the *edgecolor* parameter for polygons, + which can be used instead. However this parameter will override + facecolor. *flagcolor*: [ color | color sequence ] - Specifies the color of any flags on the barb. - This parameter is analagous to the *facecolor* parameter - for polygons, which can be used instead. However this parameter - will override facecolor. If this is not set (and *C* has not either) - then *flagcolor* will be set to match *barbcolor* so that the barb - has a uniform color. If *C* has been set, *flagcolor* has no effect. + Specifies the color of any flags on the barb. This parameter is + analagous to the *facecolor* parameter for polygons, which can be + used instead. However this parameter will override facecolor. If + this is not set (and *C* has not either) then *flagcolor* will be + set to match *barbcolor* so that the barb has a uniform color. If + *C* has been set, *flagcolor* has no effect. *sizes*: - A dictionary of coefficients specifying the ratio of a given feature - to the length of the barb. Only those values one wishes to override - need to be included. These features include: - 'spacing' - space between features (flags, full/half barbs) - 'height' - height (distance from shaft to top) of a flag or full barb - 'width' - width of a flag, twice the width of a full barb - 'emptybarb' - radius of the circle used for low magnitudes + A dictionary of coefficients specifying the ratio of a given + feature to the length of the barb. Only those values one wishes to + override need to be included. These features include: + - 'spacing' - space between features (flags, full/half barbs) + + - 'height' - height (distance from shaft to top) of a flag or + full barb + + - 'width' - width of a flag, twice the width of a full barb + + - 'emptybarb' - radius of the circle used for low magnitudes + *fill_empty*: - A flag on whether the empty barbs (circles) that are drawn should be filled - with the flag color. If they are not filled, they will be drawn such that - no color is applied to the center. - Default is False + A flag on whether the empty barbs (circles) that are drawn should + be filled with the flag color. If they are not filled, they will + be drawn such that no color is applied to the center. Default is + False *rounding*: - A flag to indicate whether the vector magnitude should be rounded when - allocating barb components. If True, the magnitude is rounded to the - nearest multiple of the half-barb increment. If False, the magnitude - is simply truncated to the next lowest multiple. - Default is True + A flag to indicate whether the vector magnitude should be rounded + when allocating barb components. If True, the magnitude is + rounded to the nearest multiple of the half-barb increment. If + False, the magnitude is simply truncated to the next lowest + multiple. Default is True *barb_increments*: - A dictionary of increments specifying values to associate with different - parts of the barb. Only those values one wishes to override need to be - included. - 'half' - half barbs (Default is 5) - 'full' - full barbs (Default is 10) - 'flag' - flags (default is 50) + A dictionary of increments specifying values to associate with + different parts of the barb. Only those values one wishes to + override need to be included. + - 'half' - half barbs (Default is 5) + + - 'full' - full barbs (Default is 10) + + - 'flag' - flags (default is 50) + *flip_barb*: - Either a single boolean flag or an array of booleans. Single boolean - indicates whether the lines and flags should point opposite to normal - for all barbs. An array (which should be the same size as the other - data arrays) indicates whether to flip for each individual barb. - Normal behavior is for the barbs and lines to point right (comes from - wind barbs having these features point towards low pressure in the - Northern Hemisphere.) - Default is False + Either a single boolean flag or an array of booleans. Single + boolean indicates whether the lines and flags should point + opposite to normal for all barbs. An array (which should be the + same size as the other data arrays) indicates whether to flip for + each individual barb. Normal behavior is for the barbs and lines + to point right (comes from wind barbs having these features point + towards low pressure in the Northern Hemisphere.) Default is + False Barbs are traditionally used in meteorology as a way to plot the speed -and direction of wind observations, but can technically be used to plot -any two dimensional vector quantity. As opposed to arrows, which give -vector magnitude by the length of the arrow, the barbs give more quantitative -information about the vector magnitude by putting slanted lines or a triangle -for various increments in magnitude, as show schematically below: +and direction of wind observations, but can technically be used to +plot any two dimensional vector quantity. As opposed to arrows, which +give vector magnitude by the length of the arrow, the barbs give more +quantitative information about the vector magnitude by putting slanted +lines or a triangle for various increments in magnitude, as show +schematically below:: - /\ \ - / \ \ - / \ \ \ -/ \ \ \ ------------------------------- + : /\ \\ + : / \ \\ + : / \ \ \\ + : / \ \ \\ + : ------------------------------ -The largest increment is given by a triangle (or "flag"). After those come full -lines (barbs). The smallest increment is a half line. There is only, of -course, ever at most 1 half line. If the magnitude is small and only needs a -single half-line and no full lines or triangles, the half-line is offset from -the end of the barb so that it can be easily distinguished from barbs with a -single full line. The magnitude for the barb shown above would nominally be -65, using the standard increments of 50, 10, and 5. +.. note the double \\ at the end of each line to make the figure +.. render correctly +The largest increment is given by a triangle (or "flag"). After those +come full lines (barbs). The smallest increment is a half line. There +is only, of course, ever at most 1 half line. If the magnitude is +small and only needs a single half-line and no full lines or +triangles, the half-line is offset from the end of the barb so that it +can be easily distinguished from barbs with a single full line. The +magnitude for the barb shown above would nominally be 65, using the +standard increments of 50, 10, and 5. + linewidths and edgecolors can be used to customize the barb. -Additional :class:`~matplotlib.collections.PolyCollection` -keyword arguments: +Additional :class:`~matplotlib.collections.PolyCollection` keyword +arguments: %(PolyCollection)s """ % martist.kwdocd @@ -647,15 +664,15 @@ ''' Specialized PolyCollection for barbs. - The only API method is set_UVC(), which can be used - to change the size, orientation, and color of the - arrows. Locations are changed using the set_offsets() collection - method.Possibly this method will be useful in animations. + The only API method is :meth:`set_UVC`, which can be used to + change the size, orientation, and color of the arrows. Locations + are changed using the :meth:`set_offsets` collection method. + Possibly this method will be useful in animations. - There is one internal function _find_tails() which finds exactly - what should be put on the barb given the vector magnitude. From there - _make_barbs() is used to find the vertices of the polygon to represent the - barb based on this information. + There is one internal function :meth:`_find_tails` which finds + exactly what should be put on the barb given the vector magnitude. + From there :meth:`_make_barbs` is used to find the vertices of the + polygon to represent the barb based on this information. ''' #This may be an abuse of polygons here to render what is essentially maybe #1 triangle and a series of lines. It works fine as far as I can tell @@ -714,12 +731,15 @@ half a barb. Mag should be the magnitude of a vector (ie. >= 0). This returns a tuple of: - (number of flags, number of barbs, half_flag, empty_flag) - half_flag is a boolean whether half of a barb is needed, since there - should only ever be one half on a given barb. Empty flag is an array - of flags to easily tell if a barb is empty (too low to plot any - barbs/flags.''' + (*number of flags*, *number of barbs*, *half_flag*, *empty_flag*) + + *half_flag* is a boolean whether half of a barb is needed, + since there should only ever be one half on a given + barb. *empty_flag* flag is an array of flags to easily tell if + a barb is empty (too low to plot any barbs/flags. + ''' + #If rounding, round to the nearest multiple of half, the smallest #increment if rounding: @@ -738,25 +758,41 @@ def _make_barbs(self, u, v, nflags, nbarbs, half_barb, empty_flag, length, pivot, sizes, fill_empty, flip): - '''This function actually creates the wind barbs. u and v are - components of the vector in the x and y directions, respectively. - nflags, nbarbs, and half_barb, empty_flag are, respectively, the number - of flags, number of barbs, flag for half a barb, and flag for empty - barb, ostensibly obtained from _find_tails. length is the length of - the barb staff in points. pivot specifies the point on the barb around - which the entire barb should be rotated. Right now valid options are - 'head' and 'middle'. sizes is a dictionary of coefficients specifying - the ratio of a given feature to the length of the barb. These features + '''This function actually creates the wind barbs. *u* and *v* + are components of the vector in the *x* and *y* directions, + respectively. + + *nflags*, *nbarbs*, and *half_barb*, empty_flag* are, + *respectively, the number of flags, number of barbs, flag for + *half a barb, and flag for empty barb, ostensibly obtained + *from :meth:`_find_tails`. + + *length* is the length of the barb staff in points. + + *pivot* specifies the point on the barb around which the + entire barb should be rotated. Right now, valid options are + 'head' and 'middle'. + + *sizes* is a dictionary of coefficients specifying the ratio + of a given feature to the length of the barb. These features include: - spacing - space between features (flags, full/half barbs) - height - height (distance from shaft of top) of a flag or full barb - width - width of a flag, twice the width of a full barb - emptybarb - radius of the circle used for low magnitudes + - *spacing*: space between features (flags, full/half + barbs) - fill_empty specifies whether the circle representing an empty barb - should be filled or not (this changes the drawing of the polygon). - flip is a flag indicating whether the features should be flipped to + - *height*: distance from shaft of top of a flag or full + barb + + - *width* - width of a flag, twice the width of a full barb + + - *emptybarb* - radius of the circle used for low + magnitudes + + *fill_empty* specifies whether the circle representing an + empty barb should be filled or not (this changes the drawing + of the polygon). + + *flip* is a flag indicating whether the features should be flipped to the other side of the barb (useful for winds in the southern hemisphere. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jr...@us...> - 2008-09-09 23:16:01
|
Revision: 6077 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6077&view=rev Author: jrevans Date: 2008-09-09 23:15:59 +0000 (Tue, 09 Sep 2008) Log Message: ----------- Fixed some issues with unitized data. Some Patches were attempting to calculate some results without knowing how to convert (not attached to any Axes). A couple of Axes routines were assuming data was not unitized or not converting the data at the appropriate place. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/patches.py Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2008-09-09 12:58:33 UTC (rev 6076) +++ trunk/matplotlib/lib/matplotlib/axes.py 2008-09-09 23:15:59 UTC (rev 6077) @@ -2679,10 +2679,12 @@ See :meth:`axhspan` for example plot and source code """ - ymin, ymax = self.get_ylim() - if ymax<ymin: ymin, ymax = ymax, ymin - scaley = (y<ymin) or (y>ymax) + ymin, ymax = self.get_ybound() + # We need to strip away the units for comparison with non-unitized bounds + yy = self.convert_yunits( y ) + scaley = (yy<ymin) or (yy>ymax) + trans = mtransforms.blended_transform_factory( self.transAxes, self.transData) l, = self.plot([xmin,xmax], [y,y], transform=trans, scalex=False, scaley=scaley, **kwargs) @@ -2731,10 +2733,12 @@ See :meth:`axhspan` for example plot and source code """ - xmin, xmax = self.get_xlim() - if xmax<xmin: xmin, xmax = xmax, xmin - scalex = (x<xmin) or (x>xmax) + xmin, xmax = self.get_xbound() + # We need to strip away the units for comparison with non-unitized bounds + xx = self.convert_xunits( x ) + scalex = (xx<xmin) or (xx>xmax) + trans = mtransforms.blended_transform_factory( self.transData, self.transAxes) l, = self.plot([x,x], [ymin,ymax] , transform=trans, scalex=scalex, scaley=False, **kwargs) @@ -2876,9 +2880,15 @@ raise DeprecationWarning( 'hlines now uses a collections.LineCollection and not a list of Line2D to draw; see API_CHANGES') + # We do the conversion first since not all unitized data is uniform + y = self.convert_yunits( y ) + xmin = self.convert_xunits( xmin ) + xmax = self.convert_xunits( xmax ) + if not iterable(y): y = [y] if not iterable(xmin): xmin = [xmin] if not iterable(xmax): xmax = [xmax] + y = np.asarray(y) xmin = np.asarray(xmin) xmax = np.asarray(xmax) @@ -2905,8 +2915,6 @@ miny = y.min() maxy = y.max() - minx, maxx = self.convert_xunits((minx, maxx)) - miny, maxy = self.convert_yunits((miny, maxy)) corners = (minx, miny), (maxx, maxy) self.update_datalim(corners) @@ -2947,9 +2955,15 @@ self._process_unit_info(xdata=x, ydata=ymin, kwargs=kwargs) + # We do the conversion first since not all unitized data is uniform + x = self.convert_xunits( x ) + ymin = self.convert_yunits( ymin ) + ymax = self.convert_yunits( ymax ) + if not iterable(x): x = [x] if not iterable(ymin): ymin = [ymin] if not iterable(ymax): ymax = [ymax] + x = np.asarray(x) ymin = np.asarray(ymin) ymax = np.asarray(ymax) @@ -2973,17 +2987,12 @@ self.add_collection(coll) coll.update(kwargs) - # We do the conversion first since not all unitized data is uniform - xx = self.convert_xunits( x ) - yymin = self.convert_yunits( ymin ) - yymax = self.convert_yunits( ymax ) + minx = min( x ) + maxx = max( x ) - minx = min( xx ) - maxx = max( xx ) + miny = min( min(ymin), min(ymax) ) + maxy = max( max(ymin), max(ymax) ) - miny = min( min(yymin), min(yymax) ) - maxy = max( max(yymin), max(yymax) ) - corners = (minx, miny), (maxx, maxy) self.update_datalim(corners) self.autoscale_view() Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2008-09-09 12:58:33 UTC (rev 6076) +++ trunk/matplotlib/lib/matplotlib/patches.py 2008-09-09 23:15:59 UTC (rev 6077) @@ -380,8 +380,8 @@ self._y = xy[1] self._width = width self._height = height + # Note: This cannot be calculated until this is added to an Axes self._rect_transform = transforms.IdentityTransform() - self._update_patch_transform() __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd def get_path(self): @@ -391,6 +391,11 @@ return Path.unit_rectangle() def _update_patch_transform(self): + """NOTE: This cannot be called until after this has been added + to an Axes, otherwise unit conversion will fail. This + maxes it very important to call the accessor method and + not directly access the transformation member variable. + """ x = self.convert_xunits(self._x) y = self.convert_yunits(self._y) width = self.convert_xunits(self._width) @@ -946,11 +951,16 @@ self.width, self.height = width, height self.angle = angle self._path = Path.unit_circle() + # Note: This cannot be calculated until this is added to an Axes self._patch_transform = transforms.IdentityTransform() - self._recompute_transform() __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd def _recompute_transform(self): + """NOTE: This cannot be called until after this has been added + to an Axes, otherwise unit conversion will fail. This + maxes it very important to call the accessor method and + not directly access the transformation member variable. + """ center = (self.convert_xunits(self.center[0]), self.convert_yunits(self.center[1])) width = self.convert_xunits(self.width) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-09-12 22:12:14
|
Revision: 6088 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6088&view=rev Author: jdh2358 Date: 2008-09-12 21:21:16 +0000 (Fri, 12 Sep 2008) Log Message: ----------- added get_children to artist base class Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/artist.py trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/mlab.py Modified: trunk/matplotlib/lib/matplotlib/artist.py =================================================================== --- trunk/matplotlib/lib/matplotlib/artist.py 2008-09-12 02:35:02 UTC (rev 6087) +++ trunk/matplotlib/lib/matplotlib/artist.py 2008-09-12 21:21:16 UTC (rev 6088) @@ -166,10 +166,15 @@ traceback.print_exc() print "while checking",self.__class__ - if hasattr(self,'get_children'): - for a in self.get_children(): L.extend(a.hitlist(event)) + + for a in self.get_children(): + L.extend(a.hitlist(event)) return L + def get_children(self): + 'return a list of the child artist this artist contains' + return [] + def contains(self, mouseevent): """Test whether the artist contains the mouse event. @@ -224,8 +229,8 @@ self.figure.canvas.pick_event(mouseevent, self, **prop) # Pick children - if hasattr(self,'get_children'): - for a in self.get_children(): a.pick(mouseevent) + for a in self.get_children(): + a.pick(mouseevent) def set_picker(self, picker): """ @@ -538,14 +543,14 @@ artists = [] - if hasattr(self, 'get_children'): - for c in self.get_children(): - if matchfunc(c): - artists.append(c) - artists.extend([thisc for thisc in c.findobj(matchfunc) if matchfunc(thisc)]) - else: - if matchfunc(self): - artists.append(self) + + for c in self.get_children(): + if matchfunc(c): + artists.append(c) + artists.extend([thisc for thisc in c.findobj(matchfunc) if matchfunc(thisc)]) + + if matchfunc(self): + artists.append(self) return artists @@ -761,14 +766,14 @@ artists = [] - if hasattr(self, 'get_children'): - for c in self.get_children(): - if matchfunc(c): - artists.append(c) - artists.extend([thisc for thisc in c.findobj(matchfunc) if matchfunc(thisc)]) - else: - if matchfunc(self): - artists.append(self) + + for c in self.get_children(): + if matchfunc(c): + artists.append(c) + artists.extend([thisc for thisc in c.findobj(matchfunc) if matchfunc(thisc)]) + + if matchfunc(self): + artists.append(self) return artists Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-09-12 02:35:02 UTC (rev 6087) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-09-12 21:21:16 UTC (rev 6088) @@ -944,7 +944,7 @@ break parent = None for p in under: - if hasattr(p,'getchildren') and h in p.get_children(): + if h in p.get_children(): parent = p break h = parent Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-09-12 02:35:02 UTC (rev 6087) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-09-12 21:21:16 UTC (rev 6088) @@ -2346,14 +2346,16 @@ class FormatInt(FormatObj): def toval(self, x): - return x + return int(x) def fromstr(self, s): return int(s) class FormatBool(FormatObj): + + def toval(self, x): - return x + return str(x) def fromstr(self, s): return bool(s) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jr...@us...> - 2008-09-15 16:09:28
|
Revision: 6097 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6097&view=rev Author: jrevans Date: 2008-09-15 23:09:24 +0000 (Mon, 15 Sep 2008) Log Message: ----------- Fixed contour to now properly strip away units for unitized data on the x and y axes. Unit registry now properly determines the registered converter to use for nested array data types. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/contour.py trunk/matplotlib/lib/matplotlib/units.py Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2008-09-15 19:59:47 UTC (rev 6096) +++ trunk/matplotlib/lib/matplotlib/contour.py 2008-09-15 23:09:24 UTC (rev 6097) @@ -724,8 +724,12 @@ Possible change: I think we should make and use an ArgumentError Exception class (here and elsewhere). ''' - x = np.asarray(args[0], dtype=np.float64) - y = np.asarray(args[1], dtype=np.float64) + # We can strip away the x and y units + x = self.ax.convert_xunits( args[0] ) + y = self.ax.convert_yunits( args[1] ) + + x = np.asarray(x, dtype=np.float64) + y = np.asarray(y, dtype=np.float64) z = ma.asarray(args[2], dtype=np.float64) if z.ndim != 2: raise TypeError("Input z must be a 2D array.") Modified: trunk/matplotlib/lib/matplotlib/units.py =================================================================== --- trunk/matplotlib/lib/matplotlib/units.py 2008-09-15 19:59:47 UTC (rev 6096) +++ trunk/matplotlib/lib/matplotlib/units.py 2008-09-15 23:09:24 UTC (rev 6097) @@ -128,12 +128,9 @@ if converter is None and iterable(x): for thisx in x: - classx = getattr(thisx, '__class__', None) - break - if classx is not None: - converter = self.get(classx) + converter = self.get_converter( thisx ) + if converter: break - #DISABLED self._cached[idx] = converter return converter This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-09-16 18:54:59
|
Revision: 6098 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6098&view=rev Author: jdh2358 Date: 2008-09-17 01:54:56 +0000 (Wed, 17 Sep 2008) Log Message: ----------- added the renderer dpi to the cache key for text Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/font_manager.py trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/lib/matplotlib/font_manager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/font_manager.py 2008-09-15 23:09:24 UTC (rev 6097) +++ trunk/matplotlib/lib/matplotlib/font_manager.py 2008-09-17 01:54:56 UTC (rev 6098) @@ -955,7 +955,7 @@ fname = prop.get_file() if fname is not None: verbose.report('findfont returning %s'%fname, 'debug') - return fname[0] + return fname if fontext == 'afm': fontdict = self.afmdict Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2008-09-15 23:09:24 UTC (rev 6097) +++ trunk/matplotlib/lib/matplotlib/text.py 2008-09-17 01:54:56 UTC (rev 6098) @@ -401,7 +401,7 @@ return (x, y, self._text, self._color, self._verticalalignment, self._horizontalalignment, hash(self._fontproperties), self._rotation, - self.figure.dpi, id(self._renderer) + self.figure.dpi, id(self._renderer), self._renderer.dpi ) def get_text(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-09-17 13:52:13
|
Revision: 6101 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6101&view=rev Author: jdh2358 Date: 2008-09-17 20:52:08 +0000 (Wed, 17 Sep 2008) Log Message: ----------- committed Jae-Joons facy box and textbox patch Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/patches.py trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2008-09-17 15:47:02 UTC (rev 6100) +++ trunk/matplotlib/lib/matplotlib/patches.py 2008-09-17 20:52:08 UTC (rev 6101) @@ -1270,3 +1270,429 @@ for k in ('Rectangle', 'Circle', 'RegularPolygon', 'Polygon', 'Wedge', 'Arrow', 'FancyArrow', 'YAArrow', 'CirclePolygon', 'Ellipse', 'Arc'): artist.kwdocd[k] = patchdoc + + + + + + + +class BboxTransmuterBase(object): + """ + Bbox Transmuter Base class + + BBoxTransmuterBase and its derivatives are used to make a fancy box + around a given rectangle. The __call__ method returns the Path of + the fancy box. This class is not an artist and actual drawing of the + fancy box is done by the FancyBboxPatch class. + + """ + + # The derived classes are required to be able to be initialized + # w/o arguments, i.e., all its argument (except self) must have + # the default values. + + def __init__(self): + super(BboxTransmuterBase, self).__init__() + + + + + def transmute(self, x0, y0, width, height, mutation_size): + """ + The transmute method is a very core of the BboxTransmuter class + and must be overriden in the subclasses. It receives the + location and size of the rectangle, and the mutation_size, with + which the amound padding and etc. will be scaled. It returns a + Path instance. + """ + raise NotImplementedError('Derived must override') + + + + def __call__(self, x0, y0, width, height, mutation_size, + aspect_ratio=1.): + """ + The __call__ method a thin wrapper around the transmute method + and take care of the aspect. + """ + if aspect_ratio is not None: + # Squeeze the given height by the aspect_ratio + y0, height = y0/aspect_ratio, height/aspect_ratio + # call transmute method with squeezed height. + path = self.transmute(x0, y0, width, height, mutation_size) + vertices, codes = path.vertices, path.codes + # Restore the height + vertices[:,1] = vertices[:,1] * aspect_ratio + return Path(vertices, codes) + else: + return self.transmute(x0, y0, width, height, mutation_size) + + + +class SquareBoxTransmuter(BboxTransmuterBase): + """ + Simple square box. + + 'pad' :an amount of padding. + """ + + def __init__(self, pad=0.3): + self.pad = pad + super(SquareBoxTransmuter, self).__init__() + + def transmute(self, x0, y0, width, height, mutation_size): + + # padding + pad = mutation_size * self.pad + + # width and height with padding added. + width, height = width + 2.*pad, \ + height + 2.*pad, + + # boundary of the padded box + x0, y0 = x0-pad, y0-pad, + x1, y1 = x0+width, y0 + height + + cp = [(x0, y0), (x1, y0), (x1, y1), (x0, y1), + (x0, y0), (x0, y0)] + + com = [Path.MOVETO, + Path.LINETO, + Path.LINETO, + Path.LINETO, + Path.LINETO, + Path.CLOSEPOLY] + + path = Path(cp, com) + + return path + + +class RoundBoxTransmuter(BboxTransmuterBase): + """ + A box with round corners. + """ + + def __init__(self, pad=0.3, rounding_size=None): + self.pad = pad + self.rounding_size = rounding_size + BboxTransmuterBase.__init__(self) + + def transmute(self, x0, y0, width, height, mutation_size): + + # padding + pad = mutation_size * self.pad + + # size of the roudning corner + if self.rounding_size: + dr = mutation_size * self.rounding_size + else: + dr = pad + + width, height = width + 2.*pad, \ + height + 2.*pad, + + + x0, y0 = x0-pad, y0-pad, + x1, y1 = x0+width, y0 + height + + # Round corners are implemented as quadratic bezier. eg. + # [(x0, y0-dr), (x0, y0), (x0+dr, y0)] for lower left corner. + cp = [(x0+dr, y0), + (x1-dr, y0), + (x1, y0), (x1, y0+dr), + (x1, y1-dr), + (x1, y1), (x1-dr, y1), + (x0+dr, y1), + (x0, y1), (x0, y1-dr), + (x0, y0+dr), + (x0, y0), (x0+dr, y0), + (x0+dr, y0)] + + com = [Path.MOVETO, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.LINETO, + Path.CURVE3, Path.CURVE3, + Path.CLOSEPOLY] + + path = Path(cp, com) + + return path + + + +def _list_available_boxstyles(transmuters): + """ a helper function of the FancyBboxPatch to list the available + box styles. It inspects the arguments of the __init__ methods of + each classes and report them + """ + import inspect + s = [] + for name, cls in transmuters.items(): + args, varargs, varkw, defaults = inspect.getargspec(cls.__init__) + args_string = ["%s=%s" % (argname, str(argdefault)) \ + for argname, argdefault in zip(args[1:], defaults)] + s.append(",".join([name]+args_string)) + return s + + + + + +class FancyBboxPatch(Patch): + """ + Draw a fancy box around a rectangle with lower left at *xy*=(*x*, + *y*) with specified width and height. + + FancyBboxPatch class is similar to Rectangle class, but it draws a + fancy box around the rectangle. The transfomation of the rectangle + box to the fancy box is delgated to the BoxTransmuterBase and its + derived classes. The "boxstyle" argument determins what kind of + fancy box will be drawn. In other words, it selects the + BboxTransmuter class to use, and sets optional attributes. A + custom BboxTransmuter can be used with bbox_transmuter argument + (should be an instance, not a class). mutation_scale determines + the overall size of the mutation (by which I mean the + transformation of the rectangle to the fancy path) and the + mutation_aspect determines the aspect-ratio of the mutation. + + """ + + _fancy_bbox_transmuters = {"square":SquareBoxTransmuter, + "round":RoundBoxTransmuter, + } + + def __str__(self): + return self.__class__.__name__ \ + + "FancyBboxPatch(%g,%g;%gx%g)" % (self._x, self._y, self._width, self._height) + + def __init__(self, xy, width, height, + boxstyle="round", + bbox_transmuter=None, + mutation_scale=1., + mutation_aspect=None, + **kwargs): + """ + *xy*=lower left corner + *width*, *height* + + The *boxstyle* describes how the fancy box will be drawn. It + should be one of the available boxstyle names, with optional + comma-separated attributes. These attributes are meant to be + scaled with the *mutation_scale*. Following box styles are + available. + + %(AvailableBoxstyles)s + + The boxstyle name can be "custom", in which case the + bbox_transmuter needs to be set, which should be an instance + of BboxTransmuterBase (or its derived). + + *mutation_scale* : a value with which attributes of boxstyle + (e.g., pad) will be scaled. default=1. + + *mutation_aspect* : The height of the rectangle will be + squeezed by this value before the mutation and the mutated + box will be stretched by the inverse of it. default=None. + + Valid kwargs are: + %(Patch)s + """ + + Patch.__init__(self, **kwargs) + + self._x = xy[0] + self._y = xy[1] + self._width = width + self._height = height + + if boxstyle == "custom": + if bbox_transmuter is None: + raise ValueError("bbox_transmuter argument is needed with custom boxstyle") + self._bbox_transmuter = bbox_transmuter + else: + self.set_boxstyle(boxstyle) + + self._mutation_scale=mutation_scale + self._mutation_aspect=mutation_aspect + + + kwdoc = dict() + kwdoc["AvailableBoxstyles"]="\n".join([" - " + l \ + for l in _list_available_boxstyles(_fancy_bbox_transmuters)]) + kwdoc.update(artist.kwdocd) + __init__.__doc__ = cbook.dedent(__init__.__doc__) % kwdoc + del kwdoc + + def list_available_boxstyles(cls): + return _list_available_boxstyles(cls._fancy_bbox_transmuters) + + + def set_boxstyle(self, boxstyle=None, **kw): + """ + Set the box style. + + *boxstyle* can be a string with boxstyle name with optional + comma-separated attributes. Alternatively, the attrs can + be probided as kewords. + + set_boxstyle("round,pad=0.2") + set_boxstyle("round", pad=0.2) + + Olf attrs simply are forgotten. + + Without argument (or with boxstyle=None), it prints out + available box styles. + """ + + if boxstyle==None: + # print out available boxstyles and return. + print " Following box styles are available." + for l in self.list_available_boxstyles(): + print " - " + l + return + + # parse the boxstyle descrption (e.g. "round,pad=0.3") + bs_list = boxstyle.replace(" ","").split(",") + boxstyle_name = bs_list[0] + try: + bbox_transmuter_cls = self._fancy_bbox_transmuters[boxstyle_name] + except KeyError: + raise ValueError("Unknown Boxstyle : %s" % boxstyle_name) + try: + boxstyle_args_pair = [bs.split("=") for bs in bs_list[1:]] + boxstyle_args = dict([(k, float(v)) for k, v in boxstyle_args_pair]) + except ValueError: + raise ValueError("Incorrect Boxstyle argument : %s" % boxstyle) + + boxstyle_args.update(kw) + self._bbox_transmuter = bbox_transmuter_cls(**boxstyle_args) + + + def set_mutation_scale(self, scale): + """ + Set the mutation scale. + + ACCEPTS: float + """ + self._mutation_scale=scale + + def get_mutation_scale(self): + """ + Return the mutation scale. + """ + return self._mutation_scale + + def set_mutation_aspect(self, aspect): + """ + Set the aspect ratio of the bbox mutation. + + ACCEPTS: float + """ + self._mutation_aspect=aspect + + def get_mutation_aspect(self): + """ + Return the aspect ratio of the bbox mutation. + """ + return self._mutation_aspect + + def set_bbox_transmuter(self, bbox_transmuter): + """ + Set the transmuter object + + ACCEPTS: BboxTransmuterBase (or its derivatives) instance + """ + self._bbox_transmuter = bbox_transmuter + + def get_bbox_transmuter(self): + "Return the current transmuter object" + return self._bbox_transmuter + + def get_path(self): + """ + Return the mutated path of the rectangle + """ + + _path = self.get_bbox_transmuter()(self._x, self._y, + self._width, self._height, + self.get_mutation_scale(), + self.get_mutation_aspect()) + return _path + + + # Followong methods are borrowed from the Rectangle class. + + def get_x(self): + "Return the left coord of the rectangle" + return self._x + + def get_y(self): + "Return the bottom coord of the rectangle" + return self._y + + def get_width(self): + "Return the width of the rectangle" + return self._width + + def get_height(self): + "Return the height of the rectangle" + return self._height + + def set_x(self, x): + """ + Set the left coord of the rectangle + + ACCEPTS: float + """ + self._x = x + + def set_y(self, y): + """ + Set the bottom coord of the rectangle + + ACCEPTS: float + """ + self._y = y + + def set_width(self, w): + """ + Set the width rectangle + + ACCEPTS: float + """ + self._width = w + + def set_height(self, h): + """ + Set the width rectangle + + ACCEPTS: float + """ + self._height = h + + def set_bounds(self, *args): + """ + Set the bounds of the rectangle: l,b,w,h + + ACCEPTS: (left, bottom, width, height) + """ + if len(args)==0: + l,b,w,h = args[0] + else: + l,b,w,h = args + self._x = l + self._y = b + self._width = w + self._height = h + + + def get_bbox(self): + return transforms.Bbox.from_bounds(self._x, self._y, self._width, self._height) + Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2008-09-17 15:47:02 UTC (rev 6100) +++ trunk/matplotlib/lib/matplotlib/text.py 2008-09-17 20:52:08 UTC (rev 6101) @@ -12,7 +12,8 @@ from artist import Artist from cbook import is_string_like, maxdict from font_manager import FontProperties -from patches import bbox_artist, YAArrow +from patches import bbox_artist, YAArrow, FancyBboxPatch +import transforms as mtransforms from transforms import Affine2D, Bbox from lines import Line2D @@ -77,6 +78,50 @@ ========================== ========================================================================= """ + + + +# TODO : This function may move into the Text class as a method. As a +# matter of fact, The information from the _get_textbox function +# should be available during the Text._get_layout() call, which is +# called within the _get_textbox. So, it would better to move this +# function as a method with some refactoring of _get_layout method. + +def _get_textbox(text, renderer): + """ + figure out the bounding box of the text. Unlike get_extents() + method, The bbox size of the text before the rotation is + calculated. + """ + + projected_xs = [] + projected_ys = [] + + theta = text.get_rotation()/180.*math.pi + tr = mtransforms.Affine2D().rotate(-theta) + + for t, wh, x, y in text._get_layout(renderer)[1]: + w, h = wh + + + xt1, yt1 = tr.transform_point((x, y)) + xt2, yt2 = xt1+w, yt1+h + + projected_xs.extend([xt1, xt2]) + projected_ys.extend([yt1, yt2]) + + + xt_box, yt_box = min(projected_xs), min(projected_ys) + w_box, h_box = max(projected_xs) - xt_box, max(projected_ys) - yt_box + + tr = mtransforms.Affine2D().rotate(theta) + + x_box, y_box = tr.transform_point((xt_box, yt_box)) + + return x_box, y_box, w_box, h_box + + + class Text(Artist): """ Handle storing and drawing of text in window or data coordinates @@ -121,6 +166,7 @@ self._rotation = rotation self._fontproperties = fontproperties self._bbox = None + self._bbox_patch = None # a FanceBboxPatch instance self._renderer = None if linespacing is None: linespacing = 1.2 # Maybe use rcParam later. @@ -271,15 +317,65 @@ def set_bbox(self, rectprops): """ - Draw a bounding box around self. rect props are any settable + Draw a bounding box around self. rectprops are any settable properties for a rectangle, eg facecolor='red', alpha=0.5. t.set_bbox(dict(facecolor='red', alpha=0.5)) - ACCEPTS: rectangle prop dict plus key 'pad' which is a pad in points + If rectprops has "boxstyle" key. A FancyBboxPatch + is initiallized with rectprops and will be drawn. The mutation + scale of the FancyBboxPath is set to the fontsize. + + ACCEPTS: rectangle prop dict plus key 'pad' which is a pad in + points. If "boxstyle" key exists, the input dictionary should + be a valid input for the FancyBboxPatch class. + """ - self._bbox = rectprops + # The self._bbox_patch object is created only if rectprops has + # boxstyle key. Otherwise, self._bbox will be set to the + # rectprops and the bbox will be drawn using bbox_artist + # function. This is to keep the backward compatibility. + + if rectprops is not None and rectprops.has_key("boxstyle"): + props = rectprops.copy() + boxstyle = props.pop("boxstyle") + bbox_transmuter = props.pop("bbox_transmuter", None) + + self._bbox_patch = FancyBboxPatch((0., 0.), + 1., 1., + boxstyle=boxstyle, + bbox_transmuter=bbox_transmuter, + transform=mtransforms.IdentityTransform(), + **props) + self._bbox = None + else: + self._bbox_patch = None + self._bbox = rectprops + + + def get_bbox_patch(self): + """ + Retrun the bbox Patch object. Returns None if the the + FancyBboxPatch is not made. + """ + return self._bbox_patch + + + def _draw_bbox(self, renderer, posx, posy): + """ Update the location and the size of the bbox, and draw. + """ + x_box, y_box, w_box, h_box = _get_textbox(self, renderer) + self._bbox_patch.set_bounds(0., 0., + w_box, h_box) + theta = self.get_rotation()/180.*math.pi + tr = mtransforms.Affine2D().rotate(theta) + tr = tr.translate(posx+x_box, posy+y_box) + self._bbox_patch.set_transform(tr) + self._bbox_patch.set_mutation_scale(self.get_size()) + self._bbox_patch.draw(renderer) + + def draw(self, renderer): #return if renderer is not None: @@ -287,6 +383,22 @@ if not self.get_visible(): return if self._text=='': return + bbox, info = self._get_layout(renderer) + trans = self.get_transform() + + + # don't use self.get_position here, which refers to text position + # in Text, and dash position in TextWithDash: + posx = float(self.convert_xunits(self._x)) + posy = float(self.convert_yunits(self._y)) + + posx, posy = trans.transform_point((posx, posy)) + canvasw, canvash = renderer.get_canvas_width_height() + + # draw the FancyBboxPatch + if self._bbox_patch: + self._draw_bbox(renderer, posx, posy) + gc = renderer.new_gc() gc.set_foreground(self._color) gc.set_alpha(self._alpha) @@ -297,17 +409,8 @@ bbox_artist(self, renderer, self._bbox) angle = self.get_rotation() - bbox, info = self._get_layout(renderer) - trans = self.get_transform() - # don't use self.get_position here, which refers to text position - # in Text, and dash position in TextWithDash: - posx = float(self.convert_xunits(self._x)) - posy = float(self.convert_yunits(self._y)) - posx, posy = trans.transform_point((posx, posy)) - canvasw, canvash = renderer.get_canvas_width_height() - if rcParams['text.usetex']: for line, wh, x, y in info: x = x + posx @@ -401,7 +504,7 @@ return (x, y, self._text, self._color, self._verticalalignment, self._horizontalalignment, hash(self._fontproperties), self._rotation, - self.figure.dpi, id(self._renderer), + self.figure.dpi, id(self._renderer), ) def get_text(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-09-23 18:23:05
|
Revision: 6116 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6116&view=rev Author: jdh2358 Date: 2008-09-23 18:22:54 +0000 (Tue, 23 Sep 2008) Log Message: ----------- moved nemerical methods back to mlab pending more comprehensive reorg Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/mlab.py Removed Paths: ------------- trunk/matplotlib/lib/matplotlib/numerical_methods.py Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2008-09-20 03:21:19 UTC (rev 6115) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2008-09-23 18:22:54 UTC (rev 6116) @@ -2489,3 +2489,295 @@ zo = np.ma.masked_where(np.isnan(zo),zo) return zo griddata._reported = False + +################################################## +# Linear interpolation algorithms +################################################## +def less_simple_linear_interpolation( x, y, xi, extrap=False ): + """ + This function provides simple (but somewhat less so than + cbook.simple_linear_interpolation) linear interpolation. + simple_linear_interpolation will give a list of point between a + start and an end, while this does true linear interpolation at an + arbitrary set of points. + + This is very inefficient linear interpolation meant to be used + only for a small number of points in relatively non-intensive use + cases. For real linear interpolation, use scipy. + """ + if cbook.is_scalar(xi): xi = [xi] + + x = np.asarray(x) + y = np.asarray(y) + xi = np.asarray(xi) + + s = list(y.shape) + s[0] = len(xi) + yi = np.tile( np.nan, s ) + + for ii,xx in enumerate(xi): + bb = x == xx + if np.any(bb): + jj, = np.nonzero(bb) + yi[ii] = y[jj[0]] + elif xx<x[0]: + if extrap: + yi[ii] = y[0] + elif xx>x[-1]: + if extrap: + yi[ii] = y[-1] + else: + jj, = np.nonzero(x<xx) + jj = max(jj) + + yi[ii] = y[jj] + (xx-x[jj])/(x[jj+1]-x[jj]) * (y[jj+1]-y[jj]) + + return yi + +def slopes(x,y): + """ + SLOPES calculate the slope y'(x) Given data vectors X and Y SLOPES + calculates Y'(X), i.e the slope of a curve Y(X). The slope is + estimated using the slope obtained from that of a parabola through + any three consecutive points. + + This method should be superior to that described in the appendix + of A CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russel + W. Stineman (Creative Computing July 1980) in at least one aspect: + + Circles for interpolation demand a known aspect ratio between x- + and y-values. For many functions, however, the abscissa are given + in different dimensions, so an aspect ratio is completely + arbitrary. + + The parabola method gives very similar results to the circle + method for most regular cases but behaves much better in special + cases + + Norbert Nemec, Institute of Theoretical Physics, University or + Regensburg, April 2006 Norbert.Nemec at physik.uni-regensburg.de + + (inspired by a original implementation by Halldor Bjornsson, + Icelandic Meteorological Office, March 2006 halldor at vedur.is) + """ + # Cast key variables as float. + x=np.asarray(x, np.float_) + y=np.asarray(y, np.float_) + + yp=np.zeros(y.shape, np.float_) + + dx=x[1:] - x[:-1] + dy=y[1:] - y[:-1] + dydx = dy/dx + yp[1:-1] = (dydx[:-1] * dx[1:] + dydx[1:] * dx[:-1])/(dx[1:] + dx[:-1]) + yp[0] = 2.0 * dy[0]/dx[0] - yp[1] + yp[-1] = 2.0 * dy[-1]/dx[-1] - yp[-2] + return yp + + +def stineman_interp(xi,x,y,yp=None): + """ + STINEMAN_INTERP Well behaved data interpolation. Given data + vectors X and Y, the slope vector YP and a new abscissa vector XI + the function stineman_interp(xi,x,y,yp) uses Stineman + interpolation to calculate a vector YI corresponding to XI. + + Here's an example that generates a coarse sine curve, then + interpolates over a finer abscissa: + + x = linspace(0,2*pi,20); y = sin(x); yp = cos(x) + xi = linspace(0,2*pi,40); + yi = stineman_interp(xi,x,y,yp); + plot(x,y,'o',xi,yi) + + The interpolation method is described in the article A + CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russell + W. Stineman. The article appeared in the July 1980 issue of + Creative Computing with a note from the editor stating that while + they were + + not an academic journal but once in a while something serious + and original comes in adding that this was + "apparently a real solution" to a well known problem. + + For yp=None, the routine automatically determines the slopes using + the "slopes" routine. + + X is assumed to be sorted in increasing order + + For values xi[j] < x[0] or xi[j] > x[-1], the routine tries a + extrapolation. The relevance of the data obtained from this, of + course, questionable... + + original implementation by Halldor Bjornsson, Icelandic + Meteorolocial Office, March 2006 halldor at vedur.is + + completely reworked and optimized for Python by Norbert Nemec, + Institute of Theoretical Physics, University or Regensburg, April + 2006 Norbert.Nemec at physik.uni-regensburg.de + + """ + + # Cast key variables as float. + x=np.asarray(x, np.float_) + y=np.asarray(y, np.float_) + assert x.shape == y.shape + N=len(y) + + if yp is None: + yp = slopes(x,y) + else: + yp=np.asarray(yp, np.float_) + + xi=np.asarray(xi, np.float_) + yi=np.zeros(xi.shape, np.float_) + + # calculate linear slopes + dx = x[1:] - x[:-1] + dy = y[1:] - y[:-1] + s = dy/dx #note length of s is N-1 so last element is #N-2 + + # find the segment each xi is in + # this line actually is the key to the efficiency of this implementation + idx = np.searchsorted(x[1:-1], xi) + + # now we have generally: x[idx[j]] <= xi[j] <= x[idx[j]+1] + # except at the boundaries, where it may be that xi[j] < x[0] or xi[j] > x[-1] + + # the y-values that would come out from a linear interpolation: + sidx = s.take(idx) + xidx = x.take(idx) + yidx = y.take(idx) + xidxp1 = x.take(idx+1) + yo = yidx + sidx * (xi - xidx) + + # the difference that comes when using the slopes given in yp + dy1 = (yp.take(idx)- sidx) * (xi - xidx) # using the yp slope of the left point + dy2 = (yp.take(idx+1)-sidx) * (xi - xidxp1) # using the yp slope of the right point + + dy1dy2 = dy1*dy2 + # The following is optimized for Python. The solution actually + # does more calculations than necessary but exploiting the power + # of numpy, this is far more efficient than coding a loop by hand + # in Python + yi = yo + dy1dy2 * np.choose(np.array(np.sign(dy1dy2), np.int32)+1, + ((2*xi-xidx-xidxp1)/((dy1-dy2)*(xidxp1-xidx)), + 0.0, + 1/(dy1+dy2),)) + return yi + +################################################## +# Code related to things in and around polygons +################################################## +def inside_poly(points, verts): + """ + points is a sequence of x,y points + verts is a sequence of x,y vertices of a poygon + + return value is a sequence of indices into points for the points + that are inside the polygon + """ + res, = np.nonzero(nxutils.points_inside_poly(points, verts)) + return res + +def poly_below(xmin, xs, ys): + """ + given a sequence of xs and ys, return the vertices of a polygon + that has a horzontal base at xmin and an upper bound at the ys. + xmin is a scalar. + + intended for use with Axes.fill, eg + xv, yv = poly_below(0, x, y) + ax.fill(xv, yv) + """ + xs = np.asarray(xs) + ys = np.asarray(ys) + Nx = len(xs) + Ny = len(ys) + assert(Nx==Ny) + x = xmin*np.ones(2*Nx) + y = np.ones(2*Nx) + x[:Nx] = xs + y[:Nx] = ys + y[Nx:] = ys[::-1] + return x, y + + +def poly_between(x, ylower, yupper): + """ + given a sequence of x, ylower and yupper, return the polygon that + fills the regions between them. ylower or yupper can be scalar or + iterable. If they are iterable, they must be equal in length to x + + return value is x, y arrays for use with Axes.fill + """ + Nx = len(x) + if not cbook.iterable(ylower): + ylower = ylower*np.ones(Nx) + + if not cbook.iterable(yupper): + yupper = yupper*np.ones(Nx) + + x = np.concatenate( (x, x[::-1]) ) + y = np.concatenate( (yupper, ylower[::-1]) ) + return x,y + +def is_closed_polygon(X): + """ + Tests whether first and last object in a sequence are the same. These are + presumably coordinates on a polygonal curve, in which case this function + tests if that curve is closed. + + """ + return np.all(X[0] == X[-1]) + +################################################## +# Vector and path length geometry calculations +################################################## +def vector_lengths( X, P=2., axis=None ): + """ + Finds the length of a set of vectors in n dimensions. This is + like the numpy norm function for vectors, but has the ability to + work over a particular axis of the supplied array or matrix. + + Computes (sum((x_i)^P))^(1/P) for each {x_i} being the elements of X along + the given axis. If *axis* is *None*, compute over all elements of X. + """ + X = np.asarray(X) + return (np.sum(X**(P),axis=axis))**(1./P) + +def distances_along_curve( X ): + """ + Computes the distance between a set of successive points in N dimensions. + + where X is an MxN array or matrix. The distances between successive rows + is computed. Distance is the standard Euclidean distance. + """ + X = np.diff( X, axis=0 ) + return vector_lengths(X,axis=1) + +def path_length(X): + """ + Computes the distance travelled along a polygonal curve in N dimensions. + + + where X is an MxN array or matrix. Returns an array of length M consisting + of the distance along the curve at each point (i.e., the rows of X). + """ + X = distances_along_curve(X) + return np.concatenate( (np.zeros(1), np.cumsum(X)) ) + +def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y): + """ + Converts a quadratic Bezier curve to a cubic approximation. + + The inputs are the x and y coordinates of the three control points + of a quadratic curve, and the output is a tuple of x and y + coordinates of the four control points of the cubic curve. + """ + # c0x, c0y = q0x, q0y + c1x, c1y = q0x + 2./3. * (q1x - q0x), q0y + 2./3. * (q1y - q0y) + c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y) + # c3x, c3y = q2x, q2y + return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y + Deleted: trunk/matplotlib/lib/matplotlib/numerical_methods.py =================================================================== --- trunk/matplotlib/lib/matplotlib/numerical_methods.py 2008-09-20 03:21:19 UTC (rev 6115) +++ trunk/matplotlib/lib/matplotlib/numerical_methods.py 2008-09-23 18:22:54 UTC (rev 6116) @@ -1,299 +0,0 @@ -""" -A collection of utility functions that do various numerical or geometrical -manipulations. -""" -import numpy as np -from numpy import ma -import matplotlib.cbook as cbook - -################################################## -# Linear interpolation algorithms -################################################## -def less_simple_linear_interpolation( x, y, xi, extrap=False ): - """ - This function provides simple (but somewhat less so than - cbook.simple_linear_interpolation) linear interpolation. - simple_linear_interpolation will give a list of point between a - start and an end, while this does true linear interpolation at an - arbitrary set of points. - - This is very inefficient linear interpolation meant to be used - only for a small number of points in relatively non-intensive use - cases. For real linear interpolation, use scipy. - """ - if cbook.is_scalar(xi): xi = [xi] - - x = np.asarray(x) - y = np.asarray(y) - xi = np.asarray(xi) - - s = list(y.shape) - s[0] = len(xi) - yi = np.tile( np.nan, s ) - - for ii,xx in enumerate(xi): - bb = x == xx - if np.any(bb): - jj, = np.nonzero(bb) - yi[ii] = y[jj[0]] - elif xx<x[0]: - if extrap: - yi[ii] = y[0] - elif xx>x[-1]: - if extrap: - yi[ii] = y[-1] - else: - jj, = np.nonzero(x<xx) - jj = max(jj) - - yi[ii] = y[jj] + (xx-x[jj])/(x[jj+1]-x[jj]) * (y[jj+1]-y[jj]) - - return yi - -def slopes(x,y): - """ - SLOPES calculate the slope y'(x) Given data vectors X and Y SLOPES - calculates Y'(X), i.e the slope of a curve Y(X). The slope is - estimated using the slope obtained from that of a parabola through - any three consecutive points. - - This method should be superior to that described in the appendix - of A CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russel - W. Stineman (Creative Computing July 1980) in at least one aspect: - - Circles for interpolation demand a known aspect ratio between x- - and y-values. For many functions, however, the abscissa are given - in different dimensions, so an aspect ratio is completely - arbitrary. - - The parabola method gives very similar results to the circle - method for most regular cases but behaves much better in special - cases - - Norbert Nemec, Institute of Theoretical Physics, University or - Regensburg, April 2006 Norbert.Nemec at physik.uni-regensburg.de - - (inspired by a original implementation by Halldor Bjornsson, - Icelandic Meteorological Office, March 2006 halldor at vedur.is) - """ - # Cast key variables as float. - x=np.asarray(x, np.float_) - y=np.asarray(y, np.float_) - - yp=np.zeros(y.shape, np.float_) - - dx=x[1:] - x[:-1] - dy=y[1:] - y[:-1] - dydx = dy/dx - yp[1:-1] = (dydx[:-1] * dx[1:] + dydx[1:] * dx[:-1])/(dx[1:] + dx[:-1]) - yp[0] = 2.0 * dy[0]/dx[0] - yp[1] - yp[-1] = 2.0 * dy[-1]/dx[-1] - yp[-2] - return yp - - -def stineman_interp(xi,x,y,yp=None): - """ - STINEMAN_INTERP Well behaved data interpolation. Given data - vectors X and Y, the slope vector YP and a new abscissa vector XI - the function stineman_interp(xi,x,y,yp) uses Stineman - interpolation to calculate a vector YI corresponding to XI. - - Here's an example that generates a coarse sine curve, then - interpolates over a finer abscissa: - - x = linspace(0,2*pi,20); y = sin(x); yp = cos(x) - xi = linspace(0,2*pi,40); - yi = stineman_interp(xi,x,y,yp); - plot(x,y,'o',xi,yi) - - The interpolation method is described in the article A - CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russell - W. Stineman. The article appeared in the July 1980 issue of - Creative Computing with a note from the editor stating that while - they were - - not an academic journal but once in a while something serious - and original comes in adding that this was - "apparently a real solution" to a well known problem. - - For yp=None, the routine automatically determines the slopes using - the "slopes" routine. - - X is assumed to be sorted in increasing order - - For values xi[j] < x[0] or xi[j] > x[-1], the routine tries a - extrapolation. The relevance of the data obtained from this, of - course, questionable... - - original implementation by Halldor Bjornsson, Icelandic - Meteorolocial Office, March 2006 halldor at vedur.is - - completely reworked and optimized for Python by Norbert Nemec, - Institute of Theoretical Physics, University or Regensburg, April - 2006 Norbert.Nemec at physik.uni-regensburg.de - - """ - - # Cast key variables as float. - x=np.asarray(x, np.float_) - y=np.asarray(y, np.float_) - assert x.shape == y.shape - N=len(y) - - if yp is None: - yp = slopes(x,y) - else: - yp=np.asarray(yp, np.float_) - - xi=np.asarray(xi, np.float_) - yi=np.zeros(xi.shape, np.float_) - - # calculate linear slopes - dx = x[1:] - x[:-1] - dy = y[1:] - y[:-1] - s = dy/dx #note length of s is N-1 so last element is #N-2 - - # find the segment each xi is in - # this line actually is the key to the efficiency of this implementation - idx = np.searchsorted(x[1:-1], xi) - - # now we have generally: x[idx[j]] <= xi[j] <= x[idx[j]+1] - # except at the boundaries, where it may be that xi[j] < x[0] or xi[j] > x[-1] - - # the y-values that would come out from a linear interpolation: - sidx = s.take(idx) - xidx = x.take(idx) - yidx = y.take(idx) - xidxp1 = x.take(idx+1) - yo = yidx + sidx * (xi - xidx) - - # the difference that comes when using the slopes given in yp - dy1 = (yp.take(idx)- sidx) * (xi - xidx) # using the yp slope of the left point - dy2 = (yp.take(idx+1)-sidx) * (xi - xidxp1) # using the yp slope of the right point - - dy1dy2 = dy1*dy2 - # The following is optimized for Python. The solution actually - # does more calculations than necessary but exploiting the power - # of numpy, this is far more efficient than coding a loop by hand - # in Python - yi = yo + dy1dy2 * np.choose(np.array(np.sign(dy1dy2), np.int32)+1, - ((2*xi-xidx-xidxp1)/((dy1-dy2)*(xidxp1-xidx)), - 0.0, - 1/(dy1+dy2),)) - return yi - -################################################## -# Code related to things in and around polygons -################################################## -def inside_poly(points, verts): - """ - points is a sequence of x,y points - verts is a sequence of x,y vertices of a poygon - - return value is a sequence of indices into points for the points - that are inside the polygon - """ - res, = np.nonzero(nxutils.points_inside_poly(points, verts)) - return res - -def poly_below(xmin, xs, ys): - """ - given a sequence of xs and ys, return the vertices of a polygon - that has a horzontal base at xmin and an upper bound at the ys. - xmin is a scalar. - - intended for use with Axes.fill, eg - xv, yv = poly_below(0, x, y) - ax.fill(xv, yv) - """ - xs = np.asarray(xs) - ys = np.asarray(ys) - Nx = len(xs) - Ny = len(ys) - assert(Nx==Ny) - x = xmin*np.ones(2*Nx) - y = np.ones(2*Nx) - x[:Nx] = xs - y[:Nx] = ys - y[Nx:] = ys[::-1] - return x, y - - -def poly_between(x, ylower, yupper): - """ - given a sequence of x, ylower and yupper, return the polygon that - fills the regions between them. ylower or yupper can be scalar or - iterable. If they are iterable, they must be equal in length to x - - return value is x, y arrays for use with Axes.fill - """ - Nx = len(x) - if not cbook.iterable(ylower): - ylower = ylower*np.ones(Nx) - - if not cbook.iterable(yupper): - yupper = yupper*np.ones(Nx) - - x = np.concatenate( (x, x[::-1]) ) - y = np.concatenate( (yupper, ylower[::-1]) ) - return x,y - -def is_closed_polygon(X): - """ - Tests whether first and last object in a sequence are the same. These are - presumably coordinates on a polygonal curve, in which case this function - tests if that curve is closed. - - """ - return np.all(X[0] == X[-1]) - -################################################## -# Vector and path length geometry calculations -################################################## -def vector_lengths( X, P=2., axis=None ): - """ - Finds the length of a set of vectors in n dimensions. This is - like the numpy norm function for vectors, but has the ability to - work over a particular axis of the supplied array or matrix. - - Computes (sum((x_i)^P))^(1/P) for each {x_i} being the elements of X along - the given axis. If *axis* is *None*, compute over all elements of X. - """ - X = np.asarray(X) - return (np.sum(X**(P),axis=axis))**(1./P) - -def distances_along_curve( X ): - """ - Computes the distance between a set of successive points in N dimensions. - - where X is an MxN array or matrix. The distances between successive rows - is computed. Distance is the standard Euclidean distance. - """ - X = np.diff( X, axis=0 ) - return vector_lengths(X,axis=1) - -def path_length(X): - """ - Computes the distance travelled along a polygonal curve in N dimensions. - - - where X is an MxN array or matrix. Returns an array of length M consisting - of the distance along the curve at each point (i.e., the rows of X). - """ - X = distances_along_curve(X) - return np.concatenate( (np.zeros(1), np.cumsum(X)) ) - -def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y): - """ - Converts a quadratic Bezier curve to a cubic approximation. - - The inputs are the x and y coordinates of the three control points - of a quadratic curve, and the output is a tuple of x and y - coordinates of the four control points of the cubic curve. - """ - # c0x, c0y = q0x, q0y - c1x, c1y = q0x + 2./3. * (q1x - q0x), q0y + 2./3. * (q1y - q0y) - c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y) - # c3x, c3y = q2x, q2y - return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2008-09-23 18:26:26
|
Revision: 6117 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6117&view=rev Author: jdh2358 Date: 2008-09-23 18:25:27 +0000 (Tue, 23 Sep 2008) Log Message: ----------- fixed numerical methods imports -> mlab Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/contour.py trunk/matplotlib/lib/matplotlib/pylab.py Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2008-09-23 18:22:54 UTC (rev 6116) +++ trunk/matplotlib/lib/matplotlib/contour.py 2008-09-23 18:25:27 UTC (rev 6117) @@ -16,7 +16,7 @@ import matplotlib.font_manager as font_manager import matplotlib.text as text import matplotlib.cbook as cbook -import matplotlib.numerical_methods as numerical_methods +import matplotlib.mlab as mlab # Import needed for adding manual selection capability to clabel from matplotlib.blocking_input import BlockingContourLabeler @@ -335,7 +335,7 @@ not empty (lc defaults to the empty list if None). *spacing* is the space around the label in pixels to leave empty. - Do both of these tasks at once to avoid calling numerical_methods.path_length + Do both of these tasks at once to avoid calling mlab.path_length multiple times, which is relatively costly. The method used here involves calculating the path length @@ -349,7 +349,7 @@ hlw = lw/2.0 # Check if closed and, if so, rotate contour so label is at edge - closed = numerical_methods.is_closed_polygon(slc) + closed = mlab.is_closed_polygon(slc) if closed: slc = np.r_[ slc[ind:-1], slc[:ind+1] ] @@ -359,7 +359,7 @@ ind = 0 # Path length in pixel space - pl = numerical_methods.path_length(slc) + pl = mlab.path_length(slc) pl = pl-pl[ind] # Use linear interpolation to get points around label @@ -369,7 +369,7 @@ else: dp = np.zeros_like(xi) - ll = numerical_methods.less_simple_linear_interpolation( pl, slc, dp+xi, + ll = mlab.less_simple_linear_interpolation( pl, slc, dp+xi, extrap=True ) # get vector in pixel space coordinates from one point to other @@ -395,16 +395,16 @@ xi = dp + xi + np.array([-spacing,spacing]) # Get indices near points of interest - I = numerical_methods.less_simple_linear_interpolation( + I = mlab.less_simple_linear_interpolation( pl, np.arange(len(pl)), xi, extrap=False ) # If those indices aren't beyond contour edge, find x,y if (not np.isnan(I[0])) and int(I[0])<>I[0]: - xy1 = numerical_methods.less_simple_linear_interpolation( + xy1 = mlab.less_simple_linear_interpolation( pl, lc, [ xi[0] ] ) if (not np.isnan(I[1])) and int(I[1])<>I[1]: - xy2 = numerical_methods.less_simple_linear_interpolation( + xy2 = mlab.less_simple_linear_interpolation( pl, lc, [ xi[1] ] ) # Make integer @@ -472,7 +472,7 @@ # zero in print_label and locate_label. Other than these # functions, this is not necessary and should probably be # eventually removed. - if numerical_methods.is_closed_polygon( lc ): + if mlab.is_closed_polygon( lc ): slc = np.r_[ slc0, slc0[1:2,:] ] else: slc = slc0 @@ -1009,12 +1009,12 @@ *linestyles*: [None | 'solid' | 'dashed' | 'dashdot' | 'dotted' ] If *linestyles* is *None*, the 'solid' is used. - + *linestyles* can also be an iterable of the above strings specifying a set of linestyles to be used. If this iterable is shorter than the number of contour levels it will be repeated as necessary. - + If contour is using a monochrome colormap and the contour level is less than 0, then the linestyle specified in ``contour.negative_linestyle`` in ``matplotlibrc`` Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2008-09-23 18:22:54 UTC (rev 6116) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2008-09-23 18:25:27 UTC (rev 6117) @@ -227,7 +227,7 @@ diagonal_matrix, base_repr, binary_repr, log2, ispower2,\ bivariate_normal, load, save -from matplotlib.numerical_methods import stineman_interp, slopes, \ +from matplotlib.mlab import stineman_interp, slopes, \ stineman_interp, inside_poly, poly_below, poly_between, \ is_closed_polygon, path_length, distances_along_curve, vector_lengths This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |