holobench 1.3.6__py2.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 (74) hide show
  1. bencher/__init__.py +41 -0
  2. bencher/bench_cfg.py +462 -0
  3. bencher/bench_plot_server.py +100 -0
  4. bencher/bench_report.py +268 -0
  5. bencher/bench_runner.py +136 -0
  6. bencher/bencher.py +805 -0
  7. bencher/caching.py +51 -0
  8. bencher/example/__init__.py +0 -0
  9. bencher/example/benchmark_data.py +200 -0
  10. bencher/example/example_all.py +45 -0
  11. bencher/example/example_categorical.py +99 -0
  12. bencher/example/example_custom_sweep.py +59 -0
  13. bencher/example/example_docs.py +34 -0
  14. bencher/example/example_float3D.py +101 -0
  15. bencher/example/example_float_cat.py +98 -0
  16. bencher/example/example_floats.py +89 -0
  17. bencher/example/example_floats2D.py +93 -0
  18. bencher/example/example_holosweep.py +104 -0
  19. bencher/example/example_holosweep_objects.py +111 -0
  20. bencher/example/example_holosweep_tap.py +144 -0
  21. bencher/example/example_image.py +82 -0
  22. bencher/example/example_levels.py +181 -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 +34 -0
  28. bencher/example/example_simple_cat.py +47 -0
  29. bencher/example/example_simple_float.py +38 -0
  30. bencher/example/example_strings.py +46 -0
  31. bencher/example/example_time_event.py +62 -0
  32. bencher/example/example_video.py +124 -0
  33. bencher/example/example_workflow.py +189 -0
  34. bencher/example/experimental/example_bokeh_plotly.py +38 -0
  35. bencher/example/experimental/example_hover_ex.py +45 -0
  36. bencher/example/experimental/example_hvplot_explorer.py +39 -0
  37. bencher/example/experimental/example_interactive.py +75 -0
  38. bencher/example/experimental/example_streamnd.py +49 -0
  39. bencher/example/experimental/example_streams.py +36 -0
  40. bencher/example/experimental/example_template.py +40 -0
  41. bencher/example/experimental/example_updates.py +84 -0
  42. bencher/example/experimental/example_vector.py +84 -0
  43. bencher/example/meta/example_meta.py +171 -0
  44. bencher/example/meta/example_meta_cat.py +25 -0
  45. bencher/example/meta/example_meta_float.py +23 -0
  46. bencher/example/meta/example_meta_levels.py +26 -0
  47. bencher/example/optuna/example_optuna.py +78 -0
  48. bencher/example/shelved/example_float2D_scatter.py +109 -0
  49. bencher/example/shelved/example_float3D_cone.py +96 -0
  50. bencher/example/shelved/example_kwargs.py +63 -0
  51. bencher/job.py +184 -0
  52. bencher/optuna_conversions.py +168 -0
  53. bencher/plotting/__init__.py +0 -0
  54. bencher/plotting/plot_filter.py +110 -0
  55. bencher/plotting/plt_cnt_cfg.py +74 -0
  56. bencher/results/__init__.py +0 -0
  57. bencher/results/bench_result.py +80 -0
  58. bencher/results/bench_result_base.py +405 -0
  59. bencher/results/float_formatter.py +44 -0
  60. bencher/results/holoview_result.py +592 -0
  61. bencher/results/optuna_result.py +354 -0
  62. bencher/results/panel_result.py +113 -0
  63. bencher/results/plotly_result.py +65 -0
  64. bencher/utils.py +148 -0
  65. bencher/variables/inputs.py +193 -0
  66. bencher/variables/parametrised_sweep.py +206 -0
  67. bencher/variables/results.py +176 -0
  68. bencher/variables/sweep_base.py +167 -0
  69. bencher/variables/time.py +74 -0
  70. bencher/video_writer.py +30 -0
  71. bencher/worker_job.py +40 -0
  72. holobench-1.3.6.dist-info/METADATA +85 -0
  73. holobench-1.3.6.dist-info/RECORD +74 -0
  74. holobench-1.3.6.dist-info/WHEEL +5 -0
@@ -0,0 +1,89 @@
1
+ # pylint: disable=duplicate-code
2
+
3
+
4
+ import bencher as bch
5
+
6
+ # All the examples will be using the data structures and benchmark function defined in this file
7
+ from bencher.example.benchmark_data import ExampleBenchCfgIn, ExampleBenchCfgOut, ExampleBenchCfg
8
+
9
+
10
+ def example_floats(
11
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
12
+ ) -> bch.Bench:
13
+ """Example of how to perform a parameter sweep for floating point variables
14
+
15
+ Args:
16
+ run_cfg (BenchRunCfg): configuration of how to perform the param sweep
17
+
18
+ Returns:
19
+ Bench: results of the parameter sweep
20
+ """
21
+ bench = bch.Bench("Bencher_Example_Floats", ExampleBenchCfg(), report=report, run_cfg=run_cfg)
22
+
23
+ with open("README.md", "r", encoding="utf-8") as file:
24
+ readme = file.read()
25
+
26
+ bench.report.append(readme, "Intro")
27
+
28
+ bench.plot_sweep(
29
+ input_vars=[ExampleBenchCfgIn.param.theta],
30
+ result_vars=[ExampleBenchCfgOut.param.out_sin],
31
+ title="Float 1D Example",
32
+ 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.
33
+ The example function takes an input theta and returns the absolute value of sin(theta) and cos(theta) +- various types of noise.
34
+
35
+ def bench_function(cfg: ExampleBenchCfgIn) -> ExampleBenchCfgOut:
36
+ "Takes an ExampleBenchCfgIn and returns a ExampleBenchCfgOut output"
37
+ out = ExampleBenchCfgOut()
38
+ noise = calculate_noise(cfg)
39
+ offset = 0.0
40
+
41
+ postprocess_fn = abs if cfg.postprocess_fn == PostprocessFn.absolute else negate_fn
42
+
43
+ out.out_sin = postprocess_fn(offset + math.sin(cfg.theta) + noise)
44
+ out.out_cos = postprocess_fn(offset + math.cos(cfg.theta) + noise)
45
+ return out
46
+
47
+ 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.
48
+ """,
49
+ 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",
50
+ )
51
+
52
+ bench.plot_sweep(
53
+ input_vars=[ExampleBenchCfgIn.param.theta, ExampleBenchCfgIn.param.noisy],
54
+ result_vars=[ExampleBenchCfgOut.param.out_sin],
55
+ title="Float 1D and Bool Example",
56
+ description="""Following from the previous example lets add another input parameter to see how that affects the output. We pass the boolean 'noisy' and keep the other parameters the same""",
57
+ post_description="Now the plot has two lines, one for each of the boolean values where noisy=true and noisy=false.",
58
+ )
59
+
60
+ bench.plot_sweep(
61
+ input_vars=[ExampleBenchCfgIn.param.theta, ExampleBenchCfgIn.param.noisy],
62
+ result_vars=[ExampleBenchCfgOut.param.out_sin, ExampleBenchCfgOut.param.out_cos],
63
+ title="Float 1D and Bool Example with multiple outputs",
64
+ description="""Following from the previous example here the second output is added to the result variables""",
65
+ post_description="Another column is added for the result variable that shows cos(theta)",
66
+ )
67
+
68
+ bench.plot_sweep(
69
+ input_vars=[
70
+ ExampleBenchCfgIn.param.theta,
71
+ ExampleBenchCfgIn.param.noisy,
72
+ ExampleBenchCfgIn.param.postprocess_fn,
73
+ ],
74
+ result_vars=[
75
+ ExampleBenchCfgOut.param.out_sin,
76
+ ExampleBenchCfgOut.param.out_cos,
77
+ ],
78
+ title="Float 1D, Bool and Categorical Example",
79
+ description="""Following from the previous example lets add another input parameter to see how that affects the output. We add the 'postprocess_fn' categorical enum value which either takes the absolute value or negates the output of the function.""",
80
+ post_description="This generates two rows of results, one for each of the category options.",
81
+ )
82
+
83
+ return bench
84
+
85
+
86
+ if __name__ == "__main__":
87
+ bench_ex = example_floats(bch.BenchRunCfg(repeats=2))
88
+ bench_ex.report.save_index()
89
+ bench_ex.report.show()
@@ -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,104 @@
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.ResultReference()
49
+ hmap1 = bch.ResultHmap()
50
+
51
+ def __call__(self, plot=True, **kwargs) -> dict:
52
+ self.update_params_from_kwargs(**kwargs)
53
+ noise = 0.1
54
+
55
+ self.fn_output = self.compute_fn.call(self.phase + self.freq * self.theta) + random.uniform(
56
+ 0, noise
57
+ )
58
+
59
+ self.hmap1 = self.plot_holo(plot)
60
+ self.hmap = bch.ResultReference(self.hmap1)
61
+
62
+ return self.get_results_values_as_dict()
63
+
64
+ def plot_holo(self, plot=True) -> hv.core.ViewableElement:
65
+ """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"""
66
+ if plot:
67
+ pt = hv.Text(0, 0, f"{self.phase}\n{self.freq}\n {self.theta}")
68
+ pt *= hv.Ellipse(0, 0, 1)
69
+ return pt
70
+ return None
71
+
72
+
73
+ def example_holosweep(
74
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
75
+ ) -> 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)
81
+
82
+ 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],
87
+ )
88
+
89
+ # print("best", res.get_best_trial_params(True))
90
+ # print(res.hmap_kdims)
91
+ # bench.report.append(res.describe_sweep())
92
+ # bench.report.append(res.to_optuna_plots())
93
+ # bench.report.append(res.get_best_holomap())
94
+ # bench.report.append(res.to_curve(), "Slider view")
95
+ # bench.report.append(res.to_holomap())
96
+
97
+ # bench.report.append(res.to_holomap().layout())
98
+ return bench
99
+
100
+
101
+ if __name__ == "__main__":
102
+ bench_run = bch.BenchRunner("bench_runner_test")
103
+ bench_run.add_run(example_holosweep)
104
+ bench_run.run(level=3, 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(run_cfg.debug)
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,82 @@
1
+ import bencher as bch
2
+ import numpy as np
3
+ import math
4
+ import holoviews as hv
5
+ import matplotlib.pyplot as plt
6
+
7
+
8
+ def polygon_points(radius: float, sides: int):
9
+ points = []
10
+ for ang in np.linspace(0, math.pi * 2, sides + 1):
11
+ points.append(([math.sin(ang) * radius, math.cos(ang) * radius]))
12
+ return points
13
+
14
+
15
+ class BenchPolygons(bch.ParametrizedSweep):
16
+ sides = bch.IntSweep(default=3, bounds=(3, 5))
17
+ radius = bch.FloatSweep(default=1, bounds=(1, 2))
18
+ linewidth = bch.FloatSweep(default=1, bounds=(1, 10))
19
+ linestyle = bch.StringSweep(["solid", "dashed", "dotted"])
20
+ color = bch.StringSweep(["red", "green", "blue"])
21
+ polygon = bch.ResultImage()
22
+ hmap = bch.ResultHmap()
23
+
24
+ def __call__(self, **kwargs):
25
+ self.update_params_from_kwargs(**kwargs)
26
+ points = polygon_points(self.radius, self.sides)
27
+ self.hmap = hv.Curve(points)
28
+ self.polygon = self.points_to_polygon_png(points, bch.gen_image_path("polygon"))
29
+ return super().__call__()
30
+
31
+ def points_to_polygon_png(self, points: list[float], filename: str):
32
+ """Draw a closed polygon and save to png"""
33
+ fig = plt.figure(frameon=False)
34
+ ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0], frameon=False)
35
+ ax.set_axis_off()
36
+ ax.plot(
37
+ [p[0] for p in points],
38
+ [p[1] for p in points],
39
+ linewidth=self.linewidth,
40
+ linestyle=self.linestyle,
41
+ color=self.color,
42
+ )
43
+ ax.set_aspect("equal")
44
+ fig.add_axes(ax)
45
+ fig.savefig(filename, dpi=50)
46
+ return filename
47
+
48
+
49
+ def example_image(
50
+ run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
51
+ ) -> bch.Bench:
52
+ bench = bch.Bench("polygons", BenchPolygons(), run_cfg=run_cfg, report=report)
53
+
54
+ for s in [
55
+ [BenchPolygons.param.sides],
56
+ [BenchPolygons.param.sides, BenchPolygons.param.linewidth],
57
+ [BenchPolygons.param.sides, BenchPolygons.param.linewidth, BenchPolygons.param.linestyle],
58
+ [
59
+ BenchPolygons.param.sides,
60
+ BenchPolygons.param.linewidth,
61
+ BenchPolygons.param.linestyle,
62
+ BenchPolygons.param.color,
63
+ ],
64
+ [
65
+ BenchPolygons.param.sides,
66
+ BenchPolygons.param.linewidth,
67
+ BenchPolygons.param.linestyle,
68
+ BenchPolygons.param.color,
69
+ BenchPolygons.param.radius,
70
+ ],
71
+ ]:
72
+ bench.plot_sweep(
73
+ f"Polygons Sweeping {len(s)} Parameters",
74
+ input_vars=s,
75
+ result_vars=[BenchPolygons.param.polygon],
76
+ )
77
+
78
+ return bench
79
+
80
+
81
+ if __name__ == "__main__":
82
+ example_image(bch.BenchRunCfg(level=2)).report.show()