|
8 | 8 | import warnings
|
9 | 9 | from contextlib import contextmanager
|
10 | 10 | from copy import deepcopy, copy
|
| 11 | +import itertools |
11 | 12 |
|
12 | 13 | from _plotly_utils.utils import _natural_sort_strings
|
13 | 14 | from .optional_imports import get_module
|
|
18 | 19 | Undefined = object()
|
19 | 20 |
|
20 | 21 |
|
| 22 | +def _rcindex_type(d): |
| 23 | + if type(d) == type(int()): |
| 24 | + return "i" |
| 25 | + elif type(d) == type(list()): |
| 26 | + return "l" |
| 27 | + elif d == "all": |
| 28 | + return "a" |
| 29 | + else: |
| 30 | + raise TypeError( |
| 31 | + "argument must be 'all', int or list, got {d_type}".format( |
| 32 | + d_type=str(type(d)) |
| 33 | + ) |
| 34 | + ) |
| 35 | + |
| 36 | + |
| 37 | +def _rcsingle_index_to_list(d): |
| 38 | + if type(d) == type(int()): |
| 39 | + return [d] |
| 40 | + return d |
| 41 | + |
| 42 | + |
| 43 | +def _row_col_index_combinations(rows, cols, max_n_rows, max_n_cols): |
| 44 | + rtype = _rcindex_type(rows) |
| 45 | + ctype = _rcindex_type(cols) |
| 46 | + rows = _rcsingle_index_to_list(rows) |
| 47 | + cols = _rcsingle_index_to_list(cols) |
| 48 | + ptype = (rtype, ctype) |
| 49 | + all_rows = range(1, max_n_rows + 1) |
| 50 | + all_cols = range(1, max_n_cols + 1) |
| 51 | + if ptype == ("a", "a"): |
| 52 | + return list(itertools.product(all_rows, all_cols)) |
| 53 | + elif ptype == ("l", "a") or ptype == ("i", "a"): |
| 54 | + return list(itertools.product(rows, all_cols)) |
| 55 | + elif ptype == ("a", "l") or ("a", "i"): |
| 56 | + return list(itertools.product(all_rows, cols)) |
| 57 | + elif ptype == ("l", "l"): |
| 58 | + if len(rows) == len(cols): |
| 59 | + return list(zip(rows, cols)) |
| 60 | + else: |
| 61 | + return list(itertools.product(rows, cols)) |
| 62 | + elif ptype == ("l", "i") or ptype == ("i", "i") or ptype == ("i", "l"): |
| 63 | + return list(itertools.product(rows, cols)) |
| 64 | + |
| 65 | + |
21 | 66 | class BaseFigure(object):
|
22 | 67 | """
|
23 | 68 | Base class for all figure types (both widget and non-widget)
|
@@ -1090,42 +1135,51 @@ def _add_annotation_like(
|
1090 | 1135 | "Received col parameter but not row.\n"
|
1091 | 1136 | "row and col must be specified together"
|
1092 | 1137 | )
|
| 1138 | + grid_ref = self._validate_get_grid_ref() |
1093 | 1139 |
|
1094 | 1140 | # Get grid_ref if specific row or column requested
|
1095 | 1141 | if row is not None:
|
1096 |
| - grid_ref = self._validate_get_grid_ref() |
1097 |
| - refs = grid_ref[row - 1][col - 1] |
| 1142 | + # TODO It is assumed that grid_ref has an equal number of columns in |
| 1143 | + # each row. Is this ever not true? |
| 1144 | + rows_cols = _row_col_index_combinations( |
| 1145 | + row, col, len(grid_ref), len(grid_ref[0]) |
| 1146 | + ) |
1098 | 1147 |
|
1099 |
| - if not refs: |
1100 |
| - raise ValueError( |
1101 |
| - "No subplot found at position ({r}, {c})".format(r=row, c=col) |
1102 |
| - ) |
| 1148 | + for r, c in rows_cols: |
| 1149 | + refs = grid_ref[r - 1][c - 1] |
1103 | 1150 |
|
1104 |
| - if refs[0].subplot_type != "xy": |
1105 |
| - raise ValueError( |
1106 |
| - """ |
1107 |
| -Cannot add {prop_singular} to subplot at position ({r}, {c}) because subplot |
1108 |
| -is of type {subplot_type}.""".format( |
1109 |
| - prop_singular=prop_singular, |
1110 |
| - r=row, |
1111 |
| - c=col, |
1112 |
| - subplot_type=refs[0].subplot_type, |
| 1151 | + if not refs: |
| 1152 | + raise ValueError( |
| 1153 | + "No subplot found at position ({r}, {c})".format(r=r, c=c) |
1113 | 1154 | )
|
1114 |
| - ) |
1115 |
| - if len(refs) == 1 and secondary_y: |
1116 |
| - raise ValueError( |
1117 |
| - """ |
1118 |
| -Cannot add {prop_singular} to secondary y-axis of subplot at position ({r}, {c}) |
1119 |
| -because subplot does not have a secondary y-axis""" |
1120 |
| - ) |
1121 |
| - if secondary_y: |
1122 |
| - xaxis, yaxis = refs[1].layout_keys |
1123 |
| - else: |
1124 |
| - xaxis, yaxis = refs[0].layout_keys |
1125 |
| - xref, yref = xaxis.replace("axis", ""), yaxis.replace("axis", "") |
1126 |
| - new_obj.update(xref=xref, yref=yref) |
1127 | 1155 |
|
1128 |
| - self.layout[prop_plural] += (new_obj,) |
| 1156 | + if refs[0].subplot_type != "xy": |
| 1157 | + raise ValueError( |
| 1158 | + """ |
| 1159 | + Cannot add {prop_singular} to subplot at position ({r}, {c}) because subplot |
| 1160 | + is of type {subplot_type}.""".format( |
| 1161 | + prop_singular=prop_singular, |
| 1162 | + r=r, |
| 1163 | + c=c, |
| 1164 | + subplot_type=refs[0].subplot_type, |
| 1165 | + ) |
| 1166 | + ) |
| 1167 | + if len(refs) == 1 and secondary_y: |
| 1168 | + raise ValueError( |
| 1169 | + """ |
| 1170 | + Cannot add {prop_singular} to secondary y-axis of subplot at position ({r}, {c}) |
| 1171 | + because subplot does not have a secondary y-axis""".format( |
| 1172 | + prop_singular=prop_singular, r=r, c=c |
| 1173 | + ) |
| 1174 | + ) |
| 1175 | + if secondary_y: |
| 1176 | + xaxis, yaxis = refs[1].layout_keys |
| 1177 | + else: |
| 1178 | + xaxis, yaxis = refs[0].layout_keys |
| 1179 | + xref, yref = xaxis.replace("axis", ""), yaxis.replace("axis", "") |
| 1180 | + new_obj.update(xref=xref, yref=yref) |
| 1181 | + |
| 1182 | + self.layout[prop_plural] += (new_obj,) |
1129 | 1183 |
|
1130 | 1184 | return self
|
1131 | 1185 |
|
|
0 commit comments