Définir le milieu d'une palette de couleurs dans matplotlib
Je veux mettre le point milieu d'une palette de couleurs, c'est à dire mes données va de -5 à 10, je veux zéro au milieu. Je pense que la façon de le faire est de sous-classement de normaliser et à l'aide de la norme, mais je n'ai trouvé aucun exemple et il n'est pas clair pour moi, exactement ce que j'ai à mettre en œuvre.
- ceci est appelé une "divergentes" ou "bipolaire" palette de couleurs, où le point central de la carte est importante et les données ci-dessus et au-dessous de ce point. sandia.gov/~kmorel/documents/ColorMaps
- Toutes les réponses dans ce fil semble plutôt compliqué. Facile d'utilisation, la solution est indiquée dans le cette excellente réponse, qui a entre-temps également rendu dans la matplotlib de la documentation, de la section Personnalisé normalisation: Deux linéaires plages.
Vous devez vous connecter pour publier un commentaire.
Noter que dans matplotlib la version 3.1 de la DivergingNorm classe a été ajoutée. Je pense qu'il couvre votre cas d'utilisation.
Il peut être utilisé comme ceci:
norm
la normalisation pour votre image.norms
aller de pair avec carte des couleurs.Je sais que c'est tard pour le jeu, mais je suis juste allé à travers ce processus et est venu avec une solution peut-être moins robuste que le sous-classement normaliser, mais beaucoup plus simple. J'ai pensé qu'il serait bon de le partager ici pour la postérité.
La fonction
Un exemple
Résultats de l'exemple:
start
etstop
ne sont pas des 0 et 1, respectivement, aprèsreg_index = np.linspace(start, stop, 257)
, vous pouvez prendre plus que la valeur de 129 est le milieu de l'original de la cmap, donc l'ensemble de la mise à l'échelle n'a pas de sens à chaque fois que vous culture. Aussi,start
doit être de 0 à 0,5 etstop
de 0,5 à 1, mais pas les deux à partir de 0 à 1 que vous demandez.midpoint
des données est égal à 0 ou 1. Voir ma réponse ci-dessous pour une solution simple à ce problème.Ici est une solution de sous-classement Normaliser. Pour l'utiliser, il
Ici, c'est la Classe:
Il est plus facile de simplement utiliser le
vmin
etvmax
arguments pourimshow
(en supposant que vous travaillez avec des données d'image) plutôt que de sous-classementmatplotlib.colors.Normalize
.E. g.
Normalize
. Je vais ajouter un exemple de juste un peu (en supposant que quelqu'un d'autre ne me battre pour elle...).vmax=abs(Z).max(), vmin=-abs(Z).max()
Cette solution est inspirée par une classe ayant le même nom de cette page
Ici, j'ai créer une sous-classe de
Normalize
suivie par un exemple minimal.Résultat:
Et le même exemple avec seulement les données positives
vals = sp.array([[1., 3], [6, 10]])
Juste pour résumer - la présente norme a les propriétés suivantes:
vmin
est plus grand quemidpoint
(ne pas tester tous les cas de bord tout de même).def __call__
)normalized_min
etnormalized_max
sont pris comme des nombres entiers. Il suffit de les placer comme 0.0. Aussi, pour obtenir la sortie correcte de votre figure, j'ai eu à utiliservals = sp.array([[-5.0, 0.0], [5.0, 10.0]])
. Merci pour la réponse, de toute façon!Vous ne savez pas si vous êtes toujours à la recherche d'une réponse. Pour moi, en essayant de la sous-classe
Normalize
a échoué. Donc je me suis concentré sur la création manuelle d'un nouveau jeu de données, les tiques étiquettes pour obtenir l'effet, je pense que vous visez.J'ai trouvé le
scale
module matplotlib qui a une classe utilisée pour transformer la ligne de parcelles par le 'syslog' règles, j'ai donc l'utiliser pour transformer les données. Puis je l'échelle les données de sorte qu'il passe de 0 à 1 (ce quiNormalize
d'habitude), mais je l'échelle des nombres positifs différemment des nombres négatifs. C'est parce que votre vmax et vmin pourrait ne pas être la même, de sorte .5 -> 1 pourrait couvrir une plus grande plage positive que le 5 -> 0, la plage négative ne. Il était plus facile pour moi de créer une routine pour calculer les tiques et les valeurs des étiquettes.Ci-dessous est le code et un exemple à la figure.
N'hésitez pas à ajuster les "constantes" (par exemple
VMAX
) en haut du script afin de confirmer qu'il se comporte bien.J'ai été en utilisant l'excellente réponse de Paul H, mais a couru dans un problème car certains de mes données variaient entre le négatif et le positif, tandis que d'autres ensembles variait de 0 pour positif ou de négatif à 0; dans les deux cas, je voulais de 0 à être de couleur blanc (le milieu de la palette que j'utilise). Avec la mise en œuvre existantes, si votre
midpoint
valeur est égale à 1 ou à 0, l'origine des mappages n'ont pas été remplacés. Vous pouvez le voir dans l'image ci-dessous:La 3e colonne semble correct, mais le bleu foncé de la zone dans la 2ème colonne et la zone rouge sombre dans les colonnes restantes sont tous censés être blanc (leurs valeurs de données sont, en fait, 0). À l'aide de mon fix me donne:
Ma fonction est essentiellement la même que celle de Paul H, avec mes modifications au début de la
for
boucle:EDIT: j'ai rencontré un problème similaire, une fois encore lors de certaines de mes données variaient d'une petite valeur positive à une plus grande valeur positive, où les très faibles valeurs étaient de couleur rouge au lieu de blanc. Je l'ai corrigé en ajoutant la ligne
Edit #2
dans le code ci-dessus.Si vous n'avez pas l'esprit en travaillant sur le rapport entre vmin, vmax, et zéro, c'est une question assez linéaire de base de la carte du bleu au blanc, au rouge, qui définit blanc selon le rapport
z
:La cdict format est assez simple: les lignes sont des points du gradient qui vient d'être créé: la première entrée est la valeur x (le ratio le long du gradient de 0 à 1), la seconde est la valeur de fin pour le segment précédent, et la troisième est la valeur de départ pour le segment suivant - si vous souhaitez lisser les dégradés, les deux derniers sont toujours les mêmes. Voir les docs pour plus de détails.
LinearSegmentedColormap.from_list()
les tuples(val,color)
et de les transmettre sous forme de liste pour lecolor
argument de cette méthode oùval0=0<val1<...<valN==1
.J'ai eu un problème similaire, mais je voulais la valeur la plus élevée à plein rouge et couper les faibles valeurs de bleu, donnant un aspect essentiel, comme le bas de la barre de couleur a été coupé. Cela a fonctionné pour moi (inclut l'option de transparence):