Source code for gemseo.post.dataset.dataset_plot

# -*- 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 - initial API and implementation and/or initial
#                           documentation
#        :author: Matthias De Lozzo
#    OTHER AUTHORS   - MACROSCOPIC CHANGES
"""
Abstract dataset plot
=====================

The :mod:`~gemseo.post.dataset.dataset_plot` module implements the abstract
:class:`.DatasetPlot` class
whose purpose is to build a graphical representation
of a :class:`.Dataset` and to display it on screen or save it to a file.
This abstract class has to be overloaded by concrete ones implementing
at least method :meth:`!DatasetPlot._run`.
"""
from __future__ import absolute_import, division, unicode_literals

from numbers import Number

import matplotlib
import pylab
from future import standard_library
from six import string_types

standard_library.install_aliases()


[docs]class DatasetPlot(object): """ Abstract plot class for dataset. """ def __init__(self, dataset): """Constructor. :param Dataset dataset: dataset """ if dataset.is_empty(): raise ValueError("Dataset is empty.") self.dataset = dataset self.output_files = []
[docs] def execute( self, save=True, show=False, file_path=None, extension="pdf", **plot_options ): """ Executes the post processing :param show: if True, displays the plot windows. Default: False. :type show: bool :param save: if True, exports plot to pdf. Default: False. :type save: bool :param file_path: the base paths of the files to export. Default: None. :type file_path: str :param extension: file extension. Default: 'pdf'. :type extension: str :param plot_options: options passed to the _plot() method. """ self._run(save, show, file_path, extension, **plot_options)
def _run(self, save, show, file_path, extension, **plot_options): """Define run of the post processing, calling _plot() and saving or displaying figure. :param plot_options: options passed to the _plot() method. :param show: if True, displays the plot windows. Default: False. :type show: bool :param save: if True, exports plot to pdf. Default: False. :type save: bool :param file_path: the base paths of the files to export. Default: None. :type file_path: str :param extension: file extension. Default: 'pdf'. :type extension: str :param plot_options: options passed to the _plot() method. """ fig = self._plot(**plot_options) if isinstance(fig, list): for index, subfig in enumerate(fig): subfig.tight_layout() filename = self.__class__.__name__ + str(index) self._save_and_show( subfig, filename=filename, save=save, show=show, file_path=file_path, extension=extension, ) else: fig.tight_layout() self._save_and_show( fig, filename=self.__class__.__name__, save=save, show=show, file_path=file_path, extension=extension, ) def _plot(self, **options): """Define plot of the post processing, to be implemented in subclasses :param options: plotting options according to associated json file """ raise NotImplementedError def _save_and_show( self, fig, filename, save=True, show=False, file_path=None, extension="pdf" ): """ Saves figures and or shows it depending on options :param fig: matplotlib figure :param str filename: name of the file to save the plot :param bool save: save the figure (default: True) :param bool show: show the figure (default: False) :param str file_path: file path to save the plot (default: None) :param str extension: file extension (default: 'pdf') """ matplotlib.rcParams.update({"font.size": 10}) if save: file_path = file_path or self.dataset.name fpath = file_path + "_" + filename fpath += "." + extension fig.savefig(fpath, bbox_inches="tight") if fpath not in self.output_files: self.output_files.append(fpath) if show: try: pylab.plt.show(fig) except TypeError: pylab.plt.show() def _get_varnames(self, df_columns): """Get varnames from columns of a pandas dataframe. :param list(tuple) dataframe: pandas dataframe """ new_columns = [] for column in df_columns: if self.dataset.sizes[column[1]] == 1: new_columns.append(column[1]) else: new_columns.append(column[1] + "(" + str(column[2]) + ")") return new_columns def _get_label(self, varname): """Returns string label associated to a variable name, as well as refactored variable name. :param varname: variable name, either a string or a (str, int) tuple. """ if isinstance(varname, string_types): label = varname varname = (self.dataset.get_group(varname), varname, "0") elif hasattr(varname, "__len__") and len(varname) == 3: is_string = isinstance(varname[0], string_types) is_string = is_string and isinstance(varname[1], string_types) is_number = isinstance(varname[2], Number) if is_string and is_number: label = varname[1] + "(" + str(varname[2]) + ")" varname[2] = str(varname[2]) varname = tuple(varname) else: raise TypeError( "varname must be either a string or a tuple" " whose first component is a string and second" " one is an integer." ) else: raise TypeError( "varname must be either a string or a tuple" " whose first component is a string and second" " one is an integer." ) return label, varname