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

Appearance settings

Commit f4b589b

Browse filesBrowse files
committed
DOC : move MEP26
1 parent a295d54 commit f4b589b
Copy full SHA for f4b589b

File tree

Expand file treeCollapse file tree

2 files changed

+233
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+233
-0
lines changed

‎doc/devel/MEP/MEP26.rst

Copy file name to clipboard
+232Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
=======================
2+
MEP26: Artist styling
3+
=======================
4+
5+
.. contents::
6+
:local:
7+
8+
9+
Status
10+
======
11+
12+
**Proposed**
13+
14+
Branches and Pull requests
15+
==========================
16+
17+
Abstract
18+
========
19+
20+
This MEP proposes a new stylesheet implementation to allow more
21+
comprehensive and dynamic styling of artists.
22+
23+
The current version of matplotlib (1.4.0) allows stylesheets based on
24+
the rcParams syntax to be applied before creation of a plot. The
25+
methodology below proposes a new syntax, based on CSS, which would
26+
allow styling of individual artists and properties, which can be
27+
applied dynamically to existing objects.
28+
29+
This is related to (and makes steps toward) the overall goal of moving
30+
to a DOM/tree-like architecture.
31+
32+
33+
Detailed description
34+
====================
35+
36+
Currently, the look and appearance of existing artist objects (figure,
37+
axes, Line2D etc...) can only be updated via `set_` and `get_` methods
38+
on the artist object, which is quite laborious, especially if no
39+
reference to the artist(s) has been stored. The new style sheets
40+
introduced in 1.4 allow styling before a plot is created, but do not
41+
offer any means to dynamically update plots or distinguish between
42+
artists of the same type (i.e. to specifiy the `line color` and `line
43+
style` separately for differing `Line2D` objects).
44+
45+
The initial development should concentrate on allowing styling of
46+
artist primitives (those `artists` that do not contain other
47+
`artists`), and further development could expand the CSS syntax rules
48+
and parser to allow more complex styling. See the appendix for a list
49+
of primitives.
50+
51+
The new methodology would require development of a number of steps:
52+
53+
- A new stylesheet syntax (likely based on CSS) to allow selection of
54+
artists by type, class, id etc...
55+
- A mechanism by which to parse a stylesheet into a tree
56+
- A mechanism by which to translate the parse-tree into something
57+
which can be used to update the properties of relevant
58+
artists. Ideally this would implement a method by which to traverse
59+
the artists in a tree-like structure.
60+
- A mechanism by which to generate a stylesheet from existing artist
61+
properties. This would be useful to allow a user to export a
62+
stylesheet from an existing figure (where the appearance may have
63+
been set using the matplotlib API)...
64+
65+
Implementation
66+
==============
67+
68+
It will be easiest to allow a '3rd party' to modify/set the style of
69+
an artist if the 'style' is created as a separate class and store
70+
against the artist as a property. The `GraphicsContext` class already
71+
provides a the basis of a `Style` class and an artists `draw` method can
72+
be refactored to use the `Style` class rather than setting up it's own
73+
`GraphicsContext` and transferring it's style-related properties to
74+
it. A minimal example of how this could be implemented is shown here:
75+
https://github.com/JamesRamm/mpl_experiment
76+
77+
IMO, this will also make the API and code base much neater as
78+
individual get/set methods for artist style properties are now
79+
redundant... Indirectly related would be a general drive to replace
80+
get/set methods with properties. Implementing the style class with
81+
properties would be a big stride toward this...
82+
83+
For initial development, I suggest developing a syntax based on a much
84+
(much much) simplified version of CSS. I am in favour of dubbing this
85+
Artist Style Sheets :+1: :
86+
87+
BNF Grammar
88+
-----------
89+
90+
I propose a very simple syntax to implement initially (like a proof of
91+
concept), which can be expanded upon in the future. The BNF form of
92+
the syntax is given below and then explained ::
93+
94+
RuleSet ::= SelectorSequence "{"Declaration"}"
95+
96+
SelectorSequence :: = Selector {"," Selector}
97+
98+
Declaration ::= propName":" propValue";"
99+
100+
Selector ::= ArtistIdent{"#"Ident}
101+
102+
propName ::= Ident
103+
104+
propValue ::= Ident | Number | Colour | "None"
105+
106+
`ArtistIdent`, `Ident`, `Number` and `Colour` are tokens (the basic
107+
building blocks of the expression) which are defined by regular
108+
expressions.
109+
110+
Syntax
111+
------
112+
113+
A CSS stylesheet consists of a series of **rule sets** in hierarchical
114+
order (rules are applied from top to bottom). Each rule follows the
115+
syntax ::
116+
117+
selector {attribute: value;}
118+
119+
Each rule can have any number of `attribute`:`value` pairs, and a
120+
stylesheet can have any number of rules.
121+
122+
The initial syntax is designed only for `artist` primitives. It does
123+
not address the question of how to set properties on `container` types
124+
(whose properties may themselves be `artists` with settable
125+
properties), however, a future solution to this could simply be nested
126+
`RuleSet`s
127+
128+
Selectors
129+
~~~~~~~~~
130+
131+
132+
Selectors define the object to which the attribute updates should be
133+
applied. As a starting point, I propose just 2 selectors to use in
134+
initial development:
135+
136+
137+
138+
Artist Type Selector
139+
140+
141+
Select an `artist` by it's type. E.g `Line2D` or `Text`::
142+
143+
Line2D {attribute: value}
144+
145+
The regex for matching the artist type selector (`ArtistIdent` in the BNF grammar) would be::
146+
147+
ArtistIdent = r'(?P<ArtistIdent>\bLine2D\b|\bText\b|\bAxesImage\b|\bFigureImage\b|\bPatch\b)'
148+
149+
GID selector
150+
~~~~~~~~~~~~
151+
152+
Select an `artist` by its `gid`::
153+
154+
Line2D#myGID {attribute: value}
155+
156+
A `gid` can be any string, so the regex could be as follows::
157+
158+
Ident = r'(?P<Ident>[a-zA-Z_][a-zA-Z_0-9]*)'
159+
160+
161+
The above selectors roughly correspond to their CSS counterparts
162+
(http://www.w3.org/TR/CSS21/selector.html)
163+
164+
Attributes and values
165+
~~~~~~~~~~~~~~~~~~~~~
166+
167+
- `Attributes` are any valid (settable) property for the `artist` in question.
168+
- `Values` are any valid value for the property (Usually a string, or number).
169+
170+
Parsing
171+
-------
172+
173+
Parsing would consist of breaking the stylesheet into tokens (the
174+
python cookbook gives a nice tokenizing recipe on page 66), applying
175+
the syntax rules and constructing a `Tree`. This requires defining the
176+
grammar of the stylesheet (again, we can borrow from CSS) and writing
177+
a parser. Happily, there is a recipe for this in the python cookbook
178+
aswell.
179+
180+
181+
Visitor pattern for matplotlib figure
182+
-------------------------------------
183+
184+
In order to apply the stylesheet rules to the relevant artists, we
185+
need to 'visit' each artist in a figure and apply the relevant rule.
186+
Here is a visitor class (again, thanks to python cookbook), where each
187+
`node` would be an artist in the figure. A `visit_` method would need
188+
to be implemented for each mpl artist, to handle the different
189+
properties for each ::
190+
191+
class Visitor:
192+
def visit(self, node):
193+
name = 'visit_' + type(node).__name__
194+
meth = getattr(self, name, None)
195+
if meth is None:
196+
raise NotImplementedError
197+
return meth(node)
198+
199+
An `evaluator` class would then take the stylesheet rules and
200+
implement the visitor on each one of them.
201+
202+
203+
204+
Backward compatibility
205+
======================
206+
207+
Implementing a separate `Style` class would break backward
208+
compatibility as many get/set methods on an artist would become
209+
redundant. While it would be possible to alter these methods to hook
210+
into the `Style` class (stored as a property against the artist), I
211+
would be in favor of simply removing them to both neaten/simplify the
212+
codebase and to provide a simple, uncluttered API...
213+
214+
Alternatives
215+
============
216+
217+
No alternatives, but some of the ground covered here overlaps with
218+
MEP25, which may assist in this development
219+
220+
Appendix
221+
========
222+
223+
Matplotlib primitives
224+
~~~~~~~~~~~~~~~~~~~~~
225+
226+
This will form the initial selectors which stylesheets can use.
227+
228+
* Line2D
229+
* Text
230+
* AxesImage
231+
* FigureImage
232+
* Patch

‎doc/devel/MEP/index.rst

Copy file name to clipboardExpand all lines: doc/devel/MEP/index.rst
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ Matplotlib Enhancement Proposals
2727
MEP23
2828
MEP24
2929
MEP25
30+
MEP26

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.