Skip to content

Make Axis3D constructor signature closer to the one of 2D axis. #21425

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/api/next_api_changes/deprecations/21425-AL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
3D Axis
~~~~~~~
The previous constructor of `.axis3d.Axis`, with signature
``(self, adir, v_intervalx, d_intervalx, axes, *args, rotate_label=None, **kwargs)``
is deprecated in favor of a new signature closer to the one of 2D Axis; it
is now ``(self, axes, *, rotate_label=None, **kwargs)`` where ``kwargs`` are
forwarded to the 2D Axis constructor. The axis direction is now inferred from
the axis class' ``axis_name`` attribute (as in the 2D case); the ``adir``
attribute is deprecated.

The ``init3d`` method of 3D Axis is also deprecated; all the relevant
initialization is done as part of the constructor.

The ``d_interval`` and ``v_interval`` attributes of 3D Axis are deprecated; use
``get_data_interval`` and ``get_view_interval`` instead.
11 changes: 3 additions & 8 deletions lib/mpl_toolkits/mplot3d/axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,9 @@ def set_top_view(self):

def _init_axis(self):
"""Init 3D axes; overrides creation of regular X/Y axes."""
self.xaxis = axis3d.XAxis('x', self.xy_viewLim.intervalx,
self.xy_dataLim.intervalx, self)
self.yaxis = axis3d.YAxis('y', self.xy_viewLim.intervaly,
self.xy_dataLim.intervaly, self)
self.zaxis = axis3d.ZAxis('z', self.zz_viewLim.intervalx,
self.zz_dataLim.intervalx, self)
for ax in self.xaxis, self.yaxis, self.zaxis:
ax.init3d()
self.xaxis = axis3d.XAxis(self)
self.yaxis = axis3d.YAxis(self)
self.zaxis = axis3d.ZAxis(self)

def get_zaxis(self):
"""Return the ``ZAxis`` (`~.axis3d.Axis`) instance."""
Expand Down
86 changes: 56 additions & 30 deletions lib/mpl_toolkits/mplot3d/axis3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
# Created: 23 Sep 2005
# Parts rewritten by Reinier Heeres <reinier@heeres.eu>

import inspect

import numpy as np

import matplotlib.transforms as mtransforms
from matplotlib import (
artist, lines as mlines, axis as maxis, patches as mpatches, rcParams)
_api, artist, lines as mlines, axis as maxis, patches as mpatches,
transforms as mtransforms, rcParams)
from . import art3d, proj3d


Expand Down Expand Up @@ -51,14 +53,34 @@ class Axis(maxis.XAxis):
'color': (0.925, 0.925, 0.925, 0.5)},
}

def __init__(self, adir, v_intervalx, d_intervalx, axes, *args,
rotate_label=None, **kwargs):
# adir identifies which axes this is
self.adir = adir
def _old_init(self, adir, v_intervalx, d_intervalx, axes, *args,
rotate_label=None, **kwargs):
return locals()

def _new_init(self, axes, *, rotate_label=None, **kwargs):
return locals()

def __init__(self, *args, **kwargs):
params = _api.select_matching_signature(
[self._old_init, self._new_init], *args, **kwargs)
if "adir" in params:
_api.warn_deprecated(
"3.6", message=f"The signature of 3D Axis constructors has "
f"changed in %(since)s; the new signature is "
f"{inspect.signature(type(self).__init__)}", pending=True)
if params["adir"] != self.axis_name:
raise ValueError(f"Cannot instantiate {type(self).__name__} "
f"with adir={params['adir']!r}")
axes = params["axes"]
rotate_label = params["rotate_label"]
args = params.get("args", ())
kwargs = params["kwargs"]

name = self.axis_name

# This is a temporary member variable.
# Do not depend on this existing in future releases!
self._axinfo = self._AXINFO[adir].copy()
self._axinfo = self._AXINFO[name].copy()
if rcParams['_internal.classic_mode']:
self._axinfo.update({
'label': {'va': 'center', 'ha': 'center'},
Expand All @@ -85,10 +107,10 @@ def __init__(self, adir, v_intervalx, d_intervalx, axes, *args,
'outward_factor': 0.1,
'linewidth': {
True: ( # major
rcParams['xtick.major.width'] if adir in 'xz' else
rcParams['xtick.major.width'] if name in 'xz' else
rcParams['ytick.major.width']),
False: ( # minor
rcParams['xtick.minor.width'] if adir in 'xz' else
rcParams['xtick.minor.width'] if name in 'xz' else
rcParams['ytick.minor.width']),
}
},
Expand All @@ -106,11 +128,18 @@ def __init__(self, adir, v_intervalx, d_intervalx, axes, *args,
super().__init__(axes, *args, **kwargs)

# data and viewing intervals for this direction
self.d_interval = d_intervalx
self.v_interval = v_intervalx
if "d_intervalx" in params:
self.set_data_interval(*params["d_intervalx"])
if "v_intervalx" in params:
self.set_view_interval(*params["v_intervalx"])
self.set_rotate_label(rotate_label)
self._init3d() # Inline after init3d deprecation elapses.

__init__.__signature__ = inspect.signature(_new_init)
adir = _api.deprecated("3.6", pending=True)(
property(lambda self: self.axis_name))

def init3d(self):
def _init3d(self):
self.line = mlines.Line2D(
xdata=(0, 0), ydata=(0, 0),
linewidth=self._axinfo['axisline']['linewidth'],
Expand All @@ -133,6 +162,10 @@ def init3d(self):
self.label._transform = self.axes.transData
self.offsetText._transform = self.axes.transData

@_api.deprecated("3.6", pending=True)
def init3d(self): # After deprecation elapses, inline _init3d to __init__.
self._init3d()

def get_major_ticks(self, numticks=None):
ticks = super().get_major_ticks(numticks)
for t in ticks:
Expand Down Expand Up @@ -496,41 +529,34 @@ def get_tightbbox(self, renderer, *, for_layout_only=False):

return mtransforms.Bbox.union([*bb_1, *bb_2, *other])

@property
def d_interval(self):
return self.get_data_interval()

@d_interval.setter
def d_interval(self, minmax):
self.set_data_interval(*minmax)

@property
def v_interval(self):
return self.get_view_interval()

@v_interval.setter
def v_interval(self, minmax):
self.set_view_interval(*minmax)


# Use classes to look at different data limits
d_interval = _api.deprecated(
"3.6", alternative="get_data_interval", pending=True)(
property(lambda self: self.get_data_interval(),
lambda self, minmax: self.set_data_interval(*minmax)))
v_interval = _api.deprecated(
"3.6", alternative="get_view_interval", pending=True)(
property(lambda self: self.get_view_interval(),
lambda self, minmax: self.set_view_interval(*minmax)))


class XAxis(Axis):
axis_name = "x"
get_view_interval, set_view_interval = maxis._make_getset_interval(
"view", "xy_viewLim", "intervalx")
get_data_interval, set_data_interval = maxis._make_getset_interval(
"data", "xy_dataLim", "intervalx")


class YAxis(Axis):
axis_name = "y"
get_view_interval, set_view_interval = maxis._make_getset_interval(
"view", "xy_viewLim", "intervaly")
get_data_interval, set_data_interval = maxis._make_getset_interval(
"data", "xy_dataLim", "intervaly")


class ZAxis(Axis):
axis_name = "z"
get_view_interval, set_view_interval = maxis._make_getset_interval(
"view", "zz_viewLim", "intervalx")
get_data_interval, set_data_interval = maxis._make_getset_interval(
Expand Down