Source code for gemseo.post.para_coord

# -*- coding: utf-8 -*-
# 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: Francois Gallard
#        :author: Damien Guenot
#    OTHER AUTHORS   - MACROSCOPIC CHANGES
"""
A parallel coordinates plot of functions and x
**********************************************
"""

from __future__ import absolute_import, division, unicode_literals

from os.path import splitext

import matplotlib as mpl
from future import standard_library
from matplotlib import pyplot
from numpy import array

from gemseo.post.core.colormaps import PARULA
from gemseo.post.opt_post_processor import OptPostProcessor

standard_library.install_aliases()
from gemseo import LOGGER


[docs]class ParallelCoordinates(OptPostProcessor): """ The **ParallelCoordinates** post processing builds parallel coordinates plots among design variables, outputs functions and constraints x- and y- figure sizes can be changed in option. It is possible either to save the plot, to show the plot or both. """ def _run(self, figsize_x=10, figsize_y=2, **options): """Visualizes the ScatterPlotMatrix :param options: plotting options according to associated json file :param figsize_x: X size of the figure Default value = 10 :param figsize_y: Y size of the figure Default value = 2 """ self._plot(figsize_x, figsize_y, **options)
[docs] @staticmethod def parallel_coordinates(y_data, x_names, color_criteria, figsize_x, figsize_y): """Plots parallel coordinates :param y_data: the lines data to plot :type y_data: array :param x_names: names of the abscissa :type x_names: list(str) :param color_criteria: the list of values of same length as y_data to colorize the lines :type color_criteria: list(float) :param figsize_x: size of figure in horizontal direction (inches) :type figsize_x: int :param figsize_y: size of figure in vertical direction (inches) :type figsize_y: int """ n_x, n_cols = y_data.shape assert n_cols == len(x_names) assert n_x == len(color_criteria) x_values = list(range(n_cols)) fig = pyplot.figure(figsize=(figsize_x, figsize_y)) main_ax = pyplot.gca() c_max = color_criteria.max() c_min = color_criteria.min() color_criteria_n = (color_criteria - c_min) / (c_max - c_min) for i in range(n_x): color = array(PARULA(color_criteria_n[i])).flatten() main_ax.plot(x_values, y_data[i, :], c=color) norm = mpl.colors.Normalize(vmin=c_min, vmax=c_max) cax, _ = mpl.colorbar.make_axes(main_ax) mpl.colorbar.ColorbarBase(cax, norm=norm, cmap=PARULA) for i in x_values: main_ax.axvline(i, linewidth=1, color="black") main_ax.set_xticks(x_values) main_ax.set_xticklabels(x_names) main_ax.grid() return fig
def _plot( self, figsize_x, figsize_y, show=False, save=False, file_path="para_coord_funcs", extension="pdf", ): """ Plots the ScatterPlotMatrix graph :param figsize_x: size of figure in horizontal direction (inches) :type figsize_x: int :param figsize_y: size of figure in vertical direction (inches) :type figsize_y: int :param show: if True, displays the plot windows :type show: bool :param save: if True, exports plot to pdf :type save: bool :param file_path: the base paths of the files to export :type file_path: str :param extension: file extension :type extension: str """ all_funcs = self.opt_problem.get_all_functions_names() design_variables = self.opt_problem.get_design_variable_names() vals, vname, _ = self.database.get_history_array(all_funcs, add_dv=True) n_x = len(self.database.get_x_by_iter(0)) x_names = [] for d_v in design_variables: dv_size = self.opt_problem.design_space.variables_sizes[d_v] if dv_size == 1: x_names.append(d_v) else: for i in range(dv_size): x_names.append(d_v + "_" + str(i)) func_names = vname[: len(vname) - n_x] obj_name = self.opt_problem.get_objective_name() obj_val = vals[:, vname.index(obj_name)] x_vals = vals[:, vals.shape[1] - len(x_names) :] x_vals = self.opt_problem.design_space.normalize_vect(x_vals) fig = self.parallel_coordinates(x_vals, x_names, obj_val, figsize_x, figsize_y) fig.suptitle( "Design variables history colored" + " by '" + obj_name + "' value" ) root = splitext(file_path)[0] self._save_and_show( fig, save=save, show=show, file_path=root + "para_coord_des_vars", extension=extension, ) func_vals = vals[:, : vals.shape[1] - len(x_names)] fig = self.parallel_coordinates( func_vals, func_names, obj_val, figsize_x, figsize_y ) fig.suptitle( "Objective function and constraints history" + " colored by '" + obj_name + "' value" ) self._save_and_show( fig, file_path=root + "para_coord_funcs", save=save, show=show, extension=extension, )