[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