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

Commit75670d0

Browse files
loc short uppercase, longlowercase
1 parent2e0c8c5 commit75670d0

File tree

11 files changed

+419
-253
lines changed

11 files changed

+419
-253
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
:orphan:
2+
3+
Compass notation for legend and other anchored artists
4+
------------------------------------------------------
5+
6+
The ``loc`` parameter for legends and other anchored artists now accepts
7+
"compass" strings. E.g. to locate such element in the upper right corner,
8+
in addition to ``'upper right'`` and ``1``, you can now use ``'NE'`` as
9+
well as ``'northeast'``. This satisfies the wish for more intuitive and
10+
unambiguous location of legends. The following (case-sensitive) location
11+
specifications are now allowed.
12+
13+
============ ============== =============== =============
14+
Compass Code Compass String Location String Location Code
15+
============ ============== =============== =============
16+
.. 'best' 0
17+
'NE' 'northeast' 'upper right' 1
18+
'NW' 'northwest' 'upper left' 2
19+
'SW' 'southwest' 'lower left' 3
20+
'SE' 'southeast' 'lower right' 4
21+
.. 'right' 5
22+
'W' 'west' 'center left' 6
23+
'E' 'east' 'center right' 7
24+
'S' 'south' 'lower center' 8
25+
'N' 'north' 'upper center' 9
26+
'C' 'center' 'center' 10
27+
============ ============== =============== =============
28+
29+
Those apply to
30+
31+
* the legends; `matplotlib.pyplot.legend`, `matplotlib.axes.Axes.legend`,
32+
`matplotlib.legend.Legend`, `matplotlib.pyplot.figlegend`,
33+
`matplotlib.figure.Figure.legend`,
34+
35+
and, with the exception of ``'best'`` and ``0``, to
36+
37+
* the `matplotlib.offsetbox`'s `matplotlib.offsetbox.AnchoredOffsetbox` and
38+
`matplotlib.offsetbox.AnchoredText`,
39+
* the `mpl_toolkits.axes_grid1.anchored_artists`'s
40+
`~.AnchoredDrawingArea`, `~.AnchoredAuxTransformBox`,
41+
`~.AnchoredEllipse`, `~.AnchoredSizeBar`, `~.AnchoredDirectionArrows`
42+
* the `mpl_toolkits.axes_grid1.inset_locator`'s
43+
`~.axes_grid1.inset_locator.inset_axes`,
44+
`~.axes_grid1.inset_locator.zoomed_inset_axes` and the
45+
`~.axes_grid1.inset_locator.AnchoredSizeLocator` and
46+
`~.axes_grid1.inset_locator.AnchoredZoomLocator`
47+
48+
Note that those new compass strings *do not* apply to ``table``.
49+
50+
The above mentioned classes also now have a getter/setter for the location.
51+
This allows to e.g. change the location *after* creating a legend::
52+
53+
legend = ax.legend(loc="west")
54+
legend.set_loc("southeast")

‎lib/matplotlib/cbook/__init__.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,3 +2075,90 @@ def _check_and_log_subprocess(command, logger, **kwargs):
20752075
.format(command,exc.output.decode('utf-8')))
20762076
logger.debug(report)
20772077
returnreport
2078+
2079+
2080+
def_check_not_matrix(**kwargs):
2081+
"""
2082+
If any value in *kwargs* is a `np.matrix`, raise a TypeError with the key
2083+
name in its message.
2084+
"""
2085+
fork,vinkwargs.items():
2086+
ifisinstance(v,np.matrix):
2087+
raiseTypeError(f"Argument{k!r} cannot be a np.matrix")
2088+
2089+
2090+
def_check_in_list(values,**kwargs):
2091+
"""
2092+
For each *key, value* pair in *kwargs*, check that *value* is in *values*;
2093+
if not, raise an appropriate ValueError.
2094+
2095+
Examples
2096+
--------
2097+
>>> cbook._check_in_list(["foo", "bar"], arg=arg, other_arg=other_arg)
2098+
"""
2099+
fork,vinkwargs.items():
2100+
ifvnotinvalues:
2101+
raiseValueError(
2102+
"{!r} is not a valid value for {}; supported values are {}"
2103+
.format(v,k,', '.join(map(repr,values))))
2104+
2105+
2106+
_valid_compass= ['NE','NW','SW','SE','E','W','E','S','N','C']
2107+
2108+
def_map_loc_to_compass(loc,allowtuple=False,allowbest=False,
2109+
fallback='NE',warnonly=True):
2110+
"""
2111+
Map a location string to a compass notation string. This is used by
2112+
AnchoredOffsetbox and Legend.
2113+
"""
2114+
codes= {
2115+
'upper right':'NE','northeast':'NE',1:'NE',
2116+
'upper left':'NW','northwest':'NW',2:'NW',
2117+
'lower left':'SW','southwest':'SW',3:'SW',
2118+
'lower right':'SE','southeast':'SE',4:'SE',
2119+
'right':'E',5:'E',
2120+
'center left':'W','west':'W',6:'W',
2121+
'center right':'E','east':'E',7:'E',
2122+
'lower center':'S','south':'S',8:'S',
2123+
'upper center':'N','north':'N',9:'N',
2124+
'center':'C',10:'C'
2125+
}
2126+
2127+
ifallowbest:
2128+
codes.update({'best':'best',0:'best'})
2129+
2130+
iflocin_valid_compass:
2131+
returnloc
2132+
2133+
ifisinstance(loc,str)orisinstance(loc,int):
2134+
iflocincodes:
2135+
returncodes[loc]
2136+
2137+
ifallowtuple:
2138+
ifhasattr(loc,'__len__')andlen(loc)==2:
2139+
x,y=loc[0],loc[1]
2140+
ifisinstance(x,numbers.Number)andisinstance(y,numbers.Number):
2141+
returntuple((x,y))
2142+
2143+
msg="Unrecognized location {}. ".format(loc)
2144+
ifisinstance(loc,str):
2145+
ifloc.lower()incodes:
2146+
fallback=codes[loc.lower()]
2147+
elifloc.upper()in_valid_compass:
2148+
fallback=loc.upper()
2149+
msg+="Location strings are now case-sensitive. "
2150+
ifwarnonly:
2151+
msg+="Falling back on {}. ".format(fallback)
2152+
ifnotallowbestandlocin [0,'best']:
2153+
msg+="Note that automatic legend placement (loc='best') is not "
2154+
msg+="implemented for figure legends or other artists. "
2155+
vcodes= [kforkincodesifnotisinstance(k,int)]+_valid_compass
2156+
msg+="Valid locations are\n\t{}\n".format('\n\t'.join(vcodes))
2157+
msg+=" as well as the numbers {} to 10.\n".format(0ifallowbestelse1)
2158+
ifwarnonly:
2159+
msg+="This will raise an exception %(removal)s."
2160+
ifwarnonly:
2161+
warn_deprecated("3.1",message=msg)
2162+
returnfallback
2163+
else:
2164+
raiseValueError(msg)

‎lib/matplotlib/legend.py

Lines changed: 55 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@
2626

2727
importnumpyasnp
2828

29+
2930
frommatplotlibimportrcParams
3031
frommatplotlibimportcbook,docstring
3132
frommatplotlib.artistimportArtist,allow_rasterization
32-
frommatplotlib.cbookimportsilent_list,is_hashable,warn_deprecated
33+
frommatplotlib.cbookimport (silent_list,is_hashable,warn_deprecated,
34+
_valid_compass,_map_loc_to_compass)
3335
frommatplotlib.font_managerimportFontProperties
3436
frommatplotlib.linesimportLine2D
3537
frommatplotlib.patchesimportPatch,Rectangle,Shadow,FancyBboxPatch
@@ -113,23 +115,23 @@ def _update_bbox_to_anchor(self, loc_in_canvas):
113115
loc : int or string or pair of floats, default: :rc:`legend.loc` ('best' for\
114116
axes, 'upper right' for figures)
115117
The location of the legend.
116-
Possible (case-insensitive) strings and codes are:
117-
118-
============================= =============
119-
Location String Compass String Location Code
120-
============================= =============
121-
'best' 0
122-
'upper right''NE' 1
123-
'upper left''NW' 2
124-
'lower left''SW' 3
125-
'lower right''SE' 4
126-
'right' 5
127-
'center left''W' 6
128-
'center right''E' 7
129-
'lower center''S' 8
130-
'upper center''N' 9
131-
'center''C' 10
132-
============================= =============
118+
Possible (case-sensitive) strings and codes are:
119+
120+
========================== =============== =============
121+
Compass Code Compass String Location String Location Code
122+
========================== =============== =============
123+
.. 'best' 0
124+
'NE''northeast' 'upper right' 1
125+
'NW' 'northwest''upper left' 2
126+
'SW' 'southwest''lower left' 3
127+
'SE''southeast' 'lower right' 4
128+
.. 'right' 5
129+
'W' 'west' 'center left' 6
130+
'E' 'east''center right' 7
131+
'S' 'south''lower center' 8
132+
'N' 'north''upper center' 9
133+
'C' 'center' 'center' 10
134+
========================== =============== =============
133135
134136
135137
Alternatively can be a 2-tuple giving ``x, y`` of the lower-left
@@ -309,21 +311,7 @@ class Legend(Artist):
309311
Place a legend on the axes at location loc.
310312
311313
"""
312-
codes= {'best':0,# only implemented for axes legends
313-
'upper right':1,
314-
'upper left':2,
315-
'lower left':3,
316-
'lower right':4,
317-
'right':5,
318-
'center left':6,
319-
'center right':7,
320-
'lower center':8,
321-
'upper center':9,
322-
'center':10,
323-
}
324-
compasscodes= {'nw':2,'n':9,'ne':1,'w':6,'c':10,'e':7,
325-
'sw':3,'s':8,'se':4}
326-
allcodes= {**codes,**compasscodes}
314+
327315
zorder=5
328316

329317
def__str__(self):
@@ -487,35 +475,6 @@ def __init__(self, parent, handles, labels,
487475
raiseTypeError("Legend needs either Axes or Figure as parent")
488476
self.parent=parent
489477

490-
iflocisNone:
491-
loc=rcParams["legend.loc"]
492-
ifnotself.isaxesandlocin [0,'best']:
493-
loc='upper right'
494-
ifisinstance(loc,str):
495-
ifloc.lower()notinself.allcodes:
496-
ifself.isaxes:
497-
cbook.warn_deprecated(
498-
"3.1",message="Unrecognized location {!r}. Falling "
499-
"back on 'best'; valid locations are\n\t{}\n"
500-
"This will raise an exception %(removal)s."
501-
.format(loc,'\n\t'.join(self.allcodes)))
502-
loc=0
503-
else:
504-
cbook.warn_deprecated(
505-
"3.1",message="Unrecognized location {!r}. Falling "
506-
"back on 'upper right'; valid locations are\n\t{}\n'"
507-
"This will raise an exception %(removal)s."
508-
.format(loc,'\n\t'.join(self.allcodes)))
509-
loc=1
510-
else:
511-
loc=self.allcodes[loc.lower()]
512-
ifnotself.isaxesandloc==0:
513-
cbook.warn_deprecated(
514-
"3.1",message="Automatic legend placement (loc='best') not "
515-
"implemented for figure legend. Falling back on 'upper "
516-
"right'. This will raise an exception %(removal)s.")
517-
loc=1
518-
519478
self._mode=mode
520479
self.set_bbox_to_anchor(bbox_to_anchor,bbox_transform)
521480

@@ -561,6 +520,9 @@ def __init__(self, parent, handles, labels,
561520
# init with null renderer
562521
self._init_legend_box(handles,labels,markerfirst)
563522

523+
# location must be set after _legend_box is created.
524+
self._loc=loc
525+
564526
# If shadow is activated use framealpha if not
565527
# explicitly passed. See Issue 8943
566528
ifframealphaisNone:
@@ -571,7 +533,6 @@ def __init__(self, parent, handles, labels,
571533
else:
572534
self.get_frame().set_alpha(framealpha)
573535

574-
self._loc=loc
575536
# figure out title fontsize:
576537
iftitle_fontsizeisNone:
577538
title_fontsize=rcParams['legend.title_fontsize']
@@ -592,6 +553,16 @@ def _set_artist_props(self, a):
592553
a.set_transform(self.get_transform())
593554

594555
def_set_loc(self,loc):
556+
iflocisNone:
557+
loc=rcParams["legend.loc"]
558+
ifnotself.isaxesandlocin [0,'best']:
559+
loc='NE'
560+
ifself.isaxes:
561+
loc=_map_loc_to_compass(loc,allowtuple=True,allowbest=True,
562+
fallback="best",warnonly=True)
563+
else:
564+
loc=_map_loc_to_compass(loc,allowtuple=True,allowbest=False,
565+
fallback="NE",warnonly=True)
595566
# find_offset function will be provided to _legend_box and
596567
# _legend_box will draw itself at the location of the return
597568
# value of the find_offset.
@@ -604,12 +575,26 @@ def _get_loc(self):
604575

605576
_loc=property(_get_loc,_set_loc)
606577

578+
defset_loc(self,loc):
579+
"""
580+
Set the legend location. For possible values see the `~.Axes.legend`
581+
docstring.
582+
"""
583+
self._set_loc(loc)
584+
585+
defget_loc(self):
586+
"""
587+
Get the legend location. This will be one of 'best', 'NE', 'NW',
588+
'SW', 'SE', 'E', 'W', 'E', 'S', 'N', 'C' or a tuple of floats.
589+
"""
590+
returnself._get_loc()
591+
607592
def_findoffset(self,width,height,xdescent,ydescent,renderer):
608593
"Helper function to locate the legend."
609594

610-
ifself._loc==0:# "best".
595+
ifself._loc=='best':# "best".
611596
x,y=self._find_best_position(width,height,renderer)
612-
elifself._locinLegend.codes.values():# Fixed location.
597+
elifisinstance(self._loc,str):# Fixed location.
613598
bbox=Bbox.from_bounds(0,0,width,height)
614599
x,y=self._get_anchored_bbox(self._loc,bbox,
615600
self.get_bbox_to_anchor(),
@@ -1079,26 +1064,12 @@ def _get_anchored_bbox(self, loc, bbox, parentbbox, renderer):
10791064
- parentbbox: a parent box which will contain the bbox. In
10801065
display coordinates.
10811066
"""
1082-
assertlocinrange(1,11)# called only internally
1083-
1084-
BEST,UR,UL,LL,LR,R,CL,CR,LC,UC,C=range(11)
1085-
1086-
anchor_coefs= {UR:"NE",
1087-
UL:"NW",
1088-
LL:"SW",
1089-
LR:"SE",
1090-
R:"E",
1091-
CL:"W",
1092-
CR:"E",
1093-
LC:"S",
1094-
UC:"N",
1095-
C:"C"}
10961067

1097-
c=anchor_coefs[loc]
1068+
assertlocin_valid_compass# as this is called only internally
10981069

10991070
fontsize=renderer.points_to_pixels(self._fontsize)
11001071
container=parentbbox.padded(-(self.borderaxespad)*fontsize)
1101-
anchored_box=bbox.anchored(c,container=container)
1072+
anchored_box=bbox.anchored(loc,container=container)
11021073
returnanchored_box.x0,anchored_box.y0
11031074

11041075
def_find_best_position(self,width,height,renderer,consider=None):
@@ -1115,10 +1086,10 @@ def _find_best_position(self, width, height, renderer, consider=None):
11151086

11161087
bbox=Bbox.from_bounds(0,0,width,height)
11171088
ifconsiderisNone:
1118-
consider= [self._get_anchored_bbox(x,bbox,
1089+
consider= [self._get_anchored_bbox(loc,bbox,
11191090
self.get_bbox_to_anchor(),
11201091
renderer)
1121-
forxinrange(1,len(self.codes))]
1092+
forlocin_valid_compass]
11221093

11231094
candidates= []
11241095
foridx, (l,b)inenumerate(consider):
@@ -1199,7 +1170,7 @@ def draggable(self, state=None, use_blit=False, update="loc"):
11991170
is changed. If "bbox", the *bbox_to_anchor* parameter is changed.
12001171
"""
12011172
warn_deprecated("2.2",
1202-
message="Legend.draggable() isdrepecated in "
1173+
message="Legend.draggable() isdeprecated in "
12031174
"favor of Legend.set_draggable(). "
12041175
"Legend.draggable may be reintroduced as a "
12051176
"property in future releases.")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp