J'utilise quadmesh
pour créer un tracé de projection polaire simple. Voici un script minimal qui produit ce que j'essaie de faire:
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt
def make_plot(data,fig,subplot):
nphi,nt = data.shape
phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2.
theta_coords = np.linspace(0,np.radians(35),nt+1)
ax = fig.add_subplot(subplot,projection='polar')
ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
theta,phi = np.meshgrid(phi_coords,theta_coords)
quadmesh = ax.pcolormesh(theta,phi,data)
ax.grid(True)
fig.colorbar(quadmesh,ax=ax)
return fig,ax
a = np.zeros((360,71)) + np.arange(360)[:,None]
b = np.random.random((360,71))
fig = plt.figure()
t1 = make_plot(a,fig,121)
t2 = make_plot(b,fig,122)
fig.savefig('test.png')
Le script ci-dessus crée un graphique qui ressemble à ceci:
J'aimerais que les barres de couleur:
Y at-il une astuce pour que cela fonctionne correctement? (Notez que cette disposition n'est pas la seule que j'utiliserai. Par exemple, je pourrais utiliser une disposition 1x2 ou 4x4 ... Il semble qu'il devrait exister un moyen de redimensionner la barre de couleur à la même hauteur que le parcelle associée ...)
Cette combinaison (et les valeurs proches de celles-ci) semble "magiquement" me permettre de garder la barre de couleur à l'échelle du tracé, quelle que soit la taille de l'affichage.
plt.colorbar(im,fraction=0.046, pad=0.04)
Vous pouvez le faire avec une combinaison de pad
, shrink
et aspect
kwargs:
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt
def make_plot(data,fig,subplot):
nphi,nt = data.shape
phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2.
theta_coords = np.linspace(0,np.radians(35),nt+1)
ax = fig.add_subplot(subplot,projection='polar')
ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
theta,phi = np.meshgrid(phi_coords,theta_coords)
quadmesh = ax.pcolormesh(theta,phi,data)
ax.grid(True)
cb = fig.colorbar(quadmesh,ax=ax, shrink=.5, pad=.2, aspect=10)
return fig,ax,cb
a = np.zeros((360,71)) + np.arange(360)[:,None]
b = np.random.random((360,71))
fig = plt.figure()
t1 = make_plot(a,fig,121)
t2 = make_plot(b,fig,122)
La meilleure valeur pour ces paramètres dépend du rapport de format des axes.
La taille des axes ne semble pas être rétractée par rapport au tracé polaire. Par conséquent, dans l'agencement 1x2, il y a beaucoup d'espace au-dessus et au-dessous du tracé qui font partie de l'objet axes, mais sont vides. La taille de la barre de couleur dépend de la taille rectangulaire, pas de la taille arrondie, ce qui explique pourquoi les valeurs par défaut ne fonctionnent pas bien. Il y a probablement un moyen de faire l'emballage sous film, mais je ne sais pas comment le faire.
Une autre méthode consiste à forcer votre personnage à avoir le bon rapport d’aspect ex:
fig.set_size_inches(10, 4) # for 1x2
fig.set_size_inches(4, 10) # for 2x1
ce qui rend les sous-parcelles carrées, donc les valeurs par défaut fonctionnent plus ou moins.
La mise à l'échelle automatique de la barre de couleur est connue pour être délicate. Essayer d'appliquer les solutions de contournement décrites à la fin de cette page ne m'a pas fonctionné, que ce soit avec votre exemple ou avec mes tentatives d'utilisation d'un objet Axes3D
. En examinant la signature d’appel de colorbar
, l’argument du mot clé ax
est "l’objet à partir duquel l’espace pour un nouvel axe de barre de couleurs sera volé". Cela explique pourquoi la barre de couleur chevauche le 6. Nous devons donc conserver une double variable Axes
. Malheureusement, le maintien des axes supplémentaires implique beaucoup de piratage manuel de la position. J'ai concocté ce qui suit:
#!/usr/bin/env python
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
N, M = 360, 71
phi_coords = np.linspace(0, np.pi*2, M+1) -np.pi/2
theta_coords = np.linspace(0, np.radians(35), N+1)
theta, phi = np.meshgrid(phi_coords, theta_coords)
# Original method
a = np.zeros((N,M)) + np.arange(N)[:,None]
ax1 = fig.add_subplot(1,2,1, projection="polar")
ax1.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax1.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
quadmesh = ax1.pcolormesh(theta, phi, a)
fig.colorbar(quadmesh,ax=ax1)
# Use ``add_axes`` to make a ``cax``
b = np.random.random((N,M))
ax2 = fig.add_subplot(1,2,2, projection="polar")
ax2.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax2.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')
quadmesh = ax2.pcolormesh(theta, phi, b)
# <hack>
# Hack to force the drawing of the image.
print(ax2.get_position())
import tempfile
with tempfile.SpooledTemporaryFile() as fid:
fig.savefig(fid, format="png")
# </hack>
# Now the axes has been scaled to the final size.
bbox = ax2.get_position()
print(bbox)
cax = fig.add_axes(
[bbox.xmax*1.03, bbox.ymin, bbox.width*0.08, bbox.height]
)
fig.colorbar(quadmesh,cax=cax)
fig.savefig('test.png')
L'image de gauche est identique à l'original, mais l'image de droite a la barre de couleur décalée par rapport au tracé polaire et la hauteur de la barre correspond au tracé polaire. Comme vous pouvez le constater, j'ai dû forcer la figure à dessiner afin d'obtenir la taille de l'axe à droite pour le tracé à gauche. Si vous ne forcez pas le redessinage, la taille de la barre de couleur est basée sur la taille d'origine des axes et vous obtenez les mêmes axes de taille que ceux de gauche. À ce stade, je n'ai pas trouvé de moyen d'indiquer à la Axes
de la barre de couleur de suivre automatiquement la Axes
principale pour les modifications de taille.