@@ -3398,116 +3398,66 @@ def errorbar(self, x, y, yerr=None, xerr=None,
3398
3398
barcols = []
3399
3399
caplines = []
3400
3400
3401
- # arrays fine here, they are booleans and hence not units
3402
- lolims = np .broadcast_to (lolims , len (x )).astype (bool )
3403
- uplims = np .broadcast_to (uplims , len (x )).astype (bool )
3404
- xlolims = np .broadcast_to (xlolims , len (x )).astype (bool )
3405
- xuplims = np .broadcast_to (xuplims , len (x )).astype (bool )
3406
-
3407
3401
# Vectorized fancy-indexer.
3408
3402
def apply_mask (arrays , mask ): return [array [mask ] for array in arrays ]
3409
3403
3410
- def extract_err (name , err , data , lolims , uplims ):
3411
- """
3412
- Private function to compute error bars.
3413
-
3414
- Parameters
3415
- ----------
3416
- name : {'x', 'y'}
3417
- Name used in the error message.
3418
- err : array-like
3419
- xerr or yerr from errorbar().
3420
- data : array-like
3421
- x or y from errorbar().
3422
- lolims : array-like
3423
- Error is only applied on **upper** side when this is True. See
3424
- the note in the main docstring about this parameter's name.
3425
- uplims : array-like
3426
- Error is only applied on **lower** side when this is True. See
3427
- the note in the main docstring about this parameter's name.
3428
- """
3404
+ # dep: dependent dataset, indep: independent dataset
3405
+ for (dep_axis , dep , err , lolims , uplims , indep , lines_func ,
3406
+ marker , lomarker , himarker ) in [
3407
+ ("x" , x , xerr , xlolims , xuplims , y , self .hlines ,
3408
+ "|" , mlines .CARETRIGHTBASE , mlines .CARETLEFTBASE ),
3409
+ ("y" , y , yerr , lolims , uplims , x , self .vlines ,
3410
+ "_" , mlines .CARETUPBASE , mlines .CARETDOWNBASE ),
3411
+ ]:
3412
+ if err is None :
3413
+ continue
3414
+ lolims = np .broadcast_to (lolims , len (dep )).astype (bool )
3415
+ uplims = np .broadcast_to (uplims , len (dep )).astype (bool )
3429
3416
try :
3430
- np .broadcast_to (err , (2 , len (data )))
3417
+ np .broadcast_to (err , (2 , len (dep )))
3431
3418
except ValueError :
3432
3419
raise ValueError (
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
3420
+ f"'{ dep_axis } err' (shape: { np .shape (err )} ) must be a "
3421
+ f"scalar or a 1D or (2, n) array-like whose shape matches "
3422
+ f"'{ dep_axis } ' (shape: { np .shape (dep )} )" ) from None
3436
3423
# This is like
3437
- # low, high = np.broadcast_to(...)
3438
- # return data - low * ~lolims, data + high * ~uplims
3424
+ # elow, ehigh = np.broadcast_to(...)
3425
+ # return dep - elow * ~lolims, dep + ehigh * ~uplims
3439
3426
# except that broadcast_to would strip units.
3440
- return data + np .row_stack ([- (1 - lolims ), 1 - uplims ]) * err
3441
-
3442
- if xerr is not None :
3443
- left , right = extract_err ('x' , xerr , x , xlolims , xuplims )
3444
- barcols .append (self .hlines (
3445
- * apply_mask ([y , left , right ], everymask ), ** eb_lines_style ))
3446
- # select points without upper/lower limits in x and
3447
- # draw normal errorbars for these points
3448
- noxlims = ~ (xlolims | xuplims )
3449
- if noxlims .any () and capsize > 0 :
3450
- yo , lo , ro = apply_mask ([y , left , right ], noxlims & everymask )
3451
- caplines .extend ([
3452
- mlines .Line2D (lo , yo , marker = '|' , ** eb_cap_style ),
3453
- mlines .Line2D (ro , yo , marker = '|' , ** eb_cap_style )])
3454
- if xlolims .any ():
3455
- xo , yo , ro = apply_mask ([x , y , right ], xlolims & everymask )
3456
- if self .xaxis_inverted ():
3457
- marker = mlines .CARETLEFTBASE
3458
- else :
3459
- marker = mlines .CARETRIGHTBASE
3460
- caplines .append (mlines .Line2D (
3461
- ro , yo , ls = 'None' , marker = marker , ** eb_cap_style ))
3462
- if capsize > 0 :
3463
- caplines .append (mlines .Line2D (
3464
- xo , yo , marker = '|' , ** eb_cap_style ))
3465
- if xuplims .any ():
3466
- xo , yo , lo = apply_mask ([x , y , left ], xuplims & everymask )
3467
- if self .xaxis_inverted ():
3468
- marker = mlines .CARETRIGHTBASE
3469
- else :
3470
- marker = mlines .CARETLEFTBASE
3471
- caplines .append (mlines .Line2D (
3472
- lo , yo , ls = 'None' , marker = marker , ** eb_cap_style ))
3473
- if capsize > 0 :
3474
- caplines .append (mlines .Line2D (
3475
- xo , yo , marker = '|' , ** eb_cap_style ))
3476
-
3477
- if yerr is not None :
3478
- lower , upper = extract_err ('y' , yerr , y , lolims , uplims )
3479
- barcols .append (self .vlines (
3480
- * apply_mask ([x , lower , upper ], everymask ), ** eb_lines_style ))
3481
- # select points without upper/lower limits in y and
3482
- # draw normal errorbars for these points
3483
- noylims = ~ (lolims | uplims )
3484
- if noylims .any () and capsize > 0 :
3485
- xo , lo , uo = apply_mask ([x , lower , upper ], noylims & everymask )
3486
- caplines .extend ([
3487
- mlines .Line2D (xo , lo , marker = '_' , ** eb_cap_style ),
3488
- mlines .Line2D (xo , uo , marker = '_' , ** eb_cap_style )])
3489
- if lolims .any ():
3490
- xo , yo , uo = apply_mask ([x , y , upper ], lolims & everymask )
3491
- if self .yaxis_inverted ():
3492
- marker = mlines .CARETDOWNBASE
3493
- else :
3494
- marker = mlines .CARETUPBASE
3495
- caplines .append (mlines .Line2D (
3496
- xo , uo , ls = 'None' , marker = marker , ** eb_cap_style ))
3497
- if capsize > 0 :
3498
- caplines .append (mlines .Line2D (
3499
- xo , yo , marker = '_' , ** eb_cap_style ))
3500
- if uplims .any ():
3501
- xo , yo , lo = apply_mask ([x , y , lower ], uplims & everymask )
3502
- if self .yaxis_inverted ():
3503
- marker = mlines .CARETUPBASE
3504
- else :
3505
- marker = mlines .CARETDOWNBASE
3506
- caplines .append (mlines .Line2D (
3507
- xo , lo , ls = 'None' , marker = marker , ** eb_cap_style ))
3427
+ low , high = dep + np .row_stack ([- (1 - lolims ), 1 - uplims ]) * err
3428
+
3429
+ barcols .append (lines_func (
3430
+ * apply_mask ([indep , low , high ], everymask ), ** eb_lines_style ))
3431
+ # Normal errorbars for points without upper/lower limits.
3432
+ nolims = ~ (lolims | uplims )
3433
+ if nolims .any () and capsize > 0 :
3434
+ indep_masked , lo_masked , hi_masked = apply_mask (
3435
+ [indep , low , high ], nolims & everymask )
3436
+ for lh_masked in [lo_masked , hi_masked ]:
3437
+ # Since this has to work for x and y as dependent data, we
3438
+ # first set both x and y to the independent variable and
3439
+ # overwrite the respective dependent data in a second step.
3440
+ line = mlines .Line2D (indep_masked , indep_masked ,
3441
+ marker = marker , ** eb_cap_style )
3442
+ line .set (** {f"{ dep_axis } data" : lh_masked })
3443
+ caplines .append (line )
3444
+ for idx , (lims , hl ) in enumerate ([(lolims , high ), (uplims , low )]):
3445
+ if not lims .any ():
3446
+ continue
3447
+ hlmarker = (
3448
+ himarker
3449
+ if getattr (self , f"{ dep_axis } axis" ).get_inverted () ^ idx
3450
+ else lomarker )
3451
+ x_masked , y_masked , hl_masked = apply_mask (
3452
+ [x , y , hl ], lims & everymask )
3453
+ # As above, we set the dependent data in a second step.
3454
+ line = mlines .Line2D (x_masked , y_masked ,
3455
+ marker = hlmarker , ** eb_cap_style )
3456
+ line .set (** {f"{ dep_axis } data" : hl_masked })
3457
+ caplines .append (line )
3508
3458
if capsize > 0 :
3509
3459
caplines .append (mlines .Line2D (
3510
- xo , yo , marker = '_' , ** eb_cap_style ))
3460
+ x_masked , y_masked , marker = marker , ** eb_cap_style ))
3511
3461
3512
3462
for l in caplines :
3513
3463
self .add_line (l )
0 commit comments