Skip to content

Commit 6627d3e

Browse files
nicholas-esterernicolaskruchten
authored andcommitted
Select annotation-like objects with string or int
If selector is string, transformed to dict(type=selector), if selector is int, indexes the resulting list of objects filtered down by row, col and secondary y.
1 parent 3e7967c commit 6627d3e

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

packages/python/plotly/plotly/basedatatypes.py

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,10 @@ def _perform_select_traces(self, filter_by_subplot, grid_subplot_refs, selector)
11941194
def _selector_matches(obj, selector):
11951195
if selector is None:
11961196
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)
11971201
# If selector is a dict, compare the fields
11981202
if (type(selector) == type(dict())) or isinstance(selector, BasePlotlyType):
11991203
# This returns True if selector is an empty dict
@@ -1450,27 +1454,46 @@ def _select_annotations_like(
14501454
yref_to_row[yref] = r + 1
14511455
yref_to_secondary_y[yref] = is_secondary_y
14521456

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)
14611462

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)
14681466

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+
)
14721472

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
14741497

14751498
def _add_annotation_like(
14761499
self,

0 commit comments

Comments
 (0)