asreviewcontrib.simulation.api.plotting

Offers functionality for plotting a list of samples taken from the parameter space.

 1"""
 2Offers functionality for plotting a list of samples taken from the parameter space.
 3"""
 4from asreviewcontrib.simulation._private.lib.plotting.padding import Padding
 5from asreviewcontrib.simulation._private.lib.plotting.trellis import plot_trellis
 6from asreviewcontrib.simulation._private.lib.plotting.trellis import TrellisHandles
 7
 8
 9__all__ = [
10    "Padding",
11    "TrellisHandles",
12    "plot_trellis",
13]
class Padding:
 2class Padding:
 3    """
 4    Class to keep track of padding length in 4 directions: `bottom`, `left`, `right`, `top`.
 5    """
 6
 7    def __init__(self, bottom: float = 0.1, left: float = 0.1, right: float = 0.1, top: float = 0.1):
 8        """
 9        Synopsis:
10
11            Constructor method.
12
13        Example usage:
14
15            Use the default lengths of 0.1 all around:
16            ```python
17            from asreviewcontrib.simulation.api.plotting import Padding
18
19
20            padding = Padding()
21            ```
22
23            Use 0.0 padding horizontally and 0.2 vertically:
24
25            ```python
26            from asreviewcontrib.simulation.api.plotting import Padding
27
28
29            padding = Padding(left=0.0, right=0.0, top=0.2, bottom=0.2)
30            ```
31        """
32        # define private attributes
33        self._bottom = None
34        self._left = None
35        self._right = None
36        self._top = None
37
38        # set private attributes via setters
39        self.bottom = bottom
40        self.left = left
41        self.right = right
42        self.top = top
43
44    @property
45    def bottom(self):
46        """
47        The padding length at the bottom side.
48        """
49        return self._bottom
50
51    @bottom.setter
52    def bottom(self, bottom):
53        """
54        The padding length at the bottom side.
55        """
56        self._bottom = bottom
57
58    @property
59    def left(self):
60        """
61        The padding length at the left side.
62        """
63        return self._left
64
65    @left.setter
66    def left(self, left):
67        """
68        The padding length at the left side.
69        """
70        self._left = left
71
72    @property
73    def right(self):
74        """
75        The padding length at the right side.
76        """
77        return self._right
78
79    @right.setter
80    def right(self, right):
81        """
82        The padding length at the right side.
83        """
84        self._right = right
85
86    @property
87    def top(self):
88        """
89        The padding length at the top side.
90        """
91        return self._top
92
93    @top.setter
94    def top(self, top):
95        """
96        The padding length at the top side.
97        """
98        self._top = top

Class to keep track of padding length in 4 directions: bottom, left, right, top.

Padding( bottom: float = 0.1, left: float = 0.1, right: float = 0.1, top: float = 0.1)
 7    def __init__(self, bottom: float = 0.1, left: float = 0.1, right: float = 0.1, top: float = 0.1):
 8        """
 9        Synopsis:
10
11            Constructor method.
12
13        Example usage:
14
15            Use the default lengths of 0.1 all around:
16            ```python
17            from asreviewcontrib.simulation.api.plotting import Padding
18
19
20            padding = Padding()
21            ```
22
23            Use 0.0 padding horizontally and 0.2 vertically:
24
25            ```python
26            from asreviewcontrib.simulation.api.plotting import Padding
27
28
29            padding = Padding(left=0.0, right=0.0, top=0.2, bottom=0.2)
30            ```
31        """
32        # define private attributes
33        self._bottom = None
34        self._left = None
35        self._right = None
36        self._top = None
37
38        # set private attributes via setters
39        self.bottom = bottom
40        self.left = left
41        self.right = right
42        self.top = top
Synopsis:

Constructor method.

Example usage:

Use the default lengths of 0.1 all around:

from asreviewcontrib.simulation.api.plotting import Padding


padding = Padding()

Use 0.0 padding horizontally and 0.2 vertically:

from asreviewcontrib.simulation.api.plotting import Padding


padding = Padding(left=0.0, right=0.0, top=0.2, bottom=0.2)
bottom
44    @property
45    def bottom(self):
46        """
47        The padding length at the bottom side.
48        """
49        return self._bottom

The padding length at the bottom side.

left
58    @property
59    def left(self):
60        """
61        The padding length at the left side.
62        """
63        return self._left

The padding length at the left side.

right
72    @property
73    def right(self):
74        """
75        The padding length at the right side.
76        """
77        return self._right

The padding length at the right side.

top
86    @property
87    def top(self):
88        """
89        The padding length at the top side.
90        """
91        return self._top

The padding length at the top side.

class TrellisHandles:
 53class TrellisHandles:
 54    def __init__(
 55        self,
 56        axes_handles: List[List[Optional[plt.Axes]]],
 57        show_params: List[str],
 58    ):
 59        """
 60        Args:
 61            axes_handles:
 62                TODO
 63            show_params:
 64                TODO
 65
 66        Synopsis:
 67
 68            TODO
 69        """
 70        self._axes = axes_handles
 71        self._show_params = show_params
 72
 73    def get_axes_by_row_name(self, row_name: str) -> List[plt.Axes]:
 74        """
 75        Args:
 76            row_name:
 77                TODO
 78
 79        Returns:
 80            TODO
 81        """
 82        assert row_name is not None, "Need a name to identify the row of subaxes"
 83        assert row_name in self.show_params[:-1], f"{row_name} is not a valid name for a row"
 84        irow = self.show_params.index(row_name)
 85        return [col for col in self.axes[irow] if col is not None]
 86
 87    def get_axes_by_col_name(self, col_name: str) -> List[plt.Axes]:
 88        """
 89        Args:
 90            col_name:
 91                TODO
 92
 93        Returns:
 94            TODO
 95        """
 96        assert col_name is not None, "Need a name to identify the column of subaxes"
 97        assert col_name in self.show_params[1:], f"{col_name} is not a valid name for a column"
 98        icol = self.show_params.index(col_name)
 99        return [row[icol] for row in self.axes if row[icol] is not None]
100
101    def get_axes_by_names(self, row_name: Optional[str] = None, col_name: Optional[str] = None) -> plt.Axes:
102        """
103        Args:
104            row_name:
105                TODO
106            col_name:
107                TODO
108
109        Returns:
110            TODO
111        """
112        assert row_name is not None, "Need a name to identify the row of subaxes"
113        assert row_name in self.show_params[:-1], f"{row_name} is not a valid name for a row"
114        assert col_name is not None, "Need a name to identify the column of subaxes"
115        assert col_name in self.show_params[1:], f"{col_name} is not a valid name for a column"
116        irow = self.show_params.index(row_name)
117        icol = self.show_params.index(col_name)
118        assert icol > irow, "No axes at that position."
119        return self._axes[irow][icol]
120
121    @property
122    def axes(self):
123        """
124        TODO
125        """
126        return self._axes
127
128    @property
129    def show_params(self):
130        """
131        TODO
132        """
133        return self._show_params
TrellisHandles( axes_handles: List[List[Optional[matplotlib.axes._axes.Axes]]], show_params: List[str])
54    def __init__(
55        self,
56        axes_handles: List[List[Optional[plt.Axes]]],
57        show_params: List[str],
58    ):
59        """
60        Args:
61            axes_handles:
62                TODO
63            show_params:
64                TODO
65
66        Synopsis:
67
68            TODO
69        """
70        self._axes = axes_handles
71        self._show_params = show_params
Arguments:
  • axes_handles: TODO
  • show_params: TODO
Synopsis:

TODO

def get_axes_by_row_name(self, row_name: str) -> List[matplotlib.axes._axes.Axes]:
73    def get_axes_by_row_name(self, row_name: str) -> List[plt.Axes]:
74        """
75        Args:
76            row_name:
77                TODO
78
79        Returns:
80            TODO
81        """
82        assert row_name is not None, "Need a name to identify the row of subaxes"
83        assert row_name in self.show_params[:-1], f"{row_name} is not a valid name for a row"
84        irow = self.show_params.index(row_name)
85        return [col for col in self.axes[irow] if col is not None]
Arguments:
  • row_name: TODO
Returns:

TODO

def get_axes_by_col_name(self, col_name: str) -> List[matplotlib.axes._axes.Axes]:
87    def get_axes_by_col_name(self, col_name: str) -> List[plt.Axes]:
88        """
89        Args:
90            col_name:
91                TODO
92
93        Returns:
94            TODO
95        """
96        assert col_name is not None, "Need a name to identify the column of subaxes"
97        assert col_name in self.show_params[1:], f"{col_name} is not a valid name for a column"
98        icol = self.show_params.index(col_name)
99        return [row[icol] for row in self.axes if row[icol] is not None]
Arguments:
  • col_name: TODO
Returns:

TODO

def get_axes_by_names( self, row_name: Optional[str] = None, col_name: Optional[str] = None) -> matplotlib.axes._axes.Axes:
101    def get_axes_by_names(self, row_name: Optional[str] = None, col_name: Optional[str] = None) -> plt.Axes:
102        """
103        Args:
104            row_name:
105                TODO
106            col_name:
107                TODO
108
109        Returns:
110            TODO
111        """
112        assert row_name is not None, "Need a name to identify the row of subaxes"
113        assert row_name in self.show_params[:-1], f"{row_name} is not a valid name for a row"
114        assert col_name is not None, "Need a name to identify the column of subaxes"
115        assert col_name in self.show_params[1:], f"{col_name} is not a valid name for a column"
116        irow = self.show_params.index(row_name)
117        icol = self.show_params.index(col_name)
118        assert icol > irow, "No axes at that position."
119        return self._axes[irow][icol]
Arguments:
  • row_name: TODO
  • col_name: TODO
Returns:

TODO

axes
121    @property
122    def axes(self):
123        """
124        TODO
125        """
126        return self._axes

TODO

show_params
128    @property
129    def show_params(self):
130        """
131        TODO
132        """
133        return self._show_params

TODO

def plot_trellis( data: List[Tuple[asreviewcontrib.simulation._private.lib.config.Config, float]], show_params: Optional[List[str]] = None, outer_padding: Optional[Padding] = None, inner_padding: Optional[Padding] = None, scatter_kwargs: Optional[Dict[str, Any]] = None, show_response_surface: bool = True, show_text: bool = True) -> TrellisHandles:
289def plot_trellis(
290    data: List[Tuple[Config, float]],
291    show_params: Optional[List[str]] = None,
292    outer_padding: Optional[Padding] = None,
293    inner_padding: Optional[Padding] = None,
294    scatter_kwargs: Optional[Dict[str, Any]] = None,
295    show_response_surface: bool = True,
296    show_text: bool = True,
297) -> TrellisHandles:
298    """
299    Args:
300        data: A list of tuples, where each tuple consists of an
301            `asreviewcontrib.simulation.api.Config` object and its associated objective score.
302        show_params:
303            The subset of the parameters that you want to plot.
304        outer_padding:
305            The padding around the trellis of axes.
306        inner_padding:
307            The padding around an individual axes.
308        scatter_kwargs:
309            `matplotlib`'s `scatter` keyword arguments, see
310            https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html.
311        show_response_surface:
312            Whether to show an interpolation of objective function scores as a background
313            image in each axes.
314        show_text:
315            Whether to show the metadata for the list of parameterizations.
316
317    Returns:
318        The handles to the axes, to facilitate subsequent customization.
319
320    Synopsis:
321
322        Visualize each combination of 2 parameters out of a user-provided list of parameters using
323        a grid/trellis of axes.
324
325    Example usage:
326
327        ```python
328        from asreviewcontrib.simulation.api import Config
329        from asreviewcontrib.simulation.api import draw_sample
330        from asreviewcontrib.simulation.api import get_pyll
331        from asreviewcontrib.simulation.api import OneModelConfig
332        from asreviewcontrib.simulation.api.plotting import plot_trellis
333        from matplotlib import pyplot as plt
334
335
336        # retrieve the sampling spaces for the double balancer model
337        # and the TF-IDF feature extraction model, respectively.
338        pyll = {
339            "bal": get_pyll("bal-double"),
340            "fex": get_pyll("fex-tfidf"),
341        }
342
343        n_samples = 100
344        results = []
345
346        for _ in range(n_samples):
347
348            # use pyll programs to draw a parameterization for 'bal' and 'fex'
349            drawn = draw_sample(pyll)
350
351            # construct an all-model config from one-model configs -- implicitly use
352            # default model choice and parameterization for models not included as
353            # argument
354            config = Config(**fixed, **drawn)
355
356            # emulate calculating objective scores with random(), naturally the
357            # results are not meaningful
358            results.append((config, random()))
359
360        plt.figure()
361        plot_trellis(results, sorted(drawn.keys()))
362        plt.show()
363        ```
364    """
365
366    assert len(data) >= 1, "Need at least one sample"
367    expected_params = data[0][0].flattened().keys()
368    for irow, row in enumerate(data):
369        actual_params = row[0].flattened().keys()
370        # verify that all the data rows are samples in the same parameter space
371        assert set(actual_params) == set(expected_params), f"Data row {irow} has unexpected key set"
372
373    # verify that the parameters selected for plotting are in fact all present
374    show_params = show_params or sorted(expected_params)
375    assert set(show_params).issubset(set(expected_params)), "The data doesn't include all the parameters you wanted to plot"
376
377    data_dict, scores = _calc_data_dict(data, show_params)
378
379    # assign defaults
380    outer = outer_padding or Padding(left=0.14, right=0.01, top=0.01, bottom=0.14)
381    inner = inner_padding or Padding(left=0.05, right=0.05, top=0.05, bottom=0.05)
382    scatter_kwargs = scatter_kwargs or {}
383
384    # prepare the grid of axes
385    axes_handles = _prep_axes(data_dict, inner=inner, outer=outer)
386
387    trellis_handles = TrellisHandles(axes_handles, show_params)
388
389    # visualize the data
390    _plot_scatter(axes_handles, data_dict, scatter_kwargs)
391
392    if show_response_surface:
393        _plot_response_surface(axes_handles, data_dict, scores)
394
395    if show_text:
396        _plot_text(data_dict, trellis_handles)
397
398    return trellis_handles
Arguments:
  • data: A list of tuples, where each tuple consists of an asreviewcontrib.simulation.api.Config object and its associated objective score.
  • show_params: The subset of the parameters that you want to plot.
  • outer_padding: The padding around the trellis of axes.
  • inner_padding: The padding around an individual axes.
  • scatter_kwargs: matplotlib's scatter keyword arguments, see https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html.
  • show_response_surface: Whether to show an interpolation of objective function scores as a background image in each axes.
  • show_text: Whether to show the metadata for the list of parameterizations.
Returns:

The handles to the axes, to facilitate subsequent customization.

Synopsis:

Visualize each combination of 2 parameters out of a user-provided list of parameters using a grid/trellis of axes.

Example usage:
from asreviewcontrib.simulation.api import Config
from asreviewcontrib.simulation.api import draw_sample
from asreviewcontrib.simulation.api import get_pyll
from asreviewcontrib.simulation.api import OneModelConfig
from asreviewcontrib.simulation.api.plotting import plot_trellis
from matplotlib import pyplot as plt


# retrieve the sampling spaces for the double balancer model
# and the TF-IDF feature extraction model, respectively.
pyll = {
    "bal": get_pyll("bal-double"),
    "fex": get_pyll("fex-tfidf"),
}

n_samples = 100
results = []

for _ in range(n_samples):

    # use pyll programs to draw a parameterization for 'bal' and 'fex'
    drawn = draw_sample(pyll)

    # construct an all-model config from one-model configs -- implicitly use
    # default model choice and parameterization for models not included as
    # argument
    config = Config(**fixed, **drawn)

    # emulate calculating objective scores with random(), naturally the
    # results are not meaningful
    results.append((config, random()))

plt.figure()
plot_trellis(results, sorted(drawn.keys()))
plt.show()