holobench 1.33.2__tar.gz → 1.35.0__tar.gz

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 (104) hide show
  1. {holobench-1.33.2 → holobench-1.35.0}/PKG-INFO +2 -2
  2. {holobench-1.33.2 → holobench-1.35.0}/bencher/__init__.py +7 -3
  3. {holobench-1.33.2 → holobench-1.35.0}/bencher/bencher.py +4 -1
  4. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_simple_float.py +1 -0
  5. holobench-1.35.0/bencher/example/inputs_0D/example_0D.py +34 -0
  6. holobench-1.35.0/bencher/example/inputs_1D/example_1D.py +53 -0
  7. {holobench-1.33.2 → holobench-1.35.0}/bencher/plotting/plot_filter.py +16 -5
  8. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/bench_result.py +3 -1
  9. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/bench_result_base.py +18 -5
  10. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/holoview_result.py +34 -8
  11. holobench-1.35.0/bencher/results/hvplot_result.py +54 -0
  12. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/optuna_result.py +7 -2
  13. {holobench-1.33.2 → holobench-1.35.0}/bencher/variables/parametrised_sweep.py +6 -1
  14. {holobench-1.33.2 → holobench-1.35.0}/pyproject.toml +11 -11
  15. {holobench-1.33.2 → holobench-1.35.0}/.gitignore +0 -0
  16. {holobench-1.33.2 → holobench-1.35.0}/LICENSE +0 -0
  17. {holobench-1.33.2 → holobench-1.35.0}/README.md +0 -0
  18. {holobench-1.33.2 → holobench-1.35.0}/bencher/bench_cfg.py +0 -0
  19. {holobench-1.33.2 → holobench-1.35.0}/bencher/bench_plot_server.py +0 -0
  20. {holobench-1.33.2 → holobench-1.35.0}/bencher/bench_report.py +0 -0
  21. {holobench-1.33.2 → holobench-1.35.0}/bencher/bench_runner.py +0 -0
  22. {holobench-1.33.2 → holobench-1.35.0}/bencher/caching.py +0 -0
  23. {holobench-1.33.2 → holobench-1.35.0}/bencher/class_enum.py +0 -0
  24. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/__init__.py +0 -0
  25. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/benchmark_data.py +0 -0
  26. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_all.py +0 -0
  27. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_categorical.py +0 -0
  28. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_composable_container.py +0 -0
  29. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_composable_container2.py +0 -0
  30. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_consts.py +0 -0
  31. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_custom_sweep.py +0 -0
  32. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_custom_sweep2.py +0 -0
  33. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_dataframe.py +0 -0
  34. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_docs.py +0 -0
  35. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_filepath.py +0 -0
  36. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_float3D.py +0 -0
  37. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_float_cat.py +0 -0
  38. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_floats.py +0 -0
  39. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_floats2D.py +0 -0
  40. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_holosweep.py +0 -0
  41. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_holosweep_objects.py +0 -0
  42. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_holosweep_tap.py +0 -0
  43. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_image.py +0 -0
  44. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_image1.py +0 -0
  45. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_levels.py +0 -0
  46. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_levels2.py +0 -0
  47. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_pareto.py +0 -0
  48. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_publish.py +0 -0
  49. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_rerun.py +0 -0
  50. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_rerun2.py +0 -0
  51. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_sample_cache.py +0 -0
  52. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_sample_cache_context.py +0 -0
  53. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_simple.py +0 -0
  54. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_simple_bool.py +0 -0
  55. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_simple_cat.py +0 -0
  56. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_simple_float2d.py +0 -0
  57. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_strings.py +0 -0
  58. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_time_event.py +0 -0
  59. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_video.py +0 -0
  60. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/example_workflow.py +0 -0
  61. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_bokeh_plotly.py +0 -0
  62. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_hover_ex.py +0 -0
  63. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_hvplot_explorer.py +0 -0
  64. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_interactive.py +0 -0
  65. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_streamnd.py +0 -0
  66. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_streams.py +0 -0
  67. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_template.py +0 -0
  68. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_updates.py +0 -0
  69. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/experimental/example_vector.py +0 -0
  70. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/meta/example_meta.py +0 -0
  71. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/meta/example_meta_cat.py +0 -0
  72. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/meta/example_meta_float.py +0 -0
  73. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/meta/example_meta_levels.py +0 -0
  74. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/optuna/example_optuna.py +0 -0
  75. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/shelved/example_float2D_scatter.py +0 -0
  76. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/shelved/example_float3D_cone.py +0 -0
  77. {holobench-1.33.2 → holobench-1.35.0}/bencher/example/shelved/example_kwargs.py +0 -0
  78. {holobench-1.33.2 → holobench-1.35.0}/bencher/flask_server.py +0 -0
  79. {holobench-1.33.2 → holobench-1.35.0}/bencher/job.py +0 -0
  80. {holobench-1.33.2 → holobench-1.35.0}/bencher/optuna_conversions.py +0 -0
  81. {holobench-1.33.2 → holobench-1.35.0}/bencher/plotting/__init__.py +0 -0
  82. {holobench-1.33.2 → holobench-1.35.0}/bencher/plotting/plt_cnt_cfg.py +0 -0
  83. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/__init__.py +0 -0
  84. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/composable_container/__init__.py +0 -0
  85. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/composable_container/composable_container_base.py +0 -0
  86. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/composable_container/composable_container_dataframe.py +0 -0
  87. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/composable_container/composable_container_panel.py +0 -0
  88. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/composable_container/composable_container_video.py +0 -0
  89. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/dataset_result.py +0 -0
  90. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/float_formatter.py +0 -0
  91. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/panel_result.py +0 -0
  92. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/plotly_result.py +0 -0
  93. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/video_result.py +0 -0
  94. {holobench-1.33.2 → holobench-1.35.0}/bencher/results/video_summary.py +0 -0
  95. {holobench-1.33.2 → holobench-1.35.0}/bencher/utils.py +0 -0
  96. {holobench-1.33.2 → holobench-1.35.0}/bencher/utils_rerun.py +0 -0
  97. {holobench-1.33.2 → holobench-1.35.0}/bencher/variables/__init__.py +0 -0
  98. {holobench-1.33.2 → holobench-1.35.0}/bencher/variables/inputs.py +0 -0
  99. {holobench-1.33.2 → holobench-1.35.0}/bencher/variables/results.py +0 -0
  100. {holobench-1.33.2 → holobench-1.35.0}/bencher/variables/sweep_base.py +0 -0
  101. {holobench-1.33.2 → holobench-1.35.0}/bencher/variables/time.py +0 -0
  102. {holobench-1.33.2 → holobench-1.35.0}/bencher/video_writer.py +0 -0
  103. {holobench-1.33.2 → holobench-1.35.0}/bencher/worker_job.py +0 -0
  104. {holobench-1.33.2 → holobench-1.35.0}/resource/bencher +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: holobench
3
- Version: 1.33.2
3
+ Version: 1.35.0
4
4
  Summary: A package for benchmarking the performance of arbitrary functions
5
5
  Project-URL: Repository, https://github.com/dyson-ai/bencher
6
6
  Project-URL: Home, https://github.com/dyson-ai/bencher
@@ -38,7 +38,7 @@ Requires-Dist: pre-commit<=4.0.1; extra == 'test'
38
38
  Requires-Dist: pylint<=3.3.3,>=3.2.5; extra == 'test'
39
39
  Requires-Dist: pytest-cov<=6.0.0,>=4.1; extra == 'test'
40
40
  Requires-Dist: pytest<=8.3.4,>=7.4; extra == 'test'
41
- Requires-Dist: ruff<=0.8.4,>=0.5.0; extra == 'test'
41
+ Requires-Dist: ruff<=0.8.5,>=0.5.0; extra == 'test'
42
42
  Description-Content-Type: text/markdown
43
43
 
44
44
  # Bencher
@@ -56,7 +56,13 @@ from .utils import (
56
56
  publish_file,
57
57
  github_content,
58
58
  )
59
- from .utils_rerun import publish_and_view_rrd, rrd_to_pane, capture_rerun_window
59
+
60
+ try:
61
+ from .utils_rerun import publish_and_view_rrd, rrd_to_pane, capture_rerun_window
62
+ from .flask_server import run_flask_in_thread
63
+ except ModuleNotFoundError as e:
64
+ pass
65
+
60
66
 
61
67
  from .plotting.plot_filter import VarRange, PlotFilter
62
68
  from .variables.parametrised_sweep import ParametrizedSweep
@@ -68,5 +74,3 @@ from .bench_report import BenchReport, GithubPagesCfg
68
74
  from .job import Executors
69
75
  from .video_writer import VideoWriter, add_image
70
76
  from .class_enum import ClassEnum, ExampleEnum
71
-
72
- from .flask_server import run_flask_in_thread
@@ -371,7 +371,7 @@ class Bench(BenchPlotServer):
371
371
  title += "s"
372
372
  title += ": " + ", ".join([f"{c[0].name}={c[1]}" for c in const_vars_in])
373
373
  else:
374
- raise RuntimeError("you must pass a title, or define inputs or consts")
374
+ title = " ".join([i.name for i in result_vars_in])
375
375
 
376
376
  if run_cfg.level > 0:
377
377
  inputs = []
@@ -871,6 +871,9 @@ class Bench(BenchPlotServer):
871
871
  def get_result(self, index: int = -1) -> BenchResult:
872
872
  return self.results[index]
873
873
 
874
+ def get_ds(self, index: int = -1) -> xr.Dataset:
875
+ return self.get_result(index).to_xarray()
876
+
874
877
  def publish(self, remote_callback: Callable) -> str:
875
878
  branch_name = f"{self.bench_name}_{self.run_cfg.run_tag}"
876
879
  return self.report.publish(remote_callback, branch_name=branch_name)
@@ -21,6 +21,7 @@ def example_1D_float(run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport =
21
21
 
22
22
  bench = SimpleFloat().to_bench(run_cfg, report)
23
23
  bench.plot_sweep()
24
+ bench.report.append(bench.get_result().to_explorer())
24
25
  return bench
25
26
 
26
27
 
@@ -0,0 +1,34 @@
1
+ """This file has some examples for how to perform basic benchmarking parameter sweeps"""
2
+
3
+ import bencher as bch
4
+ import random
5
+
6
+
7
+ class SimpleFloat0D(bch.ParametrizedSweep):
8
+ """This class has 0 input dimensions and 1 output dimensions. It samples from a gaussian distribution"""
9
+
10
+ # This defines a variable that we want to plot
11
+ output = bch.ResultVar(units="ul", doc="a sample from a gaussian distribution")
12
+
13
+ def __call__(self, **kwargs) -> dict:
14
+ """Generate a sample from a uniform distribution
15
+
16
+ Returns:
17
+ dict: a dictionary with all the result variables in the ParametrisedSweep class as named key value pairs.
18
+ """
19
+
20
+ self.output = random.gauss(mu=0.0, sigma=1.0)
21
+ return super().__call__(**kwargs)
22
+
23
+
24
+ def example_0D(run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport = None) -> bch.Bench:
25
+ """This example shows how to sample a 1 dimensional float variable and plot the result of passing that parameter sweep to the benchmarking function"""
26
+
27
+ bench = SimpleFloat0D().to_bench(run_cfg, report)
28
+ bench.plot_sweep()
29
+ return bench
30
+
31
+
32
+ if __name__ == "__main__":
33
+ run_config = bch.BenchRunCfg(repeats=100)
34
+ example_0D(run_config).report.show()
@@ -0,0 +1,53 @@
1
+ """This file has some examples for how to perform basic benchmarking parameter sweeps"""
2
+
3
+ import bencher as bch
4
+
5
+
6
+ class DataSource:
7
+ def __init__(self):
8
+ self.data = [
9
+ [0, 0, 0, 0],
10
+ [1, 1, 1, 1],
11
+ [1, 1, 1, 1],
12
+ [2, 1, 1, 0],
13
+ [2, 2, 0, 0],
14
+ [2, 2, 1, 1],
15
+ ]
16
+
17
+ def call(self, index, repeat):
18
+ return self.data[index][repeat - 1]
19
+
20
+
21
+ class Example1D(bch.ParametrizedSweep):
22
+ index = bch.IntSweep(default=0, bounds=[0, 5], doc="Input angle", units="rad", samples=30)
23
+ output = bch.ResultVar(units="v", doc="sin of theta")
24
+
25
+ def __call__(self, **kwargs):
26
+ self.update_params_from_kwargs(**kwargs)
27
+ self.output = DataSource().call(self.index, kwargs["repeat"])
28
+ return super().__call__(**kwargs)
29
+
30
+
31
+ def example_1D_float_repeats(
32
+ run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport = None
33
+ ) -> bch.Bench:
34
+ """This example shows how to sample a 1 dimensional float variable and plot the result of passing that parameter sweep to the benchmarking function"""
35
+
36
+ bench = Example1D().to_bench(run_cfg, report)
37
+ # bench.plot_sweep(pass_repeat=True,plot_callbacks=False)
38
+
39
+ # res = bench.get_result()
40
+ bench.run_cfg = bch.BenchRunCfg(repeats=4)
41
+ bench.plot_sweep(pass_repeat=True)
42
+
43
+ res = bench.get_result()
44
+ bench.report.append(res.to_auto())
45
+ bench.report.append(res.to_scatter())
46
+ bench.report.append(res.to_scatter_jitter(override=True))
47
+
48
+ # bench.report.append()
49
+ return bench
50
+
51
+
52
+ if __name__ == "__main__":
53
+ example_1D_float_repeats().report.show()
@@ -64,16 +64,24 @@ class PlotFilter:
64
64
  repeats_range: VarRange = VarRange(1, None)
65
65
  input_range: VarRange = VarRange(1, None)
66
66
 
67
- def matches_result(self, plt_cnt_cfg: PltCntCfg, plot_name: str) -> PlotMatchesResult:
67
+ def matches_result(
68
+ self, plt_cnt_cfg: PltCntCfg, plot_name: str, override: bool = False
69
+ ) -> PlotMatchesResult:
68
70
  """Checks if the result data signature matches the type of data the plot is able to display."""
69
- return PlotMatchesResult(self, plt_cnt_cfg, plot_name)
71
+ return PlotMatchesResult(self, plt_cnt_cfg, plot_name, override)
70
72
 
71
73
 
72
74
  # @dataclass
73
75
  class PlotMatchesResult:
74
76
  """Stores information about which properties match the requirements of a particular plotter"""
75
77
 
76
- def __init__(self, plot_filter: PlotFilter, plt_cnt_cfg: PltCntCfg, plot_name: str):
78
+ def __init__(
79
+ self,
80
+ plot_filter: PlotFilter,
81
+ plt_cnt_cfg: PltCntCfg,
82
+ plot_name: str,
83
+ override: bool = False,
84
+ ):
77
85
  match_info = []
78
86
  matches = []
79
87
 
@@ -92,8 +100,11 @@ class PlotMatchesResult:
92
100
  matches.append(match)
93
101
  if not match:
94
102
  match_info.append(info)
95
-
96
- self.overall = all(matches)
103
+ if override:
104
+ match_info.append(f"override: {override}")
105
+ self.overall = True
106
+ else:
107
+ self.overall = all(matches)
97
108
 
98
109
  match_info.insert(0, f"plot {plot_name} matches: {self.overall}")
99
110
  self.matches_info = "\n".join(match_info).strip()
@@ -7,11 +7,12 @@ from bencher.results.video_summary import VideoSummaryResult
7
7
  from bencher.results.panel_result import PanelResult
8
8
  from bencher.results.plotly_result import PlotlyResult
9
9
  from bencher.results.holoview_result import HoloviewResult
10
+ from bencher.results.hvplot_result import HvplotResult
10
11
  from bencher.results.dataset_result import DataSetResult
11
12
  from bencher.utils import listify
12
13
 
13
14
 
14
- class BenchResult(PlotlyResult, HoloviewResult, VideoSummaryResult, DataSetResult):
15
+ class BenchResult(PlotlyResult, HoloviewResult, HvplotResult, VideoSummaryResult, DataSetResult): # noqa pylint: disable=too-many-ancestors
15
16
  """Contains the results of the benchmark and has methods to cast the results to various datatypes and graphical representations"""
16
17
 
17
18
  def __init__(self, bench_cfg) -> None:
@@ -28,6 +29,7 @@ class BenchResult(PlotlyResult, HoloviewResult, VideoSummaryResult, DataSetResul
28
29
  HoloviewResult.to_curve,
29
30
  HoloviewResult.to_line,
30
31
  HoloviewResult.to_heatmap,
32
+ HvplotResult.to_histogram,
31
33
  PlotlyResult.to_volume,
32
34
  # PanelResult.to_video,
33
35
  PanelResult.to_panes,
@@ -21,7 +21,9 @@ from bencher.utils import listify
21
21
 
22
22
  from bencher.variables.results import ResultReference, ResultDataSet
23
23
 
24
- from bencher.results.composable_container.composable_container_panel import ComposableContainerPanel
24
+ from bencher.results.composable_container.composable_container_panel import (
25
+ ComposableContainerPanel,
26
+ )
25
27
 
26
28
  # todo add plugins
27
29
  # https://gist.github.com/dorneanu/cce1cd6711969d581873a88e0257e312
@@ -55,7 +57,10 @@ class BenchResultBase(OptunaResult):
55
57
  return self.ds.count()
56
58
 
57
59
  def to_hv_dataset(
58
- self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None, level: int = None
60
+ self,
61
+ reduce: ReduceType = ReduceType.AUTO,
62
+ result_var: ResultVar = None,
63
+ level: int = None,
59
64
  ) -> hv.Dataset:
60
65
  """Generate a holoviews dataset from the xarray dataset.
61
66
 
@@ -72,7 +77,10 @@ class BenchResultBase(OptunaResult):
72
77
  return hv.Dataset(self.to_dataset(reduce, result_var, level))
73
78
 
74
79
  def to_dataset(
75
- self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None, level: int = None
80
+ self,
81
+ reduce: ReduceType = ReduceType.AUTO,
82
+ result_var: ResultVar = None,
83
+ level: int = None,
76
84
  ) -> xr.Dataset:
77
85
  """Generate a summarised xarray dataset.
78
86
 
@@ -331,6 +339,7 @@ class BenchResultBase(OptunaResult):
331
339
  result_var: ResultVar = None,
332
340
  result_types=None,
333
341
  pane_collection: pn.pane = None,
342
+ override=False,
334
343
  **kwargs,
335
344
  ):
336
345
  plot_filter = PlotFilter(
@@ -342,7 +351,9 @@ class BenchResultBase(OptunaResult):
342
351
  repeats_range=repeats_range,
343
352
  input_range=input_range,
344
353
  )
345
- matches_res = plot_filter.matches_result(self.plt_cnt_cfg, callable_name(plot_callback))
354
+ matches_res = plot_filter.matches_result(
355
+ self.plt_cnt_cfg, callable_name(plot_callback), override
356
+ )
346
357
  if matches_res.overall:
347
358
  return self.map_plot_panes(
348
359
  plot_callback=plot_callback,
@@ -400,7 +411,9 @@ class BenchResultBase(OptunaResult):
400
411
  dim_color = color_tuple_to_css(int_to_col(num_dims - 2, 0.05, 1.0))
401
412
 
402
413
  outer_container = ComposableContainerPanel(
403
- name=" vs ".join(dims), background_col=dim_color, horizontal=not horizontal
414
+ name=" vs ".join(dims),
415
+ background_col=dim_color,
416
+ horizontal=not horizontal,
404
417
  )
405
418
  max_len = 0
406
419
  for i in range(dataset.sizes[selected_dim]):
@@ -6,9 +6,15 @@ import holoviews as hv
6
6
  from param import Parameter
7
7
  from functools import partial
8
8
  import hvplot.xarray # noqa pylint: disable=duplicate-code,unused-import
9
+ import hvplot.pandas # noqa pylint: disable=duplicate-code,unused-import
9
10
  import xarray as xr
10
11
 
11
- from bencher.utils import hmap_canonical_input, get_nearest_coords, get_nearest_coords1D, listify
12
+ from bencher.utils import (
13
+ hmap_canonical_input,
14
+ get_nearest_coords,
15
+ get_nearest_coords1D,
16
+ listify,
17
+ )
12
18
  from bencher.results.panel_result import PanelResult
13
19
  from bencher.results.bench_result_base import ReduceType
14
20
 
@@ -81,7 +87,9 @@ class HoloviewResult(PanelResult):
81
87
 
82
88
  # return time_widget_args
83
89
 
84
- def to_bar(self, result_var: Parameter = None, **kwargs) -> Optional[pn.panel]:
90
+ def to_bar(
91
+ self, result_var: Parameter = None, override: bool = False, **kwargs
92
+ ) -> Optional[pn.panel]:
85
93
  return self.filter(
86
94
  self.to_bar_ds,
87
95
  float_range=VarRange(0, 0),
@@ -92,6 +100,7 @@ class HoloviewResult(PanelResult):
92
100
  target_dimension=2,
93
101
  result_var=result_var,
94
102
  result_types=(ResultVar),
103
+ override=override,
95
104
  **kwargs,
96
105
  )
97
106
 
@@ -105,7 +114,11 @@ class HoloviewResult(PanelResult):
105
114
  return da_plot.hvplot.bar(by=by, **time_widget_args, **kwargs)
106
115
 
107
116
  def hv_container_ds(
108
- self, dataset: xr.Dataset, result_var: Parameter, container: hv.Chart = None, **kwargs
117
+ self,
118
+ dataset: xr.Dataset,
119
+ result_var: Parameter,
120
+ container: hv.Chart = None,
121
+ **kwargs,
109
122
  ):
110
123
  return hv.Dataset(dataset[result_var.name]).to(container).opts(**kwargs)
111
124
 
@@ -428,7 +441,9 @@ class HoloviewResult(PanelResult):
428
441
 
429
442
  def to_scatter(self, **kwargs) -> Optional[pn.panel]:
430
443
  match_res = PlotFilter(
431
- float_range=VarRange(0, 0), cat_range=VarRange(0, None), repeats_range=VarRange(1, 1)
444
+ float_range=VarRange(0, 0),
445
+ cat_range=VarRange(0, None),
446
+ repeats_range=VarRange(1, 1),
432
447
  ).matches_result(self.plt_cnt_cfg, "to_hvplot_scatter")
433
448
  if match_res.overall:
434
449
  hv_ds = self.to_hv_dataset(ReduceType.SQUEEZE)
@@ -530,17 +545,22 @@ class HoloviewResult(PanelResult):
530
545
  def to_scatter_jitter(
531
546
  self,
532
547
  result_var: Parameter = None,
548
+ override: bool = False,
533
549
  **kwargs, # pylint: disable=unused-argument
534
550
  ) -> List[hv.Scatter]:
535
- return self.overlay_plots(partial(self.to_scatter_jitter_single, **kwargs))
551
+ return self.overlay_plots(
552
+ partial(self.to_scatter_jitter_single, override=override, **kwargs)
553
+ )
536
554
 
537
- def to_scatter_jitter_single(self, result_var: Parameter, **kwargs) -> Optional[hv.Scatter]:
555
+ def to_scatter_jitter_single(
556
+ self, result_var: Parameter, override: bool = True, **kwargs
557
+ ) -> Optional[hv.Scatter]:
538
558
  matches = PlotFilter(
539
559
  float_range=VarRange(0, 0),
540
560
  cat_range=VarRange(0, None),
541
561
  repeats_range=VarRange(2, None),
542
562
  input_range=VarRange(1, None),
543
- ).matches_result(self.plt_cnt_cfg, "to_scatter_jitter")
563
+ ).matches_result(self.plt_cnt_cfg, "to_scatter_jitter", override)
544
564
  if matches.overall:
545
565
  ds = self.to_hv_dataset(ReduceType.NONE)
546
566
  pt = (
@@ -639,7 +659,13 @@ class HoloviewResult(PanelResult):
639
659
  def to_table(self):
640
660
  return self.to(hv.Table, ReduceType.SQUEEZE)
641
661
 
642
- def to_surface(self, result_var: Parameter = None, **kwargs) -> Optional[pn.panel]:
662
+ def to_tabulator(self, **kwargs):
663
+ """Passes the data to the panel Tabulator type to display an interactive table
664
+ see https://panel.holoviz.org/reference/widgets/Tabulator.html for extra options
665
+ """
666
+ return pn.widgets.Tabulator(self.to_pandas(), **kwargs)
667
+
668
+ def to_surface(self, result_var: Parameter = None, **kwargs) -> Optional[pn.pane.Pane]:
643
669
  return self.filter(
644
670
  self.to_surface_ds,
645
671
  float_range=VarRange(2, None),
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+ from typing import Optional
3
+ import panel as pn
4
+ from param import Parameter
5
+ import hvplot.xarray # noqa pylint: disable=duplicate-code,unused-import
6
+ import hvplot.pandas # noqa pylint: disable=duplicate-code,unused-import
7
+ import xarray as xr
8
+
9
+ from bencher.results.panel_result import PanelResult
10
+ from bencher.results.bench_result_base import ReduceType
11
+
12
+ from bencher.plotting.plot_filter import VarRange
13
+ from bencher.variables.results import ResultVar
14
+
15
+
16
+ class HvplotResult(PanelResult):
17
+ def to_explorer(self) -> pn.pane.Pane:
18
+ """Produces a hvplot explorer instance to explore the generated dataset
19
+ see: https://hvplot.holoviz.org/getting_started/explorer.html
20
+
21
+ Returns:
22
+ pn.pane.Pane: A dynamic pane for exploring a dataset
23
+ """
24
+
25
+ if len(self.bench_cfg.input_vars) > 0:
26
+ return self.to_xarray().hvplot.explorer()
27
+
28
+ # For some reason hvplot doesn't like 1D datasets in xarray, so convert to pandas which it has no problem with
29
+ # TODO look into why this is, its probably due to how I am setting up the indexing in xarray.
30
+ return self.to_pandas().hvplot.explorer()
31
+
32
+ def to_histogram(self, result_var: Parameter = None, **kwargs) -> Optional[pn.pane.Pane]:
33
+ return self.filter(
34
+ self.to_histogram_ds,
35
+ float_range=VarRange(0, 0),
36
+ cat_range=VarRange(0, None),
37
+ input_range=VarRange(0, 0),
38
+ reduce=ReduceType.NONE,
39
+ target_dimension=2,
40
+ result_var=result_var,
41
+ result_types=(ResultVar),
42
+ **kwargs,
43
+ )
44
+
45
+ def to_histogram_ds(self, dataset: xr.Dataset, result_var: Parameter, **kwargs):
46
+ return dataset.hvplot(
47
+ kind="hist",
48
+ y=[result_var.name],
49
+ ylabel="count",
50
+ legend="bottom_right",
51
+ widget_location="bottom",
52
+ title=f"{result_var.name} vs Count",
53
+ **kwargs,
54
+ )
@@ -277,7 +277,9 @@ class OptunaResult:
277
277
  if len(target_names) <= 3:
278
278
  study_pane.append(
279
279
  plot_pareto_front(
280
- study, target_names=target_names, include_dominated_trials=False
280
+ study,
281
+ target_names=target_names,
282
+ include_dominated_trials=False,
281
283
  )
282
284
  )
283
285
  else:
@@ -312,7 +314,10 @@ class OptunaResult:
312
314
 
313
315
  param_str = "\n".join(param_str)
314
316
  study_pane.append(
315
- pn.Row(pn.pane.Markdown(f"## Best Parameters\n```text\n{param_str}"), **kwargs),
317
+ pn.Row(
318
+ pn.pane.Markdown(f"## Best Parameters\n```text\n{param_str}"),
319
+ **kwargs,
320
+ ),
316
321
  )
317
322
 
318
323
  study_repeats_pane.append(study_pane)
@@ -192,7 +192,12 @@ class ParametrizedSweep(Parameterized):
192
192
  )
193
193
  )
194
194
 
195
- def __call__(self, **kwargs):
195
+ def __call__(self, **kwargs) -> dict:
196
+ """This is the function that is called to record data samples in the benchmarking function. It should be overridden with your custom logic and then call the parent method "return super().__call__(**kwargs)"
197
+
198
+ Returns:
199
+ dict: a dictionary with all the result variables in the ParametrisedSweep class as named key value pairs.
200
+ """
196
201
  return self.get_results_values_as_dict()
197
202
 
198
203
  def plot_hmap(self, **kwargs):
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "holobench"
3
- version = "1.33.2"
3
+ version = "1.35.0"
4
4
 
5
5
  authors = [{ name = "Austin Gregg-Smith", email = "blooop@gmail.com" }]
6
6
  description = "A package for benchmarking the performance of arbitrary functions"
@@ -58,7 +58,7 @@ test = [
58
58
  "pytest-cov>=4.1,<=6.0.0",
59
59
  "pytest>=7.4,<=8.3.4",
60
60
  "hypothesis>=6.104.2,<=6.123.2",
61
- "ruff>=0.5.0,<=0.8.4",
61
+ "ruff>=0.5.0,<=0.8.5",
62
62
  "coverage>=7.5.4,<=7.6.10",
63
63
  "pre-commit<=4.0.1",
64
64
  ]
@@ -88,26 +88,26 @@ format = "ruff format ."
88
88
  check-clean-workspace = "git diff --exit-code"
89
89
  ruff-lint = "ruff check . --fix"
90
90
  pylint = "pylint --version && echo 'running pylint...' && pylint $(git ls-files '*.py')"
91
- lint = { depends_on = ["ruff-lint", "pylint"] }
92
- style = { depends_on = ["format", "lint"] }
91
+ lint = { depends-on = ["ruff-lint", "pylint"] }
92
+ style = { depends-on = ["format", "lint"] }
93
93
  commit-format = "git commit -a -m'autoformat code' || true"
94
94
  test = "pytest"
95
95
  coverage = "coverage run -m pytest && coverage xml -o coverage.xml"
96
96
  coverage-report = "coverage report -m"
97
97
  update-lock = "pixi update && git commit -a -m'update pixi.lock' || true"
98
98
  push = "git push"
99
- update-lock-push = { depends_on = ["update-lock", "push"] }
100
- fix = { depends_on = ["update-lock", "pre-commit", "format", "ruff-lint"] }
101
- fix-commit-push = { depends_on = ["fix", "commit-format", "update-lock-push"] }
102
- ci-no-cover = { depends_on = ["style", "test"] }
103
- ci = { depends_on = [
99
+ update-lock-push = { depends-on = ["update-lock", "push"] }
100
+ fix = { depends-on = ["update-lock", "format", "ruff-lint", "pre-commit"] }
101
+ fix-commit-push = { depends-on = ["fix", "commit-format", "update-lock-push"] }
102
+ ci-no-cover = { depends-on = ["style", "test"] }
103
+ ci = { depends-on = [
104
104
  "format",
105
105
  "ruff-lint",
106
106
  "pylint",
107
107
  "coverage",
108
108
  "coverage-report",
109
109
  ] }
110
- ci-push = { depends_on = ["format", "ruff-lint", "update-lock", "ci", "push"] }
110
+ ci-push = { depends-on = ["format", "ruff-lint", "update-lock", "ci", "push"] }
111
111
  clear-pixi = "rm -rf .pixi pixi.lock"
112
112
  setup-git-merge-driver = "git config merge.ours.driver true"
113
113
  update-from-template-repo = "./scripts/update_from_template.sh"
@@ -121,7 +121,7 @@ extension-pkg-whitelist = ["numpy", "scipy"]
121
121
  jobs = 16 #detect number of cores
122
122
 
123
123
  [tool.pylint.'MESSAGES CONTROL']
124
- disable = "C,logging-fstring-interpolation,line-too-long,fixme,missing-module-docstring,too-many-instance-attributes,too-few-public-methods,too-many-arguments,too-many-locals,too-many-branches,too-many-statements,use-dict-literal,duplicate-code,too-many-public-methods,too-many-nested-blocks,cyclic-import, too-many-positional-arguments"
124
+ disable = "C,logging-fstring-interpolation,line-too-long,fixme,missing-module-docstring,too-many-instance-attributes,too-few-public-methods,too-many-arguments,too-many-locals,too-many-branches,too-many-statements,use-dict-literal,duplicate-code,too-many-public-methods,too-many-nested-blocks,cyclic-import,too-many-positional-arguments"
125
125
  enable = "no-else-return,consider-using-in"
126
126
 
127
127
  [tool.coverage.run]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes