From 4d97b2c8ecd24d3655e2e2551d75c048838836a1 Mon Sep 17 00:00:00 2001 From: Chris Beaumont Date: Mon, 27 Aug 2012 17:06:00 -0400 Subject: [PATCH 01/12] Checkable pan/zoom buttons for QT NavigationToolbar --- lib/matplotlib/backends/backend_qt4.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/matplotlib/backends/backend_qt4.py b/lib/matplotlib/backends/backend_qt4.py index 45fe444743d8..7224ebce6074 100644 --- a/lib/matplotlib/backends/backend_qt4.py +++ b/lib/matplotlib/backends/backend_qt4.py @@ -497,6 +497,9 @@ def __init__(self, canvas, parent, coordinates=True): """ coordinates: should we show the coordinates on the right? """ self.canvas = canvas self.coordinates = coordinates + self._actions = {} + """A mapping of toolitem method names to their QActions""" + QtGui.QToolBar.__init__( self, parent ) NavigationToolbar2.__init__( self, canvas ) @@ -512,6 +515,9 @@ def _init_toolbar(self): else: a = self.addAction(self._icon(image_file + '.png'), text, getattr(self, callback)) + self._actions[callback] = a + if callback in ['zoom', 'pan']: + a.setCheckable(True) if tooltip_text is not None: a.setToolTip(tooltip_text) @@ -570,6 +576,18 @@ def edit_parameters(self): figureoptions.figure_edit(axes, self) + def _update_buttons_checked(self): + #sync button checkstates to match active mode + self._actions['pan'].setChecked(self._active == 'PAN') + self._actions['zoom'].setChecked(self._active == 'ZOOM') + + def pan(self, *args): + super(NavigationToolbar2QT, self).pan(*args) + self._update_buttons_checked() + + def zoom(self, *args): + super(NavigationToolbar2QT, self).zoom(*args) + self._update_buttons_checked() def dynamic_update( self ): self.canvas.draw() From 70358acc9e08364cd574e086499468f5e758bf57 Mon Sep 17 00:00:00 2001 From: Benjamin Root Date: Sun, 9 Sep 2012 15:41:50 -0400 Subject: [PATCH 02/12] Allow imsave() to handle RGB(A) input arrays Thanks to Jostein Be Floystad for the original patch! --- lib/matplotlib/image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 4719667f3a9a..22df993bc41a 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1243,7 +1243,7 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, If *format* is *None* and *fname* is a string, the output format is deduced from the extension of the filename. *arr*: - A 2D array. + An MxN (luminance), MxNx3 (RGB) or MxNx4 (RGBA) array. Keyword arguments: *vmin*/*vmax*: [ None | scalar ] *vmin* and *vmax* set the color scaling for the image by fixing the @@ -1266,7 +1266,7 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas from matplotlib.figure import Figure - figsize = [x / float(dpi) for x in arr.shape[::-1]] + figsize = [x / float(dpi) for x in (arr.shape[1], arr.shape[0])] fig = Figure(figsize=figsize, dpi=dpi, frameon=False) canvas = FigureCanvas(fig) im = fig.figimage(arr, cmap=cmap, vmin=vmin, vmax=vmax, origin=origin) From 22c4a1913663c227754987914ef02ec760525b53 Mon Sep 17 00:00:00 2001 From: Benjamin Root Date: Sun, 9 Sep 2012 16:31:43 -0400 Subject: [PATCH 03/12] Added a test for imsave --- lib/matplotlib/tests/test_image.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 4556013bc4cb..2445d715f0e1 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -128,6 +128,26 @@ def test_imsave(): assert_array_equal(arr_dpi1, arr_dpi100) +def test_imsave_color_alpha(): + # The goal is to test that imsave will accept arrays with ndim=3 where + # the third dimension is color and alpha without raising any exceptions + from numpy import random + random.seed(1) + data = random.rand(256, 128, 4) + + buff = io.BytesIO() + plt.imsave(buff, data) + + buff.seek(0) + arr_buf = plt.imread(buff) + + assert arr_buf.shape == data.shape + + # Unfortunately, the AGG process "flattens" the RGBA data + # into an equivalent RGB data with no transparency. So we + # Can't directly compare the arrays like we could in some + # other imsave tests. + @image_comparison(baseline_images=['image_clip']) def test_image_clip(): from math import pi From 069526aa84dffad69b28565598aa857676f83f12 Mon Sep 17 00:00:00 2001 From: Damon McDougall Date: Tue, 11 Sep 2012 13:01:29 +0100 Subject: [PATCH 04/12] Enable dynamic updating for the OS X backend --- lib/matplotlib/backends/backend_macosx.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/matplotlib/backends/backend_macosx.py b/lib/matplotlib/backends/backend_macosx.py index 88651a94bcaf..a6df42c262f3 100644 --- a/lib/matplotlib/backends/backend_macosx.py +++ b/lib/matplotlib/backends/backend_macosx.py @@ -487,6 +487,9 @@ def prepare_configure_subplots(self): def set_message(self, message): _macosx.NavigationToolbar2.set_message(self, message.encode('utf-8')) + def dynamic_update(self): + self.canvas.draw_idle() + ######################################################################## # # Now just provide the standard names that backend.__init__ is expecting From ef9471aa51058daffcd8e2c77d9292213b45f686 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 12 Sep 2012 10:34:57 -0400 Subject: [PATCH 05/12] Upping version on master to 1.3.x --- lib/matplotlib/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index a31e6f0e4cf2..5d2aa549f7d1 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -99,7 +99,7 @@ """ from __future__ import print_function -__version__ = '1.2.x' +__version__ = '1.3.x' __version__numpy__ = '1.4' # minimum required numpy version import os, re, shutil, subprocess, sys, warnings From 54cfed6a663e8c8ce6ac618b5fdbcd3bd8ad49d3 Mon Sep 17 00:00:00 2001 From: cgohlke Date: Wed, 12 Sep 2012 09:37:49 -0700 Subject: [PATCH 06/12] Fix mri_demo.py fails with mpl 1.2.0rc1 --- examples/pylab_examples/mri_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/pylab_examples/mri_demo.py b/examples/pylab_examples/mri_demo.py index b10cc7c95fbc..6fd45cf675ec 100755 --- a/examples/pylab_examples/mri_demo.py +++ b/examples/pylab_examples/mri_demo.py @@ -4,7 +4,7 @@ from pylab import * import matplotlib.cbook as cbook # data are 256x256 16 bit integers -dfile = cbook.get_sample_data('s1045.ima') +dfile = cbook.get_sample_data('s1045.ima.gz') im = np.fromstring(dfile.read(), np.uint16).astype(float) im.shape = 256, 256 From 5ee52230fc7a218987962e42edc1ea4250dd3e56 Mon Sep 17 00:00:00 2001 From: cgohlke Date: Wed, 12 Sep 2012 10:52:05 -0700 Subject: [PATCH 07/12] Fix 2to3 and packaging of dateutil --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 25efcd53d549..08261b47616a 100644 --- a/setup.py +++ b/setup.py @@ -214,7 +214,7 @@ def add_pytz(): def add_dateutil(): packages.append('dateutil') packages.append('dateutil.zoneinfo') - package_data['dateutil'] = ['zoneinfo/zoneinfo*.tar.*'] + package_data['dateutil'] = ['zoneinfo/*.tar.gz'] if sys.version_info[0] >= 3: package_dir['dateutil'] = 'lib/dateutil_py3' else: @@ -263,7 +263,7 @@ def add_six(): if sys.version_info[0] >= 3: def should_2to3(file, root): - file = os.path.abspath(file)[len(os.path.abspath(root)):] + file = os.path.abspath(file)[len(os.path.abspath(root))+1:] if ('py3' in file or file.startswith('pytz') or file.startswith('dateutil') or From 84dd08a1c268b56601ff3859b06ba90034b39362 Mon Sep 17 00:00:00 2001 From: cgohlke Date: Wed, 12 Sep 2012 12:21:01 -0700 Subject: [PATCH 08/12] Fix poly_editor.py on Python 3 Polygon does not handle Python 3 zip objects --- examples/event_handling/poly_editor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/event_handling/poly_editor.py b/examples/event_handling/poly_editor.py index 0eeb3608d151..c7d96df66d51 100644 --- a/examples/event_handling/poly_editor.py +++ b/examples/event_handling/poly_editor.py @@ -152,7 +152,7 @@ def motion_notify_callback(self, event): xs = r*np.cos(theta) ys = r*np.sin(theta) - poly = Polygon(zip(xs, ys,), animated=True) + poly = Polygon(list(zip(xs, ys)), animated=True) ax = plt.subplot(111) ax.add_patch(poly) From d1ce64088d3f2f08e23c7a324927c6b847669abf Mon Sep 17 00:00:00 2001 From: cgohlke Date: Wed, 12 Sep 2012 15:40:05 -0700 Subject: [PATCH 09/12] Fix matplotlib.testing.util.MiniExpect.expect hangs on Windows gswin32c expects forward slashes in file paths --- lib/matplotlib/testing/compare.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/testing/compare.py b/lib/matplotlib/testing/compare.py index 7d9e1d2d985a..182cd4d58573 100644 --- a/lib/matplotlib/testing/compare.py +++ b/lib/matplotlib/testing/compare.py @@ -151,7 +151,7 @@ def make_ghostscript_conversion_command(): def do_convert(old, new): process.expect("GS>") - process.sendline("(%s) run" % old) + process.sendline("(%s) run" % old.replace('\\', '/')) with open(new, 'wb') as fd: process.expect(">>showpage, press to continue<<", fd) process.sendline('') From 6f950569b5707ad4db400f6572ea5a2949d67060 Mon Sep 17 00:00:00 2001 From: pwuertz Date: Thu, 13 Sep 2012 01:44:56 +0200 Subject: [PATCH 10/12] backend_pgf: fix parsing of CR+LF newlines --- lib/matplotlib/backends/backend_pgf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/backends/backend_pgf.py b/lib/matplotlib/backends/backend_pgf.py index 876d69ef6ccc..33a1908f6f51 100644 --- a/lib/matplotlib/backends/backend_pgf.py +++ b/lib/matplotlib/backends/backend_pgf.py @@ -340,7 +340,7 @@ def get_width_height_descent(self, text, prop): # parse metrics from the answer string try: - width, height, offset = answer.split("\n")[0].split(",") + width, height, offset = answer.splitlines()[0].split(",") except: msg = "Error processing '%s'\nLaTeX Output:\n%s" % (text, answer) raise ValueError(msg) From 62069bd2c4b1fa10eb9978149e8f1dd83a3188e6 Mon Sep 17 00:00:00 2001 From: cgohlke Date: Sat, 15 Sep 2012 17:44:37 -0700 Subject: [PATCH 11/12] Update six.py to version 1.2 --- lib/six.py | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/lib/six.py b/lib/six.py index 6bee4a99252e..34f737fb3db0 100644 --- a/lib/six.py +++ b/lib/six.py @@ -5,7 +5,7 @@ import types __author__ = "Benjamin Peterson " -__version__ = "1.1.0-mpl" +__version__ = "1.2.0-mpl" # True if we are running on Python 3. @@ -26,19 +26,23 @@ text_type = unicode binary_type = str - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit + if sys.platform == "java": + # Jython always uses 32 bits. MAXSIZE = int((1 << 31) - 1) else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X def _add_doc(func, doc): @@ -113,6 +117,7 @@ class _MovedItems(types.ModuleType): _moved_attributes = [ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("reload_module", "__builtin__", "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), @@ -200,12 +205,19 @@ def remove_move(name): _iteritems = "iteritems" +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + if PY3: def get_unbound_function(unbound): return unbound - - advance_iterator = next + Iterator = object def callable(obj): return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) @@ -213,9 +225,10 @@ def callable(obj): def get_unbound_function(unbound): return unbound.im_func + class Iterator(object): - def advance_iterator(it): - return it.next() + def next(self): + return type(self).__next__(self) callable = callable _add_doc(get_unbound_function, @@ -230,15 +243,15 @@ def advance_iterator(it): def iterkeys(d): """Return an iterator over the keys of a dictionary.""" - return getattr(d, _iterkeys)() + return iter(getattr(d, _iterkeys)()) def itervalues(d): """Return an iterator over the values of a dictionary.""" - return getattr(d, _itervalues)() + return iter(getattr(d, _itervalues)()) def iteritems(d): """Return an iterator over the (key, value) pairs of a dictionary.""" - return getattr(d, _iteritems)() + return iter(getattr(d, _iteritems)()) if PY3: From 3e0c006429bf73baa0dcc0d3f4179bb947763630 Mon Sep 17 00:00:00 2001 From: Damon McDougall Date: Mon, 17 Sep 2012 17:57:47 +0100 Subject: [PATCH 12/12] Fix typo in docstring --- lib/matplotlib/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 5d2aa549f7d1..cff5e7f70dfc 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -1,5 +1,5 @@ """ -This is an object-orient plotting library. +This is an object-oriented plotting library. A procedural interface is provided by the companion pyplot module, which may be imported directly, e.g::