From 432f9a7fd4afeb8121fad5c050466908e868334e Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 9 Feb 2023 18:11:03 -0500 Subject: [PATCH 1/4] DOC: document fmt_xdata, fmt_ydata, and fmt_ydata Co-authored-by: Elliott Sales de Andrade --- doc/api/axes_api.rst | 2 ++ .../users_explain/figure/interactive.rst | 23 +++++++++++++++++++ lib/matplotlib/axes/_base.py | 14 +++++++++++ lib/mpl_toolkits/mplot3d/axes3d.py | 7 ++++++ 4 files changed, 46 insertions(+) diff --git a/doc/api/axes_api.rst b/doc/api/axes_api.rst index b742ce9b7a55..901039cdc393 100644 --- a/doc/api/axes_api.rst +++ b/doc/api/axes_api.rst @@ -550,6 +550,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/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 e08d173744ad..ea8f2c7915fc 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -594,6 +594,20 @@ class _AxesBase(martist.Artist): - :doc:`Axis API ` """ + #: Callable to format the x-data in an interactive window. + #: + #: The expected signature is :: + #: + #: def fmt(val: float, /) -> str: ... + fmt_xdata = None + + #: Callable to format the y-data in an interactive window. + #: + #: The expected signature is :: + #: + #: def fmt(val: float, /) -> str: ... + fmt_ydata = None + 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 32da8dfde7aa..79306ce83690 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -57,6 +57,13 @@ class Axes3D(Axes): Axes._shared_axes["z"] = cbook.Grouper() Axes._shared_axes["view"] = cbook.Grouper() + #: Callable to format the z-data in an interactive window. + #: + #: The expected signature is :: + #: + #: def fmt(val: float, /) -> str: ... + fmt_zdata = None + def __init__( self, fig, rect=None, *args, elev=30, azim=-60, roll=0, shareview=None, sharez=None, From 83dedd946be17c77e5552203871b76601ae80d55 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 16 May 2025 17:38:17 -0400 Subject: [PATCH 2/4] DOC: add to rendered axes3D docs --- doc/api/toolkits/mplot3d/axes3d.rst | 2 ++ 1 file changed, 2 insertions(+) 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 -------------------------- From debd606446dc826d72927f1662f8f7e7ed6d34e7 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 16 May 2025 17:38:50 -0400 Subject: [PATCH 3/4] MNT: switch to using class level type annotations to doc target --- lib/matplotlib/axes/_base.py | 28 ++++++++++++++++------------ lib/mpl_toolkits/mplot3d/axes3d.py | 15 +++++++++------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index ea8f2c7915fc..6ef579a8dac5 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,20 +595,23 @@ class _AxesBase(martist.Artist): - :doc:`Axis API ` """ - #: Callable to format the x-data in an interactive window. - #: - #: The expected signature is :: - #: - #: def fmt(val: float, /) -> str: ... - fmt_xdata = None + fmt_xdata: Callable[[float], str] | None + """ + Callable to format the x-data in an interactive window. + + The expected signature is :: - #: Callable to format the y-data in an interactive window. - #: - #: The expected signature is :: - #: - #: def fmt(val: float, /) -> str: ... - fmt_ydata = None + 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 79306ce83690..7b1ac883b448 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,12 +58,14 @@ class Axes3D(Axes): Axes._shared_axes["z"] = cbook.Grouper() Axes._shared_axes["view"] = cbook.Grouper() - #: Callable to format the z-data in an interactive window. - #: - #: The expected signature is :: - #: - #: def fmt(val: float, /) -> str: ... - fmt_zdata = None + 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, From faa21be6cbe030f7bb7d92bffd61c8e7574cb8e2 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 11 Sep 2025 15:27:32 -0400 Subject: [PATCH 4/4] MNT: correct deprecated imports --- lib/matplotlib/axes/_base.py | 3 +-- lib/mpl_toolkits/mplot3d/axes3d.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 6ef579a8dac5..664259ad282d 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1,4 +1,4 @@ -from collections.abc import Iterable, Sequence +from collections.abc import Iterable, Sequence, Callable from contextlib import ExitStack import functools import inspect @@ -7,7 +7,6 @@ from operator import attrgetter import re import textwrap -from typing import Callable import types import numpy as np diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 7b1ac883b448..fb781dea1291 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -11,10 +11,10 @@ """ from collections import defaultdict +from collections.abc import Callable import itertools import math import textwrap -from typing import Callable import warnings import numpy as np