holobench 1.25.2__py3-none-any.whl → 1.27.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. bencher/bench_report.py +6 -109
  2. bencher/example/__init__.py +0 -0
  3. bencher/example/benchmark_data.py +196 -0
  4. bencher/example/example_all.py +45 -0
  5. bencher/example/example_categorical.py +99 -0
  6. bencher/example/example_composable_container.py +106 -0
  7. bencher/example/example_composable_container2.py +160 -0
  8. bencher/example/example_consts.py +39 -0
  9. bencher/example/example_custom_sweep.py +59 -0
  10. bencher/example/example_custom_sweep2.py +42 -0
  11. bencher/example/example_docs.py +34 -0
  12. bencher/example/example_filepath.py +27 -0
  13. bencher/example/example_float3D.py +101 -0
  14. bencher/example/example_float_cat.py +99 -0
  15. bencher/example/example_floats.py +89 -0
  16. bencher/example/example_floats2D.py +93 -0
  17. bencher/example/example_holosweep.py +98 -0
  18. bencher/example/example_holosweep_objects.py +111 -0
  19. bencher/example/example_holosweep_tap.py +144 -0
  20. bencher/example/example_image.py +155 -0
  21. bencher/example/example_levels.py +181 -0
  22. bencher/example/example_levels2.py +37 -0
  23. bencher/example/example_pareto.py +53 -0
  24. bencher/example/example_sample_cache.py +85 -0
  25. bencher/example/example_sample_cache_context.py +116 -0
  26. bencher/example/example_simple.py +134 -0
  27. bencher/example/example_simple_bool.py +35 -0
  28. bencher/example/example_simple_cat.py +48 -0
  29. bencher/example/example_simple_float.py +28 -0
  30. bencher/example/example_simple_float2d.py +29 -0
  31. bencher/example/example_strings.py +47 -0
  32. bencher/example/example_time_event.py +63 -0
  33. bencher/example/example_video.py +118 -0
  34. bencher/example/example_workflow.py +189 -0
  35. bencher/example/experimental/example_bokeh_plotly.py +38 -0
  36. bencher/example/experimental/example_hover_ex.py +45 -0
  37. bencher/example/experimental/example_hvplot_explorer.py +39 -0
  38. bencher/example/experimental/example_interactive.py +75 -0
  39. bencher/example/experimental/example_streamnd.py +49 -0
  40. bencher/example/experimental/example_streams.py +36 -0
  41. bencher/example/experimental/example_template.py +40 -0
  42. bencher/example/experimental/example_updates.py +84 -0
  43. bencher/example/experimental/example_vector.py +84 -0
  44. bencher/example/meta/example_meta.py +171 -0
  45. bencher/example/meta/example_meta_cat.py +25 -0
  46. bencher/example/meta/example_meta_float.py +23 -0
  47. bencher/example/meta/example_meta_levels.py +26 -0
  48. bencher/example/optuna/example_optuna.py +78 -0
  49. bencher/example/shelved/example_float2D_scatter.py +109 -0
  50. bencher/example/shelved/example_float3D_cone.py +96 -0
  51. bencher/example/shelved/example_kwargs.py +63 -0
  52. bencher/plotting/__init__.py +0 -0
  53. bencher/plotting/plot_filter.py +110 -0
  54. bencher/plotting/plt_cnt_cfg.py +75 -0
  55. bencher/results/__init__.py +0 -0
  56. bencher/results/bench_result.py +94 -0
  57. bencher/results/bench_result_base.py +476 -0
  58. bencher/results/composable_container/__init__.py +0 -0
  59. bencher/results/composable_container/composable_container_base.py +73 -0
  60. bencher/results/composable_container/composable_container_panel.py +39 -0
  61. bencher/results/composable_container/composable_container_video.py +184 -0
  62. bencher/results/float_formatter.py +44 -0
  63. bencher/results/holoview_result.py +753 -0
  64. bencher/results/optuna_result.py +354 -0
  65. bencher/results/panel_result.py +41 -0
  66. bencher/results/plotly_result.py +65 -0
  67. bencher/results/video_result.py +38 -0
  68. bencher/results/video_summary.py +222 -0
  69. bencher/variables/__init__.py +0 -0
  70. bencher/variables/inputs.py +202 -0
  71. bencher/variables/parametrised_sweep.py +208 -0
  72. bencher/variables/results.py +214 -0
  73. bencher/variables/sweep_base.py +162 -0
  74. bencher/variables/time.py +92 -0
  75. holobench-1.27.0.data/data/share/ament_index/resource_index/packages/bencher +0 -0
  76. holobench-1.27.0.data/data/share/bencher/package.xml +33 -0
  77. {holobench-1.25.2.dist-info → holobench-1.27.0.dist-info}/METADATA +5 -5
  78. holobench-1.27.0.dist-info/RECORD +93 -0
  79. holobench-1.25.2.dist-info/RECORD +0 -18
  80. {holobench-1.25.2.dist-info → holobench-1.27.0.dist-info}/LICENSE +0 -0
  81. {holobench-1.25.2.dist-info → holobench-1.27.0.dist-info}/WHEEL +0 -0
  82. {holobench-1.25.2.dist-info → holobench-1.27.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,93 @@
1
+ # pylint: disable=duplicate-code
2
+ import bencher as bch
3
+
4
+ # All the examples will be using the data structures and benchmark function defined in this file
5
+ from bencher.example.benchmark_data import (
6
+ ExampleBenchCfgOut,
7
+ NoiseDistribution,
8
+ ExampleBenchCfg,
9
+ call,
10
+ )
11
+
12
+
13
+ def example_floats2D(
14
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
15
+ ) -> bch.Bench:
16
+ """Example of how to perform a 2D floating point parameter sweep
17
+
18
+ Args:
19
+ run_cfg (BenchRunCfg): configuration of how to perform the param sweep
20
+
21
+ Returns:
22
+ Bench: results of the parameter sweep
23
+ """
24
+ bench = bch.Bench(
25
+ "Bencher_Example_Floats",
26
+ call,
27
+ run_cfg=run_cfg,
28
+ report=report,
29
+ )
30
+ run_cfg.use_optuna = True
31
+
32
+ bench.plot_sweep(
33
+ input_vars=[ExampleBenchCfg.param.theta, ExampleBenchCfg.param.offset],
34
+ result_vars=[ExampleBenchCfgOut.param.out_sin, ExampleBenchCfgOut.param.out_cos],
35
+ const_vars=[
36
+ ExampleBenchCfg.param.sigma.with_const(0.1),
37
+ ExampleBenchCfg.param.noise_distribution.with_const(NoiseDistribution.gaussian),
38
+ ExampleBenchCfg.param.noisy.with_const(True),
39
+ ],
40
+ title="Float 2D Example",
41
+ description="""Bencher is a tool to make it easy to explore how input parameter affect a range of output metrics. In these examples we are going to benchmark an example function which has been selected to show the features of bencher.
42
+ The example function takes an input theta and returns the absolute value of sin(theta) and cos(theta) +- various types of noise.
43
+
44
+ The following examples will show how to perform parameter sweeps to characterise the behavior of the function. The idea is that the benchmarking can be used to gain understanding of an unknown function.
45
+ """,
46
+ post_description="Here you can see the output plot of sin theta between 0 and pi. In the tabs at the top you can also view 3 tabular representations of the data",
47
+ )
48
+
49
+ bench.report.append(bench.get_result().to_surface())
50
+
51
+ bench.plot_sweep(
52
+ input_vars=[
53
+ ExampleBenchCfg.param.theta,
54
+ ExampleBenchCfg.param.offset,
55
+ ExampleBenchCfg.param.postprocess_fn,
56
+ ],
57
+ result_vars=[ExampleBenchCfgOut.param.out_sin, ExampleBenchCfgOut.param.out_cos],
58
+ const_vars=[
59
+ (ExampleBenchCfg.param.sigma, 0.1),
60
+ (ExampleBenchCfg.param.noise_distribution, NoiseDistribution.gaussian),
61
+ (ExampleBenchCfg.param.noisy, True),
62
+ ],
63
+ title="Float 2D with categorical Example",
64
+ description="""Here we add plot a 2d surface and facet over a categorical variable
65
+ """,
66
+ )
67
+ bench.report.append(bench.get_result().to_surface())
68
+
69
+ bench.plot_sweep(
70
+ input_vars=[
71
+ ExampleBenchCfg.param.theta,
72
+ ExampleBenchCfg.param.offset,
73
+ ExampleBenchCfg.param.postprocess_fn,
74
+ ExampleBenchCfg.param.noise_distribution,
75
+ ],
76
+ result_vars=[ExampleBenchCfgOut.param.out_sin, ExampleBenchCfgOut.param.out_cos],
77
+ const_vars=[
78
+ (ExampleBenchCfg.param.sigma, 0.1),
79
+ (ExampleBenchCfg.param.noise_distribution, NoiseDistribution.gaussian),
80
+ (ExampleBenchCfg.param.noisy, True),
81
+ ],
82
+ title="Float 2D with categorical x2 Example",
83
+ description="""Here we add plot a 2d surface and facet over two categorical variable
84
+ """,
85
+ )
86
+
87
+ bench.report.append(bench.get_result().to_surface())
88
+
89
+ return bench
90
+
91
+
92
+ if __name__ == "__main__":
93
+ example_floats2D(bch.BenchRunCfg(repeats=2, level=3)).report.show()
@@ -0,0 +1,98 @@
1
+ # THIS IS NOT A WORKING EXAMPLE YET
2
+
3
+ # pylint: disable=duplicate-code,unused-argument
4
+
5
+
6
+ import bencher as bch
7
+ import math
8
+ import random
9
+ import numpy as np
10
+ import holoviews as hv
11
+
12
+ from strenum import StrEnum
13
+ from enum import auto
14
+
15
+
16
+ class Function(StrEnum):
17
+ fn_cos = auto()
18
+ fn_sin = auto()
19
+ fn_log = auto()
20
+ fn_arctan = auto()
21
+
22
+ def call(self, arg) -> float:
23
+ """Calls the function defined by the name of the enum
24
+
25
+ Returns:
26
+ float: The result of calling the function defined by the enum
27
+ """
28
+ return getattr(np, self.removeprefix("fn_"))(arg)
29
+
30
+
31
+ class PlotFunctions(bch.ParametrizedSweep):
32
+ phase = bch.FloatSweep(
33
+ default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=5
34
+ )
35
+
36
+ freq = bch.FloatSweep(default=1, bounds=[0, math.pi], doc="Input angle", units="rad", samples=5)
37
+
38
+ theta = bch.FloatSweep(
39
+ default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=10
40
+ )
41
+
42
+ compute_fn = bch.EnumSweep(Function)
43
+
44
+ # RESULT VARS
45
+ fn_output = bch.ResultVar(units="v", doc="sin of theta with some noise")
46
+ out_sum = bch.ResultVar(units="v", doc="The sum")
47
+ ref = bch.ResultReference()
48
+ holomap = bch.ResultHmap()
49
+
50
+ def __call__(self, plot=True, **kwargs) -> dict:
51
+ self.update_params_from_kwargs(**kwargs)
52
+ noise = 0.1
53
+
54
+ self.fn_output = self.compute_fn.call(self.phase + self.freq * self.theta) + random.uniform(
55
+ 0, noise
56
+ )
57
+
58
+ self.holomap = self.plot_holo(plot)
59
+ self.ref = bch.ResultReference(self.ref)
60
+
61
+ return self.get_results_values_as_dict()
62
+
63
+ def plot_holo(self, plot=True) -> hv.core.ViewableElement:
64
+ """Plots a generic representation of the object that is not a basic hv datatype. In this case its an image of the values of the object, but it could be any representation of the object, e.g. a screenshot of the object state"""
65
+ if plot:
66
+ pt = hv.Text(0, 0, f"{self.phase}\n{self.freq}\n {self.theta}")
67
+ pt *= hv.Ellipse(0, 0, 1)
68
+ return pt
69
+ return None
70
+
71
+
72
+ def example_holosweep(
73
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
74
+ ) -> bch.Bench:
75
+ bench = PlotFunctions().to_bench(run_cfg, report)
76
+
77
+ bench.plot_sweep(
78
+ input_vars=["theta", "freq"],
79
+ result_vars=["fn_output", "holomap"],
80
+ )
81
+
82
+ # print("best", res.get_best_trial_params(True))
83
+ # print(res.hmap_kdims)
84
+ # bench.report.append(res.describe_sweep())
85
+ # bench.report.append(res.to_optuna_plots())
86
+ # bench.report.append(res.get_best_holomap())
87
+ # bench.report.append(res.to_curve(), "Slider view")
88
+ # bench.report.append(res.to_holomap())
89
+
90
+ # bench.report.append(res.to_holomap().layout())
91
+ return bench
92
+
93
+
94
+ if __name__ == "__main__":
95
+ PlotFunctions().to_gui()
96
+ bench_run = bch.BenchRunner("bench_runner_test")
97
+ bench_run.add_run(example_holosweep)
98
+ bench_run.run(level=6, show=True, use_cache=False)
@@ -0,0 +1,111 @@
1
+ # THIS IS NOT A WORKING EXAMPLE YET
2
+
3
+ # pylint: disable=duplicate-code,unused-argument
4
+
5
+
6
+ import bencher as bch
7
+ import math
8
+ import random
9
+ import numpy as np
10
+ import holoviews as hv
11
+
12
+ from strenum import StrEnum
13
+ from enum import auto
14
+
15
+
16
+ class Function(StrEnum):
17
+ fn_cos = auto()
18
+ fn_sin = auto()
19
+ fn_log = auto()
20
+ fn_arctan = auto()
21
+
22
+ def call(self, arg) -> float:
23
+ """Calls the function defined by the name of the enum
24
+
25
+ Returns:
26
+ float: The result of calling the function defined by the enum
27
+ """
28
+ return getattr(np, self.removeprefix("fn_"))(arg)
29
+
30
+
31
+ class FunctionInputs(bch.ParametrizedSweep):
32
+ phase = bch.FloatSweep(
33
+ default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=5
34
+ )
35
+
36
+ freq = bch.FloatSweep(default=1, bounds=[0, math.pi], doc="Input angle", units="rad", samples=5)
37
+
38
+ theta = bch.FloatSweep(
39
+ default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=10
40
+ )
41
+
42
+ compute_fn = bch.EnumSweep(Function)
43
+
44
+
45
+ class FunctionOutputs(bch.ParametrizedSweep):
46
+ fn_output = bch.ResultVar(units="v", doc="sin of theta with some noise")
47
+
48
+ out_sum = bch.ResultVar(units="v", doc="The sum")
49
+
50
+ hmap = bch.ResultHmap()
51
+
52
+ hmap2 = bch.ResultHmap()
53
+
54
+
55
+ def bench_fn(self, **kwargs) -> dict:
56
+ fin = FunctionInputs()
57
+ fin.update_params_from_kwargs(**kwargs)
58
+
59
+ output = FunctionOutputs()
60
+
61
+ output.fn_output = fin.compute_fn.call(fin.phase + fin.freq * fin.theta) + random.uniform(0, 0)
62
+ output.hmap = hv.Text(0, 0, f"{fin.phase}\n{fin.freq}\n {fin.theta}")
63
+ output.hmap2 = hv.Ellipse(0, 0, 1)
64
+ return output
65
+
66
+
67
+ def plot_holo(self, plot=True) -> hv.core.ViewableElement:
68
+ """Plots a generic representation of the object that is not a basic hv datatype. In this case its an image of the values of the object, but it could be any representation of the object, e.g. a screenshot of the object state"""
69
+ if plot:
70
+ pt = hv.Text(0, 0, f"{self.phase}\n{self.freq}\n {self.theta}")
71
+ pt *= hv.Ellipse(0, 0, 1)
72
+ return pt
73
+ return None
74
+
75
+
76
+ def example_holosweep(
77
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
78
+ ) -> bch.Bench:
79
+ # wv = PlotFunctions()
80
+
81
+ bench = bch.Bench(
82
+ "waves", bench_fn, worker_input_cfg=FunctionInputs, run_cfg=run_cfg, report=report
83
+ )
84
+
85
+ res = bench.plot_sweep(
86
+ "phase",
87
+ input_vars=[FunctionInputs.param.theta, FunctionInputs.param.freq],
88
+ result_vars=[
89
+ FunctionOutputs.param.fn_output,
90
+ FunctionOutputs.param.hmap,
91
+ FunctionOutputs.param.hmap2,
92
+ ],
93
+ )
94
+
95
+ # bench.report.append(res.summarise_sweep())
96
+ # bench.report.append(res.to_optuna())
97
+ # bench.report.append(res.get_best_holomap())
98
+ # bench.report.append(res.to_curve(), "Slider view")
99
+ # bench.report.append(res.to_holomap().layout())
100
+ # print(res.to_holomap())
101
+ bench.report.append(res.to_holomap())
102
+ # bench.report.append(res.to_holomap())
103
+
104
+ return bench
105
+
106
+
107
+ if __name__ == "__main__":
108
+ bench_run = bch.BenchRunner("bench_runner_test", run_cfg=bch.BenchRunCfg())
109
+
110
+ bench_run.add_run(example_holosweep)
111
+ bench_run.run(level=4, show=True)
@@ -0,0 +1,144 @@
1
+ # THIS IS NOT A WORKING EXAMPLE YET
2
+
3
+ # pylint: disable=duplicate-code,unused-argument
4
+
5
+
6
+ import bencher as bch
7
+ import math
8
+ import random
9
+ import numpy as np
10
+ import holoviews as hv
11
+
12
+ from strenum import StrEnum
13
+ from enum import auto
14
+
15
+
16
+ class Function(StrEnum):
17
+ fn_cos = auto()
18
+ fn_sin = auto()
19
+ fn_log = auto()
20
+ fn_arctan = auto()
21
+
22
+ def call(self, arg) -> float:
23
+ """Calls the function defined by the name of the enum
24
+
25
+ Returns:
26
+ float: The result of calling the function defined by the enum
27
+ """
28
+ return getattr(np, self.removeprefix("fn_"))(arg)
29
+
30
+
31
+ class PlotFunctions(bch.ParametrizedSweep):
32
+ phase = bch.FloatSweep(
33
+ default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=5
34
+ )
35
+
36
+ freq = bch.FloatSweep(default=1, bounds=[0, math.pi], doc="Input angle", units="rad", samples=5)
37
+
38
+ theta = bch.FloatSweep(
39
+ default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=10
40
+ )
41
+
42
+ compute_fn = bch.EnumSweep(Function)
43
+
44
+ fn_output = bch.ResultVar(units="v", doc="sin of theta with some noise")
45
+
46
+ out_sum = bch.ResultVar(units="v", doc="The sum")
47
+
48
+ hmap = bch.ResultHmap()
49
+
50
+ def __call__(self, plot=True, **kwargs) -> dict:
51
+ self.update_params_from_kwargs(**kwargs)
52
+ noise = 0.1
53
+
54
+ self.fn_output = self.compute_fn.call(self.phase + self.freq * self.theta) + random.uniform(
55
+ 0, noise
56
+ )
57
+ self.hmap = self.plot_holo(plot)
58
+
59
+ return self.get_results_values_as_dict()
60
+
61
+ def plot_holo(self, plot=True) -> hv.core.ViewableElement:
62
+ """Plots a generic representation of the object that is not a basic hv datatype. In this case its an image of the values of the object, but it could be any representation of the object, e.g. a screenshot of the object state"""
63
+ if plot:
64
+ pt = hv.Text(0, 0, f"phase:{self.phase}\nfreq:{self.freq}\ntheta:{self.theta}")
65
+ pt *= hv.Ellipse(0, 0, 1)
66
+ return pt
67
+ return None
68
+
69
+ def calc_vec(self, **kwargs) -> dict:
70
+ theta = self.param.theta.values()
71
+ kwargs.pop("theta", 0)
72
+ dat = [self.__call__(plot=False, theta=i, **kwargs)["fn_output"] for i in theta]
73
+ # print(dat)
74
+ self.out_sum = sum(dat)
75
+ self.hmap = hv.Curve((theta, dat), "theta", "voltage")
76
+ # pt = hv.Text(0, 0, f"{self.compute_fn}\n{self.phase}\n{self.freq}")
77
+ # pt *= hv.Ellipse(0, 0, 1)
78
+ return self.get_results_values_as_dict()
79
+
80
+
81
+ def example_holosweep_tap(
82
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
83
+ ) -> bch.Bench:
84
+ wv = PlotFunctions()
85
+
86
+ run_cfg.use_optuna = True
87
+ run_cfg.auto_plot = False
88
+ bench = bch.Bench("waves", wv, run_cfg=run_cfg, report=report)
89
+
90
+ res = bench.plot_sweep(
91
+ "phase",
92
+ input_vars=[PlotFunctions.param.theta, PlotFunctions.param.freq],
93
+ result_vars=[PlotFunctions.param.fn_output, PlotFunctions.param.hmap],
94
+ run_cfg=run_cfg,
95
+ )
96
+
97
+ bench.report.append(res.describe_sweep())
98
+ bench.report.append(res.to_heatmap_tap(PlotFunctions.param.fn_output))
99
+
100
+ return bench
101
+
102
+
103
+ def example_holosweep_tap_slider(
104
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
105
+ ) -> bch.Bench: # pragma: no cover
106
+ wv = PlotFunctions()
107
+
108
+ run_cfg.use_optuna = True
109
+ bench = bch.Bench("waves", wv, run_cfg=run_cfg, report=report)
110
+
111
+ res = bench.plot_sweep(
112
+ "phase",
113
+ input_vars=[PlotFunctions.param.theta, PlotFunctions.param.freq, PlotFunctions.param.phase],
114
+ result_vars=[PlotFunctions.param.fn_output],
115
+ run_cfg=run_cfg,
116
+ )
117
+
118
+ print(res.get_best_trial_params())
119
+ bench.report.append(res.get_best_holomap())
120
+
121
+ heatmap = res.to_heatmap().opts(tools=["hover", "tap"])
122
+ posxy = hv.streams.Tap(source=heatmap, x=0, y=0)
123
+ sld1 = wv.param.phase.as_slider()
124
+
125
+ def tap_plot(x, y):
126
+ print(x, y)
127
+ selres = bch.get_nearest_coords(res.ds, theta=x, freq=y, phase=sld1.value, repeat=1)
128
+ return res.hmaps[bch.hmap_canonical_input(selres)]
129
+
130
+ tap_dmap = hv.DynamicMap(tap_plot, streams=[posxy])
131
+
132
+ bench.report.append_tab(heatmap + tap_dmap, "Interactive Heatmap")
133
+ bench.report.append(sld1)
134
+
135
+ bench.report.append_tab(res.to_curve(), "Slider view")
136
+
137
+ return bench
138
+
139
+
140
+ if __name__ == "__main__":
141
+ example_holosweep_tap(bch.BenchRunCfg()).report.show()
142
+
143
+
144
+ # todo https://discourse.holoviz.org/t/pointdraw-as-parameterized-class/3539
@@ -0,0 +1,155 @@
1
+ import bencher as bch
2
+ import numpy as np
3
+ import math
4
+ import matplotlib.pyplot as plt
5
+
6
+
7
+ def polygon_points(radius: float, sides: int, start_angle: float):
8
+ points = []
9
+ for ang in np.linspace(0, 360, sides + 1):
10
+ angle = math.radians(start_angle + ang)
11
+ points.append(([math.sin(angle) * radius, math.cos(angle) * radius]))
12
+ return points
13
+
14
+
15
+ class BenchPolygons(bch.ParametrizedSweep):
16
+ sides = bch.IntSweep(default=3, bounds=(3, 7))
17
+ radius = bch.FloatSweep(default=1, bounds=(0.2, 1))
18
+ linewidth = bch.FloatSweep(default=1, bounds=(1, 10))
19
+ linestyle = bch.StringSweep(["solid", "dashed", "dotted"])
20
+ color = bch.StringSweep(["red", "green", "blue"])
21
+ start_angle = bch.FloatSweep(default=0, bounds=[0, 360])
22
+ polygon = bch.ResultImage()
23
+ area = bch.ResultVar()
24
+ side_length = bch.ResultVar()
25
+
26
+ def __call__(self, **kwargs):
27
+ self.update_params_from_kwargs(**kwargs)
28
+ 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"))
31
+
32
+ self.side_length = 2 * self.radius * math.sin(math.pi / self.sides)
33
+ self.area = (self.sides * self.side_length**2) / (4 * math.tan(math.pi / self.sides))
34
+ return super().__call__()
35
+
36
+ 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)
50
+
51
+ ax.set_aspect("equal")
52
+ fig.add_axes(ax)
53
+ fig.savefig(filename, dpi=30)
54
+
55
+ return filename
56
+
57
+
58
+ def example_image(
59
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
60
+ ) -> bch.Bench:
61
+ run_cfg.use_cache = False
62
+ bench = bch.Bench("polygons", BenchPolygons(), run_cfg=run_cfg, report=report)
63
+
64
+ bench.result_vars = ["polygon", "area"]
65
+
66
+ bench.add_plot_callback(bch.BenchResult.to_sweep_summary)
67
+ # bench.add_plot_callback(bch.BenchResult.to_auto, level=2)
68
+ bench.add_plot_callback(bch.BenchResult.to_panes, level=3)
69
+ # bench.add_plot_callback(bch.BenchResult.to_panes)
70
+
71
+ sweep_vars = ["sides", "radius", "linewidth", "color"]
72
+
73
+ # sweep_vars = ["sides", "radius" ]
74
+
75
+ for i in range(1, len(sweep_vars)):
76
+ s = sweep_vars[:i]
77
+ bench.plot_sweep(
78
+ f"Polygons Sweeping {len(s)} Parameters",
79
+ input_vars=s,
80
+ )
81
+ bench.report.append(bench.get_result().to_panes())
82
+
83
+ return bench
84
+
85
+
86
+ def example_image_vid(run_cfg: bch.BenchRunCfg = None, report: bch.BenchReport = None) -> bch.Bench:
87
+ bench = BenchPolygons().to_bench(run_cfg, report)
88
+ bench.add_plot_callback(bch.BenchResult.to_sweep_summary)
89
+ bench.add_plot_callback(
90
+ bch.BenchResult.to_video_grid,
91
+ target_duration=0.06,
92
+ compose_method_list=[
93
+ bch.ComposeType.right,
94
+ bch.ComposeType.right,
95
+ bch.ComposeType.sequence,
96
+ ],
97
+ )
98
+ # from functools import partial
99
+ # bench.add_plot_callback(bch.BenchResult.to_video_summary)
100
+ # bench.add_plot_callback(bch.BenchResult.to_video_grid, time_sequence_dimension=0)
101
+ # bench.add_plot_callback(bch.BenchResult.to_video_grid)
102
+ # bench.add_plot_callback(bch.BenchResult.to_video_grid, time_sequence_dimension=2)
103
+ # bench.add_plot_callback(bch.BenchResult.to_video_grid, time_sequence_dimension=3)
104
+
105
+ bench.plot_sweep(input_vars=["radius"])
106
+ # res = bench.plot_sweep(input_vars=["radius"], plot=False)
107
+ # bench.report.append(res.to_video_grid(target_duration=0.06))
108
+ bench.plot_sweep(input_vars=["radius", "sides"])
109
+ # bench.plot_sweep(input_vars=["radius", "sides", "linewidth"])
110
+ # bench.plot_sweep(input_vars=["radius", "sides", "linewidth", "color"])
111
+
112
+ return bench
113
+
114
+
115
+ if __name__ == "__main__":
116
+
117
+ def simple():
118
+ bench = BenchPolygons().to_bench(bch.BenchRunCfg(level=4))
119
+
120
+ # bench.plot_sweep(input_vars=["sides","color","radius"])
121
+
122
+ # res = bench.sweep(input_vars=["sides", "radius"])
123
+
124
+ # bench.report.append(res.to_heatmap(target_dimension=3))
125
+
126
+ bench.plot_sweep(input_vars=["sides"])
127
+ bench.plot_sweep(input_vars=["sides", "color"])
128
+
129
+ bench.plot_sweep(input_vars=["sides", "radius"])
130
+
131
+ # bench.report.append(res.to_line(target_dimension=1))
132
+
133
+ return bench
134
+
135
+ def example_image_vid_sequential(
136
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
137
+ ) -> bch.Bench:
138
+ bench = BenchPolygons().to_bench(run_cfg, report)
139
+ bench.add_plot_callback(bch.BenchResult.to_title)
140
+ bench.add_plot_callback(bch.BenchResult.to_video_grid)
141
+ bench.sweep_sequential(input_vars=["radius", "sides", "linewidth", "color"], group_size=4)
142
+ return bench
143
+
144
+ # def example_image_pairs()
145
+
146
+ ex_run_cfg = bch.BenchRunCfg()
147
+ ex_run_cfg.use_sample_cache = True
148
+ # ex_run_cfg.debug = True
149
+ # ex_run_cfg.repeats = 2
150
+ ex_run_cfg.level = 4
151
+ example_image_vid(ex_run_cfg).report.show()
152
+ # simple().report.show()
153
+
154
+ # example_image_vid_sequential(ex_run_cfg).report.show()
155
+ # example_image(ex_run_cfg).report.show()