holobench 1.40.0__tar.gz → 1.41.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 (116) hide show
  1. holobench-1.41.0/CHANGELOG.md +10 -0
  2. {holobench-1.40.0 → holobench-1.41.0}/PKG-INFO +9 -13
  3. {holobench-1.40.0 → holobench-1.41.0}/bencher/bench_cfg.py +26 -13
  4. {holobench-1.40.0 → holobench-1.41.0}/bencher/caching.py +1 -4
  5. holobench-1.41.0/bencher/example/example_composable_container_image.py +60 -0
  6. holobench-1.41.0/bencher/example/example_composable_container_video.py +49 -0
  7. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_image.py +17 -21
  8. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_image1.py +16 -20
  9. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_video.py +33 -17
  10. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_hvplot_explorer.py +2 -3
  11. holobench-1.41.0/bencher/example/inputs_1D/example_1_float_2_cat_repeats.py +12 -0
  12. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/meta/generate_examples.py +5 -3
  13. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/meta/generate_meta.py +27 -3
  14. {holobench-1.40.0 → holobench-1.41.0}/bencher/job.py +1 -3
  15. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/bench_result.py +2 -1
  16. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/bench_result_base.py +2 -2
  17. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/composable_container/composable_container_video.py +39 -12
  18. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/holoview_result.py +21 -12
  19. holobench-1.41.0/bencher/results/laxtex_result.py +67 -0
  20. {holobench-1.40.0 → holobench-1.41.0}/bencher/utils.py +1 -4
  21. {holobench-1.40.0 → holobench-1.41.0}/bencher/video_writer.py +37 -2
  22. {holobench-1.40.0 → holobench-1.41.0}/bencher/worker_job.py +3 -4
  23. {holobench-1.40.0 → holobench-1.41.0}/pyproject.toml +20 -39
  24. holobench-1.40.0/bencher/example/example_composable_container.py +0 -106
  25. {holobench-1.40.0 → holobench-1.41.0}/.gitignore +0 -0
  26. {holobench-1.40.0 → holobench-1.41.0}/LICENSE +0 -0
  27. {holobench-1.40.0 → holobench-1.41.0}/README.md +0 -0
  28. {holobench-1.40.0 → holobench-1.41.0}/bencher/__init__.py +0 -0
  29. {holobench-1.40.0 → holobench-1.41.0}/bencher/bench_plot_server.py +0 -0
  30. {holobench-1.40.0 → holobench-1.41.0}/bencher/bench_report.py +0 -0
  31. {holobench-1.40.0 → holobench-1.41.0}/bencher/bench_runner.py +0 -0
  32. {holobench-1.40.0 → holobench-1.41.0}/bencher/bencher.py +0 -0
  33. {holobench-1.40.0 → holobench-1.41.0}/bencher/class_enum.py +0 -0
  34. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/__init__.py +0 -0
  35. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/benchmark_data.py +0 -0
  36. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_all.py +0 -0
  37. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_categorical.py +0 -0
  38. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_composable_container2.py +0 -0
  39. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_consts.py +0 -0
  40. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_custom_sweep.py +0 -0
  41. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_custom_sweep2.py +0 -0
  42. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_dataframe.py +0 -0
  43. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_docs.py +0 -0
  44. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_filepath.py +0 -0
  45. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_float3D.py +0 -0
  46. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_float_cat.py +0 -0
  47. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_floats.py +0 -0
  48. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_floats2D.py +0 -0
  49. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_holosweep.py +0 -0
  50. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_holosweep_objects.py +0 -0
  51. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_holosweep_tap.py +0 -0
  52. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_levels.py +0 -0
  53. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_levels2.py +0 -0
  54. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_pareto.py +0 -0
  55. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_publish.py +0 -0
  56. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_rerun.py +0 -0
  57. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_rerun2.py +0 -0
  58. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_sample_cache.py +0 -0
  59. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_sample_cache_context.py +0 -0
  60. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_simple.py +0 -0
  61. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_simple_bool.py +0 -0
  62. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_simple_cat.py +0 -0
  63. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_simple_float.py +0 -0
  64. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_simple_float2d.py +0 -0
  65. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_strings.py +0 -0
  66. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_time_event.py +0 -0
  67. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/example_workflow.py +0 -0
  68. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_bokeh_plotly.py +0 -0
  69. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_hover_ex.py +0 -0
  70. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_interactive.py +0 -0
  71. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_streamnd.py +0 -0
  72. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_streams.py +0 -0
  73. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_template.py +0 -0
  74. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_updates.py +0 -0
  75. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/experimental/example_vector.py +0 -0
  76. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/inputs_0D/example_0_in_1_out.py +0 -0
  77. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/inputs_0D/example_0_in_2_out.py +0 -0
  78. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/inputs_1D/example1d_common.py +0 -0
  79. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/inputs_1D/example_1_in_1_out.py +0 -0
  80. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/inputs_1D/example_1_in_2_out.py +0 -0
  81. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/inputs_1D/example_1_in_2_out_repeats.py +0 -0
  82. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/meta/__init__.py +0 -0
  83. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/meta/example_meta.py +0 -0
  84. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/meta/example_meta_cat.py +0 -0
  85. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/meta/example_meta_float.py +0 -0
  86. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/meta/example_meta_levels.py +0 -0
  87. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/optuna/example_optuna.py +0 -0
  88. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/shelved/example_float2D_scatter.py +0 -0
  89. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/shelved/example_float3D_cone.py +0 -0
  90. {holobench-1.40.0 → holobench-1.41.0}/bencher/example/shelved/example_kwargs.py +0 -0
  91. {holobench-1.40.0 → holobench-1.41.0}/bencher/flask_server.py +0 -0
  92. {holobench-1.40.0 → holobench-1.41.0}/bencher/optuna_conversions.py +0 -0
  93. {holobench-1.40.0 → holobench-1.41.0}/bencher/plotting/__init__.py +0 -0
  94. {holobench-1.40.0 → holobench-1.41.0}/bencher/plotting/plot_filter.py +0 -0
  95. {holobench-1.40.0 → holobench-1.41.0}/bencher/plotting/plt_cnt_cfg.py +0 -0
  96. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/__init__.py +0 -0
  97. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/composable_container/__init__.py +0 -0
  98. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/composable_container/composable_container_base.py +0 -0
  99. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/composable_container/composable_container_dataframe.py +0 -0
  100. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/composable_container/composable_container_panel.py +0 -0
  101. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/dataset_result.py +0 -0
  102. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/float_formatter.py +0 -0
  103. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/hvplot_result.py +0 -0
  104. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/optuna_result.py +0 -0
  105. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/panel_result.py +0 -0
  106. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/plotly_result.py +0 -0
  107. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/video_result.py +0 -0
  108. {holobench-1.40.0 → holobench-1.41.0}/bencher/results/video_summary.py +0 -0
  109. {holobench-1.40.0 → holobench-1.41.0}/bencher/utils_rerun.py +0 -0
  110. {holobench-1.40.0 → holobench-1.41.0}/bencher/variables/__init__.py +0 -0
  111. {holobench-1.40.0 → holobench-1.41.0}/bencher/variables/inputs.py +0 -0
  112. {holobench-1.40.0 → holobench-1.41.0}/bencher/variables/parametrised_sweep.py +0 -0
  113. {holobench-1.40.0 → holobench-1.41.0}/bencher/variables/results.py +0 -0
  114. {holobench-1.40.0 → holobench-1.41.0}/bencher/variables/sweep_base.py +0 -0
  115. {holobench-1.40.0 → holobench-1.41.0}/bencher/variables/time.py +0 -0
  116. {holobench-1.40.0 → holobench-1.41.0}/resource/bencher +0 -0
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.3.10]
9
+
10
+ Before changelogs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: holobench
3
- Version: 1.40.0
3
+ Version: 1.41.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
@@ -12,28 +12,24 @@ Requires-Python: <3.13,>=3.10
12
12
  Requires-Dist: diskcache<=5.6.3,>=5.6
13
13
  Requires-Dist: holoviews<=1.20.0,>=1.15
14
14
  Requires-Dist: hvplot<=0.10.0,>=0.8
15
- Requires-Dist: matplotlib<=3.10.0,>=3.6.3
16
- Requires-Dist: moviepy-fix-codec
17
- Requires-Dist: numpy<=2.2.2,>=1.0
18
- Requires-Dist: optuna<=4.2.0,>=3.2
15
+ Requires-Dist: moviepy<=2.1.2,>=2.1.2
16
+ Requires-Dist: numpy<=2.2.3,>=1.0
17
+ Requires-Dist: optuna<=4.2.1,>=3.2
19
18
  Requires-Dist: pandas<=2.2.3,>=2.0
20
- Requires-Dist: panel<=1.6.0,>=1.3.6
19
+ Requires-Dist: panel<=1.6.1,>=1.3.6
21
20
  Requires-Dist: param<=2.2.0,>=1.13.0
22
21
  Requires-Dist: plotly<=6.0.0,>=5.15
23
22
  Requires-Dist: scikit-learn<=1.6.1,>=1.2
24
- Requires-Dist: scoop<=0.7.2.0,>=0.7.0
25
- Requires-Dist: sortedcontainers<=2.4,>=2.4
26
- Requires-Dist: str2bool<=1.1,>=1.1
27
23
  Requires-Dist: strenum<=0.4.15,>=0.4.0
28
24
  Requires-Dist: xarray<=2025.1.2,>=2023.7
29
25
  Provides-Extra: rerun
30
26
  Requires-Dist: flask; extra == 'rerun'
31
27
  Requires-Dist: flask-cors; extra == 'rerun'
32
28
  Requires-Dist: rerun-notebook; extra == 'rerun'
33
- Requires-Dist: rerun-sdk==0.21.0; extra == 'rerun'
29
+ Requires-Dist: rerun-sdk==0.22.0; extra == 'rerun'
34
30
  Provides-Extra: test
35
- Requires-Dist: coverage<=7.6.10,>=7.5.4; extra == 'test'
36
- Requires-Dist: hypothesis<=6.124.9,>=6.104.2; extra == 'test'
31
+ Requires-Dist: coverage<=7.6.12,>=7.5.4; extra == 'test'
32
+ Requires-Dist: hypothesis<=6.125.3,>=6.104.2; extra == 'test'
37
33
  Requires-Dist: ipykernel; extra == 'test'
38
34
  Requires-Dist: jupyter-bokeh; extra == 'test'
39
35
  Requires-Dist: nbformat; extra == 'test'
@@ -42,7 +38,7 @@ Requires-Dist: pre-commit<=4.1.0; extra == 'test'
42
38
  Requires-Dist: pylint<=3.3.4,>=3.2.5; extra == 'test'
43
39
  Requires-Dist: pytest-cov<=6.0.0,>=4.1; extra == 'test'
44
40
  Requires-Dist: pytest<=8.3.4,>=7.4; extra == 'test'
45
- Requires-Dist: ruff<=0.9.4,>=0.5.0; extra == 'test'
41
+ Requires-Dist: ruff<=0.9.6,>=0.5.0; extra == 'test'
46
42
  Description-Content-Type: text/markdown
47
43
 
48
44
  # Bencher
@@ -6,17 +6,14 @@ import logging
6
6
  from typing import List
7
7
 
8
8
  import param
9
- from str2bool import str2bool
10
9
  import panel as pn
11
-
10
+ from datetime import datetime
12
11
 
13
12
  from bencher.variables.sweep_base import hash_sha1, describe_variable
14
13
  from bencher.variables.time import TimeSnapshot, TimeEvent
15
14
  from bencher.variables.results import OptDir
16
15
  from bencher.job import Executors
17
- from datetime import datetime
18
-
19
- # from bencher.results.bench_result import BenchResult
16
+ from bencher.results.laxtex_result import to_latex
20
17
 
21
18
 
22
19
  class BenchPlotSrvCfg(param.Parameterized):
@@ -199,11 +196,8 @@ class BenchRunCfg(BenchPlotSrvCfg):
199
196
 
200
197
  parser.add_argument(
201
198
  "--nightly",
202
- type=lambda b: bool(str2bool(b)),
203
- nargs="?",
204
- const=False,
205
- default=False,
206
- help="turn on nightly benchmarking",
199
+ action="store_true",
200
+ help="Turn on nightly benchmarking",
207
201
  )
208
202
 
209
203
  parser.add_argument(
@@ -344,13 +338,32 @@ class BenchCfg(BenchRunCfg):
344
338
  def inputs_as_str(self) -> List[str]:
345
339
  return [i.name for i in self.input_vars]
346
340
 
347
- def describe_sweep(self, width: int = 800, accordion=True) -> pn.pane.Markdown:
341
+ def to_latex(self):
342
+ return to_latex(self)
343
+
344
+ def describe_sweep(self, width: int = 800, accordion=True) -> pn.pane.Markdown | pn.Column:
348
345
  """Produce a markdown summary of the sweep settings"""
349
346
 
347
+ latex = self.to_latex()
350
348
  desc = pn.pane.Markdown(self.describe_benchmark(), width=width)
351
349
  if accordion:
352
- return pn.Accordion(("Data Collection Parameters", desc))
353
- return desc
350
+ desc = pn.Accordion(("Expand Full Data Collection Parameters", desc))
351
+
352
+ sentence = self.sweep_sentence()
353
+ if latex is not None:
354
+ return pn.Column(sentence, latex, desc)
355
+ return pn.Column(sentence, latex, desc)
356
+
357
+ def sweep_sentence(self):
358
+ inputs = " by ".join([iv.name for iv in self.all_vars])
359
+
360
+ all_vars_lens = [len(iv.values()) for iv in reversed(self.all_vars)]
361
+ if len(all_vars_lens) == 1:
362
+ all_vars_lens.append(1)
363
+ result_sizes = "x".join([str(iv) for iv in all_vars_lens])
364
+ results = ", ".join([rv.name for rv in self.result_vars])
365
+
366
+ return f"Sweeping {inputs} to generate a {result_sizes} result dataframe containing {results}. "
354
367
 
355
368
  def describe_benchmark(self) -> str:
356
369
  """Generate a string summary of the inputs and results from a BenchCfg
@@ -3,9 +3,6 @@ from diskcache import Cache
3
3
  from bencher.variables.parametrised_sweep import ParametrizedSweep
4
4
  from bencher.utils import hash_sha1
5
5
  import logging
6
- from sortedcontainers import SortedDict
7
-
8
- # from job import job,JobCache,JobFunctionCache
9
6
 
10
7
 
11
8
  class CachedParams(ParametrizedSweep):
@@ -20,7 +17,7 @@ class CachedParams(ParametrizedSweep):
20
17
  self.cache.clear()
21
18
 
22
19
  def kwargs_to_hash_key(self, **kwargs):
23
- return tuple(SortedDict(kwargs).items())
20
+ return tuple(sorted(kwargs.items(), key=lambda item: str(item[0])))
24
21
 
25
22
  def in_cache(self, **kwargs):
26
23
  self.update_params_from_kwargs(**kwargs)
@@ -0,0 +1,60 @@
1
+ import bencher as bch
2
+
3
+ from bencher.example.example_image import BenchPolygons
4
+
5
+
6
+ class BenchComposableContainerImage(BenchPolygons):
7
+ compose_method = bch.EnumSweep(bch.ComposeType)
8
+ labels = bch.BoolSweep()
9
+ num_frames = bch.IntSweep(default=5, bounds=[1, 100])
10
+
11
+ polygon_vid = bch.ResultVideo()
12
+
13
+ def __call__(self, **kwargs):
14
+ self.update_params_from_kwargs(**kwargs)
15
+ var_name = None
16
+ var_value = None
17
+
18
+ if self.labels:
19
+ var_name = "sides"
20
+ var_value = self.sides
21
+ vr = bch.ComposableContainerVideo()
22
+ for i in range(self.num_frames):
23
+ res = super().__call__(start_angle=i)
24
+ print(res)
25
+ vr.append(res["polygon"])
26
+ self.polygon_vid = vr.to_video(
27
+ bch.RenderCfg(
28
+ compose_method=self.compose_method,
29
+ var_name=var_name,
30
+ var_value=var_value,
31
+ max_frame_duration=1.0 / 20.0,
32
+ )
33
+ )
34
+ return self.get_results_values_as_dict()
35
+
36
+
37
+ def example_composable_container_image(
38
+ run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport = None
39
+ ) -> bch.Bench:
40
+ bench = BenchComposableContainerImage().to_bench(run_cfg, report)
41
+ # bench.add_plot_callback(bch.BenchResult.to_panes)
42
+ # bench.add_plot_callback(bch.BenchResult.to_video_grid, result_types=(bch.ResultVideo))
43
+ # bench.add_plot_callback(bch.BenchResult.to_video_summary, result_types=(bch.ResultVideo))
44
+ # bench.plot_sweep(input_vars=["compose_method", "labels"])
45
+
46
+ bench.plot_sweep(input_vars=["compose_method"])
47
+
48
+ # bench.compose_
49
+ # bench.plot_sweep(
50
+ # input_vars=[bch.p("num_frames", [2, 8, 20])],
51
+ # const_vars=dict(compose_method=bch.ComposeType.sequence),
52
+ # )
53
+
54
+ return bench
55
+
56
+
57
+ if __name__ == "__main__":
58
+ ex_run_cfg = bch.BenchRunCfg()
59
+ ex_composable_image = example_composable_container_image(ex_run_cfg)
60
+ ex_composable_image.report.show()
@@ -0,0 +1,49 @@
1
+ import bencher as bch
2
+ from bencher.example.example_composable_container_image import BenchComposableContainerImage
3
+
4
+
5
+ class BenchComposableContainerVideo(bch.ParametrizedSweep):
6
+ unequal_length = bch.BoolSweep()
7
+ compose_method = bch.EnumSweep(bch.ComposeType)
8
+ labels = bch.BoolSweep()
9
+ polygon_vid = bch.ResultVideo()
10
+
11
+ def __call__(self, **kwargs):
12
+ self.update_params_from_kwargs(**kwargs)
13
+ vr = bch.ComposableContainerVideo()
14
+ for i in range(3, 5):
15
+ num_frames = i * 10 if self.unequal_length else 5
16
+ res = BenchComposableContainerImage().__call__(
17
+ compose_method=bch.ComposeType.sequence, sides=i, num_frames=num_frames
18
+ )
19
+ vr.append(res["polygon_vid"])
20
+
21
+ self.polygon_vid = vr.to_video(bch.RenderCfg(compose_method=kwargs.get("compose_method")))
22
+ return self.get_results_values_as_dict()
23
+
24
+
25
+ def example_composable_container_video(
26
+ run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport = None
27
+ ) -> bch.Bench:
28
+ bench = BenchComposableContainerVideo().to_bench(run_cfg, report)
29
+
30
+ bench.result_vars = ["polygon_vid"]
31
+ bench.add_plot_callback(bch.BenchResult.to_panes)
32
+ bench.add_plot_callback(bch.BenchResult.to_video_grid, result_types=(bch.ResultVideo))
33
+ bench.add_plot_callback(bch.BenchResult.to_video_summary, result_types=(bch.ResultVideo))
34
+ bench.plot_sweep(input_vars=["compose_method", "labels"], const_vars=dict(unequal_length=True))
35
+
36
+ res = bench.plot_sweep(
37
+ input_vars=[],
38
+ const_vars=dict(unequal_length=False, compose_method=bch.ComposeType.sequence),
39
+ plot_callbacks=False,
40
+ )
41
+
42
+ bench.report.append(res.to_video_grid())
43
+
44
+ return bench
45
+
46
+
47
+ if __name__ == "__main__":
48
+ ex_run_cfg = bch.BenchRunCfg()
49
+ example_composable_container_video(ex_run_cfg).report.show()
@@ -1,7 +1,7 @@
1
1
  import bencher as bch
2
2
  import numpy as np
3
3
  import math
4
- import matplotlib.pyplot as plt
4
+ from PIL import Image, ImageDraw
5
5
 
6
6
 
7
7
  def polygon_points(radius: float, sides: int, start_angle: float):
@@ -16,7 +16,6 @@ class BenchPolygons(bch.ParametrizedSweep):
16
16
  sides = bch.IntSweep(default=3, bounds=(3, 7))
17
17
  radius = bch.FloatSweep(default=1, bounds=(0.2, 1))
18
18
  linewidth = bch.FloatSweep(default=1, bounds=(1, 10))
19
- linestyle = bch.StringSweep(["solid", "dashed", "dotted"])
20
19
  color = bch.StringSweep(["red", "green", "blue"])
21
20
  start_angle = bch.FloatSweep(default=0, bounds=[0, 360])
22
21
  polygon = bch.ResultImage()
@@ -26,33 +25,30 @@ class BenchPolygons(bch.ParametrizedSweep):
26
25
  def __call__(self, **kwargs):
27
26
  self.update_params_from_kwargs(**kwargs)
28
27
  points = polygon_points(self.radius, self.sides, self.start_angle)
29
- # self.hmap = hv.Curve(points)
30
- self.polygon = self.points_to_polygon_png(points, bch.gen_image_path("polygon"))
28
+ filepath = bch.gen_image_path("polygon")
29
+ self.polygon = self.points_to_polygon_png(points, filepath)
30
+ # Verify filepath is being returned
31
+ assert isinstance(self.polygon, str), f"Expected string filepath, got {type(self.polygon)}"
31
32
 
32
33
  self.side_length = 2 * self.radius * math.sin(math.pi / self.sides)
33
34
  self.area = (self.sides * self.side_length**2) / (4 * math.tan(math.pi / self.sides))
34
35
  return super().__call__()
35
36
 
36
37
  def points_to_polygon_png(self, points: list[float], filename: str):
37
- """Draw a closed polygon and save to png"""
38
- fig = plt.figure(frameon=False)
39
- ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0], frameon=False)
40
- ax.set_axis_off()
41
- ax.plot(
42
- [p[0] for p in points],
43
- [p[1] for p in points],
44
- linewidth=self.linewidth,
45
- linestyle=self.linestyle,
46
- color=self.color,
47
- )
48
- ax.set_xlim(-1, 1)
49
- ax.set_ylim(-1, 1)
38
+ """Draw a closed polygon and save to png using PIL"""
39
+ size = 300
40
+ img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
41
+ draw = ImageDraw.Draw(img)
42
+
43
+ # Scale points to image size (from [-1,1] to [0,size])
44
+ scaled_points = [(((p[0] + 1) * size / 2), ((1 - p[1]) * size / 2)) for p in points]
50
45
 
51
- ax.set_aspect("equal")
52
- fig.add_axes(ax)
53
- fig.savefig(filename, dpi=30)
46
+ # Draw polygon outline
47
+ draw.line(scaled_points, fill=self.color, width=int(self.linewidth))
54
48
 
55
- return filename
49
+ img.save(filename, "PNG")
50
+ # Explicitly return the filename string
51
+ return str(filename)
56
52
 
57
53
 
58
54
  def example_image(run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport = None) -> bch.Bench:
@@ -1,7 +1,7 @@
1
1
  import bencher as bch
2
2
  import numpy as np
3
3
  import math
4
- import matplotlib.pyplot as plt
4
+ from PIL import Image, ImageDraw
5
5
 
6
6
 
7
7
  def polygon_points(radius: float, sides: int, start_angle: float):
@@ -28,36 +28,32 @@ class BenchPolygons(bch.ParametrizedSweep):
28
28
  def __call__(self, **kwargs):
29
29
  self.update_params_from_kwargs(**kwargs)
30
30
  points = polygon_points(self.radius, self.sides, self.start_angle)
31
- # self.hmap = hv.Curve(points)
32
- self.polygon = self.points_to_polygon_png(points, bch.gen_image_path("polygon"), dpi=30)
31
+ filepath = bch.gen_image_path("polygon")
32
+ self.polygon = self.points_to_polygon_png(points, filepath, dpi=30)
33
33
  self.polygon_small = self.points_to_polygon_png(
34
34
  points, bch.gen_image_path("polygon"), dpi=10
35
35
  )
36
+ # Verify filepaths are being returned
37
+ assert isinstance(self.polygon, str), f"Expected string filepath, got {type(self.polygon)}"
38
+ assert isinstance(self.polygon_small, str), (
39
+ f"Expected string filepath, got {type(self.polygon_small)}"
40
+ )
36
41
 
37
42
  self.side_length = 2 * self.radius * math.sin(math.pi / self.sides)
38
43
  self.area = (self.sides * self.side_length**2) / (4 * math.tan(math.pi / self.sides))
39
44
  return super().__call__()
40
45
 
41
46
  def points_to_polygon_png(self, points: list[float], filename: str, dpi):
42
- """Draw a closed polygon and save to png"""
43
- fig = plt.figure(frameon=False)
44
- ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0], frameon=False)
45
- ax.set_axis_off()
46
- ax.plot(
47
- [p[0] for p in points],
48
- [p[1] for p in points],
49
- linewidth=self.linewidth,
50
- linestyle=self.linestyle,
51
- color=self.color,
52
- )
53
- ax.set_xlim(-1, 1)
54
- ax.set_ylim(-1, 1)
47
+ """Draw a closed polygon and save to png using PIL"""
48
+ size = int(100 * (dpi / 30))
49
+ img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
50
+ draw = ImageDraw.Draw(img)
55
51
 
56
- ax.set_aspect("equal")
57
- fig.add_axes(ax)
58
- fig.savefig(filename, dpi=dpi)
52
+ scaled_points = [(((p[0] + 1) * size / 2), ((1 - p[1]) * size / 2)) for p in points]
53
+ draw.line(scaled_points, fill=self.color, width=int(self.linewidth))
59
54
 
60
- return filename
55
+ img.save(filename, "PNG")
56
+ return str(filename)
61
57
 
62
58
 
63
59
  def example_image_vid_sequential1(
@@ -1,9 +1,24 @@
1
1
  import bencher as bch
2
2
  import numpy as np
3
- import matplotlib.pyplot as plt
3
+ from PIL import Image
4
+ import colorcet as cc
5
+ import numpy.typing as npt
6
+
7
+
8
+ def apply_colormap(data: npt.NDArray) -> npt.NDArray:
9
+ """Apply a perceptually uniform colormap to the data"""
10
+ # Normalize data to [0, 1]
11
+ normalized = (data - data.min()) / (data.max() - data.min())
12
+ # Convert hex colors to RGB values using numpy's frombuffer
13
+ colors = np.array(
14
+ [np.frombuffer(bytes.fromhex(c.lstrip("#")), dtype=np.uint8) for c in cc.rainbow]
15
+ )
16
+ # Map normalized values to colormap indices
17
+ indices = (normalized * (len(colors) - 1)).astype(int)
18
+ # Create RGB array from the colormap
19
+ return colors[indices]
4
20
 
5
21
 
6
- # code from https://ipython-books.github.io/124-simulating-a-partial-differential-equation-reaction-diffusion-systems-and-turing-patterns/
7
22
  class TuringPattern(bch.ParametrizedSweep):
8
23
  alpha = bch.FloatSweep(default=2.8e-4, bounds=(2e-4, 5e-3))
9
24
  beta = bch.FloatSweep(default=5e-3, bounds=(1e-3, 9e-3))
@@ -17,6 +32,7 @@ class TuringPattern(bch.ParametrizedSweep):
17
32
  video = bch.ResultVideo()
18
33
  score = bch.ResultVar()
19
34
  img = bch.ResultImage()
35
+ img_extracted = bch.ResultImage()
20
36
 
21
37
  def laplacian(self, Z, dx):
22
38
  Ztop = Z[0:-2, 1:-1]
@@ -49,28 +65,28 @@ class TuringPattern(bch.ParametrizedSweep):
49
65
  def __call__(self, **kwargs):
50
66
  self.update_params_from_kwargs(**kwargs)
51
67
 
52
- n = int(self.time / self.dt) # number of iterations
53
- dx = 2.0 / self.size # space step
68
+ n = int(self.time / self.dt)
69
+ dx = 2.0 / self.size
54
70
 
55
71
  U = np.random.rand(self.size, self.size)
56
72
  V = np.random.rand(self.size, self.size)
57
73
 
58
- fig, ax = plt.subplots(frameon=False, figsize=(2, 2))
59
- fig.set_tight_layout(True)
60
- ax.set_axis_off()
61
74
  vid_writer = bch.VideoWriter()
62
75
  for i in range(n):
63
76
  self.update(U, V, dx)
64
77
  if i % 500 == 0:
65
- ax.imshow(U)
66
- fig.canvas.draw()
67
- rgb = np.array(fig.canvas.renderer.buffer_rgba())
68
- vid_writer.append(rgb)
69
-
70
- self.img = bch.add_image(rgb)
71
-
78
+ # Apply colormap to create RGB image
79
+ rgb = apply_colormap(U)
80
+ # Create PIL image with alpha channel
81
+ img = Image.fromarray(rgb, "RGB").convert("RGBA")
82
+ img = img.resize((200, 200), Image.Resampling.LANCZOS)
83
+ rgb_alpha = np.array(img)
84
+ vid_writer.append(rgb_alpha)
85
+
86
+ self.img = bch.add_image(rgb_alpha)
72
87
  self.video = vid_writer.write()
73
-
88
+ self.img_extracted = bch.video_writer.VideoWriter.extract_frame(self.video)
89
+ print("img path", self.img_extracted)
74
90
  self.score = self.alpha + self.beta
75
91
  return super().__call__()
76
92
 
@@ -109,8 +125,8 @@ def example_video_tap(
109
125
  if __name__ == "__main__":
110
126
  run_cfg_ex = bch.BenchRunCfg()
111
127
  run_cfg_ex.level = 2
112
- run_cfg_ex.cache_samples = True
113
- run_cfg_ex.only_hash_tag = True
128
+ # run_cfg_ex.cache_samples = True
129
+ # run_cfg_ex.only_hash_tag = True
114
130
 
115
131
  # example_video(run_cfg_ex).report.show()
116
132
  example_video_tap(run_cfg_ex).report.show()
@@ -1,6 +1,5 @@
1
1
  # THIS IS NOT A WORKING EXAMPLE YET
2
2
  # pylint: disable=duplicate-code
3
- import hvplot
4
3
  import bencher as bch
5
4
  from bencher import ExampleBenchCfgIn, ExampleBenchCfgOut, bench_function
6
5
 
@@ -35,5 +34,5 @@ if __name__ == "__main__":
35
34
  ),
36
35
  )
37
36
 
38
- hvexplorer = hvplot.explorer(bench_out.get_dataframe())
39
- hvexplorer.show()
37
+ bench.report.append(bench_out.to_explorer())
38
+ bench.report.show()
@@ -0,0 +1,12 @@
1
+ import bencher as bch
2
+ from bencher.example.meta.example_meta import BenchableObject
3
+
4
+ run_cfg = bch.BenchRunCfg()
5
+ run_cfg.repeats = 20
6
+ run_cfg.level = 4
7
+ bench = BenchableObject().to_bench(run_cfg)
8
+ res = bench.plot_sweep(
9
+ input_vars=["float1", "noisy", "noise_distribution"], result_vars=["distance", "sample_noise"]
10
+ )
11
+
12
+ bench.report.show()
@@ -49,6 +49,8 @@ if __name__ == "__main__":
49
49
  "/workspaces/bencher/bencher/example/inputs_1D/example_1_in_2_out_repeats.py", "1D"
50
50
  )
51
51
 
52
- convert_example_to_jupyter_notebook(
53
- "/workspaces/bencher/bencher/example/example_simple_float.py", "1D"
54
- )
52
+ # todo, enable
53
+ # convert_example_to_jupyter_notebook(
54
+ # "/workspaces/bencher/bencher/example/example_composable_container_video.py",
55
+ # "Media",
56
+ # )
@@ -39,7 +39,7 @@ class BenchMetaGen(bch.ParametrizedSweep):
39
39
  inputs_vars_float = [
40
40
  "float1",
41
41
  "float2",
42
- "float3",
42
+ bch.p("float3", max_level=3),
43
43
  "sigma",
44
44
  ]
45
45
 
@@ -107,10 +107,9 @@ def example_meta(run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport = None
107
107
  description="""## All Combinations of Variable Sweeps and Resulting Plots
108
108
  This uses bencher to display all the combinations of plots bencher is able to produce""",
109
109
  input_vars=[
110
- bch.p("float_vars", [0, 1, 2, 3]),
110
+ bch.p("float_vars", [0, 1]),
111
111
  "categorical_vars",
112
112
  bch.p("sample_with_repeats", [1, 20]),
113
- # "sample_over_time",
114
113
  ],
115
114
  const_vars=[
116
115
  # BenchMeta.param.float_vars.with_const(1),
@@ -119,6 +118,31 @@ This uses bencher to display all the combinations of plots bencher is able to pr
119
118
  # BenchMeta.param.sample_over_time.with_const(True),
120
119
  ],
121
120
  )
121
+ bench.plot_sweep(
122
+ title="Meta Bench",
123
+ description="""## All Combinations of Variable Sweeps and Resulting Plots
124
+ This uses bencher to display all the combinations of plots bencher is able to produce""",
125
+ input_vars=[
126
+ bch.p("float_vars", [2, 3]),
127
+ "categorical_vars",
128
+ ],
129
+ )
130
+
131
+ # bench.plot_sweep(
132
+ # title="Meta Bench",
133
+ # description="""## All Combinations of Variable Sweeps and Resulting Plots
134
+ # This uses bencher to display all the combinations of plots bencher is able to produce""",
135
+ # input_vars=[
136
+ # bch.p("float_vars", [2, 3]),
137
+ # "categorical_vars",
138
+ # ],
139
+ # const_vars=[
140
+ # dict(level=3)
141
+ # # BenchMeta.param.sample_with_repeats.with_const(2),
142
+ # # BenchMeta.param.categorical_vars.with_const(2),
143
+ # # BenchMeta.param.sample_over_time.with_const(True),
144
+ # ],
145
+ # )
122
146
 
123
147
  return bench
124
148
 
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
  from typing import Callable
3
- from sortedcontainers import SortedDict
4
3
  import logging
5
4
  from diskcache import Cache
6
5
  from concurrent.futures import Future, ProcessPoolExecutor
@@ -11,7 +10,6 @@ from enum import auto
11
10
  try:
12
11
  from scoop import futures as scoop_future_executor
13
12
  except ImportError as e:
14
- logging.warning(e.msg)
15
13
  scoop_future_executor = None
16
14
 
17
15
 
@@ -23,7 +21,7 @@ class Job:
23
21
  self.function = function
24
22
  self.job_args = job_args
25
23
  if job_key is None:
26
- self.job_key = hash_sha1(tuple(SortedDict(self.job_args).items()))
24
+ self.job_key = hash_sha1(tuple(sorted(self.job_args.items())))
27
25
  else:
28
26
  self.job_key = job_key
29
27
  self.tag = tag
@@ -53,6 +53,7 @@ class BenchResult(PlotlyResult, HoloviewResult, HvplotResult, VideoSummaryResult
53
53
  self,
54
54
  plot_list: List[callable] = None,
55
55
  remove_plots: List[callable] = None,
56
+ default_container=pn.Column,
56
57
  **kwargs,
57
58
  ) -> List[pn.panel]:
58
59
  self.plt_cnt_cfg.print_debug = False
@@ -67,7 +68,7 @@ class BenchResult(PlotlyResult, HoloviewResult, HvplotResult, VideoSummaryResult
67
68
 
68
69
  kwargs = self.set_plot_size(**kwargs)
69
70
 
70
- row = EmptyContainer(pn.Row())
71
+ row = EmptyContainer(default_container())
71
72
  for plot_callback in plot_list:
72
73
  if self.plt_cnt_cfg.print_debug:
73
74
  print(f"checking: {plot_callback.__name__}")
@@ -321,7 +321,7 @@ class BenchResultBase(OptunaResult):
321
321
  **kwargs,
322
322
  ) -> Optional[pn.Row]:
323
323
  if hv_dataset is None:
324
- hv_dataset = self.to_hv_dataset()
324
+ hv_dataset = self.to_hv_dataset(reduce=reduce)
325
325
 
326
326
  if pane_collection is None:
327
327
  pane_collection = pn.Row()
@@ -333,7 +333,7 @@ class BenchResultBase(OptunaResult):
333
333
  if result_types is None or isinstance(rv, result_types):
334
334
  row.append(
335
335
  self.to_panes_multi_panel(
336
- self.to_hv_dataset(reduce=reduce, result_var=rv),
336
+ hv_dataset,
337
337
  rv,
338
338
  plot_callback=partial(plot_callback, **kwargs),
339
339
  target_dimension=target_dimension,