@@ -43,12 +43,84 @@ def default_units(x, axis):
43
43
"""
44
44
45
45
from numbers import Number
46
+ import inspect
47
+ import functools
46
48
47
49
import numpy as np
48
50
49
51
from matplotlib .cbook import iterable , safe_first_element
50
52
51
53
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
+
52
124
class AxisInfo (object ):
53
125
"""
54
126
Information to support default axis labeling, tick labeling, and
0 commit comments