Получить состояние цветового цикла 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и получаетсяdictof свойства, а не только цвет.в общем, вы бы сделали что-то вроде:
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']
