@@ -2011,6 +2011,26 @@ def step(self, x, y, *args, where='pre', data=None, **kwargs):
2011
2011
kwargs ['drawstyle' ] = 'steps-' + where
2012
2012
return self .plot (x , y , * args , data = data , ** kwargs )
2013
2013
2014
+ @staticmethod
2015
+ def _convert_dx (dx , x0 , x , convert ):
2016
+ """
2017
+ Small helper to do logic of width conversion flexibly.
2018
+
2019
+ *dx* and *x0* have units, but *x* has already been converted
2020
+ to unitless. This allows the *dx* to have units that are
2021
+ different from *x0*, but are still accepted by the ``__add__``
2022
+ operator of *x0*.
2023
+ """
2024
+ try :
2025
+ # attempt to add the width to x0; this works for
2026
+ # datetime+timedelta, for instance
2027
+ dx = convert (x0 + dx ) - x
2028
+ except (TypeError , AttributeError ):
2029
+ # but doesn't work for 'string' + float, so just
2030
+ # see if the converter works on the float.
2031
+ dx = convert (dx )
2032
+ return dx
2033
+
2014
2034
@_preprocess_data ()
2015
2035
@docstring .dedent_interpd
2016
2036
def bar (self , x , height , width = 0.8 , bottom = None , * , align = "center" ,
@@ -2172,23 +2192,25 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
2172
2192
else :
2173
2193
raise ValueError ('invalid orientation: %s' % orientation )
2174
2194
2195
+ x , height , width , y , linewidth = np .broadcast_arrays (
2196
+ # Make args iterable too.
2197
+ np .atleast_1d (x ), height , width , y , linewidth )
2198
+
2175
2199
# lets do some conversions now since some types cannot be
2176
2200
# subtracted uniformly
2177
2201
if self .xaxis is not None :
2202
+ x0 = x
2178
2203
x = self .convert_xunits (x )
2179
- width = self .convert_xunits (width )
2204
+ width = self ._convert_dx (width , x0 , x , self . convert_xunits )
2180
2205
if xerr is not None :
2181
- xerr = self .convert_xunits (xerr )
2206
+ xerr = self ._convert_dx (xerr , x0 , x , self . convert_xunits )
2182
2207
2183
2208
if self .yaxis is not None :
2209
+ y0 = y
2184
2210
y = self .convert_yunits (y )
2185
- height = self .convert_yunits (height )
2211
+ height = self ._convert_dx (height , y0 , y , self . convert_yunits )
2186
2212
if yerr is not None :
2187
- yerr = self .convert_yunits (yerr )
2188
-
2189
- x , height , width , y , linewidth = np .broadcast_arrays (
2190
- # Make args iterable too.
2191
- np .atleast_1d (x ), height , width , y , linewidth )
2213
+ yerr = self ._convert_dx (yerr , y0 , y , self .convert_yunits )
2192
2214
2193
2215
# Now that units have been converted, set the tick locations.
2194
2216
if orientation == 'vertical' :
@@ -2465,10 +2487,19 @@ def broken_barh(self, xranges, yrange, **kwargs):
2465
2487
self ._process_unit_info (xdata = xdata ,
2466
2488
ydata = ydata ,
2467
2489
kwargs = kwargs )
2468
- xranges = self .convert_xunits (xranges )
2469
- yrange = self .convert_yunits (yrange )
2470
-
2471
- col = mcoll .BrokenBarHCollection (xranges , yrange , ** kwargs )
2490
+ xranges_conv = []
2491
+ for xr in xranges :
2492
+ if len (xr ) != 2 :
2493
+ raise ValueError ('each range in xrange must be a sequence '
2494
+ 'with two elements (i.e. an Nx2 array)' )
2495
+ # convert the absolute values, not the x and dx...
2496
+ x_conv = self .convert_xunits (xr [0 ])
2497
+ x1 = self ._convert_dx (xr [1 ], xr [0 ], x_conv , self .convert_xunits )
2498
+ xranges_conv .append ((x_conv , x1 ))
2499
+
2500
+ yrange_conv = self .convert_yunits (yrange )
2501
+
2502
+ col = mcoll .BrokenBarHCollection (xranges_conv , yrange_conv , ** kwargs )
2472
2503
self .add_collection (col , autolim = True )
2473
2504
self .autoscale_view ()
2474
2505
0 commit comments