holobench 1.28.1__py3-none-any.whl → 1.30.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 (40) hide show
  1. bencher/__init__.py +1 -0
  2. bencher/bench_cfg.py +9 -9
  3. bencher/bench_plot_server.py +1 -1
  4. bencher/bench_runner.py +1 -1
  5. bencher/bencher.py +23 -11
  6. bencher/example/benchmark_data.py +1 -1
  7. bencher/example/example_categorical.py +1 -1
  8. bencher/example/example_custom_sweep.py +1 -1
  9. bencher/example/example_custom_sweep2.py +1 -1
  10. bencher/example/example_dataframe.py +47 -0
  11. bencher/example/example_image.py +5 -7
  12. bencher/example/example_image1.py +80 -0
  13. bencher/example/example_levels.py +1 -1
  14. bencher/example/example_levels2.py +1 -1
  15. bencher/example/example_pareto.py +1 -1
  16. bencher/example/example_sample_cache_context.py +2 -2
  17. bencher/example/example_simple.py +5 -5
  18. bencher/example/meta/example_meta.py +1 -1
  19. bencher/example/shelved/example_kwargs.py +1 -1
  20. bencher/plotting/plot_filter.py +2 -2
  21. bencher/plotting/plt_cnt_cfg.py +10 -3
  22. bencher/results/bench_result.py +3 -1
  23. bencher/results/bench_result_base.py +58 -9
  24. bencher/results/composable_container/composable_container_base.py +2 -2
  25. bencher/results/composable_container/composable_container_dataframe.py +52 -0
  26. bencher/results/dataset_result.py +227 -0
  27. bencher/results/optuna_result.py +7 -6
  28. bencher/variables/inputs.py +5 -5
  29. bencher/variables/parametrised_sweep.py +2 -2
  30. bencher/variables/results.py +29 -1
  31. bencher/variables/sweep_base.py +1 -1
  32. bencher/variables/time.py +3 -3
  33. bencher/video_writer.py +1 -1
  34. {holobench-1.28.1.dist-info → holobench-1.30.2.dist-info}/METADATA +72 -39
  35. {holobench-1.28.1.dist-info → holobench-1.30.2.dist-info}/RECORD +38 -36
  36. {holobench-1.28.1.dist-info → holobench-1.30.2.dist-info}/WHEEL +1 -2
  37. holobench-1.28.1.data/data/share/bencher/package.xml +0 -33
  38. holobench-1.28.1.dist-info/top_level.txt +0 -1
  39. {holobench-1.28.1.dist-info → holobench-1.30.2.dist-info/licenses}/LICENSE +0 -0
  40. {holobench-1.28.1.data/data/share/ament_index/resource_index/packages → resource}/bencher +0 -0
@@ -19,9 +19,7 @@ from bencher.variables.results import ResultVar
19
19
  from bencher.plotting.plot_filter import VarRange, PlotFilter
20
20
  from bencher.utils import listify
21
21
 
22
- from bencher.variables.results import (
23
- ResultReference,
24
- )
22
+ from bencher.variables.results import ResultReference, ResultDataSet
25
23
 
26
24
  from bencher.results.composable_container.composable_container_panel import ComposableContainerPanel
27
25
 
@@ -62,7 +60,7 @@ class BenchResultBase(OptunaResult):
62
60
  """Generate a holoviews dataset from the xarray dataset.
63
61
 
64
62
  Args:
65
- reduce (ReduceType, optional): Optionally perform reduce options on the dataset. By default the returned dataset will calculate the mean and standard devation over the "repeat" dimension so that the dataset plays nicely with most of the holoviews plot types. Reduce.Sqeeze is used if there is only 1 repeat and you want the "reduce" variable removed from the dataset. ReduceType.None returns an unaltered dataset. Defaults to ReduceType.AUTO.
63
+ reduce (ReduceType, optional): Optionally perform reduce options on the dataset. By default the returned dataset will calculate the mean and standard deviation over the "repeat" dimension so that the dataset plays nicely with most of the holoviews plot types. Reduce.Sqeeze is used if there is only 1 repeat and you want the "reduce" variable removed from the dataset. ReduceType.None returns an unaltered dataset. Defaults to ReduceType.AUTO.
66
64
 
67
65
  Returns:
68
66
  hv.Dataset: results in the form of a holoviews dataset
@@ -79,7 +77,7 @@ class BenchResultBase(OptunaResult):
79
77
  """Generate a summarised xarray dataset.
80
78
 
81
79
  Args:
82
- reduce (ReduceType, optional): Optionally perform reduce options on the dataset. By default the returned dataset will calculate the mean and standard devation over the "repeat" dimension so that the dataset plays nicely with most of the holoviews plot types. Reduce.Sqeeze is used if there is only 1 repeat and you want the "reduce" variable removed from the dataset. ReduceType.None returns an unaltered dataset. Defaults to ReduceType.AUTO.
80
+ reduce (ReduceType, optional): Optionally perform reduce options on the dataset. By default the returned dataset will calculate the mean and standard deviation over the "repeat" dimension so that the dataset plays nicely with most of the holoviews plot types. Reduce.Sqeeze is used if there is only 1 repeat and you want the "reduce" variable removed from the dataset. ReduceType.None returns an unaltered dataset. Defaults to ReduceType.AUTO.
83
81
 
84
82
  Returns:
85
83
  xr.Dataset: results in the form of an xarray dataset
@@ -89,7 +87,7 @@ class BenchResultBase(OptunaResult):
89
87
 
90
88
  ds_out = self.ds if result_var is None else self.ds[result_var.name]
91
89
 
92
- match (reduce):
90
+ match reduce:
93
91
  case ReduceType.REDUCE:
94
92
  ds_reduce_mean = ds_out.mean(dim="repeat", keep_attrs=True)
95
93
  ds_reduce_std = ds_out.std(dim="repeat", keep_attrs=True)
@@ -149,9 +147,9 @@ class BenchResultBase(OptunaResult):
149
147
  opt_val = result_da.max()
150
148
  else:
151
149
  opt_val = result_da.min()
152
- indicies = result_da.where(result_da == opt_val, drop=True).squeeze()
150
+ indices = result_da.where(result_da == opt_val, drop=True).squeeze()
153
151
  logging.info(f"optimal value of {result_var.name}: {opt_val.values}")
154
- return indicies
152
+ return indices
155
153
 
156
154
  def get_optimal_inputs(
157
155
  self,
@@ -242,6 +240,46 @@ class BenchResultBase(OptunaResult):
242
240
  row.append(plot_callback(rv))
243
241
  return row.get()
244
242
 
243
+ @staticmethod
244
+ def zip_results1D(args): # pragma: no cover
245
+ first_el = [a[0] for a in args]
246
+ out = pn.Column()
247
+ for a in zip(*first_el):
248
+ row = pn.Row()
249
+ row.append(a[0])
250
+ for a1 in range(1, len(a[1])):
251
+ row.append(a[a1][1])
252
+ out.append(row)
253
+ return out
254
+
255
+ @staticmethod
256
+ def zip_results1D1(panel_list): # pragma: no cover
257
+ container_args = {"styles": {}}
258
+ container_args["styles"]["border-bottom"] = f"{2}px solid grey"
259
+ print(panel_list)
260
+ out = pn.Column()
261
+ for a in zip(*panel_list):
262
+ row = pn.Row(**container_args)
263
+ row.append(a[0][0])
264
+ for a1 in range(0, len(a)):
265
+ row.append(a[a1][1])
266
+ out.append(row)
267
+ return out
268
+
269
+ @staticmethod
270
+ def zip_results1D2(panel_list): # pragma: no cover
271
+ if panel_list is not None:
272
+ print(panel_list)
273
+ primary = panel_list[0]
274
+ secondary = panel_list[1:]
275
+ for i in range(len(primary)):
276
+ print(type(primary[i]))
277
+ if isinstance(primary[i], (pn.Column, pn.Row)):
278
+ for j in range(len(secondary)):
279
+ primary[i].append(secondary[j][i][1])
280
+ return primary
281
+ return panel_list
282
+
245
283
  def map_plot_panes(
246
284
  self,
247
285
  plot_callback: callable,
@@ -250,6 +288,7 @@ class BenchResultBase(OptunaResult):
250
288
  result_var: ResultVar = None,
251
289
  result_types=None,
252
290
  pane_collection: pn.pane = None,
291
+ zip_results=False,
253
292
  **kwargs,
254
293
  ) -> Optional[pn.Row]:
255
294
  if hv_dataset is None:
@@ -271,6 +310,9 @@ class BenchResultBase(OptunaResult):
271
310
  target_dimension=target_dimension,
272
311
  )
273
312
  )
313
+
314
+ if zip_results:
315
+ return self.zip_results1D2(row.get())
274
316
  return row.get()
275
317
 
276
318
  def filter(
@@ -405,10 +447,17 @@ class BenchResultBase(OptunaResult):
405
447
  return da_ds.values.squeeze().item()
406
448
  return da.expand_dims(dim).values[0]
407
449
 
408
- def ds_to_container(
450
+ def ds_to_container( # pylint: disable=too-many-return-statements
409
451
  self, dataset: xr.Dataset, result_var: Parameter, container, **kwargs
410
452
  ) -> Any:
411
453
  val = self.zero_dim_da_to_val(dataset[result_var.name])
454
+ if isinstance(result_var, ResultDataSet):
455
+ ref = self.dataset_list[val]
456
+ if ref is not None:
457
+ if container is not None:
458
+ return container(ref.obj)
459
+ return ref.obj
460
+ return None
412
461
  if isinstance(result_var, ResultReference):
413
462
  ref = self.object_index[val]
414
463
  if ref is not None:
@@ -10,7 +10,7 @@ class ComposeType(StrEnum):
10
10
  right = auto() # append the container to the right (creates a row)
11
11
  down = auto() # append the container below (creates a column)
12
12
  sequence = auto() # display the container after (in time)
13
- # overlay = auto() # overlay on top of the current container (alpha blending)
13
+ overlay = auto() # overlay on top of the current container (alpha blending)
14
14
 
15
15
  def flip(self):
16
16
  match self:
@@ -65,7 +65,7 @@ class ComposableContainerBase:
65
65
  self.container.append(obj)
66
66
 
67
67
  def render(self):
68
- """Return a representation of the container that can be composed with other render() results. This function can also be used to defer layout and rending options until all the information about the container content is known. You may need to ovverride this method depending on the container. See composable_container_video as an example.
68
+ """Return a representation of the container that can be composed with other render() results. This function can also be used to defer layout and rending options until all the information about the container content is known. You may need to override this method depending on the container. See composable_container_video as an example.
69
69
 
70
70
  Returns:
71
71
  Any: Visual representation of the container that can be combined with other containers
@@ -0,0 +1,52 @@
1
+ from dataclasses import dataclass
2
+ import panel as pn
3
+ import xarray as xr
4
+ from bencher.results.composable_container.composable_container_base import ComposableContainerBase
5
+ from bencher.results.composable_container.composable_container_base import ComposeType
6
+
7
+
8
+ @dataclass(kw_only=True)
9
+ class ComposableContainerDataset(ComposableContainerBase):
10
+ name: str = None
11
+ var_name: str = None
12
+ var_value: str = None
13
+ width: int = None
14
+ background_col: str = None
15
+ horizontal: bool = True
16
+
17
+ def __post_init__(
18
+ self,
19
+ ) -> None:
20
+ container_args = {
21
+ "name": self.name,
22
+ "styles": {},
23
+ }
24
+
25
+ if self.width is not None:
26
+ container_args["styles"]["border-bottom"] = f"{self.width}px solid grey"
27
+ if self.background_col is not None:
28
+ container_args["styles"]["background"] = self.background_col
29
+
30
+ if self.horizontal:
31
+ self.container = pn.Column(**container_args)
32
+ align = ("center", "center")
33
+ else:
34
+ self.container = pn.Row(**container_args)
35
+ align = ("end", "center")
36
+
37
+ label = self.label_formatter(self.var_name, self.var_value)
38
+ if label is not None:
39
+ self.label_len = len(label)
40
+ side = pn.pane.Markdown(label, align=align)
41
+ self.append(side)
42
+
43
+ def render(self, **kwargs): # pylint: disable=unused-argument
44
+ match self.compose_method:
45
+ case ComposeType.right:
46
+ return xr.concat(self.container, 0)
47
+ case ComposeType.down:
48
+ return xr.concat(self.container, 1)
49
+ case ComposeType.sequence:
50
+ return xr.concat(self.container, 2)
51
+ # case ComposeType.overlay:
52
+ # return xr.Dataset.mean()
@@ -0,0 +1,227 @@
1
+ from typing import Optional
2
+ import panel as pn
3
+ from param import Parameter
4
+ from bencher.results.bench_result_base import BenchResultBase, ReduceType
5
+
6
+
7
+ from functools import partial
8
+ import holoviews as hv
9
+ from bencher.variables.results import (
10
+ PANEL_TYPES,
11
+ )
12
+
13
+
14
+ class DataSetResult(BenchResultBase):
15
+ def to_dataset1(
16
+ self,
17
+ result_var: Parameter = None,
18
+ hv_dataset=None,
19
+ target_dimension: int = 0,
20
+ container=None,
21
+ level: int = None,
22
+ **kwargs,
23
+ ) -> Optional[pn.pane.panel]:
24
+ if hv_dataset is None:
25
+ hv_dataset = self.to_hv_dataset(ReduceType.SQUEEZE, level=level)
26
+ elif not isinstance(hv_dataset, hv.Dataset):
27
+ hv_dataset = hv.Dataset(hv_dataset)
28
+ return self.map_plot_panes(
29
+ partial(self.ds_to_container, container=container),
30
+ hv_dataset=hv_dataset,
31
+ target_dimension=target_dimension,
32
+ result_var=result_var,
33
+ result_types=PANEL_TYPES,
34
+ **kwargs,
35
+ )
36
+
37
+
38
+ # class DataSetResult(BenchResultBase):
39
+
40
+ # def to_datatset(
41
+ # self,
42
+ # result_var: Parameter = None,
43
+ # result_types=(ResultDataSet,),
44
+ # pane_collection: pn.pane = None,
45
+ # time_sequence_dimension=0,
46
+ # target_duration: float = None,
47
+ # **kwargs,
48
+ # ) -> Optional[pn.panel]:
49
+ # """Returns the results compiled into a video
50
+
51
+ # Args:
52
+ # result_var (Parameter, optional): The result var to plot. Defaults to None.
53
+ # result_types (tuple, optional): The types of result var to convert to video. Defaults to (ResultDataSet,).
54
+ # collection (pn.pane, optional): If there are multiple results, use this collection to stack them. Defaults to pn.Row().
55
+
56
+ # Returns:
57
+ # Optional[pn.panel]: a panel pane with a video of all results concatenated together
58
+ # """
59
+ # plot_filter = PlotFilter(
60
+ # float_range=VarRange(0, None),
61
+ # cat_range=VarRange(0, None),
62
+ # panel_range=VarRange(1, None),
63
+ # input_range=VarRange(0, None),
64
+ # )
65
+ # matches_res = plot_filter.matches_result(
66
+ # self.plt_cnt_cfg, callable_name(self.to_video_grid_ds)
67
+ # )
68
+
69
+ # if pane_collection is None:
70
+ # pane_collection = pn.Row()
71
+
72
+ # if matches_res.overall:
73
+ # ds = self.to_dataset(ReduceType.SQUEEZE)
74
+ # for rv in self.get_results_var_list(result_var):
75
+ # if isinstance(rv, result_types):
76
+ # pane_collection.append(
77
+ # self.to_video_grid_ds(
78
+ # ds,
79
+ # rv,
80
+ # time_sequence_dimension=time_sequence_dimension,
81
+ # target_duration=target_duration,
82
+ # **kwargs,
83
+ # )
84
+ # )
85
+ # return pane_collection
86
+ # return matches_res.to_panel()
87
+
88
+ # def to_video_grid_ds(
89
+ # self,
90
+ # dataset: xr.Dataset,
91
+ # result_var: Parameter,
92
+ # reverse=True,
93
+ # time_sequence_dimension=0,
94
+ # video_controls: VideoControls = None,
95
+ # target_duration: float = None,
96
+ # **kwargs,
97
+ # ):
98
+ # cvc = self._to_video_panes_ds(
99
+ # dataset,
100
+ # self.plot_cb,
101
+ # target_dimension=0,
102
+ # horizontal=True,
103
+ # compose_method=ComposeType.right,
104
+ # time_sequence_dimension=time_sequence_dimension,
105
+ # result_var=result_var,
106
+ # final=True,
107
+ # reverse=reverse,
108
+ # target_duration=target_duration,
109
+ # **kwargs,
110
+ # )
111
+
112
+ # filename = VideoWriter().write_video_raw(cvc)
113
+
114
+ # if filename is not None:
115
+ # if video_controls is None:
116
+ # video_controls = VideoControls()
117
+ # return video_controls.video_container(
118
+ # filename, width=kwargs.get("width", None), height=kwargs.get("height", None)
119
+ # )
120
+ # return None
121
+
122
+ # def plot_cb(self, dataset, result_var, **kwargs):
123
+ # val = self.ds_to_container(dataset, result_var, container=None, **kwargs)
124
+ # return val
125
+
126
+ # def dataset_to_compose_list(
127
+ # self,
128
+ # dataset: xr.Dataset,
129
+ # first_compose_method: ComposeType = ComposeType.down,
130
+ # time_sequence_dimension: int = 0,
131
+ # ) -> List[ComposeType]:
132
+ # """ "Given a dataset, chose an order for composing the results. By default will flip between right and down and the last dimension will be a time sequence.
133
+
134
+ # Args:
135
+ # dataset (xr.Dataset): the dataset to render
136
+ # first_compose_method (ComposeType, optional): the direction of the first composition method. Defaults to ComposeType.right.
137
+ # time_sequence_dimension (int, optional): The dimension to start time sequencing instead of composing in space. Defaults to 0.
138
+
139
+ # Returns:
140
+ # List[ComposeType]: A list of composition methods for composing the dataset result
141
+ # """
142
+
143
+ # num_dims = len(dataset.sizes)
144
+ # if time_sequence_dimension == -1: # use time sequence for everything
145
+ # compose_method_list = [ComposeType.sequence] * (num_dims + 1)
146
+ # else:
147
+ # compose_method_list = [first_compose_method]
148
+ # compose_method_list.extend(
149
+ # ComposeType.flip(compose_method_list[-1]) for _ in range(num_dims - 1)
150
+ # )
151
+ # compose_method_list.append(ComposeType.sequence)
152
+
153
+ # for i in range(min(len(compose_method_list), time_sequence_dimension + 1)):
154
+ # compose_method_list[i] = ComposeType.sequence
155
+
156
+ # return compose_method_list
157
+
158
+ # def _to_video_panes_ds(
159
+ # self,
160
+ # dataset: xr.Dataset,
161
+ # plot_callback: callable = None,
162
+ # target_dimension=0,
163
+ # compose_method=ComposeType.right,
164
+ # compose_method_list=None,
165
+ # result_var=None,
166
+ # time_sequence_dimension=0,
167
+ # root_dimensions=None,
168
+ # reverse=False,
169
+ # target_duration: float = None,
170
+ # **kwargs,
171
+ # ) -> pn.panel:
172
+ # num_dims = len(dataset.sizes)
173
+ # dims = list(d for d in dataset.sizes)
174
+ # if reverse:
175
+ # dims = list(reversed(dims))
176
+
177
+ # if root_dimensions is None:
178
+ # root_dimensions = num_dims
179
+
180
+ # if compose_method_list is None:
181
+ # compose_method_list = self.dataset_to_compose_list(
182
+ # dataset, compose_method, time_sequence_dimension=time_sequence_dimension
183
+ # )
184
+
185
+ # # print(compose_method_list)
186
+
187
+ # compose_method_list_pop = deepcopy(compose_method_list)
188
+ # if len(compose_method_list_pop) > 1:
189
+ # compose_method = compose_method_list_pop.pop()
190
+
191
+ # if num_dims > (target_dimension) and num_dims != 0:
192
+ # selected_dim = dims[-1]
193
+ # outer_container = ComposableContainerVideo()
194
+ # for i in range(dataset.sizes[selected_dim]):
195
+ # sliced = dataset.isel({selected_dim: i})
196
+ # label_val = sliced.coords[selected_dim].values.item()
197
+ # inner_container = ComposableContainerVideo()
198
+
199
+ # panes = self._to_video_panes_ds(
200
+ # sliced,
201
+ # plot_callback=plot_callback,
202
+ # target_dimension=target_dimension,
203
+ # compose_method_list=compose_method_list_pop,
204
+ # result_var=result_var,
205
+ # root_dimensions=root_dimensions,
206
+ # time_sequence_dimension=time_sequence_dimension,
207
+ # )
208
+ # inner_container.append(panes)
209
+
210
+ # rendered = inner_container.render(
211
+ # RenderCfg(
212
+ # var_name=selected_dim,
213
+ # var_value=label_val,
214
+ # compose_method=compose_method,
215
+ # duration=target_duration,
216
+ # )
217
+ # )
218
+ # outer_container.append(rendered)
219
+ # return outer_container.render(
220
+ # RenderCfg(
221
+ # compose_method=compose_method,
222
+ # duration=target_duration,
223
+ # background_col=color_tuple_to_255(int_to_col(num_dims - 2, 0.05, 1.0)),
224
+ # # background_col= (255,0,0),
225
+ # )
226
+ # )
227
+ # return plot_callback(dataset=dataset, result_var=result_var, **kwargs)
@@ -34,7 +34,7 @@ from bencher.optuna_conversions import (
34
34
 
35
35
 
36
36
  def convert_dataset_bool_dims_to_str(dataset: xr.Dataset) -> xr.Dataset:
37
- """Given a dataarray that contains boolean coordinates, conver them to strings so that holoviews loads the data properly
37
+ """Given a dataarray that contains boolean coordinates, convert them to strings so that holoviews loads the data properly
38
38
 
39
39
  Args:
40
40
  dataarray (xr.DataArray): dataarray with boolean coordinates
@@ -63,6 +63,7 @@ class OptunaResult:
63
63
  self.studies = []
64
64
  self.plt_cnt_cfg = PltCntCfg()
65
65
  self.plot_inputs = []
66
+ self.dataset_list = []
66
67
 
67
68
  # self.width=600/
68
69
  # self.height=600
@@ -177,7 +178,7 @@ class OptunaResult:
177
178
  df = self.to_pandas()
178
179
  all_vars = []
179
180
  for v in self.bench_cfg.all_vars:
180
- if type(v) != TimeEvent:
181
+ if type(v) is not TimeEvent:
181
182
  all_vars.append(v)
182
183
 
183
184
  print("All vars", all_vars)
@@ -202,8 +203,8 @@ class OptunaResult:
202
203
  params = {}
203
204
  values = []
204
205
  for i in all_vars:
205
- if type(i) == TimeSnapshot:
206
- if type(row[1][i.name]) == np.datetime64:
206
+ if type(i) is TimeSnapshot:
207
+ if type(row[1][i.name]) is np.datetime64:
207
208
  params[i.name] = row[1][i.name].timestamp()
208
209
  else:
209
210
  params[i.name] = row[1][i.name]
@@ -341,14 +342,14 @@ class OptunaResult:
341
342
  if "width" not in kwargs:
342
343
  if self.bench_cfg.plot_size is not None:
343
344
  kwargs["width"] = self.bench_cfg.plot_size
344
- # specific width overrrides general size
345
+ # specific width overrides general size
345
346
  if self.bench_cfg.plot_width is not None:
346
347
  kwargs["width"] = self.bench_cfg.plot_width
347
348
 
348
349
  if "height" not in kwargs:
349
350
  if self.bench_cfg.plot_size is not None:
350
351
  kwargs["height"] = self.bench_cfg.plot_size
351
- # specific height overrrides general size
352
+ # specific height overrides general size
352
353
  if self.bench_cfg.plot_height is not None:
353
354
  kwargs["height"] = self.bench_cfg.plot_height
354
355
  return kwargs
@@ -7,7 +7,7 @@ from bencher.variables.sweep_base import SweepBase, shared_slots
7
7
 
8
8
 
9
9
  class SweepSelector(Selector, SweepBase):
10
- """A class to reprsent a parameter sweep of bools"""
10
+ """A class to represent a parameter sweep of bools"""
11
11
 
12
12
  __slots__ = shared_slots
13
13
 
@@ -27,7 +27,7 @@ class SweepSelector(Selector, SweepBase):
27
27
 
28
28
 
29
29
  class BoolSweep(SweepSelector):
30
- """A class to reprsent a parameter sweep of bools"""
30
+ """A class to represent a parameter sweep of bools"""
31
31
 
32
32
  def __init__(self, units: str = "ul", samples: int = None, default=True, **params):
33
33
  SweepSelector.__init__(
@@ -41,7 +41,7 @@ class BoolSweep(SweepSelector):
41
41
 
42
42
 
43
43
  class StringSweep(SweepSelector):
44
- """A class to reprsent a parameter sweep of strings"""
44
+ """A class to represent a parameter sweep of strings"""
45
45
 
46
46
  def __init__(
47
47
  self,
@@ -61,7 +61,7 @@ class StringSweep(SweepSelector):
61
61
 
62
62
 
63
63
  class EnumSweep(SweepSelector):
64
- """A class to reprsent a parameter sweep of enums"""
64
+ """A class to represent a parameter sweep of enums"""
65
65
 
66
66
  __slots__ = shared_slots
67
67
 
@@ -82,7 +82,7 @@ class EnumSweep(SweepSelector):
82
82
 
83
83
 
84
84
  class IntSweep(Integer, SweepBase):
85
- """A class to reprsent a parameter sweep of ints"""
85
+ """A class to represent a parameter sweep of ints"""
86
86
 
87
87
  __slots__ = shared_slots + ["sample_values"]
88
88
 
@@ -3,7 +3,7 @@ from typing import List, Tuple, Any
3
3
  from param import Parameter, Parameterized
4
4
  import holoviews as hv
5
5
  import panel as pn
6
-
6
+ from copy import deepcopy
7
7
 
8
8
  from bencher.utils import make_namedtuple, hash_sha1
9
9
  from bencher.variables.results import ALL_RESULT_TYPES, ResultHmap
@@ -127,7 +127,7 @@ class ParametrizedSweep(Parameterized):
127
127
  inp = cls.get_inputs_only()
128
128
  defaults = {}
129
129
  for i in inp:
130
- defaults[i.name] = i.default
130
+ defaults[i.name] = deepcopy(i.default)
131
131
 
132
132
  for k, v in kwargs.items():
133
133
  defaults[k] = v
@@ -186,6 +186,25 @@ class ResultReference(param.Parameter):
186
186
  return hash_sha1(self)
187
187
 
188
188
 
189
+ class ResultDataSet(param.Parameter):
190
+ __slots__ = ["units", "obj"]
191
+
192
+ def __init__(
193
+ self,
194
+ obj: Any = None,
195
+ default: Any = None,
196
+ units: str = "dataset",
197
+ **params,
198
+ ):
199
+ super().__init__(default=default, **params)
200
+ self.units = units
201
+ self.obj = obj
202
+
203
+ def hash_persistent(self) -> str:
204
+ """A hash function that avoids the PYTHONHASHSEED 'feature' which returns a different hash value each time the program is run"""
205
+ return hash_sha1(self)
206
+
207
+
189
208
  class ResultVolume(param.Parameter):
190
209
  __slots__ = ["units", "obj"]
191
210
 
@@ -199,7 +218,15 @@ class ResultVolume(param.Parameter):
199
218
  return hash_sha1(self)
200
219
 
201
220
 
202
- PANEL_TYPES = (ResultPath, ResultImage, ResultVideo, ResultContainer, ResultString, ResultReference)
221
+ PANEL_TYPES = (
222
+ ResultPath,
223
+ ResultImage,
224
+ ResultVideo,
225
+ ResultContainer,
226
+ ResultString,
227
+ ResultReference,
228
+ ResultDataSet,
229
+ )
203
230
 
204
231
  ALL_RESULT_TYPES = (
205
232
  ResultVar,
@@ -210,5 +237,6 @@ ALL_RESULT_TYPES = (
210
237
  ResultImage,
211
238
  ResultString,
212
239
  ResultContainer,
240
+ ResultDataSet,
213
241
  ResultReference,
214
242
  )
@@ -77,7 +77,7 @@ class SweepBase(param.Parameter):
77
77
  """given a sweep variable (self), return the range of values as a panel slider
78
78
 
79
79
  Args:
80
- debug (bool, optional): pass to the sweepvar to produce a full set of varaibles, or when debug=True, a reduces number of sweep vars. Defaults to False.
80
+ debug (bool, optional): pass to the sweepvar to produce a full set of variables, or when debug=True, a reduces number of sweep vars. Defaults to False.
81
81
 
82
82
  Returns:
83
83
  pn.widgets.slider.DiscreteSlider: A panel slider with the values() of the sweep variable
bencher/variables/time.py CHANGED
@@ -7,7 +7,7 @@ from bencher.variables.sweep_base import SweepBase, shared_slots
7
7
 
8
8
 
9
9
  class TimeBase(SweepBase, Selector):
10
- """A class to capture a time snapshot of benchmark values. Time is reprented as a continous value i.e a datetime which is converted into a np.datetime64. To represent time as a discrete value use the TimeEvent class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continous variables"""
10
+ """A class to capture a time snapshot of benchmark values. Time is represent as a continuous value i.e a datetime which is converted into a np.datetime64. To represent time as a discrete value use the TimeEvent class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continuous variables"""
11
11
 
12
12
  def __init__(
13
13
  self,
@@ -40,7 +40,7 @@ class TimeBase(SweepBase, Selector):
40
40
 
41
41
 
42
42
  class TimeSnapshot(TimeBase):
43
- """A class to capture a time snapshot of benchmark values. Time is reprented as a continous value i.e a datetime which is converted into a np.datetime64. To represent time as a discrete value use the TimeEvent class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continous variables"""
43
+ """A class to capture a time snapshot of benchmark values. Time is represent as a continuous value i.e a datetime which is converted into a np.datetime64. To represent time as a discrete value use the TimeEvent class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continuous variables"""
44
44
 
45
45
  __slots__ = shared_slots
46
46
 
@@ -68,7 +68,7 @@ class TimeSnapshot(TimeBase):
68
68
 
69
69
 
70
70
  class TimeEvent(TimeBase):
71
- """A class to represent a discrete event in time where the data was captured i.e a series of pull requests. Here time is discrete and can't be interpolated, to represent time as a continous value use the TimeSnapshot class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continous variables"""
71
+ """A class to represent a discrete event in time where the data was captured i.e a series of pull requests. Here time is discrete and can't be interpolated, to represent time as a continuous value use the TimeSnapshot class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continuous variables"""
72
72
 
73
73
  __slots__ = shared_slots
74
74
 
bencher/video_writer.py CHANGED
@@ -30,7 +30,7 @@ class VideoWriter:
30
30
  if width is None:
31
31
  width = len(label) * 10
32
32
  new_img = Image.new("RGB", (width, height), color=color)
33
- # ImageDraw.Draw(new_img).text((width/2, 0), label, (0, 0, 0),align="center",achor="ms")
33
+ # ImageDraw.Draw(new_img).text((width/2, 0), label, (0, 0, 0),align="center",anchor="ms")
34
34
  ImageDraw.Draw(new_img).text(
35
35
  (width / 2.0, 0), label, (0, 0, 0), anchor="mt", font_size=height
36
36
  )