real - matplotlib python 3
matplotlib-mapa de color blanco y negro(con guiones, puntos, etc.) (4)
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)
Respuesta extendida
Nuevas versiones de matplotlib
introdujeron un nuevo rcParams
, concretamente 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''])
Para los estilos preescabados, disponibles por plt.style.use(...)
o with plt.style.context(...):
prop_cycle
es equivalente a los axes.color_cycle
tradicionales y obsoletos.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'']
pero el objeto de cycler
tiene muchas más posibilidades, en particular, un cycler
complejo se puede componer a partir de los más simples, refiriéndose a diferentes propiedades, usando +
y *
, lo que significa, respectivamente, comprimir y producto cartesiano.
Aquí importamos la función cycler
helper, definimos 3 cycler
simples que se refieren a diferentes propiedades y finalmente los compilamos usando el producto cartesiano
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
Aquí tenemos dos cycler
complejo (?) cycler
y sí, son diferentes porque esta operación no es conmutativa, eche un vistazo
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
El ciclo elemental que cambia más rápido es el último en el producto, etc., esto es importante si queremos un cierto orden en el diseño de las líneas.
¿Cómo usar la composición de cycler
s? Por medio de plt.rc
, o una forma equivalente de modificar los rcParams
de matplotlib
. P.ej,
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();
Por supuesto, esto es solo un ejemplo, y el OP puede mezclar y combinar diferentes propiedades para lograr la salida visual más agradable.
PD. Olvidé mencionar que este enfoque se ocupa automáticamente de las muestras de línea en el cuadro de leyenda,
Estoy usando matplotlib para crear gráficos 2D. A los efectos de la publicación, me gustaría tener esas tramas en blanco y negro ( no en escala de grises), y estoy luchando por encontrar una solución no intrusiva para eso.
Gnuplot altera automáticamente los patrones de estilo para diferentes líneas, ¿es posible algo similar con matplotlib?
Cosas como la plot(x,y,''k-.'')
Producirán la línea negra ( ''k''
) punteada con puntos ( ''-.''
). ¿No es eso lo que estás buscando?
Usé mucho el código de Yann, pero hoy leo una respuesta de ¿Puedo pasar por los estilos de línea en matplotlib? Así que ahora haré mis tramas BW de esta manera:
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()
A continuación, proporciono funciones para convertir una línea de color en una línea negra con un estilo único. Mi prueba rápida mostró que después de 7 líneas, los colores se repiten. Si este no es el caso (y cometí un error), entonces se necesita un ajuste menor para el COLORMAP
"constante" en la rutina proporcionada.
Aquí está la rutina y el ejemplo:
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")
Esto proporciona los dos trazados siguientes: Primero en color: Luego en blanco y negro:
Puede ajustar cómo cada color se convierte en un estilo. Si solo quiere jugar con el estilo del tablero (-. Vs. - frente al patrón que desee), establezca el COLORMAP
''marcador'' correspondiente de COLORMAP
en None
y ajuste el patrón ''dash'', o viceversa.
Por ejemplo, el último color en el diccionario es ''k'' (para negro); originalmente solo tenía un patrón discontinuo [1,2,1,10]
, que corresponde a un píxel que se muestra, dos no, uno se muestra, 10 no, que es un patrón de espacio punto-punto. Luego comenté eso, estableciendo el guión en (Ninguno, Ninguno), una forma muy formal de decir línea continua, y agregué el marcador ''o'', para el círculo.
También configuré un MARKERSIZE "constante", que establecerá el tamaño de cada marcador, porque el tamaño predeterminado es un poco grande.
Obviamente, esto no soluciona el caso cuando sus líneas ya tienen un guion o marcador, pero puede usar estas rutinas como punto de partida para construir un convertidor más sofisticado. Por ejemplo, si su trama original tiene una línea continua roja y una línea de puntos roja, ambos se convertirán en líneas negras de puntos y rayas con estas rutinas. Algo para tener en cuenta cuando los usa.