Получить состояние цветового цикла matplotlib
можно ли запросить текущее состояние цветового цикла matplotlib? Другими словами есть ли функция get_cycle_state
что будет вести себя следующим образом?
>>> plot(x1, y1)
>>> plot(x2, y2)
>>> state = get_cycle_state()
>>> print state
2
где я ожидаю, что состояние будет индексом следующего цвета, который будет использоваться в графике. Кроме того, если он вернул следующий цвет ("r" для цикла по умолчанию в приведенном выше примере), это тоже было бы хорошо.
6 ответов:
доступ к итератору цветового цикла
для доступа к базовому итератору нет метода" user-facing "(он же" public"), но вы можете получить к нему доступ через" частные " (по соглашению) методы. Однако, вы не можете получить состояние
iterator
без изменения.настройка цветового цикла
Quick aside: вы можете установить цикл цвета/свойства различными способами (например,
ax.set_color_cycle
в версии ax.set_prop_cycler in > =1.5). Взгляните на пример для версии 1.5 или выше или предыдущий стиль здесь.доступ к базовому итератор
однако, хотя нет открытого метода для доступа к iterable, вы можете получить доступ к нему для данного объекта axes (
ax
) через_get_lines
экземпляр вспомогательного класса.ax._get_lines
это прикосновение смутно названо, но это закулисный механизм, который позволяетplot
команда для обработки всех нечетных и разнообразных способы, которыеplot
можно назвать. Среди прочего, это то, что отслеживает, какие цвета автоматически назначать. Точно так же естьax._get_patches_for_fill
для управления циклическим использованием цветов заливки по умолчанию и свойств патча.во всяком случае, цикл цвета iterable
ax._get_lines.color_cycle
для строк иax._get_patches_for_fill.color_cycle
для исправления. На matplotlib >=1.5, это изменилось на использоватьcycler
библиотека, и iterable называетсяprop_cycler
вместоcolor_cycle
и получаетсяdict
of свойства, а не только цвет.в общем, вы бы сделали что-то вроде:
import matplotlib.pyplot as plt fig, ax = plt.subplots() color_cycle = ax._get_lines.color_cycle # or ax._get_lines.prop_cycler on version >= 1.5 # Note that prop_cycler cycles over dicts, so you'll want next(cycle)['color']
вы не можете просмотреть состояние
iterator
однако этот объект является "голым"
iterator
. Мы можем легко получить следующий элемент (например,next_color = next(color_cycle)
, но это значит, что следующий цвет после этого это то, что будет нанесено на график. По замыслу, нет никакого способа получить текущее состояние итератора без его изменения.на
v1.5
или выше было бы неплохо получитьcycler
объект, который используется, как мы могли бы сделать вывод о его текущем состоянии. Тем не менее,cycler
сам объект не доступен (публично или в частном порядке) в любом месте. Вместо этого, толькоitertools.cycle
экземпляр, созданный из
Примечание: В последних версиях matplotlib (>=1.5)
_get_lines
изменилось. Теперь вам нужно использоватьnext(ax._get_lines.prop_cycler)['color']
в Python 2 или 3 (илиax._get_lines.prop_cycler.next()['color']
на Python 2), чтобы получить следующий цвет из цветовой цикл.везде, где это возможно, используйте более прямой подход, показанный в нижней части ответа @joe-kington. Как
_get_lines
не API-облицовка это может измениться снова в не обратно совместимым образом в будущем.
вот способ, который работает в 1.5, который, надеюсь, будет в будущем, поскольку он не зависит от методов, добавленных с подчеркиванием:
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
Это даст вам список цветов, определенных для настоящего стиля.
конечно, это сделает это.
#rainbow import matplotlib.pyplot as plt import numpy as np x = np.linspace(0,2*np.pi) ax= plt.subplot(1,1,1) ax.plot(np.sin(x)) ax.plot(np.cos(x)) rainbow = ax._get_lines.color_cycle print rainbow for i, color in enumerate(rainbow): if i<10: print color,
выдает:
<itertools.cycle object at 0x034CB288> r c m y k b g r c m
вот функция itertools, которую использует matplotlib itertools.цикл
Edit: Спасибо за комментарий, кажется, что невозможно скопировать итератор. Идея состояла бы в том, чтобы сбросить полный цикл и отслеживать, какое значение вы используете, позвольте мне вернуться к этому.
Edit2: хорошо, это даст вам следующий цвет и сделает новый итератор, который ведет себя так, как будто дальше не назывался. Это не сохраняет порядок окраски, просто следующее значение цвета, я оставляю это вам.
это дает следующий вывод, обратите внимание, что крутизна в графике соответствует индексу, например, первый g является самым нижним графом и так далее.
#rainbow import matplotlib.pyplot as plt import numpy as np import collections import itertools x = np.linspace(0,2*np.pi) ax= plt.subplot(1,1,1) def create_rainbow(): rainbow = [ax._get_lines.color_cycle.next()] while True: nextval = ax._get_lines.color_cycle.next() if nextval not in rainbow: rainbow.append(nextval) else: return rainbow def next_color(axis_handle=ax): rainbow = create_rainbow() double_rainbow = collections.deque(rainbow) nextval = ax._get_lines.color_cycle.next() double_rainbow.rotate(-1) return nextval, itertools.cycle(double_rainbow) for i in range(1,10): nextval, ax._get_lines.color_cycle = next_color(ax) print "Next color is: ", nextval ax.plot(i*(x)) plt.savefig("SO_rotate_color.png") plt.show()
консоль
Next color is: g Next color is: c Next color is: y Next color is: b Next color is: r Next color is: m Next color is: k Next color is: g Next color is: c
Я просто хочу добавить к тому, что @Andi сказал выше. Так как
color_cycle
является устаревшим в matplotlib 1.5, вы должны использоватьprop_cycler
, однако, решение Анди (ax._get_lines.prop_cycler.next()['color']
) вернул эту ошибку для меня:AttributeError: 'itertools.цикл 'объект не имеет атрибута 'next'
код, который работал для меня было:
next(ax._get_lines.prop_cycler)
, что на самом деле не так далеко от первоначального ответа @joe-kington.лично я столкнулся с этой проблемой при оформлении ось twinx (), которая сбрасывает цветовой Циклер. Мне нужен был способ сделать цикл цветов правильно, потому что я использовал
style.use('ggplot')
. Там может быть проще/лучше способ сделать это, так что не стесняйтесь, чтобы исправить меня.
так как matplotlib использует
itertools.cycle
мы можем фактически просмотреть весь цветовой цикл, а затем восстановить итератор в его предыдущее состояние:def list_from_cycle(cycle): first = next(cycle) result = [first] for current in cycle: if current == first: break result.append(current) # Reset iterator state: for current in cycle: if current == result[-1]: break return result
это должно вернуть список без изменения состояния итератора.
используйте его с matplotlib > = 1.5:
>>> list_from_cycle(ax._get_lines.prop_cycler) [{'color': 'r'}, {'color': 'g'}, {'color': 'b'}]
или с matplotlib
>>> list_from_cycle(ax._get_lines.color_cycle) ['r', 'g', 'b']