Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
ENH: Introduce compass-notation for legend#12679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
:orphan: | ||
Compass notation for legend and other anchored artists | ||
------------------------------------------------------ | ||
The ``loc`` parameter for legends and other anchored artists now accepts | ||
"compass" strings. E.g. to locate such element in the upper right corner, | ||
in addition to ``'upper right'`` and ``1``, you can now use ``'NE'`` as | ||
well as ``'northeast'``. This satisfies the wish for more intuitive and | ||
unambiguous location of legends. The following (case-sensitive) location | ||
specifications are now allowed. | ||
============ ============== =============== ============= | ||
Compass Code Compass String Location String Location Code | ||
============ ============== =============== ============= | ||
.. 'best' 0 | ||
'NE' 'northeast' 'upper right' 1 | ||
'NW' 'northwest' 'upper left' 2 | ||
'SW' 'southwest' 'lower left' 3 | ||
'SE' 'southeast' 'lower right' 4 | ||
.. 'right' 5 | ||
'W' 'west' 'center left' 6 | ||
'E' 'east' 'center right' 7 | ||
'S' 'south' 'lower center' 8 | ||
'N' 'north' 'upper center' 9 | ||
'C' 'center' 'center' 10 | ||
============ ============== =============== ============= | ||
Those apply to | ||
* the axes legends; `matplotlib.pyplot.legend` and | ||
`matplotlib.axes.Axes.legend`, | ||
and, with the exception of ``'best'`` and ``0``, to | ||
* the figure legends; `matplotlib.pyplot.figlegend` and | ||
`matplotlib.figure.Figure.legend`, as well as the general | ||
`matplotlib.legend.Legend` class, | ||
* the `matplotlib.offsetbox`'s `matplotlib.offsetbox.AnchoredOffsetbox` and | ||
`matplotlib.offsetbox.AnchoredText`, | ||
* the `mpl_toolkits.axes_grid1.anchored_artists`'s | ||
`~.AnchoredDrawingArea`, `~.AnchoredAuxTransformBox`, | ||
`~.AnchoredEllipse`, `~.AnchoredSizeBar`, `~.AnchoredDirectionArrows` | ||
* the `mpl_toolkits.axes_grid1.inset_locator`'s | ||
`~.axes_grid1.inset_locator.inset_axes`, | ||
`~.axes_grid1.inset_locator.zoomed_inset_axes` and the | ||
`~.axes_grid1.inset_locator.AnchoredSizeLocator` and | ||
`~.axes_grid1.inset_locator.AnchoredZoomLocator` | ||
Note that those new compass strings *do not* apply to ``table``. | ||
Getter/setter for legend and other anchored artists location | ||
------------------------------------------------------------ | ||
The above mentioned classes (in particular `~.legend.Legend`, | ||
`~.offsetbox.AnchoredOffsetbox`, `~.offsetbox.AnchoredText` etc.) | ||
now have a getter/setter for the location. | ||
This allows to e.g. change the location *after* creating a legend:: | ||
legend = ax.legend(loc="west") | ||
legend.set_loc("southeast") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2156,3 +2156,86 @@ def _check_in_list(values, **kwargs): | ||
raise ValueError( | ||
"{!r} is not a valid value for {}; supported values are {}" | ||
.format(v, k, ', '.join(map(repr, values)))) | ||
# Theses are the valid compass notation codes used internally by legend | ||
# and other anchored boxes. | ||
_COMPASS_LOCS = ['NE', 'NW', 'SW', 'SE', 'E', 'W', 'S', 'N', 'C'] | ||
def _map_loc_to_compass(loc, **kwargs): | ||
""" | ||
Map a location (string) to a compass notation string. This is used by | ||
AnchoredOffsetbox and Legend. | ||
loc : A location, like 'upper right', 'NE', 'northeast', 1 | ||
allowtuple : bool, Whether to allow a tuple of numbers like (0.5, 0.2). | ||
This is useful for legends; other artists may not allow this. | ||
allowbest : bool, Whether to allow for 'best' or 0 as input for loc. | ||
warnonly : bool, if True, warn on invalid input and use fallback, | ||
if False, error out. | ||
fallback : The fallback return value in case of warnonly=True. | ||
asrcparam : string, Use if this function is used as validator for rcParams | ||
""" | ||
ImportanceOfBeingErnest marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
codes = { | ||
'upper right': 'NE', 'northeast': 'NE', 1: 'NE', | ||
'upper left': 'NW', 'northwest': 'NW', 2: 'NW', | ||
'lower left': 'SW', 'southwest': 'SW', 3: 'SW', | ||
'lower right': 'SE', 'southeast': 'SE', 4: 'SE', | ||
'right': 'E', 5: 'E', | ||
'center left': 'W', 'west': 'W', 6: 'W', | ||
'center right': 'E', 'east': 'E', 7: 'E', | ||
'lower center': 'S', 'south': 'S', 8: 'S', | ||
'upper center': 'N', 'north': 'N', 9: 'N', | ||
'center': 'C', 10: 'C' | ||
} | ||
allowtuple = kwargs.get("allowtuple", False) | ||
allowbest = kwargs.get("allowbest", False) | ||
fallback = kwargs.get("fallback", 'NE') | ||
warnonly = kwargs.get("warnonly", False) | ||
asrcparam = kwargs.get("asrcparam", None) | ||
if allowbest: | ||
codes.update({'best': 'best', 0: 'best'}) | ||
if loc in _COMPASS_LOCS: | ||
return loc | ||
if isinstance(loc, str) or isinstance(loc, int): | ||
dstansby marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
if loc in codes: | ||
return codes[loc] | ||
if allowtuple: | ||
dstansby marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
if hasattr(loc, '__len__') and len(loc) == 2: | ||
x, y = loc[0], loc[1] | ||
if isinstance(x, numbers.Number) and isinstance(y, numbers.Number): | ||
return tuple((x, y)) | ||
msg = "Unrecognized location {!r}. ".format(loc) | ||
if asrcparam: | ||
msg += "This is no valid rc parameter for {!r}. ".format(asrcparam) | ||
if isinstance(loc, str): | ||
if loc.lower() in codes: | ||
fallback = codes[loc.lower()] | ||
elif loc.upper() in _COMPASS_LOCS: | ||
fallback = loc.upper() | ||
msg += "Location strings are now case-sensitive. " | ||
if warnonly: | ||
msg += "Falling back on {!r}. ".format(fallback) | ||
if not allowbest and loc in [0, 'best']: | ||
msg += "Automatic legend placement (loc='best') is not " | ||
msg += "implemented for figure legends or other artists. " | ||
vcodes = [k for k in codes if not isinstance(k, int)] + _COMPASS_LOCS | ||
msg += "Valid locations are '{}'".format("', '".join(vcodes)) | ||
if not asrcparam: | ||
startn = 0 if allowbest else 1 | ||
msg += " as well as the numbers {} to 10. ".format(startn) | ||
if allowtuple: | ||
msg += " In addition a tuple (x,y) of coordinates can be supplied." | ||
if warnonly: | ||
ImportanceOfBeingErnest marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
msg += " This will raise an exception %(removal)s." | ||
warn_deprecated("3.1", message=msg) | ||
return fallback | ||
else: | ||
raise ValueError(msg) |
Uh oh!
There was an error while loading.Please reload this page.