2017-10-06 3 views
0

j'emprunte un exemple de la page d'exemples de CMAP personnalisé matplotlib:Comment créer des points de rupture personnalisés dans une barre de couleurs matplotlib?

https://matplotlib.org/examples/pylab_examples/custom_cmap.html

Cela produit la même image avec différents nombres de contours d'ombrage, comme indiqué dans le nombre de bacs: n_bins:

https://matplotlib.org/_images/custom_cmap_00.png

Cependant, je ne m'intéresse pas seulement au nombre de cases, mais aussi aux points de rupture spécifiques entre les valeurs de couleur. Par exemple, lorsque nbins=6 en haut à droite intrigue secondaire, comment puis-je spécifier les gammes des compartiments de telle sorte que la trame de fond est rempli dans ces domaines personnalisés:

n_bins_ranges = ([-10,-5],[-5,-2],[-2,-0.5],[-0.5,2.5],[2.5,7.5],[7.5,10]) 

Est-il également possible de spécifier l'inclusivité de la rupture points? Par exemple, je voudrais spécifier dans la gamme entre -2 et 0.5 si c'est -2 < x <= -0.5 ou -2 <= x < -0.5.

EDIT AVEC réponse ci-dessous: Utilisation de la réponse acceptée ci-dessous

, voici le code qui trace chaque étape comprenant enfin l'ajout colorbar personnalisé tiques à mi-parcours. Remarque: je ne peux pas publier d'image car je suis un nouvel utilisateur.

Mettre en place des données et 6 bacs de couleur:

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib 

# Make some illustrative fake data: 
x = np.arange(0, np.pi, 0.1) 
y = np.arange(0, 2*np.pi, 0.1) 
X, Y = np.meshgrid(x, y) 
Z = np.cos(X) * np.sin(Y) * 10 

# Create colormap with 6 discrete bins 
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # R -> G -> B 
n_bin = 6 
cmap_name = 'my_list' 
cm = matplotlib.colors.LinearSegmentedColormap.from_list(
     cmap_name, colors, N=n_bin) 

Terrain différentes options:

# Set up 4 subplots 
fig, axs = plt.subplots(2, 2, figsize=(6, 9)) 
fig.subplots_adjust(left=0.02, bottom=0.06, right=0.95, top=0.94, wspace=0.05) 

# Plot 6 bin figure 
im = axs[0,0].imshow(Z, interpolation='nearest', origin='lower', cmap=cm) 
axs[0,0].set_title("Original 6 Bin") 
fig.colorbar(im, ax=axs[0,0]) 

# Change the break points 
n_bins_ranges = [-10,-5,-2,-0.5,2.5,7.5,10] 
norm = matplotlib.colors.BoundaryNorm(n_bins_ranges, len(n_bins_ranges)) 
im = axs[0,1].imshow(Z, interpolation='nearest', origin='lower', cmap=cm, norm=norm) 
axs[0,1].set_title("Custom Break Points") 
fig.colorbar(im, ax=axs[0,1]) 

# Arrange color labels by data interval (not colors) 
im = axs[1,0].imshow(Z, interpolation='nearest', origin='lower', cmap=cm, norm=norm) 
axs[1,0].set_title("Linear Color Distribution") 
fig.colorbar(im, ax=axs[1,0], spacing="proportional") 

# Provide custom labels at color midpoints 
# And change inclusive equality by adding arbitrary small value 
n_bins_ranges_arr = np.asarray(n_bins_ranges)+1e-9 
norm = matplotlib.colors.BoundaryNorm(n_bins_ranges, len(n_bins_ranges)) 
n_bins_ranges_midpoints = (n_bins_ranges_arr[1:] + n_bins_ranges_arr[:-1])/2.0 
im = axs[1,1].imshow(Z, interpolation='nearest', origin='lower', cmap=cm ,norm=norm) 
axs[1,1].set_title("Midpoint Labels\n Switched Equal Sign") 
cbar=fig.colorbar(im, ax=axs[1,1], spacing="proportional", 
     ticks=n_bins_ranges_midpoints.tolist()) 
cbar.ax.set_yticklabels(['Red', 'Brown', 'Green 1','Green 2','Gray Blue','Blue']) 

plt.show() 
+0

Vous n'êtes pas vraiment voulu dire pour répondre à votre question dans la question (comme ce ne serait plus une question si vous y répondez déjà, n'est-ce pas?) Vous pouvez plutôt répondre à votre propre question. – ImportanceOfBeingErnest

Répondre

1

Vous pouvez utiliser un BoundaryNorm comme suit:

import matplotlib.pyplot as plt 
import matplotlib.colors 
import numpy as np 
x = np.arange(0, np.pi, 0.1) 
y = np.arange(0, 2*np.pi, 0.1) 
X, Y = np.meshgrid(x, y) 
Z = np.cos(X) * np.sin(Y) * 10 

colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # R -> G -> B 
n_bin = 6 # Discretizes the interpolation into bins 
n_bins_ranges = [-10,-5,-2,-0.5,2.5,7.5,10] 
cmap_name = 'my_list' 
fig, ax = plt.subplots() 

# Create the colormap 
cm = matplotlib.colors.LinearSegmentedColormap.from_list(
      cmap_name, colors, N=n_bin) 
norm = matplotlib.colors.BoundaryNorm(n_bins_ranges, len(n_bins_ranges)) 
# Fewer bins will result in "coarser" colomap interpolation 
im = ax.imshow(Z, interpolation='nearest', origin='lower', cmap=cm, norm=norm) 
ax.set_title("N bins: %s" % n_bin) 
fig.colorbar(im, ax=ax) 

plt.show() 

Ou, si vous voulez espacement proportionnel, c'est-à-dire la distance entre les couleurs en fonction de leurs valeurs,

fig.colorbar(im, ax=ax, spacing="proportional") 

enter image description here enter image description here

Comme les États boundary norm documentation

Si b[i] <= v < b[i+1] alors v est associée à la couleur j; comme i varie de 0 à len (limites) -2, j va de 0 à ncolors-1.

Ainsi, les couleurs sont toujours choisies comme -2 <= x < -0.5, afin d'obtenir le signe égal de l'autre côté, vous devrez fournir quelque chose comme n_bins_ranges = np.array([-10,-5,-2,-0.5,2.5,7.5,10])-1e-9

+0

Génial! Merci d'avoir passé le lien de la documentation et suggéré d'ajouter (sans soustraire, correct?) Un petit nombre arbitraire pour déplacer le côté de l'égalité. Afin de continuer à faire les nombres de barre de couleur linéairement espacés, je passerais l'argument de norme 'fig.colorbar (im, ax = ax, norme = norme)' comme discuté dans la barre de couleurs api? https://matplotlib.org/api/colorbar_api.html#matplotlib.colorbar.ColorbarBase – user8732262

+0

J'ai mis à jour la réponse avec ce que je pense que vous voulez dire par l'espacement linéaire. – ImportanceOfBeingErnest