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

Commitc24c7ad

Browse files
committed
WIP [skip ci]
1 parent677d990 commitc24c7ad

File tree

2 files changed

+243
-98
lines changed

2 files changed

+243
-98
lines changed

‎lib/matplotlib/axes/_axes.py

Lines changed: 194 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
importcollections.abc
12
importfunctools
23
importitertools
34
importlogging
@@ -3202,9 +3203,9 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
32023203

32033204
@_api.make_keyword_only("3.9","explode")
32043205
@_preprocess_data(replace_names=["x","explode","labels","colors"])
3205-
defpie(self,x,explode=None,labels=None,colors=None,
3206-
autopct=None,pctdistance=0.6,shadow=False,labeldistance=1.1,
3207-
startangle=0,radius=1,counterclock=True,
3206+
defpie(self,x,explode=None,labels=None,colors=None,wedge_labels=None,
3207+
wedge_label_distance=0.6,autopct=None,pctdistance=0.6,shadow=False,
3208+
labeldistance=1.1,startangle=0,radius=1,counterclock=True,
32083209
wedgeprops=None,textprops=None,center=(0,0),
32093210
frame=False,rotatelabels=False,*,normalize=True,hatch=None):
32103211
"""
@@ -3239,6 +3240,8 @@ def pie(self, x, explode=None, labels=None, colors=None,
32393240
32403241
.. versionadded:: 3.7
32413242
3243+
wedge_labels :
3244+
32423245
autopct : None or str or callable, default: None
32433246
If not *None*, *autopct* is a string or function used to label the
32443247
wedges with their numeric value. The label will be placed inside
@@ -3321,9 +3324,7 @@ def pie(self, x, explode=None, labels=None, colors=None,
33213324
The Axes aspect ratio can be controlled with `.Axes.set_aspect`.
33223325
"""
33233326
self.set_aspect('equal')
3324-
# The use of float32 is "historical", but can't be changed without
3325-
# regenerating the test baselines.
3326-
x=np.asarray(x,np.float32)
3327+
x=np.asarray(x)
33273328
ifx.ndim>1:
33283329
raiseValueError("x must be 1D")
33293330

@@ -3332,18 +3333,19 @@ def pie(self, x, explode=None, labels=None, colors=None,
33323333

33333334
sx=x.sum()
33343335

3336+
defcheck_length(name,values):
3337+
iflen(values)!=len(x):
3338+
raiseValueError(f"'{name}' must be of length 'x', not{len(values)}")
3339+
33353340
ifnormalize:
3336-
x=x/sx
3341+
fracs=x/sx
33373342
elifsx>1:
33383343
raiseValueError('Cannot plot an unnormalized pie with sum(x) > 1')
3339-
iflabelsisNone:
3340-
labels=['']*len(x)
3344+
else:
3345+
fracs=x
33413346
ifexplodeisNone:
33423347
explode= [0]*len(x)
3343-
iflen(x)!=len(labels):
3344-
raiseValueError(f"'labels' must be of length 'x', not{len(labels)}")
3345-
iflen(x)!=len(explode):
3346-
raiseValueError(f"'explode' must be of length 'x', not{len(explode)}")
3348+
check_length("explode",explode)
33473349
ifcolorsisNone:
33483350
get_next_color=self._get_patches_for_fill.get_next_color
33493351
else:
@@ -3368,16 +3370,155 @@ def get_next_color():
33683370

33693371
texts= []
33703372
slices= []
3371-
autotexts= []
33723373

3373-
forfrac,label,explinzip(x,labels,explode):
3374-
x,y=center
3374+
# Define some functions for choosing label fontize and horizontal alignment
3375+
# based on distance and whether we are right of center (i.e. cartesian x > 0)
3376+
3377+
deflegacy(distance,is_right):
3378+
# Used to place `labels`. This function can be removed when the
3379+
# `labeldistance` deprecation expires. Always align so the labels
3380+
# do not overlap the pie
3381+
ha='left'ifis_rightelse'right'
3382+
returnmpl.rcParams['xtick.labelsize'],ha
3383+
3384+
defflexible(distance,is_right):
3385+
ifdistance>=1:
3386+
# Align so the labels do not overlap the pie
3387+
ha='left'ifis_rightelse'right'
3388+
else:
3389+
ha='center'
3390+
3391+
returnNone,ha
3392+
3393+
deffixed(distance,is_right):
3394+
# Used to place the labels generated with autopct. Always centered
3395+
# for backwards compatibility
3396+
returnNone,'center'
3397+
3398+
# Build a (possibly empty) list of lists of wedge labels, with corresponding
3399+
# lists of distances, rotation choices and alignment functions
3400+
3401+
defsanitize_formatted_string(s):
3402+
ifmpl._val_or_rc(textprops.get("usetex"),"text.usetex"):
3403+
# escape % (i.e. \%) if it is not already escaped
3404+
returnre.sub(r"([^\\])%",r"\1\\%",s)
3405+
3406+
returns
3407+
3408+
deffmt_str_to_list(wl):
3409+
return [sanitize_formatted_string(wl.format(abs=absval,frac=frac))
3410+
forabsval,fracinzip(x,fracs)]
3411+
3412+
ifwedge_labelsisNone:
3413+
processed_wedge_labels= []
3414+
wedge_label_distance= []
3415+
rotate_wedge_labels= []
3416+
elifisinstance(wedge_labels,str):
3417+
# Format string.
3418+
processed_wedge_labels= [fmt_str_to_list(wedge_labels)]
3419+
elifnotisinstance(wedge_labels,collections.abc.Sequence):
3420+
raiseTypeError("wedge_labels must be a string or sequence")
3421+
else:
3422+
wl0=wedge_labels[0]
3423+
ifisinstance(wl0,str)andwl0.format(abs=1,frac=1)==wl0:
3424+
# Plain string. Assume we have a sequence of ready-made labels
3425+
check_length("wedge_labels",wedge_labels)
3426+
processed_wedge_labels= [wedge_labels]
3427+
else:
3428+
processed_wedge_labels= []
3429+
forwlinwedge_labels:
3430+
ifisinstance(wl,str):
3431+
# Format string
3432+
processed_wedge_labels.append(fmt_str_to_list(wl))
3433+
else:
3434+
# Ready made list
3435+
check_length("wedge_labels[i]",wl)
3436+
processed_wedge_labels.append(wl)
3437+
3438+
ifisinstance(wedge_label_distance,Number):
3439+
wedge_label_distance= [wedge_label_distance]
3440+
else:
3441+
# Copy so we won't append to user input
3442+
wedge_label_distance=wedge_label_distance[:]
3443+
3444+
if (nl:=len(processed_wedge_labels))!= (nd:=len(wedge_label_distance)):
3445+
raiseValueError(
3446+
f"Found{nl} sets of wedge labels but{nd} wedge label distances.")
3447+
3448+
ifisinstance(rotate_wedge_labels,bool):
3449+
rotate_wedge_labels= [rotate_wedge_labels]
3450+
else:
3451+
# Copy so we won't append to user input
3452+
rotate_wedge_labels=rotate_wedge_labels[:]
3453+
3454+
if (nl:=len(processed_wedge_labels))!= (nr:=len(rotate_wedge_labels)):
3455+
raiseValueError(
3456+
f"Found{nl} sets of wedge labels but{nr} wedge label rotation choices.")
3457+
3458+
prop_funcs= [flexible]*len(processed_wedge_labels)
3459+
3460+
3461+
ifautopctisnotNone:
3462+
ifisinstance(autopct,str):
3463+
processed_pct= [sanitize_formatted_string(autopct% (100.*frac))
3464+
forfracinfracs]
3465+
elifcallable(autopct):
3466+
processed_pct= [sanitize_formatted_string(autopct(100.*frac))
3467+
forfracinfracs]
3468+
else:
3469+
raiseTypeError('autopct must be callable or a format string')
3470+
3471+
processed_wedge_labels.append(processed_pct)
3472+
wedge_label_distance.append(pctdistance)
3473+
prop_funcs.append(fixed)
3474+
rotate_wedge_labels.append(False)
3475+
3476+
wedgetexts= [[]]*len(processed_wedge_labels)
3477+
3478+
3479+
print(f'{labels=}')
3480+
3481+
iflabelsisNone:
3482+
labels= [None]*len(x)
3483+
else:
3484+
check_length("labels",labels)
3485+
iflabeldistanceisnotNone:
3486+
_api.warn_deprecated(
3487+
"3.11",pending=True,
3488+
message=("Setting a non-None labeldistance is deprecated and "
3489+
"will error in future."),
3490+
alternative="wedge_labels and wedge_label_distance")
3491+
3492+
processed_wedge_labels.append(labels)
3493+
wedge_label_distance.append(labeldistance)
3494+
prop_funcs.append(legacy)
3495+
rotate_wedge_labels.append(rotatelabels)
3496+
3497+
3498+
print(f'{processed_wedge_labels=}')
3499+
3500+
# Transpose so we can loop over wedges
3501+
processed_wedge_labels=np.transpose(processed_wedge_labels)
3502+
ifnotprocessed_wedge_labels.size:
3503+
print('reshaping')
3504+
processed_wedge_labels=processed_wedge_labels.reshape(len(x),0)
3505+
3506+
print(f'{processed_wedge_labels=}')
3507+
print(f'{processed_wedge_labels.shape=}')
3508+
print(f'{wedge_label_distance=}')
3509+
print(f'{prop_funcs=}')
3510+
print(f'{rotate_wedge_labels=}')
3511+
3512+
forabsval,frac,label,expl,wlsinzip(x,fracs,labels,explode,
3513+
processed_wedge_labels):
3514+
print(f'{wls=}')
3515+
x_pos,y_pos=center
33753516
theta2= (theta1+frac)ifcounterclockelse (theta1-frac)
33763517
thetam=2*np.pi*0.5* (theta1+theta2)
3377-
x+=expl*math.cos(thetam)
3378-
y+=expl*math.sin(thetam)
3518+
x_pos+=expl*math.cos(thetam)
3519+
y_pos+=expl*math.sin(thetam)
33793520

3380-
w=mpatches.Wedge((x,y),radius,360.*min(theta1,theta2),
3521+
w=mpatches.Wedge((x_pos,y_pos),radius,360.*min(theta1,theta2),
33813522
360.*max(theta1,theta2),
33823523
facecolor=get_next_color(),
33833524
hatch=next(hatch_cycle),
@@ -3395,44 +3536,32 @@ def get_next_color():
33953536
shadow_dict.update(shadow)
33963537
self.add_patch(mpatches.Shadow(w,**shadow_dict))
33973538

3398-
iflabeldistanceisnotNone:
3399-
xt=x+labeldistance*radius*math.cos(thetam)
3400-
yt=y+labeldistance*radius*math.sin(thetam)
3401-
label_alignment_h='left'ifxt>0else'right'
3402-
label_alignment_v='center'
3403-
label_rotation='horizontal'
3404-
ifrotatelabels:
3405-
label_alignment_v='bottom'ifyt>0else'top'
3406-
label_rotation= (np.rad2deg(thetam)
3407-
+ (0ifxt>0else180))
3408-
t=self.text(xt,yt,label,
3409-
clip_on=False,
3410-
horizontalalignment=label_alignment_h,
3411-
verticalalignment=label_alignment_v,
3412-
rotation=label_rotation,
3413-
size=mpl.rcParams['xtick.labelsize'])
3414-
t.set(**textprops)
3415-
texts.append(t)
3416-
3417-
ifautopctisnotNone:
3418-
xt=x+pctdistance*radius*math.cos(thetam)
3419-
yt=y+pctdistance*radius*math.sin(thetam)
3420-
ifisinstance(autopct,str):
3421-
s=autopct% (100.*frac)
3422-
elifcallable(autopct):
3423-
s=autopct(100.*frac)
3424-
else:
3425-
raiseTypeError(
3426-
'autopct must be callable or a format string')
3427-
ifmpl._val_or_rc(textprops.get("usetex"),"text.usetex"):
3428-
# escape % (i.e. \%) if it is not already escaped
3429-
s=re.sub(r"([^\\])%",r"\1\\%",s)
3430-
t=self.text(xt,yt,s,
3431-
clip_on=False,
3432-
horizontalalignment='center',
3433-
verticalalignment='center')
3434-
t.set(**textprops)
3435-
autotexts.append(t)
3539+
ifwls.size>0:
3540+
# Add wedge labels
3541+
print('hello')
3542+
fori, (wl,ld,pf,rot)inenumerate(
3543+
zip(wls,wedge_label_distance,prop_funcs,rotate_wedge_labels)):
3544+
print(f'{wl=}')
3545+
xt=x_pos+ld*radius*math.cos(thetam)
3546+
yt=y_pos+ld*radius*math.sin(thetam)
3547+
fontsize,label_alignment_h=pf(ld,xt>0)
3548+
label_alignment_v='center'
3549+
label_rotation='horizontal'
3550+
ifrot:
3551+
label_alignment_v='bottom'ifyt>0else'top'
3552+
label_rotation= (np.rad2deg(thetam)
3553+
+ (0ifxt>0else180))
3554+
t=self.text(xt,yt,wl,
3555+
clip_on=False,
3556+
horizontalalignment=label_alignment_h,
3557+
verticalalignment=label_alignment_v,
3558+
rotation=label_rotation,
3559+
size=fontsize)
3560+
t.set(**textprops)
3561+
ifpfislegacy:
3562+
texts.append(t)
3563+
else:
3564+
wedgetexts[i].append(t)
34363565

34373566
theta1=theta2
34383567

@@ -3443,10 +3572,16 @@ def get_next_color():
34433572
xlim=(-1.25+center[0],1.25+center[0]),
34443573
ylim=(-1.25+center[1],1.25+center[1]))
34453574

3446-
ifautopctisNone:
3575+
print(f'{wedgetexts=}')
3576+
print(f'{len(wedgetexts)=}')
3577+
3578+
ifnotwedgetexts:
34473579
returnslices,texts
3580+
eliflen(wedgetexts)==1:
3581+
print('return first')
3582+
returnslices,texts,wedgetexts[0]
34483583
else:
3449-
returnslices,texts,autotexts
3584+
returnslices,texts,wedgetexts
34503585

34513586
@staticmethod
34523587
def_errorevery_to_mask(x,errorevery):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp