From 9586cc37eededf00a39210bae6c7e28b28ba255a Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 9 Feb 2023 18:11:03 -0500 Subject: [PATCH 1/6] 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 af05f147e696099e027997952436e83819015ad1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 16 May 2025 17:38:17 -0400 Subject: [PATCH 2/6] 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 5986a7073462742c43eec35d13c85f04ca78b144 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 16 May 2025 17:38:50 -0400 Subject: [PATCH 3/6] 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 9978046c2b979e38a8abc1cf011c693ddfbdcaf5 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 11 Sep 2025 15:27:32 -0400 Subject: [PATCH 4/6] 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 From fe573ac9a867d5bad61348f75a3965a280a14ca8 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Tue, 16 Sep 2025 13:31:29 -0400 Subject: [PATCH 5/6] WIP: try to fix docs --- doc/api/toolkits/mplot3d/axes3d.rst | 207 ++++++++++++++-------------- 1 file changed, 104 insertions(+), 103 deletions(-) diff --git a/doc/api/toolkits/mplot3d/axes3d.rst b/doc/api/toolkits/mplot3d/axes3d.rst index 0d3b15f7f64f..da4e06e37a06 100644 --- a/doc/api/toolkits/mplot3d/axes3d.rst +++ b/doc/api/toolkits/mplot3d/axes3d.rst @@ -11,7 +11,7 @@ mpl\_toolkits.mplot3d.axes3d.Axes3D :show-inheritance: -.. currentmodule:: mpl_toolkits.mplot3d.axes3d.Axes3D +.. currentmodule:: mpl_toolkits.mplot3d.axes3d Plotting @@ -22,26 +22,26 @@ Plotting :template: autosummary.rst :nosignatures: - plot - scatter - bar - bar3d + Axes3D.plot + Axes3D.scatter + Axes3D.bar + Axes3D.bar3d - plot_surface - plot_wireframe - plot_trisurf - fill_between + Axes3D.plot_surface + Axes3D.plot_wireframe + Axes3D.plot_trisurf + Axes3D.fill_between - clabel - contour - tricontour - contourf - tricontourf + Axes3D.clabel + Axes3D.contour + Axes3D.tricontour + Axes3D.contourf + Axes3D.tricontourf - quiver - voxels - errorbar - stem + Axes3D.quiver + Axes3D.voxels + Axes3D.errorbar + Axes3D.stem Text and annotations @@ -52,8 +52,8 @@ Text and annotations :template: autosummary.rst :nosignatures: - text - text2D + Axes3D.text + Axes3D.text2D Clearing @@ -64,7 +64,7 @@ Clearing :template: autosummary.rst :nosignatures: - clear + Axes3D.clear Appearance @@ -75,9 +75,9 @@ Appearance :template: autosummary.rst :nosignatures: - set_axis_off - set_axis_on - grid + Axes3D.set_axis_off + Axes3D.set_axis_on + Axes3D.grid Axis @@ -91,32 +91,32 @@ Axis limits and direction :template: autosummary.rst :nosignatures: - get_zaxis - get_xlim - set_xlim - get_ylim - set_ylim - get_zlim - set_zlim - get_w_lims - get_xinverted - set_xinverted - invert_xaxis - xaxis_inverted - get_yinverted - set_yinverted - invert_yaxis - yaxis_inverted - get_zinverted - set_zinverted - invert_zaxis - zaxis_inverted - get_xbound - set_xbound - get_ybound - set_ybound - get_zbound - set_zbound + Axes3D.get_zaxis + Axes3D.get_xlim + Axes3D.set_xlim + Axes3D.get_ylim + Axes3D.set_ylim + Axes3D.get_zlim + Axes3D.set_zlim + Axes3D.get_w_lims + Axes3D.get_xinverted + Axes3D.set_xinverted + Axes3D.invert_xaxis + Axes3D.xaxis_inverted + Axes3D.get_yinverted + Axes3D.set_yinverted + Axes3D.invert_yaxis + Axes3D.yaxis_inverted + Axes3D.get_zinverted + Axes3D.set_zinverted + Axes3D.invert_zaxis + Axes3D.zaxis_inverted + Axes3D.get_xbound + Axes3D.set_xbound + Axes3D.get_ybound + Axes3D.set_ybound + Axes3D.get_zbound + Axes3D.set_zbound Axis labels and title @@ -127,9 +127,9 @@ Axis labels and title :template: autosummary.rst :nosignatures: - set_zlabel - get_zlabel - set_title + Axes3D.set_zlabel + Axes3D.get_zlabel + Axes3D.set_title Axis scales @@ -140,10 +140,10 @@ Axis scales :template: autosummary.rst :nosignatures: - set_xscale - set_yscale - set_zscale - get_zscale + Axes3D.set_xscale + Axes3D.set_yscale + Axes3D.set_zscale + Axes3D.get_zscale Autoscaling and margins @@ -154,14 +154,14 @@ Autoscaling and margins :template: autosummary.rst :nosignatures: - get_zmargin - set_zmargin - margins - autoscale - autoscale_view - set_autoscalez_on - get_autoscalez_on - auto_scale_xyz + Axes3D.get_zmargin + Axes3D.set_zmargin + Axes3D.margins + Axes3D.autoscale + Axes3D.autoscale_view + Axes3D.set_autoscalez_on + Axes3D.get_autoscalez_on + Axes3D.auto_scale_xyz Aspect ratio @@ -172,9 +172,9 @@ Aspect ratio :template: autosummary.rst :nosignatures: - set_aspect - set_box_aspect - apply_aspect + Axes3D.set_aspect + Axes3D.set_box_aspect + Axes3D.apply_aspect Ticks @@ -185,15 +185,15 @@ Ticks :template: autosummary.rst :nosignatures: - tick_params - set_zticks - get_zticks - set_zticklabels - get_zticklines - get_zgridlines - get_zminorticklabels - get_zmajorticklabels - zaxis_date + Axes3D.tick_params + Axes3D.set_zticks + Axes3D.get_zticks + Axes3D.set_zticklabels + Axes3D.get_zticklines + Axes3D.get_zgridlines + Axes3D.get_zminorticklabels + Axes3D.get_zmajorticklabels + Axes3D.zaxis_date Units @@ -204,7 +204,7 @@ Units :template: autosummary.rst :nosignatures: - convert_zunits + Axes3D.convert_zunits Adding artists @@ -215,7 +215,7 @@ Adding artists :template: autosummary.rst :nosignatures: - add_collection3d + Axes3D.add_collection3d Sharing @@ -226,8 +226,8 @@ Sharing :template: autosummary.rst :nosignatures: - sharez - shareview + Axes3D.sharez + Axes3D.shareview Interactive @@ -238,15 +238,16 @@ Interactive :template: autosummary.rst :nosignatures: - can_zoom - can_pan - disable_mouse_rotation - mouse_init - drag_pan - format_zdata - format_coord + Axes3D.can_zoom + Axes3D.can_pan + Axes3D.disable_mouse_rotation + Axes3D.mouse_init + Axes3D.drag_pan + + Axes3D.fmt_zdata + Axes3D.format_zdata + Axes3D.format_coord - fmt_zdata Projection and perspective @@ -257,10 +258,10 @@ Projection and perspective :template: autosummary.rst :nosignatures: - view_init - set_proj_type - get_proj - set_top_view + Axes3D.view_init + Axes3D.set_proj_type + Axes3D.get_proj + Axes3D.set_top_view Drawing @@ -271,8 +272,8 @@ Drawing :template: autosummary.rst :nosignatures: - draw - get_tightbbox + Axes3D.draw + Axes3D.get_tightbbox Aliases and deprecated methods @@ -283,9 +284,9 @@ Aliases and deprecated methods :template: autosummary.rst :nosignatures: - set_zlim3d - stem3D - text3D + Axes3D.set_zlim3d + Axes3D.stem3D + Axes3D.text3D Other @@ -296,10 +297,10 @@ Other :template: autosummary.rst :nosignatures: - get_axis_position - add_contour_set - add_contourf_set - update_datalim + Axes3D.get_axis_position + Axes3D.add_contour_set + Axes3D.add_contourf_set + Axes3D.update_datalim .. currentmodule:: mpl_toolkits.mplot3d @@ -312,7 +313,7 @@ Sample 3D data :template: autosummary.rst :nosignatures: - axes3d.get_test_data + mpl_toolkits.mplot3d.axes3d.get_test_data .. minigallery:: mpl_toolkits.mplot3d.axes3d.Axes3D From c5e6d4601903ec10d51a8a0e28d95cad51604463 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 16 Oct 2025 14:46:43 -0400 Subject: [PATCH 6/6] DOC: try to fix method resolution --- lib/mpl_toolkits/mplot3d/axes3d.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index fb781dea1291..e3ed804f475d 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -758,7 +758,7 @@ def set_zbound(self, lower=None, upper=None, view_margin=None): is not modified. view_margin : float or None The margin to apply to the bounds. If *None*, the margin is handled - by `.set_zlim`. + by `~.set_zlim`. See Also --------