python - Cycle colors when plotting in matplotlib: Tracking state on a per-instance basis -


i'm trying build simple state-tracking function axes instance in matplotlib. every time create new axes object (either directly or through other functions subplots()), want instance have bound method, a.next_color(), can use cycle through colors create new lines add axes. wrote this:

def set_color_sequence(colors = ['r', 'g', 'b', 'c', 'm', 'y']):     = [0]     def cf(self):         i[0] += 1         return colors[(i[0]-1) % len(colors)]     return cf 

and thought being clever adding parent class:

plt.axes.next_color = set_color_sequence() 

the problem state variable i seems shared all axes instances, instead of each new instance having own state. what's elegant way ensure new instances have own state tracking function? (btw, i'd without modifying original matplotlib code.)

your existing function will work provided assign next_color attribute instance of axes rather class itself.

first of all, set_color_sequence implementing generator in roundabout way. simplify things, can achieve same thing in 1 line using itertools.cycle:

from itertools import cycle ... axes_instance.next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y']).next 

in fact, way matplotlib keeps track of in color cycle. example, if take @ instance of matplotlib.axes._subplots.axessubplot see has attribute _get_lines.color_cycle, itertools.cycle (try calling color_cycle.next()).

now take @ these 2 examples:

class myclass1(object):      # next_color attribute of *class itself*     next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y']).next   class myclass2(object):      def __init__(self):          # next_color attribute of *this instance* of class         self.next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y']).next 

in first case, happens assignment

next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y]).next 

gets evaluated once , once, when class first imported. means whenever create new instance of myclass1, next_color attribute point @ exact same itertools.cycle instance, , therefore instances of myclass1 share common state:

a = myclass1() b = myclass1()  print a.next_color b.next_color # true  print a.next_color(), a.next_color(), b.next_color() #  r g b 

however, __init__ method gets called again , again whenever new instance of class being created. consequence, every instance of myclass2 gets own itertools.cycle, , therefore own state:

a = myclass2() b = myclass2()  print a.next_color b.next_color # false  print a.next_color(), a.next_color(), b.next_color() # r g r 

if goal subclass plt.axes, need put assignment somewhere called each new instance of subclass (probably in __init__). however, if want add method existing instance literally need is:

axes_instance.next_color = get_color_sequence() 

Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -