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

Commitab27d59

Browse files
committed
Implement xtick and ytick rotation_mode
1 parent0439b37 commitab27d59

File tree

6 files changed

+117
-16
lines changed

6 files changed

+117
-16
lines changed

‎lib/matplotlib/axis.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ def _apply_params(self, **kwargs):
346346
ifkin_gridline_param_names}
347347
self.gridline.set(**grid_kw)
348348

349+
if'rotation_mode'inkwargs:
350+
rotation_mode=kwargs.pop('rotation_mode')
351+
self.label1.set_rotation_mode(rotation_mode)
352+
self.label2.set_rotation_mode(rotation_mode)
353+
349354
defupdate_position(self,loc):
350355
"""Set the location of tick in data coords with scalar *loc*."""
351356
raiseNotImplementedError('Derived must override')
@@ -1041,14 +1046,15 @@ def get_tick_params(self, which='major'):
10411046
10421047
"""
10431048
_api.check_in_list(['major','minor'],which=which)
1049+
is_x_axis=Trueifisinstance(self,XAxis)elseFalse
10441050
ifwhich=='major':
10451051
returnself._translate_tick_params(
1046-
self._major_tick_kw,reverse=True
1047-
)
1048-
returnself._translate_tick_params(self._minor_tick_kw,reverse=True)
1052+
self._major_tick_kw,reverse=True,is_x_axis=is_x_axis)
1053+
returnself._translate_tick_params(
1054+
self._minor_tick_kw,reverse=True,is_x_axis=is_x_axis)
10491055

10501056
@staticmethod
1051-
def_translate_tick_params(kw,reverse=False):
1057+
def_translate_tick_params(kw,reverse=False,is_x_axis=None):
10521058
"""
10531059
Translate the kwargs supported by `.Axis.set_tick_params` to kwargs
10541060
supported by `.Tick._apply_params`.
@@ -1072,7 +1078,7 @@ def _translate_tick_params(kw, reverse=False):
10721078
'tick1On','tick2On','label1On','label2On',
10731079
'length','direction','left','bottom','right','top',
10741080
'labelleft','labelbottom','labelright','labeltop',
1075-
'labelrotation',
1081+
'labelrotation','rotation_mode',
10761082
*_gridline_param_names]
10771083

10781084
keymap= {
@@ -1090,10 +1096,19 @@ def _translate_tick_params(kw, reverse=False):
10901096
'labeltop':'label2On',
10911097
}
10921098
ifreverse:
1093-
kwtrans= {
1094-
oldkey:kw_.pop(newkey)
1095-
foroldkey,newkeyinkeymap.items()ifnewkeyinkw_
1096-
}
1099+
kwtrans= {}
1100+
foroldkey,newkeyinkeymap.items():
1101+
ifnewkeyinkw_:
1102+
ifis_x_axisandnewkey=='label1On':
1103+
kwtrans['labelbottom']=kw_.pop(newkey)
1104+
elifis_x_axisandnewkey=='tick1On':
1105+
kwtrans['bottom']=kw_.pop(newkey)
1106+
elifis_x_axisandnewkey=='label2On':
1107+
kwtrans['labeltop']=kw_.pop(newkey)
1108+
elifis_x_axisandnewkey=='tick2On':
1109+
kwtrans['top']=kw_.pop(newkey)
1110+
else:
1111+
kwtrans[oldkey]=kw_.pop(newkey)
10971112
else:
10981113
kwtrans= {
10991114
newkey:kw_.pop(oldkey)
@@ -2095,6 +2110,8 @@ def set_ticklabels(self, labels, *, minor=False, fontdict=None, **kwargs):
20952110
forpos, (loc,tick)inenumerate(zip(locs,ticks)):
20962111
tick.update_position(loc)
20972112
tick_label=formatter(loc,pos)
2113+
tick.label1.axes=self.axes
2114+
tick.label2.axes=self.axes
20982115
# deal with label1
20992116
tick.label1.set_text(tick_label)
21002117
tick.label1._internal_update(kwargs)

‎lib/matplotlib/tests/test_axis.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
importnumpyasnp
2-
32
importmatplotlib.pyplotasplt
4-
frommatplotlib.axisimportXTick
3+
frommatplotlib.axisimportXTick,XAxis
54

65

76
deftest_tick_labelcolor_array():
@@ -29,3 +28,12 @@ def test_axis_not_in_layout():
2928
# Positions should not be affected by overlapping 100 label
3029
assertax1_left.get_position().bounds==ax2_left.get_position().bounds
3130
assertax1_right.get_position().bounds==ax2_right.get_position().bounds
31+
32+
33+
deftest__translate_tick_params():
34+
fig,ax=plt.subplots()
35+
xaxis=XAxis(ax)
36+
kw= {'label1On':'dummy_string_1','label2On':'dummy_string_2'}
37+
result=xaxis._translate_tick_params(kw,reverse=True,is_x_axis=True)
38+
assertresult['labelbottom']=='dummy_string_1'
39+
assertresult['labeltop']=='dummy_string_2'

‎lib/matplotlib/tests/test_text.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,3 +1135,42 @@ def test_font_wrap():
11351135
plt.text(3,4,t,family='monospace',ha='right',wrap=True)
11361136
plt.text(-1,0,t,fontsize=14,style='italic',ha='left',rotation=-15,
11371137
wrap=True)
1138+
1139+
1140+
def_test_ha_for_angle():
1141+
text_instance=Text()
1142+
angles=np.arange(0,360.1,0.1)
1143+
forangleinangles:
1144+
alignment=text_instance.ha_for_angle(angle)
1145+
assertalignmentin ['center','left','right']
1146+
1147+
1148+
def_test_va_for_angle():
1149+
text_instance=Text()
1150+
angles=np.arange(0,360.1,0.1)
1151+
forangleinangles:
1152+
alignment=text_instance.va_for_angle(angle)
1153+
assertalignmentin ['center','top','baseline']
1154+
1155+
1156+
@image_comparison(baseline_images=['text_xtick_ytick_rotation_modes'],
1157+
remove_text=False,extensions=['png'],style='mpl20')
1158+
deftest_xtick_ytick_rotation_modes():
1159+
defset_ticks(ax,angles):
1160+
ax.set_xticks(np.arange(10))
1161+
ax.set_yticks(np.arange(10))
1162+
ax.set_xticklabels(['L']*10)
1163+
ax.set_yticklabels(['L']*10)
1164+
ax.xaxis.set_tick_params(rotation_mode='xtick',labelsize=7)
1165+
ax.yaxis.set_tick_params(rotation_mode='ytick',labelsize=7)
1166+
forlabel,angleinzip(ax.get_xticklabels(),angles):
1167+
label.set_rotation(angle)
1168+
forlabel,angleinzip(ax.get_yticklabels(),angles):
1169+
label.set_rotation(angle)
1170+
angles=np.linspace(0,360,10)
1171+
fig,axs=plt.subplots(1,2,figsize=(5,2.5))
1172+
set_ticks(axs[0],angles)
1173+
axs[1].xaxis.tick_top()
1174+
axs[1].yaxis.tick_right()
1175+
set_ticks(axs[1],angles)
1176+
plt.tight_layout()

‎lib/matplotlib/text.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,16 +301,16 @@ def set_rotation_mode(self, m):
301301
302302
Parameters
303303
----------
304-
m : {None, 'default', 'anchor'}
304+
m : {None, 'default', 'anchor', 'xtick', 'ytick'}
305305
If ``"default"``, the text will be first rotated, then aligned according
306-
to their horizontal and vertical alignments. If ``"anchor"``,then
307-
alignment occurs before rotation. Passing ``None`` will set the rotation
308-
mode to ``"default"``.
306+
to their horizontal and vertical alignments. If ``"anchor"``,``"xtick"``
307+
or ``"ytick", thenalignment occurs before rotation. Passing ``None`` will
308+
set the rotationmode to ``"default"``.
309309
"""
310310
ifmisNone:
311311
m="default"
312312
else:
313-
_api.check_in_list(("anchor","default"),rotation_mode=m)
313+
_api.check_in_list(("anchor","default","xtick","ytick"),rotation_mode=m)
314314
self._rotation_mode=m
315315
self.stale=True
316316

@@ -453,7 +453,18 @@ def _get_layout(self, renderer):
453453
valign=self._verticalalignment
454454

455455
rotation_mode=self.get_rotation_mode()
456+
ax=getattr(self,'axes',None)
457+
ifax:
458+
y_tick_params=ax.yaxis.get_tick_params()
459+
is_tick_right_enabled=y_tick_params.get('labelright',False)
460+
x_tick_params=ax.xaxis.get_tick_params()
461+
is_tick_top_enabled=x_tick_params.get('labeltop',False)
456462
ifrotation_mode!="anchor":
463+
angle=self.get_rotation()
464+
ifrotation_mode=='xtick':
465+
halign=self._ha_for_angle(angle,is_tick_top_enabled)
466+
elifrotation_mode=='ytick':
467+
valign=self._va_for_angle(angle,is_tick_right_enabled)
457468
# compute the text location in display coords and the offsets
458469
# necessary to align the bbox with that location
459470
ifhalign=='center':
@@ -1380,6 +1391,30 @@ def set_fontname(self, fontname):
13801391
"""
13811392
self.set_fontfamily(fontname)
13821393

1394+
def_ha_for_angle(self,angle,is_tick_top_enabled):
1395+
"""
1396+
Determines horizontal alignment ('ha') based on the angle of rotation
1397+
in degrees. Adjusts for is_tick_top_enabled.
1398+
"""
1399+
if (angle<5or85<=angle<105or355<=angle<360or
1400+
170<=angle<190or265<=angle<275):
1401+
return'center'
1402+
elif5<=angle<85or190<=angle<265:
1403+
return'left'ifis_tick_top_enabledelse'right'
1404+
return'right'ifis_tick_top_enabledelse'left'
1405+
1406+
def_va_for_angle(self,angle,is_tick_right_enabled):
1407+
"""
1408+
Determines vertical alignment ('va') based on the angle of rotation
1409+
in degrees. Adjusts for is_tick_right_enabled.
1410+
"""
1411+
if (angle<5or355<=angle<360or170<=angle<190
1412+
or85<=angle<105or265<=angle<275):
1413+
return'center'
1414+
elif190<=angle<265or5<=angle<85:
1415+
return'baseline'ifis_tick_right_enabledelse'top'
1416+
return'top'ifis_tick_right_enabledelse'baseline'
1417+
13831418

13841419
classOffsetFrom:
13851420
"""Callable helper class for working with `Annotation`."""

‎lib/matplotlib/text.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class Text(Artist):
106106
defset_fontname(self,fontname:str|Iterable[str])->None: ...
107107
defget_antialiased(self)->bool: ...
108108
defset_antialiased(self,antialiased:bool)->None: ...
109+
def_ha_for_angle(self,angle:Any,is_tick_top_enabled:bool)->Literal['center','right','left']|None: ...
110+
def_va_for_angle(self,angle:Any,is_tick_right_enabled:bool)->Literal['center','top','baseline']|None: ...
109111

110112
classOffsetFrom:
111113
def__init__(

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp