From 753c9a2fb137e9e9f8cfae17025739a89c4a2522 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Tue, 28 Feb 2012 09:47:05 +0000 Subject: [PATCH 1/9] Single commit of necessary transform changes. --- lib/matplotlib/transforms.py | 59 ++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index a1f6cb9de489..5fc8d4d06237 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -99,30 +99,32 @@ def __copy__(self, *args): def invalidate(self): """ - Invalidate this :class:`TransformNode` and all of its - ancestors. Should be called any time the transform changes. + Invalidate this :class:`TransformNode` and triggers an + invalidation of its ancestors. Should be called any + time the transform changes. """ - # If we are an affine transform being changed, we can set the - # flag to INVALID_AFFINE_ONLY - value = (self.is_affine) and self.INVALID_AFFINE or self.INVALID + value = self.INVALID + if self.is_affine: + value = self.INVALID_AFFINE + return self._invalidate_internal(value, invalidating_node=self) - # Shortcut: If self is already invalid, that means its parents - # are as well, so we don't need to do anything. - if self._invalid == value: - return + def _invalidate_internal(self, value, invalidating_node): + """ + Called by :meth:`invalidate` and subsequently ascends the transform + stack calling each TransformNode's _invalidate_internal method. + """ + # determine if this call will be an extension to the invalidation status + # if not, then a shortcut means that we needn't invoke an invalidation + # up the transform stack + # XXX This makes the invalidation sticky, once a transform has been invalidated as NON_AFFINE + # too, then it is always NON_AFFINE invalid, even when triggered with a AFFINE_ONLY invalidation. + status_changed = self._invalid < value - if not len(self._parents): + if self.pass_through or status_changed: self._invalid = value - return - # Invalidate all ancestors of self using pseudo-recursion. - stack = [self] - while len(stack): - root = stack.pop() - # Stop at subtrees that have already been invalidated - if root._invalid != value or root.pass_through: - root._invalid = self.INVALID - stack.extend(root._parents.iterkeys()) + for parent in self._parents.iterkeys(): + parent._invalidate_internal(value=value, invalidating_node=self) def set_children(self, *children): """ @@ -1251,7 +1253,6 @@ class TransformWrapper(Transform): of the same dimensions. """ pass_through = True - is_affine = False def __init__(self, child): """ @@ -1286,6 +1287,7 @@ def _set(self, child): self.transform_path_non_affine = child.transform_path_non_affine self.get_affine = child.get_affine self.inverted = child.inverted + self.is_affine = child.is_affine def set(self, child): """ @@ -1890,6 +1892,8 @@ def __init__(self, a, b): self._b = b self.set_children(a, b) + is_affine = property(lambda self: self._a.is_affine and self._b.is_affine) + def frozen(self): self._invalid = 0 frozen = composite_transform_factory(self._a.frozen(), self._b.frozen()) @@ -1898,6 +1902,20 @@ def frozen(self): return frozen frozen.__doc__ = Transform.frozen.__doc__ + def _invalidate_internal(self, value, invalidating_node): + # In some cases for a composite transform, an invalidating call to AFFINE_ONLY needs + # to be extended to invalidate the NON_AFFINE part too. These cases are when the right + # hand transform is non-affine and either: + # (a) the left hand transform is non affine + # (b) it is the left hand node which has triggered the invalidation + if value == Transform.INVALID_AFFINE \ + and not self._b.is_affine \ + and (not self._a.is_affine or invalidating_node is self._a): # note use of is will break when using TransformWrapper + + value = Transform.INVALID + + Transform._invalidate_internal(self, value=value, invalidating_node=invalidating_node) + def _get_is_affine(self): return self._a.is_affine and self._b.is_affine is_affine = property(_get_is_affine) @@ -2229,6 +2247,7 @@ def __init__(self, path, transform): self._transformed_points = None def _revalidate(self): + # only recompute if the invalidation includes the non_affine part of the transform if ((self._invalid & self.INVALID_NON_AFFINE == self.INVALID_NON_AFFINE) or self._transformed_path is None): self._transformed_path = \ From c4ceace2019f7a23f586c3973ed40806d7fa8742 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Tue, 6 Mar 2012 17:59:26 +0000 Subject: [PATCH 2/9] Fixed is_affine inheritance & added scatter test which highlighted the problem. --- .../test_plot_types/scatter.pdf | Bin 0 -> 6775 bytes .../test_plot_types/scatter.png | Bin 0 -> 13662 bytes .../test_plot_types/scatter.svg | 646 ++++++++++++++++++ lib/matplotlib/tests/test_plot_types.py | 15 + lib/matplotlib/tests/test_transforms.py | 45 ++ lib/matplotlib/transforms.py | 10 +- 6 files changed, 713 insertions(+), 3 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_plot_types/scatter.pdf create mode 100644 lib/matplotlib/tests/baseline_images/test_plot_types/scatter.png create mode 100644 lib/matplotlib/tests/baseline_images/test_plot_types/scatter.svg create mode 100644 lib/matplotlib/tests/test_plot_types.py diff --git a/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.pdf b/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6f17d724276d95612eba1ddab287b784034f4502 GIT binary patch literal 6775 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 literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.svg b/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.svg new file mode 100644 index 000000000000..ceced12e0db1 --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.svg @@ -0,0 +1,646 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/matplotlib/tests/test_plot_types.py b/lib/matplotlib/tests/test_plot_types.py new file mode 100644 index 000000000000..ebd990a2b46d --- /dev/null +++ b/lib/matplotlib/tests/test_plot_types.py @@ -0,0 +1,15 @@ +import numpy as np +from numpy import ma +import matplotlib +from matplotlib.testing.decorators import image_comparison, knownfailureif +import matplotlib.pyplot as plt + + +@image_comparison(baseline_images=['scatter']) +def test_scatter_plot(): + ax = plt.axes() + ax.scatter([3, 4, 2, 6], [2, 5, 2, 3], c=['r', 'y', 'b', 'lime'], s=[24, 15, 19, 29]) + +if __name__=='__main__': + import nose + nose.runmodule(argv=['-s','--with-doctest'], exit=False) diff --git a/lib/matplotlib/tests/test_transforms.py b/lib/matplotlib/tests/test_transforms.py index 04322ea58c95..25399d5c3258 100644 --- a/lib/matplotlib/tests/test_transforms.py +++ b/lib/matplotlib/tests/test_transforms.py @@ -6,6 +6,51 @@ from matplotlib.scale import LogScale import numpy as np +import matplotlib.transforms as mtrans +import matplotlib.pyplot as plt + + + + +def test_non_affine_caching(): + class AssertingNonAffineTransform(mtrans.Transform): + """ + This transform raises an assertion error when called when it + shouldn't be and self.raise_on_transform is True. + + """ + input_dims = output_dims = 2 + is_affine = False + def __init__(self, *args, **kwargs): + mtrans.Transform.__init__(self, *args, **kwargs) + self.raise_on_transform = False + self.underlying_transform = mtrans.Affine2D().scale(10, 10) + + def transform_path_non_affine(self, path): + if self.raise_on_transform: + assert False, ('Invalidated affine part of transform ' + 'unnecessarily.') + return self.underlying_transform.transform_path(path) + transform_path = transform_path_non_affine + + def transform_non_affine(self, path): + if self.raise_on_transform: + assert False, ('Invalidated affine part of transform ' + 'unnecessarily.') + return self.underlying_transform.transform(path) + transform = transform_non_affine + + my_trans = AssertingNonAffineTransform() + ax = plt.axes() + plt.plot(range(10), transform=my_trans + ax.transData) + plt.draw() + # enable the transform to raise an exception if it's non-affine transform + # method is triggered again. + my_trans.raise_on_transform = True + ax.transAxes.invalidate() + plt.draw() + + def test_Affine2D_from_values(): points = [ [0,0], [10,20], diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index 5fc8d4d06237..1c768ff70286 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -1288,6 +1288,10 @@ def _set(self, child): self.get_affine = child.get_affine self.inverted = child.inverted self.is_affine = child.is_affine + self.get_matrix = child.get_matrix + + def __eq__(self, other): + return self._child == other def set(self, child): """ @@ -2034,11 +2038,11 @@ def composite_transform_factory(a, b): c = a + b """ - if isinstance(a, IdentityTransform): + if a == IdentityTransform(): return b - elif isinstance(b, IdentityTransform): + elif b == IdentityTransform(): return a - elif isinstance(a, AffineBase) and isinstance(b, AffineBase): + elif a.is_affine and b.is_affine: return CompositeAffine2D(a, b) return CompositeGenericTransform(a, b) From bf4dd97b19bfa948db2cd2a17c5bc2ec5b660750 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Tue, 6 Mar 2012 18:27:26 +0000 Subject: [PATCH 3/9] Fixed failing unit test. (in test_axes) --- lib/matplotlib/transforms.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index 1c768ff70286..7bd760905158 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -1119,6 +1119,12 @@ def get_affine(self): """ return IdentityTransform() + def get_matrix(self): + """ + Get the transformation matrix for the affine part of this transform. + """ + return self.get_affine().get_matrix() + def transform_point(self, point): """ A convenience function that returns the transformed copy of a From 4c88a6d43f36c455c36751a40f9b78816b24c013 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Tue, 20 Mar 2012 16:38:59 +0000 Subject: [PATCH 4/9] Moved scatter test into test_axes.py --- .../{test_plot_types => test_axes}/scatter.pdf | Bin .../{test_plot_types => test_axes}/scatter.png | Bin .../{test_plot_types => test_axes}/scatter.svg | 0 lib/matplotlib/tests/test_axes.py | 8 ++++++++ lib/matplotlib/tests/test_plot_types.py | 15 --------------- 5 files changed, 8 insertions(+), 15 deletions(-) rename lib/matplotlib/tests/baseline_images/{test_plot_types => test_axes}/scatter.pdf (100%) rename lib/matplotlib/tests/baseline_images/{test_plot_types => test_axes}/scatter.png (100%) rename lib/matplotlib/tests/baseline_images/{test_plot_types => test_axes}/scatter.svg (100%) delete mode 100644 lib/matplotlib/tests/test_plot_types.py diff --git a/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.pdf b/lib/matplotlib/tests/baseline_images/test_axes/scatter.pdf similarity index 100% rename from lib/matplotlib/tests/baseline_images/test_plot_types/scatter.pdf rename to lib/matplotlib/tests/baseline_images/test_axes/scatter.pdf diff --git a/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.png b/lib/matplotlib/tests/baseline_images/test_axes/scatter.png similarity index 100% rename from lib/matplotlib/tests/baseline_images/test_plot_types/scatter.png rename to lib/matplotlib/tests/baseline_images/test_axes/scatter.png diff --git a/lib/matplotlib/tests/baseline_images/test_plot_types/scatter.svg b/lib/matplotlib/tests/baseline_images/test_axes/scatter.svg similarity index 100% rename from lib/matplotlib/tests/baseline_images/test_plot_types/scatter.svg rename to lib/matplotlib/tests/baseline_images/test_axes/scatter.svg diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 92385e1f1e02..949da92a126e 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -650,6 +650,7 @@ def test_marker_edges(): ax.set_xticks([]) ax.set_yticks([]) +<<<<<<< HEAD @image_comparison(baseline_images=['hist_log']) def test_hist_log(): data0 = np.linspace(0,1,200)**3 @@ -697,6 +698,13 @@ def test_hist2d_transpose(): ax = fig.add_subplot(111) ax.hist2d(x,y,bins=10) + +@image_comparison(baseline_images=['scatter']) +def test_scatter_plot(): + ax = plt.axes() + ax.scatter([3, 4, 2, 6], [2, 5, 2, 3], c=['r', 'y', 'b', 'lime'], s=[24, 15, 19, 29]) + + if __name__=='__main__': import nose nose.runmodule(argv=['-s','--with-doctest'], exit=False) diff --git a/lib/matplotlib/tests/test_plot_types.py b/lib/matplotlib/tests/test_plot_types.py deleted file mode 100644 index ebd990a2b46d..000000000000 --- a/lib/matplotlib/tests/test_plot_types.py +++ /dev/null @@ -1,15 +0,0 @@ -import numpy as np -from numpy import ma -import matplotlib -from matplotlib.testing.decorators import image_comparison, knownfailureif -import matplotlib.pyplot as plt - - -@image_comparison(baseline_images=['scatter']) -def test_scatter_plot(): - ax = plt.axes() - ax.scatter([3, 4, 2, 6], [2, 5, 2, 3], c=['r', 'y', 'b', 'lime'], s=[24, 15, 19, 29]) - -if __name__=='__main__': - import nose - nose.runmodule(argv=['-s','--with-doctest'], exit=False) From c0884772332c011429a604d0ab0d04ab2f41a02c Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Fri, 20 Apr 2012 15:21:19 +0100 Subject: [PATCH 5/9] Fixed broken handling of WrappedTransform --- lib/matplotlib/transforms.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index 7bd760905158..d465d5af93de 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -1293,11 +1293,11 @@ def _set(self, child): self.transform_path_non_affine = child.transform_path_non_affine self.get_affine = child.get_affine self.inverted = child.inverted - self.is_affine = child.is_affine self.get_matrix = child.get_matrix - def __eq__(self, other): - return self._child == other + # note we do not wrap other properties here since the transform's + # child can be changed with WrappedTransform.set and so checking + # is_affine and other such properties may be dangerous. def set(self, child): """ @@ -2044,9 +2044,13 @@ def composite_transform_factory(a, b): c = a + b """ - if a == IdentityTransform(): + # check to see if any of a or b are IdentityTransforms. Note we + # do not use equality here since we may have wrapped transforms + # which are currently equal to Identity, but since wrapped transforms + # are mutable, they may not always be equal. + if isinstance(a, IdentityTransform): return b - elif b == IdentityTransform(): + elif isinstance(b, IdentityTransform): return a elif a.is_affine and b.is_affine: return CompositeAffine2D(a, b) From 1b1b340d7c11c0e52eb745ee9e6c99efe43851b3 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Fri, 20 Apr 2012 18:01:00 +0100 Subject: [PATCH 6/9] Intermediate commit to request some assistance. --- lib/matplotlib/collections.py | 9 +++++++++ lib/matplotlib/transforms.py | 10 +++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index de1d762fc1d0..7355c8f3a4e3 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -245,6 +245,15 @@ def draw(self, renderer): if self._hatch: gc.set_hatch(self._hatch) + # XXX INVESTIGATE. + print('transOffset: ', transOffset) + print(transOffset.is_affine, transOffset.get_matrix()) + mtx = transOffset.get_matrix() + import matplotlib.transforms as mtransforms + transOffset = mtransforms.Affine2D() + transOffset.set_matrix(mtx) + # XXX end investigate + renderer.draw_path_collection( gc, transform.frozen(), paths, self.get_transforms(), offsets, transOffset, self.get_facecolor(), self.get_edgecolor(), diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index d465d5af93de..a7021e901488 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -46,7 +46,7 @@ import cbook from path import Path -DEBUG = False +DEBUG = True if DEBUG: import warnings @@ -1315,6 +1315,10 @@ def set(self, child): self.invalidate() self._invalid = 0 + def _get_is_affine(self): + return self._child.is_affine + is_affine = property(_get_is_affine) + def _get_is_separable(self): return self._child.is_separable is_separable = property(_get_is_separable) @@ -1443,7 +1447,7 @@ def transform(self, points): warnings.warn( ('A non-numpy array of type %s was passed in for ' + 'transformation. Please correct this.') - % type(values)) + % type(points)) return self._transform(points) transform.__doc__ = AffineBase.transform.__doc__ @@ -2052,7 +2056,7 @@ def composite_transform_factory(a, b): return b elif isinstance(b, IdentityTransform): return a - elif a.is_affine and b.is_affine: + elif isinstance(a, Affine2D) and isinstance(b, Affine2D): return CompositeAffine2D(a, b) return CompositeGenericTransform(a, b) From e9cc98e3ef1b23c359feacca7994de57677c7c0a Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Tue, 1 May 2012 12:38:26 +0100 Subject: [PATCH 7/9] Fixed __array__ releated bug that I introduced. --- lib/matplotlib/collections.py | 12 ----------- lib/matplotlib/transforms.py | 40 ++++++++++++++++++++--------------- src/agg_py_transforms.cpp | 33 +++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 33 deletions(-) diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 7355c8f3a4e3..187469f9fc66 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -242,18 +242,6 @@ def draw(self, renderer): self._set_gc_clip(gc) gc.set_snap(self.get_snap()) - if self._hatch: - gc.set_hatch(self._hatch) - - # XXX INVESTIGATE. - print('transOffset: ', transOffset) - print(transOffset.is_affine, transOffset.get_matrix()) - mtx = transOffset.get_matrix() - import matplotlib.transforms as mtransforms - transOffset = mtransforms.Affine2D() - transOffset.set_matrix(mtx) - # XXX end investigate - renderer.draw_path_collection( gc, transform.frozen(), paths, self.get_transforms(), offsets, transOffset, self.get_facecolor(), self.get_edgecolor(), diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index a7021e901488..af59c17e9473 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -46,7 +46,7 @@ import cbook from path import Path -DEBUG = True +DEBUG = False if DEBUG: import warnings @@ -113,11 +113,14 @@ def _invalidate_internal(self, value, invalidating_node): Called by :meth:`invalidate` and subsequently ascends the transform stack calling each TransformNode's _invalidate_internal method. """ - # determine if this call will be an extension to the invalidation status - # if not, then a shortcut means that we needn't invoke an invalidation - # up the transform stack - # XXX This makes the invalidation sticky, once a transform has been invalidated as NON_AFFINE - # too, then it is always NON_AFFINE invalid, even when triggered with a AFFINE_ONLY invalidation. + # determine if this call will be an extension to the invalidation + # status if not, then a shortcut means that we needn't invoke an + # invalidation up the transform stack + # N.B This makes the invalidation sticky, once a transform has been + # invalidated as NON_AFFINE too, then it is always NON_AFFINE invalid, + # even when triggered with a AFFINE_ONLY invalidation. This will not + # be experienced, as in most cases the invalidation will by AFFINE_ONLY + # anyway. status_changed = self._invalid < value if self.pass_through or status_changed: @@ -1067,9 +1070,13 @@ def __radd__(self, other): def __array__(self, *args, **kwargs): """ - Used by C/C++ -based backends to get at the array matrix data. + Array interface to get at this Transform's matrix. """ - raise NotImplementedError + # note, this method is also used by C/C++ -based backends + if self.is_affine: + return self.get_matrix() + else: + raise ValueError('Cannot convert this transform to an array.') def transform(self, values): """ @@ -1340,6 +1347,7 @@ def __init__(self): self._inverted = None def __array__(self, *args, **kwargs): + # optimises the access of the transform matrix vs the superclass return self.get_matrix() @staticmethod @@ -1402,9 +1410,6 @@ def _get_is_separable(self): return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0 is_separable = property(_get_is_separable) - def __array__(self, *args, **kwargs): - return self.get_matrix() - def to_values(self): """ Return the values of the matrix as a sequence (a,b,c,d,e,f) @@ -1924,11 +1929,12 @@ def _invalidate_internal(self, value, invalidating_node): # (b) it is the left hand node which has triggered the invalidation if value == Transform.INVALID_AFFINE \ and not self._b.is_affine \ - and (not self._a.is_affine or invalidating_node is self._a): # note use of is will break when using TransformWrapper + and (not self._a.is_affine or invalidating_node is self._a): value = Transform.INVALID - Transform._invalidate_internal(self, value=value, invalidating_node=invalidating_node) + Transform._invalidate_internal(self, value=value, + invalidating_node=invalidating_node) def _get_is_affine(self): return self._a.is_affine and self._b.is_affine @@ -2048,10 +2054,10 @@ def composite_transform_factory(a, b): c = a + b """ - # check to see if any of a or b are IdentityTransforms. Note we - # do not use equality here since we may have wrapped transforms - # which are currently equal to Identity, but since wrapped transforms - # are mutable, they may not always be equal. + # check to see if any of a or b are IdentityTransforms. We use + # isinstance here to guarantee that the transforms will *always* + # be IdentityTransforms. Since TransformWrappers are mutable, + # use of equality here would be wrong. if isinstance(a, IdentityTransform): return b elif isinstance(b, IdentityTransform): diff --git a/src/agg_py_transforms.cpp b/src/agg_py_transforms.cpp index 457d5e7f602c..739512605b99 100644 --- a/src/agg_py_transforms.cpp +++ b/src/agg_py_transforms.cpp @@ -9,20 +9,45 @@ #include "agg_trans_affine.h" /** A helper function to convert from a Numpy affine transformation matrix - * to an agg::trans_affine. + * to an agg::trans_affine. If errors = false then an Identity transform is returned. */ agg::trans_affine py_to_agg_transformation_matrix(PyObject* obj, bool errors = true) { PyArrayObject* matrix = NULL; + /** If None either raise a TypeError or return an agg identity transform. */ + if (obj == Py_None) + { + if (errors) + { + throw Py::TypeError("Cannot convert None to an affine transform."); + } + + return agg::trans_affine(); + } + + /** Try turning the object into an affine transform matrix. */ try { - if (obj == Py_None) - throw std::exception(); matrix = (PyArrayObject*) PyArray_FromObject(obj, PyArray_DOUBLE, 2, 2); if (!matrix) throw std::exception(); + } + catch (...) + { + Py_XDECREF(matrix); + if (errors) + { + throw Py::TypeError("Unable to get an affine transform matrix from the given object."); + } + + return agg::trans_affine(); + } + + /** Try turning the matrix into an agg transform. */ + try + { if (PyArray_NDIM(matrix) == 2 || PyArray_DIM(matrix, 0) == 3 || PyArray_DIM(matrix, 1) == 3) { size_t stride0 = PyArray_STRIDE(matrix, 0); @@ -54,7 +79,7 @@ py_to_agg_transformation_matrix(PyObject* obj, bool errors = true) if (errors) { Py_XDECREF(matrix); - throw Py::TypeError("Invalid affine transformation matrix"); + throw Py::TypeError("Invalid affine transformation matrix."); } } From c898bdf8d9a989947a307ba61c7eddf2fc8dc709 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Tue, 1 May 2012 13:23:35 +0100 Subject: [PATCH 8/9] Improved comments. --- lib/matplotlib/transforms.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index af59c17e9473..5170cb13c8dc 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -114,13 +114,15 @@ def _invalidate_internal(self, value, invalidating_node): stack calling each TransformNode's _invalidate_internal method. """ # determine if this call will be an extension to the invalidation - # status if not, then a shortcut means that we needn't invoke an - # invalidation up the transform stack + # status. If not, then a shortcut means that we needn't invoke an + # invalidation up the transform stack as it will already have been + # invalidated. + # N.B This makes the invalidation sticky, once a transform has been - # invalidated as NON_AFFINE too, then it is always NON_AFFINE invalid, - # even when triggered with a AFFINE_ONLY invalidation. This will not - # be experienced, as in most cases the invalidation will by AFFINE_ONLY - # anyway. + # invalidated as NON_AFFINE, then it will always be invalidated as + # NON_AFFINE even when triggered with a AFFINE_ONLY invalidation. + # In most cases this is not a problem (i.e. for interactive panning and + # zooming) and the only side effect will be on performance. status_changed = self._invalid < value if self.pass_through or status_changed: From a81545c216b1900a01b0394b1e75ffe1cbe0828b Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 7 Jun 2012 15:01:57 +0100 Subject: [PATCH 9/9] Now working with rebased master. --- lib/matplotlib/backends/backend_svg.py | 6 +++--- lib/matplotlib/collections.py | 3 +++ .../baseline_images/test_axes/scatter.png | Bin 13662 -> 7047 bytes lib/matplotlib/tests/test_axes.py | 1 - lib/matplotlib/tests/test_figure.py | 9 +++++---- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/matplotlib/backends/backend_svg.py b/lib/matplotlib/backends/backend_svg.py index 5341063f5357..59ba7b6ff198 100644 --- a/lib/matplotlib/backends/backend_svg.py +++ b/lib/matplotlib/backends/backend_svg.py @@ -657,9 +657,9 @@ def draw_gouraud_triangle(self, gc, points, colors, trans): writer.start(u'defs') for i in range(3): - x1, y1 = points[i] - x2, y2 = points[(i + 1) % 3] - x3, y3 = points[(i + 2) % 3] + x1, y1 = tpoints[i] + x2, y2 = tpoints[(i + 1) % 3] + x3, y3 = tpoints[(i + 2) % 3] c = colors[i][:] if x2 == x3: diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 187469f9fc66..de1d762fc1d0 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -242,6 +242,9 @@ def draw(self, renderer): self._set_gc_clip(gc) gc.set_snap(self.get_snap()) + if self._hatch: + gc.set_hatch(self._hatch) + renderer.draw_path_collection( gc, transform.frozen(), paths, self.get_transforms(), offsets, transOffset, self.get_facecolor(), self.get_edgecolor(), diff --git a/lib/matplotlib/tests/baseline_images/test_axes/scatter.png b/lib/matplotlib/tests/baseline_images/test_axes/scatter.png index b73fefea322c090e55f8703f7c675f8f91daf38f..876de2fa613e98212fb0024a4c0cd0f2cb381729 100644 GIT binary patch literal 7047 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 diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 949da92a126e..15622bd467c8 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -650,7 +650,6 @@ def test_marker_edges(): ax.set_xticks([]) ax.set_yticks([]) -<<<<<<< HEAD @image_comparison(baseline_images=['hist_log']) def test_hist_log(): data0 = np.linspace(0,1,200)**3 diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index e042ac73cac1..ed64d40f276a 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -10,17 +10,17 @@ def test_figure_label(): plt.close('all') plt.figure('today') plt.figure(3) - plt.figure('tomorow') + plt.figure('tomorrow') plt.figure() plt.figure(0) plt.figure(1) plt.figure(3) assert_equal(plt.get_fignums(), [0, 1, 3, 4, 5]) - assert_equal(plt.get_figlabels(), ['', 'today', '', 'tomorow', '']) + assert_equal(plt.get_figlabels(), ['', 'today', '', 'tomorrow', '']) plt.close(10) plt.close() plt.close(5) - plt.close('tomorow') + plt.close('tomorrow') assert_equal(plt.get_fignums(), [0, 1]) assert_equal(plt.get_figlabels(), ['', 'today']) @@ -33,7 +33,8 @@ def test_figure(): ax.set_title(fig.get_label()) ax.plot(range(5)) # plot red line in a different figure. - plt.figure('tomorow') + plt.figure('tomorrow') plt.plot([0, 1], [1,0], 'r') # Return to the original; make sure the red line is not there. plt.figure('today') + plt.close('tomorrow')