Source code for geos_posp.visu.pythonViewUtils.Figure2DGenerator
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
# SPDX-FileContributor: Alexandre Benedicto
from typing import Any
import pandas as pd # type: ignore[import-untyped]
from geos.utils.Logger import Logger, getLogger
from matplotlib import axes, figure, lines # type: ignore[import-untyped]
from matplotlib.font_manager import ( # type: ignore[import-untyped]
FontProperties, # type: ignore[import-untyped]
)
from typing_extensions import Self
import geos_posp.visu.pythonViewUtils.functionsFigure2DGenerator as fcts
[docs]
class Figure2DGenerator:
def __init__( self: Self, dataframe: pd.DataFrame, userChoices: dict[ str, list[ str ] ] ) -> None:
"""Utility to create cross plots using Python View.
We want to plot f(X) = Y where in this class,
"X" will be called "variable", "Y" will be called "curves".
Args:
dataframe (pd.DataFrame): data to plot
userChoices (dict[str, list[str]]): user choices.
"""
self.m_dataframe: pd.DataFrame = dataframe
self.m_userChoices: dict[ str, Any ] = userChoices
self.m_fig: figure.Figure
self.m_axes: list[ axes._axes.Axes ] = []
self.m_lines: list[ lines.Line2D ] = []
self.m_labels: list[ str ] = []
self.m_logger: Logger = getLogger( "Python View Configurator" )
try:
# apply minus 1 multiplication on certain columns
self.initMinus1Multiplication()
# defines m_fig, m_axes, m_lines and m_lables
self.plotInitialFigure()
# then to edit and customize the figure
self.enhanceFigure()
self.m_logger.info( "Data were successfully plotted." )
except Exception as e:
mess: str = "Plot creation failed due to:"
self.m_logger.critical( mess )
self.m_logger.critical( e, exc_info=True )
[docs]
def initMinus1Multiplication( self: Self ) -> None:
"""Multiply by -1 certain columns of the input dataframe."""
df: pd.DataFrame = self.m_dataframe.copy( deep=True )
minus1CurveNames: list[ str ] = self.m_userChoices[ "curveConvention" ]
for name in minus1CurveNames:
df[ name ] = df[ name ] * ( -1 )
self.m_dataframe = df
[docs]
def enhanceFigure( self: Self ) -> None:
"""Apply all the enhancement features to the initial figure."""
self.changeTitle()
self.changeMinorticks()
self.changeAxisScale()
self.changeAxisLimits()
[docs]
def plotInitialFigure( self: Self ) -> None:
"""Generates a figure and axes objects from matplotlib.
The figure plots all the curves along the X or Y axis, with legend and
label for X and Y.
"""
if self.m_userChoices[ "plotRegions" ]:
if not self.m_userChoices[ "reverseXY" ]:
( fig, ax_all, lines, labels ) = fcts.multipleSubplots( self.m_dataframe, self.m_userChoices )
else:
( fig, ax_all, lines, labels ) = fcts.multipleSubplotsInverted( self.m_dataframe, self.m_userChoices )
else:
if not self.m_userChoices[ "reverseXY" ]:
( fig, ax_all, lines, labels ) = fcts.oneSubplot( self.m_dataframe, self.m_userChoices )
else:
( fig, ax_all, lines, labels ) = fcts.oneSubplotInverted( self.m_dataframe, self.m_userChoices )
self.m_fig = fig
self.m_axes = ax_all
self.m_lines = lines
self.m_labels = labels
[docs]
def changeTitle( self: Self ) -> None:
"""Update title of the first axis of the figure based on user choices."""
if self.m_userChoices[ "displayTitle" ]:
title: str = self.m_userChoices[ "title" ]
fontTitle: FontProperties = fcts.buildFontTitle( self.m_userChoices )
self.m_fig.suptitle( title, fontproperties=fontTitle )
[docs]
def changeMinorticks( self: Self ) -> None:
"""Set the minorticks on or off for every axes."""
choice: bool = self.m_userChoices[ "minorticks" ]
if choice:
for ax in self.m_axes:
ax.minorticks_on()
else:
for ax in self.m_axes:
ax.minorticks_off()
[docs]
def changeAxisScale( self: Self ) -> None:
"""Set the minorticks on or off for every axes."""
for ax in self.m_axes:
if self.m_userChoices[ "logScaleX" ]:
ax.set_xscale( "log" )
if self.m_userChoices[ "logScaleY" ]:
ax.set_yscale( "log" )
[docs]
def changeAxisLimits( self: Self ) -> None:
"""Update axis limits."""
if self.m_userChoices[ "customAxisLim" ]:
for ax in self.m_axes:
xmin, xmax = ax.get_xlim()
if self.m_userChoices[ "limMinX" ] is not None:
xmin = self.m_userChoices[ "limMinX" ]
if self.m_userChoices[ "limMaxX" ] is not None:
xmax = self.m_userChoices[ "limMaxX" ]
ax.set_xlim( xmin, xmax )
ymin, ymax = ax.get_ylim()
if self.m_userChoices[ "limMinY" ] is not None:
ymin = self.m_userChoices[ "limMinY" ]
if self.m_userChoices[ "limMaxY" ] is not None:
ymax = self.m_userChoices[ "limMaxY" ]
ax.set_ylim( ymin, ymax )
[docs]
def getFigure( self: Self ) -> figure.Figure:
"""Acces the m_fig attribute.
Returns:
figure.Figure: Figure containing all the plots.
"""
return self.m_fig