10000 Rewrite _process_unit_info to directly support the 3D case. · matplotlib/matplotlib@d4e0beb · GitHub
[go: up one dir, main page]

Skip to content

Commit d4e0beb

Browse files
committed
Rewrite _process_unit_info to directly support the 3D case.
1 parent ce6ac2d commit d4e0beb

File tree

4 files changed

+59
-94
lines changed

4 files changed

+59
-94
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -838,9 +838,8 @@ def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
838838
"argument; axhline generates its own transform.")
839839
ymin, ymax = self.get_ybound()
840840

841-
# We need to strip away the units for comparison with
842-
# non-unitized bounds
843-
self._process_unit_info(ydata=y, kwargs=kwargs)
841+
# Strip away the units for comparison with non-unitized bounds.
842+
self._process_unit_info({"y": y}, kwargs)
844843
yy = self.convert_yunits(y)
845844
scaley = (yy < ymin) or (yy > ymax)
846845

@@ -907,9 +906,8 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
907906
"argument; axvline generates its own transform.")
908907
xmin, xmax = self.get_xbound()
909908

910-
# We need to strip away the units for comparison with
911-
# non-unitized bounds
912-
self._process_unit_info(xdata=x, kwargs=kwargs)
909+
# Strip away the units for comparison with non-unitized bounds.
910+
self._process_unit_info({"x": x}, kwargs)
913911
xx = self.convert_xunits(x)
914912
scalex = (xx < xmin) or (xx > xmax)
915913

@@ -1050,8 +1048,7 @@ def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
10501048
self._check_no_units([xmin, xmax], ['xmin', 'xmax'])
10511049
trans = self.get_yaxis_transform(which='grid')
10521050

1053-
# process the unit information
1054-
self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs)
1051+
self._process_unit_info({"x": [xmin, xmax], "y": [ymin, ymax]}, kwargs)
10551052

10561053
# first we need to strip away the units
10571054
xmin, xmax = self.convert_xunits([xmin, xmax])
@@ -1111,8 +1108,7 @@ def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
11111108
self._check_no_units([ymin, ymax], ['ymin', 'ymax'])
11121109
trans = self.get_xaxis_transform(which='grid')
11131110

1114-
# process the unit information
1115-
self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs)
1111+
self._process_unit_info({"x": [xmin, xmax], "y": [ymin, ymax]}, kwargs)
11161112

11171113
# first we need to strip away the units
11181114
xmin, xmax = self.convert_xunits([xmin, xmax])
@@ -1162,8 +1158,7 @@ def hlines(self, y, xmin, xmax, colors=None, linestyles='solid',
11621158
"""
11631159

11641160
# We do the conversion first since not all unitized data is uniform
1165-
# process the unit information
1166-
self._process_unit_info([xmin, xmax], y, kwargs=kwargs)
1161+
self._process_unit_info({"x": [xmin, xmax], "y": y}, kwargs)
11671162
y = self.convert_yunits(y)
11681163
xmin = self.convert_xunits(xmin)
11691164
xmax = self.convert_xunits(xmax)
@@ -1243,9 +1238,8 @@ def vlines(self, x, ymin, ymax, colors=None, linestyles='solid',
12431238
axvline: vertical line across the axes
12441239
"""
12451240

1246-
self._process_unit_info(xdata=x, ydata=[ymin, ymax], kwargs=kwargs)
1247-
12481241
# We do the conversion first since not all unitized data is uniform
1242+
self._process_unit_info({"x": x, "y": [ymin, ymax]}, kwargs)
12491243
x = self.convert_xunits(x)
12501244
ymin = self.convert_yunits(ymin)
12511245
ymax = self.convert_yunits(ymax)
@@ -1386,9 +1380,8 @@ def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
13861380
--------
13871381
.. plot:: gallery/lines_bars_and_markers/eventplot_demo.py
13881382
"""
1389-
self._process_unit_info(xdata=positions,
1390-
ydata=[lineoffsets, linelengths],
1391-
kwargs=kwargs)
1383+
self._process_unit_info(
1384+
{"x": positions, "y": [lineoffsets, linelengths]}, kwargs)
13921385

13931386
# We do the conversion first since not all unitized data is uniform
13941387
positions = self.convert_xunits(positions)
@@ -2416,11 +2409,11 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
24162409
x = 0
24172410

24182411
if orientation == 'vertical':
2419-
self._process_unit_info(xdata=x, ydata=height, kwargs=kwargs)
2412+
self._process_unit_info({"x": x, "y": height}, kwargs)
24202413
if log:
24212414
self.set_yscale('log', nonpositive='clip')
24222415
elif orientation == 'horizontal':
2423-
self._process_unit_info(xdata=width, ydata=y, kwargs=kwargs)
2416+
self._process_unit_info({"x": width, "y": y}, kwargs)
24242417
if log:
24252418
self.set_xscale('log', nonpositive='clip')
24262419

@@ -2700,9 +2693,7 @@ def broken_barh(self, xranges, yrange, **kwargs):
27002693
ydata = cbook.safe_first_element(yrange)
27012694
else:
27022695
ydata = None
2703-
self._process_unit_info(xdata=xdata,
2704-
ydata=ydata,
2705-
kwargs=kwargs)
2696+
self._process_unit_info({"x": xdata, "y": ydata}, kwargs)
27062697
xranges_conv = []
27072698
for xr in xranges:
27082699
if len(xr) != 2:
@@ -2823,11 +2814,11 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
28232814
locs, heads, *args = args
28242815

28252816
if orientation == 'vertical':
2826-
self._process_unit_info(xdata=locs, ydata=heads)
2817+
self._process_unit_info({"x": locs, "y": heads})
28272818
locs = self.convert_xunits(locs)
28282819
heads = self.convert_yunits(heads)
28292820
else:
2830-
self._process_unit_info(xdata=heads, ydata=locs)
2821+
self._process_unit_info({"x": heads, "y": locs})
28312822
heads = self.convert_xunits(heads)
28322823
locs = self.convert_yunits(locs)
28332824

@@ -3313,7 +3304,7 @@ def errorbar(self, x, y, yerr=None, xerr=None,
33133304
if int(offset) != offset:
33143305
raise ValueError("errorevery's starting index must be an integer")
33153306

3316-
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
3307+
self._process_unit_info({"x": x, "y": y}, kwargs)
33173308

33183309
# Make sure all the args are iterable; use lists not arrays to preserve
33193310
# units.
@@ -4481,7 +4472,7 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
44814472
"""
44824473
# Process **kwargs to handle aliases, conflicts with explicit kwargs:
44834474

4484-
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
4475+
self._process_unit_info({"x": x, "y": y}, kwargs)
44854476
x = self.convert_xunits(x)
44864477
y = self.convert_yunits(y)
44874478

@@ -4712,7 +4703,7 @@ def reduce_C_function(C: array) -> float
47124703
%(PolyCollection)s
47134704
47144705
"""
4715-
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
4706+
self._process_unit_info({"x": x, "y": y}, kwargs)
47164707

47174708
x, y, C = cbook.delete_masked_points(x, y, C)
47184709

@@ -5061,7 +5052,7 @@ def quiverkey(self, Q, X, Y, U, label, **kw):
50615052
def _quiver_units(self, args, kw):
50625053
if len(args) > 3:
50635054
x, y = args[0:2]
5064-
self._process_unit_info(xdata=x, ydata=y, kwargs=kw)
5055+
self._process_unit_info({"x": x, "y": y}, kw)
50655056
x = self.convert_xunits(x)
50665057
y = self.convert_yunits(y)
50675058
return (x, y) + args[2:]
@@ -5249,10 +5240,8 @@ def _fill_between_x_or_y(
52495240
self._get_patches_for_fill.get_next_color()
52505241

52515242
# Handle united data, such as dates
5252-
self._process_unit_info(
5253-
**{f"{ind_dir}data": ind, f"{dep_dir}data": dep1}, kwargs=kwargs)
5254-
self._process_unit_info(
5255-
**{f"{dep_dir}data": dep2})
5243+
self._process_unit_info({ind_dir: ind, dep_dir: dep1}, kwargs)
5244+
self._process_unit_info({dep_dir: dep2})
52565245

52575246
# Convert the arrays so we can work with them
52585247
ind = ma.masked_invalid(getattr(self, f"convert_{ind_dir}units")(ind))
@@ -5866,7 +5855,7 @@ def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None,
58665855
Ny, Nx = X.shape
58675856

58685857
# unit conversion allows e.g. datetime objects as axis values
5869-
self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
5858+
self._process_unit_info({"x": X, "y": Y}, kwargs)
58705859
X = self.convert_xunits(X)
58715860
Y = self.convert_yunits(Y)
58725861

@@ -6143,7 +6132,7 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
61436132
X = X.ravel()
61446133
Y = Y.ravel()
61456134
# unit conversion allows e.g. datetime objects as axis values
6146-
self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
6135+
self._process_unit_info({"x": X, "y": Y}, kwargs)
61476136
X = self.convert_xunits(X)
61486137
Y = self.convert_yunits(Y)
61496138

@@ -6627,7 +6616,8 @@ def hist(self, x, bins=None, range=None, density=False, weights=None,
66276616

66286617
# Process unit information
66296618
# Unit conversion is done individually on each dataset
6630-
self._process_unit_info(xdata=x[0], kwargs=kwargs)
6619+
self._process_unit_info(
6620+
{"x" if orientation == "vertical" else "y": x[0]}, kwargs)
66316621
x = [self.convert_xunits(xi) for xi in x]
66326622

66336623
if bin_range is not None:

lib/matplotlib/axes/_base.py

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,46 +2175,44 @@ def update_datalim_bounds(self, bounds):
21752175
"""
21762176
self.dataLim.set(mtransforms.Bbox.union([self.dataLim, bounds]))
21772177

2178-
def _process_unit_info(self, xdata=None, ydata=None, kwargs=None):
2178+
def _process_unit_info(self, datasets=None, kwargs=None):
21792179
"""
2180-
Look for unit *kwargs* and update the axis instances as necessary
2180+
Set axis units based on *datasets* and *kwargs*.
21812181
2182-
2183-
.. warning ::
2184-
2185-
This method may mutate the dictionary passed in an kwargs and
2186-
the Axis instances attached to this Axes.
2187-
"""
2188-
2189-
def _process_single_axis(data, axis, unit_name, kwargs):
2190-
# Return if there's no axis set
2182+
Parameters
2183+
----------
2184+
datasets : dict
2185+
Mapping of axis names (per `._get_axis_map`) to datasets.
2186+
kwargs : dict
2187+
Other parameters from which unit info may be popped. Note that
2188+
this dict is mutated in-place!
2189+
"""
2190+
datasets = datasets or {}
2191+
axis_map = self._get_axis_map()
2192+
for axis_name in datasets:
2193+
if axis_name not in axis_map:
2194+
raise ValueError(f"Invalid axis name: {axis_name!r}")
2195+
for axis_name, axis in axis_map.items():
2196+
# Return if no axis is set.
21912197
if axis is None:
2192-
return kwargs
2193-
2194-
if data is not None:
2195-
# We only need to update if there is nothing set yet.
2196-
if not axis.have_units():
2197-
axis.update_units(data)
2198-
2199-
# Check for units in the kwargs, and if present update axis
2198+
continue
2199+
data = datasets.get(axis_name)
2200+
# Update from data if no unit is set yet.
2201+
if data is not None and not axis.have_units():
2202+
axis.update_units(data)
2203+
# Check for units in the kwargs, and if present update axis.
22002204
if kwargs is not None:
2201-
units = kwargs.pop(unit_name, axis.units)
2202-
if self.name == 'polar':
2203-
# handle special casing to allow the kwargs
2204-
# thetaunits and runits to be used with polar
2205-
polar_units = {'xunits': 'thetaunits', 'yunits': 'runits'}
2206-
units = kwargs.pop(polar_units[unit_name], units)
2207-
2205+
units = kwargs.pop(f"{axis_name}units", axis.units)
2206+
if self.name == "polar":
2207+
# Special case: polar supports "thetaunits"/"runits".
2208+
polar_units = {"x": "thetaunits", "y": "runits"}
2209+
units = kwargs.pop(polar_units[axis_name], units)
22082210
if units != axis.units and units is not None:
22092211
axis.set_units(units)
22102212
# If the units being set imply a different converter,
22112213
# we need to update.
22122214
if data is not None:
22132215
axis.update_units(data)
2214-
return kwargs
2215-
2216-
kwargs = _process_single_axis(xdata, self.xaxis, 'xunits', kwargs)
2217-
kwargs = _process_single_axis(ydata, self.yaxis, 'yunits', kwargs)
22182216
return kwargs
22192217

22202218
def in_axes(self, mouseevent):
@@ -3313,7 +3311,7 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False,
33133311
raise TypeError('Cannot pass both `xmax` and `right`')
33143312
right = xmax
33153313

3316-
self._process_unit_info(xdata=(left, right))
3314+
self._process_unit_info({"x": (left, right)})
33173315
left = self._validate_converted_limits(left, self.convert_xunits)
33183316
right = self._validate_converted_limits(right, self.convert_xunits)
33193317

@@ -3584,7 +3582,7 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
35843582
raise TypeError('Cannot pass both `ymax` and `top`')
35853583
top = ymax
35863584

3587-
self._process_unit_info(ydata=(bottom, top))
3585+
self._process_unit_info({"y": (bottom, top)})
35883586
bottom = self._validate_converted_limits(bottom, self.convert_yunits)
35893587
top = self._validate_converted_limits(top, self.convert_yunits)
35903588

lib/matplotlib/contour.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,7 @@ def _check_xyz(self, args, kwargs):
14741474
convert them to 2D using meshgrid.
14751475
"""
14761476
x, y = args[:2]
1477-
kwargs = self.axes._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
1477+
self.axes._process_unit_info({"x": x, "y": y}, kwargs)
14781478
x = self.axes.convert_xunits(x)
14791479
y = self.axes.convert_yunits(y)
14801480

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -161,29 +161,6 @@ def convert_zunits(self, z):
161161
"""
162162
return self.zaxis.convert_units(z)
163163

164-
def _process_unit_info(self, xdata=None, ydata=None, zdata=None,
165-
kwargs=None):
166-
"""Update the axis instances based on unit *kwargs* if given."""
167-
super()._process_unit_info(xdata=xdata, ydata=ydata, kwargs=kwargs)
168-
169-
if self.xaxis is None or self.yaxis is None or self.zaxis is None:
170-
return
171-
172-
if zdata is not None:
173-
# we only need to update if there is nothing set yet.
174-
if not self.zaxis.have_units():
175-
self.zaxis.update_units(xdata)
176-
177-
# process kwargs 2nd since these will override default units
178-
if kwargs is not None:
179-
zunits = kwargs.pop('zunits', self.zaxis.units)
180-
if zunits != self.zaxis.units:
181-
self.zaxis.set_units(zunits)
182-
# If the units being set imply a different converter,
183-
# we need to update.
184-
if zdata is not None:
185-
self.zaxis.update_units(zdata)
186-
187164
def set_top_view(self):
188165
# this happens to be the right view for the viewing coordinates
189166
# moved up and to the left slightly to fit labels and axes
@@ -746,7 +723,7 @@ def set_xlim3d(self, left=None, right=None, emit=True, auto=False,
746723
raise TypeError('Cannot pass both `xmax` and `right`')
747724
right = xmax
748725

749-
self._process_unit_info(xdata=(left, right))
726+
self._process_unit_info({"x": (left, right)})
750727
left = self._validate_converted_limits(left, self.convert_xunits)
751728
right = self._validate_converted_limits(right, self.convert_xunits)
752729

@@ -800,7 +777,7 @@ def set_ylim3d(self, bottom=None, top=None, emit=True, auto=False,
800777
raise TypeError('Cannot pass both `ymax` and `top`')
801778
top = ymax
802779

803-
self._process_unit_info(ydata=(bottom, top))
780+
self._process_unit_info({"y": (bottom, top)})
804781
bottom = self._validate_converted_limits(bottom, self.convert_yunits)
805782
top = self._validate_converted_limits(top, self.convert_yunits)
806783

@@ -855,7 +832,7 @@ def set_zlim3d(self, bottom=None, top=None, emit=True, auto=False,
855832
raise TypeError('Cannot pass both `zmax` and `top`')
856833
top = zmax
857834

858-
self._process_unit_info(zdata=(bottom, top))
835+
self._process_unit_info({"z": (bottom, top)})
859836
bottom = self._validate_converted_limits(bottom, self.convert_zunits)
860837
top = self._validate_converted_limits(top, self.convert_zunits)
861838

0 commit comments

Comments
 (0)
0