-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproblem_table.py
More file actions
154 lines (128 loc) · 6.17 KB
/
problem_table.py
File metadata and controls
154 lines (128 loc) · 6.17 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import logging
import param
import pandas as pd
import panel as pn
from report import Report
logger = logging.getLogger("visualizer.problem_table")
class ProblemTable(Report):
domain = param.Parameter(label="Domain", default="")
problem = param.Parameter(label="Problem", default="")
algorithms = param.List(label="Algorithms", default=[])
# internal parameters
df = param.DataFrame(default=pd.DataFrame(), precedence=-1)
def __init__(self, experiment_data, sizing_mode = "stretch_both", **params):
super().__init__(experiment_data, **params)
self.report_information = """
<p>Show all attributes for a single problem.</p>"""
# setting experiment_data in super triggers select_all_algorithms(),
# meaning we need to set it to the given parameter manually here
if "algorithms" in params:
self.algorithms = params["algorithms"]
self.data_view = pn.widgets.Tabulator(
value=self.param.df, disabled = True, sortable=False, pagination="remote", page_size=10000, widths=250,
frozen_columns = ["attribute"], show_index = False, sizing_mode=sizing_mode)
self.data_view.style.apply(func=self.style_table_by_row, axis=1)
self.param_view.extend([
pn.pane.HTML("<label>Domain</label>", margin=(5, 0, -5, 0)),
pn.widgets.Select.from_param(
self.param.domain,
name="",
options=self.experiment_data.param.domains,
margin=(5, 0, 5, 0),
min_width=100,
sizing_mode="stretch_width"
),
pn.pane.HTML("<label>Problem</label>", margin=(5, 0, -5, 0)),
pn.widgets.Select.from_param(
self.param.problem,
name="",
options=[],
margin=(5, 0, 5, 0),
min_width=100,
sizing_mode="stretch_width"
),
pn.pane.HTML("<label>Algorithms</label>", margin=(5, 0, -5, 0)),
pn.widgets.CrossSelector.from_param(
self.param.algorithms,
name="",
definition_order=False,
# we don't set possible options here but use "select_all_algorithms()" to update it
# (setting options here with 'options = self.experiment_data.param.algorithms'
# crashes when calling a FloatPanel Report)
# options = self.experiment_data.param.algorithms,
margin=(5, 0, 5, 0),
width=400 #TODO: can we have a min_width with stretching? (Could not get it to work so far)
)
])
def style_table_by_row(self, row):
style = [""] * len(row)
numeric_attribute = self.experiment_data.numeric_attributes.get(row.iloc[0], None)
if numeric_attribute is None: # the attribute is not a numeric attribute
return style
numeric_values = pd.to_numeric(row,errors='coerce')
min_val = numeric_values.dropna().min()
max_val = numeric_values.dropna().max()
if min_val == max_val:
return style
for i, val in enumerate(numeric_values):
if not pd.isnull(val):
percentage = (val - min_val) / (max_val-min_val)
if numeric_attribute.min_wins:
percentage = 1-percentage
green = (percentage*175).astype(int)
blue = ((1-percentage)*255).astype(int)
style[i] = style[i]+ "color: #00{:02x}{:02x};".format(green, blue)
return style
# TODO see if we can do the two functions below reactive functions instead.
@param.depends("experiment_data.algorithms", watch=True)
def select_all_algorithms(self):
logger.debug("experiment data algorithms changed")
self.param.algorithms.default = list(self.experiment_data.algorithms.values())
# TODO: can we do this nicer? The function can already trigger when
# calling super().__init__(), which sets experiment_data, and at this
# point param_view does not exist yet.
if hasattr(self, 'param_view'):
self.param_view[4].options = self.param.algorithms.default
self.algorithms = self.param.algorithms.default
@param.depends('domain', watch=True)
def update_problems(self):
logger.debug("start updating problem selection")
self.param_view[3].options = [] if not self.domain or self.domain == "" else self.experiment_data.problems_by_domain[self.domain]
logger.debug("end updating problem selection")
@param.depends("domain", "problem", "algorithms", watch=True)
def update_data(self):
logger.debug("start updating data")
if not self.problem or self.problem == "" or not self.algorithms:
self.df = pd.DataFrame()
else:
tmp = self.experiment_data.get_data(self.experiment_data.attributes, self.algorithms)
self.df = tmp.xs((self.domain, self.problem), level=(1,2)).reset_index()
logger.debug("end updating data")
# Trigger a redraw when min_wins settings change
@param.depends("experiment_data.custom_min_wins", watch=True)
def redraw(self):
self.param.trigger("df")
def get_watchers_for_param_config(self):
return [
"domain",
"problem",
"algorithms"
]
def get_param_config_dict(self):
d = {}
if self.domain != self.param.domain.default:
d["dom"] = self.domain
if self.problem != self.param.domain.default:
d["prob"] = self.problem
if self.algorithms != self.param.algorithms.default:
d["algs"] = [alg.id for alg in self.algorithms]
return d
def set_params_from_param_config_dict(self, param_config_dict):
update = {}
if "dom" in param_config_dict:
update["domain"] = param_config_dict["dom"]
if "prob" in param_config_dict:
update["problem"] = param_config_dict["prob"]
if "algs" in param_config_dict:
update["algorithms"] = [self.experiment_data.get_algorithm_by_id(id) for id in param_config_dict["algs"]]
self.param.update(update)