Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 50a8da5

Browse files
committed
Proof of concept "accepts units" decorator
Proof of concept "accepts units" decorator Add helper function Mssing commas Fix docstrings disappearing Ignore None when converting data Remove returns section in doc
1 parent bdeb21e commit 50a8da5

File tree

3 files changed

+74
-9
lines changed

3 files changed

+74
-9
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import matplotlib.ticker as mticker
3434
import matplotlib.transforms as mtransforms
3535
import matplotlib.tri as mtri
36+
import matplotlib.units as munits
3637
from matplotlib.cbook import (
3738
mplDeprecation, warn_deprecated, STEP_LOOKUP_MAP, iterable,
3839
safe_first_element)
@@ -3753,6 +3754,7 @@ def dopatch(xs, ys, **kwargs):
37533754
return dict(whiskers=whiskers, caps=caps, boxes=boxes,
37543755
medians=medians, fliers=fliers, means=means)
37553756

3757+
@munits._accepts_units(convert_x=['x'], convert_y=['y'])
37563758
@_preprocess_data(replace_names=["x", "y", "s", "linewidths",
37573759
"edgecolors", "c", "facecolor",
37583760
"facecolors", "color"],
@@ -3899,10 +3901,6 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
38993901
if edgecolors is None and not rcParams['_internal.classic_mode']:
39003902
edgecolors = 'face'
39013903

3902-
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
3903-
x = self.convert_xunits(x)
3904-
y = self.convert_yunits(y)
3905-
39063904
# np.ma.ravel yields an ndarray, not a masked array,
39073905
# unless its argument is a masked array.
39083906
xy_shape = (np.shape(x), np.shape(y))

lib/matplotlib/axes/_base.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,11 +3012,6 @@ def _validate_converted_limits(self, limit, convert):
30123012
Raise ValueError if converted limits are non-finite.
30133013
30143014
Note that this function also accepts None as a limit argument.
3015-
3016-
Returns
3017-
-------
3018-
The limit value after call to convert(), or None if limit is None.
3019-
30203015
"""
30213016
if limit is not None:
30223017
converted_limit = convert(limit)

lib/matplotlib/units.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,84 @@ def default_units(x, axis):
4343
"""
4444

4545
from numbers import Number
46+
import inspect
47+
import functools
4648

4749
import numpy as np
4850

4951
from matplotlib.cbook import iterable, safe_first_element
5052

5153

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

0 commit comments

Comments
 (0)