@@ -3282,27 +3282,19 @@ def errorbar(self, x, y, yerr=None, xerr=None,
3282
3282
kwargs = {k : v for k , v in kwargs .items () if v is not None }
3283
3283
kwargs .setdefault ('zorder' , 2 )
3284
3284
3285
- self . _process_unit_info ([( "x" , x ), ( "y" , y )], kwargs , convert = False )
3286
-
3287
- # Make sure all the args are iterable; use lists not arrays to preserve
3288
- # units.
3289
- if not np .iterable ( x ):
3290
- x = [ x ]
3291
-
3292
- if not np .iterable ( y ):
3293
- y = [ y ]
3294
-
3285
+ # Casting to object arrays preserves units.
3286
+ if not isinstance ( x , np . ndarray ):
3287
+ x = np . asarray ( x , dtype = object )
3288
+ if not isinstance ( y , np . ndarray ):
3289
+ y = np .asarray ( y , dtype = object )
3290
+ if xerr is not None and not isinstance ( xerr , np . ndarray ):
3291
+ xerr = np . asarray ( xerr , dtype = object )
3292
+ if yerr is not None and not isinstance ( yerr , np .ndarray ):
3293
+ yerr = np . asarray ( yerr , dtype = object )
3294
+ x , y = np . atleast_1d ( x , y ) # Make sure all the args are iterable.
3295
3295
if len (x ) != len (y ):
3296
3296
raise ValueError ("'x' and 'y' must have the same size" )
3297
3297
3298
- if xerr is not None :
3299
- if not np .iterable (xerr ):
3300
- xerr = [xerr ] * len (x )
3301
-
3302
- if yerr is not None :
3303
- if not np .iterable (yerr ):
3304
- yerr = [yerr ] * len (y )
3305
-
3306
3298
if isinstance (errorevery , Integral ):
3307
3299
errorevery = (0 , errorevery )
3308
3300
if isinstance (errorevery , tuple ):
@@ -3314,10 +3306,8 @@ def errorbar(self, x, y, yerr=None, xerr=None,
3314
3306
raise ValueError (
3315
3307
f'errorevery={ errorevery !r} is a not a tuple of two '
3316
3308
f'integers' )
3317
-
3318
3309
elif isinstance (errorevery , slice ):
3319
3310
pass
3320
-
3321
3311
elif not isinstance (errorevery , str ) and np .iterable (errorevery ):
3322
3312
# fancy indexing
3323
3313
try :
@@ -3329,6 +3319,8 @@ def errorbar(self, x, y, yerr=None, xerr=None,
3329
3319
else :
3330
3320
raise ValueError (
3331
3321
f"errorevery={ errorevery !r} is not a recognized value" )
3322
+ everymask = np .zeros (len (x ), bool )
3323
+ everymask [errorevery ] = True
3332
3324
3333
3325
label = kwargs .pop ("label" , None )
3334
3326
kwargs ['label' ] = '_nolegend_'
@@ -3412,13 +3404,8 @@ def errorbar(self, x, y, yerr=None, xerr=None,
3412
3404
xlolims = np .broadcast_to (xlolims , len (x )).astype (bool )
3413
3405
xuplims = np .broadcast_to (xuplims , len (x )).astype (bool )
3414
3406
3415
- everymask = np .zeros (len (x ), bool )
3416
- everymask [errorevery ] = True
3417
-
3418
- def apply_mask (arrays , mask ):
3419
- # Return, for each array in *arrays*, the elements for which *mask*
3420
- # is True, without using fancy indexing.
3421
- return [[* itertools .compress (array , mask )] for array in arrays ]
3407
+ # Vectorized fancy-indexer.
3408
+ def apply_mask (arrays , mask ): return [array [mask ] for array in arrays ]
3422
3409
3423
3410
def extract_err (name , err , data , lolims , uplims ):
3424
3411
"""
@@ -3439,24 +3426,14 @@ def extract_err(name, err, data, lolims, uplims):
3439
3426
Error is only applied on **lower** side when this is True. See
3440
3427
the note in the main docstring about this parameter's name.
3441
3428
"""
3442
- try : # Asymmetric error: pair of 1D iterables.
3443
- a , b = err
3444
- iter (a )
3445
- iter (b )
3446
- except (TypeError , ValueError ):
3447
- a = b = err # Symmetric error: 1D iterable.
3448
- if np .ndim (a ) > 1 or np .ndim (b ) > 1 :
3429
+ try :
3430
+ low , high = np .broadcast_to (err , (2 , len (data )))
3431
+ except ValueError :
3449
3432
raise ValueError (
3450
- f"{ name } err must be a scalar or a 1D or (2, n) array-like" )
3451
- # Using list comprehensions rather than arrays to preserve units.
3452
- for e in [a , b ]:
3453
- if len (data ) != len (e ):
3454
- raise ValueError (
3455
- f"The lengths of the data ({ len (data )} ) and the "
3456
- f"error { len (e )} do not match" )
3457
- low = [v if lo else v - e for v , e , lo in zip (data , a , lolims )]
3458
- high = [v if up else v + e for v , e , up in zip (data , b , uplims )]
3459
- return low , high
3433
+ f"'{ name } err' (shape: { np .shape (err )} ) must be a scalar "
3434
+ f"or a 1D or (2, n) array-like whose shape matches "
3435
+ f"'{ name } ' (shape: { np .shape (data )} )" ) from None
3436
+ return data - low * ~ lolims , data + high * ~ uplims # low, high
3460
3437
3461
3438
if xerr is not None :
3462
3439
left , right = extract_err ('x' , xerr , x , xlolims , xuplims )
0 commit comments