holobench 1.41.0__py3-none-any.whl → 1.43.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bencher/__init__.py +20 -2
- bencher/bench_cfg.py +262 -54
- bencher/bench_report.py +2 -2
- bencher/bench_runner.py +96 -10
- bencher/bencher.py +421 -89
- bencher/class_enum.py +70 -7
- bencher/example/example_dataframe.py +2 -2
- bencher/example/example_levels.py +17 -173
- bencher/example/example_pareto.py +107 -31
- bencher/example/example_rerun2.py +1 -1
- bencher/example/example_simple_bool.py +2 -2
- bencher/example/example_simple_float2d.py +6 -1
- bencher/example/example_video.py +2 -0
- bencher/example/experimental/example_hvplot_explorer.py +2 -2
- bencher/example/inputs_0D/example_0_in_1_out.py +25 -15
- bencher/example/inputs_0D/example_0_in_2_out.py +12 -3
- bencher/example/inputs_0_float/example_0_cat_in_2_out.py +88 -0
- bencher/example/inputs_0_float/example_1_cat_in_2_out.py +98 -0
- bencher/example/inputs_0_float/example_2_cat_in_2_out.py +107 -0
- bencher/example/inputs_0_float/example_3_cat_in_2_out.py +111 -0
- bencher/example/inputs_1D/example1d_common.py +48 -12
- bencher/example/inputs_1D/example_0_float_1_cat.py +33 -0
- bencher/example/inputs_1D/example_1_cat_in_2_out_repeats.py +68 -0
- bencher/example/inputs_1D/example_1_float_2_cat_repeats.py +3 -0
- bencher/example/inputs_1D/example_1_int_in_1_out.py +98 -0
- bencher/example/inputs_1D/example_1_int_in_2_out.py +101 -0
- bencher/example/inputs_1D/example_1_int_in_2_out_repeats.py +99 -0
- bencher/example/inputs_1_float/example_1_float_0_cat_in_2_out.py +117 -0
- bencher/example/inputs_1_float/example_1_float_1_cat_in_2_out.py +124 -0
- bencher/example/inputs_1_float/example_1_float_2_cat_in_2_out.py +132 -0
- bencher/example/inputs_1_float/example_1_float_3_cat_in_2_out.py +140 -0
- bencher/example/inputs_2D/example_2_cat_in_4_out_repeats.py +104 -0
- bencher/example/inputs_2_float/example_2_float_0_cat_in_2_out.py +98 -0
- bencher/example/inputs_2_float/example_2_float_1_cat_in_2_out.py +112 -0
- bencher/example/inputs_2_float/example_2_float_2_cat_in_2_out.py +122 -0
- bencher/example/inputs_2_float/example_2_float_3_cat_in_2_out.py +138 -0
- bencher/example/inputs_3_float/example_3_float_0_cat_in_2_out.py +111 -0
- bencher/example/inputs_3_float/example_3_float_1_cat_in_2_out.py +117 -0
- bencher/example/inputs_3_float/example_3_float_2_cat_in_2_out.py +124 -0
- bencher/example/inputs_3_float/example_3_float_3_cat_in_2_out.py +129 -0
- bencher/example/meta/generate_examples.py +118 -7
- bencher/example/meta/generate_meta.py +88 -40
- bencher/job.py +174 -9
- bencher/plotting/plot_filter.py +52 -17
- bencher/results/bench_result.py +117 -25
- bencher/results/bench_result_base.py +117 -8
- bencher/results/dataset_result.py +6 -200
- bencher/results/explorer_result.py +23 -0
- bencher/results/{hvplot_result.py → histogram_result.py} +3 -18
- bencher/results/holoview_results/__init__.py +0 -0
- bencher/results/holoview_results/bar_result.py +79 -0
- bencher/results/holoview_results/curve_result.py +110 -0
- bencher/results/holoview_results/distribution_result/__init__.py +0 -0
- bencher/results/holoview_results/distribution_result/box_whisker_result.py +73 -0
- bencher/results/holoview_results/distribution_result/distribution_result.py +109 -0
- bencher/results/holoview_results/distribution_result/scatter_jitter_result.py +92 -0
- bencher/results/holoview_results/distribution_result/violin_result.py +70 -0
- bencher/results/holoview_results/heatmap_result.py +319 -0
- bencher/results/holoview_results/holoview_result.py +346 -0
- bencher/results/holoview_results/line_result.py +240 -0
- bencher/results/holoview_results/scatter_result.py +107 -0
- bencher/results/holoview_results/surface_result.py +158 -0
- bencher/results/holoview_results/table_result.py +14 -0
- bencher/results/holoview_results/tabulator_result.py +20 -0
- bencher/results/optuna_result.py +30 -115
- bencher/results/video_controls.py +38 -0
- bencher/results/video_result.py +39 -36
- bencher/results/video_summary.py +2 -2
- bencher/results/{plotly_result.py → volume_result.py} +29 -8
- bencher/utils.py +175 -26
- bencher/variables/inputs.py +122 -15
- bencher/video_writer.py +2 -1
- bencher/worker_job.py +31 -3
- {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/METADATA +24 -24
- holobench-1.43.0.dist-info/RECORD +147 -0
- bencher/example/example_levels2.py +0 -37
- bencher/example/inputs_1D/example_1_in_1_out.py +0 -62
- bencher/example/inputs_1D/example_1_in_2_out.py +0 -63
- bencher/example/inputs_1D/example_1_in_2_out_repeats.py +0 -61
- bencher/results/holoview_result.py +0 -796
- bencher/results/panel_result.py +0 -41
- holobench-1.41.0.dist-info/RECORD +0 -114
- {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/WHEEL +0 -0
- {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,796 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
import logging
|
3
|
-
from typing import List, Optional
|
4
|
-
import panel as pn
|
5
|
-
import holoviews as hv
|
6
|
-
from param import Parameter
|
7
|
-
from functools import partial
|
8
|
-
import hvplot.xarray # noqa pylint: disable=duplicate-code,unused-import
|
9
|
-
import hvplot.pandas # noqa pylint: disable=duplicate-code,unused-import
|
10
|
-
import xarray as xr
|
11
|
-
|
12
|
-
from bencher.utils import (
|
13
|
-
hmap_canonical_input,
|
14
|
-
get_nearest_coords,
|
15
|
-
get_nearest_coords1D,
|
16
|
-
listify,
|
17
|
-
)
|
18
|
-
from bencher.results.panel_result import PanelResult
|
19
|
-
from bencher.results.bench_result_base import ReduceType
|
20
|
-
|
21
|
-
from bencher.plotting.plot_filter import PlotFilter, VarRange
|
22
|
-
from bencher.variables.results import ResultVar, ResultImage, ResultVideo
|
23
|
-
|
24
|
-
hv.extension("bokeh", "plotly")
|
25
|
-
|
26
|
-
# Flag to enable or disable tap tool functionality in visualizations
|
27
|
-
use_tap = True
|
28
|
-
|
29
|
-
|
30
|
-
class HoloviewResult(PanelResult):
|
31
|
-
@staticmethod
|
32
|
-
def set_default_opts(width=600, height=600):
|
33
|
-
width_heigh = {"width": width, "height": height, "tools": ["hover"]}
|
34
|
-
hv.opts.defaults(
|
35
|
-
hv.opts.Curve(**width_heigh),
|
36
|
-
hv.opts.Points(**width_heigh),
|
37
|
-
hv.opts.Bars(**width_heigh),
|
38
|
-
hv.opts.Scatter(**width_heigh),
|
39
|
-
hv.opts.HeatMap(cmap="plasma", **width_heigh, colorbar=True),
|
40
|
-
# hv.opts.Surface(**width_heigh),
|
41
|
-
hv.opts.GridSpace(plot_size=400),
|
42
|
-
)
|
43
|
-
return width_heigh
|
44
|
-
|
45
|
-
def to(self, hv_type: hv.Chart, reduce: ReduceType = ReduceType.AUTO, **kwargs) -> hv.Chart:
|
46
|
-
return self.to_hv_dataset(reduce).to(hv_type, **kwargs)
|
47
|
-
|
48
|
-
def overlay_plots(self, plot_callback: callable) -> Optional[hv.Overlay]:
|
49
|
-
results = []
|
50
|
-
markdown_results = pn.Row()
|
51
|
-
for rv in self.bench_cfg.result_vars:
|
52
|
-
res = plot_callback(rv)
|
53
|
-
if res is not None:
|
54
|
-
if isinstance(res, pn.pane.Markdown):
|
55
|
-
markdown_results.append(res)
|
56
|
-
else:
|
57
|
-
results.append(res)
|
58
|
-
if len(results) > 0:
|
59
|
-
overlay = hv.Overlay(results).collate()
|
60
|
-
if len(markdown_results) == 0:
|
61
|
-
return overlay
|
62
|
-
return pn.Row(overlay, markdown_results)
|
63
|
-
if len(markdown_results) > 0:
|
64
|
-
return markdown_results
|
65
|
-
return None
|
66
|
-
|
67
|
-
def layout_plots(self, plot_callback: callable):
|
68
|
-
if len(self.bench_cfg.result_vars) > 0:
|
69
|
-
pt = hv.Layout()
|
70
|
-
got_results = False
|
71
|
-
for rv in self.bench_cfg.result_vars:
|
72
|
-
res = plot_callback(rv)
|
73
|
-
if res is not None:
|
74
|
-
got_results = True
|
75
|
-
pt += plot_callback(rv)
|
76
|
-
return pt if got_results else None
|
77
|
-
return plot_callback(self.bench_cfg.result_vars[0])
|
78
|
-
|
79
|
-
def time_widget(self, title):
|
80
|
-
return {"title": title}
|
81
|
-
# if self.bench_cfg.over_time:
|
82
|
-
# time_widget_args = {"widget_type": "scrubber", "widget_location": "bottom"}
|
83
|
-
# time_widget_args["title"] = None # use the title generated by the widget instead
|
84
|
-
# else:
|
85
|
-
# time_widget_args = {"widget_type": "individual"}
|
86
|
-
# time_widget_args["title"] = title
|
87
|
-
|
88
|
-
# return time_widget_args
|
89
|
-
|
90
|
-
def to_bar(
|
91
|
-
self, result_var: Parameter = None, override: bool = False, **kwargs
|
92
|
-
) -> Optional[pn.panel]:
|
93
|
-
return self.filter(
|
94
|
-
self.to_bar_ds,
|
95
|
-
float_range=VarRange(0, 0),
|
96
|
-
cat_range=VarRange(0, None),
|
97
|
-
repeats_range=VarRange(1, 1),
|
98
|
-
panel_range=VarRange(0, None),
|
99
|
-
reduce=ReduceType.SQUEEZE,
|
100
|
-
target_dimension=2,
|
101
|
-
result_var=result_var,
|
102
|
-
result_types=(ResultVar),
|
103
|
-
override=override,
|
104
|
-
**kwargs,
|
105
|
-
)
|
106
|
-
|
107
|
-
def to_bar_ds(self, dataset: xr.Dataset, result_var: Parameter = None, **kwargs):
|
108
|
-
by = None
|
109
|
-
if self.plt_cnt_cfg.cat_cnt >= 2:
|
110
|
-
by = self.plt_cnt_cfg.cat_vars[1].name
|
111
|
-
da_plot = dataset[result_var.name]
|
112
|
-
title = self.title_from_ds(da_plot, result_var, **kwargs)
|
113
|
-
time_widget_args = self.time_widget(title)
|
114
|
-
return da_plot.hvplot.bar(by=by, **time_widget_args, **kwargs)
|
115
|
-
|
116
|
-
def hv_container_ds(
|
117
|
-
self,
|
118
|
-
dataset: xr.Dataset,
|
119
|
-
result_var: Parameter,
|
120
|
-
container: hv.Chart = None,
|
121
|
-
**kwargs,
|
122
|
-
):
|
123
|
-
return hv.Dataset(dataset[result_var.name]).to(container).opts(**kwargs)
|
124
|
-
|
125
|
-
def to_hv_container(
|
126
|
-
self,
|
127
|
-
container: pn.pane.panel,
|
128
|
-
reduce_type=ReduceType.AUTO,
|
129
|
-
target_dimension: int = 2,
|
130
|
-
result_var: Parameter = None,
|
131
|
-
result_types=(ResultVar),
|
132
|
-
**kwargs,
|
133
|
-
) -> Optional[pn.pane.panel]:
|
134
|
-
return self.map_plot_panes(
|
135
|
-
partial(self.hv_container_ds, container=container),
|
136
|
-
hv_dataset=self.to_hv_dataset(reduce_type),
|
137
|
-
target_dimension=target_dimension,
|
138
|
-
result_var=result_var,
|
139
|
-
result_types=result_types,
|
140
|
-
**kwargs,
|
141
|
-
)
|
142
|
-
|
143
|
-
def to_line(
|
144
|
-
self,
|
145
|
-
result_var: Parameter = None,
|
146
|
-
tap_var=None,
|
147
|
-
tap_container: pn.pane.panel = None,
|
148
|
-
target_dimension=2,
|
149
|
-
**kwargs,
|
150
|
-
) -> Optional[pn.panel]:
|
151
|
-
if tap_var is None:
|
152
|
-
tap_var = self.plt_cnt_cfg.panel_vars
|
153
|
-
elif not isinstance(tap_var, list):
|
154
|
-
tap_var = [tap_var]
|
155
|
-
|
156
|
-
if len(tap_var) == 0 or self.plt_cnt_cfg.inputs_cnt > 1 or not use_tap:
|
157
|
-
line_cb = self.to_line_ds
|
158
|
-
else:
|
159
|
-
line_cb = partial(
|
160
|
-
self.to_line_tap_ds, result_var_plots=tap_var, container=tap_container
|
161
|
-
)
|
162
|
-
|
163
|
-
return self.filter(
|
164
|
-
line_cb,
|
165
|
-
float_range=VarRange(1, 1),
|
166
|
-
cat_range=VarRange(0, None),
|
167
|
-
repeats_range=VarRange(1, 1),
|
168
|
-
panel_range=VarRange(0, None),
|
169
|
-
reduce=ReduceType.SQUEEZE,
|
170
|
-
target_dimension=target_dimension,
|
171
|
-
result_var=result_var,
|
172
|
-
result_types=(ResultVar),
|
173
|
-
**kwargs,
|
174
|
-
)
|
175
|
-
|
176
|
-
def to_line_ds(self, dataset: xr.Dataset, result_var: Parameter, **kwargs):
|
177
|
-
x = self.plt_cnt_cfg.float_vars[0].name
|
178
|
-
by = None
|
179
|
-
if self.plt_cnt_cfg.cat_cnt >= 1:
|
180
|
-
by = self.plt_cnt_cfg.cat_vars[0].name
|
181
|
-
da_plot = dataset[result_var.name]
|
182
|
-
title = self.title_from_ds(da_plot, result_var, **kwargs)
|
183
|
-
time_widget_args = self.time_widget(title)
|
184
|
-
return da_plot.hvplot.line(x=x, by=by, **time_widget_args, **kwargs)
|
185
|
-
|
186
|
-
def to_curve(self, result_var: Parameter = None, **kwargs):
|
187
|
-
return self.filter(
|
188
|
-
self.to_curve_ds,
|
189
|
-
float_range=VarRange(1, 1),
|
190
|
-
cat_range=VarRange(0, None),
|
191
|
-
repeats_range=VarRange(2, None),
|
192
|
-
reduce=ReduceType.REDUCE,
|
193
|
-
# reduce=ReduceType.MINMAX,
|
194
|
-
target_dimension=2,
|
195
|
-
result_var=result_var,
|
196
|
-
result_types=(ResultVar),
|
197
|
-
**kwargs,
|
198
|
-
)
|
199
|
-
|
200
|
-
def to_curve_ds(
|
201
|
-
self, dataset: xr.Dataset, result_var: Parameter, **kwargs
|
202
|
-
) -> Optional[hv.Curve]:
|
203
|
-
hvds = hv.Dataset(dataset)
|
204
|
-
title = self.title_from_ds(dataset, result_var, **kwargs)
|
205
|
-
# print(result_var.name)
|
206
|
-
# print( dataset)
|
207
|
-
pt = hv.Overlay()
|
208
|
-
# find pairs of {var_name} {var_name}_std to plot the line and their spreads.
|
209
|
-
var = result_var.name
|
210
|
-
std_var = f"{var}_std"
|
211
|
-
|
212
|
-
pt *= hvds.to(hv.Curve, vdims=var, label=var).opts(title=title, **kwargs)
|
213
|
-
# Only create a Spread if the matching _std variable exists
|
214
|
-
if std_var in dataset.data_vars:
|
215
|
-
pt *= hvds.to(hv.Spread, vdims=[var, std_var])
|
216
|
-
|
217
|
-
# for var in dataset.data_vars:
|
218
|
-
# print(var)
|
219
|
-
# if not var.endswith("_std"):
|
220
|
-
# std_var = f"{var}_std"
|
221
|
-
# pt *= hvds.to(hv.Curve, vdims=var, label=var).opts(title=title, **kwargs)
|
222
|
-
# #Only create a Spread if the matching _std variable exists
|
223
|
-
# if std_var in dataset.data_vars:
|
224
|
-
# pt *= hvds.to(hv.Spread, vdims=[var, std_var])
|
225
|
-
|
226
|
-
return pt.opts(legend_position="right")
|
227
|
-
|
228
|
-
def to_heatmap(
|
229
|
-
self,
|
230
|
-
result_var: Parameter = None,
|
231
|
-
tap_var=None,
|
232
|
-
tap_container: pn.pane.panel = None,
|
233
|
-
tap_container_direction: pn.Column | pn.Row = None,
|
234
|
-
target_dimension=2,
|
235
|
-
**kwargs,
|
236
|
-
) -> Optional[pn.panel]:
|
237
|
-
if tap_var is None:
|
238
|
-
tap_var = self.plt_cnt_cfg.panel_vars
|
239
|
-
elif not isinstance(tap_var, list):
|
240
|
-
tap_var = [tap_var]
|
241
|
-
|
242
|
-
if len(tap_var) == 0 or not use_tap:
|
243
|
-
heatmap_cb = self.to_heatmap_ds
|
244
|
-
else:
|
245
|
-
heatmap_cb = partial(
|
246
|
-
self.to_heatmap_container_tap_ds,
|
247
|
-
result_var_plots=tap_var,
|
248
|
-
container=tap_container,
|
249
|
-
tap_container_direction=tap_container_direction,
|
250
|
-
)
|
251
|
-
|
252
|
-
return self.filter(
|
253
|
-
heatmap_cb,
|
254
|
-
float_range=VarRange(0, None),
|
255
|
-
cat_range=VarRange(0, None),
|
256
|
-
input_range=VarRange(2, None),
|
257
|
-
panel_range=VarRange(0, None),
|
258
|
-
target_dimension=target_dimension,
|
259
|
-
result_var=result_var,
|
260
|
-
result_types=(ResultVar),
|
261
|
-
**kwargs,
|
262
|
-
)
|
263
|
-
|
264
|
-
def to_heatmap_ds(
|
265
|
-
self, dataset: xr.Dataset, result_var: Parameter, **kwargs
|
266
|
-
) -> Optional[hv.HeatMap]:
|
267
|
-
if len(dataset.dims) >= 2:
|
268
|
-
x = self.bench_cfg.input_vars[0].name
|
269
|
-
y = self.bench_cfg.input_vars[1].name
|
270
|
-
C = result_var.name
|
271
|
-
title = f"Heatmap of {result_var.name}"
|
272
|
-
time_args = self.time_widget(title)
|
273
|
-
return dataset.hvplot.heatmap(x=x, y=y, C=C, cmap="plasma", **time_args, **kwargs)
|
274
|
-
return None
|
275
|
-
|
276
|
-
def result_var_to_container(self, result_var):
|
277
|
-
if isinstance(result_var, ResultImage):
|
278
|
-
return pn.pane.PNG
|
279
|
-
return pn.pane.Video if isinstance(result_var, ResultVideo) else pn.Column
|
280
|
-
|
281
|
-
def setup_results_and_containers(self, result_var_plots, container, **kwargs):
|
282
|
-
result_var_plots = listify(result_var_plots)
|
283
|
-
if container is None:
|
284
|
-
containers = [self.result_var_to_container(rv) for rv in result_var_plots]
|
285
|
-
else:
|
286
|
-
containers = listify(container)
|
287
|
-
|
288
|
-
cont_instances = [c(**kwargs) if c is not None else None for c in containers]
|
289
|
-
return result_var_plots, cont_instances
|
290
|
-
|
291
|
-
def to_heatmap_container_tap_ds(
|
292
|
-
self,
|
293
|
-
dataset: xr.Dataset,
|
294
|
-
result_var: Parameter,
|
295
|
-
result_var_plots: List[Parameter] = None,
|
296
|
-
container: pn.pane.panel = None,
|
297
|
-
tap_container_direction: pn.Column | pn.Row = None,
|
298
|
-
**kwargs,
|
299
|
-
) -> pn.Row:
|
300
|
-
htmap = self.to_heatmap_ds(dataset, result_var).opts(tools=["hover"], **kwargs)
|
301
|
-
result_var_plots, cont_instances = self.setup_results_and_containers(
|
302
|
-
result_var_plots, container
|
303
|
-
)
|
304
|
-
title = pn.pane.Markdown("Selected: None")
|
305
|
-
|
306
|
-
state = dict(x=None, y=None, update=False)
|
307
|
-
|
308
|
-
def tap_plot_heatmap(x, y): # pragma: no cover
|
309
|
-
# print(f"moved {x}{y}")
|
310
|
-
x_nearest_new = get_nearest_coords1D(
|
311
|
-
x, dataset.coords[self.bench_cfg.input_vars[0].name].data
|
312
|
-
)
|
313
|
-
y_nearest_new = get_nearest_coords1D(
|
314
|
-
y, dataset.coords[self.bench_cfg.input_vars[1].name].data
|
315
|
-
)
|
316
|
-
|
317
|
-
# xv = self.bench_cfg.input_vars[0].name
|
318
|
-
# yv = self.bench_cfg.input_vars[1].name
|
319
|
-
# nearest = get_nearest_coords(dataset, **{xv: x, yv: y})
|
320
|
-
# print(nearest)
|
321
|
-
# print(x_nearest_new,y_nearest_new)
|
322
|
-
|
323
|
-
if x_nearest_new != state["x"]:
|
324
|
-
state["x"] = x_nearest_new
|
325
|
-
state["update"] = True
|
326
|
-
if y_nearest_new != state["y"]:
|
327
|
-
state["y"] = y_nearest_new
|
328
|
-
state["update"] = True
|
329
|
-
|
330
|
-
if state["update"]:
|
331
|
-
kdims = {}
|
332
|
-
kdims[self.bench_cfg.input_vars[0].name] = state["x"]
|
333
|
-
kdims[self.bench_cfg.input_vars[1].name] = state["y"]
|
334
|
-
|
335
|
-
if hasattr(htmap, "current_key"):
|
336
|
-
for d, k in zip(htmap.kdims, htmap.current_key):
|
337
|
-
kdims[d.name] = k
|
338
|
-
for rv, cont in zip(result_var_plots, cont_instances):
|
339
|
-
ds = dataset[rv.name]
|
340
|
-
val = ds.sel(**kdims)
|
341
|
-
item = self.zero_dim_da_to_val(val)
|
342
|
-
title.object = "Selected: " + ", ".join([f"{k}:{v}" for k, v in kdims.items()])
|
343
|
-
|
344
|
-
cont.object = item
|
345
|
-
if hasattr(cont, "autoplay"): # container is a video, set to autoplay
|
346
|
-
cont.paused = False
|
347
|
-
cont.time = 0
|
348
|
-
cont.loop = True
|
349
|
-
cont.autoplay = True
|
350
|
-
state["update"] = False
|
351
|
-
|
352
|
-
def on_exit(x, y): # pragma: no cover # pylint: disable=unused-argument
|
353
|
-
state["update"] = True
|
354
|
-
|
355
|
-
htmap_posxy = hv.streams.PointerXY(source=htmap)
|
356
|
-
htmap_posxy.add_subscriber(tap_plot_heatmap)
|
357
|
-
ls = hv.streams.MouseLeave(source=htmap)
|
358
|
-
ls.add_subscriber(on_exit)
|
359
|
-
|
360
|
-
if tap_container_direction is None:
|
361
|
-
tap_container_direction = pn.Column
|
362
|
-
bound_plot = tap_container_direction(*cont_instances)
|
363
|
-
|
364
|
-
return pn.Row(htmap, pn.Column(title, bound_plot))
|
365
|
-
|
366
|
-
def to_line_tap_ds(
|
367
|
-
self,
|
368
|
-
dataset: xr.Dataset,
|
369
|
-
result_var: Parameter,
|
370
|
-
result_var_plots: List[Parameter] = None,
|
371
|
-
container: pn.pane.panel = pn.pane.panel,
|
372
|
-
**kwargs,
|
373
|
-
) -> pn.Row:
|
374
|
-
htmap = self.to_line_ds(dataset, result_var).opts(tools=["hover"], **kwargs)
|
375
|
-
result_var_plots, cont_instances = self.setup_results_and_containers(
|
376
|
-
result_var_plots, container
|
377
|
-
)
|
378
|
-
title = pn.pane.Markdown("Selected: None")
|
379
|
-
|
380
|
-
state = dict(x=None, y=None, update=False)
|
381
|
-
|
382
|
-
def tap_plot_line(x, y): # pragma: no cover
|
383
|
-
# print(f"{x},{y}")
|
384
|
-
# print(dataset)
|
385
|
-
|
386
|
-
# xv = self.bench_cfg.input_vars[0].name
|
387
|
-
# yv = self.bench_cfg.input_vars[1].name
|
388
|
-
|
389
|
-
# x_nearest_new = get_nearest_coords1D(
|
390
|
-
# x, dataset.coords[self.bench_cfg.input_vars[0].name].data
|
391
|
-
# )
|
392
|
-
# y_nearest_new = get_nearest_coords1D(
|
393
|
-
# y, dataset.coords[self.bench_cfg.input_vars[1].name].data
|
394
|
-
# )
|
395
|
-
|
396
|
-
# kwargs = {xv: x, yv: y}
|
397
|
-
|
398
|
-
# nearest = get_nearest_coords(dataset, **kwargs)
|
399
|
-
# print(nearest)
|
400
|
-
|
401
|
-
x_nearest_new = get_nearest_coords1D(
|
402
|
-
x, dataset.coords[self.bench_cfg.input_vars[0].name].data
|
403
|
-
)
|
404
|
-
|
405
|
-
if x_nearest_new != state["x"]:
|
406
|
-
state["x"] = x_nearest_new
|
407
|
-
state["update"] = True
|
408
|
-
|
409
|
-
if self.plt_cnt_cfg.inputs_cnt > 1:
|
410
|
-
y_nearest_new = get_nearest_coords1D(
|
411
|
-
y, dataset.coords[self.bench_cfg.input_vars[1].name].data
|
412
|
-
)
|
413
|
-
if y_nearest_new != state["y"]:
|
414
|
-
state["y"] = y_nearest_new
|
415
|
-
state["update"] = True
|
416
|
-
|
417
|
-
if state["update"]:
|
418
|
-
kdims = {}
|
419
|
-
kdims[self.bench_cfg.input_vars[0].name] = state["x"]
|
420
|
-
if self.plt_cnt_cfg.inputs_cnt > 1:
|
421
|
-
kdims[self.bench_cfg.input_vars[1].name] = state["y"]
|
422
|
-
|
423
|
-
if hasattr(htmap, "current_key"):
|
424
|
-
for d, k in zip(htmap.kdims, htmap.current_key):
|
425
|
-
kdims[d.name] = k
|
426
|
-
for rv, cont in zip(result_var_plots, cont_instances):
|
427
|
-
ds = dataset[rv.name]
|
428
|
-
val = ds.sel(**kdims)
|
429
|
-
item = self.zero_dim_da_to_val(val)
|
430
|
-
title.object = "Selected: " + ", ".join([f"{k}:{v}" for k, v in kdims.items()])
|
431
|
-
cont.object = item
|
432
|
-
if hasattr(cont, "autoplay"): # container is a video, set to autoplay
|
433
|
-
cont.paused = False
|
434
|
-
cont.time = 0
|
435
|
-
cont.loop = True
|
436
|
-
cont.autoplay = True
|
437
|
-
state["update"] = False
|
438
|
-
|
439
|
-
def on_exit(x, y): # pragma: no cover # pylint: disable=unused-argument
|
440
|
-
state["update"] = True
|
441
|
-
|
442
|
-
htmap_posxy = hv.streams.PointerXY(source=htmap)
|
443
|
-
htmap_posxy.add_subscriber(tap_plot_line)
|
444
|
-
ls = hv.streams.MouseLeave(source=htmap)
|
445
|
-
ls.add_subscriber(on_exit)
|
446
|
-
bound_plot = pn.Column(title, *cont_instances)
|
447
|
-
return pn.Row(htmap, bound_plot)
|
448
|
-
|
449
|
-
def to_error_bar(self) -> hv.Bars:
|
450
|
-
return self.to_hv_dataset(ReduceType.REDUCE).to(hv.ErrorBars)
|
451
|
-
|
452
|
-
def to_points(self, reduce: ReduceType = ReduceType.AUTO) -> hv.Points:
|
453
|
-
ds = self.to_hv_dataset(reduce)
|
454
|
-
pt = ds.to(hv.Points)
|
455
|
-
if reduce:
|
456
|
-
pt *= ds.to(hv.ErrorBars)
|
457
|
-
return pt
|
458
|
-
|
459
|
-
def to_scatter(self, **kwargs) -> Optional[pn.panel]:
|
460
|
-
match_res = PlotFilter(
|
461
|
-
float_range=VarRange(0, 0),
|
462
|
-
cat_range=VarRange(0, None),
|
463
|
-
repeats_range=VarRange(1, 1),
|
464
|
-
).matches_result(self.plt_cnt_cfg, "to_hvplot_scatter")
|
465
|
-
if match_res.overall:
|
466
|
-
hv_ds = self.to_hv_dataset(ReduceType.SQUEEZE)
|
467
|
-
by = None
|
468
|
-
subplots = False
|
469
|
-
if self.plt_cnt_cfg.cat_cnt > 1:
|
470
|
-
by = [v.name for v in self.bench_cfg.input_vars[1:]]
|
471
|
-
subplots = False
|
472
|
-
return hv_ds.data.hvplot.scatter(by=by, subplots=subplots, **kwargs).opts(
|
473
|
-
title=self.to_plot_title()
|
474
|
-
)
|
475
|
-
return match_res.to_panel(**kwargs)
|
476
|
-
|
477
|
-
# def to_scatter_jitter(self, **kwargs) -> Optional[hv.Scatter]:
|
478
|
-
# matches = PlotFilter(
|
479
|
-
# float_range=VarRange(0, 0),
|
480
|
-
# cat_range=VarRange(0, None),
|
481
|
-
# repeats_range=VarRange(2, None),
|
482
|
-
# input_range=VarRange(1, None),
|
483
|
-
# ).matches_result(self.plt_cnt_cfg, "to_scatter_jitter")
|
484
|
-
# if matches.overall:
|
485
|
-
# hv_ds = self.to_hv_dataset(ReduceType.NONE)
|
486
|
-
|
487
|
-
# by = None
|
488
|
-
# groupby = None
|
489
|
-
# subplots=False
|
490
|
-
# if self.plt_cnt_cfg.cat_cnt > 1:
|
491
|
-
# by = [v.name for v in self.bench_cfg.all_vars[1:]]
|
492
|
-
# subplots=False
|
493
|
-
# return hv_ds.data.hvplot.scatter(by=by,subplots=subplots, **kwargs).opts(title=self.to_plot_title())
|
494
|
-
|
495
|
-
# # pt = (
|
496
|
-
# # hv_ds.to(hv.Scatter)
|
497
|
-
# # .opts(jitter=0.1)
|
498
|
-
# # .overlay("repeat")
|
499
|
-
# # .opts(show_legend=False, title=self.to_plot_title(), **kwargs)
|
500
|
-
# # )
|
501
|
-
# # return pt
|
502
|
-
# return matches.to_panel()
|
503
|
-
|
504
|
-
# def to_scatter_jitter_multi(self, **kwargs) -> Optional[hv.Scatter]:
|
505
|
-
# matches = PlotFilter(
|
506
|
-
# float_range=VarRange(0, 0),
|
507
|
-
# cat_range=VarRange(0, None),
|
508
|
-
# repeats_range=VarRange(2, None),
|
509
|
-
# input_range=VarRange(1, None),
|
510
|
-
# ).matches_result(self.plt_cnt_cfg, "to_scatter_jitter")
|
511
|
-
# if matches.overall:
|
512
|
-
# hv_dataset = self.to_hv_dataset(ReduceType.NONE)
|
513
|
-
|
514
|
-
# print("KDIMS",hv_dataset.kdims)
|
515
|
-
# # hv_dataset.kdims =[hv_dataset.kdims[2],hv_dataset.kdims[1],hv_dataset.kdims[0]]
|
516
|
-
# # print("KDIMS",hv_dataset.kdims)
|
517
|
-
|
518
|
-
# # exit()
|
519
|
-
# cb = partial(self.to_scatter_jitter_da, **kwargs)
|
520
|
-
# return self.to_panes_multi_panel(hv_dataset, None, plot_callback=cb, target_dimension=3)
|
521
|
-
# return matches.to_panel()
|
522
|
-
|
523
|
-
# def to_scatter_jitter_da(self, ds: xr.Dataset, **kwargs) -> Optional[hv.Scatter]:
|
524
|
-
# matches = PlotFilter(
|
525
|
-
# float_range=VarRange(0, 0),
|
526
|
-
# cat_range=VarRange(0, None),
|
527
|
-
# repeats_range=VarRange(2, None),
|
528
|
-
# input_range=VarRange(1, None),
|
529
|
-
# ).matches_result(self.plt_cnt_cfg, "to_scatter_jitter")
|
530
|
-
# if matches.overall:
|
531
|
-
|
532
|
-
# print("DA IN",da)
|
533
|
-
# da = self.to_hv_dataset(ReduceType.NONE)
|
534
|
-
# hvds = hv.Dataset(da)
|
535
|
-
# # return None
|
536
|
-
|
537
|
-
# # print("DA FRESH",da)
|
538
|
-
# result_var = self.bench_cfg.result_vars[0]
|
539
|
-
|
540
|
-
# print(hvds.data.sizes)
|
541
|
-
# print("repeat" in hvds.data.sizes)
|
542
|
-
# # if "repeat" in hvds.data.sizes:
|
543
|
-
# # try:
|
544
|
-
# # pt = (
|
545
|
-
# # hvds.to(hv.Scatter)
|
546
|
-
# # .opts(jitter=0.1)
|
547
|
-
# # # .overlay()
|
548
|
-
# # .overlay("repeat")
|
549
|
-
# # .opts(show_legend=False, title=self.to_plot_title(), clabel=result_var.name, **kwargs)
|
550
|
-
# # )
|
551
|
-
# # except:
|
552
|
-
# pt = (
|
553
|
-
# hvds.to(hv.Scatter)
|
554
|
-
# .opts(jitter=0.1)
|
555
|
-
# # .overlay()
|
556
|
-
# # .overlay("repeat")
|
557
|
-
# .opts(show_legend=False, title=self.to_plot_title(), clabel=result_var.name, **kwargs)
|
558
|
-
# )
|
559
|
-
# return pt
|
560
|
-
# return matches.to_panel()
|
561
|
-
|
562
|
-
def to_scatter_jitter(
|
563
|
-
self,
|
564
|
-
result_var: Parameter = None,
|
565
|
-
override: bool = False,
|
566
|
-
**kwargs, # pylint: disable=unused-argument
|
567
|
-
) -> List[hv.Scatter]:
|
568
|
-
return self.overlay_plots(
|
569
|
-
partial(self.to_scatter_jitter_single, override=override, **kwargs)
|
570
|
-
)
|
571
|
-
|
572
|
-
def to_scatter_jitter_single(
|
573
|
-
self, result_var: Parameter, override: bool = True, **kwargs
|
574
|
-
) -> Optional[hv.Scatter]:
|
575
|
-
matches = PlotFilter(
|
576
|
-
float_range=VarRange(0, 0),
|
577
|
-
cat_range=VarRange(0, None),
|
578
|
-
repeats_range=VarRange(2, None),
|
579
|
-
input_range=VarRange(1, None),
|
580
|
-
).matches_result(self.plt_cnt_cfg, "to_scatter_jitter", override)
|
581
|
-
if matches.overall:
|
582
|
-
ds = self.to_hv_dataset(ReduceType.NONE)
|
583
|
-
pt = (
|
584
|
-
ds.to(hv.Scatter, vdims=[result_var.name], label=result_var.name)
|
585
|
-
.opts(jitter=0.1, show_legend=False, title=self.to_plot_title(), **kwargs)
|
586
|
-
.overlay("repeat")
|
587
|
-
)
|
588
|
-
return pt
|
589
|
-
return matches.to_panel()
|
590
|
-
|
591
|
-
def to_heatmap_single(
|
592
|
-
self, result_var: Parameter, reduce: ReduceType = ReduceType.AUTO, **kwargs
|
593
|
-
) -> hv.HeatMap:
|
594
|
-
matches_res = PlotFilter(
|
595
|
-
float_range=VarRange(2, None),
|
596
|
-
cat_range=VarRange(0, None),
|
597
|
-
input_range=VarRange(1, None),
|
598
|
-
).matches_result(self.plt_cnt_cfg, "to_heatmap")
|
599
|
-
if matches_res.overall:
|
600
|
-
z = result_var
|
601
|
-
title = f"{z.name} vs ("
|
602
|
-
|
603
|
-
for iv in self.bench_cfg.input_vars:
|
604
|
-
title += f" vs {iv.name}"
|
605
|
-
title += ")"
|
606
|
-
|
607
|
-
color_label = f"{z.name} [{z.units}]"
|
608
|
-
|
609
|
-
return self.to(hv.HeatMap, reduce).opts(clabel=color_label, **kwargs)
|
610
|
-
return matches_res.to_panel()
|
611
|
-
|
612
|
-
def to_heatmap_tap(
|
613
|
-
self,
|
614
|
-
result_var: Parameter,
|
615
|
-
reduce: ReduceType = ReduceType.AUTO,
|
616
|
-
width=800,
|
617
|
-
height=800,
|
618
|
-
**kwargs,
|
619
|
-
):
|
620
|
-
htmap = self.to_heatmap_single(result_var, reduce).opts(
|
621
|
-
tools=["hover", "tap"], width=width, height=height
|
622
|
-
)
|
623
|
-
htmap_posxy = hv.streams.Tap(source=htmap, x=0, y=0)
|
624
|
-
|
625
|
-
def tap_plot(x, y):
|
626
|
-
kwargs[self.bench_cfg.input_vars[0].name] = x
|
627
|
-
kwargs[self.bench_cfg.input_vars[1].name] = y
|
628
|
-
return self.get_nearest_holomap(**kwargs).opts(width=width, height=height)
|
629
|
-
|
630
|
-
tap_htmap = hv.DynamicMap(tap_plot, streams=[htmap_posxy])
|
631
|
-
return htmap + tap_htmap
|
632
|
-
|
633
|
-
def to_nd_layout(self, hmap_name: str) -> hv.NdLayout:
|
634
|
-
return hv.NdLayout(self.get_hmap(hmap_name), kdims=self.bench_cfg.hmap_kdims).opts(
|
635
|
-
shared_axes=False, shared_datasource=False
|
636
|
-
)
|
637
|
-
|
638
|
-
def to_holomap(self, name: str = None) -> hv.HoloMap:
|
639
|
-
return hv.HoloMap(self.to_nd_layout(name)).opts(shared_axes=False)
|
640
|
-
|
641
|
-
def to_holomap_list(self, hmap_names: List[str] = None) -> hv.HoloMap:
|
642
|
-
if hmap_names is None:
|
643
|
-
hmap_names = [i.name for i in self.result_hmaps]
|
644
|
-
col = pn.Column()
|
645
|
-
for name in hmap_names:
|
646
|
-
self.to_holomap(name)
|
647
|
-
return col
|
648
|
-
|
649
|
-
def get_nearest_holomap(self, name: str = None, **kwargs):
|
650
|
-
canonical_inp = hmap_canonical_input(
|
651
|
-
get_nearest_coords(self.ds, collapse_list=True, **kwargs)
|
652
|
-
)
|
653
|
-
return self.get_hmap(name)[canonical_inp].opts(framewise=True)
|
654
|
-
|
655
|
-
def to_dynamic_map(self, name: str = None) -> hv.DynamicMap:
|
656
|
-
"""use the values stored in the holomap dictionary to populate a dynamic map. Note that this is much faster than passing the holomap to a holomap object as the values are calculated on the fly"""
|
657
|
-
|
658
|
-
def cb(**kwargs):
|
659
|
-
return self.get_hmap(name)[hmap_canonical_input(kwargs)].opts(
|
660
|
-
framewise=True, shared_axes=False
|
661
|
-
)
|
662
|
-
|
663
|
-
kdims = []
|
664
|
-
for i in self.bench_cfg.input_vars + [self.bench_cfg.iv_repeat]:
|
665
|
-
kdims.append(i.as_dim(compute_values=True))
|
666
|
-
|
667
|
-
return hv.DynamicMap(cb, kdims=kdims)
|
668
|
-
|
669
|
-
def to_grid(self, inputs=None):
|
670
|
-
if inputs is None:
|
671
|
-
inputs = self.bench_cfg.inputs_as_str()
|
672
|
-
if len(inputs) > 2:
|
673
|
-
inputs = inputs[:2]
|
674
|
-
return self.to_holomap().grid(inputs)
|
675
|
-
|
676
|
-
def to_table(self):
|
677
|
-
return self.to(hv.Table, ReduceType.SQUEEZE)
|
678
|
-
|
679
|
-
def to_tabulator(self, **kwargs):
|
680
|
-
"""Passes the data to the panel Tabulator type to display an interactive table
|
681
|
-
see https://panel.holoviz.org/reference/widgets/Tabulator.html for extra options
|
682
|
-
"""
|
683
|
-
return pn.widgets.Tabulator(self.to_pandas(), **kwargs)
|
684
|
-
|
685
|
-
def to_surface(self, result_var: Parameter = None, **kwargs) -> Optional[pn.pane.Pane]:
|
686
|
-
return self.filter(
|
687
|
-
self.to_surface_ds,
|
688
|
-
float_range=VarRange(2, None),
|
689
|
-
cat_range=VarRange(0, None),
|
690
|
-
input_range=VarRange(1, None),
|
691
|
-
reduce=ReduceType.REDUCE,
|
692
|
-
target_dimension=2,
|
693
|
-
result_var=result_var,
|
694
|
-
result_types=(ResultVar),
|
695
|
-
**kwargs,
|
696
|
-
)
|
697
|
-
|
698
|
-
def to_surface_ds(
|
699
|
-
self, dataset: xr.Dataset, result_var: Parameter, alpha: float = 0.3, **kwargs
|
700
|
-
) -> Optional[pn.panel]:
|
701
|
-
"""Given a benchCfg generate a 2D surface plot
|
702
|
-
|
703
|
-
Args:
|
704
|
-
result_var (Parameter): result variable to plot
|
705
|
-
|
706
|
-
Returns:
|
707
|
-
pn.pane.holoview: A 2d surface plot as a holoview in a pane
|
708
|
-
"""
|
709
|
-
matches_res = PlotFilter(
|
710
|
-
float_range=VarRange(2, 2),
|
711
|
-
cat_range=VarRange(0, None),
|
712
|
-
vector_len=VarRange(1, 1),
|
713
|
-
result_vars=VarRange(1, 1),
|
714
|
-
).matches_result(self.plt_cnt_cfg, "to_surface_hv")
|
715
|
-
if matches_res.overall:
|
716
|
-
# xr_cfg = plot_float_cnt_2(self.plt_cnt_cfg, result_var)
|
717
|
-
|
718
|
-
# TODO a warning suggests setting this parameter, but it does not seem to help as expected, leaving here to fix in the future
|
719
|
-
# hv.config.image_rtol = 1.0
|
720
|
-
|
721
|
-
mean = dataset[result_var.name]
|
722
|
-
|
723
|
-
hvds = hv.Dataset(dataset[result_var.name])
|
724
|
-
|
725
|
-
x = self.plt_cnt_cfg.float_vars[0]
|
726
|
-
y = self.plt_cnt_cfg.float_vars[1]
|
727
|
-
|
728
|
-
try:
|
729
|
-
surface = hvds.to(hv.Surface, vdims=[result_var.name])
|
730
|
-
surface = surface.opts(colorbar=True)
|
731
|
-
except Exception as e: # pylint: disable=broad-except
|
732
|
-
logging.warning(e)
|
733
|
-
|
734
|
-
if self.bench_cfg.repeats > 1:
|
735
|
-
std_dev = dataset[f"{result_var.name}_std"]
|
736
|
-
|
737
|
-
upper = mean + std_dev
|
738
|
-
upper.name = result_var.name
|
739
|
-
|
740
|
-
lower = mean - std_dev
|
741
|
-
lower.name = result_var.name
|
742
|
-
|
743
|
-
surface *= (
|
744
|
-
hv.Dataset(upper)
|
745
|
-
.to(hv.Surface)
|
746
|
-
.opts(alpha=alpha, colorbar=False, backend="plotly")
|
747
|
-
)
|
748
|
-
surface *= (
|
749
|
-
hv.Dataset(lower)
|
750
|
-
.to(hv.Surface)
|
751
|
-
.opts(alpha=alpha, colorbar=False, backend="plotly")
|
752
|
-
)
|
753
|
-
|
754
|
-
surface = surface.opts(
|
755
|
-
zlabel=f"{result_var.name} [{result_var.units}]",
|
756
|
-
title=f"{result_var.name} vs ({x.name} and {y.name})",
|
757
|
-
backend="plotly",
|
758
|
-
**kwargs,
|
759
|
-
)
|
760
|
-
|
761
|
-
if self.bench_cfg.render_plotly:
|
762
|
-
hv.extension("plotly")
|
763
|
-
out = surface
|
764
|
-
else:
|
765
|
-
# using render disabled the holoviews sliders :(
|
766
|
-
out = hv.render(surface, backend="plotly")
|
767
|
-
return pn.Column(out, name="surface_hv")
|
768
|
-
|
769
|
-
return matches_res.to_panel()
|
770
|
-
|
771
|
-
# def plot_scatter2D_hv(self, rv: ParametrizedSweep) -> pn.pane.Plotly:
|
772
|
-
# import plotly.express as px
|
773
|
-
|
774
|
-
# """Given a benchCfg generate a 2D scatter plot
|
775
|
-
|
776
|
-
# Args:
|
777
|
-
# bench_cfg (BenchCfg): description of benchmark
|
778
|
-
# rv (ParametrizedSweep): result variable to plot
|
779
|
-
|
780
|
-
# Returns:
|
781
|
-
# pn.pane.Plotly: A 3d volume plot as a holoview in a pane
|
782
|
-
# """
|
783
|
-
|
784
|
-
# # bench_cfg = wrap_long_time_labels(bench_cfg)
|
785
|
-
# self.ds.drop_vars("repeat")
|
786
|
-
|
787
|
-
# df = self.to_pandas()
|
788
|
-
|
789
|
-
# names = rv.index_names()
|
790
|
-
|
791
|
-
# return px.scatter(
|
792
|
-
# df, x=names[0], y=names[1], marginal_x="histogram", marginal_y="histogram"
|
793
|
-
# )
|
794
|
-
|
795
|
-
|
796
|
-
HoloviewResult.set_default_opts()
|