Noter
Cliquez ici pour télécharger l'exemple de code complet
Chemin Tutoriel #
Définir des chemins dans votre visualisation Matplotlib.
L'objet sous-jacent à tous les matplotlib.patches
objets est le Path
, qui prend en charge l'ensemble standard de commandes moveto, lineto, curveto pour dessiner des contours simples et composés constitués de segments de ligne et de splines. Le Path
est instancié avec un tableau (N, 2) de sommets (x, y) et un tableau de longueur N de codes de chemin. Par exemple pour dessiner le rectangle unitaire de (0, 0) à (1, 1), nous pourrions utiliser ce code :
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
verts = [
(0., 0.), # left, bottom
(0., 1.), # left, top
(1., 1.), # right, top
(1., 0.), # right, bottom
(0., 0.), # ignored
]
codes = [
Path.MOVETO,
Path.LINETO,
Path.LINETO,
Path.LINETO,
Path.CLOSEPOLY,
]
path = Path(verts, codes)
fig, ax = plt.subplots()
patch = patches.PathPatch(path, facecolor='orange', lw=2)
ax.add_patch(patch)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
plt.show()
Les codes de chemin suivants sont reconnus
Code |
Sommets |
La description |
---|---|---|
|
1 (ignoré) |
Un marqueur pour la fin du chemin complet (actuellement non requis et ignoré). |
|
1 |
Prenez le stylo et déplacez-vous vers le sommet donné. |
|
1 |
Tracez une ligne de la position actuelle au sommet donné. |
|
2 : 1 point de contrôle, 1 point final |
Dessinez une courbe de Bézier quadratique à partir de la position actuelle, avec le point de contrôle donné, jusqu'au point final donné. |
|
3 : 2 points de contrôle, 1 point final |
Dessinez une courbe de Bézier cubique à partir de la position actuelle, avec les points de contrôle donnés, jusqu'au point final donné. |
|
1 (le point est ignoré) |
Dessinez un segment de ligne jusqu'au point de départ de la polyligne courante. |
Exemple Bézier #
Certains des composants de chemin nécessitent plusieurs sommets pour les spécifier : par exemple, COURBE 3 est une courbe de Bézier avec un point de contrôle et un point final, et COURBE4 a trois sommets pour les deux points de contrôle et le point final. L'exemple ci-dessous montre une spline de Bézier COURBE4 -- la courbe de Bézier sera contenue dans l'enveloppe convexe du point de départ, des deux points de contrôle et du point final
verts = [
(0., 0.), # P0
(0.2, 1.), # P1
(1., 0.8), # P2
(0.8, 0.), # P3
]
codes = [
Path.MOVETO,
Path.CURVE4,
Path.CURVE4,
Path.CURVE4,
]
path = Path(verts, codes)
fig, ax = plt.subplots()
patch = patches.PathPatch(path, facecolor='none', lw=2)
ax.add_patch(patch)
xs, ys = zip(*verts)
ax.plot(xs, ys, 'x--', lw=2, color='black', ms=10)
ax.text(-0.05, -0.05, 'P0')
ax.text(0.15, 1.05, 'P1')
ax.text(1.05, 0.85, 'P2')
ax.text(0.85, -0.05, 'P3')
ax.set_xlim(-0.1, 1.1)
ax.set_ylim(-0.1, 1.1)
plt.show()
Chemins composés #
Toutes les primitives de patch simples dans matplotlib, Rectangle, Circle, Polygon, etc., sont implémentées avec un chemin simple. Les fonctions de traçage telles que hist()
et
bar()
, qui créent un certain nombre de primitives, par exemple un ensemble de rectangles, peuvent généralement être implémentées plus efficacement en utilisant un chemin composé. La raison pour laquelle bar
crée une liste de rectangles et non un chemin composé est en grande partie historique : le
Path
code est relativement nouveau et bar
antérieur. Bien que nous puissions le changer maintenant, cela casserait l'ancien code, donc ici nous verrons comment créer des chemins composés, en remplaçant la fonctionnalité dans la barre, au cas où vous auriez besoin de le faire dans votre propre code pour des raisons d'efficacité, par exemple, vous créez un graphique en barres animé.
Nous allons créer l'histogramme en créant une série de rectangles pour chaque barre d'histogramme : la largeur du rectangle est la largeur de la case et la hauteur du rectangle est le nombre de points de données dans cette case. Nous allons d'abord créer des données aléatoires normalement distribuées et calculer l'histogramme. Étant donné que numpy renvoie les bords du bac et non les centres, la longueur de bins
est supérieure de 1 à la longueur de n
dans l'exemple ci-dessous :
# histogram our data with numpy
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)
Nous allons maintenant extraire les coins des rectangles. Chacun des
tableaux left
, bottom
, etc, ci-dessous est len(n)
, où n
est le tableau des nombres pour chaque barre d'histogramme :
Nous devons maintenant construire notre chemin composé, qui consistera en une série de MOVETO
, LINETO
et CLOSEPOLY
pour chaque rectangle. Pour chaque rectangle, nous avons besoin de 5 sommets : 1 pour le MOVETO
, 3 pour le LINETO
et 1 pour le CLOSEPOLY
. Comme indiqué dans le tableau ci-dessus, le sommet du closepoly est ignoré mais nous en avons toujours besoin pour maintenir les codes alignés avec les sommets :
nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY
verts[0::5, 0] = left
verts[0::5, 1] = bottom
verts[1::5, 0] = left
verts[1::5, 1] = top
verts[2::5, 0] = right
verts[2::5, 1] = top
verts[3::5, 0] = right
verts[3::5, 1] = bottom
Il ne reste plus qu'à créer le chemin, à l'attacher à un
PathPatch
, et à l'ajouter à nos axes :
barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green',
edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
import numpy as np
import matplotlib.patches as patches
import matplotlib.path as path
fig, ax = plt.subplots()
# Fixing random state for reproducibility
np.random.seed(19680801)
# histogram our data with numpy
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)
# get the corners of the rectangles for the histogram
left = np.array(bins[:-1])
right = np.array(bins[1:])
bottom = np.zeros(len(left))
top = bottom + n
nrects = len(left)
nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY
verts[0::5, 0] = left
verts[0::5, 1] = bottom
verts[1::5, 0] = left
verts[1::5, 1] = top
verts[2::5, 0] = right
verts[2::5, 1] = top
verts[3::5, 0] = right
verts[3::5, 1] = bottom
barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green',
edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), top.max())
plt.show()