Question

J'utilise matplotlib pour créer une ligne-parcelles 2d. Aux fins de la publication, je voudrais avoir ces parcelles en noir et blanc ( pas en niveaux de gris), et je me bats pour trouver une solution non intrusive pour cela.

Gnuplot automatiquement modifie fringant modèles pour des lignes différentes, est quelque chose de similaire possible avec matplotlib?

Était-ce utile?

La solution

Ci-dessous je fournir des fonctions pour convertir une ligne de couleur à une ligne noire avec un style unique. Mon test rapide a montré que, après 7 lignes, les couleurs répétées. Si ce n'est pas le cas (et je fait une erreur), puis un ajustement mineur est nécessaire pour la COLORMAP « constante » dans la routine prévue.

Voici la routine et par 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 donne les deux parcelles suivantes: Tout d'abord en couleur: entrer dans la description d'image ici Puis, en noir et blanc: entrer image description ici

Vous pouvez régler la façon dont chaque couleur est converti en un style. Si vous voulez juste jouer uniquement avec le style de tiret (-. Contre - par rapport à ce que modèle que vous voulez), définissez la valeur COLORMAP « marqueur » correspondant à None et ajusté le modèle « tableau de bord », ou vice versa.

Par exemple, la dernière couleur dans le dictionnaire est « k » (pour le noir); l'origine I eu seulement un motif en pointillé [1,2,1,10], correspondant à un pixel représenté, deux pas, un seul est représenté, 10 pas, qui est un modèle d'espace de point-point. Ensuite, je commentais que sur, le réglage du tableau de bord à (None, None), d'une manière très formelle de dire la ligne solide, et a ajouté le marqueur « o », pour le cercle.

J'ai aussi mis une « constante » MARKERSIZE, qui fixera la taille de chaque marqueur, parce que je trouvais la taille par défaut d'être un peu grand.

Cela ne signifie évidemment pas manipuler le cas lorsque vos lignes ont déjà un boniment tableau de bord ou d'un marqueur, mais vous pouvez utiliser ces routines comme point de départ pour construire un convertisseur plus sophistiqué. Par exemple, si vous intrigue originale avait une ligne rouge solide et une ligne en pointillé rouge, ils ont tous deux se transformer en lignes au tableau de bord points noirs avec ces routines. Quelque chose à garder à l'esprit lorsque vous les utilisez.

Autres conseils

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

Les nouvelles versions de matplotlib a introduit une nouvelle 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 styles prédéfinis, disponibles par plt.style.use(...) ou with plt.style.context(...):, l'prop_cycle est équivalente à la traditionnelle et désapprouvée 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, notamment un cycler complexe peut être composé de plus simples, se référant à des propriétés différentes, en utilisant + et *, ce qui signifie respectivement passer comme un éclair et produit cartésien.

Ici, nous importons la fonction d'aide de cycler, nous définissons 3 cycler simple qui se réfèrent à des propriétés différentes et enfin 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 (?) cycler complexe et oui, ils sont différents parce que cette opération est non-commutative, consultez

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 que des changements plus rapides est le dernier dans le produit, etc., ce qui est important si nous voulons un certain ordre dans le style des lignes.

Comment utiliser la composition de cyclers? A l'aide d'plt.rc, ou un moyen équivalent pour modifier la rcParams de matplotlib. Par exemple.

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();

 entrer image description ici

Bien sûr, cela est juste un exemple, et l'OP peut mélanger et faire correspondre des propriétés différentes pour atteindre le plus agréable sortie visuelle.

PS j'ai oublié de mentionner que cette approche prend automatiquement en charge des échantillons de ligne dans la zone de légende, entrer la description d'image ici

Je fortement fait le code d'utilisation Yann, mais aujourd'hui je l'ai lu une réponse de Puis-je faire défiler les styles de ligne dans matplotlib Alors maintenant, je vais faire mes parcelles BW ainsi:

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-.') produira la ligne de points-tirets noirs ('k') ('-.'). Est-ce pas ce que vous une recherche?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top