holobench 1.18.0__py2.py3-none-any.whl → 1.30.0__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 (48) hide show
  1. bencher/__init__.py +13 -1
  2. bencher/bench_cfg.py +1 -1
  3. bencher/bench_report.py +6 -109
  4. bencher/bench_runner.py +1 -1
  5. bencher/bencher.py +117 -62
  6. bencher/example/benchmark_data.py +0 -4
  7. bencher/example/example_composable_container.py +106 -0
  8. bencher/example/example_composable_container2.py +160 -0
  9. bencher/example/example_consts.py +39 -0
  10. bencher/example/example_custom_sweep2.py +42 -0
  11. bencher/example/example_dataframe.py +48 -0
  12. bencher/example/example_filepath.py +27 -0
  13. bencher/example/example_image.py +31 -16
  14. bencher/example/example_image1.py +81 -0
  15. bencher/example/example_levels2.py +37 -0
  16. bencher/example/example_simple_float.py +15 -25
  17. bencher/example/example_simple_float2d.py +29 -0
  18. bencher/example/example_strings.py +3 -2
  19. bencher/example/example_video.py +2 -11
  20. bencher/example/meta/example_meta.py +2 -2
  21. bencher/example/meta/example_meta_cat.py +2 -2
  22. bencher/example/meta/example_meta_float.py +1 -1
  23. bencher/example/meta/example_meta_levels.py +2 -2
  24. bencher/optuna_conversions.py +3 -2
  25. bencher/plotting/plt_cnt_cfg.py +1 -0
  26. bencher/results/bench_result.py +3 -1
  27. bencher/results/bench_result_base.py +65 -8
  28. bencher/results/composable_container/composable_container_base.py +25 -12
  29. bencher/results/composable_container/composable_container_dataframe.py +52 -0
  30. bencher/results/composable_container/composable_container_panel.py +17 -18
  31. bencher/results/composable_container/composable_container_video.py +163 -55
  32. bencher/results/dataset_result.py +227 -0
  33. bencher/results/holoview_result.py +15 -7
  34. bencher/results/optuna_result.py +4 -3
  35. bencher/results/panel_result.py +1 -3
  36. bencher/results/video_summary.py +104 -99
  37. bencher/utils.py +29 -3
  38. bencher/variables/__init__.py +0 -0
  39. bencher/variables/inputs.py +24 -1
  40. bencher/variables/parametrised_sweep.py +8 -24
  41. bencher/variables/results.py +67 -9
  42. bencher/variables/time.py +22 -0
  43. bencher/video_writer.py +20 -74
  44. {holobench-1.18.0.dist-info → holobench-1.30.0.dist-info}/METADATA +77 -35
  45. {holobench-1.18.0.dist-info → holobench-1.30.0.dist-info}/RECORD +48 -34
  46. {holobench-1.18.0.dist-info → holobench-1.30.0.dist-info}/WHEEL +1 -1
  47. holobench-1.30.0.dist-info/licenses/LICENSE +21 -0
  48. resource/bencher +0 -0
@@ -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)
@@ -140,7 +140,7 @@ class HoloviewResult(PanelResult):
140
140
  elif not isinstance(tap_var, list):
141
141
  tap_var = [tap_var]
142
142
 
143
- if len(tap_var) == 0 or self.plt_cnt_cfg.inputs_cnt > 1:
143
+ if len(tap_var) == 0 or self.plt_cnt_cfg.inputs_cnt > 1 or not use_tap:
144
144
  heatmap_cb = self.to_line_ds
145
145
  else:
146
146
  heatmap_cb = partial(
@@ -200,6 +200,7 @@ class HoloviewResult(PanelResult):
200
200
  result_var: Parameter = None,
201
201
  tap_var=None,
202
202
  tap_container: pn.pane.panel = None,
203
+ tap_container_direction: pn.Column | pn.Row = None,
203
204
  target_dimension=2,
204
205
  **kwargs,
205
206
  ) -> Optional[pn.panel]:
@@ -208,11 +209,14 @@ class HoloviewResult(PanelResult):
208
209
  elif not isinstance(tap_var, list):
209
210
  tap_var = [tap_var]
210
211
 
211
- if len(tap_var) == 0:
212
+ if len(tap_var) == 0 or not use_tap:
212
213
  heatmap_cb = self.to_heatmap_ds
213
214
  else:
214
215
  heatmap_cb = partial(
215
- self.to_heatmap_container_tap_ds, result_var_plots=tap_var, container=tap_container
216
+ self.to_heatmap_container_tap_ds,
217
+ result_var_plots=tap_var,
218
+ container=tap_container,
219
+ tap_container_direction=tap_container_direction,
216
220
  )
217
221
 
218
222
  return self.filter(
@@ -251,7 +255,7 @@ class HoloviewResult(PanelResult):
251
255
  else:
252
256
  containers = listify(container)
253
257
 
254
- cont_instances = [c(**kwargs) for c in containers]
258
+ cont_instances = [c(**kwargs) if c is not None else None for c in containers]
255
259
  return result_var_plots, cont_instances
256
260
 
257
261
  def to_heatmap_container_tap_ds(
@@ -260,6 +264,7 @@ class HoloviewResult(PanelResult):
260
264
  result_var: Parameter,
261
265
  result_var_plots: List[Parameter] = None,
262
266
  container: pn.pane.panel = None,
267
+ tap_container_direction: pn.Column | pn.Row = None,
263
268
  **kwargs,
264
269
  ) -> pn.Row:
265
270
  htmap = self.to_heatmap_ds(dataset, result_var).opts(tools=["hover"], **kwargs)
@@ -322,8 +327,11 @@ class HoloviewResult(PanelResult):
322
327
  ls = hv.streams.MouseLeave(source=htmap)
323
328
  ls.add_subscriber(on_exit)
324
329
 
325
- bound_plot = pn.Column(title, *cont_instances)
326
- return pn.Row(htmap, bound_plot)
330
+ if tap_container_direction is None:
331
+ tap_container_direction = pn.Column
332
+ bound_plot = tap_container_direction(*cont_instances)
333
+
334
+ return pn.Row(htmap, pn.Column(title, bound_plot))
327
335
 
328
336
  def to_line_tap_ds(
329
337
  self,
@@ -677,7 +685,7 @@ class HoloviewResult(PanelResult):
677
685
  try:
678
686
  surface = hvds.to(hv.Surface, vdims=[result_var.name])
679
687
  surface = surface.opts(colorbar=True)
680
- except Exception as e:
688
+ except Exception as e: # pylint: disable=broad-except
681
689
  logging.warning(e)
682
690
 
683
691
  if self.bench_cfg.repeats > 1:
@@ -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]
@@ -25,10 +25,8 @@ class PanelResult(BenchResultBase):
25
25
  target_dimension: int = 0,
26
26
  container=None,
27
27
  level: int = None,
28
- **kwargs
28
+ **kwargs,
29
29
  ) -> Optional[pn.pane.panel]:
30
- if container is None:
31
- container = pn.pane.panel
32
30
  if hv_dataset is None:
33
31
  hv_dataset = self.to_hv_dataset(ReduceType.SQUEEZE, level=level)
34
32
  elif not isinstance(hv_dataset, hv.Dataset):
@@ -1,94 +1,44 @@
1
- from bencher.utils import params_to_str
2
1
  from typing import Optional, List
3
- import itertools
2
+ from copy import deepcopy
4
3
  import panel as pn
5
4
  import xarray as xr
6
5
  from param import Parameter
7
6
  from bencher.results.bench_result_base import BenchResultBase, ReduceType
8
7
  from bencher.variables.results import ResultImage
9
8
  from bencher.plotting.plot_filter import VarRange, PlotFilter
10
- from bencher.utils import callable_name, listify
9
+ from bencher.utils import callable_name, int_to_col, color_tuple_to_255
11
10
  from bencher.video_writer import VideoWriter
12
- from bencher.results.float_formatter import FormatFloat
13
11
  from bencher.results.video_result import VideoControls
14
- from bencher.utils import int_to_col
15
- from bencher.results.composable_container.composable_container_video import ComposableContainerVideo
12
+ from bencher.results.composable_container.composable_container_video import (
13
+ ComposableContainerVideo,
14
+ ComposeType,
15
+ RenderCfg,
16
+ )
16
17
 
17
18
 
18
19
  class VideoSummaryResult(BenchResultBase):
19
20
  def to_video_summary(
20
21
  self,
21
22
  result_var: Parameter = None,
22
- input_order: List[str] = None,
23
23
  reverse: bool = True,
24
24
  result_types=(ResultImage,),
25
25
  **kwargs,
26
26
  ) -> Optional[pn.panel]:
27
- plot_filter = PlotFilter(
28
- float_range=VarRange(0, None),
29
- cat_range=VarRange(0, None),
30
- panel_range=VarRange(1, None),
31
- )
32
- matches_res = plot_filter.matches_result(
33
- self.plt_cnt_cfg, callable_name(self.to_video_summary_ds)
27
+ return self.to_video_grid(
28
+ result_var=result_var,
29
+ result_types=result_types,
30
+ time_sequence_dimension=-1,
31
+ reverse=reverse,
32
+ **kwargs,
34
33
  )
35
34
 
36
- # video_controls = VideoControls()
37
- if matches_res.overall:
38
- ds = self.to_dataset(ReduceType.SQUEEZE)
39
- row = pn.Row()
40
- for rv in self.get_results_var_list(result_var):
41
- if isinstance(rv, result_types):
42
- row.append(self.to_video_summary_ds(ds, rv, input_order, reverse, **kwargs))
43
- return row
44
- return matches_res.to_panel()
45
-
46
- def to_video_summary_ds(
47
- self,
48
- dataset: xr.Dataset,
49
- result_var: Parameter,
50
- input_order: List[str] = None,
51
- reverse: bool = True,
52
- video_controls: VideoControls = None,
53
- **kwargs,
54
- ):
55
- vr = VideoWriter()
56
- da = dataset[result_var.name]
57
-
58
- if input_order is None:
59
- input_order = list(da.dims)
60
- else:
61
- input_order = params_to_str(input_order)
62
- if reverse:
63
- input_order = list(reversed(input_order))
64
-
65
- inputs_produc = [da.coords[i].values for i in input_order]
66
-
67
- for index in itertools.product(*inputs_produc):
68
- lookup = dict(zip(input_order, index))
69
- val = da.loc[lookup].item()
70
- index = listify(index)
71
- for i in range(len(index)):
72
- if isinstance(index[i], (int, float)):
73
- index[i] = FormatFloat()(index[i])
74
- label = ", ".join(f"{a[0]}={a[1]}" for a in list(zip(input_order, index)))
75
- if val is not None:
76
- vr.append_file(val, label)
77
- fn = vr.write_png(**kwargs)
78
- kwargs.pop("target_duration", None)
79
- if fn is not None:
80
- if video_controls is None:
81
- video_controls = VideoControls()
82
- vid = video_controls.video_container(fn, **kwargs)
83
- return vid
84
-
85
- return None
86
-
87
35
  def to_video_grid(
88
36
  self,
89
37
  result_var: Parameter = None,
90
38
  result_types=(ResultImage,),
91
39
  pane_collection: pn.pane = None,
40
+ time_sequence_dimension=0,
41
+ target_duration: float = None,
92
42
  **kwargs,
93
43
  ) -> Optional[pn.panel]:
94
44
  """Returns the results compiled into a video
@@ -118,7 +68,15 @@ class VideoSummaryResult(BenchResultBase):
118
68
  ds = self.to_dataset(ReduceType.SQUEEZE)
119
69
  for rv in self.get_results_var_list(result_var):
120
70
  if isinstance(rv, result_types):
121
- pane_collection.append(self.to_video_grid_ds(ds, rv, **kwargs))
71
+ pane_collection.append(
72
+ self.to_video_grid_ds(
73
+ ds,
74
+ rv,
75
+ time_sequence_dimension=time_sequence_dimension,
76
+ target_duration=target_duration,
77
+ **kwargs,
78
+ )
79
+ )
122
80
  return pane_collection
123
81
  return matches_res.to_panel()
124
82
 
@@ -127,17 +85,18 @@ class VideoSummaryResult(BenchResultBase):
127
85
  dataset: xr.Dataset,
128
86
  result_var: Parameter,
129
87
  reverse=True,
88
+ time_sequence_dimension=0,
130
89
  video_controls: VideoControls = None,
131
90
  target_duration: float = None,
132
91
  **kwargs,
133
92
  ):
134
- vr = VideoWriter()
135
-
136
93
  cvc = self._to_video_panes_ds(
137
94
  dataset,
138
95
  self.plot_cb,
139
96
  target_dimension=0,
140
97
  horizontal=True,
98
+ compose_method=ComposeType.right,
99
+ time_sequence_dimension=time_sequence_dimension,
141
100
  result_var=result_var,
142
101
  final=True,
143
102
  reverse=reverse,
@@ -145,27 +104,62 @@ class VideoSummaryResult(BenchResultBase):
145
104
  **kwargs,
146
105
  )
147
106
 
148
- fn = vr.write_video_raw(cvc)
107
+ filename = VideoWriter().write_video_raw(cvc)
149
108
 
150
- if fn is not None:
109
+ if filename is not None:
151
110
  if video_controls is None:
152
111
  video_controls = VideoControls()
153
- vid = video_controls.video_container(fn, **kwargs)
154
- return vid
112
+ return video_controls.video_container(
113
+ filename, width=kwargs.get("width", None), height=kwargs.get("height", None)
114
+ )
155
115
  return None
156
116
 
157
117
  def plot_cb(self, dataset, result_var, **kwargs):
158
118
  val = self.ds_to_container(dataset, result_var, container=None, **kwargs)
159
119
  return val
160
120
 
121
+ def dataset_to_compose_list(
122
+ self,
123
+ dataset: xr.Dataset,
124
+ first_compose_method: ComposeType = ComposeType.down,
125
+ time_sequence_dimension: int = 0,
126
+ ) -> List[ComposeType]:
127
+ """ "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.
128
+
129
+ Args:
130
+ dataset (xr.Dataset): the dataset to render
131
+ first_compose_method (ComposeType, optional): the direction of the first composition method. Defaults to ComposeType.right.
132
+ time_sequence_dimension (int, optional): The dimension to start time sequencing instead of composing in space. Defaults to 0.
133
+
134
+ Returns:
135
+ List[ComposeType]: A list of composition methods for composing the dataset result
136
+ """
137
+
138
+ num_dims = len(dataset.sizes)
139
+ if time_sequence_dimension == -1: # use time sequence for everything
140
+ compose_method_list = [ComposeType.sequence] * (num_dims + 1)
141
+ else:
142
+ compose_method_list = [first_compose_method]
143
+ compose_method_list.extend(
144
+ ComposeType.flip(compose_method_list[-1]) for _ in range(num_dims - 1)
145
+ )
146
+ compose_method_list.append(ComposeType.sequence)
147
+
148
+ for i in range(min(len(compose_method_list), time_sequence_dimension + 1)):
149
+ compose_method_list[i] = ComposeType.sequence
150
+
151
+ return compose_method_list
152
+
161
153
  def _to_video_panes_ds(
162
154
  self,
163
155
  dataset: xr.Dataset,
164
156
  plot_callback: callable = None,
165
157
  target_dimension=0,
166
- horizontal=False,
158
+ compose_method=ComposeType.right,
159
+ compose_method_list=None,
167
160
  result_var=None,
168
- final=False,
161
+ time_sequence_dimension=0,
162
+ root_dimensions=None,
169
163
  reverse=False,
170
164
  target_duration: float = None,
171
165
  **kwargs,
@@ -175,43 +169,54 @@ class VideoSummaryResult(BenchResultBase):
175
169
  if reverse:
176
170
  dims = list(reversed(dims))
177
171
 
172
+ if root_dimensions is None:
173
+ root_dimensions = num_dims
174
+
175
+ if compose_method_list is None:
176
+ compose_method_list = self.dataset_to_compose_list(
177
+ dataset, compose_method, time_sequence_dimension=time_sequence_dimension
178
+ )
179
+
180
+ # print(compose_method_list)
181
+
182
+ compose_method_list_pop = deepcopy(compose_method_list)
183
+ if len(compose_method_list_pop) > 1:
184
+ compose_method = compose_method_list_pop.pop()
185
+
178
186
  if num_dims > (target_dimension) and num_dims != 0:
179
187
  selected_dim = dims[-1]
180
- # print(f"selected dim {selected_dim}")
181
- dim_color = int_to_col(num_dims - 2, 0.05, 1.0)
182
- # sliced = dataset.isel({selected_dim: i})
183
- # label_val = sliced.coords[selected_dim].values.item()
184
-
185
- outer_container = ComposableContainerVideo(
186
- name=" vs ".join(dims),
187
- background_col=dim_color,
188
- horizontal=horizontal,
189
- target_duration=target_duration,
190
- # var_name=selected_dim,
191
- # var_value=label_val,
192
- )
193
- max_len = 0
188
+ outer_container = ComposableContainerVideo()
194
189
  for i in range(dataset.sizes[selected_dim]):
195
190
  sliced = dataset.isel({selected_dim: i})
196
191
  label_val = sliced.coords[selected_dim].values.item()
197
- inner_container = ComposableContainerVideo(
198
- outer_container.name,
199
- var_name=selected_dim,
200
- var_value=label_val,
201
- horizontal=horizontal,
202
- target_duration=target_duration,
203
- )
192
+ inner_container = ComposableContainerVideo()
193
+
204
194
  panes = self._to_video_panes_ds(
205
195
  sliced,
206
196
  plot_callback=plot_callback,
207
197
  target_dimension=target_dimension,
208
- horizontal=len(sliced.sizes) <= target_dimension + 1,
198
+ compose_method_list=compose_method_list_pop,
209
199
  result_var=result_var,
200
+ root_dimensions=root_dimensions,
201
+ time_sequence_dimension=time_sequence_dimension,
210
202
  )
211
203
  inner_container.append(panes)
212
204
 
213
- max_len = max(max_len, inner_container.label_len)
214
- rendered = inner_container.render()
205
+ rendered = inner_container.render(
206
+ RenderCfg(
207
+ var_name=selected_dim,
208
+ var_value=label_val,
209
+ compose_method=compose_method,
210
+ duration=target_duration,
211
+ )
212
+ )
215
213
  outer_container.append(rendered)
216
- return outer_container.render(concatenate=final)
214
+ return outer_container.render(
215
+ RenderCfg(
216
+ compose_method=compose_method,
217
+ duration=target_duration,
218
+ background_col=color_tuple_to_255(int_to_col(num_dims - 2, 0.05, 1.0)),
219
+ # background_col= (255,0,0),
220
+ )
221
+ )
217
222
  return plot_callback(dataset=dataset, result_var=result_var, **kwargs)