@@ -1194,6 +1194,10 @@ def _perform_select_traces(self, filter_by_subplot, grid_subplot_refs, selector)
1194
1194
def _selector_matches (obj , selector ):
1195
1195
if selector is None :
1196
1196
return True
1197
+ # If selector is a string then put it at the 'type' key of a dictionary
1198
+ # to select objects where "type":selector
1199
+ if type (selector ) == type (str ()):
1200
+ selector = dict (type = selector )
1197
1201
# If selector is a dict, compare the fields
1198
1202
if (type (selector ) == type (dict ())) or isinstance (selector , BasePlotlyType ):
1199
1203
# This returns True if selector is an empty dict
@@ -1450,27 +1454,46 @@ def _select_annotations_like(
1450
1454
yref_to_row [yref ] = r + 1
1451
1455
yref_to_secondary_y [yref ] = is_secondary_y
1452
1456
1453
- for obj in self .layout [prop ]:
1454
- # Filter by row
1455
- if col is not None and xref_to_col .get (obj .xref , None ) != col :
1456
- continue
1457
-
1458
- # Filter by col
1459
- if row is not None and yref_to_row .get (obj .yref , None ) != row :
1460
- continue
1457
+ # filter down (select) which graph objects, by applying the filters
1458
+ # successively
1459
+ def _filter_row (obj ):
1460
+ """ Filter objects in rows by column """
1461
+ return (col is None ) or (xref_to_col .get (obj .xref , None ) == col )
1461
1462
1462
- # Filter by secondary y
1463
- if (
1464
- secondary_y is not None
1465
- and yref_to_secondary_y .get (obj .yref , None ) != secondary_y
1466
- ):
1467
- continue
1463
+ def _filter_col (obj ):
1464
+ """ Filter objects in columns by row """
1465
+ return (row is None ) or (yref_to_row .get (obj .yref , None ) == row )
1468
1466
1469
- # Filter by selector
1470
- if not self ._selector_matches (obj , selector ):
1471
- continue
1467
+ def _filter_sec_y (obj ):
1468
+ """ Filter objects on secondary y axes """
1469
+ return (secondary_y is None ) or (
1470
+ yref_to_secondary_y .get (obj .yref , None ) == secondary_y
1471
+ )
1472
1472
1473
- yield obj
1473
+ def _filter_selector_matches (obj ):
1474
+ """ Filter objects for which selector matches """
1475
+ return self ._selector_matches (obj , selector )
1476
+
1477
+ funcs = [_filter_row , _filter_col , _filter_sec_y ]
1478
+ # If selector is not an int, we use the _filter_selector_matches to
1479
+ # filter out items
1480
+ if type (selector ) != type (int ()):
1481
+ # append selector as filter function
1482
+ funcs += [_filter_selector_matches ]
1483
+
1484
+ def _reducer (last , f ):
1485
+ # takes list of objects that has been filtered down up to now (last)
1486
+ # and applies the next filter function (f) to filter it down further.
1487
+ return filter (lambda o : f (o ), last )
1488
+
1489
+ # filtered_objs is a sequence of objects filtered by the above functions
1490
+ filtered_objs = reduce (_reducer , funcs , self .layout [prop ])
1491
+ # If selector is an integer, use it as an index into the sequence of
1492
+ # filtered objects. Note in this case we do not call _filter_selector_matches.
1493
+ if type (selector ) == type (int ()):
1494
+ # wrap in iter because this function should always return an iterator
1495
+ return iter ([list (filtered_objs )[selector ]])
1496
+ return filtered_objs
1474
1497
1475
1498
def _add_annotation_like (
1476
1499
self ,
0 commit comments