Matplotlib - черно -белая долька (с приемами, точками и т. Д.)
-
28-10-2019 - |
Вопрос
Я использую Matplotlib для создания 2D-линейных участков. Для целей публикации я хотел бы иметь эти сюжеты в черно -белом (нет Greyscale), и я изо всех сил пытаюсь найти для этого ненавязчивое решение.
GNUPLOT автоматически изменяет литронные шаблоны для разных линий, является ли возможным что -то сходное с Matplotlib?
Решение
Ниже я предоставляю функции для преобразования цветной линии в черную линию с уникальным стилем. Мой быстрый тест показал, что после 7 линий цвета повторялись. Если это не так (и я допустил ошибку), то для «постоянной» необходима незначительная корректировка COLORMAP
в предоставленной рутине.
Вот рутина и пример:
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")
Это обеспечивает следующие два сюжета: первый цвет:Затем в черно -белом:
Вы можете настроить, как каждый цвет преобразуется в стиль. Если вы просто хотите играть только в стиле приборной COLORMAP
соответствующее значение «маркерного» None
и отрегулировал рисунок «приборной», или наоборот.
Например, последний цвет в словаре - «k» (для черного); Первоначально у меня был только пунктир [1,2,1,10]
, соответствует одному показанному пикселю, два нет, один показан, 10 не, что представляет собой паттерн Dot-Dot. Затем я прокомментировал это, установив приборную черту (нет, нет), очень формальный способ сказать сплошной линии и добавил маркер «О» для Circle.
Я также установил «постоянный» маркеры, который установит размер каждого маркера, потому что я обнаружил, что размер по умолчанию немного большим.
Это, очевидно, не обрабатывает случай, когда ваши линии уже имеют паттерну или маркер, но вы можете использовать эти подпрограммы в качестве отправной точки для создания более сложного преобразователя. Например, если у вашего оригинального сюжета была красная сплошная линия и красная пунктирная линия, они оба превращались в черные линии Dash-Dot с этими процедурами. Что -то нужно иметь в виду, когда вы их используете.
Другие советы
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)
Расширенный ответ
Новее matplotlib
Выпуски представили новый rcParams
, а именно 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'])
Для предварительных стилей, доступных plt.style.use(...)
или же with plt.style.context(...):
, prop_cycle
эквивалентен традиционным и устарел 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']
но cycler
У объекта есть гораздо больше возможностей, в частности, сложный cycler
может быть составлен из более простых, ссылаясь на разные свойства, используя +
а также *
, Значение соответственно на молнии и картезианском продукте.
Здесь мы импортируем cycler
вспомогательная функция, мы определяем 3 простых cycler
Это относится к различным свойствам и, наконец, сочиняет их с использованием декартового продукта
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
Здесь у нас есть два разных (?) Сложных cycler
И да, они разные, потому что эта операция не общательна, посмотрите
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
Элементный цикл, который изменяется быстрее, является последним в продукте и т. Д., Это важно, если мы хотим определенный порядок в стиле линий.
Как использовать композицию cycler
s? С помощью plt.rc
, или эквивалентный способ изменить rcParams
из matplotlib
. Анкет Например,
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();
Конечно, это всего лишь пример, и OP может смешивать и соответствовать различным свойствам для достижения наиболее приятного визуального вывода.
PS Я забыл упомянуть, что этот подход автоматически заботится о образцах линий в коробке легенды,
Я сильно использовал код Янна, но сегодня я прочитал ответ из Могу ли я проходить через стили линий в matplotlib Итак, теперь я сделаю свои сюжеты BW таким образом:
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()
Вещи как plot(x,y,'k-.')
будет производить черный ('k'
) DOT-избитый ('-.'
) линия. Разве это не то, что вы ищете?