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.
Files changed (84) hide show
  1. bencher/__init__.py +20 -2
  2. bencher/bench_cfg.py +262 -54
  3. bencher/bench_report.py +2 -2
  4. bencher/bench_runner.py +96 -10
  5. bencher/bencher.py +421 -89
  6. bencher/class_enum.py +70 -7
  7. bencher/example/example_dataframe.py +2 -2
  8. bencher/example/example_levels.py +17 -173
  9. bencher/example/example_pareto.py +107 -31
  10. bencher/example/example_rerun2.py +1 -1
  11. bencher/example/example_simple_bool.py +2 -2
  12. bencher/example/example_simple_float2d.py +6 -1
  13. bencher/example/example_video.py +2 -0
  14. bencher/example/experimental/example_hvplot_explorer.py +2 -2
  15. bencher/example/inputs_0D/example_0_in_1_out.py +25 -15
  16. bencher/example/inputs_0D/example_0_in_2_out.py +12 -3
  17. bencher/example/inputs_0_float/example_0_cat_in_2_out.py +88 -0
  18. bencher/example/inputs_0_float/example_1_cat_in_2_out.py +98 -0
  19. bencher/example/inputs_0_float/example_2_cat_in_2_out.py +107 -0
  20. bencher/example/inputs_0_float/example_3_cat_in_2_out.py +111 -0
  21. bencher/example/inputs_1D/example1d_common.py +48 -12
  22. bencher/example/inputs_1D/example_0_float_1_cat.py +33 -0
  23. bencher/example/inputs_1D/example_1_cat_in_2_out_repeats.py +68 -0
  24. bencher/example/inputs_1D/example_1_float_2_cat_repeats.py +3 -0
  25. bencher/example/inputs_1D/example_1_int_in_1_out.py +98 -0
  26. bencher/example/inputs_1D/example_1_int_in_2_out.py +101 -0
  27. bencher/example/inputs_1D/example_1_int_in_2_out_repeats.py +99 -0
  28. bencher/example/inputs_1_float/example_1_float_0_cat_in_2_out.py +117 -0
  29. bencher/example/inputs_1_float/example_1_float_1_cat_in_2_out.py +124 -0
  30. bencher/example/inputs_1_float/example_1_float_2_cat_in_2_out.py +132 -0
  31. bencher/example/inputs_1_float/example_1_float_3_cat_in_2_out.py +140 -0
  32. bencher/example/inputs_2D/example_2_cat_in_4_out_repeats.py +104 -0
  33. bencher/example/inputs_2_float/example_2_float_0_cat_in_2_out.py +98 -0
  34. bencher/example/inputs_2_float/example_2_float_1_cat_in_2_out.py +112 -0
  35. bencher/example/inputs_2_float/example_2_float_2_cat_in_2_out.py +122 -0
  36. bencher/example/inputs_2_float/example_2_float_3_cat_in_2_out.py +138 -0
  37. bencher/example/inputs_3_float/example_3_float_0_cat_in_2_out.py +111 -0
  38. bencher/example/inputs_3_float/example_3_float_1_cat_in_2_out.py +117 -0
  39. bencher/example/inputs_3_float/example_3_float_2_cat_in_2_out.py +124 -0
  40. bencher/example/inputs_3_float/example_3_float_3_cat_in_2_out.py +129 -0
  41. bencher/example/meta/generate_examples.py +118 -7
  42. bencher/example/meta/generate_meta.py +88 -40
  43. bencher/job.py +174 -9
  44. bencher/plotting/plot_filter.py +52 -17
  45. bencher/results/bench_result.py +117 -25
  46. bencher/results/bench_result_base.py +117 -8
  47. bencher/results/dataset_result.py +6 -200
  48. bencher/results/explorer_result.py +23 -0
  49. bencher/results/{hvplot_result.py → histogram_result.py} +3 -18
  50. bencher/results/holoview_results/__init__.py +0 -0
  51. bencher/results/holoview_results/bar_result.py +79 -0
  52. bencher/results/holoview_results/curve_result.py +110 -0
  53. bencher/results/holoview_results/distribution_result/__init__.py +0 -0
  54. bencher/results/holoview_results/distribution_result/box_whisker_result.py +73 -0
  55. bencher/results/holoview_results/distribution_result/distribution_result.py +109 -0
  56. bencher/results/holoview_results/distribution_result/scatter_jitter_result.py +92 -0
  57. bencher/results/holoview_results/distribution_result/violin_result.py +70 -0
  58. bencher/results/holoview_results/heatmap_result.py +319 -0
  59. bencher/results/holoview_results/holoview_result.py +346 -0
  60. bencher/results/holoview_results/line_result.py +240 -0
  61. bencher/results/holoview_results/scatter_result.py +107 -0
  62. bencher/results/holoview_results/surface_result.py +158 -0
  63. bencher/results/holoview_results/table_result.py +14 -0
  64. bencher/results/holoview_results/tabulator_result.py +20 -0
  65. bencher/results/optuna_result.py +30 -115
  66. bencher/results/video_controls.py +38 -0
  67. bencher/results/video_result.py +39 -36
  68. bencher/results/video_summary.py +2 -2
  69. bencher/results/{plotly_result.py → volume_result.py} +29 -8
  70. bencher/utils.py +175 -26
  71. bencher/variables/inputs.py +122 -15
  72. bencher/video_writer.py +2 -1
  73. bencher/worker_job.py +31 -3
  74. {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/METADATA +24 -24
  75. holobench-1.43.0.dist-info/RECORD +147 -0
  76. bencher/example/example_levels2.py +0 -37
  77. bencher/example/inputs_1D/example_1_in_1_out.py +0 -62
  78. bencher/example/inputs_1D/example_1_in_2_out.py +0 -63
  79. bencher/example/inputs_1D/example_1_in_2_out_repeats.py +0 -61
  80. bencher/results/holoview_result.py +0 -796
  81. bencher/results/panel_result.py +0 -41
  82. holobench-1.41.0.dist-info/RECORD +0 -114
  83. {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/WHEEL +0 -0
  84. {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()