8000 MEP26 · matplotlib/matplotlib Wiki · GitHub
[go: up one dir, main page]

Skip to content
JamesRamm edited this page Jul 16, 2014 · 7 revisions

.. contents:: Table of Contents

.. author:: James Ramm

.. date:: August 3, 2012

This MEP template is a guideline of the sections that a MEP should contain. Extra sections may be added if appropriate, and unnecessary sections may be noted as such.

Status

Proposed

Branches and Pull requests

All development branches containing work on this MEP should be linked to from here.

All pull requests submitted relating to this MEP should be linked to from here. (A MEP does not need to be implemented in a single pull request if it makes sense to implement it in discrete phases).

Abstract

This MEP proposes a new stylesheet implementation to allow more comprehensive and dynamic styling of artists.

The current version of matplotlib (1.4.0) allows stylesheets based on the rcParams syntax to be applied before creation of a plot. The methodology below proposes a new syntax, based on CSS, which would allow styling of individual artists and properties, which can be applied dynamically to existing objects.

This is related to (and makes steps toward) the overall goal of moving to a DOM/tree-like architecture.

Detailed description

Currently, the look and appearance of existing artist objects (figure, axes, Line2D etc...) can only be updated via set_ and get_ methods on the artist object, which is quite laborious, especially if no reference to the artist(s) has been stored. The new style sheets introduced in 1.4 allow styling before a plot is created, but do not offer any means to dynamically update plots or distinguish between artists of the same type (i.e. to specifiy the line color and line style separately for differing Line2D objects).

The new methodology would require development of a number of steps:

  • A new stylesheet syntax (likely based on CSS) to allow selection of artists by type, class, id etc...
  • A mechanism by which to parse a stylesheet into a tree
  • A mechanism by which to translate the parse-tree into something which can be used to update the properties of relevant artists. Ideally this would implement a method by which to traverse the artists in a tree-like structure.
  • A mechanism by which to generate a stylesheet from existing artist properties. This would be useful to allow a user to export a stylesheet from an existing figure (where the appearance may have been set using the matplotlib API)...

Implementation

For initial development, I suggest developing a syntax based on a much (much much) simplified version of CSS. I am in favour of dubbing this Artist Style Sheets 👍 :

Syntax

A CSS stylesheet consists of a series of rules in hierarchical order (rules are applied from top to bottom). Each rule follows the syntax:

selector {attribute: value;}

Selectors

Selectors define the object to which the attribute updates should be applied. As a starting point, I propose just 2 selectors to use in initial development:

Artist Type Selector

Select an artist by it's type. E.g Line2D or Text:

Line2D {attribute: value}
GID selector

Select an artist by its gid:

Line2D#myGID {attribute: value}
Property Class selector

select an artist property which itself is an artist (e.g. the ylabel property of axes):

Axes.ylabel {attribute: value}

In this case, the property is referred to by the property attribute, rather than the artist type (which in this case would be Text).

The above selectors roughly correspond to their CSS counterparts (http://www.w3.org/TR/CSS21/selector.html)

Attributes and values

Attributes are any valid (settable) property for the artist in question, with the exception of property classes (those properties which are themselves artists with settable properties). Values are any valid value for the property (Usually a string, number, array or list)

Parsing

Parsing would consist of breaking the stylesheet into tokens (the python cookbook gives a nice tokenizing recipe on page 66), applying the syntax rules and constructing a Tree. This requires defining the grammar of the stylesheet (again, we can borrow from CSS) and writing a parser. Happily, there is a recipe for this in the python cookbook aswell.

Visitor pattern for matplotlib figure

In order to apply the stylesheet rules to the relevant artists, we need to 'visit' each artist in a figure and apply the relevant rule. Here is a visitor class (again, thanks to python cookbook), where each node would be an artist in the figure. A visit_ method would need to be implemented for each mpl artist, to handle the different properties for each.

class Visitor:
    def visit(self, node):
       name = 'visit_' + type(node).__name__
       meth = getattr(self, name, None)
       if meth is None:
          raise NotImplementedError
       return meth(node)

An evaluator class would then take the stylesheet rules and implement the visitor on each one of them.

Backward compatibility

This section describes the ways in which the MEP breaks backward incompatibility.

Alternatives

If there were any alternative solutions to solving the same problem, they should be discussed here, along with a justification for the chosen approach.

Clone this wiki locally
0