@@ -2011,6 +2011,58 @@ 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 , xconv , convert ):
2016
+ """
2017
+ Small helper to do logic of width conversion flexibly.
2018
+
2019
+ *dx* and *x0* have units, but *xconv* has already been converted
2020
+ to unitless (and is an ndarray). This allows the *dx* to have units
2021
+ that are different from *x0*, but are still accepted by the
2022
+ ``__add__`` operator of *x0*.
2023
+ """
2024
+
2025
+ # x should be an array...
2026
+ assert type (xconv ) is np .ndarray
2027
+
2028
+ if xconv .size == 0 :
2029
+ # xconv has already been converted, but maybe empty...
2030
+ return convert (dx )
2031
+
2032
+ try :
2033
+ # attempt to add the width to x0; this works for
2034
+ # datetime+timedelta, for instance
2035
+
2036
+ # only use the first element of x and x0. This saves
2037
+ # having to be sure addition works across the whole
2038
+ # vector. This is particularly an issue if
2039
+ # x0 and dx are lists so x0 + dx just concatenates the lists.
2040
+ # We can't just cast x0 and dx to numpy arrays because that
2041
+ # removes the units from unit packages like `pint` that
2042
+ # wrap numpy arrays.
2043
+ try :
2044
+ x0 = x0 [0 ]
2045
+ except (TypeError , IndexError , KeyError ):
2046
+ x0 = x0
2047
+
2048
+ try :
2049
+ x = xconv [0 ]
2050
+ except (TypeError , IndexError , KeyError ):
2051
+ x = xconv
2052
+
2053
+ delist = False
2054
+ if not np .iterable (dx ):
2055
+ dx = [dx ]
2056
+ delist = True
2057
+ dx = [convert (x0 + ddx ) - x for ddx in dx ]
2058
+ if delist :
2059
+ dx = dx [0 ]
2060
+ except (TypeError , AttributeError ) as e :
2061
+ # but doesn't work for 'string' + float, so just
2062
+ # see if the converter works on the float.
2063
+ dx = convert (dx )
2064
+ return dx
2065
+
2014
2066
@_preprocess_data ()
2015
2067
@docstring .dedent_interpd
2016
2068
def bar (self , x , height , width = 0.8 , bottom = None , * , align = "center" ,
@@ -2175,16 +2227,17 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
2175
2227
# lets do some conversions now since some types cannot be
2176
2228
# subtracted uniformly
2177
2229
if self .xaxis is not None :
2178
- x = self .convert_xunits (x )
2179
- width = self .convert_xunits (width )
2230
+ x0 = x
2231
+ x = np .asarray (self .convert_xunits (x ))
2232
+ width = self ._convert_dx (width , x0 , x , self .convert_xunits )
2180
2233
if xerr is not None :
2181
- xerr = self .convert_xunits (xerr )
2182
-
2234
+ xerr = self ._convert_dx (xerr , x0 , x , self .convert_xunits )
2183
2235
if self .yaxis is not None :
2184
- y = self .convert_yunits (y )
2185
- height = self .convert_yunits (height )
2236
+ y0 = y
2237
+ y = np .asarray (self .convert_yunits (y ))
2238
+ height = self ._convert_dx (height , y0 , y , self .convert_yunits )
2186
2239
if yerr is not None :
2187
- yerr = self .convert_yunits (yerr )
2240
+ yerr = self ._convert_dx (yerr , y0 , y , self . convert_yunits )
2188
2241
2189
2242
x , height , width , y , linewidth = np .broadcast_arrays (
2190
2243
# Make args iterable too.
@@ -2465,10 +2518,19 @@ def broken_barh(self, xranges, yrange, **kwargs):
2465
2518
self ._process_unit_info (xdata = xdata ,
2466
2519
ydata = ydata ,
2467
2520
kwargs = kwargs )
2468
- xranges = self .convert_xunits (xranges )
2469
- yrange = self .convert_yunits (yrange )
2470
-
2471
- col = mcoll .BrokenBarHCollection (xranges , yrange , ** kwargs )
2521
+ xranges_conv = []
2522
+ for xr in xranges :
2523
+ if len (xr ) != 2 :
2524
+ raise ValueError ('each range in xrange must be a sequence '
2525
+ 'with two elements (i.e. an Nx2 array)' )
2526
+ # convert the absolute values, not the x and dx...
2527
+ x_conv = np .asarray (self .convert_xunits (xr [0 ]))
2528
+ x1 = self ._convert_dx (xr [1 ], xr [0 ], x_conv , self .convert_xunits )
2529
+ xranges_conv .append ((x_conv , x1 ))
2530
+
2531
+ yrange_conv = self .convert_yunits (yrange )
2532
+
2533
+ col = mcoll .BrokenBarHCollection (xranges_conv , yrange_conv , ** kwargs )
2472
2534
self .add_collection (col , autolim = True )
2473
2535
self .autoscale_view ()
2474
2536
0 commit comments