Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite524354

Browse files
committed
API/ENH: Color cycle handling
API/ENH: Color cycle handling
1 parent9f83d53 commite524354

File tree

11 files changed

+152
-52
lines changed

11 files changed

+152
-52
lines changed

‎examples/pylab_examples/color_demo.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
"""
3-
matplotlib gives you4 ways to specify colors,
3+
matplotlib gives you5 ways to specify colors,
44
55
1) as a single letter string, ala MATLAB
66
@@ -11,6 +11,9 @@
1111
4) as a string representing a floating point number
1212
from 0 to 1, corresponding to shades of gray.
1313
14+
5) as a special color "Cn", where n is a number 0-9 specifying the
15+
nth color in the currently active color cycle.
16+
1417
See help(colors) for more info.
1518
"""
1619
importmatplotlib.pyplotasplt
@@ -20,8 +23,8 @@
2023
#subplot(111, facecolor='#ababab')
2124
t=np.arange(0.0,2.0,0.01)
2225
s=np.sin(2*np.pi*t)
23-
plt.plot(t,s,'y')
24-
plt.xlabel('time (s)',color='r')
26+
plt.plot(t,s,'C1')
27+
plt.xlabel('time (s)',color='C1')
2528
plt.ylabel('voltage (mV)',color='0.5')# grayscale color
2629
plt.title('About as silly as it gets, folks',color='#afeeee')
2730
plt.show()

‎lib/matplotlib/axes/_axes.py

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
frommatplotlib.externalsimportsix
55
frommatplotlib.externals.six.movesimportreduce,xrange,zip,zip_longest
66

7+
importitertools
78
importmath
89
importwarnings
910

@@ -2457,7 +2458,7 @@ def pie(self, x, explode=None, labels=None, colors=None,
24572458
Call signature::
24582459
24592460
pie(x, explode=None, labels=None,
2460-
colors=('b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'),
2461+
colors=None,
24612462
autopct=None, pctdistance=0.6, shadow=False,
24622463
labeldistance=1.1, startangle=None, radius=None,
24632464
counterclock=True, wedgeprops=None, textprops=None,
@@ -2477,7 +2478,8 @@ def pie(self, x, explode=None, labels=None, colors=None,
24772478
24782479
*colors*: [ *None* | color sequence ]
24792480
A sequence of matplotlib color args through which the pie chart
2480-
will cycle.
2481+
will cycle. If `None`, will use the colors in the currently
2482+
active cycle.
24812483
24822484
*labels*: [ *None* | len(x) sequence of strings ]
24832485
A sequence of strings providing the labels for each wedge
@@ -2566,7 +2568,12 @@ def pie(self, x, explode=None, labels=None, colors=None,
25662568
iflen(x)!=len(explode):
25672569
raiseValueError("'explode' must be of length 'x'")
25682570
ifcolorsisNone:
2569-
colors= ('b','g','r','c','m','y','k','w')
2571+
get_next_color=self._get_patches_for_fill.get_next_color
2572+
else:
2573+
color_cycle=itertools.cycle(colors)
2574+
2575+
defget_next_color():
2576+
returnsix.next(color_cycle)
25702577

25712578
ifradiusisNone:
25722579
radius=1
@@ -2602,7 +2609,7 @@ def pie(self, x, explode=None, labels=None, colors=None,
26022609

26032610
w=mpatches.Wedge((x,y),radius,360.*min(theta1,theta2),
26042611
360.*max(theta1,theta2),
2605-
facecolor=colors[i%len(colors)],
2612+
facecolor=get_next_color(),
26062613
**wedgeprops)
26072614
slices.append(w)
26082615
self.add_patch(w)
@@ -3022,8 +3029,8 @@ def xywhere(xs, ys, mask):
30223029
l0,=self.plot(x,y,fmt,label='_nolegend_',**kwargs)
30233030

30243031
ifecolorisNone:
3025-
ifl0isNoneand'color'inself._get_lines._prop_keys:
3026-
ecolor=next(self._get_lines.prop_cycler)['color']
3032+
ifl0isNone:
3033+
ecolor=self._get_lines.get_next_color()
30273034
else:
30283035
ecolor=l0.get_color()
30293036

@@ -3844,7 +3851,10 @@ def scatter(self, x, y, s=None, c=None, marker='o', cmap=None, norm=None,
38443851
iffacecolorsisnotNone:
38453852
c=facecolors
38463853
else:
3847-
c='b'# The original default
3854+
ifrcParams['_internal.classic_mode']:
3855+
c='b'# The original default
3856+
else:
3857+
c=self._get_patches_for_fill.get_next_color()
38483858

38493859
ifedgecolorsisNoneandnotrcParams['_internal.classic_mode']:
38503860
edgecolors='face'
@@ -6015,9 +6025,8 @@ def _normalize_input(inp, ename='input'):
60156025
raiseValueError(
60166026
'weights should have the same shape as x')
60176027

6018-
ifcolorisNoneand'color'inself._get_lines._prop_keys:
6019-
color= [next(self._get_lines.prop_cycler)['color']
6020-
foriinxrange(nx)]
6028+
ifcolorisNone:
6029+
color= [self._get_lines.get_next_color()foriinxrange(nx)]
60216030
else:
60226031
color=mcolors.colorConverter.to_rgba_array(color)
60236032
iflen(color)!=nx:
@@ -7503,6 +7512,12 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
75037512
perp_lines=self.vlines
75047513
par_lines=self.hlines
75057514

7515+
ifrcParams['_internal.classic_mode']:
7516+
fillcolor='y'
7517+
edgecolor='r'
7518+
else:
7519+
fillcolor=edgecolor=self._get_lines.get_next_color()
7520+
75067521
# Render violins
75077522
bodies= []
75087523
forstats,pos,widthinzip(vpstats,positions,widths):
@@ -7513,7 +7528,7 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
75137528
bodies+= [fill(stats['coords'],
75147529
-vals+pos,
75157530
vals+pos,
7516-
facecolor='y',
7531+
facecolor=fillcolor,
75177532
alpha=0.3)]
75187533
means.append(stats['mean'])
75197534
mins.append(stats['min'])
@@ -7523,20 +7538,24 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
75237538

75247539
# Render means
75257540
ifshowmeans:
7526-
artists['cmeans']=perp_lines(means,pmins,pmaxes,colors='r')
7541+
artists['cmeans']=perp_lines(means,pmins,pmaxes,
7542+
colors=edgecolor)
75277543

75287544
# Render extrema
75297545
ifshowextrema:
7530-
artists['cmaxes']=perp_lines(maxes,pmins,pmaxes,colors='r')
7531-
artists['cmins']=perp_lines(mins,pmins,pmaxes,colors='r')
7532-
artists['cbars']=par_lines(positions,mins,maxes,colors='r')
7546+
artists['cmaxes']=perp_lines(maxes,pmins,pmaxes,
7547+
colors=edgecolor)
7548+
artists['cmins']=perp_lines(mins,pmins,pmaxes,
7549+
colors=edgecolor)
7550+
artists['cbars']=par_lines(positions,mins,maxes,
7551+
colors=edgecolor)
75337552

75347553
# Render medians
75357554
ifshowmedians:
75367555
artists['cmedians']=perp_lines(medians,
75377556
pmins,
75387557
pmaxes,
7539-
colors='r')
7558+
colors=edgecolor)
75407559

75417560
returnartists
75427561

‎lib/matplotlib/axes/_base.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def _process_plot_format(fmt):
5252
* 'ko': black circles
5353
* '.b': blue dots
5454
* 'r--': red dashed lines
55+
* 'C2--': the third color in the color cycle, dashed lines
5556
5657
.. seealso::
5758
@@ -97,7 +98,9 @@ def _process_plot_format(fmt):
9798

9899
chars= [cforcinfmt]
99100

100-
forcinchars:
101+
i=0
102+
whilei<len(chars):
103+
c=chars[i]
101104
ifcinmlines.lineStyles:
102105
iflinestyleisnotNone:
103106
raiseValueError(
@@ -113,9 +116,14 @@ def _process_plot_format(fmt):
113116
raiseValueError(
114117
'Illegal format string "%s"; two color symbols'%fmt)
115118
color=c
119+
elifc=='C'andi<len(chars)-1:
120+
color_cycle_number=int(chars[i+1])
121+
color=mcolors.colorConverter._get_nth_color(color_cycle_number)
122+
i+=1
116123
else:
117124
raiseValueError(
118125
'Unrecognized character %c in format string'%c)
126+
i+=1
119127

120128
iflinestyleisNoneandmarkerisNone:
121129
linestyle=rcParams['lines.linestyle']
@@ -161,6 +169,10 @@ def set_prop_cycle(self, *args, **kwargs):
161169
else:
162170
prop_cycler=cycler(*args,**kwargs)
163171

172+
# Make sure the cycler always has at least one color
173+
if'color'notinprop_cycler.keys:
174+
prop_cycler=prop_cycler*cycler('color', ['k'])
175+
164176
self.prop_cycler=itertools.cycle(prop_cycler)
165177
# This should make a copy
166178
self._prop_keys=prop_cycler.keys
@@ -186,6 +198,12 @@ def __call__(self, *args, **kwargs):
186198
ret=self._grab_next_args(*args,**kwargs)
187199
returnret
188200

201+
defget_next_color(self):
202+
"""
203+
Return the next color in the cycle.
204+
"""
205+
returnsix.next(self.prop_cycler)['color']
206+
189207
defset_lineprops(self,line,**kwargs):
190208
assertself.command=='plot','set_lineprops only works with "plot"'
191209
line.set(**kwargs)

‎lib/matplotlib/colors.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
- k: black
3232
- w: white
3333
34+
To use the colors that are part of the active color cycle in the current style,
35+
use `C` followed by a digit. For example:
36+
37+
- `C0`: The first color in the cycle
38+
- `C1`: The second color in the cycle
39+
3440
Gray shades can be given as a string encoding a float in the 0-1 range, e.g.::
3541
3642
color = '0.75'
@@ -67,6 +73,19 @@
6773

6874
defis_color_like(c):
6975
'Return *True* if *c* can be converted to *RGB*'
76+
77+
# Special-case the N-th color cycle syntax, because its parsing
78+
# needs to be deferred. We may be reading a value from rcParams
79+
# here before the color_cycle rcParam has been parsed.
80+
ifisinstance(c,bytes):
81+
match=re.match(b'^C[0-9]$',c)
82+
ifmatchisnotNone:
83+
returnTrue
84+
elifisinstance(c,six.text_type):
85+
match=re.match('^C[0-9]$',c)
86+
ifmatchisnotNone:
87+
returnTrue
88+
7089
try:
7190
colorConverter.to_rgb(c)
7291
returnTrue
@@ -114,9 +133,36 @@ class ColorConverter(object):
114133
'k': (0,0,0),
115134
'w': (1,1,1)}
116135

136+
_prop_cycler=None
137+
117138
cache= {}
118139
CN_LOOKUPS= [COLOR_NAMES[k]forkin ['css4','xkcd']]
119140

141+
@classmethod
142+
def_get_nth_color(cls,val):
143+
"""
144+
Get the Nth color in the current color cycle. If N is greater
145+
than the number of colors in the cycle, it is wrapped around.
146+
"""
147+
frommatplotlib.rcsetupimportcycler
148+
frommatplotlibimportrcParams
149+
150+
prop_cycler=rcParams['axes.prop_cycle']
151+
ifprop_cyclerisNoneand'axes.color_cycle'inrcParams:
152+
clist=rcParams['axes.color_cycle']
153+
prop_cycler=cycler('color',clist)
154+
155+
colors=prop_cycler._transpose()['color']
156+
returncolors[val%len(colors)]
157+
158+
@classmethod
159+
def_parse_nth_color(cls,val):
160+
match=re.match('^C[0-9]$',val)
161+
ifmatchisnotNone:
162+
returncls._get_nth_color(int(val[1]))
163+
164+
raiseValueError("Not a color cycle color")
165+
120166
defto_rgb(self,arg):
121167
"""
122168
Returns an *RGB* tuple of three floats from 0-1.
@@ -154,6 +200,10 @@ def to_rgb(self, arg):
154200
argl=arg.lower()
155201
color=self.colors.get(argl,None)
156202
ifcolorisNone:
203+
try:
204+
argl=self._parse_nth_color(arg)
205+
exceptValueError:
206+
pass
157207
forcmappinginself.CN_LOOKUPS:
158208
str1=cmapping.get(argl,argl)
159209
ifstr1!=argl:

‎lib/matplotlib/rcsetup.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ def validate_hist_bins(s):
852852
# line props
853853
'lines.linewidth': [1.5,validate_float],# line width in points
854854
'lines.linestyle': ['-',six.text_type],# solid line
855-
'lines.color': ['b',validate_color],#blue
855+
'lines.color': ['C0',validate_color],#first color in color cycle
856856
'lines.marker': ['None',six.text_type],# black
857857
'lines.markeredgewidth': [1.0,validate_float],
858858
'lines.markersize': [6,validate_float],# markersize, in points
@@ -871,7 +871,7 @@ def validate_hist_bins(s):
871871
## patch props
872872
'patch.linewidth': [None,validate_float_or_None],# line width in points
873873
'patch.edgecolor': ['k',validate_color],# black
874-
'patch.facecolor': ['#1f77b4',validate_color],#blue (first color in color cycle)
874+
'patch.facecolor': ['C0',validate_color],# first color in color cycle
875875
'patch.antialiased': [True,validate_bool],# antialiased (no jaggies)
876876

877877
## hatch props
@@ -892,27 +892,27 @@ def validate_hist_bins(s):
892892
'boxplot.showfliers': [True,validate_bool],
893893
'boxplot.meanline': [False,validate_bool],
894894

895-
'boxplot.flierprops.color': ['b',validate_color],
895+
'boxplot.flierprops.color': ['C0',validate_color],
896896
'boxplot.flierprops.marker': ['+',six.text_type],
897897
'boxplot.flierprops.markerfacecolor': ['auto',validate_color_or_auto],
898898
'boxplot.flierprops.markeredgecolor': ['k',validate_color],
899899
'boxplot.flierprops.markersize': [6,validate_float],
900900
'boxplot.flierprops.linestyle': ['none',six.text_type],
901901
'boxplot.flierprops.linewidth': [1.0,validate_float],
902902

903-
'boxplot.boxprops.color': ['b',validate_color],
903+
'boxplot.boxprops.color': ['C0',validate_color],
904904
'boxplot.boxprops.linewidth': [1.0,validate_float],
905905
'boxplot.boxprops.linestyle': ['-',six.text_type],
906906

907-
'boxplot.whiskerprops.color': ['b',validate_color],
907+
'boxplot.whiskerprops.color': ['C0',validate_color],
908908
'boxplot.whiskerprops.linewidth': [1.0,validate_float],
909909
'boxplot.whiskerprops.linestyle': ['--',six.text_type],
910910

911911
'boxplot.capprops.color': ['k',validate_color],
912912
'boxplot.capprops.linewidth': [1.0,validate_float],
913913
'boxplot.capprops.linestyle': ['-',six.text_type],
914914

915-
'boxplot.medianprops.color': ['r',validate_color],
915+
'boxplot.medianprops.color': ['C1',validate_color],
916916
'boxplot.medianprops.linewidth': [1.0,validate_float],
917917
'boxplot.medianprops.linestyle': ['-',six.text_type],
918918

@@ -1023,7 +1023,10 @@ def validate_hist_bins(s):
10231023
'axes.formatter.use_mathtext': [False,validate_bool],
10241024
'axes.formatter.useoffset': [True,validate_bool],
10251025
'axes.unicode_minus': [True,validate_bool],
1026-
'axes.color_cycle': [['b','g','r','c','m','y','k'],
1026+
'axes.color_cycle': [
1027+
['#1f77b4','#ff7f0e','#2ca02c','#d62728',
1028+
'#9467bd','#8c564b','#e377c2','#7f7f7f',
1029+
'#bcbd22','#17becf'],
10271030
deprecate_axes_colorcycle],# cycle of plot
10281031
# line colors
10291032
# This entry can be either a cycler object or a

‎lib/matplotlib/sankey.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
frommatplotlib.transformsimportAffine2D
4646
frommatplotlibimportverbose
4747
frommatplotlibimportdocstring
48+
frommatplotlibimportrcParams
4849

4950
__author__="Kevin L. Davies"
5051
__credits__= ["Yannick Copin"]
@@ -770,11 +771,15 @@ def _get_angle(a, r):
770771
print("lrpath\n",self._revert(lrpath))
771772
xs,ys=list(zip(*vertices))
772773
self.ax.plot(xs,ys,'go-')
773-
patch=PathPatch(Path(vertices,codes),
774-
fc=kwargs.pop('fc',kwargs.pop('facecolor',
775-
'#bfd1d4')),# Custom defaults
776-
lw=kwargs.pop('lw',kwargs.pop('linewidth',0.5)),
777-
**kwargs)
774+
ifrcParams['_internal.classic_mode']:
775+
fc=kwargs.pop('fc',kwargs.pop('facecolor','#bfd1d4'))
776+
lw=kwargs.pop('lw',kwargs.pop('linewidth',0.5))
777+
else:
778+
fc=kwargs.pop('fc',kwargs.pop('facecolor',None))
779+
lw=kwargs.pop('lw',kwargs.pop('linewidth',None))
780+
iffcisNone:
781+
fc=six.next(self.ax._get_patches_for_fill.prop_cycler)['color']
782+
patch=PathPatch(Path(vertices,codes),fc=fc,lw=lw,**kwargs)
778783
self.ax.add_patch(patch)
779784

780785
# Add the path labels.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp