Source code for pymoo.visualization.heatmap

"""Heatmap visualization for multi-objective optimization results."""

import numpy as np

from pymoo.core.plot import Plot
from pymoo.util.misc import set_if_none_from_tuples
from pymoo.visualization.util import normalize, parse_bounds


[docs] class Heatmap(Plot): """Visualize results as a heatmap.""" def __init__( self, cmap="Blues", order_by_objectives=False, reverse=True, solution_labels=True, **kwargs, ): """Initialize Heatmap. Args: cmap: The color map to be used. order_by_objectives: Whether the result should be ordered by an objective. If False no order. Otherwise, either supply just the objective or a list (it is lexicographically sorted). reverse: If True large values are white and small values the corresponding color. Otherwise, the other way around. solution_labels: If False no labels are plotted in the y axis. If True just the corresponding index. Otherwise, the label provided. **kwargs: Additional keyword arguments passed to parent Plot class. """ super().__init__(cmap=cmap, reverse=reverse, **kwargs) self.order_by_objectives = order_by_objectives self.solution_labels = solution_labels # set default style set_if_none_from_tuples( self.axis_style, ("interpolation", "nearest"), ("vmin", 0), ("vmax", 1) ) def _do(self): if len(self.to_plot) != 1: raise Exception("Only one element can be added to a heatmap.") # initial a figure with a single plot self.init_figure() # normalize the input bounds = parse_bounds(self.bounds, self.n_dim) to_plot_norm = normalize(self.to_plot, bounds, reverse=self.reverse) (F, kwargs) = to_plot_norm[0] # dot the sorting if required if ( self.order_by_objectives is not None and self.order_by_objectives is not False ): if ( isinstance(self.order_by_objectives, list) and len(self.order_by_objectives) == self.n_dim ): L = self.order_by_objectives elif isinstance(self.order_by_objectives, int): L = [i for i in range(F.shape[1]) if i != self.order_by_objectives] L.insert(0, self.order_by_objectives) else: L = range(self.n_dim) _F = [F[:, j] for j in L] indices = np.lexsort(_F[::-1]) else: indices = np.arange(len(F)) # plot the data self.ax.imshow(F[indices], cmap=self.cmap, **self.axis_style) # set the x ticks and labels self.ax.set_xticks(np.arange(self.n_dim)) self.ax.set_xticklabels(self.get_labels()) # no solution labels should be used if self.solution_labels is None: pass # if true, just use a number for each solution elif isinstance(self.solution_labels, bool) and self.solution_labels: self.solution_labels = np.arange(len(F)) + 1 # otherwise, use directly the label provided else: if len(self.solution_labels) != len(F): raise Exception( "The labels provided for each solution must be equal to the number of solutions being plotted." ) if self.solution_labels is None: self.ax.set_yticks([]) self.ax.set_yticklabels([]) else: # for ordered by objective apply it to labels self.solution_labels = [self.solution_labels[i] for i in indices] self.ax.set_yticks(np.arange(len(F))) self.ax.set_yticklabels(self.solution_labels)