Source code for gemseo.post.radar_chart

# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
# Contributors:
#    INITIAL AUTHORS - API and implementation and/or documentation
#        :author: Pierre-Jean Barjhoux
#    OTHER AUTHORS   - MACROSCOPIC CHANGES
"""Plot the constraints on a radar chart at a given dataset index."""

from __future__ import annotations

from typing import ClassVar

from numpy import vstack
from numpy import zeros

from gemseo.datasets.dataset import Dataset
from gemseo.post.base_post import BasePost
from gemseo.post.dataset.radar_chart import RadarChart as RadarChartPost
from gemseo.post.radar_chart_settings import RadarChart_Settings


[docs] class RadarChart(BasePost[RadarChart_Settings]): """Plot the constraints on a radar chart at a given dataset index.""" Settings: ClassVar[type[RadarChart_Settings]] = RadarChart_Settings def _plot(self, settings: RadarChart_Settings) -> None: """ Raises: ValueError: When a requested name is not a constraint or when the requested iteration is neither a dataset index nor the tag ``"opt"``. """ # noqa: D205, D212, D415 constraint_names = settings.constraint_names constraint_names = ( list(constraint_names) if not isinstance(constraint_names, list) else constraint_names ) iteration = settings.iteration constraint_names_mapping = ( self._optimization_metadata.output_names_to_constraint_names ) if constraint_names: names = [] for constraint_name in constraint_names: if constraint_name in constraint_names_mapping: names.extend(constraint_names_mapping[constraint_name]) else: names.append(constraint_name) constraint_names = names invalid_names = sorted( set(constraint_names) - set( self._dataset.inequality_constraint_names + self._dataset.equality_constraint_names ) ) if invalid_names: msg = ( f"The names {invalid_names} are not names of constraints " "stored in the dataset." ) raise ValueError(msg) else: constraint_names = ( self._dataset.equality_constraint_names + self._dataset.inequality_constraint_names ) # optimum_index is the zero-based position of the optimum. # while an iteration is a one-based position. assert self._optimization_metadata.optimum_iteration is not None optimum_iteration = self._optimization_metadata.optimum_iteration if iteration is None: iteration = optimum_iteration is_optimum = iteration == optimum_iteration dataset = self._dataset n_iterations = len(dataset) if abs(iteration) not in range(1, n_iterations + 1): msg = ( f"The requested iteration {iteration} is neither " f"in ({-n_iterations},...,-1,1,...,{n_iterations}) " f"nor None." ) raise ValueError(msg) if iteration < 0: iteration = n_iterations + iteration + 1 constraint_values = dataset.get_view(variable_names=constraint_names).to_numpy() constraint_names = dataset.get_columns(constraint_names) # "-1" because ndarray uses zero-based indexing and iteration is one-based. constraint_values = constraint_values[iteration - 1, :].ravel() dataset = Dataset(dataset_name="Constraints") values = vstack((constraint_values, zeros(len(constraint_values)))) dataset.add_group( dataset.DEFAULT_GROUP, values, constraint_names, ) dataset.index = ["computed constraints", "limit constraint"] radar = RadarChartPost( dataset, display_zero=False, radial_ticks=settings.show_names_radially ) radar.linestyle = ["-", "--"] radar.color = ["k", "r"] title_suffix = " (optimum)" if is_optimum else "" radar.title = f"Constraints at iteration {iteration}{title_suffix}" self._add_figure(radar)