matplotlib-colormap noir et blanc (avec des tirets, des points, etc.)
j'utilise matplotlib pour créer des tracés de ligne 2d. Pour les besoins de la publication, je voudrais avoir ces parcelles en noir et blanc ( et non ), et je me bats pour trouver une solution non-intrusive pour cela.
gnuplot modifie automatiquement les motifs fringants pour différentes lignes, est-ce que quelque chose de similaire est possible avec matplotlib?
4 réponses
ci-dessous je fournis des fonctions pour convertir une ligne de couleur à une ligne noire avec un style unique. Mon test rapide a montré qu'après 7 lignes, les couleurs répétées. Si ce n'est pas le cas (et j'ai fait une erreur), puis un ajustement mineur est nécessaire pour la "constante COLORMAP
dans la routine.
Voici la routine et l'exemple:
import matplotlib.pyplot as plt
import numpy as np
def setAxLinesBW(ax):
"""
Take each Line2D in the axes, ax, and convert the line style to be
suitable for black and white viewing.
"""
MARKERSIZE = 3
COLORMAP = {
'b': {'marker': None, 'dash': (None,None)},
'g': {'marker': None, 'dash': [5,5]},
'r': {'marker': None, 'dash': [5,3,1,3]},
'c': {'marker': None, 'dash': [1,3]},
'm': {'marker': None, 'dash': [5,2,5,2,5,10]},
'y': {'marker': None, 'dash': [5,3,1,2,1,10]},
'k': {'marker': 'o', 'dash': (None,None)} #[1,2,1,10]}
}
lines_to_adjust = ax.get_lines()
try:
lines_to_adjust += ax.get_legend().get_lines()
except AttributeError:
pass
for line in lines_to_adjust:
origColor = line.get_color()
line.set_color('black')
line.set_dashes(COLORMAP[origColor]['dash'])
line.set_marker(COLORMAP[origColor]['marker'])
line.set_markersize(MARKERSIZE)
def setFigLinesBW(fig):
"""
Take each axes in the figure, and for each line in the axes, make the
line viewable in black and white.
"""
for ax in fig.get_axes():
setAxLinesBW(ax)
xval = np.arange(100)*.01
fig = plt.figure()
ax = fig.add_subplot(211)
ax.plot(xval,np.cos(2*np.pi*xval))
ax.plot(xval,np.cos(3*np.pi*xval))
ax.plot(xval,np.cos(4*np.pi*xval))
ax.plot(xval,np.cos(5*np.pi*xval))
ax.plot(xval,np.cos(6*np.pi*xval))
ax.plot(xval,np.cos(7*np.pi*xval))
ax.plot(xval,np.cos(8*np.pi*xval))
ax = fig.add_subplot(212)
ax.plot(xval,np.cos(2*np.pi*xval))
ax.plot(xval,np.cos(3*np.pi*xval))
ax.plot(xval,np.cos(4*np.pi*xval))
ax.plot(xval,np.cos(5*np.pi*xval))
ax.plot(xval,np.cos(6*np.pi*xval))
ax.plot(xval,np.cos(7*np.pi*xval))
ax.plot(xval,np.cos(8*np.pi*xval))
fig.savefig("colorDemo.png")
setFigLinesBW(fig)
fig.savefig("bwDemo.png")
cela fournit les deux parcelles suivantes: D'abord en couleur: Puis dans noir et blanc:
vous pouvez ajuster la façon dont chaque couleur est convertie en un style. Si vous voulez seulement jouer avec le style dash ( -. vs. -- vs. whatever pattern you want), définissez la valeur COLORMAP
correspondant au "marqueur" à None
et ajustez le "dash" pattern, ou vice versa.
par exemple , la dernière couleur du dictionnaire est "k" (pour le noir); à l'origine je n'avais qu'un motif en tirets [1,2,1,10]
, correspondant à un pixel montré, deux pas, un montré, 10 pas, qui est un motif point-point-Espace. Puis j'ai commenté que dehors, mettant le tiret à (Aucun, Aucun), une manière très formelle de dire ligne solide, et ai ajouté le marqueur 'o', pour cercle.
j'ai aussi défini un MARKERSIZE 'constant', qui définira la taille de chaque marqueur, parce que j'ai trouvé que la taille par défaut est un peu grande.
cela ne gère évidemment pas le cas lorsque vos lignes ont déjà un tiret ou un marqueur patter, mais vous pouvez utiliser ces routines comme point de départ pour construire un convertisseur plus sophistiqué. Par exemple, si votre parcelle d'origine avait une ligne pleine rouge et une ligne pointillée rouge, les deux se transformeraient en lignes noires de points de tableau de bord avec ces routines. Quelque chose à garder à l'esprit lorsque vous les utilisez.
TL; DR
import matplotlib.pyplot as plt
from cycler import cycler
monochrome = (cycler('color', ['k']) * cycler('marker', ['', '.']) *
cycler('linestyle', ['-', '--', ':', '=.']))
plt.rc('axes', prop_cycle=monochrome)
réponse prolongée
le plus Récent matplotlib
versions introduit un nouveau rcParams
, à savoir axes.prop_cycle
In [1]: import matplotlib.pyplot as plt
In [2]: plt.rcParams['axes.prop_cycle']
Out[2]: cycler('color', ['b', 'g', 'r', 'c', 'm', 'y', 'k'])
pour les modèles précannés, disponibles par plt.style.use(...)
ou with plt.style.context(...):
, le prop_cycle
est équivalent au traditionnel et déprécié axes.color_cycle
In [3]: plt.rcParams['axes.color_cycle']
/.../__init__.py:892: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
warnings.warn(self.msg_depr % (key, alt_key))
Out[3]: ['b', 'g', 'r', 'c', 'm', 'y', 'k']
mais l'objet cycler
a beaucoup plus de possibilités, en particulier un complexe cycler
peut être composé de plus simples, se référant à des propriétés différentes, en utilisant +
et *
, signification respectivement fermeture éclair et produit cartésien.
ici nous importons la fonction d'aide cycler
, nous définissons 3 simple cycler
qui se réfèrent à des propriétés différentes et finalement les composent en utilisant le produit cartésien
In [4]: from cycler import cycler
In [5]: color_c = cycler('color', ['k'])
In [6]: style_c = cycler('linestyle', ['-', '--', ':', '-.'])
In [7]: markr_c = cycler('marker', ['', '.', 'o'])
In [8]: c_cms = color_c * markr_c * style_c
In [9]: c_csm = color_c * style_c * markr_c
ici nous avons deux différents(?) complexe cycler
et oui, ils sont différents parce que cette opération n'est pas commutative, avoir un look
In [10]: for d in c_csm: print('\t'.join(d[k] for k in d))
- k
- . k
- o k
-- k
-- . k
-- o k
: k
: . k
: o k
-. k
-. . k
-. o k
In [11]: for d in c_cms: print('\t'.join(d[k] for k in d))
- k
-- k
: k
-. k
- . k
-- . k
: . k
-. . k
- o k
-- o k
: o k
-. o k
le cycle élémentaire qui change plus vite est le dernier dans le produit, etc. ceci est important si nous voulons un certain ordre dans le style de lignes.
comment utiliser la composition de cycler
s? Au moyen de plt.rc
, ou d'une manière équivalente pour modifier le rcParams
de matplotlib
. E. g.,
In [12]: %matplotlib
Using matplotlib backend: Qt4Agg
In [13]: import numpy as np
In [14]: x = np.linspace(0, 8, 101)
In [15]: y = np.cos(np.arange(7)+x[:,None])
In [16]: plt.rc('axes', prop_cycle=c_cms)
In [17]: plt.plot(x, y);
In [18]: plt.grid();
bien sûr, ce n'est qu'un exemple, et L'OP peut mélanger et assortir différentes propriétés pour obtenir le résultat visuel le plus agréable.
PS j'ai oublié de mentionner que cette approche s'occupe automatiquement des échantillons de ligne dans la boîte de légende,
j'ai beaucoup utilisé le code de Yann, mais aujourd'hui, j'ai lu une réponse de puis-je cycle à travers les styles de ligne dans matplotlib donc maintenant, je vais faire mes parcelles de BW de cette façon:
import pylab as plt
from itertools import cycle
lines = ["k-","k--","k-.","k:"]
linecycler = cycle(lines)
plt.figure()
for i in range(4):
x = range(i,i+10)
plt.plot(range(10),x,next(linecycler))
plt.show()
des choses comme plot(x,y,'k-.')
produiront la ligne noire ( 'k'
) pointillée ( '-.'
). N'est-ce pas ce que vous cherchez?