MEP26: Künstler-Styling #
Status #
Abgelehnt
Branches und Pull-Requests #
Zusammenfassung #
Dieses MdEP schlägt eine neue Stylesheet-Implementierung vor, um ein umfassenderes und dynamischeres Styling von Künstlern zu ermöglichen.
Die aktuelle Version von matplotlib (1.4.0) ermöglicht die Anwendung von Stylesheets basierend auf der rcParams-Syntax vor der Erstellung eines Plots. Die nachstehende Methodik schlägt eine neue, auf CSS basierende Syntax vor, die eine Gestaltung individueller Künstler und Eigenschaften ermöglichen würde, die dynamisch auf vorhandene Objekte angewendet werden können.
Dies hängt mit dem übergeordneten Ziel zusammen, zu einer DOM-/baumartigen Architektur überzugehen (und macht Schritte darauf zu).
Detaillierte Beschreibung #
Derzeit kann das Aussehen und Aussehen von bestehenden Künstlerobjekten (Figur, Achsen, Line2D usw.) nur über set_
und get_
Methoden am Künstlerobjekt aktualisiert werden, was ziemlich mühsam ist, insbesondere wenn kein Verweis auf den/die Künstler gespeichert wurde . Die neuen Stylesheets, die in 1.4 eingeführt wurden, ermöglichen das Stylen, bevor ein Plot erstellt wird, bieten jedoch keine Möglichkeit, Plots dynamisch zu aktualisieren oder zwischen Künstlern des gleichen Typs zu unterscheiden (dh und getrennt für unterschiedliche Objekte anzugeben).line color
line
style
Line2D
Die anfängliche Entwicklung sollte sich darauf konzentrieren, das Stylen von Künstlerprimitiven zu ermöglichen (die Artist
s, die keine anderen
Artist
s enthalten), und die weitere Entwicklung könnte die CSS-Syntaxregeln und den Parser erweitern, um ein komplexeres Styling zu ermöglichen. Im Anhang finden Sie eine Liste der Grundelemente.
Die neue Methodik würde die Entwicklung einer Reihe von Schritten erfordern:
Eine neue Stylesheet-Syntax (wahrscheinlich basierend auf CSS), um die Auswahl von Künstlern nach Typ, Klasse, ID usw. zu ermöglichen.
Ein Mechanismus, mit dem ein Stylesheet in einen Baum zerlegt wird
Ein Mechanismus zum Übersetzen des Analysebaums in etwas, das zum Aktualisieren der Eigenschaften relevanter Künstler verwendet werden kann. Idealerweise würde dies ein Verfahren implementieren, mit dem die Künstler in einer baumartigen Struktur durchlaufen werden.
Ein Mechanismus zum Generieren eines Stylesheets aus vorhandenen Künstlereigenschaften. Dies wäre nützlich, um einem Benutzer zu ermöglichen, ein Stylesheet aus einer vorhandenen Figur zu exportieren (wobei das Erscheinungsbild möglicherweise mit der Matplotlib-API festgelegt wurde) ...
Implementierung #
Es ist am einfachsten, einem „Drittanbieter“ zu erlauben, den Stil eines Künstlers zu modifizieren/einzustellen, wenn der „Stil“ als separate Klasse erstellt und als Eigenschaft für den Künstler gespeichert wird. Die GraphicsContextBase
Klasse stellt bereits die Grundlage einer
Style
Klasse bereit, und die Methode eines Künstlers draw
kann so umgestaltet werden, dass sie die Style
Klasse verwendet, anstatt eine eigene einzurichten GraphicsContextBase
und ihre stilbezogenen Eigenschaften darauf zu übertragen. Ein minimales Beispiel, wie dies implementiert werden könnte, wird hier gezeigt: https://github.com/JamesRamm/mpl_experiment
Meiner Meinung nach wird dies auch die API und die Codebasis viel übersichtlicher machen, da einzelne Get/Set-Methoden für Künstlerstileigenschaften jetzt überflüssig sind ... Indirekt damit verbunden wäre ein allgemeines Bestreben, Get/Set-Methoden durch Eigenschaften zu ersetzen. Die Implementierung der Stilklasse mit Eigenschaften wäre ein großer Schritt in diese Richtung ...
Für die anfängliche Entwicklung schlage ich vor, eine Syntax zu entwickeln, die auf einer sehr (viel) vereinfachten Version von CSS basiert. Ich bin dafür, diese Artist Style Sheets zu synchronisieren :+1: :
BNF-Grammatik #
Ich schlage eine sehr einfache Syntax vor, die zunächst implementiert werden kann (wie ein Machbarkeitsnachweis), die in Zukunft erweitert werden kann. Die BNF-Form der Syntax wird unten angegeben und dann erklärt
RuleSet ::= SelectorSequence "{"Declaration"}"
SelectorSequence :: = Selector {"," Selector}
Declaration ::= propName":" propValue";"
Selector ::= ArtistIdent{"#"Ident}
propName ::= Ident
propValue ::= Ident | Number | Colour | "None"
ArtistIdent
, Ident
, Number
und Colour
sind Token (die Grundbausteine des Ausdrucks), die durch reguläre Ausdrücke definiert werden.
Syntax #
Ein CSS-Stylesheet besteht aus einer Reihe von Regelsätzen in hierarchischer Reihenfolge (Regeln werden von oben nach unten angewendet). Jede Regel folgt der Syntax
selector {attribute: value;}
Jede Regel kann eine beliebige Anzahl von Paaren haben, und ein Stylesheet kann eine beliebige Anzahl von Regeln haben.attribute: value
Die anfängliche Syntax ist nur für Artist
Primitive ausgelegt. Es befasst sich nicht mit der Frage, wie Eigenschaften für Container
Typen festgelegt werden (deren Eigenschaften selbst Artist
s mit einstellbaren Eigenschaften sein können), jedoch könnte eine zukünftige Lösung dafür einfach verschachtelte
RuleSet
s sein
Selektoren #
Selektoren definieren das Objekt, auf das die Attributaktualisierungen angewendet werden sollen. Als Ausgangspunkt schlage ich nur 2 Selektoren zur Verwendung in der anfänglichen Entwicklung vor:
Auswahl des Künstlertyps
Wählen Sie eine Artist
nach ihrem Typ aus. zB Line2D
oder Text
:
Line2D {attribute: value}
Die Regex für den Abgleich der Künstlertypauswahl ( ArtistIdent
in der BNF-Grammatik) wäre:
ArtistIdent = r'(?P<ArtistIdent>\bLine2D\b|\bText\b|\bAxesImage\b|\bFigureImage\b|\bPatch\b)'
GID-Selektor #
Wählen Sie eine Artist
anhand ihrer aus gid
:
Line2D#myGID {attribute: value}
A gid
kann ein beliebiger String sein, also könnte die Regex wie folgt aussehen:
Ident = r'(?P<Ident>[a-zA-Z_][a-zA-Z_0-9]*)'
Die obigen Selektoren entsprechen in etwa ihren CSS-Pendants ( http://www.w3.org/TR/CSS21/selector.html )
Attribute und Werte #
Attributes
sind alle gültigen (einstellbaren) Eigenschaften für dieArtist
fraglichen.Values
sind alle gültigen Werte für die Eigenschaft (normalerweise eine Zeichenfolge oder Zahl).
Parsing #
Das Parsen würde darin bestehen, das Stylesheet in Tokens zu zerlegen (das Python-Kochbuch gibt auf Seite 66 ein nettes Tokenisierungsrezept), die Syntaxregeln anzuwenden und eine Tree
. Dies erfordert die Definition der Grammatik des Stylesheets (wiederum können wir von CSS leihen) und das Schreiben eines Parsers. Glücklicherweise gibt es dafür auch ein Rezept im Python-Kochbuch.
Besuchermuster für Matplotlib-Figur #
Um die Stylesheet-Regeln auf die relevanten Künstler anzuwenden, müssen wir jeden Künstler in einer Figur „besuchen“ und die relevante Regel anwenden. Hier ist eine Besucherklasse (wieder dank python cookbook), wo jeder
node
ein Künstler in der Figur wäre. visit_
Für jeden mpl-Künstler müsste eine Methode implementiert werden, um die unterschiedlichen Eigenschaften für jeden zu handhaben
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)
Eine evaluator
Klasse würde dann die Stylesheet-Regeln nehmen und den Besucher auf jeder von ihnen implementieren.
Abwärtskompatibilität #
Die Implementierung einer separaten Style
Klasse würde die Abwärtskompatibilität beeinträchtigen, da viele get/set-Methoden für einen Künstler überflüssig würden. Obwohl es möglich wäre, diese Methoden so zu ändern, dass sie sich in die Style
Klasse einklinken (als Eigenschaft für den Künstler gespeichert), wäre ich dafür, sie einfach zu entfernen, um die Codebasis zu verschönern/vereinfachen und eine einfache, übersichtliche API bereitzustellen. .
Alternativen #
Keine Alternativen, aber einige der hier behandelten Themen überschneiden sich mit MEP25, was zu dieser Entwicklung beitragen kann
Anhang #
Matplotlib-Primitive #
Dies bildet die anfänglichen Selektoren, die Stylesheets verwenden können.
Linie2D
Text
AxesImage
AbbildungBild
Patch