holobench 1.3.5__py3-none-any.whl → 1.22.2__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 (77) hide show
  1. bencher/__init__.py +3 -0
  2. bencher/bench_cfg.py +29 -33
  3. bencher/bench_plot_server.py +5 -1
  4. bencher/bench_report.py +14 -14
  5. bencher/bench_runner.py +2 -1
  6. bencher/bencher.py +77 -52
  7. bencher/class_enum.py +52 -0
  8. bencher/job.py +6 -4
  9. bencher/optuna_conversions.py +1 -1
  10. bencher/utils.py +42 -4
  11. bencher/video_writer.py +101 -10
  12. holobench-1.22.2.data/data/share/bencher/package.xml +33 -0
  13. holobench-1.22.2.dist-info/LICENSE +21 -0
  14. {holobench-1.3.5.dist-info → holobench-1.22.2.dist-info}/METADATA +39 -31
  15. holobench-1.22.2.dist-info/RECORD +20 -0
  16. {holobench-1.3.5.dist-info → holobench-1.22.2.dist-info}/WHEEL +2 -1
  17. holobench-1.22.2.dist-info/top_level.txt +1 -0
  18. bencher/example/benchmark_data.py +0 -200
  19. bencher/example/example_all.py +0 -45
  20. bencher/example/example_categorical.py +0 -99
  21. bencher/example/example_custom_sweep.py +0 -59
  22. bencher/example/example_docs.py +0 -34
  23. bencher/example/example_float3D.py +0 -101
  24. bencher/example/example_float_cat.py +0 -98
  25. bencher/example/example_floats.py +0 -89
  26. bencher/example/example_floats2D.py +0 -93
  27. bencher/example/example_holosweep.py +0 -104
  28. bencher/example/example_holosweep_objects.py +0 -111
  29. bencher/example/example_holosweep_tap.py +0 -144
  30. bencher/example/example_image.py +0 -82
  31. bencher/example/example_levels.py +0 -181
  32. bencher/example/example_pareto.py +0 -53
  33. bencher/example/example_sample_cache.py +0 -85
  34. bencher/example/example_sample_cache_context.py +0 -116
  35. bencher/example/example_simple.py +0 -134
  36. bencher/example/example_simple_bool.py +0 -34
  37. bencher/example/example_simple_cat.py +0 -47
  38. bencher/example/example_simple_float.py +0 -38
  39. bencher/example/example_strings.py +0 -46
  40. bencher/example/example_time_event.py +0 -62
  41. bencher/example/example_video.py +0 -124
  42. bencher/example/example_workflow.py +0 -189
  43. bencher/example/experimental/example_bokeh_plotly.py +0 -38
  44. bencher/example/experimental/example_hover_ex.py +0 -45
  45. bencher/example/experimental/example_hvplot_explorer.py +0 -39
  46. bencher/example/experimental/example_interactive.py +0 -75
  47. bencher/example/experimental/example_streamnd.py +0 -49
  48. bencher/example/experimental/example_streams.py +0 -36
  49. bencher/example/experimental/example_template.py +0 -40
  50. bencher/example/experimental/example_updates.py +0 -84
  51. bencher/example/experimental/example_vector.py +0 -84
  52. bencher/example/meta/example_meta.py +0 -171
  53. bencher/example/meta/example_meta_cat.py +0 -25
  54. bencher/example/meta/example_meta_float.py +0 -23
  55. bencher/example/meta/example_meta_levels.py +0 -26
  56. bencher/example/optuna/example_optuna.py +0 -78
  57. bencher/example/shelved/example_float2D_scatter.py +0 -109
  58. bencher/example/shelved/example_float3D_cone.py +0 -96
  59. bencher/example/shelved/example_kwargs.py +0 -63
  60. bencher/plotting/__init__.py +0 -0
  61. bencher/plotting/plot_filter.py +0 -110
  62. bencher/plotting/plt_cnt_cfg.py +0 -74
  63. bencher/results/__init__.py +0 -0
  64. bencher/results/bench_result.py +0 -80
  65. bencher/results/bench_result_base.py +0 -405
  66. bencher/results/float_formatter.py +0 -44
  67. bencher/results/holoview_result.py +0 -592
  68. bencher/results/optuna_result.py +0 -354
  69. bencher/results/panel_result.py +0 -113
  70. bencher/results/plotly_result.py +0 -65
  71. bencher/variables/inputs.py +0 -193
  72. bencher/variables/parametrised_sweep.py +0 -206
  73. bencher/variables/results.py +0 -176
  74. bencher/variables/sweep_base.py +0 -167
  75. bencher/variables/time.py +0 -74
  76. holobench-1.3.5.dist-info/RECORD +0 -74
  77. /bencher/example/__init__.py → /holobench-1.22.2.data/data/share/ament_index/resource_index/packages/bencher +0 -0
bencher/utils.py CHANGED
@@ -8,7 +8,8 @@ from colorsys import hsv_to_rgb
8
8
  from pathlib import Path
9
9
  from uuid import uuid4
10
10
  from functools import partial
11
- from typing import Callable, Any
11
+ from typing import Callable, Any, List
12
+ import param
12
13
 
13
14
 
14
15
  def hmap_canonical_input(dic: dict) -> tuple:
@@ -60,6 +61,9 @@ def get_nearest_coords(dataset: xr.Dataset, collapse_list=False, **kwargs) -> di
60
61
  def get_nearest_coords1D(val: Any, coords) -> Any:
61
62
  if isinstance(val, (int, float)):
62
63
  return min(coords, key=lambda x_: abs(x_ - val))
64
+ for i in coords:
65
+ if val == i:
66
+ return i
63
67
  return val
64
68
 
65
69
 
@@ -94,6 +98,19 @@ def un_camel(camel: str) -> str:
94
98
  return capitalise_words(re.sub("([a-z])([A-Z])", r"\g<1> \g<2>", camel.replace("_", " ")))
95
99
 
96
100
 
101
+ def tabs_in_markdown(regular_str: str, spaces: int = 2) -> str:
102
+ """Given a string with tabs in the form \t convert the to &ensp; which is a double space in markdown
103
+
104
+ Args:
105
+ regular_str (str): A string with tabs in it
106
+ spaces (int): the number of spaces per tab
107
+
108
+ Returns:
109
+ str: A string with sets of &nbsp; to represent the tabs in markdown
110
+ """
111
+ return regular_str.replace("\t", "".join(["&nbsp;"] * spaces))
112
+
113
+
97
114
  def int_to_col(int_val, sat=0.5, val=0.95, alpha=-1) -> tuple[float, float, float]:
98
115
  """Uses the golden angle to generate colors programmatically with minimum overlap between colors.
99
116
  https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
@@ -125,17 +142,17 @@ def color_tuple_to_css(color: tuple[float, float, float]) -> str:
125
142
  return f"rgb{(color[0] * 255, color[1] * 255, color[2] * 255)}"
126
143
 
127
144
 
128
- def gen_path(filename, folder, suffix):
145
+ def gen_path(filename, folder="generic", suffix=".dat"):
129
146
  path = Path(f"cachedir/{folder}/{filename}/")
130
147
  path.mkdir(parents=True, exist_ok=True)
131
148
  return f"{path.absolute().as_posix()}/{filename}_{uuid4()}{suffix}"
132
149
 
133
150
 
134
- def gen_video_path(video_name: str, extension: str = ".webm") -> str:
151
+ def gen_video_path(video_name: str = "vid", extension: str = ".webm") -> str:
135
152
  return gen_path(video_name, "vid", extension)
136
153
 
137
154
 
138
- def gen_image_path(image_name: str, filetype=".png") -> str:
155
+ def gen_image_path(image_name: str = "img", filetype=".png") -> str:
139
156
  return gen_path(image_name, "img", filetype)
140
157
 
141
158
 
@@ -146,3 +163,24 @@ def callable_name(any_callable: Callable[..., Any]) -> str:
146
163
  return any_callable.__name__
147
164
  except AttributeError:
148
165
  return str(any_callable)
166
+
167
+
168
+ def listify(obj) -> list:
169
+ """Take an object and turn it into a list if its not already a list. However if the object is none, don't turn it into a list"""
170
+ if obj is None:
171
+ return None
172
+ if isinstance(obj, list):
173
+ return obj
174
+ if isinstance(obj, tuple):
175
+ return list(obj)
176
+ return [obj]
177
+
178
+
179
+ def get_name(var):
180
+ if isinstance(var, param.Parameter):
181
+ return var.name
182
+ return var
183
+
184
+
185
+ def params_to_str(param_list: List[param.Parameter]):
186
+ return [get_name(i) for i in param_list]
bencher/video_writer.py CHANGED
@@ -1,26 +1,117 @@
1
- from bencher import gen_video_path, gen_image_path
2
- from PIL import Image
3
1
  import numpy as np
2
+ import moviepy.video.io.ImageSequenceClip
3
+ from pathlib import Path
4
+ from .utils import gen_video_path, gen_image_path
5
+
6
+ import moviepy
7
+ from moviepy.editor import (
8
+ VideoFileClip,
9
+ ImageClip,
10
+ ImageSequenceClip,
11
+ clips_array,
12
+ concatenate_videoclips,
13
+ )
14
+ from PIL import Image, ImageDraw
4
15
 
5
16
 
6
17
  class VideoWriter:
7
18
  def __init__(self, filename: str = "vid") -> None:
8
19
  self.images = []
20
+ self.image_files = []
21
+ self.video_files = []
9
22
  self.filename = gen_video_path(filename)
10
23
 
11
24
  def append(self, img):
12
25
  self.images.append(img)
13
26
 
14
- def write(self, bitrate: int = 1500) -> str:
15
- import moviepy.video.io.ImageSequenceClip
27
+ def write(self) -> str:
28
+ clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(
29
+ self.images, fps=30, with_mask=False, load_images=True
30
+ )
31
+ self.write_video_raw(clip)
32
+ return self.filename
33
+
34
+ @staticmethod
35
+ def create_label(label, width=None, height=14):
36
+ if width is None:
37
+ width = len(label) * 8
38
+ new_img = Image.new("RGB", (width, height), (255, 255, 255))
39
+ # ImageDraw.Draw(new_img).text((width/2, 0), label, (0, 0, 0),align="center",achor="ms")
40
+ ImageDraw.Draw(new_img).text((width / 2.0, 0), label, (0, 0, 0), anchor="mt", font_size=12)
41
+
42
+ return new_img
43
+
44
+ @staticmethod
45
+ def label_image(path: Path, label, padding=20) -> Path:
46
+ image = Image.open(path)
47
+ new_img = VideoWriter.create_label(label, image.size[0], image.size[1] + padding)
48
+ new_img.paste(image, (0, padding))
49
+ return new_img
50
+
51
+ def append_file(self, filepath, label=None):
52
+ if label is not None:
53
+ path = Path(filepath)
54
+ new_path = path.with_name(path.stem + "_labelled" + path.suffix).as_posix()
55
+ padding = 20
56
+ match path.suffix:
57
+ case ".png" | ".jpg":
58
+ image = Image.open(filepath)
59
+ new_img = self.create_label(label, image.size[0], image.size[1] + padding)
60
+ new_img.paste(image, (0, padding))
61
+ new_img.save(new_path)
62
+ self.image_files.append(new_path)
63
+ case ".webm":
64
+ import warnings
65
+
66
+ video_clip = VideoFileClip(filepath)
67
+ new_img = self.create_label(label, video_clip.w, padding)
68
+
69
+ # Convert PIL image to MoviePy clip
70
+ label_clip = ImageClip(np.array(new_img), duration=video_clip.duration)
71
+
72
+ labeled_video_clip = clips_array([[label_clip], [video_clip]])
73
+
74
+ # otherwise ffmpeg complains that the file is not getting read. We don't need the file just the size
75
+ with warnings.catch_warnings():
76
+ warnings.simplefilter(action="ignore")
77
+ labeled_video_clip.write_videofile(new_path, remove_temp=True, logger=None)
78
+ self.video_files.append(new_path)
79
+ else:
80
+ self.image_files.append(filepath)
81
+
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)
84
+ if isinstance(images, list) and len(images) > 0:
85
+ if frame_time is None:
86
+ fps = len(images) / target_duration
87
+ fps = max(fps, 1) # never slower that 1 seconds per frame
88
+ fps = min(fps, 30)
89
+ else:
90
+ fps = 1.0 / frame_time
91
+ return ImageSequenceClip(images, fps=fps, with_mask=False)
92
+ return None
16
93
 
17
- # todo
18
- # if len(self.images[0.shape) == 2:
19
- # for i in range(len(self.images)):
20
- # self.images[i] = np.expand_dims(self.images[i], 2)
94
+ def write_png(self, **kwargs):
95
+ clip = None
96
+ if len(self.image_files) > 0:
97
+ clip = self.to_images_sequence(self.image_files, **kwargs)
98
+ if len(self.video_files) > 0:
99
+ clip = concatenate_videoclips([VideoFileClip(f) for f in self.video_files])
100
+ if clip is not None:
101
+ clip.write_videofile(self.filename)
102
+ return self.filename
103
+ return None
21
104
 
22
- clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(self.images, fps=30)
23
- clip.write_videofile(self.filename, bitrate=f"{bitrate}k", logger=None)
105
+ def write_video_raw(self, video_clip: moviepy.video.VideoClip, fps: int = 30) -> str:
106
+ video_clip.write_videofile(
107
+ self.filename,
108
+ codec="libvpx",
109
+ audio=False,
110
+ bitrate="0",
111
+ fps=fps,
112
+ ffmpeg_params=["-crf", "34"],
113
+ )
114
+ video_clip.close()
24
115
  return self.filename
25
116
 
26
117
 
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0"?>
2
+ <package format="3">
3
+ <name>bencher</name>
4
+ <version>0.1.0</version>
5
+ <description>A package for benchmarking the performance of arbitrary functions</description>
6
+ <maintainer email="austin.gregg-smith@dyson.com">Austin Gregg-Smith</maintainer>
7
+ <license>MIT</license>
8
+
9
+ <depend>python3-diskcache</depend>
10
+
11
+ <depend>python3-pandas</depend>
12
+ <depend>python3-seaborn</depend>
13
+ <depend>python3-matplotlib</depend>
14
+ <depend>python3-numpy</depend>
15
+ <depend>python3-pytest</depend>
16
+ <depend>python3-hypothesis</depend>
17
+ <depend>xarray</depend>
18
+ <depend>python3-zarr</depend>
19
+ <depend>python3-param</depend>
20
+ <depend>python3-panel</depend>
21
+ <depend>python3-hvplot</depend>
22
+ <depend>python3-optuna</depend>
23
+ <depend>python3-plotly</depend>
24
+
25
+ <!-- TO REMOVE WHEN WE UPGRADE TO PYTHON 3.11, This is in the standard library for python>=3.11 -->
26
+ <depend>strenum</depend>
27
+
28
+ <test_depend>python3-pytest-cov</test_depend>
29
+
30
+ <export>
31
+ <build_type>ament_python</build_type>
32
+ </export>
33
+ </package>
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Dyson AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,37 +1,38 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: holobench
3
- Version: 1.3.5
3
+ Version: 1.22.2
4
4
  Summary: A package for benchmarking the performance of arbitrary functions
5
5
  Author-email: Austin Gregg-Smith <blooop@gmail.com>
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- Requires-Dist: holoviews>=1.15,<=1.18.1
9
- Requires-Dist: numpy>=1.0,<=1.26.2
10
- Requires-Dist: param>=1.13.0,<=2.0.1
11
- Requires-Dist: hvplot>=0.8,<=0.9.1
12
- Requires-Dist: matplotlib>=3.6.3,<=3.8.2
13
- Requires-Dist: panel>=1.3.6,<=1.3.6
14
- Requires-Dist: diskcache>=5.6,<=5.6.3
15
- Requires-Dist: optuna>=3.2,<=3.5.0
16
- Requires-Dist: xarray>=2023.7,<=2023.12.0
17
- Requires-Dist: plotly>=5.15,<=5.18.0
18
- Requires-Dist: sortedcontainers>=2.4,<=2.4
19
- Requires-Dist: pandas>=2.0,<=2.1.4
20
- Requires-Dist: strenum>=0.4.0,<=0.4.15
21
- Requires-Dist: scikit-learn>=1.2,<=1.3.2
22
- Requires-Dist: str2bool>=1.1,<=1.1
23
- Requires-Dist: scoop>=0.7.0,<=0.7.2.0
24
- Requires-Dist: moviepy>=1.0.3,<=1.0.3
25
- Requires-Dist: black>=23,<=23.12.1 ; extra == "test"
26
- Requires-Dist: pylint>=2.16,<=3.0.3 ; extra == "test"
27
- Requires-Dist: pytest-cov>=4.1,<=4.1 ; extra == "test"
28
- Requires-Dist: pytest>=7.4,<=7.4.4 ; extra == "test"
29
- Requires-Dist: hypothesis>=6.82,<=6.92.2 ; extra == "test"
30
- Requires-Dist: ruff>=0.0.280,<=0.1.9 ; extra == "test"
31
- Requires-Dist: coverage>=7.2.7,<=7.4.0 ; extra == "test"
6
+ Project-URL: Repository, https://github.com/dyson-ai/bencher
32
7
  Project-URL: Home, https://github.com/dyson-ai/bencher
33
- Project-URL: Source, https://github.com/dyson-ai/bencher
8
+ Project-URL: Documentation, https://bencher.readthedocs.io/en/latest/
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: holoviews <=1.18.3,>=1.15
12
+ Requires-Dist: numpy <=1.26.4,>=1.0
13
+ Requires-Dist: param <=2.1.0,>=1.13.0
14
+ Requires-Dist: hvplot <=0.10.0,>=0.8
15
+ Requires-Dist: matplotlib <=3.9.0,>=3.6.3
16
+ Requires-Dist: panel <=1.4.3,>=1.3.6
17
+ Requires-Dist: diskcache <=5.6.3,>=5.6
18
+ Requires-Dist: optuna <=3.6.1,>=3.2
19
+ Requires-Dist: xarray <=2024.5.0,>=2023.7
20
+ Requires-Dist: plotly <=5.22.0,>=5.15
21
+ Requires-Dist: sortedcontainers <=2.4,>=2.4
22
+ Requires-Dist: pandas <=2.2.2,>=2.0
23
+ Requires-Dist: strenum <=0.4.15,>=0.4.0
24
+ Requires-Dist: scikit-learn <=1.5.0,>=1.2
25
+ Requires-Dist: str2bool <=1.1,>=1.1
26
+ Requires-Dist: scoop <=0.7.2.0,>=0.7.0
27
+ Requires-Dist: moviepy <=1.0.3,>=1.0.3
34
28
  Provides-Extra: test
29
+ Requires-Dist: black <=24.4.2,>=23 ; extra == 'test'
30
+ Requires-Dist: pylint <=3.2.2,>=2.17.7 ; extra == 'test'
31
+ Requires-Dist: pytest-cov <=5.0.0,>=4.1 ; extra == 'test'
32
+ Requires-Dist: pytest <=8.2.1,>=7.4 ; extra == 'test'
33
+ Requires-Dist: hypothesis <=6.102.6,>=6.82 ; extra == 'test'
34
+ Requires-Dist: ruff <=0.4.5,>=0.3 ; extra == 'test'
35
+ Requires-Dist: coverage <=7.5.2,>=7.2.7 ; extra == 'test'
35
36
 
36
37
  # Bencher
37
38
 
@@ -45,14 +46,21 @@ Provides-Extra: test
45
46
  [![PyPI](https://img.shields.io/pypi/v/holobench)](https://pypi.org/project/holobench/)
46
47
  [![GitHub release](https://img.shields.io/github/release/dyson-ai/bencher.svg)](https://GitHub.com/dyson-ai/bencher/releases/)
47
48
  [![License](https://img.shields.io/pypi/l/bencher)](https://opensource.org/license/mit/)
48
- [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11-blue)](https://www.python.org/downloads/release/python-310/)
49
+ [![Python](https://img.shields.io/badge/python-3.10-blue)](https://www.python.org/downloads/release/python-310/)
50
+ [![Python](https://img.shields.io/badge/python-3.11-blue)](https://www.python.org/downloads/release/python-311/)
51
+ [![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json)](https://pixi.sh)
52
+
53
+ ## Badges
54
+
55
+ ### Pixi Badge
56
+ The Pixi badge indicates that this project is optimized for performance and follows best practices as evaluated by the Pixi tool. For more information, visit [Pixi](https://pixi.sh).
49
57
 
50
58
 
51
59
  ## Intro
52
60
 
53
- Bencher is a tool to make it easy to benchmark the interactions between the input parameters to your algorithm and its resulting performance on a set of metrics.
61
+ Bencher is a tool to make it easy to benchmark the interactions between the input parameters to your algorithm and its resulting performance on a set of metrics. It calculates the [cartesian product](https://en.wikipedia.org/wiki/Cartesian_product) of a set of variables
54
62
 
55
- Parameters for bencher are defined using the param library https://param.holoviz.org/ as a config class with extra metadata that describes the bounds of the search space you want to measure. You must define a benchmarking function that accepts an instance of the config class and return a dictionary with string metric names and float values.
63
+ Parameters for bencher are defined using the [param](https://param.holoviz.org/) library as a config class with extra metadata that describes the bounds of the search space you want to measure. You must define a benchmarking function that accepts an instance of the config class and return a dictionary with string metric names and float values.
56
64
 
57
65
  Parameters are benchmarked by passing in a list N parameters, and an N-Dimensional tensor is returned. You can optionally sample each point multiple times to get back a distribution and also track its value over time. By default the data will be plotted automatically based on the types of parameters you are sampling (e.g, continous, discrete), but you can also pass in a callback to customize plotting.
58
66
 
@@ -0,0 +1,20 @@
1
+ bencher/__init__.py,sha256=G37hQHeemdNYZUaN5BYds5v8AFLzVM1KIAkpUcrk2To,1321
2
+ bencher/bench_cfg.py,sha256=8rvJyeQXalZmYF8Lb-NKb9RFJs0w08k9ogcZSR1rhgs,18413
3
+ bencher/bench_plot_server.py,sha256=D00_SOrHa2IT8zAjwetoNL6tEiHSHvXnbea9iElCLVk,4195
4
+ bencher/bench_report.py,sha256=jh3T_q9KByZDeMPMf0KNJojZukxRzkfaYGeuWQU8MKM,10528
5
+ bencher/bench_runner.py,sha256=F4DN1YSFXnUAGO17tJ6DZDyEu7QBgvTyqn8G_iCd36c,6165
6
+ bencher/bencher.py,sha256=SmdjwFEdjNkPTVeoG6oXLRM8LOobZLVN90LSAsHCS5E,33299
7
+ bencher/caching.py,sha256=AusaNrzGGlj5m6zcwcqnTn55Mam2mQdF--oqelO806M,1627
8
+ bencher/class_enum.py,sha256=kYHW9qKkKcNdwaXizZL-fTptS_DUEGv4c88yCehk3gc,1492
9
+ bencher/job.py,sha256=swa0VwrZf41v7qNjreVDIYUU6r_dfuLipPZbg_w5x7c,6089
10
+ bencher/optuna_conversions.py,sha256=DAa1DBXJ5EvTGiPyzuDTovQSjKVpMZ2sdwEXThlXJVU,5288
11
+ bencher/utils.py,sha256=MXoJxtpBOf82-iiZBdWBSz6U0AqoUImQK1rXlmwWzF4,6125
12
+ bencher/video_writer.py,sha256=v0yXr7PV0rYWTWqVWBZkXFD3N_ExrZHHHkbEXcXK5bc,4512
13
+ bencher/worker_job.py,sha256=FREi0yWQACFmH86R1j-LH72tALEFkKhLDmmoGQY9Jh4,1571
14
+ holobench-1.22.2.data/data/share/ament_index/resource_index/packages/bencher,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ holobench-1.22.2.data/data/share/bencher/package.xml,sha256=HxWM9qIEiLbE60tG0aKsS7q3UaSKDyCMD4-1nYw8vOs,1045
16
+ holobench-1.22.2.dist-info/LICENSE,sha256=dSHXTdRY4Y7qGFMv63UksV700iff7iE-p7GGs6Sbnvo,1065
17
+ holobench-1.22.2.dist-info/METADATA,sha256=MVUNJCVjAdZG72Is39V08gCnGUgqZl9iSpPonIbdIzk,5613
18
+ holobench-1.22.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
19
+ holobench-1.22.2.dist-info/top_level.txt,sha256=rkP5-F_W08mOD-25ZPkt0HJsHxedb2EiRcRA7IP6Ceg,8
20
+ holobench-1.22.2.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: flit 3.9.0
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ bencher
@@ -1,200 +0,0 @@
1
- """This file contains an example of how to define benchmarking parameters sweeps. Categorical values are defined as enums and passed to EnumSweep classes, other types of sweeps are defined by their respective classes.
2
-
3
- You can define a subclass which contains an input configuration which can be passed to a function in a type safe way. You can combine the subclass with a higher level class which contains more configuation parameters. This is to help manage the complexity of large configuration/parameter spaces.
4
- """
5
-
6
- import math
7
- import random
8
- from enum import auto
9
-
10
- from strenum import StrEnum
11
-
12
-
13
- from bencher.variables.inputs import IntSweep, FloatSweep, StringSweep, EnumSweep, BoolSweep
14
- from bencher.variables.results import ResultVar, OptDir
15
-
16
- from bencher.variables.parametrised_sweep import ParametrizedSweep
17
-
18
-
19
- class PostprocessFn(StrEnum):
20
- """Apply a postprocessing step to the data"""
21
-
22
- absolute = auto() # return the abs of the output data
23
- negate = auto() # return the negative of the output data
24
-
25
-
26
- class NoiseDistribution(StrEnum):
27
- """A categorical variable describing the types of random noise"""
28
-
29
- uniform = auto() # uniform random noiase
30
- gaussian = auto() # gaussian noise
31
- lognorm = auto() # lognorm noise
32
-
33
-
34
- class NoiseCfg(ParametrizedSweep):
35
- """A class for storing the parameters for generating various types of noise"""
36
-
37
- noisy = BoolSweep(
38
- default=False, doc="Optionally add random noise to the output of the function"
39
- )
40
-
41
- noise_distribution = EnumSweep(NoiseDistribution, doc=NoiseDistribution.__doc__)
42
-
43
- sigma = FloatSweep(
44
- default=1,
45
- bounds=[0, 10],
46
- doc="The standard deviation of the noise",
47
- units="v",
48
- )
49
-
50
-
51
- def calculate_noise(config: NoiseCfg) -> float:
52
- """Generate a float value based on a noise distribution and scale
53
-
54
- Args:
55
- config (NoiseCfg): see NoiseCfg type
56
-
57
- Returns:
58
- float: a noisy float value
59
- """
60
-
61
- noise = 0.0
62
- if config.noisy:
63
- match config.noise_distribution:
64
- case NoiseDistribution.uniform:
65
- noise = random.uniform(0, config.sigma)
66
- case NoiseDistribution.gaussian:
67
- noise = random.gauss(0, config.sigma)
68
- case NoiseDistribution.lognorm:
69
- noise = random.lognormvariate(0, config.sigma)
70
-
71
- return noise
72
-
73
-
74
- class ExampleBenchCfgIn(NoiseCfg):
75
- """A class for representing a set of configuration options for the example worker. This class inherits from NoiseCfg so it also stores all its values as well."""
76
-
77
- theta = FloatSweep(default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=30)
78
- offset = FloatSweep(default=0, bounds=[0, 0.3], doc="dc offset", units="v", samples=30)
79
- postprocess_fn = EnumSweep(PostprocessFn)
80
-
81
-
82
- class ExampleBenchCfgOut(ParametrizedSweep):
83
- out_sin = ResultVar(units="v", direction=OptDir.minimize, doc="sin of theta with some noise")
84
- out_cos = ResultVar(units="v", direction=OptDir.minimize, doc="cos of theta with some noise")
85
- out_bool = ResultVar(units="%", doc="sin > 0.5")
86
-
87
-
88
- def negate_fn(fn_input: float):
89
- """returns the negative of the input
90
-
91
- Args:
92
- fn_input (float): any float value
93
-
94
- Returns:
95
- float: negative of the input
96
- """
97
- return -fn_input
98
-
99
-
100
- def bench_function(cfg: ExampleBenchCfgIn) -> ExampleBenchCfgOut:
101
- """Takes an ExampleBenchCfgIn and returns a ExampleBenchCfgOut output"""
102
- out = ExampleBenchCfgOut()
103
- noise = calculate_noise(cfg)
104
-
105
- postprocess_fn = abs if cfg.postprocess_fn == PostprocessFn.absolute else negate_fn
106
-
107
- out.out_sin = postprocess_fn(cfg.offset + math.sin(cfg.theta) + noise)
108
- out.out_cos = postprocess_fn(cfg.offset + math.cos(cfg.theta) + noise)
109
-
110
- out.out_bool = out.out_sin > 0.5
111
- return out
112
-
113
-
114
- class ExampleBenchCfg(ParametrizedSweep):
115
- theta = FloatSweep(default=0, bounds=[0, math.pi], doc="Input angle", units="rad", samples=30)
116
- offset = FloatSweep(default=0, bounds=[0, 0.3], doc="dc offset", units="v", samples=30)
117
- postprocess_fn = EnumSweep(PostprocessFn)
118
-
119
- noisy = BoolSweep(
120
- default=False, doc="Optionally add random noise to the output of the function"
121
- )
122
- noise_distribution = EnumSweep(NoiseDistribution, doc=NoiseDistribution.__doc__)
123
- sigma = FloatSweep(
124
- default=1,
125
- bounds=[0, 10],
126
- doc="The standard deviation of the noise",
127
- units="v",
128
- )
129
-
130
- out_sin = ResultVar(units="v", direction=OptDir.minimize, doc="sin of theta with some noise")
131
- out_cos = ResultVar(units="v", direction=OptDir.minimize, doc="cos of theta with some noise")
132
- out_bool = ResultVar(units="%", doc="sin > 0.5")
133
-
134
- def __call__(self, **kwwargs) -> dict:
135
- self.update_params_from_kwargs(**kwwargs)
136
-
137
- noise = self.calculate_noise()
138
- postprocess_fn = abs if self.postprocess_fn == PostprocessFn.absolute else negate_fn
139
-
140
- self.out_sin = postprocess_fn(self.offset + math.sin(self.theta) + noise)
141
- self.out_cos = postprocess_fn(self.offset + math.cos(self.theta) + noise)
142
- self.out_bool = self.out_sin > 0.5
143
- return self.get_results_values_as_dict()
144
-
145
- def calculate_noise(self):
146
- noise = 0.0
147
- if self.noisy:
148
- match self.noise_distribution:
149
- case NoiseDistribution.uniform:
150
- noise = random.uniform(0, self.sigma)
151
- case NoiseDistribution.gaussian:
152
- noise = random.gauss(0, self.sigma)
153
- case NoiseDistribution.lognorm:
154
- noise = random.lognormvariate(0, self.sigma)
155
-
156
- return noise
157
-
158
-
159
- def call(**kwargs) -> dict:
160
- return ExampleBenchCfg().__call__(**kwargs)
161
-
162
-
163
- class AllSweepVars(ParametrizedSweep):
164
- """A class containing all the sweep types, This class is used for unit testing how the configuration classes are serialised and hashed"""
165
-
166
- var_float = FloatSweep(default=5, bounds=(0, 10), units="m/s")
167
- var_int = IntSweep(default=3, bounds=[0, 4])
168
- var_int_big = IntSweep(default=0, bounds=[0, 100], samples=3)
169
- var_bool = BoolSweep()
170
- var_string = StringSweep(["string1", "string2"])
171
- var_enum = EnumSweep(PostprocessFn)
172
-
173
- result = ResultVar()
174
-
175
- def __call__(self, **kwargs) -> dict:
176
- self.update_params_from_kwargs(**kwargs)
177
- self.result = self.var_float + self.var_int
178
- return self.get_results_values_as_dict()
179
-
180
-
181
- class SimpleBenchClass(ParametrizedSweep):
182
- var1 = IntSweep(default=0, bounds=[0, 2])
183
-
184
- result = ResultVar()
185
-
186
- def __call__(self, **kwargs) -> dict:
187
- self.update_params_from_kwargs(**kwargs)
188
- self.result = self.var1
189
- return self.get_results_values_as_dict()
190
-
191
-
192
- class SimpleBenchClassFloat(ParametrizedSweep):
193
- var1 = FloatSweep(bounds=[0, 100])
194
-
195
- result = ResultVar()
196
-
197
- def __call__(self, **kwargs) -> dict:
198
- self.update_params_from_kwargs(**kwargs)
199
- self.result = self.var1
200
- return self.get_results_values_as_dict()
@@ -1,45 +0,0 @@
1
- import bencher as bch
2
-
3
- from bencher.example.example_categorical import example_categorical
4
- from bencher.example.example_floats import example_floats
5
- from bencher.example.example_floats2D import example_floats2D
6
- from bencher.example.example_pareto import example_pareto
7
- from bencher.example.example_simple_cat import example_1D_cat
8
- from bencher.example.example_simple_float import example_1D_float
9
- from bencher.example.example_float_cat import example_float_cat
10
- from bencher.example.example_time_event import example_time_event
11
- from bencher.example.example_float3D import example_floats3D
12
-
13
- from bencher.example.example_custom_sweep import example_custom_sweep
14
- from bencher.example.example_holosweep import example_holosweep
15
- from bencher.example.example_holosweep_tap import example_holosweep_tap
16
-
17
- from bencher.example.optuna.example_optuna import optuna_rastrigin
18
- from bencher.example.example_sample_cache import example_sample_cache
19
-
20
- # from bencher.example.example_workflow import example_floats2D_workflow, example_floats3D_workflow
21
-
22
-
23
- if __name__ == "__main__":
24
- run_cfg = bch.BenchRunCfg()
25
- run_cfg.overwrite_sample_cache = True
26
- bench_runner = bch.BenchRunner("bencher_examples", run_cfg=run_cfg)
27
-
28
- bench_runner.add_run(example_categorical)
29
- bench_runner.add_run(example_floats)
30
- bench_runner.add_run(example_floats2D)
31
- bench_runner.add_run(example_floats3D)
32
- bench_runner.add_run(example_1D_cat)
33
- bench_runner.add_run(example_1D_float)
34
- bench_runner.add_run(example_pareto)
35
- bench_runner.add_run(example_float_cat)
36
- bench_runner.add_run(example_time_event)
37
- bench_runner.add_run(example_custom_sweep)
38
- bench_runner.add_run(example_holosweep)
39
- bench_runner.add_run(example_holosweep_tap)
40
- bench_runner.add_run(optuna_rastrigin)
41
- bench_runner.add_run(example_sample_cache)
42
-
43
- # bench_runner.run(level=2, show=True, grouped=True)
44
-
45
- bench_runner.run(level=4, show=True, grouped=True, save=False)