获取matplotlib颜色循环状态

有没有可能查询matplotlib颜色循环的当前状态? 换句话说,是否有一个函数get_cycle_state将以下列方式performance?

 >>> plot(x1, y1) >>> plot(x2, y2) >>> state = get_cycle_state() >>> print state 2 

在那里,我期望的状态是下一个将用于阴谋的颜色的指标。 或者,如果它返回下一个颜色(上面例子中的默认循环“r”),那也可以。

访问颜色循环迭代器

没有“面向用户”(又名“public”)方法来访问底层迭代器,但是你可以通过“私有”(惯例)方法来访问它。 但是,如果不更改它,你将无法获得iterator的状态。

设置颜色循环

快速放在一边:您可以通过多种方式设置颜色/属性周期(例如,版本<1.5的ax.set_prop_cycler或> = 1.5的ax.set_prop_cycler )。 看看1.5版本或更高版本的例子 ,或者这里的上一个样式 。

访问基础迭代器

但是,虽然没有公开的方法来访问迭代,但您可以通过_get_lines helper类实例访问给定的轴对象( ax )。 ax._get_lines是一个容易混淆的名字,但它是幕后机制,允许plot指挥处理所有可以调用plot的奇怪而多样的方式。 除此之外,它跟踪什么颜色自动分配。 同样,有ax._get_patches_for_fill来控制通过默认填充颜色和补丁属性的循环。

无论如何,迭代的颜色循环是ax._get_patches_for_fill.color_cycle ,补丁是ax._get_lines.color_cycle 。 在matplotlib> = 1.5上,这已经改变为使用cycler库 ,迭代器被称为prop_cycler而不是color_cycle并产生一个属性dict ,而不是一个颜色。

总而言之,你会做这样的事情:

 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) ,但这意味着之后的下一个颜色将被绘制出来。通过devise,没有办法获得迭代器的当前状态而不改变它。

v1.5或更高版本中,获取使用的cycler对象将是很好的,因为我们可以推断它的当前状态。 然而, cycler对象本身不能在任何地方(公共或私人)访问。 相反,只有从itertools.cycle对象创build的itertools.cycle实例是可访问的。 无论哪种方式,都无法达到颜色/属性循环仪的基本状态。

匹配先前绘制的项目的颜色

在你的情况下,这听起来像你想要匹配刚刚绘制的东西的颜色。 不要尝试确定颜色/属性是什么,根据绘制的属性设置新项目的颜色等。

例如,在你描述的情况下,我会做这样的事情:

 import matplotlib.pyplot as plt import numpy as np def custom_plot(x, y, **kwargs): ax = kwargs.pop('ax', plt.gca()) base_line, = ax.plot(x, y, **kwargs) ax.fill_between(x, 0.9*y, 1.1*y, facecolor=base_line.get_color(), alpha=0.5) x = np.linspace(0, 1, 10) custom_plot(x, x) custom_plot(x, 2*x) custom_plot(x, -x, color='yellow', lw=3) plt.show() 

在这里输入图像说明

这并不是唯一的方法,但是在这种情况下,它要比事先弄清绘制线的颜色更清洁。

注意:在最新版本的matplotlib(> = 1.5)中_get_lines已经改变。 您现在需要使用Python 2或Python 3中的next(ax._get_lines.prop_cycler)['color'] (或Python 2中的ax._get_lines.prop_cycler.next()['color'] )来获取下一个颜色颜色循环。

尽可能使用@ joe-kington答案下半部分显示的更直接的方法。 由于_get_lines不是面向API的,它将来可能会以不兼容的方式再次改变。

当然,这将做到这一点。

 #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> rcmykbgrcm 

这里是matplotlib使用itertools.cycle的itertools函数

编辑:感谢评论,似乎是不可能复制一个迭代器。 一个想法是转储一个完整的周期,并跟踪你正在使用的价值,让我回到这一点。

编辑2:好吧,这将给你下一个颜色,并使一个新的迭代器,就好像next未被调用。 这不保留着色的顺序,只是下一个颜色值,我把它留给你。

这给出以下输出,注意图中的陡度对应于索引,例如,第一个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 

旋转颜色

这里有一个在1.5中工作的方式,这将有望成为未来的保证,因为它不依赖于下划线前面的方法:

 colors = plt.rcParams["axes.prop_cycle"].by_key()["color"] 

这将给你一个为目前的风格定义的颜色列表。

我只是想补充@Andi上面所说的。 由于color_cycle在matplotlib 1.5中被弃用,所以你必须使用prop_cycler ,然而,Andi的解决scheme( ax._get_lines.prop_cycler.next()['color'] )为我返回了这个错误:

AttributeError:'itertools.cycle'对象没有属性'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 <1.5:

 >>> list_from_cycle(ax._get_lines.color_cycle) ['r', 'g', 'b']