Skip to content

Commit cffa364

Browse files
committed
Proof of concept "accepts units" decorator
1 parent 1ac18e8 commit cffa364

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

lib/matplotlib/axes/_axes.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -4059,7 +4059,7 @@ def dopatch(xs, ys, **kwargs):
40594059
return dict(whiskers=whiskers, caps=caps, boxes=boxes,
40604060
medians=medians, fliers=fliers, means=means)
40614061

4062-
@munits._accepts_units(self, convert_x=[1], convert_y=[2])
4062+
@munits._accepts_units(convert_x=['x'], convert_y=['y'])
40634063
@_preprocess_data(replace_names=["x", "y", "s", "linewidths",
40644064
"edgecolors", "c", "facecolor",
40654065
"facecolors", "color"],
@@ -4211,7 +4211,6 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
42114211
if edgecolors is None and not rcParams['_internal.classic_mode']:
42124212
edgecolors = 'face'
42134213

4214-
42154214
# np.ma.ravel yields an ndarray, not a masked array,
42164215
# unless its argument is a masked array.
42174216
xy_shape = (np.shape(x), np.shape(y))

lib/matplotlib/units.py

+70-1
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,81 @@ def default_units(x, axis):
4444
from __future__ import (absolute_import, division, print_function,
4545
unicode_literals)
4646

47-
47+
import inspect
4848
import six
4949
from matplotlib.cbook import iterable, is_numlike, safe_first_element
5050
import numpy as np
5151

5252

53+
def _accepts_units(convert_x, convert_y):
54+
"""
55+
A decorator for functions and methods that accept units. The parameters
56+
indicated in *convert_x* and *convert_y* are used to update the axis
57+
unit information, are converted, and then handed on to the decorated
58+
function.
59+
60+
Parameters
61+
----------
62+
convert_x, convert_y : list
63+
A list of integers or strings, indicating the arguments to be converted
64+
"""
65+
def decorator(func):
66+
def wrapper(*args, **kwargs):
67+
axes = args[0]
68+
# Bind the incoming arguments to the function signature
69+
bound_args = inspect.signature(func).bind(*args, **kwargs)
70+
# Get the original arguments - these will be modified later
71+
arguments = bound_args.arguments
72+
# Check for data kwarg
73+
has_data = (('data' in arguments) and
74+
(arguments['data'] is not None))
75+
if has_data:
76+
data = arguments['data']
77+
78+
# Loop through each argument to be converted, update the axis
79+
# unit info, convert argument, and replace in *arguments* with
80+
# converted values
81+
for arg in convert_x:
82+
if has_data and arguments[arg] in data:
83+
data_arg = arguments[arg]
84+
original_data = data[data_arg]
85+
axes._process_unit_info(xdata=original_data, kwargs=kwargs)
86+
converted_data = axes.convert_xunits(original_data)
87+
data[data_arg] = converted_data
88+
else:
89+
original_data = arguments[arg]
90+
axes._process_unit_info(xdata=original_data, kwargs=kwargs)
91+
converted_data = axes.convert_xunits(original_data)
92+
arguments[arg] = converted_data
93+
94+
for arg in convert_y:
95+
if has_data and arguments[arg] in data:
96+
data_arg = arguments[arg]
97+
original_data = data[data_arg]
98+
axes._process_unit_info(ydata=original_data, kwargs=kwargs)
99+
converted_data = axes.convert_yunits(original_data)
100+
data[data_arg] = converted_data
101+
else:
102+
original_data = arguments[arg]
103+
axes._process_unit_info(ydata=original_data, kwargs=kwargs)
104+
converted_data = axes.convert_yunits(original_data)
105+
arguments[arg] = converted_data
106+
107+
if has_data:
108+
arguments['data'] = data
109+
# Update the arguments with converted values
110+
bound_args.arguments = arguments
111+
112+
# Give updated values to the original function
113+
args = bound_args.args
114+
kwargs = bound_args.kwargs
115+
kwargs.pop('xunits', None)
116+
kwargs.pop('yunits', None)
117+
return func(*args, **kwargs)
118+
return wrapper
119+
return decorator
120+
121+
53122
class AxisInfo(object):
54123
"""
55124
Information to support default axis labeling, tick labeling, and

0 commit comments

Comments
 (0)