[Python-modules-commits] [python-mplexporter] 33/135: add collection exports

Wolfgang Borgert debacle at moszumanska.debian.org
Tue Sep 23 21:19:01 UTC 2014


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to branch master
in repository python-mplexporter.

commit a1de8794f288672ec62c1bb73116db45ddc2d730
Author: Jake Vanderplas <vanderplas at astro.washington.edu>
Date:   Fri Feb 21 16:50:26 2014 -0800

    add collection exports
---
 mplexporter/exporter.py       |  47 ++++++++++-
 mplexporter/renderers/base.py | 187 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 221 insertions(+), 13 deletions(-)

diff --git a/mplexporter/exporter.py b/mplexporter/exporter.py
index dcb0cf5..153c205 100644
--- a/mplexporter/exporter.py
+++ b/mplexporter/exporter.py
@@ -36,7 +36,7 @@ class Exporter(object):
         self._crawl_fig(fig)
 
     @staticmethod
-    def _process_transform(transform, ax=None, data=None):
+    def _process_transform(transform, ax=None, data=None, return_trans=False):
         """Process the transform and convert data to figure or data coordinates
 
         Parameters
@@ -50,6 +50,8 @@ class Exporter(object):
         data : ndarray (optional)
             The array of data to be transformed.
 
+        return_trans : bool (optional)
+
         Returns
         -------
         code : string
@@ -66,9 +68,16 @@ class Exporter(object):
             code = "figure"
 
         if data is not None:
-            return code, transform.transform(data)
+            if return_trans:
+                return code, transform.transform(data), transform
+            else:
+                return code, transform.transform(data)
+            
         else:
-            return code
+            if return_trans:
+                return code, transform
+            else:
+                return code
 
     def _crawl_fig(self, fig):
         properties = {'figwidth': fig.get_figwidth(),
@@ -94,6 +103,7 @@ class Exporter(object):
             self._extract_lines(ax)
             self._extract_patches(ax)
             self._extract_texts(ax)
+            self._extract_collections(ax)
 
     def _extract_lines(self, ax):
         for line in ax.lines:
@@ -140,3 +150,34 @@ class Exporter(object):
                                     coordinates=coordinates,
                                     pathcodes=pathcodes,
                                     style=linestyle)
+
+    def _extract_collections(self, ax):
+        for collection in ax.collections:
+            (transform, transOffset,
+             offsets, paths) = collection._prepare_points()
+
+            offset_coordinates, offsets = self._process_transform(transOffset,
+                                                                  ax,
+                                                                  offsets)
+            processed_paths = [utils.SVG_path(path) for path in paths]
+            path_coordinates, tr = self._process_transform(transform, ax,
+                                                           return_trans=True)
+            processed_paths = [(tr.transform(path[0]), path[1])
+                               for path in processed_paths]
+            path_transforms = collection.get_transforms()
+            styles = {'linewidth':collection.get_linewidths(),
+                      'facecolor':collection.get_facecolors(),
+                      'edgecolor':collection.get_edgecolors(),
+                      'alpha':collection._alpha}
+
+            offset_dict = {"data": "before",
+                           "screen": "after"}
+            offset_order = offset_dict[collection.get_offset_position()]
+
+            self.renderer.draw_path_collection(processed_paths,
+                                               path_coordinates,
+                                               path_transforms,
+                                               offsets,
+                                               offset_coordinates,
+                                               offset_order,
+                                               styles)
diff --git a/mplexporter/renderers/base.py b/mplexporter/renderers/base.py
index 1c7d637..c37e2db 100644
--- a/mplexporter/renderers/base.py
+++ b/mplexporter/renderers/base.py
@@ -5,7 +5,10 @@ This submodule contains renderer objects which define renderer behavior used
 within the Exporter class.
 """
 import warnings
+import itertools
 from contextlib import contextmanager
+from matplotlib import transforms
+from .. import utils
 
 
 class Renderer(object):
@@ -71,20 +74,184 @@ class Renderer(object):
     def close_axes(self, ax):
         pass
 
-    def draw_markers(self, data, coordinates, style):
-        raise NotImplementedError()
-
-    def draw_text(self, text, position, coordinates, style):
-        raise NotImplementedError()
+    def draw_line(self, data, coordinates, style):
+        """
+        Draw a line. By default, draw the line via the draw_path() command.
+        Some renderers might wish to override this and provide more
+        fine-grained behavior.
 
-    def draw_path(self, data, coordinates, pathcodes, style):
-        raise NotImplementedError()
+        In matplotlib, lines are generally created via the plt.plot() command,
+        though this command also can create marker collections.
 
-    def draw_line(self, data, coordinates, style):
-        # by default, draw the line via the draw_path() command. Some renderers
-        # might wish to override this and provide more fine-grained behavior.
+        Parameters
+        ----------
+        data : array_like
+            A shape (N, 2) array of datapoints.
+        coordinates : string
+            A string code, which should be either 'data' for data coordinates,
+            or 'figure' for figure (pixel) coordinates.
+        style : dictionary
+            a dictionary specifying the appearance of the line.
+        """
         pathcodes = ['M'] + (data.shape[0] - 1) * ['L']
         pathstyle = dict(facecolor='none', **style)
         pathstyle['edgecolor'] = pathstyle.pop('color')
         pathstyle['edgewidth'] = pathstyle.pop('linewidth')
         self.draw_path(data, coordinates, pathcodes, pathstyle)
+
+    def _iter_path_collection(self, paths, path_transforms, offsets, styles):
+        """Build an iterator over the elements of the path collection"""
+        N = max(len(paths), len(offsets))
+
+        if not path_transforms:
+            path_transforms = [np.eye(3)]
+
+        elements = [paths, path_transforms, offsets,
+                    styles['edgecolor'],
+                    styles['linewidth'],
+                    styles['facecolor']]
+        it = itertools
+        return it.islice(it.izip(*it.imap(it.cycle, elements)), N)
+
+    def draw_path_collection(self, paths, path_coordinates, path_transforms,
+                             offsets, offset_coordinates, offset_order,
+                             styles):
+        """
+        Draw a collection of paths. The paths, offsets, and styles are all
+        iterables, and the number of paths is max(len(paths), len(offsets)).
+
+        By default, this is implemented via multiple calls to the draw_path()
+        function. For efficiency, Renderers may choose to customize this
+        implementation.
+
+        Examples of path collections created by matplotlib are scatter plots,
+        histograms, contour plots, and many others.
+
+        Parameters
+        ----------
+        paths : list
+            list of tuples, where each tuple has two elements:
+            (data, pathcodes).  See draw_path() for a description of these.
+        path_coordinates: string
+            the coordinates code for the paths, which should be either
+            'data' for data coordinates, or 'figure' for figure (pixel)
+            coordinates.
+        path_transforms: array_like
+            an array of shape (*, 3, 3), giving a series of 2D Affine
+            transforms for the paths. These encode translations, rotations,
+            and scalings in the standard way.
+        offsets: array_like
+            An array of offsets of shape (N, 2)
+        offset_coordinates : string
+            the coordinates code for the offsets, which should be either
+            'data' for data coordinates, or 'figure' for figure (pixel)
+            coordinates.
+        offset_order : string
+            either "before" or "after". This specifies whether the offset
+            is applied before the path transform, or after.  The matplotlib
+            backend equivalent is "before"->"data", "after"->"screen".
+        styles: dictionary
+            A dictionary in which each value is a list of length N, containing
+            the style(s) for the paths.
+        """
+        if offset_order == "before":
+            raise NotImplementedError("offset before transform")
+
+        for tup in self._iter_path_collection(paths, path_transforms,
+                                              offsets, styles):
+            (path, path_transform, offset, ec, lw, fc) = tup
+            vertices, pathcodes = path
+            path_transform = transforms.Affine2D(path_transform)
+            vertices = path_transform.transform(vertices)
+            # This is a hack:
+            if path_coordinates == "figure":
+                path_coordinates = "points"
+            style={"edgecolor":utils.color_to_hex(ec),
+                   "facecolor":utils.color_to_hex(fc),
+                   "edgewidth":lw,
+                   "dasharray":"10,0", "alpha":styles['alpha']}
+            self.draw_path(vertices, path_coordinates, pathcodes, style,
+                           offset, offset_coordinates)
+
+    def draw_markers(self, data, coordinates, style):
+        """
+        Draw a set of markers. By default, this is done by repeatedly
+        calling draw_path(), but renderers should generally overload
+        this method to provide a more efficient implementation.
+
+        In matplotlib, markers are created using the plt.plot() command.
+
+        Parameters
+        ----------
+        data : array_like
+            A shape (N, 2) array of datapoints.
+        coordinates : string
+            A string code, which should be either 'data' for data coordinates,
+            or 'figure' for figure (pixel) coordinates.
+        style : dictionary
+            a dictionary specifying the appearance of the markers.
+        """
+        vertices, pathcodes = style['markerpath']
+        pathstyle = dict((key, style[key]) for key in ['alpha', 'edgecolor',
+                                                       'facecolor',
+                                                       'edgewidth'])
+        pathstyle['dasharray'] = "10,0"
+        for vertex in data:
+            self.draw_path(vertices, "points", pathcodes, pathstyle,
+                           vertex, coordinates)
+
+    def draw_text(self, text, position, coordinates, style):
+        """
+        Draw text on the image.
+
+        Parameters
+        ----------
+        text : string
+            The text to draw
+        position : tuple
+            The (x, y) position of the text
+        coordinates : string
+            A string code, which should be either 'data' for data coordinates,
+            or 'figure' for figure (pixel) coordinates.
+        style : dictionary
+            a dictionary specifying the appearance of the text.
+        """
+        raise NotImplementedError()
+
+    def draw_path(self, data, coordinates, pathcodes, style,
+                  offset=None, offset_coordinates="data"):
+        """
+        Draw a path.
+
+        In matplotlib, paths are created by filled regions, histograms,
+        contour plots, patches, etc.
+
+        Parameters
+        ----------
+        data : array_like
+            A shape (N, 2) array of datapoints.
+        coordinates : string
+            A string code, which should be either 'data' for data coordinates,
+            'figure' for figure (pixel) coordinates, or "points" for raw
+            point coordinates (useful in conjunction with offsets, below).
+        pathcodes : list
+            A list of single-character SVG pathcodes associated with the data.
+            Path codes are one of ['M', 'm', 'L', 'l', 'Q', 'q', 'T', 't',
+                                   'S', 's', 'C', 'c', 'Z', 'z']
+            See the SVG specification for details.  Note that some path codes
+            consume more than one datapoint (while 'Z' consumes none), so
+            in general, the length of the pathcodes list will not be the same
+            as that of the data array.
+        style : dictionary
+            a dictionary specifying the appearance of the line.
+        offset : list (optional)
+            the (x, y) offset of the path. If not given, no offset will
+            be used.
+        offset_coordinates : string (optional)
+            A string code, which should be either 'data' for data coordinates,
+            or 'figure' for figure (pixel) coordinates.
+        """
+        raise NotImplementedError()
+
+    def draw_image(self, imdata, extent, coordinates, style):
+        raise NotImplementedError()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-mplexporter.git



More information about the Python-modules-commits mailing list