Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
JamesRamm edited this pageAug 8, 2014 ·7 revisions

.. contents:: Table of Contents

.. author:: James Ramm

.. date:: July 16, 2014

Status

Proposed

Branches and Pull requests

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 viaset_ andget_ 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 theline color andline style separately for differingLine2D objects).

The initial development should concentrate on allowing styling of artist primitives (thoseartists that do not contain otherartists), and further development could expand the CSS syntax rules and parser to allow more complex styling. See the appendix for a list of primitives.

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

It will be easiest to allow a '3rd party' to modify/set the style of an artist if the 'style' is created as a separate class and store against the artist as a property.TheGraphicsContextclass already provides a the basis of aStyleclass and an artistsdrawmethod can be refactored to use theStyleclass rather than setting up it's ownGraphicsContext and transferring it's style-related properties to it.A minimal example of how this could be implemented is shown here:https://github.com/JamesRamm/mpl_experiment

IMO, this will also make the API and code base much neater as individual get/set methods for artist style properties are now redundant...Indirectly related would be a general drive to replace get/set methods with properties. Implementing the style class with properties would be a big stride toward this...

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 👍 :

BNF Grammar

I propose a very simple syntax to implement initially (like a proof of concept), which can be expanded upon in the future. The BNF form of the syntax is given below and then explained:

RuleSet ::= SelectorSequence "{"Declaration"}"SelectorSequence :: = Selector {"," Selector}Declaration ::= propName":" propValue";"Selector ::= ArtistIdent{"#"Ident}propName ::= IdentpropValue ::= Ident | Number | Colour | "None"

ArtistIdent,Ident,Number andColour are tokens (the basic building blocks of the expression) which are defined by regular expressions.

Syntax

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

selector {attribute: value;}

Each rule can have any number ofattribute:value pairs, and a stylesheet can have any number of rules.

The initial syntax is designed only forartist primitives. It does not address the question of how to set properties oncontainer types (whose properties may themselves beartists with settable properties), however, a future solution to this could simply be nestedRuleSets

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 anartist by it's type. E.gLine2D orText:

Line2D {attribute: value}

The regex for matching the artist type selector (ArtistIdent in the BNF grammar) would be:

ArtistIdent = r'(?P<ArtistIdent>\bLine2D\b|\bText\b|\bAxesImage\b|\bFigureImage\b|\bPatch\b)'
GID selector

Select anartist by itsgid:

Line2D#myGID {attribute: value}

Agid can be any string, so the regex could be as follows:

Ident = r'(?P<Ident>[a-zA-Z_][a-zA-Z_0-9]*)'

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 theartist in question.Values are any valid value for the property (Usually a string, or number).

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 aTree. 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 andapply the relevant rule.Here is a visitor class (again, thanks to python cookbook), where eachnode would be an artist in the figure. Avisit_ 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)

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

Backward compatibility

Implementing a seperateStyleclass would break backward compatibility as many get/set methods on an artist would become redundant.While it would be possible to alter these methods to hook into theStyleclass (stored as a property against the artist), I would be in favour of simply removing them to both neaten/simplify the codebase and to provide a simple, uncluttered API...

Alternatives

No alternatives, but some of the ground covered here overlaps with MEP25, which may assist in this development

Appendix

Matplotlib primitives

This will form the initial selectors which stylesheets can use.

  • Line2D
  • Text
  • AxesImage
  • FigureImage
  • Patch
Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp