holobench 1.25.1__py3-none-any.whl → 1.26.3__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 (81) hide show
  1. bencher/example/benchmark_data.py +196 -0
  2. bencher/example/example_all.py +45 -0
  3. bencher/example/example_categorical.py +99 -0
  4. bencher/example/example_composable_container.py +106 -0
  5. bencher/example/example_composable_container2.py +160 -0
  6. bencher/example/example_consts.py +39 -0
  7. bencher/example/example_custom_sweep.py +59 -0
  8. bencher/example/example_custom_sweep2.py +42 -0
  9. bencher/example/example_docs.py +34 -0
  10. bencher/example/example_filepath.py +27 -0
  11. bencher/example/example_float3D.py +101 -0
  12. bencher/example/example_float_cat.py +99 -0
  13. bencher/example/example_floats.py +89 -0
  14. bencher/example/example_floats2D.py +93 -0
  15. bencher/example/example_holosweep.py +98 -0
  16. bencher/example/example_holosweep_objects.py +111 -0
  17. bencher/example/example_holosweep_tap.py +144 -0
  18. bencher/example/example_image.py +155 -0
  19. bencher/example/example_levels.py +181 -0
  20. bencher/example/example_levels2.py +37 -0
  21. bencher/example/example_pareto.py +53 -0
  22. bencher/example/example_sample_cache.py +85 -0
  23. bencher/example/example_sample_cache_context.py +116 -0
  24. bencher/example/example_simple.py +134 -0
  25. bencher/example/example_simple_bool.py +35 -0
  26. bencher/example/example_simple_cat.py +48 -0
  27. bencher/example/example_simple_float.py +28 -0
  28. bencher/example/example_simple_float2d.py +29 -0
  29. bencher/example/example_strings.py +47 -0
  30. bencher/example/example_time_event.py +63 -0
  31. bencher/example/example_video.py +118 -0
  32. bencher/example/example_workflow.py +189 -0
  33. bencher/example/experimental/example_bokeh_plotly.py +38 -0
  34. bencher/example/experimental/example_hover_ex.py +45 -0
  35. bencher/example/experimental/example_hvplot_explorer.py +39 -0
  36. bencher/example/experimental/example_interactive.py +75 -0
  37. bencher/example/experimental/example_streamnd.py +49 -0
  38. bencher/example/experimental/example_streams.py +36 -0
  39. bencher/example/experimental/example_template.py +40 -0
  40. bencher/example/experimental/example_updates.py +84 -0
  41. bencher/example/experimental/example_vector.py +84 -0
  42. bencher/example/meta/example_meta.py +171 -0
  43. bencher/example/meta/example_meta_cat.py +25 -0
  44. bencher/example/meta/example_meta_float.py +23 -0
  45. bencher/example/meta/example_meta_levels.py +26 -0
  46. bencher/example/optuna/example_optuna.py +78 -0
  47. bencher/example/shelved/example_float2D_scatter.py +109 -0
  48. bencher/example/shelved/example_float3D_cone.py +96 -0
  49. bencher/example/shelved/example_kwargs.py +63 -0
  50. bencher/plotting/__init__.py +0 -0
  51. bencher/plotting/plot_filter.py +110 -0
  52. bencher/plotting/plt_cnt_cfg.py +75 -0
  53. bencher/results/__init__.py +0 -0
  54. bencher/results/bench_result.py +94 -0
  55. bencher/results/bench_result_base.py +476 -0
  56. bencher/results/composable_container/__init__.py +0 -0
  57. bencher/results/composable_container/composable_container_base.py +73 -0
  58. bencher/results/composable_container/composable_container_panel.py +39 -0
  59. bencher/results/composable_container/composable_container_video.py +184 -0
  60. bencher/results/float_formatter.py +44 -0
  61. bencher/results/holoview_result.py +753 -0
  62. bencher/results/optuna_result.py +354 -0
  63. bencher/results/panel_result.py +41 -0
  64. bencher/results/plotly_result.py +65 -0
  65. bencher/results/video_result.py +38 -0
  66. bencher/results/video_summary.py +222 -0
  67. bencher/variables/__init__.py +0 -0
  68. bencher/variables/inputs.py +202 -0
  69. bencher/variables/parametrised_sweep.py +208 -0
  70. bencher/variables/results.py +214 -0
  71. bencher/variables/sweep_base.py +162 -0
  72. bencher/variables/time.py +92 -0
  73. holobench-1.26.3.data/data/share/ament_index/resource_index/packages/bencher +0 -0
  74. {holobench-1.25.1.dist-info → holobench-1.26.3.dist-info}/METADATA +5 -7
  75. holobench-1.26.3.dist-info/RECORD +93 -0
  76. holobench-1.25.1.dist-info/RECORD +0 -20
  77. /holobench-1.25.1.data/data/share/ament_index/resource_index/packages/bencher → /bencher/example/__init__.py +0 -0
  78. {holobench-1.25.1.data → holobench-1.26.3.data}/data/share/bencher/package.xml +0 -0
  79. {holobench-1.25.1.dist-info → holobench-1.26.3.dist-info}/LICENSE +0 -0
  80. {holobench-1.25.1.dist-info → holobench-1.26.3.dist-info}/WHEEL +0 -0
  81. {holobench-1.25.1.dist-info → holobench-1.26.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,63 @@
1
+ # import math
2
+
3
+ # import bencher as bch
4
+
5
+
6
+ # def bench_function(
7
+ # theta: float = 0,
8
+ # offset: float = 0,
9
+ # scale: float = 1.0,
10
+ # trig_func: str = "sin",
11
+ # **kwargs, # pylint: disable=unused-argument
12
+ # ) -> dict:
13
+ # """All the other examples use classes and parameters to define the inputs and outputs to the function. However it makes the code less flexible when integrating with other systems, so this example shows a more basic interface that accepts and returns dictionaries. The classes still need to be defined however because that is how the sweep and plotting settings are calcuated"""
14
+ # output = {}
15
+
16
+ # if trig_func == "sin":
17
+ # output["voltage"] = offset + math.sin(theta) * scale
18
+ # elif trig_func == "cos":
19
+ # output["voltage"] = offset + math.cos(theta) * scale
20
+
21
+ # return output
22
+
23
+
24
+ # class InputCfg(bch.ParametrizedSweep):
25
+ # """This class is used to define the default values and bounds of the variables to benchmark."""
26
+
27
+ # theta = bch.FloatSweep(
28
+ # default=0.0,
29
+ # bounds=[0.0, 6.0],
30
+ # doc="Input angle to the trig function",
31
+ # units="rad",
32
+ # samples=10,
33
+ # )
34
+
35
+ # offset = bch.FloatSweep(
36
+ # default=0.0,
37
+ # bounds=[0.0, 3.0],
38
+ # doc="Add an offset voltage to the result of the trig function",
39
+ # units="v",
40
+ # samples=5,
41
+ # )
42
+
43
+ # trig_func = bch.StringSweep(["sin", "cos"], doc="Select what trigonometric function use")
44
+
45
+
46
+ # class OutputVoltage(bch.ParametrizedSweep):
47
+ # voltage = bch.ResultVar(units="v", doc="Output voltage")
48
+
49
+
50
+ # if __name__ == "__main__":
51
+ # # pass the objective function you have defined to bencher. The other examples pass the InputCfg type, but this benchmark function accepts a kwargs dictionary so you don't need to pass the inputCfg type.
52
+ # bench = bch.Bench("Bencher_Example_Categorical", bench_function)
53
+
54
+ # # Bencher needs to know the metadata of the variable in order to automatically sweep and plot it, so it is passed by using param's metadata syntax. InputCfg.param.* is how to access the metadata defined in the class description.
55
+ # bench.plot_sweep(
56
+ # input_vars=[InputCfg.param.theta, InputCfg.param.offset],
57
+ # result_vars=[OutputVoltage.param.voltage],
58
+ # title="Example with kwarg inputs and dict output",
59
+ # description=bench_function.__doc__,
60
+ # )
61
+
62
+ # # launch web server and view
63
+ # bench.report.show()
File without changes
@@ -0,0 +1,110 @@
1
+ from __future__ import annotations
2
+ from typing import Optional
3
+ from dataclasses import dataclass
4
+ from bencher.plotting.plt_cnt_cfg import PltCntCfg
5
+ import panel as pn
6
+
7
+
8
+ class VarRange:
9
+ """A VarRange represents the bounded and unbounded ranges of integers. This class is used to define filters for various variable types. For example by defining cat_var = VarRange(0,0), calling matches(0) will return true, but any other integer will not match. You can also have unbounded ranges for example VarRange(2,None) will match to 2,3,4... up to infinity. for By default the lower and upper bounds are set to -1 so so that no matter what value is passsed to matches() will return false. Matches only takes 0 and positive integers."""
10
+
11
+ def __init__(self, lower_bound: int = 0, upper_bound: int = -1) -> None:
12
+ """
13
+ Args:
14
+ lower_bound (int, optional): The smallest acceptable value to matches(). Passing None will result in a lower bound of 0 (as matches only accepts positive integers). Defaults to 0.
15
+ upper_bound (int, optional): The largest acceptable value to matches(). Passing None will result in no upper bound. Defaults to -1 which results in a range with no matches.
16
+ """
17
+ self.lower_bound = lower_bound
18
+ self.upper_bound = upper_bound
19
+
20
+ def matches(self, val: int) -> bool:
21
+ """Checks that a value is within the variable range. lower_bound and upper_bound are inclusive (lower_bound<=val<=upper_bound )
22
+
23
+ Args:
24
+ val (int): A positive integer representing a number of items
25
+
26
+ Returns:
27
+ bool: True if the items is within the range, False otherwise.
28
+
29
+ Raises:
30
+ ValueError: If val < 0
31
+ """
32
+ if val < 0:
33
+ raise ValueError("val must be >= 0")
34
+ if self.lower_bound is not None:
35
+ lower_match = val >= self.lower_bound
36
+ else:
37
+ lower_match = True
38
+
39
+ if self.upper_bound is not None:
40
+ upper_match = val <= self.upper_bound
41
+ else:
42
+ upper_match = True
43
+
44
+ return lower_match and upper_match
45
+
46
+ def matches_info(self, val, name):
47
+ match = self.matches(val)
48
+ info = f"{name}\t{match}\t{self.lower_bound}>= {val} <={self.upper_bound}"
49
+ return match, info
50
+
51
+ def __str__(self) -> str:
52
+ return f"VarRange(lower_bound={self.lower_bound}, upper_bound={self.upper_bound})"
53
+
54
+
55
+ @dataclass
56
+ class PlotFilter:
57
+ """A class for representing the types of results a plot is able to represent."""
58
+
59
+ float_range: VarRange = VarRange()
60
+ cat_range: VarRange = VarRange()
61
+ vector_len: VarRange = VarRange(1, 1)
62
+ result_vars: VarRange = VarRange(1, 1)
63
+ panel_range: VarRange = VarRange(0, 0)
64
+ repeats_range: VarRange = VarRange(1, None)
65
+ input_range: VarRange = VarRange(1, None)
66
+
67
+ def matches_result(self, plt_cnt_cfg: PltCntCfg, plot_name: str) -> PlotMatchesResult:
68
+ """Checks if the result data signature matches the type of data the plot is able to display."""
69
+ return PlotMatchesResult(self, plt_cnt_cfg, plot_name)
70
+
71
+
72
+ # @dataclass
73
+ class PlotMatchesResult:
74
+ """Stores information about which properites match the requirements of a particular plotter"""
75
+
76
+ def __init__(self, plot_filter: PlotFilter, plt_cnt_cfg: PltCntCfg, plot_name: str):
77
+ match_info = []
78
+ matches = []
79
+
80
+ match_candidates = [
81
+ (plot_filter.float_range, plt_cnt_cfg.float_cnt, "float"),
82
+ (plot_filter.cat_range, plt_cnt_cfg.cat_cnt, "cat"),
83
+ (plot_filter.vector_len, plt_cnt_cfg.vector_len, "vec"),
84
+ (plot_filter.result_vars, plt_cnt_cfg.result_vars, "results"),
85
+ (plot_filter.panel_range, plt_cnt_cfg.panel_cnt, "panels"),
86
+ (plot_filter.repeats_range, plt_cnt_cfg.repeats, "repeats"),
87
+ (plot_filter.input_range, plt_cnt_cfg.inputs_cnt, "inputs"),
88
+ ]
89
+
90
+ for m, cnt, name in match_candidates:
91
+ match, info = m.matches_info(cnt, name)
92
+ matches.append(match)
93
+ if not match:
94
+ match_info.append(info)
95
+
96
+ self.overall = all(matches)
97
+
98
+ match_info.insert(0, f"plot {plot_name} matches: {self.overall}")
99
+ self.matches_info = "\n".join(match_info).strip()
100
+ self.plt_cnt_cfg = plt_cnt_cfg
101
+
102
+ if self.plt_cnt_cfg.print_debug:
103
+ print(f"checking {plot_name} result: {self.overall}")
104
+ if not self.overall:
105
+ print(self.matches_info)
106
+
107
+ def to_panel(self, **kwargs) -> Optional[pn.pane.Markdown]:
108
+ if self.plt_cnt_cfg.print_debug:
109
+ return pn.pane.Markdown(self.matches_info, **kwargs)
110
+ return None
@@ -0,0 +1,75 @@
1
+ from __future__ import annotations
2
+ import param
3
+ from bencher.bench_cfg import BenchCfg
4
+ from bencher.variables.results import PANEL_TYPES
5
+
6
+ from bencher.variables.inputs import IntSweep, FloatSweep, BoolSweep, EnumSweep, StringSweep
7
+ from bencher.variables.time import TimeSnapshot
8
+
9
+
10
+ class PltCntCfg(param.Parameterized):
11
+ """Plot Count Config"""
12
+
13
+ float_vars = param.List(doc="A list of float vars in order of plotting, x then y")
14
+ float_cnt = param.Integer(0, doc="The number of float variables to plot")
15
+ cat_vars = param.List(doc="A list of categorical values to plot in order hue,row,col")
16
+ cat_cnt = param.Integer(0, doc="The number of cat variables")
17
+ vector_len = param.Integer(1, doc="The vector length of the return variable , scalars = len 1")
18
+ result_vars = param.Integer(1, doc="The number result variables to plot") # todo remove
19
+ panel_vars = param.List(doc="A list of panel results")
20
+ panel_cnt = param.Integer(0, doc="Number of results reprented as panel panes")
21
+ repeats = param.Integer(0, doc="The number of repeat samples")
22
+ inputs_cnt = param.Integer(0, doc="The number of repeat samples")
23
+
24
+ print_debug = param.Boolean(
25
+ True, doc="Print debug information about why a filter matches this config or not"
26
+ )
27
+
28
+ @staticmethod
29
+ def generate_plt_cnt_cfg(
30
+ bench_cfg: BenchCfg,
31
+ ) -> PltCntCfg:
32
+ """Given a BenchCfg work out how many float and cat variables there are and store in a PltCntCfg class
33
+
34
+ Args:
35
+ bench_cfg (BenchCfg): See BenchCfg definition
36
+
37
+ Raises:
38
+ ValueError: If no plotting procedure could be automatically detected
39
+
40
+ Returns:
41
+ PltCntCfg: see PltCntCfg definition
42
+ """
43
+ plt_cnt_cfg = PltCntCfg()
44
+ # plt_cnt_cfg.float_vars = deepcopy(bench_cfg.iv_time)
45
+
46
+ plt_cnt_cfg.cat_vars = []
47
+ plt_cnt_cfg.float_vars = []
48
+
49
+ for iv in bench_cfg.input_vars:
50
+ type_allocated = False
51
+ if isinstance(iv, (IntSweep, FloatSweep, TimeSnapshot)):
52
+ # if "IntSweep" in typestr or "FloatSweep" in typestr:
53
+ plt_cnt_cfg.float_vars.append(iv)
54
+ type_allocated = True
55
+ if isinstance(iv, (EnumSweep, BoolSweep, StringSweep)):
56
+ # if "EnumSweep" in typestr or "BoolSweep" in typestr or "StringSweep" in typestr:
57
+ plt_cnt_cfg.cat_vars.append(iv)
58
+ type_allocated = True
59
+
60
+ if not type_allocated:
61
+ raise ValueError(f"No rule for type {type(iv)}")
62
+
63
+ for rv in bench_cfg.result_vars:
64
+ if isinstance(rv, PANEL_TYPES):
65
+ plt_cnt_cfg.panel_vars.append(rv)
66
+
67
+ plt_cnt_cfg.float_cnt = len(plt_cnt_cfg.float_vars)
68
+ plt_cnt_cfg.cat_cnt = len(plt_cnt_cfg.cat_vars)
69
+ plt_cnt_cfg.panel_cnt = len(plt_cnt_cfg.panel_vars)
70
+ plt_cnt_cfg.repeats = bench_cfg.repeats
71
+ plt_cnt_cfg.inputs_cnt = len(bench_cfg.input_vars)
72
+ return plt_cnt_cfg
73
+
74
+ def __str__(self):
75
+ return f"float_cnt: {self.float_cnt}\ncat_cnt: {self.cat_cnt} \npanel_cnt: {self.panel_cnt}\nvector_len: {self.vector_len}"
File without changes
@@ -0,0 +1,94 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+ import panel as pn
4
+
5
+ from bencher.results.bench_result_base import EmptyContainer
6
+ from bencher.results.video_summary import VideoSummaryResult
7
+ from bencher.results.panel_result import PanelResult
8
+ from bencher.results.plotly_result import PlotlyResult
9
+ from bencher.results.holoview_result import HoloviewResult
10
+ from bencher.utils import listify
11
+
12
+
13
+ class BenchResult(PlotlyResult, HoloviewResult, VideoSummaryResult):
14
+ """Contains the results of the benchmark and has methods to cast the results to various datatypes and graphical representations"""
15
+
16
+ def __init__(self, bench_cfg) -> None:
17
+ PlotlyResult.__init__(self, bench_cfg)
18
+ HoloviewResult.__init__(self, bench_cfg)
19
+
20
+ @staticmethod
21
+ def default_plot_callbacks():
22
+ return [
23
+ # VideoSummaryResult.to_video_summary, #quite expensive so not turned on by default
24
+ HoloviewResult.to_bar,
25
+ HoloviewResult.to_scatter_jitter,
26
+ HoloviewResult.to_curve,
27
+ HoloviewResult.to_line,
28
+ HoloviewResult.to_heatmap,
29
+ PlotlyResult.to_volume,
30
+ # PanelResult.to_video,
31
+ PanelResult.to_panes,
32
+ ]
33
+
34
+ @staticmethod
35
+ def plotly_callbacks():
36
+ return [HoloviewResult.to_surface, PlotlyResult.to_volume]
37
+
38
+ def plot(self) -> pn.panel:
39
+ """Plots the benchresult using the plot callbacks defined by the bench run
40
+
41
+ Returns:
42
+ pn.panel: A panel representation of the results
43
+ """
44
+ if self.bench_cfg.plot_callbacks is not None:
45
+ return pn.Column(*[cb(self) for cb in self.bench_cfg.plot_callbacks])
46
+ return None
47
+
48
+ def to_auto(
49
+ self,
50
+ plot_list: List[callable] = None,
51
+ remove_plots: List[callable] = None,
52
+ **kwargs,
53
+ ) -> List[pn.panel]:
54
+ self.plt_cnt_cfg.print_debug = False
55
+ plot_list = listify(plot_list)
56
+ remove_plots = listify(remove_plots)
57
+
58
+ if plot_list is None:
59
+ plot_list = BenchResult.default_plot_callbacks()
60
+ if remove_plots is not None:
61
+ for p in remove_plots:
62
+ plot_list.remove(p)
63
+
64
+ kwargs = self.set_plot_size(**kwargs)
65
+
66
+ row = EmptyContainer(pn.Row())
67
+ for plot_callback in plot_list:
68
+ if self.plt_cnt_cfg.print_debug:
69
+ print(f"checking: {plot_callback.__name__}")
70
+ # the callbacks are passed from the static class definition, so self needs to be passed before the plotting callback can be called
71
+ row.append(plot_callback(self, **kwargs))
72
+
73
+ self.plt_cnt_cfg.print_debug = True
74
+ if len(row.pane) == 0:
75
+ row.append(
76
+ pn.pane.Markdown("No Plotters are able to represent these results", **kwargs)
77
+ )
78
+ return row.pane
79
+
80
+ def to_auto_plots(self, **kwargs) -> pn.panel:
81
+ """Given the dataset result of a benchmark run, automatically dedeuce how to plot the data based on the types of variables that were sampled
82
+
83
+ Args:
84
+ bench_cfg (BenchCfg): Information on how the benchmark was sampled and the resulting data
85
+
86
+ Returns:
87
+ pn.pane: A panel containing plot results
88
+ """
89
+
90
+ plot_cols = pn.Column()
91
+ plot_cols.append(self.to_sweep_summary(name="Plots View"))
92
+ plot_cols.append(self.to_auto(**kwargs))
93
+ plot_cols.append(self.bench_cfg.to_post_description())
94
+ return plot_cols