holobench 1.9.0__tar.gz → 1.11.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 (81) hide show
  1. {holobench-1.9.0 → holobench-1.11.0}/PKG-INFO +13 -13
  2. {holobench-1.9.0 → holobench-1.11.0}/bencher/__init__.py +1 -0
  3. {holobench-1.9.0 → holobench-1.11.0}/bencher/bench_cfg.py +5 -10
  4. {holobench-1.9.0 → holobench-1.11.0}/bencher/bencher.py +1 -2
  5. holobench-1.11.0/bencher/class_enum.py +52 -0
  6. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_holosweep.py +10 -16
  7. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_holosweep_tap.py +1 -1
  8. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_image.py +3 -3
  9. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_levels.py +1 -1
  10. {holobench-1.9.0 → holobench-1.11.0}/bencher/job.py +6 -4
  11. {holobench-1.9.0 → holobench-1.11.0}/bencher/optuna_conversions.py +1 -1
  12. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/bench_result_base.py +9 -4
  13. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/composable_container/composable_container_video.py +2 -1
  14. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/holoview_result.py +2 -2
  15. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/video_summary.py +25 -7
  16. {holobench-1.9.0 → holobench-1.11.0}/bencher/variables/inputs.py +11 -30
  17. {holobench-1.9.0 → holobench-1.11.0}/bencher/variables/parametrised_sweep.py +11 -8
  18. {holobench-1.9.0 → holobench-1.11.0}/bencher/variables/results.py +11 -3
  19. {holobench-1.9.0 → holobench-1.11.0}/bencher/variables/sweep_base.py +23 -28
  20. {holobench-1.9.0 → holobench-1.11.0}/bencher/variables/time.py +1 -5
  21. {holobench-1.9.0 → holobench-1.11.0}/bencher/video_writer.py +4 -3
  22. {holobench-1.9.0 → holobench-1.11.0}/pyproject.toml +16 -16
  23. {holobench-1.9.0 → holobench-1.11.0}/README.md +0 -0
  24. {holobench-1.9.0 → holobench-1.11.0}/bencher/bench_plot_server.py +0 -0
  25. {holobench-1.9.0 → holobench-1.11.0}/bencher/bench_report.py +0 -0
  26. {holobench-1.9.0 → holobench-1.11.0}/bencher/bench_runner.py +0 -0
  27. {holobench-1.9.0 → holobench-1.11.0}/bencher/caching.py +0 -0
  28. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/__init__.py +0 -0
  29. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/benchmark_data.py +0 -0
  30. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_all.py +0 -0
  31. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_categorical.py +0 -0
  32. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_custom_sweep.py +0 -0
  33. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_docs.py +0 -0
  34. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_float3D.py +0 -0
  35. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_float_cat.py +0 -0
  36. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_floats.py +0 -0
  37. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_floats2D.py +0 -0
  38. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_holosweep_objects.py +0 -0
  39. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_pareto.py +0 -0
  40. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_sample_cache.py +0 -0
  41. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_sample_cache_context.py +0 -0
  42. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_simple.py +0 -0
  43. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_simple_bool.py +0 -0
  44. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_simple_cat.py +0 -0
  45. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_simple_float.py +0 -0
  46. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_strings.py +0 -0
  47. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_time_event.py +0 -0
  48. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_video.py +0 -0
  49. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/example_workflow.py +0 -0
  50. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_bokeh_plotly.py +0 -0
  51. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_hover_ex.py +0 -0
  52. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_hvplot_explorer.py +0 -0
  53. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_interactive.py +0 -0
  54. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_streamnd.py +0 -0
  55. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_streams.py +0 -0
  56. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_template.py +0 -0
  57. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_updates.py +0 -0
  58. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/experimental/example_vector.py +0 -0
  59. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/meta/example_meta.py +0 -0
  60. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/meta/example_meta_cat.py +0 -0
  61. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/meta/example_meta_float.py +0 -0
  62. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/meta/example_meta_levels.py +0 -0
  63. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/optuna/example_optuna.py +0 -0
  64. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/shelved/example_float2D_scatter.py +0 -0
  65. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/shelved/example_float3D_cone.py +0 -0
  66. {holobench-1.9.0 → holobench-1.11.0}/bencher/example/shelved/example_kwargs.py +0 -0
  67. {holobench-1.9.0 → holobench-1.11.0}/bencher/plotting/__init__.py +0 -0
  68. {holobench-1.9.0 → holobench-1.11.0}/bencher/plotting/plot_filter.py +0 -0
  69. {holobench-1.9.0 → holobench-1.11.0}/bencher/plotting/plt_cnt_cfg.py +0 -0
  70. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/__init__.py +0 -0
  71. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/bench_result.py +0 -0
  72. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/composable_container/__init__.py +0 -0
  73. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/composable_container/composable_container_base.py +0 -0
  74. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/composable_container/composable_container_panel.py +0 -0
  75. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/float_formatter.py +0 -0
  76. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/optuna_result.py +0 -0
  77. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/panel_result.py +0 -0
  78. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/plotly_result.py +0 -0
  79. {holobench-1.9.0 → holobench-1.11.0}/bencher/results/video_result.py +0 -0
  80. {holobench-1.9.0 → holobench-1.11.0}/bencher/utils.py +0 -0
  81. {holobench-1.9.0 → holobench-1.11.0}/bencher/worker_job.py +0 -0
@@ -1,23 +1,23 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: holobench
3
- Version: 1.9.0
3
+ Version: 1.11.0
4
4
  Summary: A package for benchmarking the performance of arbitrary functions
5
5
  Author-email: Austin Gregg-Smith <blooop@gmail.com>
6
6
  Description-Content-Type: text/markdown
7
- Requires-Dist: holoviews>=1.15,<=1.18.1
8
- Requires-Dist: numpy>=1.0,<=1.26.3
9
- Requires-Dist: param>=1.13.0,<=2.0.2
7
+ Requires-Dist: holoviews>=1.15,<=1.18.3
8
+ Requires-Dist: numpy>=1.0,<=1.26.4
9
+ Requires-Dist: param>=1.13.0,<=2.1.0
10
10
  Requires-Dist: hvplot>=0.8,<=0.9.2
11
- Requires-Dist: matplotlib>=3.6.3,<=3.8.2
12
- Requires-Dist: panel>=1.3.6,<=1.3.8
11
+ Requires-Dist: matplotlib>=3.6.3,<=3.8.3
12
+ Requires-Dist: panel>=1.3.6,<=1.4.0
13
13
  Requires-Dist: diskcache>=5.6,<=5.6.3
14
- Requires-Dist: optuna>=3.2,<=3.5.0
15
- Requires-Dist: xarray>=2023.7,<=2024.1.1
16
- Requires-Dist: plotly>=5.15,<=5.18.0
14
+ Requires-Dist: optuna>=3.2,<=3.6.1
15
+ Requires-Dist: xarray>=2023.7,<=2024.3.0
16
+ Requires-Dist: plotly>=5.15,<=5.20.0
17
17
  Requires-Dist: sortedcontainers>=2.4,<=2.4
18
- Requires-Dist: pandas>=2.0,<=2.2.0
18
+ Requires-Dist: pandas>=2.0,<=2.2.1
19
19
  Requires-Dist: strenum>=0.4.0,<=0.4.15
20
- Requires-Dist: scikit-learn>=1.2,<=1.4.0
20
+ Requires-Dist: scikit-learn>=1.2,<=1.4.1.post1
21
21
  Requires-Dist: str2bool>=1.1,<=1.1
22
22
  Requires-Dist: scoop>=0.7.0,<=0.7.2.0
23
23
  Requires-Dist: moviepy>=1.0.3,<=1.0.3
@@ -25,8 +25,8 @@ Requires-Dist: black>=23,<=24.1.1 ; extra == "test"
25
25
  Requires-Dist: pylint>=2.16,<=3.0.3 ; extra == "test"
26
26
  Requires-Dist: pytest-cov>=4.1,<=4.1 ; extra == "test"
27
27
  Requires-Dist: pytest>=7.4,<=8.0.0 ; extra == "test"
28
- Requires-Dist: hypothesis>=6.82,<=6.97.4 ; extra == "test"
29
- Requires-Dist: ruff>=0.0.280,<=0.1.15 ; extra == "test"
28
+ Requires-Dist: hypothesis>=6.82,<=6.97.1 ; extra == "test"
29
+ Requires-Dist: ruff>=0.0.280,<=0.1.14 ; extra == "test"
30
30
  Requires-Dist: coverage>=7.2.7,<=7.4.1 ; extra == "test"
31
31
  Project-URL: Documentation, https://bencher.readthedocs.io/en/latest/
32
32
  Project-URL: Home, https://github.com/dyson-ai/bencher
@@ -39,3 +39,4 @@ from .results.holoview_result import ReduceType, HoloviewResult
39
39
  from .bench_report import BenchReport
40
40
  from .job import Executors
41
41
  from .video_writer import VideoWriter, add_image
42
+ from .class_enum import ClassEnum, ExampleEnum
@@ -38,10 +38,6 @@ class BenchRunCfg(BenchPlotSrvCfg):
38
38
  doc="If true each time the function is called it will plot a timeseries of historical and the latest result.",
39
39
  )
40
40
 
41
- debug: bool = param.Boolean(
42
- False, doc="Debug the sampling faster by reducing the dimension sampling resolution"
43
- )
44
-
45
41
  use_optuna: bool = param.Boolean(False, doc="show optuna plots")
46
42
 
47
43
  summarise_constant_inputs = param.Boolean(
@@ -333,7 +329,6 @@ class BenchCfg(BenchRunCfg):
333
329
  hash_sha1(str(self.title)),
334
330
  hash_sha1(self.over_time),
335
331
  repeats_hash,
336
- hash_sha1(self.debug),
337
332
  hash_sha1(self.tag),
338
333
  )
339
334
  )
@@ -364,16 +359,16 @@ class BenchCfg(BenchRunCfg):
364
359
 
365
360
  benchmark_sampling_str.append("Input Variables:")
366
361
  for iv in self.input_vars:
367
- benchmark_sampling_str.extend(describe_variable(iv, self.debug, True))
362
+ benchmark_sampling_str.extend(describe_variable(iv, True))
368
363
 
369
364
  if self.const_vars and (self.summarise_constant_inputs):
370
365
  benchmark_sampling_str.append("\nConstants:")
371
366
  for cv in self.const_vars:
372
- benchmark_sampling_str.extend(describe_variable(cv[0], False, False, cv[1]))
367
+ benchmark_sampling_str.extend(describe_variable(cv[0], False, cv[1]))
373
368
 
374
369
  benchmark_sampling_str.append("\nResult Variables:")
375
370
  for rv in self.result_vars:
376
- benchmark_sampling_str.extend(describe_variable(rv, self.debug, False))
371
+ benchmark_sampling_str.extend(describe_variable(rv, False))
377
372
 
378
373
  print_meta = True
379
374
  # if len(self.meta_vars) == 1:
@@ -394,7 +389,7 @@ class BenchCfg(BenchRunCfg):
394
389
  benchmark_sampling_str.append(f" parallel: {self.executor}")
395
390
 
396
391
  for mv in self.meta_vars:
397
- benchmark_sampling_str.extend(describe_variable(mv, self.debug, True))
392
+ benchmark_sampling_str.extend(describe_variable(mv, True))
398
393
 
399
394
  benchmark_sampling_str.append("```")
400
395
 
@@ -455,7 +450,7 @@ class DimsCfg:
455
450
  self.dims_name = [i.name for i in bench_cfg.all_vars]
456
451
 
457
452
  self.dim_ranges = []
458
- self.dim_ranges = [i.values(bench_cfg.debug) for i in bench_cfg.all_vars]
453
+ self.dim_ranges = [i.values() for i in bench_cfg.all_vars]
459
454
  self.dims_size = [len(p) for p in self.dim_ranges]
460
455
  self.dim_ranges_index = [list(range(i)) for i in self.dims_size]
461
456
  self.dim_ranges_str = [f"{s}\n" for s in self.dim_ranges]
@@ -573,7 +573,7 @@ class Bench(BenchPlotServer):
573
573
  # bench_cfg.all_vars = [ bench_cfg.iv_repeat] +bench_cfg.input_vars + bench_cfg.iv_time
574
574
 
575
575
  for i in bench_cfg.all_vars:
576
- logging.info(i.sampling_str(bench_cfg.debug))
576
+ logging.info(i.sampling_str())
577
577
 
578
578
  dims_cfg = DimsCfg(bench_cfg)
579
579
  function_inputs = list(
@@ -631,7 +631,6 @@ class Bench(BenchPlotServer):
631
631
  default=repeats,
632
632
  bounds=[1, repeats],
633
633
  samples=repeats,
634
- samples_debug=2 if repeats > 2 else 1,
635
634
  units="repeats",
636
635
  doc="The number of times a sample was measured",
637
636
  )
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+ from strenum import StrEnum
3
+ from typing import Any
4
+ import importlib
5
+ from abc import abstractmethod
6
+ from dataclasses import dataclass
7
+ from enum import auto
8
+
9
+
10
+ class ClassEnum(StrEnum):
11
+ """A ClassEnum is a pattern to make it easier to create factory a factory method that converts from an enum to a corresponding class. Subclasses should implement to_class(enum_instance:EnumType) which takes an enum returns the corresponding instance of that class."""
12
+
13
+ @classmethod
14
+ def to_class_generic(cls, module_import: str, class_name: str) -> Any:
15
+ """Create an instance of the class referred to by this enum
16
+
17
+ Returns:
18
+ Any: instance of the class
19
+ """
20
+
21
+ class_def = getattr(importlib.import_module(module_import), class_name)
22
+ return class_def()
23
+
24
+ @classmethod
25
+ @abstractmethod
26
+ def to_class(cls, enum_val: ClassEnum) -> Any:
27
+ """Subclasses should overrides this method to take an enum returns the corresponding instance of that class."""
28
+ raise NotImplementedError()
29
+
30
+
31
+ @dataclass
32
+ class BaseClass:
33
+ baseclassname: str = "class0"
34
+
35
+
36
+ @dataclass
37
+ class Class1(BaseClass):
38
+ classname: str = "class1"
39
+
40
+
41
+ @dataclass
42
+ class Class2(BaseClass):
43
+ classname: str = "class2"
44
+
45
+
46
+ class ExampleEnum(ClassEnum):
47
+ Class1 = auto()
48
+ Class2 = auto()
49
+
50
+ @classmethod
51
+ def to_class(cls, enum_val: ExampleEnum) -> BaseClass:
52
+ return cls.to_class_generic("bencher.class_enum", enum_val)
@@ -41,12 +41,11 @@ class PlotFunctions(bch.ParametrizedSweep):
41
41
 
42
42
  compute_fn = bch.EnumSweep(Function)
43
43
 
44
+ # RESULT VARS
44
45
  fn_output = bch.ResultVar(units="v", doc="sin of theta with some noise")
45
-
46
46
  out_sum = bch.ResultVar(units="v", doc="The sum")
47
-
48
- hmap = bch.ResultReference()
49
- hmap1 = bch.ResultHmap()
47
+ ref = bch.ResultReference()
48
+ holomap = bch.ResultHmap()
50
49
 
51
50
  def __call__(self, plot=True, **kwargs) -> dict:
52
51
  self.update_params_from_kwargs(**kwargs)
@@ -56,8 +55,8 @@ class PlotFunctions(bch.ParametrizedSweep):
56
55
  0, noise
57
56
  )
58
57
 
59
- self.hmap1 = self.plot_holo(plot)
60
- self.hmap = bch.ResultReference(self.hmap1)
58
+ self.holomap = self.plot_holo(plot)
59
+ self.ref = bch.ResultReference(self.ref)
61
60
 
62
61
  return self.get_results_values_as_dict()
63
62
 
@@ -73,17 +72,11 @@ class PlotFunctions(bch.ParametrizedSweep):
73
72
  def example_holosweep(
74
73
  run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
75
74
  ) -> bch.Bench:
76
- wv = PlotFunctions()
77
-
78
- # run_cfg.use_optuna = True
79
-
80
- bench = bch.Bench("waves", wv, run_cfg=run_cfg, report=report)
75
+ bench = PlotFunctions().to_bench(run_cfg, report)
81
76
 
82
77
  bench.plot_sweep(
83
- "phase",
84
- input_vars=[PlotFunctions.param.theta, PlotFunctions.param.freq],
85
- result_vars=[PlotFunctions.param.fn_output, PlotFunctions.param.hmap],
86
- # result_vars=[PlotFunctions.param.hmap],
78
+ input_vars=["theta", "freq"],
79
+ result_vars=["fn_output", "holomap"],
87
80
  )
88
81
 
89
82
  # print("best", res.get_best_trial_params(True))
@@ -99,6 +92,7 @@ def example_holosweep(
99
92
 
100
93
 
101
94
  if __name__ == "__main__":
95
+ PlotFunctions().to_gui()
102
96
  bench_run = bch.BenchRunner("bench_runner_test")
103
97
  bench_run.add_run(example_holosweep)
104
- bench_run.run(level=3, show=True, use_cache=False)
98
+ bench_run.run(level=6, show=True, use_cache=False)
@@ -120,7 +120,7 @@ def example_holosweep_tap_slider(
120
120
 
121
121
  heatmap = res.to_heatmap().opts(tools=["hover", "tap"])
122
122
  posxy = hv.streams.Tap(source=heatmap, x=0, y=0)
123
- sld1 = wv.param.phase.as_slider(run_cfg.debug)
123
+ sld1 = wv.param.phase.as_slider()
124
124
 
125
125
  def tap_plot(x, y):
126
126
  print(x, y)
@@ -82,7 +82,7 @@ def example_image_vid(
82
82
  ) -> bch.Bench:
83
83
  bench = BenchPolygons().to_bench(run_cfg, report)
84
84
  bench.add_plot_callback(bch.BenchResult.to_sweep_summary)
85
- bench.add_plot_callback(bch.BenchResult.to_video_grid)
85
+ bench.add_plot_callback(bch.BenchResult.to_video_grid, target_duration=1)
86
86
  bench.plot_sweep(input_vars=["sides"])
87
87
  bench.plot_sweep(input_vars=["radius", "sides"])
88
88
  bench.plot_sweep(input_vars=["radius", "sides", "linewidth"])
@@ -108,6 +108,6 @@ if __name__ == "__main__":
108
108
  # ex_run_cfg.debug = True
109
109
  # ex_run_cfg.repeats = 2
110
110
  ex_run_cfg.level = 4
111
- # example_image_vid(ex_run_cfg).report.show()
111
+ example_image_vid(ex_run_cfg).report.show()
112
112
  # example_image_vid_sequential(ex_run_cfg).report.show()
113
- example_image(ex_run_cfg).report.show()
113
+ # example_image(ex_run_cfg).report.show()
@@ -37,7 +37,7 @@ class RunWithLevel(bch.ParametrizedSweep):
37
37
 
38
38
  self.level_samples = int(
39
39
  pow(
40
- len(bch.FloatSweep(bounds=[0, 1]).with_level(self.level).values(False)),
40
+ len(bch.FloatSweep(bounds=[0, 1]).with_level(self.level).values()),
41
41
  self.dimensions,
42
42
  )
43
43
  )
@@ -80,7 +80,8 @@ class FutureCache:
80
80
  size_limit: int = int(20e9), # 20 GB
81
81
  use_cache=True,
82
82
  ):
83
- self.executor = Executors.factory(executor)
83
+ self.executor_type = executor
84
+ self.executor = None
84
85
  if use_cache:
85
86
  self.cache = Cache(f"cachedir/{cache_name}", tag_index=tag_index, size_limit=size_limit)
86
87
  logging.info(f"cache dir: {self.cache.directory}")
@@ -110,6 +111,9 @@ class FutureCache:
110
111
 
111
112
  self.worker_fn_call_count += 1
112
113
 
114
+ if self.executor_type is not Executors.SERIAL:
115
+ if self.executor is None:
116
+ self.executor = Executors.factory(self.executor_type)
113
117
  if self.executor is not None:
114
118
  self.overwrite_msg(job, " starting parallel job...")
115
119
  return JobFuture(
@@ -148,9 +152,7 @@ class FutureCache:
148
152
  self.cache.close()
149
153
  if self.executor:
150
154
  self.executor.shutdown()
151
-
152
- # def __del__(self):
153
- # self.close()
155
+ self.executor = None
154
156
 
155
157
  def stats(self) -> str:
156
158
  logging.info(f"job calls: {self.worker_wrapper_call_count}")
@@ -30,7 +30,7 @@ def optuna_grid_search(bench_cfg: BenchCfg) -> optuna.Study:
30
30
  """
31
31
  search_space = {}
32
32
  for iv in bench_cfg.all_vars:
33
- search_space[iv.name] = iv.values(bench_cfg.debug)
33
+ search_space[iv.name] = iv.values()
34
34
  directions = []
35
35
  for rv in bench_cfg.optuna_targets(True):
36
36
  directions.append(rv.direction)
@@ -249,11 +249,16 @@ class BenchResultBase(OptunaResult):
249
249
  target_dimension: int = 2,
250
250
  result_var: ResultVar = None,
251
251
  result_types=None,
252
+ pane_collection: pn.pane = None,
252
253
  **kwargs,
253
254
  ) -> Optional[pn.Row]:
254
255
  if hv_dataset is None:
255
256
  hv_dataset = self.to_hv_dataset()
256
- row = EmptyContainer(pn.Row())
257
+
258
+ if pane_collection is None:
259
+ pane_collection = pn.Row()
260
+
261
+ row = EmptyContainer(pane_collection)
257
262
 
258
263
  # kwargs= self.set_plot_size(**kwargs)
259
264
  for rv in self.get_results_var_list(result_var):
@@ -283,6 +288,7 @@ class BenchResultBase(OptunaResult):
283
288
  target_dimension: int = 2,
284
289
  result_var: ResultVar = None,
285
290
  result_types=None,
291
+ pane_collection: pn.pane = None,
286
292
  **kwargs,
287
293
  ):
288
294
  plot_filter = PlotFilter(
@@ -302,6 +308,7 @@ class BenchResultBase(OptunaResult):
302
308
  target_dimension=target_dimension,
303
309
  result_var=result_var,
304
310
  result_types=result_types,
311
+ pane_collection=pane_collection,
305
312
  **kwargs,
306
313
  )
307
314
  return matches_res.to_panel()
@@ -372,9 +379,7 @@ class BenchResultBase(OptunaResult):
372
379
  horizontal=len(sliced.sizes) <= target_dimension + 1,
373
380
  result_var=result_var,
374
381
  )
375
-
376
- if inner_container.label_len > max_len:
377
- max_len = inner_container.label_len
382
+ max_len = max(max_len, inner_container.label_len)
378
383
  inner_container.append(panes)
379
384
  outer_container.append(inner_container.container)
380
385
  for c in outer_container.container:
@@ -19,12 +19,13 @@ class ComposableContainerVideo(ComposableContainerBase):
19
19
  var_value: str = None,
20
20
  background_col: tuple[3] = (255, 255, 255),
21
21
  horizontal: bool = True,
22
+ target_duration: float = None,
22
23
  ) -> None:
23
24
  super().__init__(horizontal)
24
25
  self.name = name
25
26
  self.container = []
26
27
  self.background_col = background_col
27
- self.target_duration = 10.0
28
+ self.target_duration = 10 if target_duration is None else target_duration
28
29
  self.var_name = var_name
29
30
 
30
31
  self.label = self.label_formatter(var_name, var_value)
@@ -465,7 +465,7 @@ class HoloviewResult(PanelResult):
465
465
 
466
466
  kdims = []
467
467
  for i in self.bench_cfg.input_vars + [self.bench_cfg.iv_repeat]:
468
- kdims.append(i.as_dim(compute_values=True, debug=self.bench_cfg.debug))
468
+ kdims.append(i.as_dim(compute_values=True))
469
469
 
470
470
  return hv.DynamicMap(cb, kdims=kdims)
471
471
 
@@ -510,7 +510,7 @@ class HoloviewResult(PanelResult):
510
510
  result_vars=VarRange(1, 1),
511
511
  ).matches_result(self.plt_cnt_cfg, "to_surface_hv")
512
512
  if matches_res.overall:
513
- # xr_cfg = plot_float_cnt_2(self.plt_cnt_cfg, result_var, self.bench_cfg.debug)
513
+ # xr_cfg = plot_float_cnt_2(self.plt_cnt_cfg, result_var)
514
514
 
515
515
  # TODO a warning suggests setting this parameter, but it does not seem to help as expected, leaving here to fix in the future
516
516
  # hv.config.image_rtol = 1.0
@@ -74,7 +74,8 @@ class VideoSummaryResult(BenchResultBase):
74
74
  label = ", ".join(f"{a[0]}={a[1]}" for a in list(zip(input_order, index)))
75
75
  if val is not None:
76
76
  vr.append_file(val, label)
77
- fn = vr.write_png()
77
+ fn = vr.write_png(**kwargs)
78
+ kwargs.pop("target_duration", None)
78
79
  if fn is not None:
79
80
  if video_controls is None:
80
81
  video_controls = VideoControls()
@@ -87,8 +88,19 @@ class VideoSummaryResult(BenchResultBase):
87
88
  self,
88
89
  result_var: Parameter = None,
89
90
  result_types=(ResultImage,),
91
+ pane_collection: pn.pane = None,
90
92
  **kwargs,
91
93
  ) -> Optional[pn.panel]:
94
+ """Returns the results compiled into a video
95
+
96
+ Args:
97
+ result_var (Parameter, optional): The result var to plot. Defaults to None.
98
+ result_types (tuple, optional): The types of result var to convert to video. Defaults to (ResultImage,).
99
+ collection (pn.pane, optional): If there are multiple results, use this collection to stack them. Defaults to pn.Row().
100
+
101
+ Returns:
102
+ Optional[pn.panel]: a panel pane with a video of all results concatenated together
103
+ """
92
104
  plot_filter = PlotFilter(
93
105
  float_range=VarRange(0, None),
94
106
  cat_range=VarRange(0, None),
@@ -98,13 +110,16 @@ class VideoSummaryResult(BenchResultBase):
98
110
  matches_res = plot_filter.matches_result(
99
111
  self.plt_cnt_cfg, callable_name(self.to_video_grid_ds)
100
112
  )
113
+
114
+ if pane_collection is None:
115
+ pane_collection = pn.Row()
116
+
101
117
  if matches_res.overall:
102
118
  ds = self.to_dataset(ReduceType.SQUEEZE)
103
- row = pn.Row()
104
119
  for rv in self.get_results_var_list(result_var):
105
120
  if isinstance(rv, result_types):
106
- row.append(self.to_video_grid_ds(ds, rv, **kwargs))
107
- return row
121
+ pane_collection.append(self.to_video_grid_ds(ds, rv, **kwargs))
122
+ return pane_collection
108
123
  return matches_res.to_panel()
109
124
 
110
125
  def to_video_grid_ds(
@@ -113,6 +128,7 @@ class VideoSummaryResult(BenchResultBase):
113
128
  result_var: Parameter,
114
129
  reverse=True,
115
130
  video_controls: VideoControls = None,
131
+ target_duration: float = None,
116
132
  **kwargs,
117
133
  ):
118
134
  vr = VideoWriter()
@@ -125,6 +141,7 @@ class VideoSummaryResult(BenchResultBase):
125
141
  result_var=result_var,
126
142
  final=True,
127
143
  reverse=reverse,
144
+ target_duration=target_duration,
128
145
  **kwargs,
129
146
  )
130
147
 
@@ -150,6 +167,7 @@ class VideoSummaryResult(BenchResultBase):
150
167
  result_var=None,
151
168
  final=False,
152
169
  reverse=False,
170
+ target_duration: float = None,
153
171
  **kwargs,
154
172
  ) -> pn.panel:
155
173
  num_dims = len(dataset.sizes)
@@ -168,6 +186,7 @@ class VideoSummaryResult(BenchResultBase):
168
186
  name=" vs ".join(dims),
169
187
  background_col=dim_color,
170
188
  horizontal=horizontal,
189
+ target_duration=target_duration,
171
190
  # var_name=selected_dim,
172
191
  # var_value=label_val,
173
192
  )
@@ -180,6 +199,7 @@ class VideoSummaryResult(BenchResultBase):
180
199
  var_name=selected_dim,
181
200
  var_value=label_val,
182
201
  horizontal=horizontal,
202
+ target_duration=target_duration,
183
203
  )
184
204
  panes = self._to_video_panes_ds(
185
205
  sliced,
@@ -190,9 +210,7 @@ class VideoSummaryResult(BenchResultBase):
190
210
  )
191
211
  inner_container.append(panes)
192
212
 
193
- if inner_container.label_len > max_len:
194
- max_len = inner_container.label_len
195
-
213
+ max_len = max(max_len, inner_container.label_len)
196
214
  rendered = inner_container.render()
197
215
  outer_container.append(rendered)
198
216
  return outer_container.render(concatenate=final)
@@ -11,7 +11,7 @@ class SweepSelector(Selector, SweepBase):
11
11
 
12
12
  __slots__ = shared_slots
13
13
 
14
- def __init__(self, units: str = "ul", samples: int = None, samples_debug: int = 2, **params):
14
+ def __init__(self, units: str = "ul", samples: int = None, **params):
15
15
  SweepBase.__init__(self)
16
16
  Selector.__init__(self, **params)
17
17
 
@@ -20,24 +20,20 @@ class SweepSelector(Selector, SweepBase):
20
20
  self.samples = len(self.objects)
21
21
  else:
22
22
  self.samples = samples
23
- self.samples_debug = min(self.samples, samples_debug)
24
23
 
25
- def values(self, debug=False) -> List[Any]:
24
+ def values(self) -> List[Any]:
26
25
  """return all the values for a parameter sweep. If debug is true return a reduced list"""
27
- return self.indices_to_samples(self.samples_debug if debug else self.samples, self.objects)
26
+ return self.indices_to_samples(self.samples, self.objects)
28
27
 
29
28
 
30
29
  class BoolSweep(SweepSelector):
31
30
  """A class to reprsent a parameter sweep of bools"""
32
31
 
33
- def __init__(
34
- self, units: str = "ul", samples: int = None, samples_debug: int = 2, default=True, **params
35
- ):
32
+ def __init__(self, units: str = "ul", samples: int = None, default=True, **params):
36
33
  SweepSelector.__init__(
37
34
  self,
38
35
  units=units,
39
36
  samples=samples,
40
- samples_debug=samples_debug,
41
37
  default=default,
42
38
  objects=[True, False] if default else [False, True],
43
39
  **params,
@@ -52,7 +48,6 @@ class StringSweep(SweepSelector):
52
48
  string_list: List[str],
53
49
  units: str = "",
54
50
  samples: int = None,
55
- samples_debug: int = 2,
56
51
  **params,
57
52
  ):
58
53
  SweepSelector.__init__(
@@ -61,7 +56,6 @@ class StringSweep(SweepSelector):
61
56
  instantiate=True,
62
57
  units=units,
63
58
  samples=samples,
64
- samples_debug=samples_debug,
65
59
  **params,
66
60
  )
67
61
 
@@ -71,9 +65,7 @@ class EnumSweep(SweepSelector):
71
65
 
72
66
  __slots__ = shared_slots
73
67
 
74
- def __init__(
75
- self, enum_type: Enum | List[Enum], units=" ", samples=None, samples_debug=2, **params
76
- ):
68
+ def __init__(self, enum_type: Enum | List[Enum], units=" ", samples=None, **params):
77
69
  # The enum can either be an Enum type or a list of enums
78
70
  list_of_enums = isinstance(enum_type, list)
79
71
  selector_list = enum_type if list_of_enums else list(enum_type)
@@ -83,7 +75,6 @@ class EnumSweep(SweepSelector):
83
75
  instantiate=True,
84
76
  units=units,
85
77
  samples=samples,
86
- samples_debug=samples_debug,
87
78
  **params,
88
79
  )
89
80
  if not list_of_enums: # Grab the docs from the enum type def
@@ -95,12 +86,11 @@ class IntSweep(Integer, SweepBase):
95
86
 
96
87
  __slots__ = shared_slots + ["sample_values"]
97
88
 
98
- def __init__(self, units="ul", samples=None, samples_debug=2, sample_values=None, **params):
89
+ def __init__(self, units="ul", samples=None, sample_values=None, **params):
99
90
  SweepBase.__init__(self)
100
91
  Integer.__init__(self, **params)
101
92
 
102
93
  self.units = units
103
- self.samples_debug = samples_debug
104
94
 
105
95
  if sample_values is None:
106
96
  if samples is None:
@@ -116,7 +106,7 @@ class IntSweep(Integer, SweepBase):
116
106
  if "default" not in params:
117
107
  self.default = sample_values[0]
118
108
 
119
- def values(self, debug=False) -> List[int]:
109
+ def values(self) -> List[int]:
120
110
  """return all the values for a parameter sweep. If debug is true return the list"""
121
111
  sample_values = (
122
112
  self.sample_values
@@ -124,7 +114,7 @@ class IntSweep(Integer, SweepBase):
124
114
  else list(range(int(self.bounds[0]), int(self.bounds[1] + 1)))
125
115
  )
126
116
 
127
- return self.indices_to_samples(self.samples_debug if debug else self.samples, sample_values)
117
+ return self.indices_to_samples(self.samples, sample_values)
128
118
 
129
119
  ###THESE ARE COPIES OF INTEGER VALIDATION BUT ALSO ALLOW NUMPY INT TYPES
130
120
  def _validate_value(self, val, allow_None):
@@ -152,14 +142,11 @@ class FloatSweep(Number, SweepBase):
152
142
 
153
143
  __slots__ = shared_slots + ["sample_values"]
154
144
 
155
- def __init__(
156
- self, units="ul", samples=10, samples_debug=2, sample_values=None, step=None, **params
157
- ):
145
+ def __init__(self, units="ul", samples=10, sample_values=None, step=None, **params):
158
146
  SweepBase.__init__(self)
159
147
  Number.__init__(self, step=step, **params)
160
148
 
161
149
  self.units = units
162
- self.samples_debug = samples_debug
163
150
 
164
151
  self.sample_values = sample_values
165
152
 
@@ -170,20 +157,14 @@ class FloatSweep(Number, SweepBase):
170
157
  if "default" not in params:
171
158
  self.default = sample_values[0]
172
159
 
173
- def values(self, debug=False) -> List[float]:
160
+ def values(self) -> List[float]:
174
161
  """return all the values for a parameter sweep. If debug is true return a reduced list"""
175
- samps = self.samples_debug if debug else self.samples
162
+ samps = self.samples
176
163
  if self.sample_values is None:
177
164
  if self.step is None:
178
165
  return np.linspace(self.bounds[0], self.bounds[1], samps)
179
166
 
180
167
  return np.arange(self.bounds[0], self.bounds[1], self.step)
181
- if debug:
182
- indices = [
183
- int(i)
184
- for i in np.linspace(0, len(self.sample_values) - 1, self.samples_debug, dtype=int)
185
- ]
186
- return [self.sample_values[i] for i in indices]
187
168
  return self.sample_values
188
169
 
189
170
 
@@ -153,7 +153,7 @@ class ParametrizedSweep(Parameterized):
153
153
 
154
154
  @classmethod
155
155
  def get_results_only(cls) -> List[Parameter]:
156
- """Return a list of input parameters
156
+ """Return a list of result parameters
157
157
 
158
158
  Returns:
159
159
  List[param.Parameter]: A list of result parameters
@@ -175,16 +175,19 @@ class ParametrizedSweep(Parameterized):
175
175
  return [iv.as_dim(compute_values) for iv in inputs]
176
176
 
177
177
  def to_dynamic_map(
178
- self,
179
- callback=None,
180
- name=None,
181
- remove_dims: str | List[str] = None,
178
+ self, callback=None, name=None, remove_dims: str | List[str] = None, result_var: str = None
182
179
  ) -> hv.DynamicMap:
183
180
  if callback is None:
184
181
  callback = self.__call__
185
182
 
183
+ if result_var is None:
184
+ result_vars = self.get_input_and_results().results
185
+ for k, rv in result_vars.items():
186
+ if isinstance(rv, ResultHmap):
187
+ result_var = k
188
+
186
189
  def callback_wrapper(**kwargs):
187
- return callback(**kwargs)["hmap"]
190
+ return callback(**kwargs)[result_var]
188
191
 
189
192
  return hv.DynamicMap(
190
193
  callback=callback_wrapper,
@@ -192,9 +195,9 @@ class ParametrizedSweep(Parameterized):
192
195
  name=name,
193
196
  ).opts(shared_axes=False, framewise=True, width=1000, height=1000)
194
197
 
195
- def to_gui(self): # pragma: no cover
198
+ def to_gui(self, result_var: str = None, **kwargs): # pragma: no cover
196
199
  main = pn.Row(
197
- self.to_dynamic_map(),
200
+ self.to_dynamic_map(result_var=result_var, **kwargs),
198
201
  )
199
202
  main.show()
200
203
 
@@ -1,5 +1,5 @@
1
1
  from enum import auto
2
- from typing import List, Callable, Any
2
+ from typing import List, Callable, Any, Optional
3
3
 
4
4
  import panel as pn
5
5
  import param
@@ -87,8 +87,16 @@ class ResultHmap(param.Parameter):
87
87
  return hash_sha1(self)
88
88
 
89
89
 
90
- def curve(x_vals: List[float], y_vals: List[float], x_name: str, y_name: str, **kwargs) -> hv.Curve:
91
- return hv.Curve(zip(x_vals, y_vals), kdims=[x_name], vdims=[y_name], label=y_name, **kwargs)
90
+ def curve(
91
+ x_vals: List[float],
92
+ y_vals: List[float],
93
+ x_name: str,
94
+ y_name: str,
95
+ label: Optional[str] = None,
96
+ **kwargs,
97
+ ) -> hv.Curve:
98
+ label = label or y_name
99
+ return hv.Curve(zip(x_vals, y_vals), kdims=[x_name], vdims=[y_name], label=label, **kwargs)
92
100
 
93
101
 
94
102
  class PathResult(param.Filename):
@@ -11,12 +11,10 @@ from bencher.utils import hash_sha1
11
11
 
12
12
  # slots that are shared across all Sweep classes
13
13
  # param and slots don't work easily with multiple inheritance so define here
14
- shared_slots = ["units", "samples", "samples_debug"]
14
+ shared_slots = ["units", "samples"]
15
15
 
16
16
 
17
- def describe_variable(
18
- v: Parameterized, debug: bool, include_samples: bool, value=None
19
- ) -> List[str]:
17
+ def describe_variable(v: Parameterized, include_samples: bool, value=None) -> List[str]:
20
18
  """Generate a string description of a variable
21
19
 
22
20
  Args:
@@ -32,8 +30,8 @@ def describe_variable(
32
30
  sampling_str.append(f"{v.name}:")
33
31
  if include_samples:
34
32
  # sampling_str.append(f"{indent}{v.sampling_str(debug)}")
35
- sampling_str.append(f"{indent}number of samples: {len(v.values(debug))}")
36
- sampling_str.append(f"{indent}sample values: {[str(v) for v in v.values(debug)]}")
33
+ sampling_str.append(f"{indent}number of samples: {len(v.values())}")
34
+ sampling_str.append(f"{indent}sample values: {[str(v) for v in v.values()]}")
37
35
 
38
36
  if value is not None:
39
37
  sampling_str.append(f"{indent}value: {value}")
@@ -51,15 +49,14 @@ class SweepBase(param.Parameter):
51
49
  # def __init__(self, **params):
52
50
  # super().__init__(**params)
53
51
  # self.units = ""
54
- # slots = ["units", "samples", "samples_debug"]
52
+ # slots = ["units", "samples"]
55
53
  # __slots__ = shared_slots
56
54
 
57
- def values(self, debug: bool) -> List[Any]:
55
+ def values(
56
+ self,
57
+ ) -> List[Any]:
58
58
  """All sweep classes must implement this method. This generates sample values from based on the parameters bounds and sample number.
59
59
 
60
- Args:
61
- debug (bool): Return a reduced set of samples to enable fast debugging of a data generation and plotting pipeline. Ideally when debug is true, 2 samples will be returned
62
-
63
60
  Returns:
64
61
  List[Any]: A list of samples from the variable
65
62
  """
@@ -67,22 +64,16 @@ class SweepBase(param.Parameter):
67
64
 
68
65
  def hash_persistent(self) -> str:
69
66
  """A hash function that avoids the PYTHONHASHSEED 'feature' which returns a different hash value each time the program is run"""
70
- return hash_sha1(
71
- (self.units, self.samples, self.samples_debug) # pylint: disable=no-member
72
- )
73
-
74
- def sampling_str(self, debug=False) -> str:
75
- """Generate a string representation of the of the sampling procedure
67
+ return hash_sha1((self.units, self.samples)) # pylint: disable=no-member
76
68
 
77
- Args:
78
- debug (bool): If true then self.samples_debug is used
79
- """
69
+ def sampling_str(self) -> str:
70
+ """Generate a string representation of the of the sampling procedure"""
80
71
 
81
- samples = self.values(debug)
72
+ samples = self.values()
82
73
  object_str = ",".join([str(i) for i in samples])
83
74
  return f"Taking {len(samples)} samples from {self.name} with values: [{object_str}]"
84
75
 
85
- def as_slider(self, debug=False) -> pn.widgets.slider.DiscreteSlider:
76
+ def as_slider(self) -> pn.widgets.slider.DiscreteSlider:
86
77
  """given a sweep variable (self), return the range of values as a panel slider
87
78
 
88
79
  Args:
@@ -91,9 +82,9 @@ class SweepBase(param.Parameter):
91
82
  Returns:
92
83
  pn.widgets.slider.DiscreteSlider: A panel slider with the values() of the sweep variable
93
84
  """
94
- return pn.widgets.slider.DiscreteSlider(name=self.name, options=list(self.values(debug)))
85
+ return pn.widgets.slider.DiscreteSlider(name=self.name, options=list(self.values()))
95
86
 
96
- def as_dim(self, compute_values=False, debug=False) -> hv.Dimension:
87
+ def as_dim(self, compute_values=False) -> hv.Dimension:
97
88
  """Takes a sweep variable and turns it into a holoview dimension
98
89
 
99
90
  Returns:
@@ -102,22 +93,26 @@ class SweepBase(param.Parameter):
102
93
  name_tuple = (self.name, self.name)
103
94
 
104
95
  params = {}
105
- if hasattr(self, "bounds"):
96
+ if hasattr(self, "bounds") and self.bounds is not None:
106
97
  if compute_values:
107
- params["values"] = self.values(debug)
98
+ params["values"] = self.values()
108
99
  # params["range"] = tuple(self.bounds)
109
100
  else:
110
101
  params["range"] = tuple(self.bounds)
111
102
  params["default"] = self.default
112
103
 
113
104
  else:
114
- params["values"] = self.values(debug)
105
+ params["values"] = self.values()
115
106
  params["default"] = self.default
116
107
 
117
108
  if hasattr(self, "step"):
118
109
  params["step"] = getattr(self, "step")
119
110
 
120
- return hv.Dimension(name_tuple, unit=self.units, **params) # pylint: disable=no-member
111
+ # TODO investigate why this stopped working after a holoviews update
112
+ # if hasattr(self, "units"):
113
+ # params["unit"] = getattr(self, "units")
114
+
115
+ return hv.Dimension(name_tuple, **params)
121
116
 
122
117
  def indices_to_samples(self, desires_num_samples, sample_values):
123
118
  indices = [
@@ -11,7 +11,7 @@ class TimeBase(SweepBase, Selector):
11
11
 
12
12
  __slots__ = shared_slots
13
13
 
14
- def values(self, debug=False) -> List[str]:
14
+ def values(self) -> List[str]:
15
15
  """return all the values for a parameter sweep. If debug is true return a reduced list"""
16
16
  # print(self.sampling_str(debug))
17
17
  return self.objects
@@ -27,7 +27,6 @@ class TimeSnapshot(TimeBase):
27
27
  datetime_src: datetime | str,
28
28
  units: str = "time",
29
29
  samples: int = None,
30
- samples_debug: int = 2,
31
30
  **params,
32
31
  ):
33
32
  if isinstance(datetime_src, str):
@@ -44,7 +43,6 @@ class TimeSnapshot(TimeBase):
44
43
  self.samples = len(self.objects)
45
44
  else:
46
45
  self.samples = samples
47
- self.samples_debug = min(self.samples, samples_debug)
48
46
 
49
47
 
50
48
  class TimeEvent(TimeBase):
@@ -57,7 +55,6 @@ class TimeEvent(TimeBase):
57
55
  time_event: str,
58
56
  units: str = "event",
59
57
  samples: int = None,
60
- samples_debug: int = 2,
61
58
  **params,
62
59
  ):
63
60
  TimeBase.__init__(
@@ -71,4 +68,3 @@ class TimeEvent(TimeBase):
71
68
  self.samples = len(self.objects)
72
69
  else:
73
70
  self.samples = samples
74
- self.samples_debug = min(self.samples, samples_debug)
@@ -79,7 +79,8 @@ class VideoWriter:
79
79
  else:
80
80
  self.image_files.append(filepath)
81
81
 
82
- def to_images_sequence(self, images, target_duration: float = 10.0, frame_time=None):
82
+ def to_images_sequence(self, images, target_duration: float = 10.0, frame_time=None, **kwargs):
83
+ target_duration = kwargs.pop("target_duration", target_duration)
83
84
  if isinstance(images, list) and len(images) > 0:
84
85
  if frame_time is None:
85
86
  fps = len(images) / target_duration
@@ -90,10 +91,10 @@ class VideoWriter:
90
91
  return ImageSequenceClip(images, fps=fps, with_mask=False)
91
92
  return None
92
93
 
93
- def write_png(self):
94
+ def write_png(self, **kwargs):
94
95
  clip = None
95
96
  if len(self.image_files) > 0:
96
- clip = self.to_images_sequence(self.image_files)
97
+ clip = self.to_images_sequence(self.image_files, **kwargs)
97
98
  if len(self.video_files) > 0:
98
99
  clip = concatenate_videoclips([VideoFileClip(f) for f in self.video_files])
99
100
  if clip is not None:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "holobench"
3
- version = "1.9.0"
3
+ version = "1.11.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"
@@ -11,20 +11,20 @@ readme = "README.md"
11
11
 
12
12
 
13
13
  dependencies = [
14
- "holoviews>=1.15,<=1.18.1",
15
- "numpy>=1.0,<=1.26.3",
16
- "param>=1.13.0,<=2.0.2",
14
+ "holoviews>=1.15,<=1.18.3",
15
+ "numpy>=1.0,<=1.26.4",
16
+ "param>=1.13.0,<=2.1.0",
17
17
  "hvplot>=0.8,<=0.9.2",
18
- "matplotlib>=3.6.3,<=3.8.2",
19
- "panel>=1.3.6,<=1.3.8",
18
+ "matplotlib>=3.6.3,<=3.8.3",
19
+ "panel>=1.3.6,<=1.4.0",
20
20
  "diskcache>=5.6,<=5.6.3",
21
- "optuna>=3.2,<=3.5.0",
22
- "xarray>=2023.7,<=2024.1.1",
23
- "plotly>=5.15,<=5.18.0",
21
+ "optuna>=3.2,<=3.6.1",
22
+ "xarray>=2023.7,<=2024.3.0",
23
+ "plotly>=5.15,<=5.20.0",
24
24
  "sortedcontainers>=2.4,<=2.4",
25
- "pandas>=2.0,<=2.2.0",
25
+ "pandas>=2.0,<=2.2.1",
26
26
  "strenum>=0.4.0,<=0.4.15",
27
- "scikit-learn>=1.2,<=1.4.0",
27
+ "scikit-learn>=1.2,<=1.4.1.post1",
28
28
  "str2bool>=1.1,<=1.1",
29
29
  "scoop>=0.7.0,<=0.7.2.0",
30
30
  "moviepy>=1.0.3,<=1.0.3",
@@ -36,8 +36,8 @@ test = [
36
36
  "pylint>=2.16,<=3.0.3",
37
37
  "pytest-cov>=4.1,<=4.1",
38
38
  "pytest>=7.4,<=8.0.0",
39
- "hypothesis>=6.82,<=6.97.4",
40
- "ruff>=0.0.280,<=0.1.15",
39
+ "hypothesis>=6.82,<=6.97.1",
40
+ "ruff>=0.0.280,<=0.1.14",
41
41
  "coverage>=7.2.7,<=7.4.1",
42
42
  ]
43
43
 
@@ -74,7 +74,7 @@ line-length = 100
74
74
  [tool.ruff]
75
75
  # Never enforce `E501` (line length violations).
76
76
  #"F841" will auto remove unused variables which is annoying during development, pylint catches this anyway
77
- ignore = ["E501", "E902", "F841"]
77
+ lint.ignore = ["E501", "E902", "F841"]
78
78
 
79
79
 
80
80
  # Same as Black.
@@ -83,10 +83,10 @@ line-length = 100
83
83
  target-version = "py310"
84
84
 
85
85
  # Allow unused variables when underscore-prefixed.
86
- dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
86
+ lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
87
87
 
88
88
  # Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
89
- [tool.ruff.per-file-ignores]
89
+ [tool.ruff.lint.per-file-ignores]
90
90
  "__init__.py" = ["E402", "F401"]
91
91
 
92
92
 
File without changes
File without changes
File without changes