diff --git a/doc/api/axes_api.rst b/doc/api/axes_api.rst index 4bbcbe081194..c2920e2f61f1 100644 --- a/doc/api/axes_api.rst +++ b/doc/api/axes_api.rst @@ -549,6 +549,8 @@ Interactive Axes.format_cursor_data Axes.format_xdata Axes.format_ydata + Axes.fmt_xdata + Axes.fmt_ydata Axes.mouseover Axes.in_axes diff --git a/doc/api/toolkits/mplot3d/axes3d.rst b/doc/api/toolkits/mplot3d/axes3d.rst index 612b3dd82a4b..0d3b15f7f64f 100644 --- a/doc/api/toolkits/mplot3d/axes3d.rst +++ b/doc/api/toolkits/mplot3d/axes3d.rst @@ -246,6 +246,8 @@ Interactive format_zdata format_coord + fmt_zdata + Projection and perspective -------------------------- diff --git a/galleries/users_explain/figure/interactive.rst b/galleries/users_explain/figure/interactive.rst index c6fc3c2025d7..5eddf1474d84 100644 --- a/galleries/users_explain/figure/interactive.rst +++ b/galleries/users_explain/figure/interactive.rst @@ -312,6 +312,29 @@ Preserve aspect ratio hold **CONTROL** when panning/zooming with mo ================================== =============================== +Position Format +--------------- + +The location of the cursor is shown in the UI and generated via the +`~axes.Axes.format_coord` method which in turn calls the +`~axes.Axes.format_xdata` and `~axes.Axes.format_ydata` methods. The hard +coded format in `~axes.Axes.format_coord` is ``f'x={formatted_x} +y={formatted_y}'``. + +To easily customize how the x and y values are formatted, you can set the +`.axes.Axes.fmt_xdata` and `.axes.Axes.fmt_ydata` attributes on the +`~axes.Axes` instance. The values are expected to be functions that +take a float and return a string. For example :: + + fig, ax = plt.subplots() + ax.set_ylim(-5, 5) + ax.fmt_ydata = lambda v: f'{v:.3g}' if v > 0 else f'({-v:.3g})' + +will format negative y-values with parenthesis rather than a negative sign. If +these attributes are set to `None`, then the `.Formatter.format_data_short` +method on the major formatter of the respective axes will be used instead. + + .. _other-shells: Other Python prompts diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 15f8e97b449f..134bbfa49473 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -7,6 +7,7 @@ from operator import attrgetter import re import textwrap +from typing import Callable import types import numpy as np @@ -594,6 +595,23 @@ class _AxesBase(martist.Artist): - :doc:`Axis API ` """ + fmt_xdata: Callable[[float], str] | None + """ + Callable to format the x-data in an interactive window. + + The expected signature is :: + + def fmt(val: float, /) -> str: ... + """ + + fmt_ydata: Callable[[float], str] | None + """ + Callable to format the y-data in an interactive window. + + The expected signature is :: + + def fmt(val: float, /) -> str: ... + """ def __str__(self): return "{0}({1[0]:g},{1[1]:g};{1[2]:g}x{1[3]:g})".format( type(self).__name__, self._position.bounds) diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 55b204022fb9..7e67818debeb 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -14,6 +14,7 @@ import itertools import math import textwrap +from typing import Callable import warnings import numpy as np @@ -57,6 +58,15 @@ class Axes3D(Axes): Axes._shared_axes["z"] = cbook.Grouper() Axes._shared_axes["view"] = cbook.Grouper() + fmt_zdata: Callable[[float], str] | None + """ + Callable to format the z-data in an interactive window. + + The expected signature is :: + + def fmt(val: float, /) -> str: ... + """ + def __init__( self, fig, rect=None, *args, elev=30, azim=-60, roll=0, shareview=None, sharez=None,