-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathalgorithm_pairs_selector.py
More file actions
126 lines (102 loc) · 5 KB
/
algorithm_pairs_selector.py
File metadata and controls
126 lines (102 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import logging
import panel as pn
from panel.viewable import Viewer
import param
logger = logging.getLogger("visualizer.algorithm_pairs_selector")
class AlgorithmPair(Viewer):
first = param.Parameter(default="")
second = param.Parameter(default="")
algorithm_pairs = param.List(default=[])
def __init__(self, algorithm_pair_selector, exp_data, **params):
super().__init__(**params)
self.exp_data = exp_data
self.algorithm_pair_selector = algorithm_pair_selector
self.set_pairs()
@param.depends("exp_data.algorithms")
def first_view(self):
return pn.widgets.AutocompleteInput.from_param(
self.param.first,
name="",
options=[""] + list(self.exp_data.algorithms.keys()),
case_sensitive=False,
search_strategy='includes',
restrict=False,
margin=(5, 0, 5, 0),
min_width=100,
sizing_mode="stretch_width",
)
@param.depends("exp_data.algorithms")
def second_view(self):
return pn.widgets.AutocompleteInput.from_param(
self.param.second,
name="",
options=[""] + list(self.exp_data.algorithms.keys()),
case_sensitive=False,
search_strategy='includes',
restrict=False,
margin=(5, 0, 5, 0),
min_width=100,
sizing_mode="stretch_width",
)
@param.depends("first", "second", watch=True)
def set_pairs(self):
if self.first in self.exp_data.algorithms.keys() and self.second in self.exp_data.algorithms.keys():
self.algorithm_pairs = [(self.exp_data.algorithms[self.first], self.exp_data.algorithms[self.second])]
elif len(self.first) > 1 and len(self.second) > 1 and self.first[0] == self.first[-1] == self.second[0] == self.second[-1]:
result = []
subname1 = self.first[1:-1]
subname2 = self.second[1:-1]
match1 = [x for x in list(self.exp_data.algorithms.keys()) if subname1 in x]
match2 = [x for x in list(self.exp_data.algorithms.keys()) if subname2 in x]
for alg1 in match1:
for alg2 in match2:
if alg1.replace(subname1, "") == alg2.replace(subname2, ""):
result.append((self.exp_data.algorithms[alg1], self.exp_data.algorithms[alg2]))
self.algorithm_pairs = result
else:
self.algorithm_pairs = []
self.algorithm_pair_selector.param.trigger("entries")
class AlgorithmPairsSelector(Viewer):
entries = param.List(default=[])
algorithm_pairs = param.List(default=[])
def __init__(self, exp_data, **params):
super().__init__(**params)
self.exp_data = exp_data
self.entries = [AlgorithmPair(self, self.exp_data)]
self.param_view = pn.Column(
pn.Row(
pn.pane.HTML("<label>Algorithms</label>", margin=(5,-10,5,0)),
pn.widgets.TooltipIcon(
value='Each row specifies the algorithm used on the x '
'(left) and y (axis) for one subplot.\n'
'Specifying a pair "\*x\*" "\*y\*" will make a subplot '
'for all algorithm pairs whose name only differs in '
'that the x axis algorithm contains "x" and the '
'y axis algorithm contains "y".')
),
pn.Column(
pn.Row(self.entries[0].first_view, self.entries[0].second_view, margin=(-10,0,0,0))
),
pn.widgets.Button(name='+', button_type='primary', margin=(-2,0,5,0))
)
def add_button_clicked(event):
if not event:
return
self.entries.append(AlgorithmPair(self, self.exp_data))
# TODO: it would be nicer to define the param_view above reactively to just contain a row for each entry
# (then we could also avoid the setting of param_view in set_params()
self.param_view[1].append(pn.Row(self.entries[-1].first_view, self.entries[-1].second_view, margin=(-10,0,0,0)))
pn.bind(add_button_clicked, self.param_view[-1], watch=True)
@param.depends("entries", watch=True)
def set_pairs(self):
# We transform the list to a dict and back to a list to eliminate
# duplicates but preserving the order.
self.algorithm_pairs = list(dict.fromkeys([pair for object in self.entries for pair in object.algorithm_pairs]))
def __panel__(self):
return self.param_view
def get_params(self):
# TODO: It seems the encoding changes tuples to lists, can we avoid that and pass tuples here instead?
return [ [x.first, x.second] for x in self.entries if x.algorithm_pairs != [] ]
def set_params(self, l):
self.entries = [AlgorithmPair(self, self.exp_data, first=x[0], second=x[1]) for x in l]
self.param_view[1].objects = [pn.Row(x.first_view, x.second_view, margin=(-10,0,0,0)) for x in self.entries]