holobench 1.41.0__py3-none-any.whl → 1.43.0__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.
- bencher/__init__.py +20 -2
- bencher/bench_cfg.py +262 -54
- bencher/bench_report.py +2 -2
- bencher/bench_runner.py +96 -10
- bencher/bencher.py +421 -89
- bencher/class_enum.py +70 -7
- bencher/example/example_dataframe.py +2 -2
- bencher/example/example_levels.py +17 -173
- bencher/example/example_pareto.py +107 -31
- bencher/example/example_rerun2.py +1 -1
- bencher/example/example_simple_bool.py +2 -2
- bencher/example/example_simple_float2d.py +6 -1
- bencher/example/example_video.py +2 -0
- bencher/example/experimental/example_hvplot_explorer.py +2 -2
- bencher/example/inputs_0D/example_0_in_1_out.py +25 -15
- bencher/example/inputs_0D/example_0_in_2_out.py +12 -3
- bencher/example/inputs_0_float/example_0_cat_in_2_out.py +88 -0
- bencher/example/inputs_0_float/example_1_cat_in_2_out.py +98 -0
- bencher/example/inputs_0_float/example_2_cat_in_2_out.py +107 -0
- bencher/example/inputs_0_float/example_3_cat_in_2_out.py +111 -0
- bencher/example/inputs_1D/example1d_common.py +48 -12
- bencher/example/inputs_1D/example_0_float_1_cat.py +33 -0
- bencher/example/inputs_1D/example_1_cat_in_2_out_repeats.py +68 -0
- bencher/example/inputs_1D/example_1_float_2_cat_repeats.py +3 -0
- bencher/example/inputs_1D/example_1_int_in_1_out.py +98 -0
- bencher/example/inputs_1D/example_1_int_in_2_out.py +101 -0
- bencher/example/inputs_1D/example_1_int_in_2_out_repeats.py +99 -0
- bencher/example/inputs_1_float/example_1_float_0_cat_in_2_out.py +117 -0
- bencher/example/inputs_1_float/example_1_float_1_cat_in_2_out.py +124 -0
- bencher/example/inputs_1_float/example_1_float_2_cat_in_2_out.py +132 -0
- bencher/example/inputs_1_float/example_1_float_3_cat_in_2_out.py +140 -0
- bencher/example/inputs_2D/example_2_cat_in_4_out_repeats.py +104 -0
- bencher/example/inputs_2_float/example_2_float_0_cat_in_2_out.py +98 -0
- bencher/example/inputs_2_float/example_2_float_1_cat_in_2_out.py +112 -0
- bencher/example/inputs_2_float/example_2_float_2_cat_in_2_out.py +122 -0
- bencher/example/inputs_2_float/example_2_float_3_cat_in_2_out.py +138 -0
- bencher/example/inputs_3_float/example_3_float_0_cat_in_2_out.py +111 -0
- bencher/example/inputs_3_float/example_3_float_1_cat_in_2_out.py +117 -0
- bencher/example/inputs_3_float/example_3_float_2_cat_in_2_out.py +124 -0
- bencher/example/inputs_3_float/example_3_float_3_cat_in_2_out.py +129 -0
- bencher/example/meta/generate_examples.py +118 -7
- bencher/example/meta/generate_meta.py +88 -40
- bencher/job.py +174 -9
- bencher/plotting/plot_filter.py +52 -17
- bencher/results/bench_result.py +117 -25
- bencher/results/bench_result_base.py +117 -8
- bencher/results/dataset_result.py +6 -200
- bencher/results/explorer_result.py +23 -0
- bencher/results/{hvplot_result.py → histogram_result.py} +3 -18
- bencher/results/holoview_results/__init__.py +0 -0
- bencher/results/holoview_results/bar_result.py +79 -0
- bencher/results/holoview_results/curve_result.py +110 -0
- bencher/results/holoview_results/distribution_result/__init__.py +0 -0
- bencher/results/holoview_results/distribution_result/box_whisker_result.py +73 -0
- bencher/results/holoview_results/distribution_result/distribution_result.py +109 -0
- bencher/results/holoview_results/distribution_result/scatter_jitter_result.py +92 -0
- bencher/results/holoview_results/distribution_result/violin_result.py +70 -0
- bencher/results/holoview_results/heatmap_result.py +319 -0
- bencher/results/holoview_results/holoview_result.py +346 -0
- bencher/results/holoview_results/line_result.py +240 -0
- bencher/results/holoview_results/scatter_result.py +107 -0
- bencher/results/holoview_results/surface_result.py +158 -0
- bencher/results/holoview_results/table_result.py +14 -0
- bencher/results/holoview_results/tabulator_result.py +20 -0
- bencher/results/optuna_result.py +30 -115
- bencher/results/video_controls.py +38 -0
- bencher/results/video_result.py +39 -36
- bencher/results/video_summary.py +2 -2
- bencher/results/{plotly_result.py → volume_result.py} +29 -8
- bencher/utils.py +175 -26
- bencher/variables/inputs.py +122 -15
- bencher/video_writer.py +2 -1
- bencher/worker_job.py +31 -3
- {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/METADATA +24 -24
- holobench-1.43.0.dist-info/RECORD +147 -0
- bencher/example/example_levels2.py +0 -37
- bencher/example/inputs_1D/example_1_in_1_out.py +0 -62
- bencher/example/inputs_1D/example_1_in_2_out.py +0 -63
- bencher/example/inputs_1D/example_1_in_2_out_repeats.py +0 -61
- bencher/results/holoview_result.py +0 -796
- bencher/results/panel_result.py +0 -41
- holobench-1.41.0.dist-info/RECORD +0 -114
- {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/WHEEL +0 -0
- {holobench-1.41.0.dist-info → holobench-1.43.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Optional, Any
|
3
|
+
import panel as pn
|
4
|
+
import holoviews as hv
|
5
|
+
from param import Parameter
|
6
|
+
import xarray as xr
|
7
|
+
|
8
|
+
from bencher.results.holoview_results.distribution_result.distribution_result import (
|
9
|
+
DistributionResult,
|
10
|
+
)
|
11
|
+
|
12
|
+
from bencher.results.bench_result_base import ReduceType
|
13
|
+
from bencher.plotting.plot_filter import VarRange
|
14
|
+
from bencher.variables.results import ResultVar
|
15
|
+
|
16
|
+
|
17
|
+
class ScatterJitterResult(DistributionResult):
|
18
|
+
"""A class for creating scatter jitter plots from benchmark results.
|
19
|
+
|
20
|
+
Scatter jitter plots display individual data points with slight random offsets
|
21
|
+
to avoid overlapping, making it easier to visualize the distribution of data.
|
22
|
+
This is particularly useful for smaller datasets where showing individual points
|
23
|
+
provides more insight than aggregate statistics, or alongside box plots to show
|
24
|
+
the actual data distribution.
|
25
|
+
|
26
|
+
Key features:
|
27
|
+
- Displays individual data points rather than statistical summaries
|
28
|
+
- Applies controlled random offsets to avoid point overlap
|
29
|
+
- Useful for revealing the actual sample size and distribution
|
30
|
+
- Complements statistical plots like box plots or violin plots
|
31
|
+
"""
|
32
|
+
|
33
|
+
def to_plot(
|
34
|
+
self,
|
35
|
+
result_var: Optional[Parameter] = None,
|
36
|
+
override: bool = True,
|
37
|
+
jitter: float = 0.1,
|
38
|
+
**kwargs: Any,
|
39
|
+
) -> Optional[pn.panel]:
|
40
|
+
"""Generates a scatter jitter plot from benchmark data.
|
41
|
+
|
42
|
+
This method applies filters to ensure the data is appropriate for a scatter plot
|
43
|
+
and then passes the filtered data to to_scatter_jitter_ds for rendering.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
result_var: The result variable to plot. If None, uses the default.
|
47
|
+
override: Whether to override filter restrictions. Defaults to True.
|
48
|
+
jitter: Amount of jitter to apply to points. Defaults to 0.1.
|
49
|
+
**kwargs: Additional keyword arguments passed to the plot rendering.
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
A panel containing the scatter jitter plot if data is appropriate,
|
53
|
+
otherwise returns filter match results.
|
54
|
+
"""
|
55
|
+
return self.filter(
|
56
|
+
self.to_scatter_jitter_ds,
|
57
|
+
float_range=VarRange(0, 0),
|
58
|
+
cat_range=VarRange(0, 1),
|
59
|
+
repeats_range=VarRange(2, None),
|
60
|
+
reduce=ReduceType.NONE,
|
61
|
+
target_dimension=self.plt_cnt_cfg.cat_cnt + 1, # +1 cos we have a repeats dimension
|
62
|
+
result_var=result_var,
|
63
|
+
result_types=(ResultVar,),
|
64
|
+
override=override,
|
65
|
+
jitter=jitter,
|
66
|
+
**kwargs,
|
67
|
+
)
|
68
|
+
|
69
|
+
def to_scatter_jitter_ds(
|
70
|
+
self, dataset: xr.Dataset, result_var: Parameter, jitter: float = 0.1, **kwargs: Any
|
71
|
+
) -> hv.Scatter:
|
72
|
+
"""Creates a scatter jitter plot from the provided dataset.
|
73
|
+
|
74
|
+
Given a filtered dataset, this method generates a scatter visualization showing
|
75
|
+
individual data points with random jitter to avoid overlapping, making the
|
76
|
+
distribution of values more visible.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
dataset: The dataset containing benchmark results.
|
80
|
+
result_var: The result variable to plot.
|
81
|
+
jitter: Amount of jitter to apply to points. Defaults to 0.1.
|
82
|
+
**kwargs: Additional keyword arguments for plot customization, such as:
|
83
|
+
- color: Color for data points
|
84
|
+
- size: Size of data points
|
85
|
+
- alpha: Transparency of data points
|
86
|
+
- marker: Shape of data points ('o', 's', 'd', etc.)
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
A HoloViews Scatter plot of the benchmark data with jittered points.
|
90
|
+
"""
|
91
|
+
# Prepare the data using the common method from the parent class
|
92
|
+
return self._plot_distribution(dataset, result_var, hv.Scatter, jitter=jitter, **kwargs)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Optional, Any
|
3
|
+
import panel as pn
|
4
|
+
import holoviews as hv
|
5
|
+
from param import Parameter
|
6
|
+
import xarray as xr
|
7
|
+
|
8
|
+
from bencher.results.holoview_results.distribution_result.distribution_result import (
|
9
|
+
DistributionResult,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
class ViolinResult(DistributionResult):
|
14
|
+
"""A class for creating violin plots from benchmark results.
|
15
|
+
|
16
|
+
Violin plots combine aspects of box plots with kernel density plots, showing
|
17
|
+
the distribution shape of the data. This class provides methods to generate
|
18
|
+
these plots from benchmark data, which is particularly useful for visualizing
|
19
|
+
the distribution of metrics across different configurations or repetitions.
|
20
|
+
|
21
|
+
Violin plots display:
|
22
|
+
- The full probability density of the data (the width of the "violin" at each point)
|
23
|
+
- Summary statistics like median and interquartile ranges
|
24
|
+
- The overall distribution shape, revealing features like multi-modality that
|
25
|
+
box plots might miss
|
26
|
+
"""
|
27
|
+
|
28
|
+
def to_plot(
|
29
|
+
self, result_var: Optional[Parameter] = None, override: bool = True, **kwargs: Any
|
30
|
+
) -> Optional[pn.panel]:
|
31
|
+
"""Generates a violin plot from benchmark data.
|
32
|
+
|
33
|
+
This method applies filters to ensure the data is appropriate for a violin plot
|
34
|
+
and then passes the filtered data to to_violin_ds for rendering.
|
35
|
+
|
36
|
+
Args:
|
37
|
+
result_var (Optional[Parameter]): The result variable to plot. If None, uses the default.
|
38
|
+
override (bool): Whether to override filter restrictions. Defaults to True.
|
39
|
+
**kwargs (Any): Additional keyword arguments passed to the plot rendering.
|
40
|
+
|
41
|
+
Returns:
|
42
|
+
Optional[pn.panel]: A panel containing the violin plot if data is appropriate,
|
43
|
+
otherwise returns filter match results.
|
44
|
+
"""
|
45
|
+
return self.to_distribution_plot(
|
46
|
+
self.to_violin_ds,
|
47
|
+
result_var=result_var,
|
48
|
+
override=override,
|
49
|
+
**kwargs,
|
50
|
+
)
|
51
|
+
|
52
|
+
def to_violin_ds(self, dataset: xr.Dataset, result_var: Parameter, **kwargs: Any) -> hv.Violin:
|
53
|
+
"""Creates a violin plot from the provided dataset.
|
54
|
+
|
55
|
+
Given a filtered dataset, this method generates a violin plot visualization showing
|
56
|
+
the distribution of values for a result variable, potentially grouped by a categorical variable.
|
57
|
+
|
58
|
+
Args:
|
59
|
+
dataset (xr.Dataset): The dataset containing benchmark results.
|
60
|
+
result_var (Parameter): The result variable to plot.
|
61
|
+
**kwargs (Any): Additional keyword arguments for plot customization, such as:
|
62
|
+
- violin_color: Color for the violin body
|
63
|
+
- inner_color: Color for inner statistics markers
|
64
|
+
- line_width: Width of outline lines
|
65
|
+
- bandwidth: Controls the smoothness of the density estimate
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
hv.Violin: A HoloViews Violin plot of the benchmark data.
|
69
|
+
"""
|
70
|
+
return self._plot_distribution(dataset, result_var, hv.Violin, **kwargs)
|
@@ -0,0 +1,319 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import List, Optional
|
3
|
+
import panel as pn
|
4
|
+
import holoviews as hv
|
5
|
+
from param import Parameter
|
6
|
+
from functools import partial
|
7
|
+
import hvplot.xarray # noqa pylint: disable=duplicate-code,unused-import
|
8
|
+
import xarray as xr
|
9
|
+
|
10
|
+
from bencher.utils import (
|
11
|
+
get_nearest_coords1D,
|
12
|
+
)
|
13
|
+
from bencher.results.bench_result_base import ReduceType
|
14
|
+
from bencher.plotting.plot_filter import PlotFilter, VarRange
|
15
|
+
from bencher.variables.results import ResultVar
|
16
|
+
from bencher.results.holoview_results.holoview_result import HoloviewResult
|
17
|
+
|
18
|
+
|
19
|
+
class HeatmapResult(HoloviewResult):
|
20
|
+
"""A class for creating heatmap visualizations from benchmark results.
|
21
|
+
|
22
|
+
Heatmaps are effective for visualizing the relationship between two input variables
|
23
|
+
and a result variable by using color intensity to represent the result values.
|
24
|
+
This class provides methods for generating interactive heatmaps that can display
|
25
|
+
additional information when hovering over or selecting points on the heatmap.
|
26
|
+
"""
|
27
|
+
|
28
|
+
def to_plot(
|
29
|
+
self,
|
30
|
+
result_var: Parameter = None,
|
31
|
+
tap_var=None,
|
32
|
+
tap_container: pn.pane.panel = None,
|
33
|
+
tap_container_direction: pn.Column | pn.Row = None,
|
34
|
+
target_dimension=2,
|
35
|
+
override: bool = True,
|
36
|
+
use_tap: bool = None,
|
37
|
+
**kwargs,
|
38
|
+
) -> Optional[pn.panel]:
|
39
|
+
"""Generates a heatmap visualization from benchmark data.
|
40
|
+
|
41
|
+
This is a convenience method that calls to_heatmap() with the same parameters.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
result_var (Parameter, optional): The result variable to plot. If None, uses the default.
|
45
|
+
tap_var: Variables to display when tapping on heatmap points.
|
46
|
+
tap_container (pn.pane.panel, optional): Container to hold tapped information.
|
47
|
+
tap_container_direction (pn.Column | pn.Row, optional): Layout direction for the tap container.
|
48
|
+
target_dimension (int, optional): Target dimensionality for the plot. Defaults to 2.
|
49
|
+
override (bool, optional): Whether to override filter restrictions. Defaults to True.
|
50
|
+
use_tap (bool, optional): Whether to enable tap functionality.
|
51
|
+
**kwargs: Additional keyword arguments passed to the plot rendering.
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
Optional[pn.panel]: A panel containing the heatmap if data is appropriate,
|
55
|
+
otherwise returns filter match results.
|
56
|
+
"""
|
57
|
+
return self.to_heatmap(
|
58
|
+
result_var=result_var,
|
59
|
+
tap_var=tap_var,
|
60
|
+
tap_container=tap_container,
|
61
|
+
tap_container_direction=tap_container_direction,
|
62
|
+
target_dimension=target_dimension,
|
63
|
+
override=override,
|
64
|
+
use_tap=use_tap,
|
65
|
+
**kwargs,
|
66
|
+
)
|
67
|
+
|
68
|
+
def to_heatmap(
|
69
|
+
self,
|
70
|
+
result_var: Parameter = None,
|
71
|
+
tap_var=None,
|
72
|
+
tap_container: pn.pane.panel = None,
|
73
|
+
tap_container_direction: pn.Column | pn.Row = None,
|
74
|
+
target_dimension=2,
|
75
|
+
override: bool = True,
|
76
|
+
use_tap: bool = None,
|
77
|
+
**kwargs,
|
78
|
+
) -> Optional[pn.panel]:
|
79
|
+
"""Generates a heatmap visualization from benchmark data.
|
80
|
+
|
81
|
+
This method applies filters to ensure the data is appropriate for a heatmap
|
82
|
+
and then passes the filtered data to the appropriate rendering method. If tap
|
83
|
+
functionality is enabled, it will create an interactive heatmap that displays
|
84
|
+
additional information when data points are selected.
|
85
|
+
|
86
|
+
Args:
|
87
|
+
result_var (Parameter, optional): The result variable to plot. If None, uses the default.
|
88
|
+
tap_var: Variables to display when tapping on heatmap points.
|
89
|
+
tap_container (pn.pane.panel, optional): Container to hold tapped information.
|
90
|
+
tap_container_direction (pn.Column | pn.Row, optional): Layout direction for the tap container.
|
91
|
+
target_dimension (int, optional): Target dimensionality for the plot. Defaults to 2.
|
92
|
+
override (bool, optional): Whether to override filter restrictions. Defaults to True.
|
93
|
+
use_tap (bool, optional): Whether to enable tap functionality.
|
94
|
+
**kwargs: Additional keyword arguments passed to the plot rendering.
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
Optional[pn.panel]: A panel containing the heatmap if data is appropriate,
|
98
|
+
otherwise returns filter match results.
|
99
|
+
"""
|
100
|
+
if tap_var is None:
|
101
|
+
tap_var = self.plt_cnt_cfg.panel_vars
|
102
|
+
elif not isinstance(tap_var, list):
|
103
|
+
tap_var = [tap_var]
|
104
|
+
|
105
|
+
if len(tap_var) == 0 or not use_tap:
|
106
|
+
heatmap_cb = self.to_heatmap_ds
|
107
|
+
else:
|
108
|
+
heatmap_cb = partial(
|
109
|
+
self.to_heatmap_container_tap_ds,
|
110
|
+
result_var_plots=tap_var,
|
111
|
+
container=tap_container,
|
112
|
+
tap_container_direction=tap_container_direction,
|
113
|
+
)
|
114
|
+
|
115
|
+
return self.filter(
|
116
|
+
heatmap_cb,
|
117
|
+
float_range=VarRange(0, None),
|
118
|
+
cat_range=VarRange(0, None),
|
119
|
+
input_range=VarRange(2, None),
|
120
|
+
panel_range=VarRange(0, None),
|
121
|
+
target_dimension=target_dimension,
|
122
|
+
result_var=result_var,
|
123
|
+
result_types=(ResultVar),
|
124
|
+
override=override,
|
125
|
+
**kwargs,
|
126
|
+
)
|
127
|
+
|
128
|
+
def to_heatmap_ds(
|
129
|
+
self, dataset: xr.Dataset, result_var: Parameter, **kwargs
|
130
|
+
) -> Optional[hv.HeatMap]:
|
131
|
+
"""Creates a basic heatmap from the provided dataset.
|
132
|
+
|
133
|
+
Given a filtered dataset, this method generates a heatmap visualization showing
|
134
|
+
the relationship between two input variables and a result variable using color intensity.
|
135
|
+
|
136
|
+
Args:
|
137
|
+
dataset (xr.Dataset): The dataset containing benchmark results.
|
138
|
+
result_var (Parameter): The result variable to plot.
|
139
|
+
**kwargs: Additional keyword arguments passed to the heatmap options.
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
Optional[hv.HeatMap]: A heatmap visualization if the dataset has at least 2 dimensions,
|
143
|
+
otherwise returns None.
|
144
|
+
"""
|
145
|
+
if len(dataset.dims) >= 2:
|
146
|
+
x = self.bench_cfg.input_vars[0].name
|
147
|
+
y = self.bench_cfg.input_vars[1].name
|
148
|
+
C = result_var.name
|
149
|
+
title = f"Heatmap of {result_var.name}"
|
150
|
+
time_args = self.time_widget(title)
|
151
|
+
return dataset.hvplot.heatmap(x=x, y=y, C=C, cmap="plasma", **time_args, **kwargs)
|
152
|
+
return None
|
153
|
+
|
154
|
+
def to_heatmap_container_tap_ds(
|
155
|
+
self,
|
156
|
+
dataset: xr.Dataset,
|
157
|
+
result_var: Parameter,
|
158
|
+
result_var_plots: List[Parameter] = None,
|
159
|
+
container: pn.pane.panel = None,
|
160
|
+
tap_container_direction: pn.Column | pn.Row = None,
|
161
|
+
**kwargs,
|
162
|
+
) -> pn.Row:
|
163
|
+
"""Creates an interactive heatmap with tap functionality.
|
164
|
+
|
165
|
+
This method generates a heatmap with interactive tap functionality that displays
|
166
|
+
additional information about selected points in separate containers.
|
167
|
+
|
168
|
+
Args:
|
169
|
+
dataset (xr.Dataset): The dataset containing benchmark results.
|
170
|
+
result_var (Parameter): The primary result variable to plot in the heatmap.
|
171
|
+
result_var_plots (List[Parameter], optional): Additional result variables to display when a point is tapped.
|
172
|
+
container (pn.pane.panel, optional): Container to display tapped information.
|
173
|
+
tap_container_direction (pn.Column | pn.Row, optional): Layout direction for the tap containers.
|
174
|
+
**kwargs: Additional keyword arguments passed to the heatmap options.
|
175
|
+
|
176
|
+
Returns:
|
177
|
+
pn.Row: A panel row containing the interactive heatmap and containers for tapped information.
|
178
|
+
"""
|
179
|
+
htmap = self.to_heatmap_ds(dataset, result_var).opts(tools=["hover"], **kwargs)
|
180
|
+
result_var_plots, cont_instances = self.setup_results_and_containers(
|
181
|
+
result_var_plots, container
|
182
|
+
)
|
183
|
+
title = pn.pane.Markdown("Selected: None")
|
184
|
+
|
185
|
+
state = dict(x=None, y=None, update=False)
|
186
|
+
|
187
|
+
def tap_plot_heatmap(x, y): # pragma: no cover
|
188
|
+
# print(f"moved {x}{y}")
|
189
|
+
x_nearest_new = get_nearest_coords1D(
|
190
|
+
x, dataset.coords[self.bench_cfg.input_vars[0].name].data
|
191
|
+
)
|
192
|
+
y_nearest_new = get_nearest_coords1D(
|
193
|
+
y, dataset.coords[self.bench_cfg.input_vars[1].name].data
|
194
|
+
)
|
195
|
+
|
196
|
+
# xv = self.bench_cfg.input_vars[0].name
|
197
|
+
# yv = self.bench_cfg.input_vars[1].name
|
198
|
+
# nearest = get_nearest_coords(dataset, **{xv: x, yv: y})
|
199
|
+
# print(nearest)
|
200
|
+
# print(x_nearest_new,y_nearest_new)
|
201
|
+
|
202
|
+
if x_nearest_new != state["x"]:
|
203
|
+
state["x"] = x_nearest_new
|
204
|
+
state["update"] = True
|
205
|
+
if y_nearest_new != state["y"]:
|
206
|
+
state["y"] = y_nearest_new
|
207
|
+
state["update"] = True
|
208
|
+
|
209
|
+
if state["update"]:
|
210
|
+
kdims = {}
|
211
|
+
kdims[self.bench_cfg.input_vars[0].name] = state["x"]
|
212
|
+
kdims[self.bench_cfg.input_vars[1].name] = state["y"]
|
213
|
+
|
214
|
+
if hasattr(htmap, "current_key"):
|
215
|
+
for d, k in zip(htmap.kdims, htmap.current_key):
|
216
|
+
kdims[d.name] = k
|
217
|
+
for rv, cont in zip(result_var_plots, cont_instances):
|
218
|
+
ds = dataset[rv.name]
|
219
|
+
val = ds.sel(**kdims)
|
220
|
+
item = self.zero_dim_da_to_val(val)
|
221
|
+
title.object = "Selected: " + ", ".join([f"{k}:{v}" for k, v in kdims.items()])
|
222
|
+
|
223
|
+
cont.object = item
|
224
|
+
if hasattr(cont, "autoplay"): # container is a video, set to autoplay
|
225
|
+
cont.paused = False
|
226
|
+
cont.time = 0
|
227
|
+
cont.loop = True
|
228
|
+
cont.autoplay = True
|
229
|
+
state["update"] = False
|
230
|
+
|
231
|
+
def on_exit(x, y): # pragma: no cover # pylint: disable=unused-argument
|
232
|
+
state["update"] = True
|
233
|
+
|
234
|
+
htmap_posxy = hv.streams.PointerXY(source=htmap)
|
235
|
+
htmap_posxy.add_subscriber(tap_plot_heatmap)
|
236
|
+
ls = hv.streams.MouseLeave(source=htmap)
|
237
|
+
ls.add_subscriber(on_exit)
|
238
|
+
|
239
|
+
if tap_container_direction is None:
|
240
|
+
tap_container_direction = pn.Column
|
241
|
+
bound_plot = tap_container_direction(*cont_instances)
|
242
|
+
|
243
|
+
return pn.Row(htmap, pn.Column(title, bound_plot))
|
244
|
+
|
245
|
+
def to_heatmap_single(
|
246
|
+
self,
|
247
|
+
result_var: Parameter,
|
248
|
+
override: bool = True,
|
249
|
+
reduce: ReduceType = ReduceType.AUTO,
|
250
|
+
**kwargs,
|
251
|
+
) -> hv.HeatMap:
|
252
|
+
"""Creates a single heatmap from the result variable.
|
253
|
+
|
254
|
+
This method creates a heatmap directly from the benchmark results dataset without
|
255
|
+
applying the standard filtering pipeline.
|
256
|
+
|
257
|
+
Args:
|
258
|
+
result_var (Parameter): The result variable to plot.
|
259
|
+
override (bool, optional): Whether to override filter restrictions. Defaults to True.
|
260
|
+
reduce (ReduceType, optional): How to reduce the data. Defaults to ReduceType.AUTO.
|
261
|
+
**kwargs: Additional keyword arguments passed to the heatmap options.
|
262
|
+
|
263
|
+
Returns:
|
264
|
+
hv.HeatMap: A heatmap visualization if data matches criteria,
|
265
|
+
otherwise returns filter match results.
|
266
|
+
"""
|
267
|
+
matches_res = PlotFilter(
|
268
|
+
float_range=VarRange(2, None),
|
269
|
+
cat_range=VarRange(0, None),
|
270
|
+
input_range=VarRange(1, None),
|
271
|
+
).matches_result(self.plt_cnt_cfg, "to_heatmap", override)
|
272
|
+
if matches_res.overall:
|
273
|
+
z = result_var
|
274
|
+
title = f"{z.name} vs ("
|
275
|
+
|
276
|
+
for iv in self.bench_cfg.input_vars:
|
277
|
+
title += f" vs {iv.name}"
|
278
|
+
title += ")"
|
279
|
+
|
280
|
+
color_label = f"{z.name} [{z.units}]"
|
281
|
+
|
282
|
+
return self.to_hv_type(hv.HeatMap, reduce).opts(clabel=color_label, **kwargs)
|
283
|
+
return matches_res.to_panel()
|
284
|
+
|
285
|
+
def to_heatmap_tap(
|
286
|
+
self,
|
287
|
+
result_var: Parameter,
|
288
|
+
reduce: ReduceType = ReduceType.AUTO,
|
289
|
+
width=800,
|
290
|
+
height=800,
|
291
|
+
**kwargs,
|
292
|
+
):
|
293
|
+
"""Creates a tappable heatmap that shows details when tapped.
|
294
|
+
|
295
|
+
This method generates a heatmap with tap functionality that displays
|
296
|
+
additional visualizations when a point is selected.
|
297
|
+
|
298
|
+
Args:
|
299
|
+
result_var (Parameter): The result variable to plot.
|
300
|
+
reduce (ReduceType, optional): How to reduce the data. Defaults to ReduceType.AUTO.
|
301
|
+
width (int, optional): Width of the plot in pixels. Defaults to 800.
|
302
|
+
height (int, optional): Height of the plot in pixels. Defaults to 800.
|
303
|
+
**kwargs: Additional keyword arguments.
|
304
|
+
|
305
|
+
Returns:
|
306
|
+
hv.Layout: A layout containing both the heatmap and the dynamically updated detail view.
|
307
|
+
"""
|
308
|
+
htmap = self.to_heatmap_single(result_var, reduce).opts(
|
309
|
+
tools=["hover", "tap"], width=width, height=height
|
310
|
+
)
|
311
|
+
htmap_posxy = hv.streams.Tap(source=htmap, x=0, y=0)
|
312
|
+
|
313
|
+
def tap_plot(x, y):
|
314
|
+
kwargs[self.bench_cfg.input_vars[0].name] = x
|
315
|
+
kwargs[self.bench_cfg.input_vars[1].name] = y
|
316
|
+
return self.get_nearest_holomap(**kwargs).opts(width=width, height=height)
|
317
|
+
|
318
|
+
tap_htmap = hv.DynamicMap(tap_plot, streams=[htmap_posxy])
|
319
|
+
return htmap + tap_htmap
|