|
|
Où l'art de disposer des vignettes sur un canevas...
|
|
|
... dit plus sérieusement : disposition des vignettes au sein d'une figure.
|
|
|
|
|
|
Une **figure** de matplotlib peut contenir une ou plusieurs zones de tracé, que j'appelle à titre tout à fait personnel des "vignettes" tant qu'il n'est question que de disposition des différents éléments dans l'espace et pas encore (vraiment) des objets Axes et Subplots, je m'en explique dans la partie **définition**.
|
|
|
Cette page présente les principaux outils pour organiser les **vignettes**, telles que définies dans ce tuto, dans une figure ; vous trouverez comme mot-clés en français "disposition" et en anglais "layout" (à ajouter au lexique ?).
|
|
|
|
|
|
On utilise cette notion dans les ateliers C et G, et cette section permet donc de regrouper des remarques concernant les deux exercices, utilisés ici pour illustrer.
|
|
|
L'idée de cette section est venue de petits problème lors de l'écriture des codes C et G... en fait, la doc et les tutoriels couvrent bien ces notions mais dès que l'on travaille de mémoire il est facile de confondre des notions et d'obtenir des résultats incohérents (en particulier, plt.subplot(111) et plt.subplot*s*(111): la première instruction crée une vignette, la seconde en crée 111 ; la différence entre les deux est un "s"... La syntaxe correcte pour le 2e pour une seule vignette serait plt.subplot(1,1), avec une virgule...
|
|
|
|
|
|
Mes références préférées sur le sujet :
|
|
|
- [doc de Matplotlib](https://matplotlib.org/stable/tutorials/intermediate/gridspec.html)
|
|
|
- [doc de scipy](https://scipy-lectures.org/intro/matplotlib/index.html)
|
|
|
- [Python simple, volet "graphes multiples" pour les grilles régulières](http://www.python-simple.com/python-matplotlib/graphes-multiples.php) et [volet graphes complexes](http://www.python-simple.com/python-matplotlib/disposition-complexe-graphes.php)
|
|
|
- [cours de X. Garrido, diapo 43 et suivantes](https://xgarrido.github.io/licence_python_teaching/pdf/06_slide_matplotlib.pdf)
|
|
|
|
|
|
On distingue ici :
|
|
|
- **Grille régulière** = je découpe la figure par une grille de nrows ligne et ncols colonne ; la seule difficulté est de récupérer le ou les "Axes" que la fonction subplots retourne au bon format : valeur unique, vecteur ou matrice...
|
|
|
- **Grille régulière avec des différences de hauteurs ou de largeurs** : on ajoute un argument pour donner les proportions des différentes lignes et colonnes (dictionnaire gridspec_kw, clés height_ratios et width_ratios)
|
|
|
- **Grille apparemment irrégulière** = jé crée une grille régulière, mais je définis des Axes qui peuvent s'étendre sur plusieurs lignes et/ou plusieurs colonnes : on ne devine plus forcément la grille sous-jacente, car les subplots peuvent être de tailles très différentes.
|
|
|
- **Grille vraiment irrégulière** : je place mes Axes comme je veux, en définissant les coordonnées des coins par rapport à la figure ; cela permet d'emboîter des vignettes (effet de "zoom")
|
|
|
|
|
|
:new: **fig.subplot_mosaic** une méthode vraiment intéressante pour définir via une liste la disposition des vignettes éventuellement imbriquées. Je ne connaissais pas avant de la repérer dans les nouveautés de la version 3.5.
|
|
|
|
|
|
|
|
|
## Rappel de quelques définitions
|
|
|
### classe Figure et méthode plt.figure()
|
|
|
La **Figure** est l'objet principal.
|
|
|
La **méthode** figure de pyplot renvoie une instance de la **classe** Figure.
|
|
|
Elle est elle-même attachée au canvas d'une fenêtre, mais on interviendra pas sur la fenêtre directement. Si on veut donner un titre à la fenêtre, qui sera le nom par défaut pour enregistrer le fichier (widget "save") on passera par la figure via l'attribut canvas.manager (avant la version 4, canvas suffisait).
|
|
|
|
|
|
```Python
|
|
|
fig_pp = plt.figure()
|
|
|
# fig_pp.canvas.set_window_title("ScE - Hydrologie -Démo Gumbel") #obsolète depuis mpl 4.0
|
|
|
fig_pp.canvas.manager.set_window_title("ScE - Hydrologie -Démo Gumbel") #obsolète depuis mpl 4.0
|
|
|
```
|
|
|
|
|
|
### [Axes](https://matplotlib.org/stable/api/axes_api.html#the-axes-class)
|
|
|
Le nom de cette **classe** prête à confusion ! Une instance de "Axes" est définie par un espace sur la figure et deux axes (instances de Axis ; au sens cette fois de axe des x et axe des y ; mais axis au pluriel fait axes...ce qui rend les explications parfois confuses). Ici et dans les diapos, j'emploie le terme de "vignettes" quand je fais référence à l'espace occupé dans la figure ; quand cet espace comporte plusieurs objets "Axes", avec par exemple un axe des y à droite et un à gauche, j'emploie le terme "système d'axes" pour une instance de Axes pour insister sur ce qui les différencie.
|
|
|
|
|
|
### subplot
|
|
|
la méthode **subplots** permet de créer d'un coup une figure et une ou plusieurs instances de Axes selon une grille régulière
|
|
|
la méthode **add_subplot** permet d'ajouter à une figure une instance
|
|
|
|
|
|
En général, on écrit que la **méthode subplots** renvoie un objet figure et un objet Axes, mais c'est plus exactement un objet **AxesSubplot**. La doc décrit les subplots comme des "Axes" avec des propriétés particulières : "(...) Axes instances with additional methods to facilitate generating and manipulating a set of Axes within a figure."
|
|
|
La méthode **add_ax**, présentée tout à la fin, crée elle des objets **matplotlib.axes._axes.Axes**
|
|
|
|
|
|
La malédiction de "Axes" ne s'arrête donc pas à la confusion possible avec les axes des x et des y. Il serait plus clair de parler de "subplot" en langage naturel (en anglais...), mais pour Python il y a une méthode suplots, une méthode supplot, une classe Axes et une classe AxesSubplots... (ou plus exactement matplotlib.axes._subplots.**AxesSubplot**... et matplotlib.axes._axes.**Axes** ! ! !)
|
|
|
:warning: il existe des instructions qui fonctionnent sur un Axes mais pas sur un Subplots !
|
|
|
|
|
|
Donc, pour ce tutoriel, je propose d'appeler en français **"vignette"** une zone de tracé, quelle que soit la méthode employée pour la créer, et "Axes" ou système d'axes pour l'objet, qu'il soit un vrai Axes ou un AxesSubplots...
|
|
|
|
|
|
|
|
|
```Python
|
|
|
fig, ax = plt.subplots()
|
|
|
type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'matplotlib.axes._subplots.AxesSubplot'>
|
|
|
```
|
|
|
|
|
|
## Grille régulière
|
|
|
:warning: on rappelle les bases, en indiquant une source possible d'erreurs : confondre **subplots** avec s et **subplot** sans s
|
|
|
|
|
|
|
|
|
### méthode **subplots** (avec un s)
|
|
|
|
|
|
On va distinguer 3 cas : une seule vignette, des vignettes sur une seule colonne ou une seule ligne, et enfin une grille 2D de vignettes.
|
|
|
La doc résume les objets renvoyés, que nous allons détailler ci-dessous :
|
|
|
"if only one subplot is constructed (nrows=ncols=1), the resulting single Axes object is returned as a scalar.
|
|
|
for Nx1 or 1xM subplots, the returned object is a 1D numpy object array of Axes objects.
|
|
|
for NxM, subplots with N>1 and M>1 are returned as a 2D array."
|
|
|
|
|
|
|
|
|
#### cas le plus simple : "Figure" avec un "Axes" unique
|
|
|
|
|
|
En l'absence de déclarations explicites d'une figure et d'un axe, l'instruction plt.plot(x,y) va définir une figure et un ax, qui ne seront donc pas nommés mais que l'on pourra appeler au besoin avec respectivement plt.gcf() pour get current figure et plt.gca() pour get current ax.
|
|
|
Si on veut agir sur ces objets figure et ax, il vaut mieux les nommer explicitement.
|
|
|
|
|
|
#### arguments et leurs valeurs par défaut
|
|
|
Les arguments de subplots sont **nrows** le nombre de lignes de la grille, et **ncols** le nombre de colonnes. Par défaut, nrows=1 et ncols=1.
|
|
|
Donc fig, ax = plt.subplots() est équivalent à fig, ax = plt.subplots(1,1)
|
|
|
|
|
|
```Python
|
|
|
fig, ax = plt.subplots()
|
|
|
print(type(fig), type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'matplotlib.axes._subplots.AxesSubplot'>
|
|
|
|
|
|
# équivalent à :
|
|
|
fig, ax = plt.subplots(nrows=1,ncols=1)
|
|
|
print(type(fig), type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'matplotlib.axes._subplots.AxesSubplot'>
|
|
|
|
|
|
# comme nrows et ncols sont des arguments de position, on peut omettre les noms :
|
|
|
fig, ax = plt.subplots(1,1)
|
|
|
print(type(fig), type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'matplotlib.axes._subplots.AxesSubplot'>
|
|
|
|
|
|
# attention, il faut bien mettre des virgules ! contrairement à la méthode subplot sans s...
|
|
|
fig, ax = plt.subplots(11)
|
|
|
print(type(fig), type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'numpy.ndarray'>
|
|
|
len(ax)
|
|
|
Out[13]: 11
|
|
|
```
|
|
|
#### méthode **subplots** (avec un s), cas "vecteur" : "Figure" avec plusieurs "Axes" en ligne ou en colonne
|
|
|
C'est le cas de l'atelier C; on veut superposer deux ou trois "axes" l'un au dessus de l'autre.
|
|
|
Si on écrit "fig, ax" comme précédemment, ax correspond **à plusieurs axes** ; c'est un vecteur d'objets de classe Axes. Dans le cas suivant, avec trois lignes, on a donc un array de taille 3, avec ax[0] en haut, ax[1] au milieu et ax[2] en bas. Cela peut être pratique pour itérer sur les vignettes.
|
|
|
Si on préfère des noms plus explicites, on peut demander à retourner les élément dans un tuple pour les nommer individuellement.
|
|
|
|
|
|
```Python
|
|
|
# trois vignettes les unes sous les autres
|
|
|
fig, ax = plt.subplots(nrows=3,ncols=1)
|
|
|
print(type(fig), type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'numpy.ndarray'>
|
|
|
len(ax)
|
|
|
Out[15]:3
|
|
|
print(type(ax[1]))
|
|
|
<class 'matplotlib.axes._subplots.AxesSubplot'>
|
|
|
|
|
|
# équivalent à
|
|
|
fig,(ax_du_haut, ax_du_milieu, ax_du_bas) = plt.subplots(nrows=3,ncols=1)
|
|
|
|
|
|
|
|
|
# dans l'exemple de l'atelier C, deux vignettes les unes sous les autres partageant le même axe des x (donc solidaires pour le zoom)
|
|
|
fig, (ax_pluie, ax_q) = plt.subplots(ncols=1, nrows=2, sharex=True)
|
|
|
fig.subplots_adjust(bottom=0.15) # marge en bas
|
|
|
```
|
|
|
|
|
|
```Python
|
|
|
# trois vignettes les unes à côté des autres
|
|
|
fig, ax = plt.subplots(nrows=1,ncols=3)
|
|
|
print(type(fig), type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'numpy.ndarray'>
|
|
|
len(ax)
|
|
|
Out[15]:3
|
|
|
print(type(ax[1]))
|
|
|
<class 'matplotlib.axes._subplots.AxesSubplot'>
|
|
|
|
|
|
# équivalent à
|
|
|
fig,(ax_gauche, ax_du_milieu, ax_droit) = plt.subplots(nrows=1,ncols=3)
|
|
|
|
|
|
# trois vignettes les unes à côté des autres partageant le même axe des y
|
|
|
fig, ax = plt.subplots(nrows=1,ncols=3, sharey=True)
|
|
|
```
|
|
|
|
|
|
|
|
|
#### méthode **subplots** (avec un s), cas "matrice" : "Figure" avec plusieurs "Axes" en ligne
|
|
|
On peut enfin définir une grille avec plisieurs lignes et plusieurs colonnes
|
|
|
|
|
|
```Python
|
|
|
# neuf vignettes en carré
|
|
|
fig, ax = plt.subplots(nrows=3,ncols=3)
|
|
|
print(type(fig), type(ax))
|
|
|
<class 'matplotlib.figure.Figure'> <class 'numpy.ndarray'>
|
|
|
len(ax)
|
|
|
Out[15]:3 # trois car trois lignes !
|
|
|
print(type(ax[1]))
|
|
|
<class 'numpy.ndarray'>
|
|
|
print(type(ax[1,1]))
|
|
|
<class 'matplotlib.axes._subplots.AxesSubplot'>
|
|
|
|
|
|
# équivalent à, SANS OUBLIER LES PARENTHESES
|
|
|
fig,((ax_hg, ax_hm, ax_hd),(ax_mg, ax_mm, ax_md),(ax_bg, ax_bm, ax_bd))= plt.subplots(nrows=3,ncols=3)
|
|
|
|
|
|
```
|
|
|
|
|
|
:warning: Ne pas oublier les parenthèses !
|
|
|
il faut bien définir une matrice de noms de variables pour récupérer la matrice des "Axes"
|
|
|
```Python
|
|
|
fig,(ax_hg, ax_hm, ax_hd,ax_mg, ax_mm, ax_md,ax_bg, ax_bm, ax_bd)= plt.subplots(nrows=3,ncols=3) ValueError: not enough values to unpack (expected 9, got 3)
|
|
|
```
|
|
|
##problèmes de recouvrement des vignettes (titres, titres d'axes...)
|
|
|
Il existe plusieurs manières de les éviter :
|
|
|
- définir des marges et des espacements avec plt.subplots_adjust
|
|
|
- ajouter des "Axes" vides pour créer des espacements ; il faur alors supprimer leurs axes, leur cadre et rendre leur surface transparente (voir ci-dessous);
|
|
|
- plt.tight_layout() est censé tout régler mais a quelques trous dans la raquette : il ne gère pas les suptitles, au niveau de la figure, ni les widgets : s'il décale les titres des sliders à juste titre il décale du même coup les tracés de courbes car il aligne le bord gauche de leur vignettes avec le bord gauche du slider, qui suit le titre...
|
|
|
|
|
|
|
|
|
```Python
|
|
|
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
|
|
|
[voir subplots_adjust dans la doc](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots_adjust.html)¶
|
|
|
```
|
|
|
|
|
|
```Python
|
|
|
# ax_espace a été créé seulement pour que la vignette correspondante crée un intervalle
|
|
|
# afin d'éviter les recouvrements
|
|
|
# d'abord on enlève les axes de toutes les vignettes qui ne comporteront pas de courbes (vignettes d'espacement, mais aussi pour placer les widgets)
|
|
|
for ax in [ax_espace , ax_radiob1, ax_radiob2, ax_message]:
|
|
|
ax.xaxis.set_visible(False)
|
|
|
ax.yaxis.set_visible(False)
|
|
|
|
|
|
#ensuite on enlève le cadre là où nécessaire, pour ax_espace notamment
|
|
|
for pos in ['right', 'top', 'bottom', 'left']:
|
|
|
ax_espace.spines[pos].set_visible(False)
|
|
|
|
|
|
# enfin, on rend la surface transparente pour ne pas le texte des autres axes
|
|
|
# que l'on cherche justement à séparer les uns des autres
|
|
|
ax_espace.patch.set_alpha(0.01) #sinon cet axe cache le titre de l'axe des x au-dessus !)
|
|
|
|
|
|
```Python
|
|
|
|
|
|
|
|
|
## Grille avec des différences de hauteurs ou de largeur
|
|
|
Le plus simple est d'utiliser l'argument gridspec_kw dans subplots.
|
|
|
Dans le code "Chegodaiev.py", on définit un Axes plus haut que les autres pour le graphique, les autres abritent des widgets et n'ont pas besoin d'être hauts. On définit donc un vecteur qui détermine les rapports des hauteurs, de dimension nrows.
|
|
|
L'argument **gridspec_kw** (kw pour "keywords") attend un dictonnaire clé/valeurs, avec ici clé='height_ratios' avec comme valeur associée le vecteur des ratios.
|
|
|
On aura donc ax qui occupe 10/14e de la hauteur de la figure, ax_slide_a 1/14e et ainsi de suite
|
|
|
Pour les figures avec plusieurs colonnes, on peut définir de même une valeur pour la clé width_ratios.
|
|
|
|
|
|
```Python
|
|
|
fig_pp, (ax, ax_slide_a, ax_slide_b, ax_slide_n, ax_chb) = plt.subplots(nrows=5, ncols=1, gridspec_kw={'height_ratios': [10, 1, 1, 1,2]})
|
|
|
plt.subplots_adjust(wspace=1, hspace=0.5,left=0.1,top=0.85,right=0.9,bottom=0.1)
|
|
|
```
|
|
|
|
|
|
|
|
|
## Grille apparemment irrégulière
|
|
|
Il est possible d'avoir plus de souplesse pour définir des vignettes de tailles différentes. Dans le code **GenerateurCruesMaxAnnuelles.py**, on veut des graphiques prenant toute la largeur, et pour certains widgets des vignettes tenant à deux sur la même ligne.
|
|
|
|
|
|
Il faut définir la figure séparément, et ajouter dessus des axes avec une méthode qui permet de les placer comme on veut sur une grille indicative.
|
|
|
On va présenter ici deux méthodes, une utilisant **subplot sans s** ou **add_subplot** et l'autre avec **gridspec**, cette fois-ci comme méthode ( comme utilisé dans le code **GenerateurCruesMaxAnnuelles.py**).
|
|
|
|
|
|
|
|
|
### méthode **subplot** sans s !
|
|
|
:warning: ne pas confondre !
|
|
|
LA méthode **plt.subplot** sans s, équivalente à **add_subplot** permet de créer une vignette à la fois selon une grille ; c'est pratique pour ajouter des vignettes en cours d'exécution.
|
|
|
|
|
|
```Python
|
|
|
subplot(nrows, ncols, index, **kwargs)
|
|
|
subplot(pos, **kwargs)
|
|
|
subplot(**kwargs)
|
|
|
subplot(ax)
|
|
|
|
|
|
```
|
|
|
Les trois arguments nrows, ncols, index peuvent être passés sans virgule ! Ce qu'il ne faut pas faire avec **subplots avec un s* car suplots(111) crée 111 axes les uns sur les autres...
|
|
|
La logique est la suivante : sur une grille (nrows, ncols) je travaille avec le subplot d'indice index (numérotation comme on écrit, 1 = vignette en haut à gauche).
|
|
|
|
|
|
```Python
|
|
|
plt.subplot(221) # je vais travailler avec la vignette du quart haut gauche
|
|
|
|
|
|
# equivalent but more general
|
|
|
ax1 = plt.subplot(2, 2, 1)
|
|
|
|
|
|
# add a red subplot that shares the x-axis with ax1
|
|
|
plt.subplot(224, sharex=ax1, facecolor='red') # vignette du quart bas gauche
|
|
|
|
|
|
# delete ax2 from the figure
|
|
|
plt.delaxes(ax2)
|
|
|
|
|
|
# add ax2 to the figure again
|
|
|
plt.subplot(ax2)
|
|
|
|
|
|
# make the first axes "current" again
|
|
|
plt.subplot(221)
|
|
|
|
|
|
```
|
|
|
EN théorie, on est libres de créer une grille irrégulière, mais il faut faire attention : créer un nouveau subplot dans un "espace" déjà occupé écrase le précédent.
|
|
|
|
|
|
**plt.subplot** est en fait un alias de la méthode **add_subplot** de Figure
|
|
|
|
|
|
|
|
|
```Python
|
|
|
fig = plt.figure()
|
|
|
|
|
|
fig.add_subplot(231)
|
|
|
ax1 = fig.add_subplot(2, 3, 1) # equivalent but more general
|
|
|
|
|
|
fig.add_subplot(232, frameon=False) # subplot with no frame
|
|
|
fig.add_subplot(234, sharex=ax1) # subplot sharing x-axis with ax1
|
|
|
fig.add_subplot(235, facecolor="red") # red subplot
|
|
|
|
|
|
ax1.remove() # delete ax1 from the figure
|
|
|
fig.add_subplot(ax1) # add ax1 back to the figure
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
### avec **matplotlib.gridspec.GridSpec**
|
|
|
|
|
|
Il faut d'abord importer le module matplotlib.gridspec
|
|
|
Ensuite, on définit une grille, avec un nombre de lignes et un nombre de colonnes, que l'on appelle par convention **gs**.
|
|
|
Sur cette grille, on va définir la position des Axes avec subplot ou fig.add_subplot avec comme argument un "slice" de gs.
|
|
|
|
|
|
L'exemple de [Python simple ](http://www.python-simple.com/python-matplotlib/disposition-complexe-graphes.php) est intéressant car grâce aux couleurs on voit très facilement la correspondance entre la coordonnée exprimée avec gs et le rendu en "vignettes" !
|
|
|
Pour obtenir des cases de tailles différentes, cet exemple combine les ratios de hauteur et largeur (mot-clés width_ratios et height_ratios) avec le "slicing", définissant une position éventuellement à cheval sur plusieurs lignes et/ou plusieurs colonnes.
|
|
|
|
|
|
```Python
|
|
|
import matplotlib.gridspec as gridspec
|
|
|
gs = matplotlib.gridspec.GridSpec(4, 3,
|
|
|
width_ratios = [3, 3, 1], height_ratios = [1, 1, 1, 1],
|
|
|
left = 0, right = 1, bottom = 0.1, top = 1,
|
|
|
hspace = 0, wspace = 0)
|
|
|
# gs est une grille avec 4 lignes (indexées de 0 à 3) et 3 colonnes (de 0 à 2)
|
|
|
pyplot.subplot(gs[0, 0], facecolor = 'yellow') # une seule case, en haut à gauche
|
|
|
pyplot.subplot(gs[1,0:2], facecolor = 'skyblue') # deuxième ligne, colonnes 0 et 1 (2 exclu)
|
|
|
pyplot.subplot(gs[0:4, 2], facecolor = 'pink') # 4 premières lignes, colonne 2
|
|
|
pyplot.subplot(gs[2:4, 0:2], facecolor = 'orange') # lignes 2 et 3 (4 exclu), colonnes 0 et 1
|
|
|
```
|
|
|
On va commenter maintenant le code de **GenerateurCruesMaxAnnuelles.py**
|
|
|
On n'a pas utilisé width_ratios et height_ratios dans cette version.
|
|
|
Par exemple:
|
|
|
- gs[0:6, :] = la vignette va occuper les 6 premières lignes et toutes les colonnes.
|
|
|
- gs[7, 1] = la vignette va occuper la 8e ligne et la 2e colonne (ici = colonne de droite)
|
|
|
On remarque que certaines cases ne sont pas occupées ; le positionnement a été fait pour éviter le recouvrement entre les titres, les noms des axes et les autres vignettes. Normalement, l'option "tight layout" permet d'éviter ces recouvrements.
|
|
|
|
|
|
|
|
|
```Python
|
|
|
import matplotlib.gridspec as gridspec
|
|
|
fig_pp = plt.figure()
|
|
|
gs = gridspec.GridSpec(17, 2)
|
|
|
ax_chrono = plt.subplot(gs[0:6, :])
|
|
|
ax_bouton = plt.subplot(gs[7, 0])
|
|
|
ax_bouton_RAZ = plt.subplot(gs[7, 1])
|
|
|
ax_T = plt.subplot(gs[8:13, :])
|
|
|
ax_slide_a = plt.subplot(gs[16, 0])
|
|
|
ax_slide_b = plt.subplot(gs[16, 1])
|
|
|
ax_T2f = plt.subplot(gs[15, :])
|
|
|
```
|
|
|
|
|
|
## Grille vraiment irrégulière
|
|
|
|
|
|
La méthode **add_ax** permet une totale liberté de positionnement.
|
|
|
Contrairement à **add_subplot** qui suppose une grille sous-jacente, **add_ax** prend comme argument les coordonnées (x0,y0) du coin en bas à gauche, une largeur et une hauteur.
|
|
|
Coordonnées et dimensions sont exprimées par rapport au canvas, donc peuvent aller de 0 à 1.
|
|
|
|
|
|
```Python
|
|
|
rect = [x0, y0, width, height]
|
|
|
add_axes(rect)
|
|
|
ax = fig.add_axes([0,0,1,1]) # tout le canevas
|
|
|
type(ax)
|
|
|
Out[29]: matplotlib.axes._axes.Axes
|
|
|
```
|
|
|
|
|
|
## :new: Une méthode puissante :subplot_mosaic:
|
|
|
Il suffit de décrire la structure des vignettes par une liste, en nommant au passage les vignettes.
|
|
|
Dans l'exemple ci-dessous, la liste **mosaic** comprend deux lignes et deux colonnes, et l'un des éléments est lui-même composé d'une matrice 2x2. Il existe d'autres variantes pour définir l'argument : [voir la doc](https://matplotlib.org/3.5.0/api/figure_api.html?highlight=subplot_mosaic#matplotlib.figure.Figure.subplot_mosaic).
|
|
|
Le symbole '.' indique un emplacement vide ; on peut changer ce code avec l'argument **empty_sentinel**.
|
|
|
On crée un dictionnaire **ax_dict** en passant **mosaic** comme argument à la fonction **subplot_mosaic** appliquée à **fig**. L'**Axes** de la vignette en bas à gauche s'appelle donc **ax_dict['F']**
|
|
|
|
|
|
Depuis la version 3.5.0, on peut préciser également que tous les "Axes" partagent les mêmes axes.
|
|
|
|
|
|
```Python
|
|
|
mosaic = [
|
|
|
['A', [['B', 'C'],
|
|
|
['D', 'E']]],
|
|
|
['F', 'G'],
|
|
|
]
|
|
|
fig = plt.figure(constrained_layout=True)
|
|
|
ax_dict = fig.subplot_mosaic(mosaic, sharex=True, sharey=True)
|
|
|
# All Axes use these scales after this call.
|
|
|
ax_dict['A'].set(xscale='log', yscale='logit')
|
|
|
```
|
|
|
|
|
|
Pour voir le résultat, essayez le code ou [allez voir la doc](https://matplotlib.org/3.5.0/_images/whats_new_3-5-0-1.png) |
|
|
\ No newline at end of file |