Source code for gemseo.post.opt_post_processor
# -*- 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
# OTHER AUTHORS - MACROSCOPIC CHANGES
"""
Base class for all optimization post processings
************************************************
"""
from __future__ import absolute_import, division, unicode_literals
import inspect
from os.path import abspath, dirname, exists, join, splitext
import matplotlib
import pylab
from future import standard_library
from gemseo.core.grammar import InvalidDataException
from gemseo.core.json_grammar import JSONGrammar
from gemseo.utils.source_parsing import SourceParsing
standard_library.install_aliases()
[docs]class OptPostProcessor(object):
"""Abstract class for optimization post processing methods"""
def __init__(self, opt_problem):
"""
Constructor
:param opt_problem: the optimization problem to run
"""
self.opt_problem = opt_problem
self.database = opt_problem.database
cls_name = self.__class__.__name__
name = cls_name + "_options"
f_class = inspect.getfile(self.__class__)
comp_dir = abspath(dirname(f_class))
schema_file = join(comp_dir, name + ".json")
if not exists(schema_file):
schema_file = join(comp_dir, "options", name + ".json")
if not exists(schema_file):
raise ValueError(
"Options grammar for optimization "
+ " post processor does not exists"
+ ", expected: "
+ str(schema_file)
+ "or: "
+ str(join(comp_dir, name + ".json"))
)
self.opt_grammar = JSONGrammar(name, schema_file=schema_file)
if hasattr(self.__class__, "_plot"):
descr_opts = SourceParsing.get_options_doc(
self.__class__._plot
) # pylint: disable=E1101
self.opt_grammar.add_description(descr_opts)
if hasattr(self.__class__, "_run"):
descr_opts = SourceParsing.get_options_doc(self.__class__._run)
self.opt_grammar.add_description(descr_opts)
# the data dict to eventually rebuild the plot in another framework
self.out_data_dict = {}
# Store output files generated by the post processing
self.output_files = []
[docs] def execute(self, **options):
"""
Executes the post processing
:param options: options dict, see associated JSON file
"""
self.check_options(**options)
if not self.opt_problem.database:
raise ValueError(
"Optimization problem was not solved,"
+ " cannot run post processing "
+ str(self.__class__.__name__)
)
self._run(**options)
[docs] def check_options(self, **options):
"""
Checks the options of the post processor
:param options: options dict, see associated JSON file
"""
try:
self.opt_grammar.load_data(options)
except InvalidDataException:
name = self.__class__.__name__
raise InvalidDataException(
"Invalid options for post processing " + name + " got : " + str(options)
)
def _run(self, **options):
"""Visualizes the optimization history
:param options: options of the plot,
see associated JSON file
"""
self._plot(**options)
def _plot(self, **options):
"""Visualizers
:param options: options dict, see associated JSON file
"""
raise NotImplementedError()
def _save_and_show(self, fig, file_path, save=True, show=False, extension="pdf"):
"""
Saves figures and or shows it depending on options
:param fig: matplotlib figure
:param file_path: file path to save the plot. If it does not end with
the specified extension, the extension is replaced
:param save: save the figure (default: True)
:param show: show the figure (default: False)
:param extension: file extension (default: 'pdf')
"""
matplotlib.rcParams.update({"font.size": 10})
if save:
if not file_path.endswith(extension):
basen = splitext(file_path)[0]
file_path = basen + "." + extension
fig.savefig(file_path, bbox_inches="tight")
self.output_files.append(file_path)
if show:
try:
pylab.plt.show(fig)
except TypeError:
pylab.plt.show()