From: <ef...@us...> - 2010-04-20 19:02:00
|
Revision: 8249 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8249&view=rev Author: efiring Date: 2010-04-20 19:01:53 +0000 (Tue, 20 Apr 2010) Log Message: ----------- Add margins() method to Axes, function to pyplot Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/boilerplate.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/pyplot.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-04-20 17:38:56 UTC (rev 8248) +++ trunk/matplotlib/CHANGELOG 2010-04-20 19:01:53 UTC (rev 8249) @@ -1,3 +1,5 @@ +2010-04-20 Added margins() Axes method and pyplot function. - EF + 2010-04-18 update the axes_grid documentation. -JJL 2010-04-18 Control MaxNLocator parameters after instantiation, Modified: trunk/matplotlib/boilerplate.py =================================================================== --- trunk/matplotlib/boilerplate.py 2010-04-20 17:38:56 UTC (rev 8248) +++ trunk/matplotlib/boilerplate.py 2010-04-20 19:01:53 UTC (rev 8249) @@ -103,6 +103,7 @@ 'annotate', 'ticklabel_format', 'locator_params', + 'margins', ) cmappable = { Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-04-20 17:38:56 UTC (rev 8248) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-04-20 19:01:53 UTC (rev 8249) @@ -836,6 +836,8 @@ self._autoscaleXon = True self._autoscaleYon = True + self._xmargin = 0 + self._ymargin = 0 self._update_transScale() # needed? self._get_lines = _process_plot_var_args(self) @@ -1605,6 +1607,83 @@ """ self._autoscaleYon = b + def set_xmargin(self, m): + """ + Set padding of X data limits prior to autoscaling. + + *m* times the data interval will be added to each + end of that interval before it is used in autoscaling. + + accepts: float in range 0 to 1 + """ + if m < 0 or m > 1: + raise ValueError("margin must be in range 0 to 1") + self._xmargin = m + + def set_ymargin(self, m): + """ + Set padding of Y data limits prior to autoscaling. + + *m* times the data interval will be added to each + end of that interval before it is used in autoscaling. + + accepts: float in range 0 to 1 + """ + if m < 0 or m > 1: + raise ValueError("margin must be in range 0 to 1") + self._ymargin = m + + + def margins(self, *args, **kw): + """ + Convenience method to set or retrieve autoscaling margins. + + signatures:: + + margins() + + returns xmargin, ymargin + + :: + + margins(margin, tight=True) + + margins(xmargin, ymargin, tight=True) + + margins(x=xmargin, y=ymargin, tight=True) + + All three forms above set the xmargin and ymargin parameters. + All keyword parameters are optional. A single argument + specifies both xmargin and ymargin. The *tight* parameter + is passed to :meth:`autoscale_view`, which is executed after + a margin is changed. + + Specifying any margin changes only the autoscaling; for example, + if *xmargin* is not zero, then *xmargin* times the X data + interval will be added to each end of that interval before + it is used in autoscaling. + + """ + if not args and not kw: + return self._ymargin, self._ymargin + + tight = kw.pop('tight', False) + mx = kw.pop('x', None) + my = kw.pop('y', None) + if len(args) == 1: + mx = my = args[0] + elif len(args) == 2: + mx, my = args + else: + raise ValueError("more than two arguments were supplied") + if mx is not None: + self.set_xmargin(mx) + if my is not None: + self.set_ymargin(my) + + self.autoscale_view(tight=tight, scalex=bool(mx), scaley=bool(my)) + + def set_rasterization_zorder(self, z): """ Set zorder value below which artists will be rasterized @@ -1631,11 +1710,21 @@ dl = [ax.dataLim for ax in xshared] bb = mtransforms.BboxBase.union(dl) x0, x1 = bb.intervalx + if self._xmargin > 0: + delta = (x1 - x0) * self._xmargin + x0 -= delta + x1 += delta + if scaley and self._autoscaleYon: yshared = self._shared_y_axes.get_siblings(self) dl = [ax.dataLim for ax in yshared] bb = mtransforms.BboxBase.union(dl) y0, y1 = bb.intervaly + if self._ymargin > 0: + delta = (y1 - y0) * self._ymargin + y0 -= delta + y1 += delta + if (tight or (len(self.images)>0 and len(self.lines)==0 and len(self.patches)==0)): @@ -1958,7 +2047,7 @@ of ticks and use tight bounds when plotting small subplots, for example:: - ax.set_locator_params(tight=True, nbins=4) + ax.locator_params(tight=True, nbins=4) Because the locator is involved in autoscaling, :meth:`autoscale_view` is called automatically after Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2010-04-20 17:38:56 UTC (rev 8248) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2010-04-20 19:01:53 UTC (rev 8249) @@ -2545,6 +2545,14 @@ # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost +...@do...py_dedent(Axes.margins) +def margins(*args, **kw): + ret = gca().margins(*args, **kw) + draw_if_interactive() + return ret + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost def autumn(): ''' set the default colormap to autumn and apply to current image if any. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2010-04-20 20:23:06
|
Revision: 8259 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8259&view=rev Author: ryanmay Date: 2010-04-20 20:23:00 +0000 (Tue, 20 Apr 2010) Log Message: ----------- Add example using new generic timer support and update ChangeLog. Modified Paths: -------------- trunk/matplotlib/CHANGELOG Added Paths: ----------- trunk/matplotlib/examples/event_handling/timers.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-04-20 20:02:38 UTC (rev 8258) +++ trunk/matplotlib/CHANGELOG 2010-04-20 20:23:00 UTC (rev 8259) @@ -1,3 +1,8 @@ +2010-04-20 Added generic support for connecting to a timer for events. This + adds TimerBase, TimerGTK, TimerQT, TimerWx, and TimerTk to + the backends and a new_timer() method to each backend's + canvas to allow ease of creating a new timer. - RM + 2010-04-20 Added margins() Axes method and pyplot function. - EF 2010-04-18 update the axes_grid documentation. -JJL Added: trunk/matplotlib/examples/event_handling/timers.py =================================================================== --- trunk/matplotlib/examples/event_handling/timers.py (rev 0) +++ trunk/matplotlib/examples/event_handling/timers.py 2010-04-20 20:23:00 UTC (rev 8259) @@ -0,0 +1,30 @@ +# Simple example of using general timer objects. This is used to update +# the time placed in the title of the figure. +import matplotlib.pyplot as plt +import numpy as np +from datetime import datetime + +def update_title(axes): + axes.set_title(datetime.now()) + axes.figure.canvas.draw() + +fig = plt.figure() +ax = fig.add_subplot(1, 1, 1) + +x = np.linspace(-3, 3) +ax.plot(x, x*x) + +# Create a new timer object. Set the interval 500 milliseconds (1000 is default) +# and tell the timer what function should be called. +timer = fig.canvas.new_timer() +timer.interval = 100 +timer.add_callback(update_title, ax) +timer.start() + +#Or could start the timer on first figure draw +#def start_timer(evt): +# timer.start() +# fig.canvas.mpl_disconnect(drawid) +#drawid = fig.canvas.mpl_connect('draw_event', start_timer) + +plt.show() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2010-04-20 22:37:08
|
Revision: 8260 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8260&view=rev Author: ryanmay Date: 2010-04-20 22:37:01 +0000 (Tue, 20 Apr 2010) Log Message: ----------- Update timer support to allow for kwargs on callbacks. Also fix up a few bugs in the TkAgg implementation. Modified Paths: -------------- trunk/matplotlib/examples/event_handling/timers.py trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_gtk.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 Modified: trunk/matplotlib/examples/event_handling/timers.py =================================================================== --- trunk/matplotlib/examples/event_handling/timers.py 2010-04-20 20:23:00 UTC (rev 8259) +++ trunk/matplotlib/examples/event_handling/timers.py 2010-04-20 22:37:01 UTC (rev 8260) @@ -16,8 +16,7 @@ # Create a new timer object. Set the interval 500 milliseconds (1000 is default) # and tell the timer what function should be called. -timer = fig.canvas.new_timer() -timer.interval = 100 +timer = fig.canvas.new_timer(interval=100) timer.add_callback(update_title, ax) timer.start() Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2010-04-20 20:23:00 UTC (rev 8259) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2010-04-20 22:37:01 UTC (rev 8260) @@ -893,11 +893,19 @@ upon timer events. This list can be manipulated directly, or the functions add_callback and remove_callback can be used. ''' - def __init__(self): - #Initialize empty callbacks list and setup default settings - self.callbacks = [] + def __init__(self, interval=None, callbacks=None): + #Initialize empty callbacks list and setup default settings if necssary + if callbacks is None: + self.callbacks = [] + else: + self.callbacks = callbacks[:] # Create a copy + + if interval is None: + self._interval = 1000 + else: + self._interval = interval + self._single = False - self._interval = 1000 # Default attribute for holding the GUI-specific timer object self._timer = None @@ -949,21 +957,21 @@ single_shot = property(_get_single_shot, _set_single_shot) - def add_callback(self, func, *args): + def add_callback(self, func, *args, **kwargs): ''' Register `func` to be called by timer when the event fires. Any additional arguments provided will be passed to `func`. ''' - self.callbacks.append((func, args)) + self.callbacks.append((func, args, kwargs)) - def remove_callback(self, func, *args): + def remove_callback(self, func, *args, **kwargs): ''' - Remove `func` from list of callbacks. `args` is optional and used - to distinguish between copies of the same function registered to be - called with different arguments. + Remove `func` from list of callbacks. `args` and `kwargs` are optional + and used to distinguish between copies of the same function registered + to be called with different arguments. ''' - if args: - self.callbacks.remove((func, args)) + if args or kwargs: + self.callbacks.remove((func, args, kwargs)) else: funcs = [c[0] for c in self.callbacks] if func in funcs: @@ -983,10 +991,10 @@ can return False if they should not be called any more. If there are no callbacks, the timer is automatically stopped. ''' - for func,args in self.callbacks: - ret = func(*args) + for func,args,kwargs in self.callbacks: + ret = func(*args, **kwargs) if ret == False: - self.callbacks.remove((func,args)) + self.callbacks.remove((func,args,kwargs)) if len(self.callbacks) == 0: self.stop() @@ -1929,13 +1937,21 @@ """ return self.callbacks.disconnect(cid) - def new_timer(self): + def new_timer(self, *args, **kwargs): """ Creates a new backend-specific subclass of :class:`backend_bases.Timer`. This is useful for getting periodic events through the backend's native event loop. Implemented only for backends with GUIs. + + optional arguments: + + *interval* + Timer interval in milliseconds + *callbacks* + Sequence of (func, args, kwargs) where func(*args, **kwargs) will + be executed by the timer every *interval*. """ - return TimerBase() + return TimerBase(*args, **kwargs) def flush_events(self): """ Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2010-04-20 20:23:00 UTC (rev 8259) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2010-04-20 22:37:01 UTC (rev 8260) @@ -448,13 +448,21 @@ def get_default_filetype(self): return 'png' - def new_timer(self): + def new_timer(self, *args, **kwargs): """ - Creates a new backend-specific subclass of - :class:`backend_bases.TimerBase`. This is useful for getting periodic - events through the backend's native event loop. + Creates a new backend-specific subclass of :class:`backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + optional arguments: + + *interval* + Timer interval in milliseconds + *callbacks* + Sequence of (func, args, kwargs) where func(*args, **kwargs) will + be executed by the timer every *interval*. """ - return TimerGTK() + return TimerGTK(*args, **kwargs) def flush_events(self): gtk.gdk.threads_enter() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2010-04-20 20:23:00 UTC (rev 8259) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2010-04-20 22:37:01 UTC (rev 8260) @@ -97,8 +97,8 @@ upon timer events. This list can be manipulated directly, or the functions add_callback and remove_callback can be used. ''' - def __init__(self): - TimerBase.__init__(self) + def __init__(self, *args, **kwargs): + TimerBase.__init__(self, *args, **kwargs) # Create a new timer and connect the timeout() signal to the # _on_timer method. @@ -232,13 +232,21 @@ return key - def new_timer(self): + def new_timer(self, *args, **kwargs): """ - Creates a new backend-specific subclass of - :class:`backend_bases.TimerBase`. This is useful for getting periodic - events through the backend's native event loop. + Creates a new backend-specific subclass of :class:`backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + optional arguments: + + *interval* + Timer interval in milliseconds + *callbacks* + Sequence of (func, args, kwargs) where func(*args, **kwargs) will + be executed by the timer every *interval*. """ - return TimerQT() + return TimerQT(*args, **kwargs) def flush_events(self): Qt.qApp.processEvents() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2010-04-20 20:23:00 UTC (rev 8259) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2010-04-20 22:37:01 UTC (rev 8260) @@ -108,8 +108,8 @@ upon timer events. This list can be manipulated directly, or the functions add_callback and remove_callback can be used. ''' - def __init__(self, parent): - TimerBase.__init__(self) + def __init__(self, parent, *args, **kwargs): + TimerBase.__init__(self, *args, **kwargs) self.parent = parent def _timer_start(self): @@ -126,7 +126,7 @@ # Tk after() is only a single shot, so we need to add code here to # reset the timer if we're not operating in single shot mode. if not self._single and len(self.callbacks) > 0: - self._timer = self.parent.after(self._interval, _self._on_timer) + self._timer = self.parent.after(self._interval, self._on_timer) else: self._timer = None @@ -358,13 +358,21 @@ key = self._get_key(event) FigureCanvasBase.key_release_event(self, key, guiEvent=event) - def new_timer(self): + def new_timer(self, *args, **kwargs): """ - Creates a new backend-specific subclass of - :class:`backend_bases.TimerBase`. This is useful for getting periodic - events through the backend's native event loop. + Creates a new backend-specific subclass of :class:`backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + optional arguments: + + *interval* + Timer interval in milliseconds + *callbacks* + Sequence of (func, args, kwargs) where func(*args, **kwargs) will + be executed by the timer every *interval*. """ - return TimerTk() + return TimerTk(self._tkcanvas, *args, **kwargs) def flush_events(self): self._master.update() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2010-04-20 20:23:00 UTC (rev 8259) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2010-04-20 22:37:01 UTC (rev 8260) @@ -240,8 +240,8 @@ upon timer events. This list can be manipulated directly, or the functions add_callback and remove_callback can be used. ''' - def __init__(self, parent): - TimerBase.__init__(self) + def __init__(self, parent, *args, **kwargs): + TimerBase.__init__(self, *args, **kwargs) # Create a new timer and connect the timer event to our handler. # For WX, the events have to use a widget for binding. @@ -1022,13 +1022,21 @@ self._isDrawn = True self.gui_repaint(drawDC=drawDC) - def new_timer(self): + def new_timer(self, *args, **kwargs): """ - Creates a new backend-specific subclass of - :class:`backend_bases.TimerBase`. This is useful for getting periodic - events through the backend's native event loop. + Creates a new backend-specific subclass of :class:`backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + optional arguments: + + *interval* + Timer interval in milliseconds + *callbacks* + Sequence of (func, args, kwargs) where func(*args, **kwargs) will + be executed by the timer every *interval*. """ - return TimerWx(self) + return TimerWx(self, *args, **kwargs) def flush_events(self): wx.Yield() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-04-27 20:31:01
|
Revision: 8278 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8278&view=rev Author: efiring Date: 2010-04-27 20:30:53 +0000 (Tue, 27 Apr 2010) Log Message: ----------- contouring: fix various bugs Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/contour_image.py trunk/matplotlib/lib/matplotlib/contour.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py Modified: trunk/matplotlib/examples/pylab_examples/contour_image.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/contour_image.py 2010-04-27 19:39:27 UTC (rev 8277) +++ trunk/matplotlib/examples/pylab_examples/contour_image.py 2010-04-27 20:30:53 UTC (rev 8278) @@ -67,7 +67,7 @@ imshow(Z, extent=extent) v = axis() -contour(Z, cset3.levels, hold='on', colors = 'k', +contour(Z, levels, hold='on', colors = 'k', origin='upper', extent=extent) axis(v) title("Image, origin 'upper'") @@ -76,7 +76,7 @@ imshow(Z, origin='lower', extent=extent) v = axis() -contour(Z, cset3.levels, hold='on', colors = 'k', +contour(Z, levels, hold='on', colors = 'k', origin='lower', extent=extent) axis(v) title("Image, origin 'lower'") @@ -91,7 +91,7 @@ # domain that is contoured does not extend beyond these pixel centers. im = imshow(Z, interpolation='nearest', extent=extent) v = axis() -contour(Z, cset3.levels, hold='on', colors = 'k', +contour(Z, levels, hold='on', colors = 'k', origin='image', extent=extent) axis(v) ylim = get(gca(), 'ylim') Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2010-04-27 19:39:27 UTC (rev 8277) +++ trunk/matplotlib/lib/matplotlib/contour.py 2010-04-27 20:30:53 UTC (rev 8278) @@ -147,7 +147,7 @@ if len(args) == 0: levels = self.levels - indices = range(len(self.levels)) + indices = range(len(levels)) elif len(args) == 1: levlabs = list(args[0]) indices, levels = [], [] @@ -674,7 +674,10 @@ self._process_levels() if self.colors is not None: - cmap = colors.ListedColormap(self.colors, N=len(self.layers)) + ncolors = len(self.levels) + if self.filled: + ncolors -= 1 + cmap = colors.ListedColormap(self.colors, N=ncolors) if self.filled: self.collections = cbook.silent_list('collections.PathCollection') else: @@ -772,7 +775,7 @@ havelimits = True if havelimits: self.ax.update_datalim([min, max]) - self.ax.autoscale_view() + self.ax.autoscale_view(tight=True) def _get_allsegs_and_allkinds(self): """ @@ -881,13 +884,15 @@ self.vmin = 2 * self.levels[0] - self.levels[1] if self.extend in ('both', 'max'): self.vmax = 2 * self.levels[-1] - self.levels[-2] - self.layers = self._levels # contour: a line is a thin layer if self.filled: self.layers = 0.5 * (self._levels[:-1] + self._levels[1:]) if self.extend in ('both', 'min'): self.layers[0] = 0.5 * (self.vmin + self._levels[1]) if self.extend in ('both', 'max'): self.layers[-1] = 0.5 * (self.vmax + self._levels[-2]) + else: + self.layers = self.levels # contour: a line is a thin layer + # Use only original levels--no extended levels def _process_colors(self): """ @@ -903,11 +908,13 @@ """ self.monochrome = self.cmap.monochrome if self.colors is not None: - i0, i1 = 0, len(self.layers) + i0, i1 = 0, len(self.levels) + if self.filled: + i1 -= 1 if self.extend in ('both', 'min'): i0 = -1 if self.extend in ('both', 'max'): - i1 = i1 + 1 + i1 += 1 self.cvalues = range(i0, i1) self.set_norm(colors.NoNorm()) else: @@ -944,8 +951,9 @@ tlinestyles = ['solid'] * Nlev if self.monochrome: neg_ls = mpl.rcParams['contour.negative_linestyle'] + eps = - (self.zmax - self.zmin) * 1e-15 for i, lev in enumerate(self.levels): - if lev < 0.0: + if lev < eps: tlinestyles[i] = neg_ls else: if cbook.is_string_like(linestyles): @@ -1073,6 +1081,8 @@ C = args[0].Cntr if self.levels is None: self.levels = args[0].levels + self.zmin = args[0].zmin + self.zmax = args[0].zmax else: x, y, z = self._contour_args(args, kwargs) @@ -1081,7 +1091,7 @@ y0 = ma.minimum(y) y1 = ma.maximum(y) self.ax.update_datalim([(x0,y0), (x1,y1)]) - self.ax.autoscale_view() + self.ax.autoscale_view(tight=True) _mask = ma.getmask(z) if _mask is ma.nomask: _mask = None Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-04-27 19:39:27 UTC (rev 8277) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-04-27 20:30:53 UTC (rev 8278) @@ -201,7 +201,7 @@ # Let autoscale_view figure out how to use this data. self.autoscale_view() - def autoscale_view(self, scalex=True, scaley=True, scalez=True): + def autoscale_view(self, scalex=True, scaley=True, scalez=True, **kw): # This method looks at the rectanglular volume (see above) # of data and decides how to scale the view portal to fit it. @@ -284,19 +284,19 @@ if elev or azim are None (default), then the initial value is used which was specified in the :class:`Axes3D` constructor. """ - + self.dist = 10 - + if elev is None: self.elev = self.initial_elev else: self.elev = elev - + if azim is None: self.azim = self.initial_azim else: self.azim = azim - + def get_proj(self): """Create the projection matrix from the current viewing position. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-04-28 15:08:25
|
Revision: 8280 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8280&view=rev Author: mdboom Date: 2010-04-28 15:08:19 +0000 (Wed, 28 Apr 2010) Log Message: ----------- Fix path simplification -- distance threshold should have been squared. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/offset_points.png trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/polar_axes.png trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_simplification/fft_peaks.png trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_simplification/fft_peaks.svg trunk/matplotlib/lib/matplotlib/tests/test_simplification.py trunk/matplotlib/src/path_converters.h Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/offset_points.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/polar_axes.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_simplification/fft_peaks.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_simplification/fft_peaks.svg =================================================================== --- trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_simplification/fft_peaks.svg 2010-04-28 06:44:49 UTC (rev 8279) +++ trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_simplification/fft_peaks.svg 2010-04-28 15:08:19 UTC (rev 8280) @@ -23,11 +23,12 @@ <clipPath id="p50431ccdcb28178602d99d9270004dde"> <rect x="72.000000" y="43.200000" width="446.400000" height="345.600000"/> </clipPath> -</defs><path style="fill: none; stroke: #0000ff; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" clip-path="url(#p50431ccdcb28178602d99d9270004dde)" d="M72.000000 388.800000L76.145143 388.578724L76.151520 388.455734 -L76.157897 388.474541L76.177029 70.552590L76.489509 388.799636 -L175.303337 388.800000L485.723520 388.493668L485.736274 386.681411 -L485.755406 70.552590L486.067886 388.799652L489.926057 388.800000 -L489.926057 388.800000"/> +</defs><path style="fill: none; stroke: #0000ff; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" clip-path="url(#p50431ccdcb28178602d99d9270004dde)" d="M72.000000 388.800000L76.132389 388.704243L76.151520 388.455734 +L76.157897 388.474541L76.170651 262.490246L76.177029 70.552590 +L76.272686 388.786908L76.629806 388.799881L221.059337 388.800000 +L485.704389 388.713691L485.729897 388.401770L485.736274 386.681411 +L485.755406 70.552590L485.844686 388.786149L486.182674 388.799863 +L489.926057 388.800000L489.926057 388.800000"/> </g> <g id="matplotlib.axis1"> </g> Modified: trunk/matplotlib/lib/matplotlib/tests/test_simplification.py =================================================================== --- trunk/matplotlib/lib/matplotlib/tests/test_simplification.py 2010-04-28 06:44:49 UTC (rev 8279) +++ trunk/matplotlib/lib/matplotlib/tests/test_simplification.py 2010-04-28 15:08:19 UTC (rev 8280) @@ -69,7 +69,7 @@ path = transform.transform_path(path) simplified = list(path.iter_segments(simplify=(800, 600))) - assert len(simplified) == 2675 + assert len(simplified) == 3884 def test_sine_plus_noise(): np.random.seed(0) @@ -86,7 +86,7 @@ path = transform.transform_path(path) simplified = list(path.iter_segments(simplify=(800, 600))) - assert len(simplified) == 628 + assert len(simplified) == 876 @image_comparison(baseline_images=['simplify_curve']) def test_simplify_curve(): @@ -131,7 +131,7 @@ path = transform.transform_path(path) simplified = list(path.iter_segments(simplify=(800, 600))) - assert len(simplified) == 13 + assert len(simplified) == 17 def test_start_with_moveto(): # Should be entirely clipped away to a single MOVETO Modified: trunk/matplotlib/src/path_converters.h =================================================================== --- trunk/matplotlib/src/path_converters.h 2010-04-28 06:44:49 UTC (rev 8279) +++ trunk/matplotlib/src/path_converters.h 2010-04-28 15:08:19 UTC (rev 8280) @@ -477,7 +477,7 @@ /* Set simplify to true to perform simplification */ PathSimplifier(VertexSource& source, bool do_simplify, double simplify_threshold) : m_source(&source), m_simplify(do_simplify), - m_simplify_threshold(simplify_threshold), + m_simplify_threshold(simplify_threshold*simplify_threshold), m_moveto(true), m_after_moveto(false), m_lastx(0.0), m_lasty(0.0), m_clipped(false), m_origdx(0.0), m_origdy(0.0), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-04-28 18:14:13
|
Revision: 8281 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8281&view=rev Author: mdboom Date: 2010-04-28 18:14:06 +0000 (Wed, 28 Apr 2010) Log Message: ----------- Add interpolation option to fill between so intersections are not broken. Thanks to Joonas Paalasmaa (Bug #2978358) for the report and initial implementation. Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/fill_between_demo.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/pyplot.py trunk/matplotlib/lib/matplotlib/tests/test_axes.py Added Paths: ----------- trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.pdf trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.png trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.svg Modified: trunk/matplotlib/examples/pylab_examples/fill_between_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/fill_between_demo.py 2010-04-28 15:08:19 UTC (rev 8280) +++ trunk/matplotlib/examples/pylab_examples/fill_between_demo.py 2010-04-28 18:14:06 UTC (rev 8281) @@ -29,16 +29,16 @@ fig = figure() ax = fig.add_subplot(211) ax.plot(x, y1, x, y2, color='black') -ax.fill_between(x, y1, y2, where=y2>=y1, facecolor='green') -ax.fill_between(x, y1, y2, where=y2<=y1, facecolor='red') +ax.fill_between(x, y1, y2, where=y2>=y1, facecolor='green', interpolate=True) +ax.fill_between(x, y1, y2, where=y2<=y1, facecolor='red', interpolate=True) ax.set_title('fill between where') # Test support for masked arrays. y2 = np.ma.masked_greater(y2, 1.0) ax1 = fig.add_subplot(212, sharex=ax) ax1.plot(x, y1, x, y2, color='black') -ax1.fill_between(x, y1, y2, where=y2>=y1, facecolor='green') -ax1.fill_between(x, y1, y2, where=y2<=y1, facecolor='red') +ax1.fill_between(x, y1, y2, where=y2>=y1, facecolor='green', interpolate=True) +ax1.fill_between(x, y1, y2, where=y2<=y1, facecolor='red', interpolate=True) ax1.set_title('Now regions with y2>1 are masked') # This example illustrates a problem; because of the data Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-04-28 15:08:19 UTC (rev 8280) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-04-28 18:14:06 UTC (rev 8281) @@ -6157,7 +6157,8 @@ return patches @docstring.dedent_interpd - def fill_between(self, x, y1, y2=0, where=None, **kwargs): + def fill_between(self, x, y1, y2=0, where=None, interpolate=False, + **kwargs): """ call signature:: @@ -6181,6 +6182,12 @@ it is a a N length numpy boolean array and the fill will only happen over the regions where ``where==True`` + *interpolate* + If True, interpolate between the two lines to find the + precise point of intersection. Otherwise, the start and + end points of the filled region will only occur on explicit + values in the *x* array. + *kwargs* keyword args passed on to the :class:`PolyCollection` @@ -6236,17 +6243,41 @@ N = len(xslice) X = np.zeros((2*N+2, 2), np.float) - # the purpose of the next two lines is for when y2 is a - # scalar like 0 and we want the fill to go all the way - # down to 0 even if none of the y1 sample points do - X[0] = xslice[0], y2slice[0] - X[N+1] = xslice[-1], y2slice[-1] + if interpolate: + def get_interp_point(ind): + x_values = x[ind-1:ind+1] + diff_values = y1[ind-1:ind+1] - y2[ind-1:ind+1] + y1_values = y1[ind-1:ind+1] + if len(diff_values) == 2: + if np.ma.is_masked(diff_values[1]): + return x[ind-1], y1[ind-1] + elif np.ma.is_masked(diff_values[0]): + return x[ind], y1[ind] + + diff_order = diff_values.argsort() + diff_root_x = np.interp( + 0, diff_values[diff_order], x_values[diff_order]) + diff_root_y = np.interp(diff_root_x, x_values, y1_values) + return diff_root_x, diff_root_y + + start = get_interp_point(ind0) + end = get_interp_point(ind1) + else: + # the purpose of the next two lines is for when y2 is a + # scalar like 0 and we want the fill to go all the way + # down to 0 even if none of the y1 sample points do + start = xslice[0], y2slice[0] + end = xslice[-1], y2slice[-1] + + X[0] = start + X[N+1] = end + X[1:N+1,0] = xslice X[1:N+1,1] = y1slice X[N+2:,0] = xslice[::-1] X[N+2:,1] = y2slice[::-1] - + polys.append(X) collection = mcoll.PolyCollection(polys, **kwargs) @@ -6256,7 +6287,6 @@ XY2 = np.array([x[where], y2[where]]).T self.dataLim.update_from_data_xy(XY1, self.ignore_existing_data_limits, updatex=True, updatey=True) - self.dataLim.update_from_data_xy(XY2, self.ignore_existing_data_limits, updatex=False, updatey=True) self.add_collection(collection) Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2010-04-28 15:08:19 UTC (rev 8280) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2010-04-28 18:14:06 UTC (rev 8281) @@ -2049,7 +2049,7 @@ # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost @autogen_docstring(Axes.fill_between) -def fill_between(x, y1, y2=0, where=None, hold=None, **kwargs): +def fill_between(x, y1, y2=0, where=None, interpolate=False, hold=None, **kwargs): ax = gca() # allow callers to override the hold state by passing hold=True|False washold = ax.ishold() @@ -2057,7 +2057,7 @@ if hold is not None: ax.hold(hold) try: - ret = ax.fill_between(x, y1, y2, where, **kwargs) + ret = ax.fill_between(x, y1, y2, where, interpolate, **kwargs) draw_if_interactive() finally: ax.hold(washold) Added: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.pdf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.pdf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.png =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.svg =================================================================== --- trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.svg (rev 0) +++ trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_axes/fill_between_interpolate.svg 2010-04-28 18:14:06 UTC (rev 8281) @@ -0,0 +1,763 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Created with matplotlib (http://matplotlib.sourceforge.net/) --> +<svg width="576pt" height="432pt" viewBox="0 0 576 432" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.1" + id="svg1"> +<filter id="colorAdd"><feComposite in="SourceGraphic" in2="BackgroundImage" operator="arithmetic" k2="1" k3="1"/></filter> +<g id="figure1"> +<g id="patch1"> +<path style="fill: #ffffff; stroke: #ffffff; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" d="M0.000000 432.000000L576.000000 432.000000L576.000000 0.000000 +L0.000000 0.000000L0.000000 432.000000"/> +</g> +<g id="axes1"> +<g id="patch2"> +<path style="fill: #ffffff; opacity: 1.000000" d="M72.000000 200.290909L518.400000 200.290909L518.400000 43.200000 +L72.000000 43.200000L72.000000 200.290909"/> +</g> +<g id="PolyCollection1"> +<defs> +<path id="coll0_0_aaf56935a2c13518ed60e01cdc1dee73" d="M72.000000 -310.254545L72.000000 -310.254545L76.464000 -316.817449 +L80.928000 -323.276852L85.392000 -329.530886L89.856000 -335.480920 +L94.320000 -341.033119L98.784000 -346.099921L103.248000 -350.601421 +L107.712000 -354.466626L112.176000 -357.634580L112.508717 -357.815006 +L112.176000 -358.670796L107.712000 -367.110587L103.248000 -371.977904 +L98.784000 -372.966916L94.320000 -370.015479L89.856000 -363.309042 +L85.392000 -353.268996L80.928000 -340.526195L76.464000 -325.881314 +L72.000000 -310.254545z"/> +<path id="coll0_1_a4538251d9ee85a3e02c1608986ad8bb" d="M183.600000 -310.254545L188.064000 -303.691642L192.528000 -297.232239 +L196.992000 -290.978205L201.456000 -285.028171L205.920000 -279.475972 +L210.384000 -274.409170L214.848000 -269.907670L219.312000 -266.042465 +L223.776000 -262.874511L228.240000 -260.453768L232.704000 -258.818413 +L237.168000 -257.994237L241.632000 -257.994237L246.096000 -258.818413 +L250.560000 -260.453768L254.691283 -262.694085L250.560000 -273.320258 +L246.096000 -287.122937L241.632000 -302.379061L237.168000 -318.130030 +L232.704000 -333.386154L228.240000 -347.188833L223.776000 -358.670796 +L219.312000 -367.110587L214.848000 -371.977904L210.384000 -372.966916 +L205.920000 -370.015479L201.456000 -363.309042L196.992000 -353.268996 +L192.528000 -340.526195L188.064000 -325.881314z"/> +<path id="coll0_2_7e1bc78ca422414c858b233668c6bc42" d="M295.200000 -310.254545L299.664000 -316.817449L304.128000 -323.276852 +L308.592000 -329.530886L313.056000 -335.480920L317.520000 -341.033119 +L321.984000 -346.099921L326.448000 -350.601421L330.912000 -354.466626 +L335.376000 -357.634580L335.708717 -357.815006L335.376000 -358.670796 +L330.912000 -367.110587L326.448000 -371.977904L321.984000 -372.966916 +L317.520000 -370.015479L313.056000 -363.309042L308.592000 -353.268996 +L304.128000 -340.526195L299.664000 -325.881314z"/> +<path id="coll0_3_c3b5c2b0e85ad5a4572d45dacb38da0e" d="M406.800000 -310.254545L411.264000 -303.691642L415.728000 -297.232239 +L420.192000 -290.978205L424.656000 -285.028171L429.120000 -279.475972 +L433.584000 -274.409170L438.048000 -269.907670L442.512000 -266.042465 +L446.976000 -262.874511L451.440000 -260.453768L455.904000 -258.818413 +L460.368000 -257.994237L464.832000 -257.994237L469.296000 -258.818413 +L473.760000 -260.453768L477.891283 -262.694085L473.760000 -273.320258 +L469.296000 -287.122937L464.832000 -302.379061L460.368000 -318.130030 +L455.904000 -333.386154L451.440000 -347.188833L446.976000 -358.670796 +L442.512000 -367.110587L438.048000 -371.977904L433.584000 -372.966916 +L429.120000 -370.015479L424.656000 -363.309042L420.192000 -353.268996 +L415.728000 -340.526195L411.264000 -325.881314z"/> +</defs> +<defs> + <clipPath id="pad2bdf97e9fd82d59a5c57b91897f3de"> +<rect x="72.000000" y="43.200000" width="446.400000" height="157.090909"/> + </clipPath> +</defs><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll0_0_aaf56935a2c13518ed60e01cdc1dee73" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll0_1_a4538251d9ee85a3e02c1608986ad8bb" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll0_2_7e1bc78ca422414c858b233668c6bc42" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll0_3_c3b5c2b0e85ad5a4572d45dacb38da0e" x="0.000000" y="432.000000"/> +</g></g> +<g id="PolyCollection2"> +<defs> +<path id="coll1_0_59cf1511b6d916e21dd73a7f3e4d31ec" d="M72.000000 -310.254545L72.000000 -310.254545L72.000000 -310.254545 +L72.000000 -310.254545z"/> +<path id="coll1_1_e39ea564cf8eb3ca5381599ae079b29b" d="M112.508717 -357.815006L116.640000 -360.055323L121.104000 -361.690678 +L125.568000 -362.514854L130.032000 -362.514854L134.496000 -361.690678 +L138.960000 -360.055323L143.424000 -357.634580L147.888000 -354.466626 +L152.352000 -350.601421L156.816000 -346.099921L161.280000 -341.033119 +L165.744000 -335.480920L170.208000 -329.530886L174.672000 -323.276852 +L179.136000 -316.817449L183.600000 -310.254545L183.600000 -310.254545 +L183.600000 -310.254545L179.136000 -294.627777L174.672000 -279.982896 +L170.208000 -267.240095L165.744000 -257.200049L161.280000 -250.493612 +L156.816000 -247.542175L152.352000 -248.531187L147.888000 -253.398504 +L143.424000 -261.838295L138.960000 -273.320258L134.496000 -287.122937 +L130.032000 -302.379061L125.568000 -318.130030L121.104000 -333.386154 +L116.640000 -347.188833z"/> +<path id="coll1_2_0f64580eb1567b0582e386cb71b8b9cd" d="M254.691283 -262.694085L255.024000 -262.874511L259.488000 -266.042465 +L263.952000 -269.907670L268.416000 -274.409170L272.880000 -279.475972 +L277.344000 -285.028171L281.808000 -290.978205L286.272000 -297.232239 +L290.736000 -303.691642L295.200000 -310.254545L295.200000 -310.254545 +L295.200000 -310.254545L290.736000 -294.627777L286.272000 -279.982896 +L281.808000 -267.240095L277.344000 -257.200049L272.880000 -250.493612 +L268.416000 -247.542175L263.952000 -248.531187L259.488000 -253.398504 +L255.024000 -261.838295z"/> +<path id="coll1_3_ca80bd8ff98b9208864e7e898d4b563e" d="M335.708717 -357.815006L339.840000 -360.055323L344.304000 -361.690678 +L348.768000 -362.514854L353.232000 -362.514854L357.696000 -361.690678 +L362.160000 -360.055323L366.624000 -357.634580L371.088000 -354.466626 +L375.552000 -350.601421L380.016000 -346.099921L384.480000 -341.033119 +L388.944000 -335.480920L393.408000 -329.530886L397.872000 -323.276852 +L402.336000 -316.817449L406.800000 -310.254545L406.800000 -310.254545 +L406.800000 -310.254545L402.336000 -294.627777L397.872000 -279.982896 +L393.408000 -267.240095L388.944000 -257.200049L384.480000 -250.493612 +L380.016000 -247.542175L375.552000 -248.531187L371.088000 -253.398504 +L366.624000 -261.838295L362.160000 -273.320258L357.696000 -287.122937 +L353.232000 -302.379061L348.768000 -318.130030L344.304000 -333.386154 +L339.840000 -347.188833z"/> +<path id="coll1_4_c1ff4955e7872f3ca161dc94104c2fad" d="M477.891283 -262.694085L478.224000 -262.874511L482.688000 -266.042465 +L487.152000 -269.907670L491.616000 -274.409170L496.080000 -279.475972 +L500.544000 -285.028171L505.008000 -290.978205L509.472000 -297.232239 +L513.936000 -303.691642L513.936000 -303.691642L513.936000 -294.627777 +L509.472000 -279.982896L505.008000 -267.240095L500.544000 -257.200049 +L496.080000 -250.493612L491.616000 -247.542175L487.152000 -248.531187 +L482.688000 -253.398504L478.224000 -261.838295z"/> +</defs> +<g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll1_0_59cf1511b6d916e21dd73a7f3e4d31ec" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll1_1_e39ea564cf8eb3ca5381599ae079b29b" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll1_2_0f64580eb1567b0582e386cb71b8b9cd" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll1_3_ca80bd8ff98b9208864e7e898d4b563e" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll1_4_c1ff4955e7872f3ca161dc94104c2fad" x="0.000000" y="432.000000"/> +</g></g> +<g id="line2d1"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)" d="M72.000000 121.745455L76.464000 115.182551L80.928000 108.723148 +L85.392000 102.469114L89.856000 96.519080L94.320000 90.966881 +L98.784000 85.900079L103.248000 81.398579L107.712000 77.533374 +L112.176000 74.365420L116.640000 71.944677L121.104000 70.309322 +L125.568000 69.485146L130.032000 69.485146L134.496000 70.309322 +L138.960000 71.944677L143.424000 74.365420L147.888000 77.533374 +L152.352000 81.398579L156.816000 85.900079L161.280000 90.966881 +L165.744000 96.519080L170.208000 102.469114L174.672000 108.723148 +L179.136000 115.182551L183.600000 121.745455L188.064000 128.308358 +L192.528000 134.767761L196.992000 141.021795L201.456000 146.971829 +L205.920000 152.524028L210.384000 157.590830L214.848000 162.092330 +L219.312000 165.957535L223.776000 169.125489L228.240000 171.546232 +L232.704000 173.181587L237.168000 174.005763L241.632000 174.005763 +L246.096000 173.181587L250.560000 171.546232L255.024000 169.125489 +L259.488000 165.957535L263.952000 162.092330L268.416000 157.590830 +L272.880000 152.524028L277.344000 146.971829L281.808000 141.021795 +L286.272000 134.767761L290.736000 128.308358L295.200000 121.745455 +L299.664000 115.182551L304.128000 108.723148L308.592000 102.469114 +L313.056000 96.519080L317.520000 90.966881L321.984000 85.900079 +L326.448000 81.398579L330.912000 77.533374L335.376000 74.365420 +L339.840000 71.944677L344.304000 70.309322L348.768000 69.485146 +L353.232000 69.485146L357.696000 70.309322L362.160000 71.944677 +L366.624000 74.365420L371.088000 77.533374L375.552000 81.398579 +L380.016000 85.900079L384.480000 90.966881L388.944000 96.519080 +L393.408000 102.469114L397.872000 108.723148L402.336000 115.182551 +L406.800000 121.745455L411.264000 128.308358L415.728000 134.767761 +L420.192000 141.021795L424.656000 146.971829L429.120000 152.524028 +L433.584000 157.590830L438.048000 162.092330L442.512000 165.957535 +L446.976000 169.125489L451.440000 171.546232L455.904000 173.181587 +L460.368000 174.005763L464.832000 174.005763L469.296000 173.181587 +L473.760000 171.546232L478.224000 169.125489L482.688000 165.957535 +L487.152000 162.092330L491.616000 157.590830L496.080000 152.524028 +L500.544000 146.971829L505.008000 141.021795L509.472000 134.767761 +L513.936000 128.308358"/> +</g> +<g id="line2d2"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" clip-path="url(#pad2bdf97e9fd82d59a5c57b91897f3de)" d="M72.000000 121.745455L76.464000 106.118686L80.928000 91.473805 +L85.392000 78.731004L89.856000 68.690958L94.320000 61.984521 +L98.784000 59.033084L103.248000 60.022096L107.712000 64.889413 +L112.176000 73.329204L116.640000 84.811167L121.104000 98.613846 +L125.568000 113.869970L130.032000 129.620939L134.496000 144.877063 +L138.960000 158.679742L143.424000 170.161705L147.888000 178.601496 +L152.352000 183.468813L156.816000 184.457825L161.280000 181.506388 +L165.744000 174.799951L170.208000 164.759905L174.672000 152.017104 +L179.136000 137.372223L183.600000 121.745455L188.064000 106.118686 +L192.528000 91.473805L196.992000 78.731004L201.456000 68.690958 +L205.920000 61.984521L210.384000 59.033084L214.848000 60.022096 +L219.312000 64.889413L223.776000 73.329204L228.240000 84.811167 +L232.704000 98.613846L237.168000 113.869970L241.632000 129.620939 +L246.096000 144.877063L250.560000 158.679742L255.024000 170.161705 +L259.488000 178.601496L263.952000 183.468813L268.416000 184.457825 +L272.880000 181.506388L277.344000 174.799951L281.808000 164.759905 +L286.272000 152.017104L290.736000 137.372223L295.200000 121.745455 +L299.664000 106.118686L304.128000 91.473805L308.592000 78.731004 +L313.056000 68.690958L317.520000 61.984521L321.984000 59.033084 +L326.448000 60.022096L330.912000 64.889413L335.376000 73.329204 +L339.840000 84.811167L344.304000 98.613846L348.768000 113.869970 +L353.232000 129.620939L357.696000 144.877063L362.160000 158.679742 +L366.624000 170.161705L371.088000 178.601496L375.552000 183.468813 +L380.016000 184.457825L384.480000 181.506388L388.944000 174.799951 +L393.408000 164.759905L397.872000 152.017104L402.336000 137.372223 +L406.800000 121.745455L411.264000 106.118686L415.728000 91.473805 +L420.192000 78.731004L424.656000 68.690958L429.120000 61.984521 +L433.584000 59.033084L438.048000 60.022096L442.512000 64.889413 +L446.976000 73.329204L451.440000 84.811167L455.904000 98.613846 +L460.368000 113.869970L464.832000 129.620939L469.296000 144.877063 +L473.760000 158.679742L478.224000 170.161705L482.688000 178.601496 +L487.152000 183.468813L491.616000 184.457825L496.080000 181.506388 +L500.544000 174.799951L505.008000 164.759905L509.472000 152.017104 +L513.936000 137.372223"/> +</g> +<g id="matplotlib.axis1"> +<g id="xtick1"> +<g id="line2d3"> +<defs><path id="m30e32995789d870ad79a2e54c91cf9c6" d="M0.000000 0.000000L0.000000 -4.000000"/></defs> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="72.000000" y="200.290909"/> +</g></g> +<g id="line2d4"> +<defs><path id="m9281cae24120827b11d5ea8a7ad3e96b" d="M0.000000 0.000000L0.000000 4.000000"/></defs> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="72.000000" y="43.200000"/> +</g></g> +<g id="text1"> +<defs> +<path id="c_7a2040fe3b94fcd41d0a72c84e93b115" d="M31.781250 -66.406250q-7.609375 0.000000 -11.453125 7.500000q-3.828125 7.484375 -3.828125 22.531250q0.000000 14.984375 3.828125 22.484375q3.843750 7.500000 11.453125 7.500000q7.671875 0.000000 11.500000 -7.500000q3.843750 -7.500000 3.843750 -22.484375q0.000000 -15.046875 -3.843750 -22.531250q-3.828125 -7.500000 -11.500000 -7.500000M31.781250 -74.218750q12.265625 0.000000 18.734375 9.703125q6.468750 9.687500 6.468750 28.140625q0.000000 18.406250 -6.468750 28.109375q-6.468750 9.687500 -18.734375 9.687500q-12.250000 0.000000 -18.718750 -9.687500q-6.468750 -9.703125 -6.468750 -28.109375q0.000000 -18.453125 6.468750 -28.140625q6.468750 -9.703125 18.718750 -9.703125"/> +<path id="c_ed3e21196fb739f392806f09ca0594ef" d="M10.687500 -12.406250l10.312500 0.000000l0.000000 12.406250l-10.312500 0.000000z"/> +</defs> +<g style="fill: #000000; opacity: 1.000000" transform="translate(63.250000,213.197159)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick2"> +<g id="line2d5"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="183.600000" y="200.290909"/> +</g></g> +<g id="line2d6"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="183.600000" y="43.200000"/> +</g></g> +<g id="text2"> +<defs> +<path id="c_1260a2df50f305f3db244e29828f968e" d="M10.796875 -72.906250l38.718750 0.000000l0.000000 8.312500l-29.687500 0.000000l0.000000 17.859375q2.140625 -0.734375 4.281250 -1.093750q2.156250 -0.359375 4.312500 -0.359375q12.203125 0.000000 19.328125 6.687500q7.140625 6.687500 7.140625 18.109375q0.000000 11.765625 -7.328125 18.296875q-7.328125 6.515625 -20.656250 6.515625q-4.593750 0.000000 -9.359375 -0.781250q-4.750000 -0.781250 -9.828125 -2.343750l0.000000 -9.921875q4.390625 2.390625 9.078125 3.562500q4.687500 1.171875 9.906250 1.171875q8.453125 0.000000 13.375000 -4.437500q4.937500 -4.437500 4.937500 -12.062500q0.000000 -7.609375 -4.937500 -12.046875q-4.921875 -4.453125 -13.375000 -4.453125q-3.953125 0.000000 -7.890625 0.875000q-3.921875 0.875000 -8.015625 2.734375z"/> +</defs> +<g style="fill: #000000; opacity: 1.000000" transform="translate(174.975000,213.197159)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick3"> +<g id="line2d7"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="295.200000" y="200.290909"/> +</g></g> +<g id="line2d8"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="295.200000" y="43.200000"/> +</g></g> +<g id="text3"> +<defs> +<path id="c_42baa63129a918535c52adb20d687ea7" d="M12.406250 -8.296875l16.109375 0.000000l0.000000 -55.625000l-17.531250 3.515625l0.000000 -8.984375l17.437500 -3.515625l9.859375 0.000000l0.000000 64.609375l16.109375 0.000000l0.000000 8.296875l-41.984375 0.000000z"/> +</defs> +<g style="fill: #000000; opacity: 1.000000" transform="translate(286.707812,213.197159)scale(0.120000)"> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick4"> +<g id="line2d9"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="406.800000" y="200.290909"/> +</g></g> +<g id="line2d10"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="406.800000" y="43.200000"/> +</g></g> +<g id="text4"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(398.432812,213.040909)scale(0.120000)"> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick5"> +<g id="line2d11"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="518.400000" y="200.290909"/> +</g></g> +<g id="line2d12"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="518.400000" y="43.200000"/> +</g></g> +<g id="text5"> +<defs> +<path id="c_ed3f3ed3ebfbd18bcb9c012009a68ad1" d="M19.187500 -8.296875l34.421875 0.000000l0.000000 8.296875l-46.281250 0.000000l0.000000 -8.296875q5.609375 -5.812500 15.296875 -15.593750q9.703125 -9.796875 12.187500 -12.640625q4.734375 -5.312500 6.609375 -9.000000q1.890625 -3.687500 1.890625 -7.250000q0.000000 -5.812500 -4.078125 -9.468750q-4.078125 -3.671875 -10.625000 -3.671875q-4.640625 0.000000 -9.796875 1.609375q-5.140625 1.609375 -11.000000 4.890625l0.000000 -9.968750q5.953125 -2.390625 11.125000 -3.609375q5.187500 -1.218750 9.484375 -1.218750q11.328125 0.000000 18.062500 5.671875q6.734375 5.656250 6.734375 15.125000q0.000000 4.500000 -1.687500 8.531250q-1.671875 4.015625 -6.125000 9.484375q-1.218750 1.421875 -7.765625 8.187500q-6.531250 6.765625 -18.453125 18.921875"/> +</defs> +<g style="fill: #000000; opacity: 1.000000" transform="translate(509.689062,213.197159)scale(0.120000)"> +<use xlink:href="#c_ed3f3ed3ebfbd18bcb9c012009a68ad1"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +</g> +<g id="matplotlib.axis2"> +<g id="ytick1"> +<g id="line2d13"> +<defs><path id="m3400efa6b1638b3fea9e19e898273957" d="M0.000000 0.000000L4.000000 0.000000"/></defs> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="200.290909"/> +</g></g> +<g id="line2d14"> +<defs><path id="m20b58b2501143cb5e0a5e8f1ef6f1643" d="M0.000000 0.000000L-4.000000 0.000000"/></defs> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="200.290909"/> +</g></g> +<g id="text6"> +<defs> +<path id="c_6a8d56c819c37117ab4cf023bec22a5a" d="M10.593750 -35.500000l62.593750 0.000000l0.000000 8.296875l-62.593750 0.000000z"/> +</defs> +<g style="fill: #000000; opacity: 1.000000" transform="translate(41.156250,204.579972)scale(0.120000)"> +<use xlink:href="#c_6a8d56c819c37117ab4cf023bec22a5a"/> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7" x="83.789062"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="147.412109"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="179.199219"/> +</g> +</g> +</g> +<g id="ytick2"> +<g id="line2d15"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="174.109091"/> +</g></g> +<g id="line2d16"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="174.109091"/> +</g></g> +<g id="text7"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(40.906250,178.476278)scale(0.120000)"> +<use xlink:href="#c_6a8d56c819c37117ab4cf023bec22a5a"/> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7" x="83.789062"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="147.412109"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="179.199219"/> +</g> +</g> +</g> +<g id="ytick3"> +<g id="line2d17"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="147.927273"/> +</g></g> +<g id="line2d18"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="147.927273"/> +</g></g> +<g id="text8"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(41.156250,152.294460)scale(0.120000)"> +<use xlink:href="#c_6a8d56c819c37117ab4cf023bec22a5a"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="83.789062"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="147.412109"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="179.199219"/> +</g> +</g> +</g> +<g id="ytick4"> +<g id="line2d19"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="121.745455"/> +</g></g> +<g id="line2d20"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="121.745455"/> +</g></g> +<g id="text9"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(50.500000,126.112642)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +<g id="ytick5"> +<g id="line2d21"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="95.563636"/> +</g></g> +<g id="line2d22"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="95.563636"/> +</g></g> +<g id="text10"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(50.750000,99.930824)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="95.410156"/> +</g> +</g> +</g> +<g id="ytick6"> +<g id="line2d23"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="69.381818"/> +</g></g> +<g id="line2d24"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="69.381818"/> +</g></g> +<g id="text11"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(51.015625,73.749006)scale(0.120000)"> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +<g id="ytick7"> +<g id="line2d25"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="43.200000"/> +</g></g> +<g id="line2d26"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="43.200000"/> +</g></g> +<g id="text12"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(51.265625,47.489062)scale(0.120000)"> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="95.410156"/> +</g> +</g> +</g> +</g> +<g id="patch3"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" d="M72.000000 43.200000L518.400000 43.200000"/> +</g> +<g id="patch4"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" d="M518.400000 200.290909L518.400000 43.200000"/> +</g> +<g id="patch5"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" d="M72.000000 200.290909L518.400000 200.290909"/> +</g> +<g id="patch6"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" d="M72.000000 200.290909L72.000000 43.200000"/> +</g> +</g> +<g id="axes2"> +<g id="patch7"> +<path style="fill: #ffffff; opacity: 1.000000" d="M72.000000 388.800000L518.400000 388.800000L518.400000 231.709091 +L72.000000 231.709091L72.000000 388.800000"/> +</g> +<g id="PolyCollection3"> +<defs> +<path id="coll2_0_46fd974f6d18f5a0a68d531beb577700" d="M72.000000 -137.454545L72.000000 -137.454545L76.464000 -145.330030 +L80.928000 -153.081314L85.392000 -160.586154L85.392000 -160.586154 +L85.392000 -189.071887L80.928000 -173.780524L76.464000 -156.206667 +L72.000000 -137.454545z"/> +<path id="coll2_1_8be4f92688f0eba5fa3fdb87085b7f86" d="M112.176000 -194.310587L112.176000 -194.310587L112.508717 -194.527099 +L112.176000 -195.554046z"/> +<path id="coll2_2_20ec3575585369c6307e012db84037fd" d="M183.600000 -137.454545L188.064000 -129.579061L192.528000 -121.827777 +L196.992000 -114.322937L196.992000 -114.322937L196.992000 -189.071887 +L192.528000 -173.780524L188.064000 -156.206667z"/> +<path id="coll2_3_23b0f9263c46c9ceec1f92c96a9227b4" d="M223.776000 -80.598504L223.776000 -80.598504L228.240000 -77.693612 +L232.704000 -75.731187L237.168000 -74.742175L241.632000 -74.742175 +L246.096000 -75.731187L250.560000 -77.693612L254.691283 -80.381992 +L250.560000 -93.133400L246.096000 -109.696616L241.632000 -128.003964 +L237.168000 -146.905127L232.704000 -165.212475L228.240000 -181.775691 +L223.776000 -195.554046z"/> +<path id="coll2_4_e39c3b124eb232f8f64f9f24c1f7a81b" d="M295.200000 -137.454545L299.664000 -145.330030L304.128000 -153.081314 +L308.592000 -160.586154L308.592000 -160.586154L308.592000 -189.071887 +L304.128000 -173.780524L299.664000 -156.206667z"/> +<path id="coll2_5_a3b93d11f806ad2797c2a4e1c65e9be3" d="M335.376000 -194.310587L335.376000 -194.310587L335.708717 -194.527099 +L335.376000 -195.554046z"/> +<path id="coll2_6_48770cc756a14ea59a12220750586725" d="M406.800000 -137.454545L411.264000 -129.579061L415.728000 -121.827777 +L420.192000 -114.322937L420.192000 -114.322937L420.192000 -189.071887 +L415.728000 -173.780524L411.264000 -156.206667z"/> +<path id="coll2_7_66eac2d1cfb76197e93f61741c9bda26" d="M446.976000 -80.598504L446.976000 -80.598504L451.440000 -77.693612 +L455.904000 -75.731187L460.368000 -74.742175L464.832000 -74.742175 +L469.296000 -75.731187L473.760000 -77.693612L477.891283 -80.381992 +L473.760000 -93.133400L469.296000 -109.696616L464.832000 -128.003964 +L460.368000 -146.905127L455.904000 -165.212475L451.440000 -181.775691 +L446.976000 -195.554046z"/> +</defs> +<defs> + <clipPath id="pdceb94b59b302b6d614f8fc54d3b8e04"> +<rect x="72.000000" y="231.709091" width="446.400000" height="157.090909"/> + </clipPath> +</defs><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_0_46fd974f6d18f5a0a68d531beb577700" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_1_8be4f92688f0eba5fa3fdb87085b7f86" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_2_20ec3575585369c6307e012db84037fd" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_3_23b0f9263c46c9ceec1f92c96a9227b4" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_4_e39c3b124eb232f8f64f9f24c1f7a81b" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_5_a3b93d11f806ad2797c2a4e1c65e9be3" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_6_48770cc756a14ea59a12220750586725" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #008000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll2_7_66eac2d1cfb76197e93f61741c9bda26" x="0.000000" y="432.000000"/> +</g></g> +<g id="PolyCollection4"> +<defs> +<path id="coll3_0_94785b50af4b70a86b59016efebda6fa" d="M72.000000 -137.454545L72.000000 -137.454545L72.000000 -137.454545 +L72.000000 -137.454545z"/> +<path id="coll3_1_b89b074290be78a074730e88a9f8da14" d="M112.508717 -194.527099L116.640000 -197.215479L121.104000 -199.177904 +L125.568000 -200.166916L130.032000 -200.166916L134.496000 -199.177904 +L138.960000 -197.215479L143.424000 -194.310587L147.888000 -190.509042 +L152.352000 -185.870796L156.816000 -180.468996L161.280000 -174.388833 +L165.744000 -167.726195L170.208000 -160.586154L174.672000 -153.081314 +L179.136000 -145.330030L183.600000 -137.454545L183.600000 -137.454545 +L183.600000 -137.454545L179.136000 -118.702424L174.672000 -101.128567 +L170.208000 -85.837204L165.744000 -73.789150L161.280000 -65.741426 +L156.816000 -62.199701L152.352000 -63.386515L147.888000 -69.227295 +L143.424000 -79.355045L138.960000 -93.133400L134.496000 -109.696616 +L130.032000 -128.003964L125.568000 -146.905127L121.104000 -165.212475 +L116.640000 -181.775691z"/> +<path id="coll3_2_300df8223ffbe600e5ec6d3660361009" d="M254.691283 -80.381992L255.024000 -80.598504L259.488000 -84.400049 +L263.952000 -89.038295L268.416000 -94.440095L272.880000 -100.520258 +L277.344000 -107.182896L281.808000 -114.322937L286.272000 -121.827777 +L290.736000 -129.579061L295.200000 -137.454545L295.200000 -137.454545 +L295.200000 -137.454545L290.736000 -118.702424L286.272000 -101.128567 +L281.808000 -85.837204L277.344000 -73.789150L272.880000 -65.741426 +L268.416000 -62.199701L263.952000 -63.386515L259.488000 -69.227295 +L255.024000 -79.355045z"/> +<path id="coll3_3_ea9f940b34b4b127ddaeae93dbac851f" d="M335.708717 -194.527099L339.840000 -197.215479L344.304000 -199.177904 +L348.768000 -200.166916L353.232000 -200.166916L357.696000 -199.177904 +L362.160000 -197.215479L366.624000 -194.310587L371.088000 -190.509042 +L375.552000 -185.870796L380.016000 -180.468996L384.480000 -174.388833 +L388.944000 -167.726195L393.408000 -160.586154L397.872000 -153.081314 +L402.336000 -145.330030L406.800000 -137.454545L406.800000 -137.454545 +L406.800000 -137.454545L402.336000 -118.702424L397.872000 -101.128567 +L393.408000 -85.837204L388.944000 -73.789150L384.480000 -65.741426 +L380.016000 -62.199701L375.552000 -63.386515L371.088000 -69.227295 +L366.624000 -79.355045L362.160000 -93.133400L357.696000 -109.696616 +L353.232000 -128.003964L348.768000 -146.905127L344.304000 -165.212475 +L339.840000 -181.775691z"/> +<path id="coll3_4_fca770bf0e4a6dd8e02ca3518b412a67" d="M477.891283 -80.381992L478.224000 -80.598504L482.688000 -84.400049 +L487.152000 -89.038295L491.616000 -94.440095L496.080000 -100.520258 +L500.544000 -107.182896L505.008000 -114.322937L509.472000 -121.827777 +L513.936000 -129.579061L513.936000 -129.579061L513.936000 -118.702424 +L509.472000 -101.128567L505.008000 -85.837204L500.544000 -73.789150 +L496.080000 -65.741426L491.616000 -62.199701L487.152000 -63.386515 +L482.688000 -69.227295L478.224000 -79.355045z"/> +</defs> +<g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll3_0_94785b50af4b70a86b59016efebda6fa" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll3_1_b89b074290be78a074730e88a9f8da14" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll3_2_300df8223ffbe600e5ec6d3660361009" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll3_3_ea9f940b34b4b127ddaeae93dbac851f" x="0.000000" y="432.000000"/> +</g><g clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)"><use style="fill: #ff0000; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#coll3_4_fca770bf0e4a6dd8e02ca3518b412a67" x="0.000000" y="432.000000"/> +</g></g> +<g id="line2d27"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)" d="M72.000000 294.545455L76.464000 286.669970L80.928000 278.918686 +L85.392000 271.413846L89.856000 264.273805L94.320000 257.611167 +L98.784000 251.531004L103.248000 246.129204L107.712000 241.490958 +L112.176000 237.689413L116.640000 234.784521L121.104000 232.822096 +L125.568000 231.833084L130.032000 231.833084L134.496000 232.822096 +L138.960000 234.784521L143.424000 237.689413L147.888000 241.490958 +L152.352000 246.129204L156.816000 251.531004L161.280000 257.611167 +L165.744000 264.273805L170.208000 271.413846L174.672000 278.918686 +L179.136000 286.669970L183.600000 294.545455L188.064000 302.420939 +L192.528000 310.172223L196.992000 317.677063L201.456000 324.817104 +L205.920000 331.479742L210.384000 337.559905L214.848000 342.961705 +L219.312000 347.599951L223.776000 351.401496L228.240000 354.306388 +L232.704000 356.268813L237.168000 357.257825L241.632000 357.257825 +L246.096000 356.268813L250.560000 354.306388L255.024000 351.401496 +L259.488000 347.599951L263.952000 342.961705L268.416000 337.559905 +L272.880000 331.479742L277.344000 324.817104L281.808000 317.677063 +L286.272000 310.172223L290.736000 302.420939L295.200000 294.545455 +L299.664000 286.669970L304.128000 278.918686L308.592000 271.413846 +L313.056000 264.273805L317.520000 257.611167L321.984000 251.531004 +L326.448000 246.129204L330.912000 241.490958L335.376000 237.689413 +L339.840000 234.784521L344.304000 232.822096L348.768000 231.833084 +L353.232000 231.833084L357.696000 232.822096L362.160000 234.784521 +L366.624000 237.689413L371.088000 241.490958L375.552000 246.129204 +L380.016000 251.531004L384.480000 257.611167L388.944000 264.273805 +L393.408000 271.413846L397.872000 278.918686L402.336000 286.669970 +L406.800000 294.545455L411.264000 302.420939L415.728000 310.172223 +L420.192000 317.677063L424.656000 324.817104L429.120000 331.479742 +L433.584000 337.559905L438.048000 342.961705L442.512000 347.599951 +L446.976000 351.401496L451.440000 354.306388L455.904000 356.268813 +L460.368000 357.257825L464.832000 357.257825L469.296000 356.268813 +L473.760000 354.306388L478.224000 351.401496L482.688000 347.599951 +L487.152000 342.961705L491.616000 337.559905L496.080000 331.479742 +L500.544000 324.817104L505.008000 317.677063L509.472000 310.172223 +L513.936000 302.420939"/> +</g> +<g id="line2d28"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" clip-path="url(#pdceb94b59b302b6d614f8fc54d3b8e04)" d="M72.000000 294.545455L76.464000 275.793333L80.928000 258.219476 +L85.392000 242.928113M112.176000 236.445954L116.640000 250.224309 +L121.104000 266.787525L125.568000 285.094873L130.032000 303.996036 +L134.496000 322.303384L138.960000 338.866600L143.424000 352.644955 +L147.888000 362.772705L152.352000 368.613485L156.816000 369.800299 +L161.280000 366.258574L165.744000 358.210850L170.208000 346.162796 +L174.672000 330.871433L179.136000 313.297576L183.600000 294.545455 +L188.064000 275.793333L192.528000 258.219476L196.992000 242.928113 +M223.776000 236.445954L228.240000 250.224309L232.704000 266.787525 +L237.168000 285.094873L241.632000 303.996036L246.096000 322.303384 +L250.560000 338.866600L255.024000 352.644955L259.488000 362.772705 +L263.952000 368.613485L268.416000 369.800299L272.880000 366.258574 +L277.344000 358.210850L281.808000 346.162796L286.272000 330.871433 +L290.736000 313.297576L295.200000 294.545455L299.664000 275.793333 +L304.128000 258.219476L308.592000 242.928113M335.376000 236.445954 +L339.840000 250.224309L344.304000 266.787525L348.768000 285.094873 +L353.232000 303.996036L357.696000 322.303384L362.160000 338.866600 +L366.624000 352.644955L371.088000 362.772705L375.552000 368.613485 +L380.016000 369.800299L384.480000 366.258574L388.944000 358.210850 +L393.408000 346.162796L397.872000 330.871433L402.336000 313.297576 +L406.800000 294.545455L411.264000 275.793333L415.728000 258.219476 +L420.192000 242.928113M446.976000 236.445954L451.440000 250.224309 +L455.904000 266.787525L460.368000 285.094873L464.832000 303.996036 +L469.296000 322.303384L473.760000 338.866600L478.224000 352.644955 +L482.688000 362.772705L487.152000 368.613485L491.616000 369.800299 +L496.080000 366.258574L500.544000 358.210850L505.008000 346.162796 +L509.472000 330.871433L513.936000 313.297576"/> +</g> +<g id="matplotlib.axis3"> +<g id="xtick6"> +<g id="line2d29"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="72.000000" y="388.800000"/> +</g></g> +<g id="line2d30"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="72.000000" y="231.709091"/> +</g></g> +<g id="text13"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(63.250000,401.706250)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick7"> +<g id="line2d31"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="183.600000" y="388.800000"/> +</g></g> +<g id="line2d32"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="183.600000" y="231.709091"/> +</g></g> +<g id="text14"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(174.975000,401.706250)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick8"> +<g id="line2d33"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="295.200000" y="388.800000"/> +</g></g> +<g id="line2d34"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="295.200000" y="231.709091"/> +</g></g> +<g id="text15"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(286.707812,401.706250)scale(0.120000)"> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick9"> +<g id="line2d35"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="406.800000" y="388.800000"/> +</g></g> +<g id="line2d36"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="406.800000" y="231.709091"/> +</g></g> +<g id="text16"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(398.432812,401.550000)scale(0.120000)"> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="95.410156"/> +</g> +</g> +</g> +<g id="xtick10"> +<g id="line2d37"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m30e32995789d870ad79a2e54c91cf9c6" x="518.400000" y="388.800000"/> +</g></g> +<g id="line2d38"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m9281cae24120827b11d5ea8a7ad3e96b" x="518.400000" y="231.709091"/> +</g></g> +<g id="text17"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(509.689062,401.706250)scale(0.120000)"> +<use xlink:href="#c_ed3f3ed3ebfbd18bcb9c012009a68ad1"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +</g> +<g id="matplotlib.axis4"> +<g id="ytick8"> +<g id="line2d39"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="388.800000"/> +</g></g> +<g id="line2d40"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="388.800000"/> +</g></g> +<g id="text18"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(41.156250,393.089063)scale(0.120000)"> +<use xlink:href="#c_6a8d56c819c37117ab4cf023bec22a5a"/> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7" x="83.789062"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="147.412109"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="179.199219"/> +</g> +</g> +</g> +<g id="ytick9"> +<g id="line2d41"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="357.381818"/> +</g></g> +<g id="line2d42"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="357.381818"/> +</g></g> +<g id="text19"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(40.906250,361.749006)scale(0.120000)"> +<use xlink:href="#c_6a8d56c819c37117ab4cf023bec22a5a"/> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7" x="83.789062"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="147.412109"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="179.199219"/> +</g> +</g> +</g> +<g id="ytick10"> +<g id="line2d43"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="325.963636"/> +</g></g> +<g id="line2d44"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="325.963636"/> +</g></g> +<g id="text20"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(41.156250,330.330824)scale(0.120000)"> +<use xlink:href="#c_6a8d56c819c37117ab4cf023bec22a5a"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="83.789062"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="147.412109"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="179.199219"/> +</g> +</g> +</g> +<g id="ytick11"> +<g id="line2d45"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="294.545455"/> +</g></g> +<g id="line2d46"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="294.545455"/> +</g></g> +<g id="text21"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(50.500000,298.912642)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +<g id="ytick12"> +<g id="line2d47"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="263.127273"/> +</g></g> +<g id="line2d48"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="263.127273"/> +</g></g> +<g id="text22"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(50.750000,267.494460)scale(0.120000)"> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_1260a2df50f305f3db244e29828f968e" x="95.410156"/> +</g> +</g> +</g> +<g id="ytick13"> +<g id="line2d49"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m3400efa6b1638b3fea9e19e898273957" x="72.000000" y="231.709091"/> +</g></g> +<g id="line2d50"> +<g ><use style="fill: none; stroke: #000000; stroke-width: 0.500000; stroke-linejoin: round; stroke-linecap: butt; opacity: 1.000000" xlink:href="#m20b58b2501143cb5e0a5e8f1ef6f1643" x="518.400000" y="231.709091"/> +</g></g> +<g id="text23"> +<g style="fill: #000000; opacity: 1.000000" transform="translate(51.015625,236.076278)scale(0.120000)"> +<use xlink:href="#c_42baa63129a918535c52adb20d687ea7"/> +<use xlink:href="#c_ed3e21196fb739f392806f09ca0594ef" x="63.623047"/> +<use xlink:href="#c_7a2040fe3b94fcd41d0a72c84e93b115" x="95.410156"/> +</g> +</g> +</g> +</g> +<g id="patch8"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" d="M72.000000 231.709091L518.400000 231.709091"/> +</g> +<g id="patch9"> +<path style="fill: none; stroke: #000000; stroke-width: 1.000000; stroke-linejoin: round; stroke-linecap: square; opacity: 1.000000" d="M518.400000 388.800000L518.400000 231.709091"/> +</g> +<g id="... [truncated message content] |
From: <ef...@us...> - 2010-04-28 19:44:53
|
Revision: 8283 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8283&view=rev Author: efiring Date: 2010-04-28 19:44:47 +0000 (Wed, 28 Apr 2010) Log Message: ----------- Applied whitespace patch by Mark Roddy; closes 2993733. Modified Paths: -------------- trunk/matplotlib/examples/api/span_regions.py trunk/matplotlib/examples/pylab_examples/usetex_demo.py trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py trunk/matplotlib/lib/matplotlib/mlab.py trunk/matplotlib/lib/matplotlib/pylab.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py trunk/matplotlib/release/win32/data/setupwin.py trunk/matplotlib/release/win32/data/setupwinegg.py Modified: trunk/matplotlib/examples/api/span_regions.py =================================================================== --- trunk/matplotlib/examples/api/span_regions.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/examples/api/span_regions.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -21,11 +21,11 @@ ax.axhline(0, color='black', lw=2) collection = collections.BrokenBarHCollection.span_where( - t, ymin=0, ymax=1, where=s1>0, facecolor='green', alpha=0.5) + t, ymin=0, ymax=1, where=s1>0, facecolor='green', alpha=0.5) ax.add_collection(collection) collection = collections.BrokenBarHCollection.span_where( - t, ymin=-1, ymax=0, where=s1<0, facecolor='red', alpha=0.5) + t, ymin=-1, ymax=0, where=s1<0, facecolor='red', alpha=0.5) ax.add_collection(collection) Modified: trunk/matplotlib/examples/pylab_examples/usetex_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/usetex_demo.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/examples/pylab_examples/usetex_demo.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -41,8 +41,8 @@ pylab.yticks((0, 0.5, 1), ('0', '.5', '1'), color = 'k', size = 20) ## Right Y-axis labels -pylab.text(1.05, 0.5, r"\bf{level set} $\phi$", {'color' : 'g', 'fontsize' : 20}, - horizontalalignment = 'left', +pylab.text(1.05, 0.5, r"\bf{level set} $\phi$", {'color' : 'g', 'fontsize' : 20}, + horizontalalignment = 'left', verticalalignment = 'center', rotation = 90, clip_on = False) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -138,8 +138,8 @@ def draw_path(self, gc, path, transform, rgbFace=None): - if len(path.vertices) > 18980: - raise ValueError("The Cairo backend can not draw paths longer than 18980 points.") + if len(path.vertices) > 18980: + raise ValueError("The Cairo backend can not draw paths longer than 18980 points.") ctx = gc.ctx @@ -148,7 +148,7 @@ ctx.new_path() self.convert_path(ctx, path, transform) - + self._fill_and_stroke(ctx, rgbFace, gc.get_alpha()) def draw_image(self, gc, x, y, im): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -241,7 +241,7 @@ self._resize_callback(event) # compute desired figure size in inches - dpival = self.figure.dpi + dpival = self.figure.dpi winch = width/dpival hinch = height/dpival self.figure.set_size_inches(winch, hinch) Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -2309,11 +2309,11 @@ if needheader: while 1: - # skip past any comments and consume one line of column header - row = reader.next() - if len(row) and row[0].startswith(comments): - continue - break + # skip past any comments and consume one line of column header + row = reader.next() + if len(row) and row[0].startswith(comments): + continue + break # iterate over the remaining rows and convert the data to date # objects, ints, or floats as approriate Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -252,7 +252,7 @@ import numpy.ma as ma def load(*args, **kwargs): - raise NotImplementedError(load.__doc__) + raise NotImplementedError(load.__doc__) load.__doc__ = """\ pylab no longer provides a load function, though the old pylab function is still available as matplotlib.mlab.load (you can refer @@ -265,7 +265,7 @@ def save(*args, **kwargs): - raise NotImplementedError(save.__doc__) + raise NotImplementedError(save.__doc__) save.__doc__ = """\ pylab no longer provides a save function, though the old pylab function is still available as matplotlib.mlab.save (you can still Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -779,7 +779,7 @@ shade = np.array(shade) mask = ~np.isnan(shade) - if len(shade[mask]) > 0: + if len(shade[mask]) > 0: norm = Normalize(min(shade[mask]), max(shade[mask])) if art3d.iscolor(color): color = color.copy() Modified: trunk/matplotlib/release/win32/data/setupwin.py =================================================================== --- trunk/matplotlib/release/win32/data/setupwin.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/release/win32/data/setupwin.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -1,12 +1,12 @@ from distutils import cygwinccompiler try: - # Python 2.6 - # Replace the msvcr func to return an [] - cygwinccompiler.get_msvcr - cygwinccompiler.get_msvcr = lambda: [] + # Python 2.6 + # Replace the msvcr func to return an [] + cygwinccompiler.get_msvcr + cygwinccompiler.get_msvcr = lambda: [] except AttributeError: - pass + pass execfile('setup.py') Modified: trunk/matplotlib/release/win32/data/setupwinegg.py =================================================================== --- trunk/matplotlib/release/win32/data/setupwinegg.py 2010-04-28 19:17:17 UTC (rev 8282) +++ trunk/matplotlib/release/win32/data/setupwinegg.py 2010-04-28 19:44:47 UTC (rev 8283) @@ -1,13 +1,13 @@ from distutils import cygwinccompiler try: - # Python 2.6 - # Replace the msvcr func to return an empty list - cygwinccompiler.get_msvcr - cygwinccompiler.get_msvcr = lambda: [] + # Python 2.6 + # Replace the msvcr func to return an empty list + cygwinccompiler.get_msvcr + cygwinccompiler.get_msvcr = lambda: [] except AttributeError: - pass + pass from setuptools import setup execfile('setup.py', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-04-28 19:50:17
|
Revision: 8284 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8284&view=rev Author: mdboom Date: 2010-04-28 19:50:11 +0000 (Wed, 28 Apr 2010) Log Message: ----------- Fix docstring formatting. Modified Paths: -------------- trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axis_artist_api.rst trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py Modified: trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axis_artist_api.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axis_artist_api.rst 2010-04-28 19:44:47 UTC (rev 8283) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axis_artist_api.rst 2010-04-28 19:50:11 UTC (rev 8284) @@ -1,6 +1,6 @@ :mod:`mpl_toolkits.axes_grid.axis_artist` -======================================= +========================================= .. autoclass:: mpl_toolkits.axes_grid.axis_artist.AxisArtist :members: Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-04-28 19:44:47 UTC (rev 8283) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-04-28 19:50:11 UTC (rev 8284) @@ -1975,9 +1975,9 @@ Optional keyword arguments: - ============ ===================================== + ============ ========================================= Keyword Description - ============ ===================================== + ============ ========================================= *style* [ 'sci' (or 'scientific') | 'plain' ] plain turns off scientific notation *scilimits* (m, n), pair of integers; if *style* @@ -1991,7 +1991,7 @@ numeric offset is specified, it will be used. *axis* [ 'x' | 'y' | 'both' ] - ============ ===================================== + ============ ========================================= Only the major ticks are affected. If the method is called when the Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-04-28 19:44:47 UTC (rev 8283) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-04-28 19:50:11 UTC (rev 8284) @@ -52,6 +52,7 @@ ================ ========================================= *azim* Azimuthal viewing angle (default -60) *elev* Elevation viewing angle (default 30) + ================ ========================================= ''' if rect is None: @@ -349,9 +350,9 @@ the axes. Also optionally sets the mouse buttons for 3D rotation and zooming. - ============ ================================================ + ============ ======================================================= Argument Description - ============ ================================================ + ============ ======================================================= *rotate_btn* The integer or list of integers specifying which mouse button or buttons to use for 3D rotation of the axes. Default = 1. @@ -359,7 +360,8 @@ *zoom_btn* The integer or list of integers specifying which mouse button or buttons to use to zoom the 3D axes. Default = 3. - ============ ================================================ + ============ ======================================================= + """ self.button_pressed = None canv = self.figure.canvas @@ -636,22 +638,20 @@ but it also supports color mapping by supplying the *cmap* argument. - ========== ================================================ - Argument Description - ========== ================================================ - *X*, *Y*, Data values as numpy.arrays - *Z* - *rstride* Array row stride (step size) - *cstride* Array column stride (step size) - *color* Color of the surface patches - *cmap* A colormap for the surface patches. - *facecolors* Face colors for the individual patches - *norm* An instance of Normalize to map values to colors - *vmin* Minimum value to map - *vmax* Maximum value to map - *shade* Whether to shade the facecolors, default: - false when cmap specified, true otherwise - ========== ================================================ + ============= ================================================ + Argument Description + ============= ================================================ + *X*, *Y*, *Z* Data values as numpy.arrays + *rstride* Array row stride (step size) + *cstride* Array column stride (step size) + *color* Color of the surface patches + *cmap* A colormap for the surface patches. + *facecolors* Face colors for the individual patches + *norm* An instance of Normalize to map values to colors + *vmin* Minimum value to map + *vmax* Maximum value to map + *shade* Whether to shade the facecolors + ============= ================================================ Other arguments are passed on to :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection.__init__` @@ -1083,16 +1083,21 @@ dx, dy, dz can be arrays or scalars. *color* can be: + - A single color value, to color all bars the same color. + - An array of colors of length N bars, to color each bar - independently. - - An array of colors of length 6, to color the faces of the bars - similarly. + independently. + + - An array of colors of length 6, to color the faces of the + bars similarly. + - An array of colors of length 6 * N bars, to color each face - independently. + independently. - When coloring the faces of the boxes specifically, this is the order - of the coloring: + When coloring the faces of the boxes specifically, this is + the order of the coloring: + 1. -Z (bottom of box) 2. +Z (top of box) 3. -Y This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2010-05-04 17:53:39
|
Revision: 8294 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8294&view=rev Author: dsdale Date: 2010-05-04 17:53:33 +0000 (Tue, 04 May 2010) Log Message: ----------- Improve backend_qt4 so it displays figures with the correct size Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-05-04 05:24:53 UTC (rev 8293) +++ trunk/matplotlib/CHANGELOG 2010-05-04 17:53:33 UTC (rev 8294) @@ -1,3 +1,6 @@ +2010-05-04 Improve backend_qt4 so it displays figures with the + correct size - DSD + 2010-04-20 Added generic support for connecting to a timer for events. This adds TimerBase, TimerGTK, TimerQT, TimerWx, and TimerTk to the backends and a new_timer() method to each backend's Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2010-05-04 05:24:53 UTC (rev 8293) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2010-05-04 17:53:33 UTC (rev 8294) @@ -318,6 +318,13 @@ QtCore.QObject.connect(self.toolbar, QtCore.SIGNAL("message"), self.window.statusBar().showMessage) + # resize the main window so it will display the canvas with the + # requested size: + cs = canvas.sizeHint() + tbs = self.toolbar.sizeHint() + sbs = self.window.statusBar().sizeHint() + self.window.resize(cs.width(), cs.height()+tbs.height()+sbs.height()) + self.window.setCentralWidget(self.canvas) if matplotlib.is_interactive(): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ian...@us...> - 2010-05-13 09:13:56
|
Revision: 8316 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8316&view=rev Author: ianthomas23 Date: 2010-05-13 09:13:49 +0000 (Thu, 13 May 2010) Log Message: ----------- Added triangular grid plotting and contouring functions. Modified Paths: -------------- trunk/matplotlib/boilerplate.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/pyplot.py trunk/matplotlib/setup.py trunk/matplotlib/setupext.py Added Paths: ----------- trunk/matplotlib/examples/misc/contour_manual.py trunk/matplotlib/examples/pylab_examples/tricontour_demo.py trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py trunk/matplotlib/examples/pylab_examples/triplot_demo.py trunk/matplotlib/lib/matplotlib/tri/ trunk/matplotlib/lib/matplotlib/tri/__init__.py trunk/matplotlib/lib/matplotlib/tri/_tri.cpp trunk/matplotlib/lib/matplotlib/tri/_tri.h trunk/matplotlib/lib/matplotlib/tri/triangulation.py trunk/matplotlib/lib/matplotlib/tri/tricontour.py trunk/matplotlib/lib/matplotlib/tri/tripcolor.py trunk/matplotlib/lib/matplotlib/tri/triplot.py Modified: trunk/matplotlib/boilerplate.py =================================================================== --- trunk/matplotlib/boilerplate.py 2010-05-12 17:58:17 UTC (rev 8315) +++ trunk/matplotlib/boilerplate.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -89,6 +89,10 @@ #'spy', 'stem', 'step', + 'tricontour', + 'tricontourf', + 'tripcolor', + 'triplot', 'vlines', 'xcorr', 'barbs', @@ -117,6 +121,9 @@ #'spy' : 'sci(%(ret)s)', ### may return image or Line2D 'quiver' : 'sci(%(ret)s)', 'specgram' : 'sci(%(ret)s[-1])', + 'tricontour' : 'if %(ret)s._A is not None: sci(%(ret)s)', + 'tricontourf': 'if %(ret)s._A is not None: sci(%(ret)s)', + 'tripcolor' : 'sci(%(ret)s)', } Added: trunk/matplotlib/examples/misc/contour_manual.py =================================================================== --- trunk/matplotlib/examples/misc/contour_manual.py (rev 0) +++ trunk/matplotlib/examples/misc/contour_manual.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -0,0 +1,50 @@ +""" +Example of displaying your own contour lines and polygons using ContourSet. +""" +import matplotlib.pyplot as plt +from matplotlib.contour import ContourSet +import matplotlib.cm as cm + +# Contour lines for each level are a list/tuple of polygons. +lines0 = [ [[0,0],[0,4]] ] +lines1 = [ [[2,0],[1,2],[1,3]] ] +lines2 = [ [[3,0],[3,2]], [[3,3],[3,4]] ] # Note two lines. + +# Filled contours between two levels are also a list/tuple of polygons. +# Points can be ordered clockwise or anticlockwise. +filled01 = [ [[0,0],[0,4],[1,3],[1,2],[2,0]] ] +filled12 = [ [[2,0],[3,0],[3,2],[1,3],[1,2]], # Note two polygons. + [[1,4],[3,4],[3,3]] ] + + +plt.figure() + +# Filled contours using filled=True. +cs = ContourSet(plt.gca(), [0,1,2], [filled01, filled12], filled=True, cmap=cm.bone) +cbar = plt.colorbar(cs) + +# Contour lines (non-filled). +lines = ContourSet(plt.gca(), [0,1,2], [lines0, lines1, lines2], cmap=cm.cool, + linewidths=3) +cbar.add_lines(lines) + +plt.axis([-0.5, 3.5, -0.5, 4.5]) +plt.title('User-specified contours') + + + +# Multiple filled contour lines can be specified in a single list of polygon +# vertices along with a list of vertex kinds (code types) as described in the +# Path class. This is particularly useful for polygons with holes. +# Here a code type of 1 is a MOVETO, and 2 is a LINETO. + +plt.figure() +filled01 = [ [[0,0],[3,0],[3,3],[0,3],[1,1],[1,2],[2,2],[2,1]] ] +kinds01 = [ [1,2,2,2,1,2,2,2] ] +cs = ContourSet(plt.gca(), [0,1], [filled01], [kinds01], filled=True) +cbar = plt.colorbar(cs) + +plt.axis([-0.5, 3.5, -0.5, 3.5]) +plt.title('User specified filled contours with holes') + +plt.show() \ No newline at end of file Property changes on: trunk/matplotlib/examples/misc/contour_manual.py ___________________________________________________________________ Added: svn:keywords + Id Added: trunk/matplotlib/examples/pylab_examples/tricontour_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/tricontour_demo.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/tricontour_demo.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -0,0 +1,98 @@ +""" +Contour plots of unstructured triangular grids. +""" +import matplotlib.pyplot as plt +import matplotlib.tri as tri +import numpy as np +import math + +# Creating a Triangulation without specifying the triangles results in the +# Delaunay triangulation of the points. + +# First create the x and y coordinates of the points. +n_angles = 48 +n_radii = 8 +min_radius = 0.25 +radii = np.linspace(min_radius, 0.95, n_radii) + +angles = np.linspace(0, 2*math.pi, n_angles, endpoint=False) +angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1) +angles[:,1::2] += math.pi/n_angles + +x = (radii*np.cos(angles)).flatten() +y = (radii*np.sin(angles)).flatten() +z = (np.cos(radii)*np.cos(angles*3.0)).flatten() + +# Create the Triangulation; no triangles so Delaunay triangulation created. +triang = tri.Triangulation(x, y) + +# Mask off unwanted triangles. +xmid = x[triang.triangles].mean(axis=1) +ymid = y[triang.triangles].mean(axis=1) +mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0) +triang.set_mask(mask) + +# pcolor plot. +plt.figure() +plt.gca().set_aspect('equal') +plt.tricontourf(triang, z) +plt.colorbar() +plt.tricontour(triang, z, colors='k') +plt.title('Contour plot of Delaunay triangulation') + +# You can specify your own triangulation rather than perform a Delaunay +# triangulation of the points, where each triangle is given by the indices of +# the three points that make up the triangle, ordered in either a clockwise or +# anticlockwise manner. + +xy = np.asarray([ + [-0.101,0.872],[-0.080,0.883],[-0.069,0.888],[-0.054,0.890],[-0.045,0.897], + [-0.057,0.895],[-0.073,0.900],[-0.087,0.898],[-0.090,0.904],[-0.069,0.907], + [-0.069,0.921],[-0.080,0.919],[-0.073,0.928],[-0.052,0.930],[-0.048,0.942], + [-0.062,0.949],[-0.054,0.958],[-0.069,0.954],[-0.087,0.952],[-0.087,0.959], + [-0.080,0.966],[-0.085,0.973],[-0.087,0.965],[-0.097,0.965],[-0.097,0.975], + [-0.092,0.984],[-0.101,0.980],[-0.108,0.980],[-0.104,0.987],[-0.102,0.993], + [-0.115,1.001],[-0.099,0.996],[-0.101,1.007],[-0.090,1.010],[-0.087,1.021], + [-0.069,1.021],[-0.052,1.022],[-0.052,1.017],[-0.069,1.010],[-0.064,1.005], + [-0.048,1.005],[-0.031,1.005],[-0.031,0.996],[-0.040,0.987],[-0.045,0.980], + [-0.052,0.975],[-0.040,0.973],[-0.026,0.968],[-0.020,0.954],[-0.006,0.947], + [ 0.003,0.935],[ 0.006,0.926],[ 0.005,0.921],[ 0.022,0.923],[ 0.033,0.912], + [ 0.029,0.905],[ 0.017,0.900],[ 0.012,0.895],[ 0.027,0.893],[ 0.019,0.886], + [ 0.001,0.883],[-0.012,0.884],[-0.029,0.883],[-0.038,0.879],[-0.057,0.881], + [-0.062,0.876],[-0.078,0.876],[-0.087,0.872],[-0.030,0.907],[-0.007,0.905], + [-0.057,0.916],[-0.025,0.933],[-0.077,0.990],[-0.059,0.993] ]) +x = xy[:,0]*180/3.14159 +y = xy[:,1]*180/3.14159 +x0 = -5 +y0 = 52 +z = np.exp(-0.01*( (x-x0)*(x-x0) + (y-y0)*(y-y0) )) + +triangles = np.asarray([ + [67,66, 1],[65, 2,66],[ 1,66, 2],[64, 2,65],[63, 3,64],[60,59,57], + [ 2,64, 3],[ 3,63, 4],[ 0,67, 1],[62, 4,63],[57,59,56],[59,58,56], + [61,60,69],[57,69,60],[ 4,62,68],[ 6, 5, 9],[61,68,62],[69,68,61], + [ 9, 5,70],[ 6, 8, 7],[ 4,70, 5],[ 8, 6, 9],[56,69,57],[69,56,52], + [70,10, 9],[54,53,55],[56,55,53],[68,70, 4],[52,56,53],[11,10,12], + [69,71,68],[68,13,70],[10,70,13],[51,50,52],[13,68,71],[52,71,69], + [12,10,13],[71,52,50],[71,14,13],[50,49,71],[49,48,71],[14,16,15], + [14,71,48],[17,19,18],[17,20,19],[48,16,14],[48,47,16],[47,46,16], + [16,46,45],[23,22,24],[21,24,22],[17,16,45],[20,17,45],[21,25,24], + [27,26,28],[20,72,21],[25,21,72],[45,72,20],[25,28,26],[44,73,45], + [72,45,73],[28,25,29],[29,25,31],[43,73,44],[73,43,40],[72,73,39], + [72,31,25],[42,40,43],[31,30,29],[39,73,40],[42,41,40],[72,33,31], + [32,31,33],[39,38,72],[33,72,38],[33,38,34],[37,35,38],[34,38,35], + [35,37,36] ]) + +# Rather than create a Triangulation object, can simply pass x, y and triangles +# arrays to tripcolor directly. It would be better to use a Triangulation object +# if the same triangulation was to be used more than once to save duplicated +# calculations. +plt.figure() +plt.gca().set_aspect('equal') +plt.tricontourf(x, y, triangles, z) +plt.colorbar() +plt.title('Contour plot of user-specified triangulation') +plt.xlabel('Longitude (degrees)') +plt.ylabel('Latitude (degrees)') + +plt.show() Property changes on: trunk/matplotlib/examples/pylab_examples/tricontour_demo.py ___________________________________________________________________ Added: svn:keywords + Id Added: trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -0,0 +1,47 @@ +""" +Comparison of griddata and tricontour for an unstructured triangular grid. +""" +import matplotlib.pyplot as plt +import matplotlib.tri as tri +import numpy as np +from numpy.random import uniform, seed +from matplotlib.mlab import griddata +import time + +seed(0) +npts = 200 +ngridx = 100 +ngridy = 200 +x = uniform(-2,2,npts) +y = uniform(-2,2,npts) +z = x*np.exp(-x**2-y**2) + +# griddata and contour. +start = time.clock() +plt.subplot(211) +xi = np.linspace(-2.1,2.1,ngridx) +yi = np.linspace(-2.1,2.1,ngridy) +zi = griddata(x,y,z,xi,yi,interp='linear') +plt.contour(xi,yi,zi,15,linewidths=0.5,colors='k') +plt.contourf(xi,yi,zi,15,cmap=plt.cm.jet) +plt.colorbar() # draw colorbar +plt.plot(x, y, 'ko', ms=3) +plt.xlim(-2,2) +plt.ylim(-2,2) +plt.title('griddata and contour (%d points, %d grid points)' % (npts, ngridx*ngridy)) +print 'griddata and contour seconds:', time.clock() - start + +# tricontour. +start = time.clock() +plt.subplot(212) +triang = tri.Triangulation(x, y) +plt.tricontour(x, y, z, 15, linewidths=0.5, colors='k') +plt.tricontourf(x, y, z, 15, cmap=plt.cm.jet) +plt.colorbar() +plt.plot(x, y, 'ko', ms=3) +plt.xlim(-2,2) +plt.ylim(-2,2) +plt.title('tricontour (%d points)' % npts) +print 'tricontour seconds:', time.clock() - start + +plt.show() Property changes on: trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py ___________________________________________________________________ Added: svn:keywords + Id Added: trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -0,0 +1,98 @@ +""" +Pseudocolor plots of unstructured triangular grids. +""" +import matplotlib.pyplot as plt +import matplotlib.tri as tri +import numpy as np +import math + +# Creating a Triangulation without specifying the triangles results in the +# Delaunay triangulation of the points. + +# First create the x and y coordinates of the points. +n_angles = 36 +n_radii = 8 +min_radius = 0.25 +radii = np.linspace(min_radius, 0.95, n_radii) + +angles = np.linspace(0, 2*math.pi, n_angles, endpoint=False) +angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1) +angles[:,1::2] += math.pi/n_angles + +x = (radii*np.cos(angles)).flatten() +y = (radii*np.sin(angles)).flatten() +z = (np.cos(radii)*np.cos(angles*3.0)).flatten() + +# Create the Triangulation; no triangles so Delaunay triangulation created. +triang = tri.Triangulation(x, y) + +# Mask off unwanted triangles. +xmid = x[triang.triangles].mean(axis=1) +ymid = y[triang.triangles].mean(axis=1) +mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0) +triang.set_mask(mask) + +# pcolor plot. +plt.figure() +plt.gca().set_aspect('equal') +plt.tripcolor(triang, z, shading='faceted') +plt.colorbar() +plt.title('tripcolor of Delaunay triangulation') + + +# You can specify your own triangulation rather than perform a Delaunay +# triangulation of the points, where each triangle is given by the indices of +# the three points that make up the triangle, ordered in either a clockwise or +# anticlockwise manner. + +xy = np.asarray([ + [-0.101,0.872],[-0.080,0.883],[-0.069,0.888],[-0.054,0.890],[-0.045,0.897], + [-0.057,0.895],[-0.073,0.900],[-0.087,0.898],[-0.090,0.904],[-0.069,0.907], + [-0.069,0.921],[-0.080,0.919],[-0.073,0.928],[-0.052,0.930],[-0.048,0.942], + [-0.062,0.949],[-0.054,0.958],[-0.069,0.954],[-0.087,0.952],[-0.087,0.959], + [-0.080,0.966],[-0.085,0.973],[-0.087,0.965],[-0.097,0.965],[-0.097,0.975], + [-0.092,0.984],[-0.101,0.980],[-0.108,0.980],[-0.104,0.987],[-0.102,0.993], + [-0.115,1.001],[-0.099,0.996],[-0.101,1.007],[-0.090,1.010],[-0.087,1.021], + [-0.069,1.021],[-0.052,1.022],[-0.052,1.017],[-0.069,1.010],[-0.064,1.005], + [-0.048,1.005],[-0.031,1.005],[-0.031,0.996],[-0.040,0.987],[-0.045,0.980], + [-0.052,0.975],[-0.040,0.973],[-0.026,0.968],[-0.020,0.954],[-0.006,0.947], + [ 0.003,0.935],[ 0.006,0.926],[ 0.005,0.921],[ 0.022,0.923],[ 0.033,0.912], + [ 0.029,0.905],[ 0.017,0.900],[ 0.012,0.895],[ 0.027,0.893],[ 0.019,0.886], + [ 0.001,0.883],[-0.012,0.884],[-0.029,0.883],[-0.038,0.879],[-0.057,0.881], + [-0.062,0.876],[-0.078,0.876],[-0.087,0.872],[-0.030,0.907],[-0.007,0.905], + [-0.057,0.916],[-0.025,0.933],[-0.077,0.990],[-0.059,0.993] ]) +x = xy[:,0]*180/3.14159 +y = xy[:,1]*180/3.14159 +x0 = -5 +y0 = 52 +z = np.exp(-0.01*( (x-x0)*(x-x0) + (y-y0)*(y-y0) )) + +triangles = np.asarray([ + [67,66, 1],[65, 2,66],[ 1,66, 2],[64, 2,65],[63, 3,64],[60,59,57], + [ 2,64, 3],[ 3,63, 4],[ 0,67, 1],[62, 4,63],[57,59,56],[59,58,56], + [61,60,69],[57,69,60],[ 4,62,68],[ 6, 5, 9],[61,68,62],[69,68,61], + [ 9, 5,70],[ 6, 8, 7],[ 4,70, 5],[ 8, 6, 9],[56,69,57],[69,56,52], + [70,10, 9],[54,53,55],[56,55,53],[68,70, 4],[52,56,53],[11,10,12], + [69,71,68],[68,13,70],[10,70,13],[51,50,52],[13,68,71],[52,71,69], + [12,10,13],[71,52,50],[71,14,13],[50,49,71],[49,48,71],[14,16,15], + [14,71,48],[17,19,18],[17,20,19],[48,16,14],[48,47,16],[47,46,16], + [16,46,45],[23,22,24],[21,24,22],[17,16,45],[20,17,45],[21,25,24], + [27,26,28],[20,72,21],[25,21,72],[45,72,20],[25,28,26],[44,73,45], + [72,45,73],[28,25,29],[29,25,31],[43,73,44],[73,43,40],[72,73,39], + [72,31,25],[42,40,43],[31,30,29],[39,73,40],[42,41,40],[72,33,31], + [32,31,33],[39,38,72],[33,72,38],[33,38,34],[37,35,38],[34,38,35], + [35,37,36] ]) + +# Rather than create a Triangulation object, can simply pass x, y and triangles +# arrays to tripcolor directly. It would be better to use a Triangulation object +# if the same triangulation was to be used more than once to save duplicated +# calculations. +plt.figure() +plt.gca().set_aspect('equal') +plt.tripcolor(x, y, triangles, z, shading='faceted') +plt.colorbar() +plt.title('tripcolor of user-specified triangulation') +plt.xlabel('Longitude (degrees)') +plt.ylabel('Latitude (degrees)') + +plt.show() Property changes on: trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py ___________________________________________________________________ Added: svn:keywords + Id Added: trunk/matplotlib/examples/pylab_examples/triplot_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/triplot_demo.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/triplot_demo.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -0,0 +1,92 @@ +""" +Creating and plotting unstructured triangular grids. +""" +import matplotlib.pyplot as plt +import matplotlib.tri as tri +import numpy as np +import math + +# Creating a Triangulation without specifying the triangles results in the +# Delaunay triangulation of the points. + +# First create the x and y coordinates of the points. +n_angles = 36 +n_radii = 8 +min_radius = 0.25 +radii = np.linspace(min_radius, 0.95, n_radii) + +angles = np.linspace(0, 2*math.pi, n_angles, endpoint=False) +angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1) +angles[:,1::2] += math.pi/n_angles + +x = (radii*np.cos(angles)).flatten() +y = (radii*np.sin(angles)).flatten() + +# Create the Triangulation; no triangles so Delaunay triangulation created. +triang = tri.Triangulation(x, y) + +# Mask off unwanted triangles. +xmid = x[triang.triangles].mean(axis=1) +ymid = y[triang.triangles].mean(axis=1) +mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0) +triang.set_mask(mask) + +# Plot the triangulation. +plt.figure() +plt.gca().set_aspect('equal') +plt.triplot(triang, 'bo-') +plt.title('triplot of Delaunay triangulation') + + +# You can specify your own triangulation rather than perform a Delaunay +# triangulation of the points, where each triangle is given by the indices of +# the three points that make up the triangle, ordered in either a clockwise or +# anticlockwise manner. + +xy = np.asarray([ + [-0.101,0.872],[-0.080,0.883],[-0.069,0.888],[-0.054,0.890],[-0.045,0.897], + [-0.057,0.895],[-0.073,0.900],[-0.087,0.898],[-0.090,0.904],[-0.069,0.907], + [-0.069,0.921],[-0.080,0.919],[-0.073,0.928],[-0.052,0.930],[-0.048,0.942], + [-0.062,0.949],[-0.054,0.958],[-0.069,0.954],[-0.087,0.952],[-0.087,0.959], + [-0.080,0.966],[-0.085,0.973],[-0.087,0.965],[-0.097,0.965],[-0.097,0.975], + [-0.092,0.984],[-0.101,0.980],[-0.108,0.980],[-0.104,0.987],[-0.102,0.993], + [-0.115,1.001],[-0.099,0.996],[-0.101,1.007],[-0.090,1.010],[-0.087,1.021], + [-0.069,1.021],[-0.052,1.022],[-0.052,1.017],[-0.069,1.010],[-0.064,1.005], + [-0.048,1.005],[-0.031,1.005],[-0.031,0.996],[-0.040,0.987],[-0.045,0.980], + [-0.052,0.975],[-0.040,0.973],[-0.026,0.968],[-0.020,0.954],[-0.006,0.947], + [ 0.003,0.935],[ 0.006,0.926],[ 0.005,0.921],[ 0.022,0.923],[ 0.033,0.912], + [ 0.029,0.905],[ 0.017,0.900],[ 0.012,0.895],[ 0.027,0.893],[ 0.019,0.886], + [ 0.001,0.883],[-0.012,0.884],[-0.029,0.883],[-0.038,0.879],[-0.057,0.881], + [-0.062,0.876],[-0.078,0.876],[-0.087,0.872],[-0.030,0.907],[-0.007,0.905], + [-0.057,0.916],[-0.025,0.933],[-0.077,0.990],[-0.059,0.993] ]) +x = xy[:,0]*180/3.14159 +y = xy[:,1]*180/3.14159 + +triangles = np.asarray([ + [67,66, 1],[65, 2,66],[ 1,66, 2],[64, 2,65],[63, 3,64],[60,59,57], + [ 2,64, 3],[ 3,63, 4],[ 0,67, 1],[62, 4,63],[57,59,56],[59,58,56], + [61,60,69],[57,69,60],[ 4,62,68],[ 6, 5, 9],[61,68,62],[69,68,61], + [ 9, 5,70],[ 6, 8, 7],[ 4,70, 5],[ 8, 6, 9],[56,69,57],[69,56,52], + [70,10, 9],[54,53,55],[56,55,53],[68,70, 4],[52,56,53],[11,10,12], + [69,71,68],[68,13,70],[10,70,13],[51,50,52],[13,68,71],[52,71,69], + [12,10,13],[71,52,50],[71,14,13],[50,49,71],[49,48,71],[14,16,15], + [14,71,48],[17,19,18],[17,20,19],[48,16,14],[48,47,16],[47,46,16], + [16,46,45],[23,22,24],[21,24,22],[17,16,45],[20,17,45],[21,25,24], + [27,26,28],[20,72,21],[25,21,72],[45,72,20],[25,28,26],[44,73,45], + [72,45,73],[28,25,29],[29,25,31],[43,73,44],[73,43,40],[72,73,39], + [72,31,25],[42,40,43],[31,30,29],[39,73,40],[42,41,40],[72,33,31], + [32,31,33],[39,38,72],[33,72,38],[33,38,34],[37,35,38],[34,38,35], + [35,37,36] ]) + +# Rather than create a Triangulation object, can simply pass x, y and triangles +# arrays to triplot directly. It would be better to use a Triangulation object +# if the same triangulation was to be used more than once to save duplicated +# calculations. +plt.figure() +plt.gca().set_aspect('equal') +plt.triplot(x, y, triangles, 'go-') +plt.title('triplot of user-specified triangulation') +plt.xlabel('Longitude (degrees)') +plt.ylabel('Latitude (degrees)') + +plt.show() Property changes on: trunk/matplotlib/examples/pylab_examples/triplot_demo.py ___________________________________________________________________ Added: svn:keywords + Id Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-05-12 17:58:17 UTC (rev 8315) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -32,6 +32,7 @@ import matplotlib.text as mtext import matplotlib.ticker as mticker import matplotlib.transforms as mtransforms +import matplotlib.tri as mtri iterable = cbook.iterable @@ -8021,7 +8022,23 @@ self.xaxis.set_minor_locator(mticker.NullLocator()) self.yaxis.set_minor_locator(mticker.NullLocator()) + def tricontour(self, *args, **kwargs): + return mtri.tricontour(self, *args, **kwargs) + tricontour.__doc__ = mtri.TriContourSet.tricontour_doc + def tricontourf(self, *args, **kwargs): + return mtri.tricontourf(self, *args, **kwargs) + tricontourf.__doc__ = mtri.TriContourSet.tricontour_doc + + def tripcolor(self, *args, **kwargs): + return mtri.tripcolor(self, *args, **kwargs) + tripcolor.__doc__ = mtri.tripcolor.__doc__ + + def triplot(self, *args, **kwargs): + mtri.triplot(self, *args, **kwargs) + triplot.__doc__ = mtri.triplot.__doc__ + + class SubplotBase: """ Base class for subplots, which are :class:`Axes` instances with Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-12 17:58:17 UTC (rev 8315) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -2427,6 +2427,78 @@ # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost +@autogen_docstring(Axes.tricontour) +def tricontour(*args, **kwargs): + ax = gca() + # allow callers to override the hold state by passing hold=True|False + washold = ax.ishold() + hold = kwargs.pop('hold', None) + if hold is not None: + ax.hold(hold) + try: + ret = ax.tricontour(*args, **kwargs) + draw_if_interactive() + finally: + ax.hold(washold) + if ret._A is not None: sci(ret) + return ret + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost +@autogen_docstring(Axes.tricontourf) +def tricontourf(*args, **kwargs): + ax = gca() + # allow callers to override the hold state by passing hold=True|False + washold = ax.ishold() + hold = kwargs.pop('hold', None) + if hold is not None: + ax.hold(hold) + try: + ret = ax.tricontourf(*args, **kwargs) + draw_if_interactive() + finally: + ax.hold(washold) + if ret._A is not None: sci(ret) + return ret + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost +@autogen_docstring(Axes.tripcolor) +def tripcolor(*args, **kwargs): + ax = gca() + # allow callers to override the hold state by passing hold=True|False + washold = ax.ishold() + hold = kwargs.pop('hold', None) + if hold is not None: + ax.hold(hold) + try: + ret = ax.tripcolor(*args, **kwargs) + draw_if_interactive() + finally: + ax.hold(washold) + sci(ret) + return ret + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost +@autogen_docstring(Axes.triplot) +def triplot(*args, **kwargs): + ax = gca() + # allow callers to override the hold state by passing hold=True|False + washold = ax.ishold() + hold = kwargs.pop('hold', None) + if hold is not None: + ax.hold(hold) + try: + ret = ax.triplot(*args, **kwargs) + draw_if_interactive() + finally: + ax.hold(washold) + + return ret + +# This function was autogenerated by boilerplate.py. Do not edit as +# changes will be lost @autogen_docstring(Axes.vlines) def vlines(x, ymin, ymax, colors='k', linestyles='solid', label='', hold=None, **kwargs): ax = gca() Added: trunk/matplotlib/lib/matplotlib/tri/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/tri/__init__.py (rev 0) +++ trunk/matplotlib/lib/matplotlib/tri/__init__.py 2010-05-13 09:13:49 UTC (rev 8316) @@ -0,0 +1,8 @@ +""" +Unstructured triangular grid functions. +""" + +from triangulation import * +from tricontour import * +from tripcolor import * +from triplot import * Property changes on: trunk/matplotlib/lib/matplotlib/tri/__init__.py ___________________________________________________________________ Added: svn:keywords + Id Added: trunk/matplotlib/lib/matplotlib/tri/_tri.cpp =================================================================== --- trunk/matplotlib/lib/matplotlib/tri/_tri.cpp (rev 0) +++ trunk/matplotlib/lib/matplotlib/tri/_tri.cpp 2010-05-13 09:13:49 UTC (rev 8316) @@ -0,0 +1,1112 @@ +#include "_tri.h" +#include "src/mplutils.h" + +#include <algorithm> +#include <iostream> +#include <set> + +#define MOVETO 1 +#define LINETO 2 + + + +TriEdge::TriEdge() + : tri(-1), edge(-1) +{} + +TriEdge::TriEdge(int tri_, int edge_) + : tri(tri_), edge(edge_) +{} + +bool TriEdge::operator<(const TriEdge& other) const +{ + if (tri != other.tri) + return tri < other.tri; + else + return edge < other.edge; +} + +bool TriEdge::operator==(const TriEdge& other) const +{ + return tri == other.tri && edge == other.edge; +} + +bool TriEdge::operator!=(const TriEdge& other) const +{ + return !operator==(other); +} + +std::ostream& operator<<(std::ostream& os, const TriEdge& tri_edge) +{ + return os << tri_edge.tri << ' ' << tri_edge.edge; +} + + + +XY::XY() +{} + +XY::XY(const double& x_, const double& y_) + : x(x_), y(y_) +{} + +double XY::angle() const +{ + return atan2(y, x); +} + +double XY::cross_z(const XY& other) const +{ + return x*other.y - y*other.x; +} + +bool XY::operator==(const XY& other) const +{ + return x == other.x && y == other.y; +} + +bool XY::operator!=(const XY& other) const +{ + return x != other.x || y != other.y; +} + +bool XY::operator<(const XY& other) const +{ + if (y == other.y) + return x < other.x; + else + return y < other.y; +} + +XY XY::operator*(const double& multiplier) const +{ + return XY(x*multiplier, y*multiplier); +} + +XY XY::operator+(const XY& other) const +{ + return XY(x + other.x, y + other.y); +} + +XY XY::operator-(const XY& other) const +{ + return XY(x - other.x, y - other.y); +} + +std::ostream& operator<<(std::ostream& os, const XY& xy) +{ + return os << '(' << xy.x << ' ' << xy.y << ')'; +} + + + +BoundingBox::BoundingBox() + : empty(true) +{} + +void BoundingBox::add(const XY& point) +{ + if (empty) { + empty = false; + lower = upper = point; + } else { + if (point.x < lower.x) lower.x = point.x; + else if (point.x > upper.x) upper.x = point.x; + + if (point.y < lower.y) lower.y = point.y; + else if (point.y > upper.y) upper.y = point.y; + } +} + +bool BoundingBox::contains_x(const double& x) const +{ + return !empty && x >= lower.x && x <= upper.x; +} + +std::ostream& operator<<(std::ostream& os, const BoundingBox& box) +{ + if (box.empty) + return os << "<empty>"; + else + return os << box.lower << " -> " << box.upper; +} + + + +ContourLine::ContourLine() + : std::vector<XY>() +{} + +void ContourLine::insert_unique(iterator pos, const XY& point) +{ + if (empty() || pos == end() || point != *pos) + std::vector<XY>::insert(pos, point); +} + +void ContourLine::push_back(const XY& point) +{ + if (empty() || point != back()) + std::vector<XY>::push_back(point); +} + +void ContourLine::write() const +{ + std::cout << "ContourLine of " << size() << " points:"; + for (const_iterator it = begin(); it != end(); ++it) + std::cout << ' ' << *it; + std::cout << std::endl; +} + + + +void write_contour(const Contour& contour) +{ + std::cout << "Contour of " << contour.size() << " lines." << std::endl; + for (Contour::const_iterator it = contour.begin(); it != contour.end(); ++it) + it->write(); +} + + + + +Triangulation::Triangulation(PyArrayObject* x, + PyArrayObject* y, + PyArrayObject* triangles, + PyArrayObject* mask, + PyArrayObject* edges, + PyArrayObject* neighbors) + : _npoints(PyArray_DIM(x,0)), + _ntri(PyArray_DIM(triangles,0)), + _x(x), + _y(y), + _triangles(triangles), + _mask(mask), + _edges(edges), + _neighbors(neighbors) +{ + _VERBOSE("Triangulation::Triangulation"); + correct_triangles(); +} + +Triangulation::~Triangulation() +{ + _VERBOSE("Triangulation::~Triangulation"); + Py_XDECREF(_x); + Py_XDECREF(_y); + Py_XDECREF(_triangles); + Py_XDECREF(_mask); + Py_XDECREF(_edges); + Py_XDECREF(_neighbors); +} + +void Triangulation::calculate_boundaries() +{ + _VERBOSE("Triangulation::calculate_boundaries"); + + get_neighbors(); // Ensure _neighbors has been created. + + // Create set of all boundary TriEdges, which are those which do not + // have a neighbor triangle. + typedef std::set<TriEdge> BoundaryEdges; + BoundaryEdges boundary_edges; + for (int tri = 0; tri < _ntri; ++tri) { + if (!is_masked(tri)) { + for (int edge = 0; edge < 3; ++edge) { + if (get_neighbor(tri, edge) == -1) { + boundary_edges.insert(TriEdge(tri, edge)); + } + } + } + } + + // Take any boundary edge and follow the boundary until return to start + // point, removing edges from boundary_edges as they are used. At the same + // time, initialise the _tri_edge_to_boundary_map. + while (!boundary_edges.empty()) { + // Start of new boundary. + BoundaryEdges::iterator it = boundary_edges.begin(); + int tri = it->tri; + int edge = it->edge; + _boundaries.push_back(Boundary()); + Boundary& boundary = _boundaries.back(); + + while (true) { + boundary.push_back(TriEdge(tri, edge)); + boundary_edges.erase(it); + _tri_edge_to_boundary_map[TriEdge(tri, edge)] = + BoundaryEdge(_boundaries.size()-1, boundary.size()-1); + + // Move to next edge of current triangle. + edge = (edge+1) % 3; + + // Find start point index of boundary edge. + int point = get_triangle_point(tri, edge); + + // Find next TriEdge by traversing neighbors until find one + // without a neighbor. + while (get_neighbor(tri, edge) != -1) { + tri = get_neighbor(tri, edge); + edge = get_edge_in_triangle(tri, point); + } + + if (TriEdge(tri,edge) == boundary.front()) + break; // Reached beginning of this boundary, so finished it. + else + it = boundary_edges.find(TriEdge(tri, edge)); + } + } +} + +void Triangulation::calculate_edges() +{ + _VERBOSE("Triangulation::calculate_edges"); + Py_XDECREF(_edges); + + // Create set of all edges, storing them with start point index less than + // end point index. + typedef std::set<Edge> EdgeSet; + EdgeSet edge_set; + for (int tri = 0; tri < _ntri; ++tri) { + if (!is_masked(tri)) { + for (int edge = 0; edge < 3; edge++) { + int start = get_triangle_point(tri, edge); + int end = get_triangle_point(tri, (edge+1)%3); + edge_set.insert(start > end ? Edge(start,end) : Edge(end,start)); + } + } + } + + // Convert to python _edges array. + npy_intp dims[2] = {edge_set.size(), 2}; + _edges = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_INT); + int* edges_ptr = (int*)PyArray_DATA(_edges); + for (EdgeSet::const_iterator it = edge_set.begin(); it != edge_set.end(); ++it) { + *edges_ptr++ = it->start; + *edges_ptr++ = it->end; + } +} + +void Triangulation::calculate_neighbors() +{ + _VERBOSE("Triangulation::calculate_neighbors"); + Py_XDECREF(_neighbors); + + // Create _neighbors array with shape (ntri,3) and initialise all to -1. + npy_intp dims[2] = {_ntri,3}; + _neighbors = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_INT); + int* neighbors_ptr = (int*)PyArray_DATA(_neighbors); + std::fill(neighbors_ptr, neighbors_ptr + 3*_ntri, -1); + + // For each triangle edge (start to end point), find corresponding neighbor + // edge from end to start point. Do this by traversing all edges and + // storing them in a map from edge to TriEdge. If corresponding neighbor + // edge is already in the map, don't need to store new edge as neighbor + // already found. + typedef std::map<Edge, TriEdge> EdgeToTriEdgeMap; + EdgeToTriEdgeMap edge_to_tri_edge_map; + for (int tri = 0; tri < _ntri; ++tri) { + if (!is_masked(tri)) { + for (int edge = 0; edge < 3; ++edge) { + int start = get_triangle_point(tri, edge); + int end = get_triangle_point(tri, (edge+1)%3); + EdgeToTriEdgeMap::iterator it = + edge_to_tri_edge_map.find(Edge(end,start)); + if (it == edge_to_tri_edge_map.end()) { + // No neighbor edge exists in the edge_to_tri_edge_map, so + // add this edge to it. + edge_to_tri_edge_map[Edge(start,end)] = TriEdge(tri,edge); + } else { + // Neighbor edge found, set the two elements of _neighbors + // and remove edge from edge_to_tri_edge_map. + neighbors_ptr[3*tri + edge] = it->second.tri; + neighbors_ptr[3*it->second.tri + it->second.edge] = tri; + edge_to_tri_edge_map.erase(it); + } + } + } + } + + // Note that remaining edges in the edge_to_tri_edge_map correspond to + // boundary edges, but the boundaries are calculated separately elsewhere. +} + +void Triangulation::correct_triangles() +{ + int* triangles_ptr = (int*)PyArray_DATA(_triangles); + int* neighbors_ptr = _neighbors != 0 ? (int*)PyArray_DATA(_neighbors) : 0; + for (int tri = 0; tri < _ntri; ++tri) { + XY point0 = get_point_coords(*triangles_ptr++); + XY point1 = get_point_coords(*triangles_ptr++); + XY point2 = get_point_coords(*triangles_ptr++); + if ( (point1 - point0).cross_z(point2 - point0) < 0.0) { + // Triangle points are clockwise, so change them to anticlockwise. + std::swap(*(triangles_ptr-2), *(triangles_ptr-1)); + if (neighbors_ptr) + std::swap(*(neighbors_ptr+3*tri+1), *(neighbors_ptr+3*tri+2)); + } + } +} + +const Triangulation::Boundaries& Triangulation::get_boundaries() const +{ + _VERBOSE("Triangulation::get_boundaries"); + if (_boundaries.empty()) + const_cast<Triangulation*>(this)->calculate_boundaries(); + return _boundaries; +} + +void Triangulation::get_boundary_edge(const TriEdge& triEdge, + int& boundary, + int& edge) const +{ + get_boundaries(); // Ensure _tri_edge_to_boundary_map has been created. + TriEdgeToBoundaryMap::const_iterator it = + _tri_edge_to_boundary_map.find(triEdge); + assert(it != _tri_edge_to_boundary_map.end() && + "TriEdge is not on a boundary"); + boundary = it->second.boundary; + edge = it->second.edge; +} + +int Triangulation::get_edge_in_triangle(int tri, int point) const +{ + assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds"); + assert(point >= 0 && point < _npoints && "Point index out of bounds."); + const int* triangles_ptr = get_triangles_ptr() + 3*tri; + for (int edge = 0; edge < 3; ++edge) { + if (*triangles_ptr++ == point) return edge; + } + return -1; // point is not in triangle. +} + +Py::Object Triangulation::get_edges() +{ + _VERBOSE("Triangulation::get_edges"); + if (_edges == 0) + calculate_edges(); + return Py::asObject(Py::new_reference_to((PyObject*)_edges)); +} + +int Triangulation::get_neighbor(int tri, int edge) const +{ + assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds"); + assert(edge >= 0 && edge < 3 && "Edge index out of bounds"); + return get_neighbors_ptr()[3*tri + edge]; +} + +TriEdge Triangulation::get_neighbor_edge(int tri, int edge) const +{ + int neighbor_tri = get_neighbor(tri, edge); + if (neighbor_tri == -1) + return TriEdge(-1,-1); + else + return TriEdge(neighbor_tri, + get_edge_in_triangle(neighbor_tri, + get_triangle_point(tri, + (edge+1)%3))); +} + +Py::Object Triangulation::get_neighbors() +{ + _VERBOSE("Triangulation::get_neighbors"); + if (_neighbors == 0) calculate_neighbors(); + return Py::asObject(Py::new_reference_to((PyObject*)_neighbors)); +} + +const int* Triangulation::get_neighbors_ptr() const +{ + if (_neighbors == 0) + const_cast<Triangulation*>(this)->calculate_neighbors(); + return (const int*)PyArray_DATA(_neighbors); +} + +int Triangulation::get_npoints() const +{ + return _npoints; +} + +int Triangulation::get_ntri() const +{ + return _ntri; +} + +XY Triangulation::get_point_coords(int point) const +{ + assert(point >= 0 && point < _npoints && "Point index out of bounds."); + return XY( ((const double*)PyArray_DATA(_x))[point], + ((const double*)PyArray_DATA(_y))[point] ); +} + +int Triangulation::get_triangle_point(int tri, int edge) const +{ + assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds"); + assert(edge >= 0 && edge < 3 && "Edge index out of bounds"); + return get_triangles_ptr()[3*tri + edge]; +} + +int Triangulation::get_triangle_point(const TriEdge& tri_edge) const +{ + return get_triangle_point(tri_edge.tri, tri_edge.edge); +} + +const int* Triangulation::get_triangles_ptr() const +{ + return (const int*)PyArray_DATA(_triangles); +} + +void Triangulation::init_type() +{ + _VERBOSE("Triangulation::init_type"); + + behaviors().name("Triangulation"); + behaviors().doc("Triangulation"); + + add_noargs_method("get_edges", &Triangulation::get_edges, + "get_edges()"); + add_noargs_method("get_neighbors", &Triangulation::get_neighbors, + "get_neighbors()"); + add_varargs_method("set_mask", &Triangulation::set_mask, + "set_mask(mask)"); +} + +bool Triangulation::is_masked(int tri) const +{ + assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds."); + return _mask && *((bool*)PyArray_DATA(_mask) + tri); +} + +Py::Object Triangulation::set_mask(const Py::Tuple &args) +{ + _VERBOSE("Triangulation::set_mask"); + args.verify_length(1); + + Py_XDECREF(_mask); + _mask = 0; + if (args[0] != Py::None()) + { + _mask = (PyArrayObject*)PyArray_ContiguousFromObject( + args[0].ptr(), PyArray_BOOL, 1, 1); + if (_mask == 0 || PyArray_DIM(_mask,0) != PyArray_DIM(_triangles,0)) { + Py_XDECREF(_mask); + throw Py::ValueError( + "mask must be a 1D array with the same length as the triangles array"); + } + } + + // Clear derived fields so they are recalculated when needed. + Py_XDECREF(_edges); + _edges = 0; + Py_XDECREF(_neighbors); + _neighbors = 0; + _boundaries.clear(); + + return Py::None(); +} + +void Triangulation::write_boundaries() const +{ + const Boundaries& bs = get_boundaries(); + std::cout << "Number of boundaries: " << bs.size() << std::endl; + for (Boundaries::const_iterator it = bs.begin(); it != bs.end(); ++it) { + const Boundary& b = *it; + std::cout << " Boundary of " << b.size() << " points: "; + for (Boundary::const_iterator itb = b.begin(); itb != b.end(); ++itb) { + std::cout << *itb << ", "; + } + std::cout << std::endl; + } +} + + + + +TriContourGenerator::TriContourGenerator(Py::Object triangulation, + PyArrayObject* z) + : _triangulation(triangulation), + _z(z), + _interior_visited(2*get_triangulation().get_ntri()), + _boundaries_visited(0), + _boundaries_used(0) +{ + _VERBOSE("TriContourGenerator::TriContourGenerator"); +} + +TriContourGenerator::~TriContourGenerator() +{ + _VERBOSE("TriContourGenerator::~TriContourGenerator"); + Py_XDECREF(_z); +} + +void TriContourGenerator::clear_visited_flags(bool include_boundaries) +{ + // Clear _interiorVisited. + std::fill(_interior_visited.begin(), _interior_visited.end(), false); + + if (include_boundaries) { + if (_boundaries_visited.empty()) { + const Boundaries& boundaries = get_boundaries(); + + // Initialise _boundaries_visited. + _boundaries_visited.reserve(boundaries.size()); + for (Boundaries::const_iterator it = boundaries.begin(); + it != boundaries.end(); ++it) + _boundaries_visited.push_back(BoundaryVisited(it->size())); + + // Initialise _boundaries_used. + _boundaries_used = BoundariesUsed(boundaries.size()); + } + + // Clear _boundaries_visited. + for (BoundariesVisited::iterator it = _boundaries_visited.begin(); + it != _boundaries_visited.end(); ++it) + fill(it->begin(), it->end(), false); + + // Clear _boundaries_used. + fill(_boundaries_used.begin(), _boundaries_used.end(), false); + } +} + +Py::Object TriContourGenerator::contour_to_segs(const Contour& contour) +{ + Py::List segs(contour.size()); + for (Contour::size_type i = 0; i < contour.size(); ++i) { + const ContourLine& line = contour[i]; + npy_intp dims[2] = {line.size(),2}; + PyArrayObject* py_line = (PyArrayObject*)PyArray_SimpleNew( + 2, dims, PyArray_DOUBLE); + double* p = (double*)PyArray_DATA(py_line); + for (ContourLine::const_iterator it = line.begin(); it != line.end(); ++it) { + *p++ = it->x; + *p++ = it->y; + } + segs[i] = Py::asObject((PyObject*)py_line); + } + return segs; +} + +Py::Object TriContourGenerator::contour_to_segs_and_kinds(const Contour& contour) +{ + Contour::const_iterator line; + ContourLine::const_iterator point; + + // Find total number of points in all contour lines. + int n_points = 0; + for (line = contour.begin(); line != contour.end(); ++line) + n_points += line->size(); + + // Create segs array for point coordinates. + npy_intp segs_dims[2] = {n_points, 2}; + PyArrayObject* segs = (PyArrayObject*)PyArray_SimpleNew( + 2, segs_dims, PyArray_DOUBLE); + double* segs_ptr = (double*)PyArray_DATA(segs); + + // Create kinds array for code types. + npy_intp kinds_dims[1] = {n_points}; + PyArrayObject* kinds = (PyArrayObject*)PyArray_SimpleNew( + 1, kinds_dims, PyArray_UBYTE); + unsigned char* kinds_ptr = (unsigned char*)PyArray_DATA(kinds); + + for (line = contour.begin(); line != contour.end(); ++line) { + for (point = line->begin(); point != line->end(); point++) { + *segs_ptr++ = point->x; + *segs_ptr++ = point->y; + *kinds_ptr++ = (point == line->begin() ? MOVETO : LINETO); + } + } + + Py::Tuple result(2); + result[0] = Py::asObject((PyObject*)segs); + result[1] = Py::asObject((PyObject*)kinds); + return result; +} + +Py::Object TriContourGenerator::create_contour(const Py::Tuple &args) +{ + _VERBOSE("TriContourGenerator::create_contour"); + args.verify_length(1); + + double level = (Py::Float)args[0]; + + clear_visited_flags(false); + Contour contour; + + find_boundary_lines(contour, level); + find_interior_lines(contour, level, false, false); + + return contour_to_segs(contour); +} + +Py::Object TriContourGenerator::create_filled_contour(const Py::Tuple &args) +{ + _VERBOSE("TriContourGenerator::create_filled_contour"); + args.verify_length(2); + + double lower_level = (Py::Float)args[0]; + double upper_level = (Py::Float)args[1]; + + clear_visited_flags(true); + Contour contour; + + find_boundary_lines_filled(contour, lower_level, upper_level); + find_interior_lines(contour, lower_level, false, true); + find_interior_lines(contour, upper_level, true, true); + + return contour_to_segs_and_kinds(contour); +} + +XY TriContourGenerator::edge_interp(int tri, int edge, const double& level) +{ + return interp(get_triangulation().get_triangle_point(tri, edge), + get_triangulation().get_triangle_point(tri, (edge+1)%3), + level); +} + +void TriContourGenerator::find_boundary_lines(Contour& contour, + const double& level) +{ + // Traverse boundaries to find starting points for all contour lines that + // intersect the boundaries. For each starting point found, follow the + // line to its end before continuing. + const Triangulation& triang = get_triangulation(); + const Boundaries& boundaries = get_boundaries(); + for (Boundaries::const_iterator it = boundaries.begin(); + it != boundaries.end(); ++it) { + const Boundary& boundary = *it; + bool startAbove, endAbove = false; + for (Boundary::const_iterator itb = boundary.begin(); + itb != boundary.end(); ++itb) { + if (itb == boundary.begin()) + startAbove = get_z(triang.get_triangle_point(*itb)) >= level; + else + startAbove = endAbove; + endAbove = get_z(triang.get_triangle_point(itb->tri, + (itb->edge+1)%3)) >= level; + if (startAbove && !endAbove) { + // This boundary edge is the start point for a contour line, + // so follow the line. + contour.push_back(ContourLine()); + ContourLine& contour_line = contour.back(); + TriEdge tri_edge = *itb; + follow_interior(contour_line, tri_edge, true, level, false); + } + } + } +} + +void TriContourGenerator::find_boundary_lines_filled(Contour& contour, + const double& lower_level, + const double& upper_level) +{ + // Traverse boundaries to find starting points for all contour lines that + // intersect the boundaries. For each starting point found, follow the + // line to its end before continuing. + const Triangulation& triang = get_triangulation(); + const Boundaries& boundaries = get_boundaries(); + for (Boundaries::size_type i = 0; i < boundaries.size(); ++i) { + const Boundary& boundary = boundaries[i]; + for (Boundary::size_type j = 0; j < boundary.size(); ++j) { + if (!_boundaries_visited[i][j]) { + // z values of start and end of this boundary edge. + double z_start = get_z(triang.get_triangle_point(boundary[j])); + double z_end = get_z(triang.get_triangle_point( + boundary[j].tri, (boundary[j].edge+1)%3)); + + // Does this boundary edge's z increase through upper level + // and/or decrease through lower level? + bool incr_upper = (z_start < upper_level && z_end >= upper_level); + bool decr_lower = (z_start >= lower_level && z_end < lower_level); + + if (decr_lower || incr_upper) { + // Start point for contour line, so follow it. + contour.push_back(ContourLine()); + ContourLine& contour_line = contour.back(); + TriEdge start_tri_edge = boundary[j]; + TriEdge tri_edge = start_tri_edge; + + // Traverse interior and boundaries until return to start. + bool on_upper = incr_upper; + do { + follow_interior(contour_line, tri_edge, true, + on_upper ? upper_level : lower_level, on_upper); + on_upper = follow_boundary(contour_line, tri_edge, + lower_level, upper_level, on_upper); + } while (tri_edge != start_tri_edge); + + // Filled contour lines must not have same first and last + // points. + if (contour_line.size() > 1 && + contour_line.front() == contour_line.back()) + contour_line.pop_back(); + } + } + } + } + + // Add full boundaries that lie between the lower and upper levels. These + // are boundaries that have not been touched by an internal contour line + // which are stored in _boundaries_used. + for (Boundaries::size_type i = 0; i < boundaries.size(); ++i) { + if (!_boundaries_used[i]) { + const Boundary& boundary = boundaries[i]; + double z = get_z(triang.get_triangle_point(boundary[0])); + if (z >= lower_level && z < upper_level) { + contour.push_back(ContourLine()); + ContourLine& contour_line = contour.back(); + for (Boundary::size_type j = 0; j < boundary.size(); ++j) + contour_line.push_back(triang.get_point_coords( + triang.get_triangle_point(boundary[j]))); + } + } + } +} + +void TriContourGenerator::find_interior_lines(Contour& contour, + const double& level, + bool on_upper, + bool filled) +{ + const Triangulation& triang = get_triangulation(); + int ntri = triang.get_ntri(); + for (int tri = 0; tri < ntri; ++tri) { + int visited_index = (on_upper ? tri+ntri : tri); + + if (_interior_visited[visited_index] || triang.is_masked(tri)) + continue; // Triangle has already been visited or is masked. + + _interior_visited[visited_index] = true; + + // Determine edge via which to leave this triangle. + int edge = get_exit_edge(tri, level, on_upper); + assert(edge >= -1 && edge < 3 && "Invalid exit edge"); + if (edge == -1) + continue; // Contour does not pass through this triangle. + + // Found start of new contour line loop. + contour.push_back(ContourLine()); + ContourLine& contour_line = contour.back(); + TriEdge tri_edge = triang.get_neighbor_edge(tri, edge); + follow_interior(contour_line, tri_edge, false, level, on_upper); + + if (!filled) + // Non-filled contour lines must be closed. + contour_line.push_back(contour_line.front()); + else if (contour_line.size() > 1 && + contour_line.front() == contour_line.back()) + // Filled contour lines must not have same first and last points. + contour_line.pop_back(); + } +} + +bool TriContourGenerator::follow_boundary(ContourLine& contour_line, + TriEdge& tri_edge, + const double& lower_level, + const double& upper_level, + bool on_upper) +{ + const Triangulation& triang = get_triangulation(); + const Boundaries& boundaries = get_boundaries(); + + // Have TriEdge to start at, need equivalent boundary edge. + int boundary, edge; + triang.get_boundary_edge(tri_edge, boundary, edge); + _boundaries_used[boundary] = true; + + bool stop = false; + bool first_edge = true; + double z_start, z_end = 0; + while (!stop) + { + assert(!_boundaries_visited[boundary][edge] && "Boundary already visited"); + _boundaries_visited[boundary][edge] = true; + + // z values of start and end points of boundary edge. + if (first_edge) + z_start = get_z(triang.get_triangle_point(tri_edge)); + else + z_start = z_end; + z_end = get_z(triang.get_triangle_point(tri_edge.tri, + (tri_edge.edge+1)%3)); + + if (z_end > z_start) { // z increasing. + if (!(!on_upper && first_edge) && + z_end >= lower_level && z_start < lower_level) { + stop = true; + on_upper = false; + } else if (z_end >= upper_level && z_start < upper_level) { + stop = true; + on_upper = true; + } + } else { // z decreasing. + if (!(on_upper && first_edge) && + z_start >= upper_level && z_end < upper_level) { + stop = true; + on_upper = true; + } else if (z_start >= lower_level && z_end < lower_level) { + stop = true; + on_upper = false; + } + } + + first_edge = false; + + if (!stop) { + // Move to next boundary edge, adding point to contour line. + edge = (edge+1) % (int)boundaries[boundary].size(); + tri_edge = boundaries[boundary][edge]; + contour_line.push_back(triang.get_point_coords( + triang.get_triangle_point(tri_edge))); + } + } + + return on_upper; +} + +void TriContourGenerator::follow_interior(ContourLine& contour_line, + TriEdge& tri_edge, + bool end_on_boundary, + const double& level, + bool on_upper) +{ + int& tri = tri_edge.tri; + int& edge = tri_edge.edge; + + // Initial point. + contour_line.push_back(edge_interp(tri, edge, level)); + + while (true) { + int visited_index = tri; + if (on_upper) + visited_index += get_triangulation().get_ntri(); + + // Check for end not on boundary. + if (!end_on_boundary && _interior_visited[visited_index]) + break; // Reached start point, so return. + + // Determine edge by which to leave this triangle. + edge = get_exit_edge(tri, level, on_upper); + assert(edge >= 0 && edge < 3 && "Invalid exit edge"); + + _interior_visited[visited_index] = true; + + // Append new point to point set. + assert(edge >= 0 && edge < 3 && "Invalid triangle edge"); + contour_line.push_back(edge_interp(tri, edge, level)); + + // Move to next triangle. + TriEdge next_tri_edge = get_triangulation().get_neighbor_edge(tri,edge); + + // Check if ending on a boundary. + if (end_on_boundary && next_tri_edge.tri == -1) + break; + + tri_edge = next_tri_edge; + assert(tri_edge.tri != -1 && "Invalid triangle for internal loop"); + } +} + +const TriContourGenerator::Boundaries& TriContourGenerator::get_boundaries() const +{ + return get_triangulation().get_boundaries(); +} + +int TriContourGenerator::get_exit_edge(int tri, + const double& level, + bool on_upper) const +{ + assert(tri >= 0 && tri < get_triangulation().get_ntri() && + "Triangle index out of bounds."); + + unsigned int config = + (get_z(get_triangulation().get_triangle_point(tri, 0)) >= level) | + (get_z(get_triangulation().get_triangle_point(tri, 1)) >= level) << 1 | + (get_z(get_triangulation().get_triangle_point(tri, 2)) >= level) << 2; + + if (on_upper) config = 7-config; + + switch (config) { + case 0: return -1; + case 1: return 2; + case 2: return 0; + case 3: return 2; + case 4: return 1; + case 5: return 1; + case 6: return 0; + case 7: return -1; + default: assert(0 && "Invalid config value"); return -1; + } +} + +const Triangulation& TriContourGenerator::get_triangulation() const +{ + return *(Triangulation*)_triangulation.ptr(); +} + +const double& TriContourGenerator::get_z(int point) const +{ + assert(point >= 0 && point < get_triangulation().get_npoints() && + "Point index out of bounds."); + return ((const double*)PyArray_DATA(_z))[point]; +} + +void TriContourGenerator::init_type() +{ + _VERBOSE("TriContourGenerator::init_type"); + + behaviors().name("TriContourGenerator"); + behaviors().doc("TriContourGenerator"); + + add_varargs_method("create_contour", + &TriContourGenerator::create_contour, + "create_contour(level)"); + add_varargs_method("create_filled_contour", + &TriContourGenerator::create_filled_contour, + "create_filled_contour(lower_level, upper_level)"); +} + +XY TriContourGenerator::interp(int point1, + int point2, + const double& level) const +{ + assert(point1 >= 0 && point1 < get_triangulation().get_npoints() && + "Point index 1 out of bounds."); + assert(point2 >= 0 && point2 < get_triangulation().get_npoints() && + "Point index 2 out of bounds."); + assert(point1 != point2 && "Identical points"); + double fraction = (get_z(point2) - level) / (get_z(point2) - get_z(point1)); + return get_triangulation().get_point_coords(point1)*fraction + + get_triangulation().get_point_coords(point2)*(1.0 - fraction); +} + + + + + +#if defined(_MSC_VER) +DL_EXPORT(void) +#elif defined(__cplusplus) +extern "C" void +#else +void +#endif +init_tri() +{ + static TriModule* triModule = new TriModule; + import_array(); +} + +TriModule::TriModule() + : Py::ExtensionModule<TriModule>("tri") +{ + Triangulation::init_type(); + TriContourGenerator::init_type(); + + add_varargs_method("Triangulation", &TriModule::new_triangulation, + "Create and return new C++ Triangulation object"); + add_varargs_method("TriContourGenerator", &TriModule::new_tricontourgenerator, + "Create and return new C++ TriContourGenerator object"); + + initialize("Module for unstructured triangular grids"); +} + +Py::Object TriModule::new_triangulation(const Py::Tuple &args) +{ + _VERBOSE("TriModule::new_triangulation"); + args.verify_length(6); + + // x and y. + PyArrayObject* x = (PyArrayObject*)PyArray_ContiguousFromObject( + args[0].ptr(), PyArray_DOUBLE, 1, 1); + PyArrayObject* y = (PyArrayObject*)PyArray_ContiguousFromObject( + args[1].ptr(), PyArray_DOUBLE, 1, 1); + if (x == 0 || y == 0 || PyArray_DIM(x,0) != PyArray_DIM(y,0)) { + Py_XDECREF(x); + Py_XDECREF(y); + throw Py::ValueError("x and y must be 1D arrays of the same length"); + } + + // triangles. + PyArrayObject* triangles = (PyArrayObject*)PyArray_ContiguousFromObject( + args[2].ptr(), PyArray_INT, 2, 2); + if (triangles == 0 || PyArray_DIM(triangles,1) != 3) { + Py_XDECREF(x); + Py_XDECREF(y); + Py_XDECREF(triangles); + throw Py::ValueError("triangles must be a 2D array of shape (?,3)"); + } + + // Optiona... [truncated message content] |
From: <ef...@us...> - 2010-05-17 19:04:04
|
Revision: 8317 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8317&view=rev Author: efiring Date: 2010-05-17 19:03:58 +0000 (Mon, 17 May 2010) Log Message: ----------- Axes.hist: fix bug in handling of weights kwarg; thanks to Jeff Klukas. Also use weights kwarg in examples/histogram_demo_extended. Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py 2010-05-13 09:13:49 UTC (rev 8316) +++ trunk/matplotlib/examples/pylab_examples/histogram_demo_extended.py 2010-05-17 19:03:58 UTC (rev 8317) @@ -1,4 +1,5 @@ #!/usr/bin/env python +import numpy as np import pylab as P # @@ -90,8 +91,20 @@ x1 = mu + sigma*P.randn(7000) x2 = mu + sigma*P.randn(3000) +# and exercise the weights option by arbitrarily giving the first half +# of each series only half the weight of the others: + +w0 = np.ones_like(x0) +w0[:len(x0)/2] = 0.5 +w1 = np.ones_like(x1) +w1[:len(x1)/2] = 0.5 +w2 = np.ones_like(x2) +w0[:len(x2)/2] = 0.5 + + + P.figure() -n, bins, patches = P.hist( [x0,x1,x2], 10, histtype='bar') +n, bins, patches = P.hist( [x0,x1,x2], 10, weights=[w0, w1, w2], histtype='bar') P.show() Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-05-13 09:13:49 UTC (rev 8316) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-05-17 19:03:58 UTC (rev 8317) @@ -7364,7 +7364,7 @@ raise ValueError("color kwarg must have one color per dataset") if weights is not None: - if isinstance(w, np.ndarray): + if isinstance(weights, np.ndarray): w = np.array(weights) if w.ndim == 2: w = w.T This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2010-05-19 00:32:33
|
Revision: 8321 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8321&view=rev Author: leejjoon Date: 2010-05-19 00:32:26 +0000 (Wed, 19 May 2010) Log Message: ----------- update docs. for gridspec Modified Paths: -------------- trunk/matplotlib/CHANGELOG Added Paths: ----------- trunk/matplotlib/doc/users/gridspec.rst trunk/matplotlib/doc/users/plotting/examples/demo_gridspec01.py trunk/matplotlib/doc/users/plotting/examples/demo_gridspec02.py trunk/matplotlib/doc/users/plotting/examples/demo_gridspec03.py trunk/matplotlib/doc/users/plotting/examples/demo_gridspec04.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-05-19 00:32:18 UTC (rev 8320) +++ trunk/matplotlib/CHANGELOG 2010-05-19 00:32:26 UTC (rev 8321) @@ -1,3 +1,5 @@ +2010-05-18 Merge mpl_toolkits.gridspec into the main tree. - JJL + 2010-05-04 Improve backend_qt4 so it displays figures with the correct size - DSD Added: trunk/matplotlib/doc/users/gridspec.rst =================================================================== --- trunk/matplotlib/doc/users/gridspec.rst (rev 0) +++ trunk/matplotlib/doc/users/gridspec.rst 2010-05-19 00:32:26 UTC (rev 8321) @@ -0,0 +1,130 @@ +.. _gridspec-guide: + + +************************************************ + Customizing Location of Subplot Using GridSpec +************************************************ + + ``GridSpec`` + specifies the geometry of the grid that a subplot will be + placed. The number of rows and number of columns of the grid + need to be set. Optionally, the subplot layout parameters + (e.g., left, right, etc.) can be tuned. + + ``SubplotSpec`` + specifies the location of the subplot in the given *GridSpec*. + + ``subplot2grid`` + a helper function that is similar to "pyplot.subplot" but uses + 0-based indexing and let subplot to occupy multiple cells. + + + Basic Example of using subplot2grid +===================================== + +To use subplot2grid, you provide geometry of the grid and the location +of the subplot in the grid. For a simple single-cell subplot, :: + + ax = plt.subplot2grid((2,2),(0, 0)) + +is identical to :: + + ax = plt.subplot(2,2,1) + +Note that, unlike matplotlib's subplot, the index starts from 0 in gridspec. + +To create a subplot that spans multiple cells, :: + + ax2 = plt.subplot2grid((3,3), (1, 0), colspan=2) + ax3 = plt.subplot2grid((3,3), (1, 2), rowspan=2) + +For example, the following commands :: + + ax1 = plt.subplot2grid((3,3), (0,0), colspan=3) + ax2 = plt.subplot2grid((3,3), (1,0), colspan=2) + ax3 = plt.subplot2grid((3,3), (1, 2), rowspan=2) + ax4 = plt.subplot2grid((3,3), (2, 0)) + ax5 = plt.subplot2grid((3,3), (2, 1)) + +creates + +.. plot:: users/plotting/examples/demo_gridspec01.py + + +GridSpec and SubplotSpec +======================== + +You can create GridSpec explicitly and use them to create a Subplot. + +For example, :: + + ax = plt.subplot2grid((2,2),(0, 0)) + +is equal to :: + + import matplotlib.gridspec as gridspec + gs = gridspec.GridSpec(2, 2) + ax = plt.subplot(gs[0, 0]) + +A gridspec instance provides array-like (2d or 1d) indexing that +returns the SubplotSpec instance. For, SubplotSpec that spans multiple +cells, use slice. :: + + ax2 = plt.subplot(gs[1,:-1]) + ax3 = plt.subplot(gs[1:, -1]) + +The above example becomes :: + + gs = gridspec.GridSpec(3, 3) + ax1 = plt.subplot(gs[0, :]) + ax2 = plt.subplot(gs[1,:-1]) + ax3 = plt.subplot(gs[1:, -1]) + ax4 = plt.subplot(gs[-1,0]) + ax5 = plt.subplot(gs[-1,-2]) + +.. plot:: users/plotting/examples/demo_gridspec02.py + +Adjust GridSpec layout +====================== + +When a GridSpec is explicitly used, you can adjust the layout +parameters of subplots that are created from the gridspec. :: + + gs1 = gridspec.GridSpec(3, 3) + gs1.update(left=0.05, right=0.48, wspace=0.05) + +This is similar to *subplots_adjust*, but it only affects the subplots +that are created from the given GridSpec. + +The code below :: + + gs1 = gridspec.GridSpec(3, 3) + gs1.update(left=0.05, right=0.48, wspace=0.05) + ax1 = plt.subplot(gs1[:-1, :]) + ax2 = plt.subplot(gs1[-1, :-1]) + ax3 = plt.subplot(gs1[-1, -1]) + + gs2 = gridspec.GridSpec(3, 3) + gs2.update(left=0.55, right=0.98, hspace=0.05) + ax4 = plt.subplot(gs2[:, :-1]) + ax5 = plt.subplot(gs2[:-1, -1]) + ax6 = plt.subplot(gs2[-1, -1]) + +creates + +.. plot:: users/plotting/examples/demo_gridspec03.py + +GridSpec using SubplotSpec +========================== + +You can create GridSpec from the SubplotSpec, in which case its layout +parameters are set to that of the locataion of the given SubplotSpec. :: + + gs0 = gridspec.GridSpec(1, 2) + + gs00 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[0]) + gs01 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[1]) + + +.. plot:: users/plotting/examples/demo_gridspec04.py + Added: trunk/matplotlib/doc/users/plotting/examples/demo_gridspec01.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/demo_gridspec01.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/demo_gridspec01.py 2010-05-19 00:32:26 UTC (rev 8321) @@ -0,0 +1,20 @@ +import matplotlib.pyplot as plt + +def make_ticklabels_invisible(fig): + for i, ax in enumerate(fig.axes): + ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") + for tl in ax.get_xticklabels() + ax.get_yticklabels(): + tl.set_visible(False) + + +plt.figure(0) +ax1 = plt.subplot2grid((3,3), (0,0), colspan=3) +ax2 = plt.subplot2grid((3,3), (1,0), colspan=2) +ax3 = plt.subplot2grid((3,3), (1, 2), rowspan=2) +ax4 = plt.subplot2grid((3,3), (2, 0)) +ax5 = plt.subplot2grid((3,3), (2, 1)) + +plt.suptitle("subplot2grid") +make_ticklabels_invisible(plt.gcf()) +plt.show() + Added: trunk/matplotlib/doc/users/plotting/examples/demo_gridspec02.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/demo_gridspec02.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/demo_gridspec02.py 2010-05-19 00:32:26 UTC (rev 8321) @@ -0,0 +1,26 @@ +import matplotlib.pyplot as plt +from matplotlib.gridspec import GridSpec + + +def make_ticklabels_invisible(fig): + for i, ax in enumerate(fig.axes): + ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") + for tl in ax.get_xticklabels() + ax.get_yticklabels(): + tl.set_visible(False) + + +plt.figure() + +gs = GridSpec(3, 3) +ax1 = plt.subplot(gs[0, :]) +# identical to ax1 = plt.subplot(gs.new_subplotspec((0,0), colspan=3)) +ax2 = plt.subplot(gs[1,:-1]) +ax3 = plt.subplot(gs[1:, -1]) +ax4 = plt.subplot(gs[-1,0]) +ax5 = plt.subplot(gs[-1,-2]) + +plt.suptitle("GridSpec") +make_ticklabels_invisible(plt.gcf()) + +plt.show() + Added: trunk/matplotlib/doc/users/plotting/examples/demo_gridspec03.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/demo_gridspec03.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/demo_gridspec03.py 2010-05-19 00:32:26 UTC (rev 8321) @@ -0,0 +1,34 @@ +import matplotlib.pyplot as plt +from matplotlib.gridspec import GridSpec + + +def make_ticklabels_invisible(fig): + for i, ax in enumerate(fig.axes): + ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") + for tl in ax.get_xticklabels() + ax.get_yticklabels(): + tl.set_visible(False) + + + +# demo 3 : gridspec with subplotpars set. + +f = plt.figure() + +plt.suptitle("GirdSpec w/ different subplotpars") + +gs1 = GridSpec(3, 3) +gs1.update(left=0.05, right=0.48, wspace=0.05) +ax1 = plt.subplot(gs1[:-1, :]) +ax2 = plt.subplot(gs1[-1, :-1]) +ax3 = plt.subplot(gs1[-1, -1]) + +gs2 = GridSpec(3, 3) +gs2.update(left=0.55, right=0.98, hspace=0.05) +ax4 = plt.subplot(gs2[:, :-1]) +ax5 = plt.subplot(gs2[:-1, -1]) +ax6 = plt.subplot(gs2[-1, -1]) + +make_ticklabels_invisible(plt.gcf()) + +plt.show() + Added: trunk/matplotlib/doc/users/plotting/examples/demo_gridspec04.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/demo_gridspec04.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/demo_gridspec04.py 2010-05-19 00:32:26 UTC (rev 8321) @@ -0,0 +1,41 @@ +import matplotlib.pyplot as plt +import matplotlib.gridspec as gridspec + +def make_ticklabels_invisible(fig): + for i, ax in enumerate(fig.axes): + ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") + for tl in ax.get_xticklabels() + ax.get_yticklabels(): + tl.set_visible(False) + + + +# gridspec inside gridspec + +f = plt.figure() + +gs0 = gridspec.GridSpec(1, 2) + +gs00 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[0]) + +ax1 = plt.Subplot(f, gs00[:-1, :]) +f.add_subplot(ax1) +ax2 = plt.Subplot(f, gs00[-1, :-1]) +f.add_subplot(ax2) +ax3 = plt.Subplot(f, gs00[-1, -1]) +f.add_subplot(ax3) + + +gs01 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[1]) + +ax4 = plt.Subplot(f, gs01[:, :-1]) +f.add_subplot(ax4) +ax5 = plt.Subplot(f, gs01[:-1, -1]) +f.add_subplot(ax5) +ax6 = plt.Subplot(f, gs01[-1, -1]) +f.add_subplot(ax6) + +plt.suptitle("GirdSpec Inside GridSpec") +make_ticklabels_invisible(plt.gcf()) + +plt.show() + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2010-05-19 00:32:44
|
Revision: 8323 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8323&view=rev Author: leejjoon Date: 2010-05-19 00:32:37 +0000 (Wed, 19 May 2010) Log Message: ----------- gridspec supports grid of different cell sizes Modified Paths: -------------- trunk/matplotlib/doc/users/gridspec.rst trunk/matplotlib/lib/matplotlib/gridspec.py Added Paths: ----------- trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py Modified: trunk/matplotlib/doc/users/gridspec.rst =================================================================== --- trunk/matplotlib/doc/users/gridspec.rst 2010-05-19 00:32:31 UTC (rev 8322) +++ trunk/matplotlib/doc/users/gridspec.rst 2010-05-19 00:32:37 UTC (rev 8323) @@ -129,3 +129,23 @@ .. plot:: users/plotting/examples/demo_gridspec04.py +GridSpec with Varying Cell Sizes +================================ + +By default, GridSpec creates cells of equal sizes. You can adjust +relative heights and widths of rows and columns. Note that absolute +values are meaningless, onlt their relative ratios matter. :: + + gs = gridspec.GridSpec(2, 2, + width_ratios=[1,2], + height_ratios=[4,1] + ) + + ax1 = plt.subplot(gs[0]) + ax2 = plt.subplot(gs[1]) + ax3 = plt.subplot(gs[2]) + ax4 = plt.subplot(gs[3]) + + +.. plot:: users/plotting/examples/demo_gridspec05.py + Added: trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py =================================================================== --- trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py (rev 0) +++ trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py 2010-05-19 00:32:37 UTC (rev 8323) @@ -0,0 +1,26 @@ +import matplotlib.pyplot as plt +import matplotlib.gridspec as gridspec + +def make_ticklabels_invisible(fig): + for i, ax in enumerate(fig.axes): + ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center") + for tl in ax.get_xticklabels() + ax.get_yticklabels(): + tl.set_visible(False) + + + +f = plt.figure() + +gs = gridspec.GridSpec(2, 2, + width_ratios=[1,2], + height_ratios=[4,1] + ) + +ax1 = plt.subplot(gs[0]) +ax2 = plt.subplot(gs[1]) +ax3 = plt.subplot(gs[2]) +ax4 = plt.subplot(gs[3]) + +make_ticklabels_invisible(f) +plt.show() + Modified: trunk/matplotlib/lib/matplotlib/gridspec.py =================================================================== --- trunk/matplotlib/lib/matplotlib/gridspec.py 2010-05-19 00:32:31 UTC (rev 8322) +++ trunk/matplotlib/lib/matplotlib/gridspec.py 2010-05-19 00:32:37 UTC (rev 8323) @@ -21,95 +21,113 @@ import matplotlib.transforms as mtransforms +import numpy as np -class GridSpec(object): +class GridSpecBase(object): """ - A class that specifies the geometry of the grid that a subplot - will be placed. + A base class of GridSpec that specifies the geometry of the grid + that a subplot will be placed. """ + def __init__(self, nrows, ncols, - left=None, bottom=None, right=None, top=None, - wspace=None, hspace=None): + height_ratios=None, width_ratios=None): """ - The number of rows and number of columns of the - grid need to be set. Optionally, the subplot layout parameters - (e.g., left, right, etc.) can be tuned. + The number of rows and number of columns of the grid need to + be set. Optionally, the ratio of heights and widths of ros and + columns can be specified. """ #self.figure = figure self._nrows , self._ncols = nrows, ncols - self.left=left - self.bottom=bottom - self.right=right - self.top=top - self.wspace=wspace - self.hspace=hspace + self.set_height_ratios(height_ratios) + self.set_width_ratios(width_ratios) + def get_geometry(self): 'get the geometry of the grid, eg 2,3' return self._nrows, self._ncols - _AllowedKeys = ["left", "bottom", "right", "top", "wspace", "hspace"] + def get_subplot_params(self, fig=None): + pass - def update(self, **kwargs): + def new_subplotspec(self, loc, rowspan=1, colspan=1): """ - Update the current values. If any kwarg is None, default to - the current value, if set, otherwise to rc. + create and return a SuplotSpec instance. """ + loc1, loc2 = loc + subplotspec = self[loc1:loc1+rowspan, loc2:loc2+colspan] + return subplotspec - for k, v in kwargs.items(): - if k in self._AllowedKeys: - setattr(self, k, v) - else: - raise AttributeError("%s is unknown keyword" % (k,)) + def set_width_ratios(self, width_ratios): + self._col_width_ratios = width_ratios - from matplotlib import _pylab_helpers - from matplotlib.axes import SubplotBase - for figmanager in _pylab_helpers.Gcf.figs.values(): - for ax in figmanager.canvas.figure.axes: - # copied from Figure.subplots_adjust - if not isinstance(ax, SubplotBase): - # Check if sharing a subplots axis - if ax._sharex is not None and isinstance(ax._sharex, SubplotBase): - ax._sharex.update_params() - ax.set_position(ax._sharex.figbox) - elif ax._sharey is not None and isinstance(ax._sharey,SubplotBase): - ax._sharey.update_params() - ax.set_position(ax._sharey.figbox) - else: - ax.update_params() - ax.set_position(ax.figbox) + def get_width_ratios(self): + return self._col_width_ratios + def set_height_ratios(self, height_ratios): + self._row_height_ratios = height_ratios - def get_subplot_params(self, fig=None): + def get_height_ratios(self): + return self._row_height_ratios + + + def get_grid_positions(self, fig): """ - return a dictionary of subplot layout parameters. The default - parameters are from rcParams unless a figure attribute is set. + return lists of bottom and top position of rows, left and + right positions of columns. """ - from matplotlib.figure import SubplotParams - import copy - if fig is None: - kw = dict([(k, rcParams["figure.subplot."+k]) \ - for k in self._AllowedKeys]) - subplotpars = SubplotParams(**kw) + nrows, ncols = self.get_geometry() + + subplot_params = self.get_subplot_params(fig) + left = subplot_params.left + right = subplot_params.right + bottom = subplot_params.bottom + top = subplot_params.top + wspace = subplot_params.wspace + hspace = subplot_params.hspace + totWidth = right-left + totHeight = top-bottom + + # calculate accumulated heights of columns + cellH = totHeight/(nrows + hspace*(nrows-1)) + sepH = hspace*cellH + + if self._row_height_ratios is not None: + netHeight = cellH * nrows + tr = float(sum(self._row_height_ratios)) + cellHeights = [netHeight*r/tr for r in self._row_height_ratios] else: - subplotpars = copy.copy(fig.subplotpars) + cellHeights = [cellH] * nrows - update_kw = dict([(k, getattr(self, k)) for k in self._AllowedKeys]) - subplotpars.update(**update_kw) + sepHeights = [0] + ([sepH] * (nrows-1)) + cellHs = np.add.accumulate(np.ravel(zip(sepHeights, cellHeights))) - return subplotpars + # calculate accumulated widths of rows + cellW = totWidth/(ncols + wspace*(ncols-1)) + sepW = wspace*cellW - def new_subplotspec(self, loc, rowspan=1, colspan=1): - """ - create and return a SuplotSpec instance. - """ - loc1, loc2 = loc - subplotspec = self[loc1:loc1+rowspan, loc2:loc2+colspan] - return subplotspec + if self._col_width_ratios is not None: + netWidth = cellW * ncols + tr = float(sum(self._col_width_ratios)) + cellWidths = [netWidth*r/tr for r in self._col_width_ratios] + else: + cellWidths = [cellW] * ncols + sepWidths = [0] + ([sepW] * (ncols-1)) + cellWs = np.add.accumulate(np.ravel(zip(sepWidths, cellWidths))) + + + figTops = [top - cellHs[2*rowNum] for rowNum in range(nrows)] + figBottoms = [top - cellHs[2*rowNum+1] for rowNum in range(nrows)] + figLefts = [left + cellWs[2*colNum] for colNum in range(ncols)] + figRights = [left + cellWs[2*colNum+1] for colNum in range(ncols)] + + + return figBottoms, figTops, figLefts, figRights + + def __getitem__(self, key): """ create and return a SuplotSpec instance. @@ -156,28 +174,121 @@ return SubplotSpec(self, num1, num2) -class GridSpecFromSubplotSpec(GridSpec): +class GridSpec(GridSpecBase): """ + A class that specifies the geometry of the grid that a subplot + will be placed. The location of grid is determined by similar way + as the SubplotParams. + """ + + def __init__(self, nrows, ncols, + left=None, bottom=None, right=None, top=None, + wspace=None, hspace=None, + width_ratios=None, height_ratios=None): + """ + The number of rows and number of columns of the + grid need to be set. Optionally, the subplot layout parameters + (e.g., left, right, etc.) can be tuned. + """ + #self.figure = figure + self.left=left + self.bottom=bottom + self.right=right + self.top=top + self.wspace=wspace + self.hspace=hspace + + GridSpecBase.__init__(self, nrows, ncols, + width_ratios=width_ratios, + height_ratios=height_ratios) + #self.set_width_ratios(width_ratios) + #self.set_height_ratios(height_ratios) + + + _AllowedKeys = ["left", "bottom", "right", "top", "wspace", "hspace"] + + def update(self, **kwargs): + """ + Update the current values. If any kwarg is None, default to + the current value, if set, otherwise to rc. + """ + + for k, v in kwargs.items(): + if k in self._AllowedKeys: + setattr(self, k, v) + else: + raise AttributeError("%s is unknown keyword" % (k,)) + + + from matplotlib import _pylab_helpers + from matplotlib.axes import SubplotBase + for figmanager in _pylab_helpers.Gcf.figs.values(): + for ax in figmanager.canvas.figure.axes: + # copied from Figure.subplots_adjust + if not isinstance(ax, SubplotBase): + # Check if sharing a subplots axis + if ax._sharex is not None and isinstance(ax._sharex, SubplotBase): + ax._sharex.update_params() + ax.set_position(ax._sharex.figbox) + elif ax._sharey is not None and isinstance(ax._sharey,SubplotBase): + ax._sharey.update_params() + ax.set_position(ax._sharey.figbox) + else: + ax.update_params() + ax.set_position(ax.figbox) + + + + def get_subplot_params(self, fig=None): + """ + return a dictionary of subplot layout parameters. The default + parameters are from rcParams unless a figure attribute is set. + """ + from matplotlib.figure import SubplotParams + import copy + if fig is None: + kw = dict([(k, rcParams["figure.subplot."+k]) \ + for k in self._AllowedKeys]) + subplotpars = SubplotParams(**kw) + else: + subplotpars = copy.copy(fig.subplotpars) + + update_kw = dict([(k, getattr(self, k)) for k in self._AllowedKeys]) + subplotpars.update(**update_kw) + + return subplotpars + + +class GridSpecFromSubplotSpec(GridSpecBase): + """ GridSpec whose subplot layout parameters are inherited from the location specified by a given SubplotSpec. """ def __init__(self, nrows, ncols, subplot_spec, - wspace=None, hspace=None): + wspace=None, hspace=None, + height_ratios=None, width_ratios=None): """ The number of rows and number of columns of the grid need to - be set. An instance of SubplotSpec is also need to be set from - which the layout parameters will be inheirted. The wspace and - hspace of the layout can be optionally specified or the + be set. An instance of SubplotSpec is also needed to be set + from which the layout parameters will be inheirted. The wspace + and hspace of the layout can be optionally specified or the default values (from the figure or rcParams) will be used. """ - self._nrows , self._ncols = nrows, ncols self._wspace=wspace self._hspace=hspace self._subplot_spec = subplot_spec + GridSpecBase.__init__(self, nrows, ncols, + width_ratios=width_ratios, + height_ratios=height_ratios) + + def get_subplot_params(self, fig=None): + """ + return a dictionary of subplot layout parameters. + """ if fig is None: hspace = rcParams["figure.subplot.hspace"] @@ -249,37 +360,25 @@ """ gridspec = self.get_gridspec() - rows, cols = gridspec.get_geometry() + nrows, ncols = gridspec.get_geometry() - subplot_params = gridspec.get_subplot_params(fig) - left = subplot_params.left - right = subplot_params.right - bottom = subplot_params.bottom - top = subplot_params.top - wspace = subplot_params.wspace - hspace = subplot_params.hspace - totWidth = right-left - totHeight = top-bottom + figBottoms, figTops, figLefts, figRights = \ + gridspec.get_grid_positions(fig) - figH = totHeight/(rows + hspace*(rows-1)) - sepH = hspace*figH - figW = totWidth/(cols + wspace*(cols-1)) - sepW = wspace*figW + rowNum, colNum = divmod(self.num1, ncols) + figBottom = figBottoms[rowNum] + figTop = figTops[rowNum] + figLeft = figLefts[colNum] + figRight = figRights[colNum] - rowNum, colNum = divmod(self.num1, cols) - figBottom = top - (rowNum+1)*figH - rowNum*sepH - figLeft = left + colNum*(figW + sepW) - figTop = figBottom + figH - figRight = figLeft + figW - if self.num2 is not None: - rowNum2, colNum2 = divmod(self.num2, cols) - figBottom2 = top - (rowNum2+1)*figH - rowNum2*sepH - figLeft2 = left + colNum2*(figW + sepW) - figTop2 = figBottom2 + figH - figRight2 = figLeft2 + figW + rowNum2, colNum2 = divmod(self.num2, ncols) + figBottom2 = figBottoms[rowNum2] + figTop2 = figTops[rowNum2] + figLeft2 = figLefts[colNum2] + figRight2 = figRights[colNum2] figBottom = min(figBottom, figBottom2) figLeft = min(figLeft, figLeft2) @@ -291,7 +390,7 @@ if return_all: - return figbox, rowNum, colNum, rows, cols + return figbox, rowNum, colNum, nrows, ncols else: return figbox This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-05-30 18:48:41
|
Revision: 8344 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8344&view=rev Author: efiring Date: 2010-05-30 18:48:35 +0000 (Sun, 30 May 2010) Log Message: ----------- pyplot.findobj: use docstring decorator. Closes 2994238. Thanks to Mark Roddy. Modified Paths: -------------- trunk/matplotlib/examples/tests/backend_driver.py trunk/matplotlib/lib/matplotlib/pyplot.py Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2010-05-30 18:35:42 UTC (rev 8343) +++ trunk/matplotlib/examples/tests/backend_driver.py 2010-05-30 18:48:35 UTC (rev 8344) @@ -387,7 +387,7 @@ return failures def parse_options(): - doc = __doc__.split('\n\n') + doc = (__doc__ and __doc__.split('\n\n')) or " " op = OptionParser(description=doc[0].strip(), usage='%prog [options] [--] [backends and switches]', #epilog='\n'.join(doc[1:]) # epilog not supported on my python2.4 machine: JDH Modified: trunk/matplotlib/lib/matplotlib/pyplot.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-30 18:35:42 UTC (rev 8343) +++ trunk/matplotlib/lib/matplotlib/pyplot.py 2010-05-30 18:48:35 UTC (rev 8344) @@ -78,12 +78,11 @@ from matplotlib.backends import pylab_setup new_figure_manager, draw_if_interactive, show = pylab_setup() - +...@do...py_dedent(Artist.findobj) def findobj(o=None, match=None): if o is None: o = gcf() return o.findobj(match) -findobj.__doc__ = Artist.findobj.__doc__ def switch_backend(newbackend): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-06-01 19:06:35
|
Revision: 8364 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8364&view=rev Author: mdboom Date: 2010-06-01 19:06:28 +0000 (Tue, 01 Jun 2010) Log Message: ----------- Fix compiler warnings. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp trunk/matplotlib/lib/matplotlib/tri/_tri.cpp trunk/matplotlib/src/_path.cpp trunk/matplotlib/src/cntr.c trunk/matplotlib/src/path_converters.h Modified: trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp =================================================================== --- trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/lib/matplotlib/delaunay/_delaunay.cpp 2010-06-01 19:06:28 UTC (rev 8364) @@ -12,8 +12,8 @@ extern "C" { -static void reorder_edges(int npoints, int ntriangles, - double *x, double *y, +static void reorder_edges(int npoints, int ntriangles, + double *x, double *y, int *edge_db, int *tri_edges, int *tri_nbrs) { int neighbors[3], nodes[3]; @@ -69,7 +69,7 @@ // Not trusting me? Okay, let's go through it: // We have three edges to deal with and three nodes. Without loss - // of generality, let's label the nodes A, B, and C with (A, B) + // of generality, let's label the nodes A, B, and C with (A, B) // forming the first edge in the order they arrive on input. // Then there are eight possibilities as to how the other edge-tuples // may be labeled, but only two variations that are going to affect the @@ -85,7 +85,7 @@ // The second test we need to perform is for counter-clockwiseness. // Again, there are only two variations that will affect the outcome: // either ABC is counter-clockwise, or it isn't. In the former case, - // we're done setting the node order, we just need to associate the + // we're done setting the node order, we just need to associate the // appropriate neighbor triangles with their opposite nodes, something // which can be done by inspection. In the latter case, to order the // nodes counter-clockwise, we only have to switch B and C to get @@ -113,7 +113,7 @@ static PyObject* getMesh(int npoints, double *x, double *y) { - PyObject *vertices, *edge_db, *tri_edges, *tri_nbrs; + PyObject *vertices = NULL, *edge_db = NULL, *tri_edges = NULL, *tri_nbrs = NULL; PyObject *temp; int tri0, tri1, reg0, reg1; double tri0x, tri0y, tri1x, tri1y; @@ -138,7 +138,7 @@ edge_db = PyArray_SimpleNew(2, dim, PyArray_INT); if (!edge_db) goto fail; edge_db_ptr = (int*)PyArray_DATA(edge_db); - + dim[0] = numtri; vertices = PyArray_SimpleNew(2, dim, PyArray_DOUBLE); if (!vertices) goto fail; @@ -192,7 +192,7 @@ // tri_edges contains lists of edges; convert to lists of nodes in // counterclockwise order and reorder tri_nbrs to match. Each node // corresponds to the edge opposite it in the triangle. - reorder_edges(npoints, numtri, x, y, edge_db_ptr, tri_edges_ptr, + reorder_edges(npoints, numtri, x, y, edge_db_ptr, tri_edges_ptr, tri_nbrs_ptr); temp = Py_BuildValue("(OOOO)", vertices, edge_db, tri_edges, tri_nbrs); @@ -221,7 +221,7 @@ int i; double *planes_ptr; double x02, y02, z02, x12, y12, z12, xy0212; - + dims[0] = ntriangles; dims[1] = 3; planes = PyArray_SimpleNew(2, dims, PyArray_DOUBLE); @@ -240,15 +240,15 @@ xy0212 = y02/y12; INDEX3(planes_ptr,i,0) = (z02 - z12 * xy0212) / (x02 - x12 * xy0212); INDEX3(planes_ptr,i,1) = (z12 - INDEX3(planes_ptr,i,0)*x12) / y12; - INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - - INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - INDEX3(planes_ptr,i,1)*y[INDEX3(nodes,i,2)]); } else { xy0212 = x02/x12; INDEX3(planes_ptr,i,1) = (z02 - z12 * xy0212) / (y02 - y12 * xy0212); INDEX3(planes_ptr,i,0) = (z12 - INDEX3(planes_ptr,i,1)*y12) / x12; - INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - - INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,2) = (z[INDEX3(nodes,i,2)] - + INDEX3(planes_ptr,i,0)*x[INDEX3(nodes,i,2)] - INDEX3(planes_ptr,i,1)*y[INDEX3(nodes,i,2)]); } } @@ -256,24 +256,24 @@ return (PyObject*)planes; } -static double linear_interpolate_single(double targetx, double targety, +static double linear_interpolate_single(double targetx, double targety, double *x, double *y, int *nodes, int *neighbors, PyObject *planes, double defvalue, int start_triangle, int *end_triangle) { double *planes_ptr; planes_ptr = (double*)PyArray_DATA(planes); if (start_triangle == -1) start_triangle = 0; - *end_triangle = walking_triangles(start_triangle, targetx, targety, + *end_triangle = walking_triangles(start_triangle, targetx, targety, x, y, nodes, neighbors); if (*end_triangle == -1) return defvalue; - return (targetx*INDEX3(planes_ptr,*end_triangle,0) + + return (targetx*INDEX3(planes_ptr,*end_triangle,0) + targety*INDEX3(planes_ptr,*end_triangle,1) + INDEX3(planes_ptr,*end_triangle,2)); } -static PyObject *linear_interpolate_grid(double x0, double x1, int xsteps, +static PyObject *linear_interpolate_grid(double x0, double x1, int xsteps, double y0, double y1, int ysteps, - PyObject *planes, double defvalue, + PyObject *planes, double defvalue, int npoints, double *x, double *y, int *nodes, int *neighbors) { int ix, iy; @@ -312,7 +312,7 @@ static PyObject *compute_planes_method(PyObject *self, PyObject *args) { PyObject *pyx, *pyy, *pyz, *pynodes; - PyObject *x, *y, *z, *nodes; + PyObject *x = NULL, *y = NULL, *z = NULL, *nodes = NULL; int npoints, ntriangles; PyObject *planes; @@ -351,7 +351,7 @@ goto fail; } - planes = linear_planes(ntriangles, (double*)PyArray_DATA(x), + planes = linear_planes(ntriangles, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), (double*)PyArray_DATA(z), (int*)PyArray_DATA(nodes)); Py_DECREF(x); @@ -374,7 +374,7 @@ double x0, x1, y0, y1, defvalue; int xsteps, ysteps; PyObject *pyplanes, *pyx, *pyy, *pynodes, *pyneighbors, *grid; - PyObject *planes, *x, *y, *nodes, *neighbors; + PyObject *planes = NULL, *x = NULL, *y = NULL, *nodes = NULL, *neighbors = NULL; int npoints; @@ -417,7 +417,7 @@ (PyObject*)planes, defvalue, npoints, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), (int*)PyArray_DATA(nodes), (int*)PyArray_DATA(neighbors)); - + Py_DECREF(x); Py_DECREF(y); Py_DECREF(planes); @@ -455,7 +455,7 @@ { PyObject *pyx, *pyy, *pyz, *pycenters, *pynodes, *pyneighbors, *pyintx, *pyinty; PyObject *x = NULL, *y = NULL, *z = NULL, *centers = NULL, *nodes = NULL, - *neighbors = NULL, *intx = NULL, *inty = NULL, *intz; + *neighbors = NULL, *intx = NULL, *inty = NULL, *intz = NULL; double defvalue; int size, npoints, ntriangles; @@ -506,7 +506,7 @@ return NULL; } ntriangles = PyArray_DIM(neighbors, 0); - if ((PyArray_DIM(nodes, 0) != ntriangles) || + if ((PyArray_DIM(nodes, 0) != ntriangles) || (PyArray_DIM(centers, 0) != ntriangles)) { PyErr_SetString(PyExc_ValueError, "centers,nodes,neighbors must be of equal length"); CLEANUP @@ -542,13 +542,13 @@ return NULL; } - NaturalNeighbors nn(npoints, ntriangles, + NaturalNeighbors nn(npoints, ntriangles, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), - (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), + (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), (int*)PyArray_DATA(neighbors)); size = PyArray_Size(intx); - nn.interpolate_unstructured((double*)PyArray_DATA(z), size, - (double*)PyArray_DATA(intx), (double*)PyArray_DATA(inty), + nn.interpolate_unstructured((double*)PyArray_DATA(z), size, + (double*)PyArray_DATA(intx), (double*)PyArray_DATA(inty), (double*)PyArray_DATA(intz), defvalue); Py_XDECREF(x); @@ -575,13 +575,13 @@ static PyObject *nn_interpolate_method(PyObject *self, PyObject *args) { PyObject *pyx, *pyy, *pyz, *pycenters, *pynodes, *pyneighbors, *grid; - PyObject *x, *y, *z, *centers, *nodes, *neighbors; + PyObject *x = NULL, *y = NULL, *z = NULL, *centers = NULL, *nodes = NULL, *neighbors = NULL; double x0, x1, y0, y1, defvalue; int xsteps, ysteps; int npoints, ntriangles; intp dims[2]; - if (!PyArg_ParseTuple(args, "ddiddidOOOOOO", &x0, &x1, &xsteps, + if (!PyArg_ParseTuple(args, "ddiddidOOOOOO", &x0, &x1, &xsteps, &y0, &y1, &ysteps, &defvalue, &pyx, &pyy, &pyz, &pycenters, &pynodes, &pyneighbors)) { return NULL; @@ -629,7 +629,7 @@ return NULL; } ntriangles = PyArray_DIM(neighbors, 0); - if ((PyArray_DIM(nodes, 0) != ntriangles) || + if ((PyArray_DIM(nodes, 0) != ntriangles) || (PyArray_DIM(centers, 0) != ntriangles)) { PyErr_SetString(PyExc_ValueError, "centers,nodes,neighbors must be of equal length"); CLEANUP @@ -644,11 +644,11 @@ return NULL; } - NaturalNeighbors nn(npoints, ntriangles, + NaturalNeighbors nn(npoints, ntriangles, (double*)PyArray_DATA(x), (double*)PyArray_DATA(y), - (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), + (double*)PyArray_DATA(centers), (int*)PyArray_DATA(nodes), (int*)PyArray_DATA(neighbors)); - nn.interpolate_grid((double*)PyArray_DATA(z), + nn.interpolate_grid((double*)PyArray_DATA(z), x0, x1, xsteps, y0, y1, ysteps, (double*)PyArray_DATA(grid), @@ -664,7 +664,7 @@ static PyObject *delaunay_method(PyObject *self, PyObject *args) { PyObject *pyx, *pyy, *mesh; - PyObject *x, *y; + PyObject *x = NULL, *y = NULL; int npoints; if (!PyArg_ParseTuple(args, "OO", &pyx, &pyy)) { @@ -703,7 +703,7 @@ } static PyMethodDef delaunay_methods[] = { - {"delaunay", (PyCFunction)delaunay_method, METH_VARARGS, + {"delaunay", (PyCFunction)delaunay_method, METH_VARARGS, "Compute the Delaunay triangulation of a cloud of 2-D points.\n\n" "circumcenters, edges, tri_points, tri_neighbors = delaunay(x, y)\n\n" "x, y -- shape-(npoints,) arrays of floats giving the X and Y coordinates of the points\n" @@ -730,7 +730,7 @@ PyMODINIT_FUNC init_delaunay(void) { PyObject* m; - m = Py_InitModule3("_delaunay", delaunay_methods, + m = Py_InitModule3("_delaunay", delaunay_methods, "Tools for computing the Delaunay triangulation and some operations on it.\n" ); if (m == NULL) Modified: trunk/matplotlib/lib/matplotlib/tri/_tri.cpp =================================================================== --- trunk/matplotlib/lib/matplotlib/tri/_tri.cpp 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/lib/matplotlib/tri/_tri.cpp 2010-06-01 19:06:28 UTC (rev 8364) @@ -990,7 +990,8 @@ #endif init_tri() { - static TriModule* triModule = new TriModule; + static TriModule* triModule = NULL; + triModule = new TriModule(); import_array(); } Modified: trunk/matplotlib/src/_path.cpp =================================================================== --- trunk/matplotlib/src/_path.cpp 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/src/_path.cpp 2010-06-01 19:06:28 UTC (rev 8364) @@ -818,7 +818,7 @@ } Polygon polygon1, polygon2; - double x, y; + double x = 0, y = 0; unsigned code = 0; path.rewind(0); Modified: trunk/matplotlib/src/cntr.c =================================================================== --- trunk/matplotlib/src/cntr.c 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/src/cntr.c 2010-06-01 19:06:28 UTC (rev 8364) @@ -607,8 +607,8 @@ } if (fwd < 0 && level0 && left < 0) { - /* remove J0_START from this boundary edge as boundary is - * included by the upwards slit from contour line below. */ + /* remove J0_START from this boundary edge as boundary is + * included by the upwards slit from contour line below. */ data[edge] &= ~J0_START; if (n_kind) kcp[n_kind] += kind_start_slit; return slit_cutter (site, 0, pass2); @@ -1479,8 +1479,8 @@ int nparts, long ntotal) { PyObject *all_contours; - PyArrayObject *xyv; - PyArrayObject *kv; + PyArrayObject *xyv = NULL; + PyArrayObject *kv = NULL; npy_intp dims[2]; npy_intp kdims[1]; int i; Modified: trunk/matplotlib/src/path_converters.h =================================================================== --- trunk/matplotlib/src/path_converters.h 2010-06-01 19:04:17 UTC (rev 8363) +++ trunk/matplotlib/src/path_converters.h 2010-06-01 19:06:28 UTC (rev 8364) @@ -233,9 +233,9 @@ } while (MPL_notisfinite64(*x) || MPL_notisfinite64(*y)); return agg::path_cmd_move_to; } + + return code; } - - return code; } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ry...@us...> - 2010-06-02 03:23:04
|
Revision: 8366 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8366&view=rev Author: ryanmay Date: 2010-06-02 03:22:57 +0000 (Wed, 02 Jun 2010) Log Message: ----------- Make pcolormesh() and QuadMesh take/forward on kwargs as appropriate. This fixes (at least) zorder for pcolormesh. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/collections.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-06-02 02:22:16 UTC (rev 8365) +++ trunk/matplotlib/CHANGELOG 2010-06-02 03:22:57 UTC (rev 8366) @@ -1,3 +1,6 @@ +2010-06-01 Fix pcolormesh() and QuadMesh to pass on kwargs as + appropriate. - RM + 2010-05-18 Merge mpl_toolkits.gridspec into the main tree. - JJL 2010-05-04 Improve backend_qt4 so it displays figures with the Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-06-02 02:22:16 UTC (rev 8365) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-06-02 03:22:57 UTC (rev 8366) @@ -6897,7 +6897,7 @@ collection = mcoll.QuadMesh( Nx - 1, Ny - 1, coords, showedges, - antialiased=antialiased, shading=shading) # kwargs are not used + antialiased=antialiased, shading=shading, **kwargs) collection.set_alpha(alpha) collection.set_array(C) if norm is not None: assert(isinstance(norm, mcolors.Normalize)) Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2010-06-02 02:22:16 UTC (rev 8365) +++ trunk/matplotlib/lib/matplotlib/collections.py 2010-06-02 03:22:57 UTC (rev 8366) @@ -1088,8 +1088,8 @@ *shading* may be 'flat', 'faceted' or 'gouraud' """ def __init__(self, meshWidth, meshHeight, coordinates, showedges, - antialiased=True, shading='flat'): - Collection.__init__(self) + antialiased=True, shading='flat', **kwargs): + Collection.__init__(self, **kwargs) self._meshWidth = meshWidth self._meshHeight = meshHeight self._coordinates = coordinates This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-02 20:41:17
|
Revision: 8369 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8369&view=rev Author: efiring Date: 2010-06-02 20:41:10 +0000 (Wed, 02 Jun 2010) Log Message: ----------- Axes.bar: added error_kw kwarg Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/api_changes.rst trunk/matplotlib/examples/pylab_examples/barchart_demo.py trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-06-02 19:25:13 UTC (rev 8368) +++ trunk/matplotlib/CHANGELOG 2010-06-02 20:41:10 UTC (rev 8369) @@ -1,3 +1,5 @@ +2010-06-02 Add error_kw kwarg to Axes.bar(). - EF + 2010-06-01 Fix pcolormesh() and QuadMesh to pass on kwargs as appropriate. - RM Modified: trunk/matplotlib/doc/api/api_changes.rst =================================================================== --- trunk/matplotlib/doc/api/api_changes.rst 2010-06-02 19:25:13 UTC (rev 8368) +++ trunk/matplotlib/doc/api/api_changes.rst 2010-06-02 20:41:10 UTC (rev 8369) @@ -10,6 +10,10 @@ Changes beyond 0.99.x ===================== +* The :meth:`matplotlib.axes.Axes.bar` method accepts a *error_kw* + kwarg; it is a dictionary of kwargs to be passed to the + errorbar function. + * The :meth:`matplotlib.axes.Axes.hist` *color* kwarg now accepts a sequence of color specs to match a sequence of datasets. Modified: trunk/matplotlib/examples/pylab_examples/barchart_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/barchart_demo.py 2010-06-02 19:25:13 UTC (rev 8368) +++ trunk/matplotlib/examples/pylab_examples/barchart_demo.py 2010-06-02 20:41:10 UTC (rev 8369) @@ -12,11 +12,17 @@ plt.subplot(111) -rects1 = plt.bar(ind, menMeans, width, color='r', yerr=menStd) +rects1 = plt.bar(ind, menMeans, width, + color='r', + yerr=menStd, + error_kw=dict(elinewidth=6, ecolor='pink')) womenMeans = (25, 32, 34, 20, 25) womenStd = (3, 5, 2, 3, 3) -rects2 = plt.bar(ind+width, womenMeans, width, color='y', yerr=womenStd) +rects2 = plt.bar(ind+width, womenMeans, width, + color='y', + yerr=womenStd, + error_kw=dict(elinewidth=6, ecolor='yellow')) # add some plt.ylabel('Scores') Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-06-02 19:25:13 UTC (rev 8368) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-06-02 20:41:10 UTC (rev 8369) @@ -4288,6 +4288,10 @@ *ecolor* specifies the color of any errorbar *capsize* (default 3) determines the length in points of the error bar caps + *error_kw* dictionary of kwargs to be passed to + errorbar method. *ecolor* and *capsize* + may be specified here rather than as + independent kwargs. *align* 'edge' (default) | 'center' *orientation* 'vertical' | 'horizontal' *log* [False|True] False (default) leaves the @@ -4322,13 +4326,18 @@ color = kwargs.pop('color', None) edgecolor = kwargs.pop('edgecolor', None) linewidth = kwargs.pop('linewidth', None) + # Because xerr and yerr will be passed to errorbar, # most dimension checking and processing will be left # to the errorbar method. xerr = kwargs.pop('xerr', None) yerr = kwargs.pop('yerr', None) + error_kw = kwargs.pop('error_kw', dict()) ecolor = kwargs.pop('ecolor', None) capsize = kwargs.pop('capsize', 3) + error_kw.setdefault('ecolor', ecolor) + error_kw.setdefault('capsize', capsize) + align = kwargs.pop('align', 'edge') orientation = kwargs.pop('orientation', 'vertical') log = kwargs.pop('log', False) @@ -4478,7 +4487,7 @@ self.errorbar( x, y, yerr=yerr, xerr=xerr, - fmt=None, ecolor=ecolor, capsize=capsize) + fmt=None, **error_kw) self.hold(holdstate) # restore previous hold state @@ -4833,17 +4842,17 @@ If a scalar number, len(N) array-like object, or an Nx1 array-like object, errorbars are drawn +/- value. - If a rank-1, 2xN numpy array, errorbars are drawn at -row1 and + If a sequence of shape 2xN, errorbars are drawn at -row1 and +row2 *fmt*: '-' - The plot format symbol for *y*. If *fmt* is *None*, just plot the - errorbars with no line symbols. This can be useful for creating a - bar plot with errorbars. + The plot format symbol. If *fmt* is *None*, only the + errorbars are plotted. This is used for adding + errorbars to a bar plot, for example. *ecolor*: [ None | mpl color ] - a matplotlib color arg which gives the color the errorbar lines; if - *None*, use the marker color. + a matplotlib color arg which gives the color the errorbar lines; + if *None*, use the marker color. *elinewidth*: scalar the linewidth of the errorbar lines. If *None*, use the linewidth. @@ -4862,8 +4871,7 @@ type as *xerr* and *yerr*. All other keyword arguments are passed on to the plot command for the - markers, so you can add additional key=value pairs to control the - errorbar markers. For example, this code makes big red squares with + markers, For example, this code makes big red squares with thick green edges:: x,y,yerr = rand(3,10) @@ -4878,13 +4886,17 @@ %(Line2D)s - Return value is a length 3 tuple. The first element is the - :class:`~matplotlib.lines.Line2D` instance for the *y* symbol - lines. The second element is a list of error bar cap lines, - the third element is a list of - :class:`~matplotlib.collections.LineCollection` instances for - the horizontal and vertical error ranges. + Returns (*plotline*, *caplines*, *barlinecols*): + *plotline*: :class:`~matplotlib.lines.Line2D` instance + *x*, *y* plot markers and/or line + + *caplines*: list of error bar cap + :class:`~matplotlib.lines.Line2D` instances + *barlinecols*: list of + :class:`~matplotlib.collections.LineCollection` instances for + the horizontal and vertical error ranges. + **Example:** .. plot:: mpl_examples/pylab_examples/errorbar_demo.py This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-04 03:38:04
|
Revision: 8372 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8372&view=rev Author: efiring Date: 2010-06-04 03:37:56 +0000 (Fri, 04 Jun 2010) Log Message: ----------- alpha is left as None until you really want to specify it; closes 2957321. I think this, together with some other recent commits, fixes various longstanding problems in the way alpha has been handled. The default value is left as None, and with this value, existing alpha specified in RGBA sequences will not be overridden. Substitution of the default value of 1 for a value of None is delayed until the GraphicsContextBase set_alpha method is executed. Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/figimage_demo.py trunk/matplotlib/lib/matplotlib/artist.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/cm.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/colorbar.py trunk/matplotlib/lib/matplotlib/contour.py trunk/matplotlib/lib/matplotlib/figure.py trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/examples/pylab_examples/figimage_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/figimage_demo.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/examples/pylab_examples/figimage_demo.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -1,5 +1,6 @@ """ -See pcolor_demo2 for a much faster way of generating pcolor plots +This illustrates placing images directly in the figure, with no axes. + """ import numpy as np import matplotlib @@ -12,19 +13,9 @@ Z.shape = 100,100 Z[:,50:] = 1. -ax = fig.add_subplot(111) -ax.grid(True) - im1 = plt.figimage(Z, xo=50, yo=0, cmap=cm.jet, origin='lower') im2 = plt.figimage(Z, xo=100, yo=100, alpha=.8, cmap=cm.jet, origin='lower') - -if 0: - dpi = 72 - plt.savefig('figimage_%d.png'%dpi, dpi=dpi, facecolor='gray') - plt.savefig('figimage_%d.pdf'%dpi, dpi=dpi, facecolor='gray') - plt.savefig('figimage_%d.svg'%dpi, dpi=dpi, facecolor='gray') - plt.savefig('figimage_%d.eps'%dpi, dpi=dpi, facecolor='gray') plt.show() Modified: trunk/matplotlib/lib/matplotlib/artist.py =================================================================== --- trunk/matplotlib/lib/matplotlib/artist.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/artist.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -78,7 +78,7 @@ self._transformSet = False self._visible = True self._animated = False - self._alpha = 1.0 + self._alpha = None self.clipbox = None self._clippath = None self._clipon = True Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -372,7 +372,7 @@ Keyword Description ================ ========================================= *adjustable* [ 'box' | 'datalim' | 'box-forced'] - *alpha* float: the alpha transparency + *alpha* float: the alpha transparency (can be None) *anchor* [ 'C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W' ] *aspect* [ 'auto' | 'equal' | aspect_ratio ] @@ -5338,14 +5338,14 @@ @docstring.dedent_interpd def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None, - vmin=None, vmax=None, alpha=1.0, linewidths=None, + vmin=None, vmax=None, alpha=None, linewidths=None, faceted=True, verts=None, **kwargs): """ call signatures:: scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None, - vmin=None, vmax=None, alpha=1.0, linewidths=None, + vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, **kwargs) Make a scatter plot of *x* versus *y*, where *x*, *y* are @@ -5438,7 +5438,7 @@ *norm* instance, your settings for *vmin* and *vmax* will be ignored. - *alpha*: 0 <= scalar <= 1 + *alpha*: 0 <= scalar <= 1 or None The alpha value for the patches *linewidths*: [ None | scalar | sequence ] @@ -5656,7 +5656,7 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None, xscale = 'linear', yscale = 'linear', extent = None, cmap=None, norm=None, vmin=None, vmax=None, - alpha=1.0, linewidths=None, edgecolors='none', + alpha=None, linewidths=None, edgecolors='none', reduce_C_function = np.mean, mincnt=None, marginals=False, **kwargs): """ @@ -5665,7 +5665,7 @@ hexbin(x, y, C = None, gridsize = 100, bins = None, xscale = 'linear', yscale = 'linear', cmap=None, norm=None, vmin=None, vmax=None, - alpha=1.0, linewidths=None, edgecolors='none' + alpha=None, linewidths=None, edgecolors='none' reduce_C_function = np.mean, mincnt=None, marginals=True **kwargs) @@ -5744,7 +5744,7 @@ array *C* is used. Note if you pass a norm instance, your settings for *vmin* and *vmax* will be ignored. - *alpha*: scalar + *alpha*: scalar between 0 and 1, or None the alpha value for the patches *linewidths*: [ None | scalar ] @@ -6438,14 +6438,14 @@ @docstring.dedent_interpd def imshow(self, X, cmap=None, norm=None, aspect=None, - interpolation=None, alpha=1.0, vmin=None, vmax=None, + interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, shape=None, filternorm=1, filterrad=4.0, imlim=None, resample=None, url=None, **kwargs): """ call signature:: imshow(X, cmap=None, norm=None, aspect=None, interpolation=None, - alpha=1.0, vmin=None, vmax=None, origin=None, extent=None, + alpha=None, vmin=None, vmax=None, origin=None, extent=None, **kwargs) Display the image in *X* to current axes. *X* may be a float @@ -6505,6 +6505,7 @@ *alpha*: scalar The alpha blending value, between 0 (transparent) and 1 (opaque) + or *None* *origin*: [ None | 'upper' | 'lower' ] Place the [0,0] index of the array in the upper left or lower left @@ -6673,7 +6674,7 @@ An mpl color or sequence of colors will set the edge color - *alpha*: 0 <= scalar <= 1 + *alpha*: 0 <= scalar <= 1 or *None* the alpha blending value Return value is a :class:`matplotlib.collection.Collection` @@ -6729,7 +6730,7 @@ if not self._hold: self.cla() - alpha = kwargs.pop('alpha', 1.0) + alpha = kwargs.pop('alpha', None) norm = kwargs.pop('norm', None) cmap = kwargs.pop('cmap', None) vmin = kwargs.pop('vmin', None) @@ -6858,7 +6859,7 @@ An mpl color or sequence of colors will set the edge color - *alpha*: 0 <= scalar <= 1 + *alpha*: 0 <= scalar <= 1 or *None* the alpha blending value Return value is a :class:`matplotlib.collection.QuadMesh` @@ -6878,7 +6879,7 @@ """ if not self._hold: self.cla() - alpha = kwargs.pop('alpha', 1.0) + alpha = kwargs.pop('alpha', None) norm = kwargs.pop('norm', None) cmap = kwargs.pop('cmap', None) vmin = kwargs.pop('vmin', None) @@ -7003,7 +7004,7 @@ luminance data. If either are *None*, the min and max of the color array *C* is used. If you pass a norm instance, *vmin* and *vmax* will be *None*. - *alpha*: 0 <= scalar <= 1 + *alpha*: 0 <= scalar <= 1 or *None* the alpha blending value Return value is an image if a regular or rectangular grid @@ -7014,7 +7015,7 @@ if not self._hold: self.cla() - alpha = kwargs.pop('alpha', 1.0) + alpha = kwargs.pop('alpha', None) norm = kwargs.pop('norm', None) cmap = kwargs.pop('cmap', None) vmin = kwargs.pop('vmin', None) Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -727,6 +727,8 @@ Set the alpha value used for blending - not supported on all backends """ + if alpha is None: + alpha = 1.0 self._alpha = alpha def set_antialiased(self, b): Modified: trunk/matplotlib/lib/matplotlib/cm.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cm.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/cm.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -160,21 +160,25 @@ 'set the colorbar image and axes associated with mappable' self.colorbar = im, ax - def to_rgba(self, x, alpha=1.0, bytes=False): + def to_rgba(self, x, alpha=None, bytes=False): '''Return a normalized rgba array corresponding to *x*. If *x* is already an rgb array, insert *alpha*; if it is already rgba, return it unchanged. If *bytes* is True, return rgba as 4 uint8s instead of 4 floats. ''' + if alpha is None: + _alpha = 1.0 + else: + _alpha = alpha try: if x.ndim == 3: if x.shape[2] == 3: if x.dtype == np.uint8: - alpha = np.array(alpha*255, np.uint8) + _alpha = np.array(_alpha*255, np.uint8) m, n = x.shape[:2] xx = np.empty(shape=(m,n,4), dtype = x.dtype) xx[:,:,:3] = x - xx[:,:,3] = alpha + xx[:,:,3] = _alpha elif x.shape[2] == 4: xx = x else: Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/collections.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -443,25 +443,27 @@ def set_alpha(self, alpha): """ Set the alpha tranparencies of the collection. *alpha* must be - a float. + a float or *None*. - ACCEPTS: float + ACCEPTS: float or None """ - try: float(alpha) - except TypeError: raise TypeError('alpha must be a float') - else: - artist.Artist.set_alpha(self, alpha) + if alpha is not None: try: - self._facecolors = mcolors.colorConverter.to_rgba_array( - self._facecolors_original, self._alpha) - except (AttributeError, TypeError, IndexError): - pass - try: - if self._edgecolors_original != 'face': - self._edgecolors = mcolors.colorConverter.to_rgba_array( - self._edgecolors_original, self._alpha) - except (AttributeError, TypeError, IndexError): - pass + float(alpha) + except TypeError: + raise TypeError('alpha must be a float or None') + artist.Artist.set_alpha(self, alpha) + try: + self._facecolors = mcolors.colorConverter.to_rgba_array( + self._facecolors_original, self._alpha) + except (AttributeError, TypeError, IndexError): + pass + try: + if self._edgecolors_original != 'face': + self._edgecolors = mcolors.colorConverter.to_rgba_array( + self._edgecolors_original, self._alpha) + except (AttributeError, TypeError, IndexError): + pass def get_linewidths(self): return self._linewidths Modified: trunk/matplotlib/lib/matplotlib/colorbar.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colorbar.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/colorbar.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -197,7 +197,7 @@ def __init__(self, ax, cmap=None, norm=None, - alpha=1.0, + alpha=None, values=None, boundaries=None, orientation='vertical', Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/contour.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -655,7 +655,7 @@ self.linewidths = kwargs.get('linewidths', None) self.linestyles = kwargs.get('linestyles', None) - self.alpha = kwargs.get('alpha', 1.0) + self.alpha = kwargs.get('alpha', None) self.origin = kwargs.get('origin', None) self.extent = kwargs.get('extent', None) cmap = kwargs.get('cmap', None) Modified: trunk/matplotlib/lib/matplotlib/figure.py =================================================================== --- trunk/matplotlib/lib/matplotlib/figure.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/figure.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -340,7 +340,7 @@ def figimage(self, X, xo=0, yo=0, - alpha=1.0, + alpha=None, norm=None, cmap=None, vmin=None, @@ -380,7 +380,7 @@ None, the min and max of the luminance values will be used. Note if you pass a norm instance, the settings for *vmin* and *vmax* will be ignored. - alpha the alpha blending value, default is 1.0 + alpha the alpha blending value, default is None origin [ 'upper' | 'lower' ] Indicates where the [0,0] index of the array is in the upper left or lower left corner of the axes. Defaults to the rc image.origin value Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2010-06-04 02:40:00 UTC (rev 8371) +++ trunk/matplotlib/lib/matplotlib/text.py 2010-06-04 03:37:56 UTC (rev 8372) @@ -61,7 +61,7 @@ ========================== ========================================================================= Property Value ========================== ========================================================================= - alpha float + alpha float or None animated [True | False] backgroundcolor any matplotlib color bbox rectangle prop dict plus key 'pad' which is a pad in points This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2010-06-07 13:04:31
|
Revision: 8392 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8392&view=rev Author: jdh2358 Date: 2010-06-07 13:04:24 +0000 (Mon, 07 Jun 2010) Log Message: ----------- fix adjusted prices so divs are included propely; closes sf 2949906 Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/finance.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-06-07 01:03:54 UTC (rev 8391) +++ trunk/matplotlib/CHANGELOG 2010-06-07 13:04:24 UTC (rev 8392) @@ -1,3 +1,12 @@ +2010-06-06 Change the way we do split/dividend adjustments in + finance.py to handle dividends and fix the zero division bug reported + in sf bug 2949906. Note that volume is not adjusted + because the Yahoo CSV does not distinguish between share + split and dividend adjustments making it near impossible to + get volume adjustement right (unless we want to guess based + on the size of the adjustment or scrape the html tables, + which we don't) - JDH + 2010-06-06 Updated dateutil to 1.5 and pytz to 2010h. 2010-06-02 Add error_kw kwarg to Axes.bar(). - EF Modified: trunk/matplotlib/lib/matplotlib/finance.py =================================================================== --- trunk/matplotlib/lib/matplotlib/finance.py 2010-06-07 01:03:54 UTC (rev 8391) +++ trunk/matplotlib/lib/matplotlib/finance.py 2010-06-07 13:04:24 UTC (rev 8392) @@ -42,7 +42,10 @@ where d is a floating poing representation of date, as returned by date2num - if adjusted=True, use adjusted prices + if adjusted=True, use adjusted prices. Note that volume is not + adjusted and we are not able to handle volume adjustments properly + because the Yahoo CSV does not distinguish between split and + dividend adjustments. """ results = [] @@ -68,10 +71,10 @@ volume = int(vals[5]) if adjusted: aclose = float(vals[6]) - m = aclose/close - open *= m - high *= m - low *= m + delta = aclose-close + open += delta + high += delta + low += delta close = aclose results.append((d, open, close, high, low, volume)) @@ -146,7 +149,10 @@ if asobject is True, the return val is an object with attrs date, open, close, high, low, volume, which are equal length arrays - if adjust=True, use adjusted prices + if adjusted=True, use adjusted prices. Note that volume is not + adjusted and we are not able to handle volume adjustments properly + because the Yahoo CSV does not distinguish between split and + dividend adjustments. Ex: sp = f.quotes_historical_yahoo('^GSPC', d1, d2, asobject=True, adjusted=True) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2010-06-09 17:57:46
|
Revision: 8402 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8402&view=rev Author: efiring Date: 2010-06-09 17:57:36 +0000 (Wed, 09 Jun 2010) Log Message: ----------- Axes.grid controls minor and/or major lines; axis.grid allows 'both' Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/axis.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-06-09 03:04:53 UTC (rev 8401) +++ trunk/matplotlib/CHANGELOG 2010-06-09 17:57:36 UTC (rev 8402) @@ -1,3 +1,7 @@ +2010-06-09 Allow Axes.grid to control minor gridlines; allow + Axes.grid and Axis.grid to control major and minor + gridlines in the same method call. - EF + 2010-06-06 Change the way we do split/dividend adjustments in finance.py to handle dividends and fix the zero division bug reported in sf bug 2949906. Note that volume is not adjusted Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2010-06-09 03:04:53 UTC (rev 8401) +++ trunk/matplotlib/lib/matplotlib/axes.py 2010-06-09 17:57:36 UTC (rev 8402) @@ -1957,19 +1957,22 @@ self._axisbelow = b @docstring.dedent_interpd - def grid(self, b=None, **kwargs): + def grid(self, b=None, which='major', **kwargs): """ call signature:: - grid(self, b=None, **kwargs) + grid(self, b=None, which='major', **kwargs) Set the axes grids on or off; *b* is a boolean. (For Matlab compatibility, *b* may also be a string, 'on' or 'off'.) If *b* is *None* and ``len(kwargs)==0``, toggle the grid state. If *kwargs* are supplied, it is assumed that you want a grid and *b* - is thus set to *True* + is thus set to *True*. + *which* can be 'major' (default), 'minor', or 'both' to control + whether major tick grids, minor tick grids, or both are affected. + *kawrgs* are used to set the grid line properties, eg:: ax.grid(color='r', linestyle='-', linewidth=2) @@ -1981,8 +1984,8 @@ if len(kwargs): b = True b = _string_to_bool(b) - self.xaxis.grid(b, **kwargs) - self.yaxis.grid(b, **kwargs) + self.xaxis.grid(b, which=which, **kwargs) + self.yaxis.grid(b, which=which, **kwargs) def ticklabel_format(self, **kwargs): """ Modified: trunk/matplotlib/lib/matplotlib/axis.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axis.py 2010-06-09 03:04:53 UTC (rev 8401) +++ trunk/matplotlib/lib/matplotlib/axis.py 2010-06-09 17:57:36 UTC (rev 8402) @@ -1002,7 +1002,7 @@ def grid(self, b=None, which='major', **kwargs): """ Set the axis grid on or off; b is a boolean. Use *which* = - 'major' | 'minor' to set the grid for major or minor ticks. + 'major' | 'minor' | 'both' to set the grid for major or minor ticks. If *b* is *None* and len(kwargs)==0, toggle the grid state. If *kwargs* are supplied, it is assumed you want the grid on and *b* @@ -1013,14 +1013,15 @@ xax.grid(color='r', linestyle='-', linewidth=2) """ if len(kwargs): b = True - if which.lower().find('minor')>=0: + which = which.lower() + if which in ['minor', 'both']: if b is None: self._gridOnMinor = not self._gridOnMinor else: self._gridOnMinor = b for tick in self.minorTicks: # don't use get_ticks here! if tick is None: continue tick.gridOn = self._gridOnMinor if len(kwargs): artist.setp(tick.gridline,**kwargs) - if which.lower().find('major')>=0: + if which in ['major', 'both']: if b is None: self._gridOnMajor = not self._gridOnMajor else: self._gridOnMajor = b for tick in self.majorTicks: # don't use get_ticks here! This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2010-06-09 22:05:16
|
Revision: 8403 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8403&view=rev Author: jdh2358 Date: 2010-06-09 22:05:09 +0000 (Wed, 09 Jun 2010) Log Message: ----------- fix legend doc typos Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/users/legend_guide.rst Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-06-09 17:57:36 UTC (rev 8402) +++ trunk/matplotlib/CHANGELOG 2010-06-09 22:05:09 UTC (rev 8403) @@ -4,7 +4,7 @@ 2010-06-06 Change the way we do split/dividend adjustments in finance.py to handle dividends and fix the zero division bug reported - in sf bug 2949906. Note that volume is not adjusted + in sf bug 2949906 and 2123566. Note that volume is not adjusted because the Yahoo CSV does not distinguish between share split and dividend adjustments making it near impossible to get volume adjustement right (unless we want to guess based Modified: trunk/matplotlib/doc/users/legend_guide.rst =================================================================== --- trunk/matplotlib/doc/users/legend_guide.rst 2010-06-09 17:57:36 UTC (rev 8402) +++ trunk/matplotlib/doc/users/legend_guide.rst 2010-06-09 22:05:09 UTC (rev 8403) @@ -12,14 +12,14 @@ ==================== The legend command has a following call signature:: - + legend(*args, **kwargs) - + If len(args) is 2, the first argument should be a list of artist to be labeled, and the second argument should a list of string labels. If len(args) is 0, it automatically generate the legend from label properties of the child artists by calling -:meth:`~matplotlib.axes.Axes.get_legend_handles_labels` method. +:meth:`~matplotlib.axes.Axes.get_legend_handles_labels` method. For example, *ax.legend()* is equivalent to:: handles, labels = ax.get_legend_handles_labels() @@ -44,7 +44,7 @@ * :class:`~matplotlib.patches.Patch` * :class:`~matplotlib.collections.LineCollection` * :class:`~matplotlib.collections.RegularPolyCollection` - + Unfortunately, there is no easy workaround when you need legend for an artist not in the above list (You may use one of the supported artist as a proxy. See below), or customize it beyond what is @@ -84,28 +84,28 @@ p1, = ax.plot([1,2,3], label="line 1") p2, = ax.plot([3,2,1], label="line 2") p3, = ax.plot([2,3,1], label="line 3") - + handles, labels = ax.get_legend_handles_labels() # reverse the order ax.legend(handles[::-1], labels[::-1]) - + # or sort them by labels import operator hl = sorted(zip(handles, labels), key=operator.itemgetter(1)) handles2, labels2 = zip(*hl) - + ax.legend(handles2, labels2) Using Proxy Artist ------------------ -When you want to display legend for an artist not supported by the -matplotlib, you may use other supported artist as a proxy. For -example, you may creates an proxy artist without adding it to the axes -(so the proxy artist will not be drawn in the main axes) and feet it +When you want to display legend for an artist not supported by +matplotlib, you may use another artist as a proxy. For +example, you may create a proxy artist without adding it to the axes +(so the proxy artist will not be drawn in the main axes) and feed it to the legend function.:: p = Rectangle((0, 0), 1, 1, fc="r") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-06-10 17:04:50
|
Revision: 8407 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8407&view=rev Author: mdboom Date: 2010-06-10 17:04:44 +0000 (Thu, 10 Jun 2010) Log Message: ----------- [2908399] Support clip paths in QuadMesh with gouraud shading Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py trunk/matplotlib/src/_backend_agg.cpp Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2010-06-10 14:06:50 UTC (rev 8406) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2010-06-10 17:04:44 UTC (rev 8407) @@ -370,6 +370,24 @@ self._n_gradients += 1 + def draw_gouraud_triangles(self, gc, triangles_array, colors_array, + transform): + write = self._svgwriter.write + + clipid = self._get_gc_clip_svg(gc) + if clipid is None: + clippath = '' + else: + clippath = 'clip-path="url(#%s)"' % clipid + + write('<g %s>\n' % clippath) + + transform = transform.frozen() + for tri, col in zip(triangles_array, colors_array): + self.draw_gouraud_triangle(gc, tri, col, transform) + + write('</g>\n') + def draw_image(self, gc, x, y, im): # MGDTODO: Support clippath here trans = [1,0,0,1,0,0] Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2010-06-10 14:06:50 UTC (rev 8406) +++ trunk/matplotlib/src/_backend_agg.cpp 2010-06-10 17:04:44 UTC (rev 8407) @@ -1532,7 +1532,7 @@ theRasterizer.reset_clipping(); rendererBase.reset_clipping(true); set_clipbox(gc.cliprect, theRasterizer); - /* TODO: Support clip paths */ + bool has_clippath = render_clippath(gc.clippath, gc.clippath_trans); trans *= agg::trans_affine_scaling(1.0, -1.0); trans *= agg::trans_affine_translation(0.0, (double)height); @@ -1560,7 +1560,19 @@ theRasterizer.add_path(span_gen); - agg::render_scanlines_aa(theRasterizer, slineP8, rendererBase, span_alloc, span_gen); + if (has_clippath) { + typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type; + typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type; + typedef agg::renderer_scanline_aa<amask_ren_type, span_alloc_t, span_gen_t> + amask_aa_renderer_type; + + pixfmt_amask_type pfa(pixFmt, alphaMask); + amask_ren_type r(pfa); + amask_aa_renderer_type ren(r, span_alloc, span_gen); + agg::render_scanlines(theRasterizer, slineP8, ren); + } else { + agg::render_scanlines_aa(theRasterizer, slineP8, rendererBase, span_alloc, span_gen); + } } Py::Object This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-06-10 17:48:17
|
Revision: 8408 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8408&view=rev Author: mdboom Date: 2010-06-10 17:48:10 +0000 (Thu, 10 Jun 2010) Log Message: ----------- Update to the 1.0 STIX fonts. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/font_manager.py trunk/matplotlib/lib/matplotlib/mathtext.py trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/LICENSE_STIX trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneralBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUni.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUniBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUniBolIta.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUniIta.ttf trunk/matplotlib/setup.py Added Paths: ----------- trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFiveSymReg.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymReg.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymReg.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymReg.ttf Removed Paths: ------------- trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz1Sym.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz1SymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz2Sym.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz2SymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz3Sym.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz3SymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz4Sym.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz4SymBol.ttf trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz5Sym.ttf Modified: trunk/matplotlib/lib/matplotlib/font_manager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/font_manager.py 2010-06-10 17:04:44 UTC (rev 8407) +++ trunk/matplotlib/lib/matplotlib/font_manager.py 2010-06-10 17:48:10 UTC (rev 8408) @@ -975,7 +975,7 @@ # Increment this version number whenever the font cache data # format or behavior has changed and requires a existing font # cache files to be rebuilt. - __version__ = 6 + __version__ = 7 def __init__(self, size=None, weight='normal'): self._version = self.__version__ Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2010-06-10 17:04:44 UTC (rev 8407) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2010-06-10 17:48:10 UTC (rev 8408) @@ -330,7 +330,7 @@ def render_glyph(self, ox, oy, info): oy = self.height - oy + info.offset thetext = unichr_safe(info.num) - + self.svg_glyphs.append( (info.font, info.fontsize, thetext, ox, oy, info.metrics)) @@ -850,7 +850,7 @@ fontname, font_class, uniindex) new_fontname = fontname - + # Only characters in the "Letter" class should be italicized in 'it' # mode. Greek capital letters should be Roman. if found_symbol: @@ -923,11 +923,11 @@ 'nonunibf' : 'STIXNonUnicode:weight=bold', 0 : 'STIXGeneral', - 1 : 'STIXSize1', - 2 : 'STIXSize2', - 3 : 'STIXSize3', - 4 : 'STIXSize4', - 5 : 'STIXSize5' + 1 : 'STIXSizeOneSym', + 2 : 'STIXSizeTwoSym', + 3 : 'STIXSizeThreeSym', + 4 : 'STIXSizeFourSym', + 5 : 'STIXSizeFiveSym' } use_cmex = False cm_fallback = False Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/LICENSE_STIX =================================================================== --- trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/LICENSE_STIX 2010-06-10 17:04:44 UTC (rev 8407) +++ trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/LICENSE_STIX 2010-06-10 17:48:10 UTC (rev 8408) @@ -1,71 +1,124 @@ -TERMS AND CONDITIONS +The STIX fonts distributed with matplotlib have been modified from +their canonical form. They have been converted from OTF to TTF format +using Fontforge and this script: - 1. Permission is hereby granted, free of charge, to any person -obtaining a copy of the STIX Fonts-TM set accompanying this license -(collectively, the "Fonts") and the associated documentation files -(collectively with the Fonts, the "Font Software"), to reproduce and -distribute the Font Software, including the rights to use, copy, merge -and publish copies of the Font Software, and to permit persons to whom -the Font Software is furnished to do so same, subject to the following -terms and conditions (the "License"). + #!/usr/bin/env fontforge + i=1 + while ( i<$argc ) + Open($argv[i]) + Generate($argv[i]:r + ".ttf") + i = i+1 + endloop - 2. The following copyright and trademark notice and these Terms and -Conditions shall be included in all copies of one or more of the Font -typefaces and any derivative work created as permitted under this -License: +The original STIX Font License begins below. - Copyright (c) 2001-2005 by the STI Pub Companies, consisting of -the American Institute of Physics, the American Chemical Society, the -American Mathematical Society, the American Physical Society, Elsevier, -Inc., and The Institute of Electrical and Electronic Engineers, Inc. -Portions copyright (c) 1998-2003 by MicroPress, Inc. Portions copyright -(c) 1990 by Elsevier, Inc. All rights reserved. STIX Fonts-TM is a -trademark of The Institute of Electrical and Electronics Engineers, Inc. +----------------------------------------------------------- - 3. You may (a) convert the Fonts from one format to another (e.g., -from TrueType to PostScript), in which case the normal and reasonable -distortion that occurs during such conversion shall be permitted and (b) -embed or include a subset of the Fonts in a document for the purposes of -allowing users to read text in the document that utilizes the Fonts. In -each case, you may use the STIX Fonts-TM mark to designate the resulting -Fonts or subset of the Fonts. +STIX Font License - 4. You may also (a) add glyphs or characters to the Fonts, or modify -the shape of existing glyphs, so long as the base set of glyphs is not -removed and (b) delete glyphs or characters from the Fonts, provided -that the resulting font set is distributed with the following -disclaimer: "This [name] font does not include all the Unicode points -covered in the STIX Fonts-TM set but may include others." In each case, -the name used to denote the resulting font set shall not include the -term "STIX" or any similar term. +24 May 2010 - 5. You may charge a fee in connection with the distribution of the -Font Software, provided that no copy of one or more of the individual -Font typefaces that form the STIX Fonts-TM set may be sold by itself. +Copyright (c) 2001-2010 by the STI Pub Companies, consisting of the American +Institute of Physics, the American Chemical Society, the American Mathematical +Society, the American Physical Society, Elsevier, Inc., and The Institute of +Electrical and Electronic Engineers, Inc. (www.stixfonts.org), with Reserved +Font Name STIX Fonts, STIX Fonts (TM) is a trademark of The Institute of +Electrical and Electronics Engineers, Inc. - 6. THE FONT SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY -KIND, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK OR OTHER RIGHT. IN NO EVENT SHALL -MICROPRESS OR ANY OF THE STI PUB COMPANIES BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, INCLUDING, BUT NOT LIMITED TO, ANY GENERAL, -SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM OR OUT OF THE USE OR -INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT -SOFTWARE. +Portions copyright (c) 1998-2003 by MicroPress, Inc. (www.micropress-inc.com), +with Reserved Font Name TM Math. To obtain additional mathematical fonts, please +contact MicroPress, Inc., 68-30 Harrow Street, Forest Hills, NY 11375, USA, +Phone: (718) 575-1816. - 7. Except as contained in the notice set forth in Section 2, the -names MicroPress Inc. and STI Pub Companies, as well as the names of the -companies/organizations that compose the STI Pub Companies, shall not be -used in advertising or otherwise to promote the sale, use or other -dealings in the Font Software without the prior written consent of the -respective company or organization. +Portions copyright (c) 1990 by Elsevier, Inc. - 8. This License shall become null and void in the event of any -material breach of the Terms and Conditions herein by licensee. +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL - 9. A substantial portion of the STIX Fonts set was developed by -MicroPress Inc. for the STI Pub Companies. To obtain additional -mathematical fonts, please contact MicroPress, Inc., 68-30 Harrow -Street, Forest Hills, NY 11375, USA - Phone: (718) 575-1816. +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneralBol.ttf =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUni.ttf =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUniBol.ttf =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUniBolIta.ttf =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXNonUniIta.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz1Sym.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz1SymBol.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz2Sym.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz2SymBol.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz3Sym.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz3SymBol.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz4Sym.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz4SymBol.ttf =================================================================== (Binary files differ) Deleted: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSiz5Sym.ttf =================================================================== (Binary files differ) Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFiveSymReg.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFiveSymReg.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymBol.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymBol.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymReg.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizFourSymReg.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymBol.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymBol.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymBol.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymBol.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymReg.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymReg.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymBol.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymBol.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymReg.ttf =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/lib/matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymReg.ttf ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/matplotlib/setup.py =================================================================== --- trunk/matplotlib/setup.py 2010-06-10 17:04:44 UTC (rev 8407) +++ trunk/matplotlib/setup.py 2010-06-10 17:48:10 UTC (rev 8408) @@ -95,6 +95,10 @@ 'mpl-data/fonts/pdfcorefonts/*.afm', 'mpl-data/fonts/pdfcorefonts/*.txt', 'mpl-data/fonts/ttf/*.ttf', + 'mpl-data/fonts/ttf/LICENSE_STIX', + 'mpl-data/fonts/ttf/COPYRIGHT.TXT', + 'mpl-data/fonts/ttf/README.TXT', + 'mpl-data/fonts/ttf/RELEASENOTES.TXT', 'mpl-data/images/*.xpm', 'mpl-data/images/*.svg', 'mpl-data/images/*.png', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-06-11 14:30:38
|
Revision: 8414 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8414&view=rev Author: mdboom Date: 2010-06-11 14:30:32 +0000 (Fri, 11 Jun 2010) Log Message: ----------- Take stroke width into account when quantizing rectilinear paths. Discovered by Jason Grout in the mailing list thread "Plots shifted up or to the left a pixel or so" Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/artist.py trunk/matplotlib/lib/matplotlib/path.py trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_dates/date_axhline.png trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_dates/date_axvline.png trunk/matplotlib/src/_backend_agg.cpp trunk/matplotlib/src/_macosx.m trunk/matplotlib/src/_path.cpp trunk/matplotlib/src/path_cleanup.cpp trunk/matplotlib/src/path_converters.h Modified: trunk/matplotlib/lib/matplotlib/artist.py =================================================================== --- trunk/matplotlib/lib/matplotlib/artist.py 2010-06-11 08:34:24 UTC (rev 8413) +++ trunk/matplotlib/lib/matplotlib/artist.py 2010-06-11 14:30:32 UTC (rev 8414) @@ -412,7 +412,7 @@ * None: (auto) If the path contains only rectilinear line segments, round to the nearest pixel center - Only supported by the Agg backends. + Only supported by the Agg and MacOSX backends. """ return self._snap @@ -427,7 +427,7 @@ * None: (auto) If the path contains only rectilinear line segments, round to the nearest pixel center - Only supported by the Agg backends. + Only supported by the Agg and MacOSX backends. """ self._snap = snap Modified: trunk/matplotlib/lib/matplotlib/path.py =================================================================== --- trunk/matplotlib/lib/matplotlib/path.py 2010-06-11 08:34:24 UTC (rev 8413) +++ trunk/matplotlib/lib/matplotlib/path.py 2010-06-11 14:30:32 UTC (rev 8414) @@ -188,7 +188,8 @@ return len(self.vertices) def iter_segments(self, transform=None, remove_nans=True, clip=None, - quantize=False, simplify=None, curves=True): + quantize=False, stroke_width=1.0, simplify=None, + curves=True): """ Iterates over all of the curve segments in the path. Each iteration returns a 2-tuple (*vertices*, *code*), where @@ -210,6 +211,9 @@ *quantize*: if None, auto-quantize. If True, force quantize, and if False, don't quantize. + *stroke_width*: the width of the stroke being drawn. Needed + as a hint for the quantizer. + *simplify*: if True, perform simplification, to remove vertices that do not affect the appearance of the path. If False, perform no simplification. If None, use the @@ -232,7 +236,7 @@ STOP = self.STOP vertices, codes = cleanup_path(self, transform, remove_nans, clip, - quantize, simplify, curves) + quantize, stroke_width, simplify, curves) len_vertices = len(vertices) i = 0 Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_dates/date_axhline.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_dates/date_axvline.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2010-06-11 08:34:24 UTC (rev 8413) +++ trunk/matplotlib/src/_backend_agg.cpp 2010-06-11 14:30:32 UTC (rev 8414) @@ -535,14 +535,16 @@ transformed_path_t marker_path_transformed(marker_path, marker_trans); quantize_t marker_path_quantized(marker_path_transformed, gc.quantize_mode, - marker_path.total_vertices()); + marker_path.total_vertices(), + gc.linewidth); curve_t marker_path_curve(marker_path_quantized); PathIterator path(path_obj); transformed_path_t path_transformed(path, trans); quantize_t path_quantized(path_transformed, gc.quantize_mode, - path.total_vertices()); + path.total_vertices(), + 1.0); curve_t path_curve(path_quantized); path_curve.rewind(0); @@ -1106,7 +1108,7 @@ transformed_path_t tpath(path, trans); nan_removed_t nan_removed(tpath, true, path.has_curves()); clipped_t clipped(nan_removed, clip, width, height); - quantized_t quantized(clipped, gc.quantize_mode, path.total_vertices()); + quantized_t quantized(clipped, gc.quantize_mode, path.total_vertices(), gc.linewidth); simplify_t simplified(quantized, simplify, path.simplify_threshold()); curve_t curve(simplified); @@ -1273,7 +1275,8 @@ transformed_path_t tpath(path, trans); nan_removed_t nan_removed(tpath, true, has_curves); clipped_t clipped(nan_removed, do_clip, width, height); - quantized_t quantized(clipped, gc.quantize_mode, path.total_vertices()); + quantized_t quantized(clipped, gc.quantize_mode, + path.total_vertices(), gc.linewidth); if (has_curves) { quantized_curve_t curve(quantized); _draw_path(curve, has_clippath, face, gc); Modified: trunk/matplotlib/src/_macosx.m =================================================================== --- trunk/matplotlib/src/_macosx.m 2010-06-11 08:34:24 UTC (rev 8413) +++ trunk/matplotlib/src/_macosx.m 2010-06-11 14:30:32 UTC (rev 8414) @@ -289,6 +289,7 @@ 0, rect, QUANTIZE_FALSE, + 1.0, 0); Py_DECREF(transform); if (!iterator) @@ -662,6 +663,7 @@ 0, rect, QUANTIZE_AUTO, + 1.0, 0); Py_DECREF(transform); if (!iterator) @@ -889,6 +891,7 @@ 0, rect, QUANTIZE_AUTO, + CGContextGetLineWidth(self), rgbFace == NULL); if (!iterator) { @@ -966,6 +969,7 @@ 0, rect, QUANTIZE_AUTO, + CGContextGetLineWidth(self), 0); if (!iterator) { @@ -1042,6 +1046,7 @@ 0, rect, mode, + CGContextGetLineWidth(self), 0); if (!iterator) { @@ -1063,6 +1068,7 @@ 1, rect, QUANTIZE_TRUE, + 1.0, 0); if (!iterator) { @@ -1326,6 +1332,17 @@ 0, rect, mode, + 1.0, + /* Hardcoding stroke width to 1.0 + here, but for true + correctness, the paths would + need to be set up for each + different linewidth that may + be applied below. This + difference is very minute in + practice, so this hardcoding + is probably ok for now. -- + MGD */ 0); Py_DECREF(transform); Py_DECREF(path); @@ -1362,6 +1379,7 @@ 0, rect, QUANTIZE_AUTO, + 1.0, 0); if (!iterator) { @@ -1669,6 +1687,7 @@ 0, rect, QUANTIZE_AUTO, + 1.0, 0); if (iterator) { @@ -2654,6 +2673,7 @@ 0, rect, QUANTIZE_AUTO, + 1.0, 0); if (iterator) { Modified: trunk/matplotlib/src/_path.cpp =================================================================== --- trunk/matplotlib/src/_path.cpp 2010-06-11 08:34:24 UTC (rev 8413) +++ trunk/matplotlib/src/_path.cpp 2010-06-11 14:30:32 UTC (rev 8414) @@ -1228,8 +1228,9 @@ void _cleanup_path(PathIterator& path, const agg::trans_affine& trans, bool remove_nans, bool do_clip, const agg::rect_base<double>& rect, - e_quantize_mode quantize_mode, bool do_simplify, - bool return_curves, std::vector<double>& vertices, + e_quantize_mode quantize_mode, double stroke_width, + bool do_simplify, bool return_curves, + std::vector<double>& vertices, std::vector<npy_uint8>& codes) { typedef agg::conv_transform<PathIterator> transformed_path_t; typedef PathNanRemover<transformed_path_t> nan_removal_t; @@ -1241,7 +1242,7 @@ transformed_path_t tpath(path, trans); nan_removal_t nan_removed(tpath, remove_nans, path.has_curves()); clipped_t clipped(nan_removed, do_clip, rect); - quantized_t quantized(clipped, quantize_mode, path.total_vertices()); + quantized_t quantized(clipped, quantize_mode, path.total_vertices(), stroke_width); simplify_t simplified(quantized, do_simplify, path.simplify_threshold()); vertices.reserve(path.total_vertices() * 2); @@ -1260,7 +1261,7 @@ Py::Object _path_module::cleanup_path(const Py::Tuple& args) { - args.verify_length(7); + args.verify_length(8); PathIterator path(args[0]); agg::trans_affine trans = py_to_agg_transformation_matrix(args[1].ptr(), false); @@ -1300,8 +1301,10 @@ quantize_mode = QUANTIZE_FALSE; } + double stroke_width = Py::Float(args[5]); + bool simplify; - Py::Object simplify_obj = args[5]; + Py::Object simplify_obj = args[6]; if (simplify_obj.isNone()) { simplify = path.should_simplify(); @@ -1311,13 +1314,13 @@ simplify = simplify_obj.isTrue(); } - bool return_curves = args[6].isTrue(); + bool return_curves = args[7].isTrue(); std::vector<double> vertices; std::vector<npy_uint8> codes; _cleanup_path(path, trans, remove_nans, do_clip, clip_rect, quantize_mode, - simplify, return_curves, vertices, codes); + stroke_width, simplify, return_curves, vertices, codes); npy_intp length = codes.size(); npy_intp dims[] = { length, 2, 0 }; Modified: trunk/matplotlib/src/path_cleanup.cpp =================================================================== --- trunk/matplotlib/src/path_cleanup.cpp 2010-06-11 08:34:24 UTC (rev 8413) +++ trunk/matplotlib/src/path_cleanup.cpp 2010-06-11 14:30:32 UTC (rev 8414) @@ -28,14 +28,16 @@ PathCleanupIterator(PyObject* path, agg::trans_affine trans, bool remove_nans, bool do_clip, const agg::rect_base<double>& rect, - e_quantize_mode quantize_mode, bool do_simplify) : + e_quantize_mode quantize_mode, double stroke_width, + bool do_simplify) : m_path_obj(path, true), m_path_iter(m_path_obj), m_transform(trans), m_transformed(m_path_iter, m_transform), m_nan_removed(m_transformed, remove_nans, m_path_iter.has_curves()), m_clipped(m_nan_removed, do_clip, rect), - m_quantized(m_clipped, quantize_mode, m_path_iter.total_vertices()), + m_quantized(m_clipped, quantize_mode, m_path_iter.total_vertices(), + stroke_width), m_simplify(m_quantized, do_simplify && m_path_iter.should_simplify(), m_path_iter.simplify_threshold()) { @@ -53,14 +55,15 @@ void* get_path_iterator( PyObject* path, PyObject* trans, int remove_nans, int do_clip, - double rect[4], e_quantize_mode quantize_mode, int do_simplify) + double rect[4], e_quantize_mode quantize_mode, double stroke_width, + int do_simplify) { agg::trans_affine agg_trans = py_to_agg_transformation_matrix(trans, false); agg::rect_base<double> clip_rect(rect[0], rect[1], rect[2], rect[3]); PathCleanupIterator* pipeline = new PathCleanupIterator( path, agg_trans, remove_nans != 0, do_clip != 0, - clip_rect, quantize_mode, do_simplify != 0); + clip_rect, quantize_mode, stroke_width, do_simplify != 0); return (void*)pipeline; } Modified: trunk/matplotlib/src/path_converters.h =================================================================== --- trunk/matplotlib/src/path_converters.h 2010-06-11 08:34:24 UTC (rev 8413) +++ trunk/matplotlib/src/path_converters.h 2010-06-11 14:30:32 UTC (rev 8414) @@ -378,6 +378,7 @@ private: VertexSource* m_source; bool m_quantize; + double m_quantize_value; static bool should_quantize(VertexSource& path, e_quantize_mode quantize_mode, @@ -436,10 +437,17 @@ - QUANTIZE_FALSE: No quantization */ PathQuantizer(VertexSource& source, e_quantize_mode quantize_mode, - unsigned total_vertices=15) : + unsigned total_vertices=15, double stroke_width=0.0) : m_source(&source) { m_quantize = should_quantize(source, quantize_mode, total_vertices); + + if (m_quantize) + { + int odd_even = (int)mpl_round(stroke_width) % 2; + m_quantize_value = (odd_even) ? 0.5 : 0.0; + } + source.rewind(0); } @@ -454,8 +462,8 @@ code = m_source->vertex(x, y); if (m_quantize && agg::is_vertex(code)) { - *x = mpl_round(*x) + 0.5; - *y = mpl_round(*y) + 0.5; + *x = mpl_round(*x) + m_quantize_value; + *y = mpl_round(*y) + m_quantize_value; } return code; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2010-06-11 18:17:59
|
Revision: 8415 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8415&view=rev Author: mdboom Date: 2010-06-11 18:17:52 +0000 (Fri, 11 Jun 2010) Log Message: ----------- Add a global rcParam 'path.snap' that, when False, turns off all pixel-snapping. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/artist.py trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/config/mplconfig.py trunk/matplotlib/lib/matplotlib/config/rcsetup.py trunk/matplotlib/lib/matplotlib/patches.py trunk/matplotlib/lib/matplotlib/rcsetup.py trunk/matplotlib/matplotlibrc.template Modified: trunk/matplotlib/lib/matplotlib/artist.py =================================================================== --- trunk/matplotlib/lib/matplotlib/artist.py 2010-06-11 14:30:32 UTC (rev 8414) +++ trunk/matplotlib/lib/matplotlib/artist.py 2010-06-11 18:17:52 UTC (rev 8415) @@ -2,7 +2,7 @@ import re, warnings import matplotlib import matplotlib.cbook as cbook -from matplotlib import docstring +from matplotlib import docstring, rcParams from transforms import Bbox, IdentityTransform, TransformedBbox, TransformedPath from path import Path @@ -414,7 +414,10 @@ Only supported by the Agg and MacOSX backends. """ - return self._snap + if rcParams['path.snap']: + return self._snap + else: + return False def set_snap(self, snap): """ Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2010-06-11 14:30:32 UTC (rev 8414) +++ trunk/matplotlib/lib/matplotlib/collections.py 2010-06-11 18:17:52 UTC (rev 8415) @@ -211,6 +211,7 @@ gc = renderer.new_gc() self._set_gc_clip(gc) + gc.set_snap(self.get_snap()) renderer.draw_path_collection( gc, transform.frozen(), paths, self.get_transforms(), Modified: trunk/matplotlib/lib/matplotlib/config/mplconfig.py =================================================================== --- trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2010-06-11 14:30:32 UTC (rev 8414) +++ trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2010-06-11 18:17:52 UTC (rev 8415) @@ -118,6 +118,7 @@ class path(TConfig): simplify = T.false simplify_threshold = T.float(1.0 / 9.0) + snap = T.true class patch(TConfig): linewidth = T.Float(1.0) @@ -444,7 +445,8 @@ # Path properties 'path.simplify' : (self.tconfig.path, 'simplify'), - 'path.simplify_threshold' : (self.tconfig.path, 'simplify_threshold') + 'path.simplify_threshold' : (self.tconfig.path, 'simplify_threshold'), + 'path.snap' : (self.tconfig.path, 'snap') } def __setitem__(self, key, val): Modified: trunk/matplotlib/lib/matplotlib/config/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/config/rcsetup.py 2010-06-11 14:30:32 UTC (rev 8414) +++ trunk/matplotlib/lib/matplotlib/config/rcsetup.py 2010-06-11 18:17:52 UTC (rev 8415) @@ -476,7 +476,8 @@ 'plugins.directory' : ['.matplotlib_plugins', str], # where plugin directory is locate 'path.simplify' : [True, validate_bool], - 'path.simplify_threshold' : [1.0 / 9.0, ValidateInterval(0.0, 1.0)] + 'path.simplify_threshold' : [1.0 / 9.0, ValidateInterval(0.0, 1.0)], + 'path.snap' : [True, validate_bool] } if __name__ == '__main__': Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2010-06-11 14:30:32 UTC (rev 8414) +++ trunk/matplotlib/lib/matplotlib/patches.py 2010-06-11 18:17:52 UTC (rev 8415) @@ -356,7 +356,7 @@ self._set_gc_clip(gc) gc.set_capstyle('projecting') gc.set_url(self._url) - gc.set_snap(self._snap) + gc.set_snap(self.get_snap()) if (not self.fill or self._facecolor is None or (cbook.is_string_like(self._facecolor) and self._facecolor.lower()=='none')): @@ -3845,6 +3845,7 @@ gc.set_antialiased(self._antialiased) self._set_gc_clip(gc) gc.set_capstyle('round') + gc.set_snap(self.get_snap()) if (not self.fill or self._facecolor is None or (cbook.is_string_like(self._facecolor) and self._facecolor.lower()=='none')): Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2010-06-11 14:30:32 UTC (rev 8414) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2010-06-11 18:17:52 UTC (rev 8415) @@ -546,16 +546,17 @@ 'path.simplify' : [True, validate_bool], 'path.simplify_threshold' : [1.0 / 9.0, ValidateInterval(0.0, 1.0)], + 'path.snap' : [True, validate_bool], 'agg.path.chunksize' : [0, validate_int], # 0 to disable chunking; # recommend about 20000 to # enable. Experimental. # key-mappings - 'keymap.fullscreen' : ['f', validate_stringlist], + 'keymap.fullscreen' : ['f', validate_stringlist], 'keymap.home' : [['h', 'r', 'home'], validate_stringlist], 'keymap.back' : [['left', 'c', 'backspace'], validate_stringlist], 'keymap.forward' : [['right', 'v'], validate_stringlist], 'keymap.pan' : ['p', validate_stringlist], - 'keymap.zoom' : ['o', validate_stringlist], + 'keymap.zoom' : ['o', validate_stringlist], 'keymap.save' : ['s', validate_stringlist], 'keymap.grid' : ['g', validate_stringlist], 'keymap.yscale' : ['l', validate_stringlist], Modified: trunk/matplotlib/matplotlibrc.template =================================================================== --- trunk/matplotlib/matplotlibrc.template 2010-06-11 14:30:32 UTC (rev 8414) +++ trunk/matplotlib/matplotlibrc.template 2010-06-11 18:17:52 UTC (rev 8415) @@ -63,10 +63,10 @@ # circles. See # http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.patches # information on patch properties -#patch.linewidth : 1.0 # edge width in points -#patch.facecolor : blue -#patch.edgecolor : black -#patch.antialiased : True # render patches in antialised (no jaggies) +#patch.linewidth : 1.0 # edge width in points +#patch.facecolor : blue +#patch.edgecolor : black +#patch.antialiased : True # render patches in antialised (no jaggies) ### FONT # @@ -268,12 +268,12 @@ # The figure subplot parameters. All dimensions are fraction of the # figure width or height -#figure.subplot.left : 0.125 # the left side of the subplots of the figure -#figure.subplot.right : 0.9 # the right side of the subplots of the figure -#figure.subplot.bottom : 0.1 # the bottom of the subplots of the figure -#figure.subplot.top : 0.9 # the top of the subplots of the figure -#figure.subplot.wspace : 0.2 # the amount of width reserved for blank space between subplots -#figure.subplot.hspace : 0.2 # the amount of height reserved for white space between subplots +#figure.subplot.left : 0.125 # the left side of the subplots of the figure +#figure.subplot.right : 0.9 # the right side of the subplots of the figure +#figure.subplot.bottom : 0.1 # the bottom of the subplots of the figure +#figure.subplot.top : 0.9 # the top of the subplots of the figure +#figure.subplot.wspace : 0.2 # the amount of width reserved for blank space between subplots +#figure.subplot.hspace : 0.2 # the amount of height reserved for white space between subplots ### IMAGES #image.aspect : equal # equal | auto | a number @@ -297,12 +297,15 @@ # A value of 20000 is probably a good # starting point. ### SAVING FIGURES -#path.simplify : False # When True, simplify paths by removing "invisible" +#path.simplify : True # When True, simplify paths by removing "invisible" # points to reduce file size and increase rendering # speed #path.simplify_threshold : 0.1 # The threshold of similarity below which # vertices will be removed in the simplification # process +#path.snap : True # When True, rectilinear axis-aligned paths will be snapped to + # the nearest pixel when certain criteria are met. When False, + # paths will never be snapped. # the default savefig params can be different from the display params # Eg, you may want a higher resolution, or to make the figure @@ -362,12 +365,12 @@ #verbose.fileo : sys.stdout # a log filename, sys.stdout or sys.stderr # Event keys to interact with figures/plots via keyboard. -# Customize these settings according to your needs. -# Leave the field(s) empty if you don't need a key-map. (i.e., fullscreen : '') +# Customize these settings according to your needs. +# Leave the field(s) empty if you don't need a key-map. (i.e., fullscreen : '') -#keymap.fullscreen : f # toggling +#keymap.fullscreen : f # toggling #keymap.home : h, r, home # home or reset mnemonic -#keymap.back : left, c, backspace # forward / backward keys to enable +#keymap.back : left, c, backspace # forward / backward keys to enable #keymap.forward : right, v # left handed quick navigation #keymap.pan : p # pan mnemonic #keymap.zoom : o # zoom mnemonic This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |