diff --git a/geos-geomechanics/src/geos/geomechanics/model/MohrCircle.py b/geos-geomechanics/src/geos/geomechanics/model/MohrCircle.py index 228722ab..c664f83a 100644 --- a/geos-geomechanics/src/geos/geomechanics/model/MohrCircle.py +++ b/geos-geomechanics/src/geos/geomechanics/model/MohrCircle.py @@ -39,6 +39,7 @@ center: float = mohrCircle.getCircleCenter() """ +loggerTitle : str = "MohrCircle" class MohrCircle: diff --git a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py index 9e738556..0d5101e5 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py @@ -70,7 +70,7 @@ def fillPartialAttributes( """ # Check if an external logger is given. if logger is None: - logger = getLogger( "fillPartialAttributes", True ) + logger = getLogger( "fillPartialAttributes") # Check if the input mesh is inherited from vtkMultiBlockDataSet. if not isinstance( multiBlockDataSet, vtkMultiBlockDataSet ): @@ -161,7 +161,7 @@ def fillAllPartialAttributes( """ # Check if an external logger is given. if logger is None: - logger = getLogger( "fillAllPartialAttributes", True ) + logger = getLogger( "fillAllPartialAttributes") # Check if the input mesh is inherited from vtkMultiBlockDataSet. if not isinstance( multiBlockDataSet, vtkMultiBlockDataSet ): @@ -252,7 +252,7 @@ def createConstantAttribute( """ # Check if an external logger is given. if logger is None: - logger = getLogger( "createConstantAttribute", True ) + logger = getLogger( "createConstantAttribute") # Deals with multiBlocksDataSets. if isinstance( mesh, ( vtkMultiBlockDataSet, vtkCompositeDataSet ) ): @@ -353,7 +353,7 @@ def createAttribute( """ # Check if an external logger is given. if logger is None: - logger = getLogger( "createAttribute", True ) + logger = getLogger( "createAttribute") # Check the piece. if piece not in [ Piece.POINTS, Piece.CELLS ]: @@ -458,7 +458,7 @@ def copyAttribute( """ # Check if an external logger is given. if logger is None: - logger = getLogger( "copyAttribute", True ) + logger = getLogger( "copyAttribute") if isinstance( meshTo, vtkDataSet ) and isinstance( meshFrom, vtkDataSet ): # Small check to check if the two meshes are similar. @@ -578,8 +578,8 @@ def transferAttributeWithElementMap( AttributeError: Error with the attribute attributeName. """ # Check if an external logger is given. - if logger is None: - logger = getLogger( "transferAttributeWithElementMap", True ) + if logger is None:# + logger = getLogger( "transferAttributeWithElementMap") # Check the piece. if piece not in [ Piece.POINTS, Piece.CELLS ]: diff --git a/geos-processing/pyproject.toml b/geos-processing/pyproject.toml index 743e3eb6..cd1e9732 100644 --- a/geos-processing/pyproject.toml +++ b/geos-processing/pyproject.toml @@ -19,6 +19,7 @@ maintainers = [ {name = "Alexandre Benedicto", email = "alexandre.benedicto@external.totalenergies.com" }, {name = "Romain Baville", email = "romain.baville@external.totalenergies.com" }, {name = "Paloma Martinez", email = "paloma.martinez@external.totalenergies.com" }, + {name = "Jacques Franc", email = "jacques.franc@external.totalenergies.com" }, ] license = {text = "Apache-2.0"} classifiers = [ diff --git a/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py b/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py index 03640096..8605d843 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py @@ -4,7 +4,6 @@ # ruff: noqa: E402 # disable Module level import not at top of file import numpy as np import numpy.typing as npt -import logging from typing_extensions import Self, Union from vtkmodules.vtkCommonDataModel import vtkDataSet, vtkMultiBlockDataSet from geos.mesh.utils.arrayModifiers import transferAttributeWithElementMap @@ -43,21 +42,15 @@ attributeNames: set[ str ] # Optional inputs. piece: Piece # defaults to Piece.CELLS - speHandler: bool # defaults to False # Instantiate the filter attributeMappingFilter: AttributeMapping = AttributeMapping( meshFrom, meshTo, attributeNames, - piece, - speHandler, + onPoints, ) - # Set the handler of yours (only if speHandler is True). - yourHandler: logging.Handler - attributeMappingFilter.setLoggerHandler( yourHandler ) - # Do calculations. try: attributeMappingFilter.applyFilter() @@ -79,7 +72,6 @@ def __init__( meshTo: Union[ vtkDataSet, vtkMultiBlockDataSet ], attributeNames: set[ str ], piece: Piece = Piece.CELLS, - speHandler: bool = False, ) -> None: """Transfer global attributes from a source mesh to a final mesh. @@ -102,40 +94,8 @@ def __init__( # Element map self.ElementMap: dict[ int, npt.NDArray[ np.int64 ] ] = {} - # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) - - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, - be sure to have at least the same 4 levels. - - Args: - handler (logging.Handler): The handler to add. - """ - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) + # Logger. + self.logger: Logger = getLogger( loggerTitle ) def getElementMap( self: Self ) -> dict[ int, npt.NDArray[ np.int64 ] ]: """Getter of the element mapping dictionary. diff --git a/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py b/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py index 94a269e2..1f7f91ef 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache 2.0 # SPDX-FileCopyrightText: Copyright 2023-2025 TotalEnergies # SPDX-FileContributor: Jacques Franc -import logging import numpy as np import numpy.typing as npt @@ -218,7 +217,7 @@ def __getFramePoints( self, vpts: vtkPoints ) -> tuple[ vtkPoints, vtkPoints ]: class ClipToMainFrame( vtkTransformFilter ): """Filter to clip a mesh to the main frame using ClipToMainFrame class.""" - def __init__( self, speHandler: bool = False, **properties: str ) -> None: + def __init__( self, **properties: str ) -> None: """Initialize the ClipToMainFrame Filter with optional speHandler args and forwarding properties to main class. Args: @@ -227,41 +226,8 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: properties (kwargs): kwargs forwarded to vtkTransformFilter. """ super().__init__( **properties ) - - # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) - - def Update( self ) -> None: # type: ignore[override] - """Update the filter.""" - super().Update() - - result: str = f"The filter { self.logger.name } succeeded" - if self.counter.warningCount > 0: - self.logger.warning( f"{ result } but { self.counter.warningCount } warnings have been logged." ) - else: - self.logger.info( f"{ result }." ) - - # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is applied again. - self.nbWarnings = self.counter.warningCount - self.counter.resetWarningCount() + # Logger. + self.logger: Logger = getLogger( loggerTitle ) def ComputeTransform( self ) -> None: """Update the transformation.""" @@ -284,20 +250,7 @@ def ComputeTransform( self ) -> None: clip.Update() self.SetTransform( clip ) - - def SetLoggerHandler( self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, - be sure to have at least the same 4 levels. - - Args: - handler (logging.Handler): The handler to add. - """ - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) + self.logger.info( f"{self.logger.name} applied successfully." ) def __locate_reference_point( self, multiBlockDataSet: vtkMultiBlockDataSet ) -> int: """Locate the block to use as reference for the transformation. diff --git a/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py b/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py index dd99317a..d6a96104 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py @@ -43,7 +43,6 @@ valueNpType: type nbComponents: int componentNames: tuple[ str, ... ] - speHandler: bool # Instantiate the filter createConstantAttributePerRegionFilter: CreateConstantAttributePerRegion = CreateConstantAttributePerRegion( @@ -54,7 +53,6 @@ valueNpType, nbComponents, componentNames, - speHandler, ) # Set your handler (only if speHandler is True). @@ -85,7 +83,6 @@ def __init__( valueNpType: type = np.float32, nbComponents: int = 1, componentNames: tuple[ str, ...] = (), # noqa: C408 - speHandler: bool = False, ) -> None: """Create an attribute with constant value per region. @@ -120,41 +117,14 @@ def __init__( # Check if the new component have default values (information for the output message). self.useDefaultValue: bool = False - # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) + # Logger. + self.logger: Logger = getLogger( loggerTitle ) # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + # Add the handler to count warnings messages. self.logger.addHandler( self.counter ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, - be sure to have at least the same 4 levels. - - Args: - handler (logging.Handler): The handler to add. - """ - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) - def applyFilter( self: Self ) -> None: """Create a constant attribute per region in the mesh. diff --git a/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py b/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py index 5a468396..767bdfa2 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py @@ -5,11 +5,11 @@ from typing_extensions import Self from typing import Union, Any -from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import getLogger from geos.mesh.utils.arrayModifiers import fillPartialAttributes from geos.mesh.utils.arrayHelpers import getAttributePieceInfo +# from geos.utils.details import addLogSupport from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet __doc__ = """ @@ -68,7 +68,6 @@ def __init__( self: Self, multiBlockDataSet: vtkMultiBlockDataSet, dictAttributesValues: dict[ str, Union[ list[ Any ], None ] ], - speHandler: bool = False, ) -> None: """Fill partial attributes with constant value per component. @@ -81,50 +80,13 @@ def __init__( Args: multiBlockDataSet (vtkMultiBlockDataSet): The mesh where to fill the attribute. - dictAttributesValues (dict[str, Any]): The dictionary with the attribute to fill as keys - and the list of filling values as values. - speHandler (bool, optional): True to use a specific handler, False to use the internal handler. - Defaults to False. + dictAttributesValues (dict[str, Any]): The dictionary with the attribute to fill as keys and the list of filling values as items. """ + self.logger = getLogger( loggerTitle ) self.multiBlockDataSet: vtkMultiBlockDataSet = multiBlockDataSet self.dictAttributesValues: dict[ str, Union[ list[ Any ], None ] ] = dictAttributesValues - # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) - - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, - be sure to have at least the same 4 levels. - - Args: - handler (logging.Handler): The handler to add. - """ - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) - - def applyFilter( self: Self ) -> None: + def applyFilter( self: Self ) -> bool: """Create a constant attribute per region in the mesh. Raise: diff --git a/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py b/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py index d482f6e6..1a5605a8 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py @@ -2,7 +2,6 @@ # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Paloma Martinez # ruff: noqa: E402 # disable Module level import not at top of file -import logging from typing_extensions import Self @@ -65,7 +64,6 @@ class MergeBlockEnhanced: def __init__( self: Self, inputMesh: vtkMultiBlockDataSet, - speHandler: bool = False, ) -> None: """Merge a multiblock dataset and keep the partial attributes in the output mesh. @@ -83,38 +81,7 @@ def __init__( self.outputMesh: vtkUnstructuredGrid = vtkUnstructuredGrid() # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) - - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, be sure to have at least the same 4 levels. - - Args: - handler (logging.Handler): The handler to add. - """ - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) + self.logger: Logger = getLogger( loggerTitle ) def applyFilter( self: Self ) -> None: """Merge the blocks of a multiblock dataset mesh. diff --git a/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py b/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py index 51afc7f5..84b10616 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Antoine Mazuyer, Martin Lemay -import logging import numpy as np import numpy.typing as npt from typing_extensions import Self @@ -53,12 +52,12 @@ outputMesh: vtkUnstructuredGrid = splitMeshFilter.getOutput() """ -loggerTitle: str = "Split Mesh" +loggerTitle: str = "SplitMesh" class SplitMesh(): - def __init__( self, inputMesh: vtkUnstructuredGrid, speHandler: bool = False ) -> None: + def __init__( self, inputMesh: vtkUnstructuredGrid ) -> None: """SplitMesh filter splits each cell using edge centers. Args: @@ -72,50 +71,11 @@ def __init__( self, inputMesh: vtkUnstructuredGrid, speHandler: bool = False ) - self.points: vtkPoints self.originalId: vtkIdTypeArray self.cellTypes: list[ int ] - self.speHandler: bool = speHandler - self.handler: None | logging.Handler = None + #subordonate filter + self.cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( self.inputMesh ) # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - handlers: list[ logging.Handler ] = self.logger.handlers - # Get the handler to specify if the logger already exist and has it - for handler in handlers: - # The CountVerbosityHandler can't be the handler to specify - if type( handler ) is not type( CountVerbosityHandler() ): - self.handler = handler - break - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) - - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, be sure to have at least the same 4 levels. - - Args: - handler (logging.Handler): The handler to add. - """ - self.handler = handler - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) + self.logger: Logger = getLogger( loggerTitle ) def applyFilter( self: Self ) -> None: """Apply the filter SplitMesh. @@ -212,16 +172,9 @@ def _getCellCounts( self: Self ) -> CellTypeCounts: Returns: CellTypeCounts: cell type counts """ - cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( - self.inputMesh, self.speHandler ) - if self.speHandler and not isHandlerInLogger( self.handler, cellTypeCounterEnhancedFilter.logger ): - cellTypeCounterEnhancedFilter.setLoggerHandler( self.handler ) - - cellTypeCounterEnhancedFilter.applyFilter() - # Add to the warning counter the number of warning logged with the call of CelltypeCounterEnhanced filter - self.counter.addExternalWarningCount( cellTypeCounterEnhancedFilter.nbWarnings ) - - return cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() + if not self.cellTypeCounterEnhancedFilter.applyFilter(): + raise + return self.cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() def _addMidPoint( self: Self, ptA: int, ptB: int ) -> int: """Add a point at the center of the edge defined by input point ids. diff --git a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py index 960ddfd5..c352d6da 100644 --- a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py +++ b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py @@ -76,15 +76,9 @@ # Define filter inputs mesh: vtkUnstructuredGrid computeAdvancedProperties: bool # optional, defaults to False - speHandler: bool # optional, defaults to False - loggerName: str # Defaults to "Geomechanics Calculator" # Instantiate the filter - geomechanicsCalculatorFilter: GeomechanicsCalculator = GeomechanicsCalculator( mesh, computeAdvancedProperties, speHandler ) - - # Use your own handler (if speHandler is True) - yourHandler: logging.Handler - geomechanicsCalculatorFilter.setLoggerHandler( yourHandler ) + geomechanicsCalculatorFilter: GeomechanicsCalculator = GeomechanicsCalculator( mesh, computeAdvancedProperties ) # Change the physical constants if needed ## For the basic properties @@ -170,6 +164,9 @@ ADVANCED_PROPERTIES: tuple[ AttributeEnum, ...] = ( CRITICAL_TOTAL_STRESS_RATIO, TOTAL_STRESS_RATIO_THRESHOLD, CRITICAL_PORE_PRESSURE, CRITICAL_PORE_PRESSURE_THRESHOLD ) + + +loggerTitle: str = "Geomechanics Calculator" class GeomechanicsCalculator: @@ -699,8 +696,6 @@ def __init__( self: Self, mesh: vtkUnstructuredGrid, computeAdvancedProperties: bool = False, - loggerName: str = "Geomechanics Calculator", - speHandler: bool = False, ) -> None: """VTK Filter to perform geomechanics properties computation. @@ -710,8 +705,6 @@ def __init__( Defaults to False. loggerName (str, optional): Name of the filter logger. Defaults to "Geomechanics Calculator". - speHandler (bool, optional): True to use a specific handler, False to use the internal handler. - Defaults to False. """ self.output: vtkUnstructuredGrid = mesh.NewInstance() self.output.DeepCopy( mesh ) @@ -726,25 +719,7 @@ def __init__( self._attributesToCreate: list[ AttributeEnum ] = [] # Logger. - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerName, True ) - else: - self.logger = logging.getLogger( loggerName ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) + self.logger: Logger = getLogger( loggerTitle ) def applyFilter( self: Self ) -> None: """Compute the geomechanics properties and create attributes on the mesh. diff --git a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py index 335ceeab..e8730f92 100644 --- a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py +++ b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py @@ -2,7 +2,6 @@ # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Martin Lemay, Paloma Martinez # ruff: noqa: E402 # disable Module level import not at top of file -import logging import numpy as np from typing_extensions import Self, Union @@ -92,12 +91,7 @@ class SurfaceGeomechanics: - def __init__( - self: Self, - surfacicMesh: vtkPolyData, - loggerName: str = "Surface Geomechanics", - speHandler: bool = False, - ) -> None: + def __init__( self: Self, surfacicMesh: vtkPolyData ) -> None: """Vtk filter to compute geomechanical surfacic attributes. Input and Output objects are a vtkPolydata with surfaces @@ -111,26 +105,12 @@ def __init__( Defaults to False. """ # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerName, True ) - else: - self.logger = logging.getLogger( loggerName ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) + self.logger: Logger = getLogger( loggerTitle ) + # Input surfacic mesh + print( surfacicMesh ) + if not surfacicMesh.IsA( "vtkPolyData" ): + self.logger.error( f"Input surface is expected to be a vtkPolyData, not a {type(surfacicMesh)}." ) self.inputMesh: vtkPolyData = surfacicMesh # Identification of the input surface (logging purpose) self.name: Union[ str, None ] = None @@ -151,18 +131,13 @@ def __init__( # New created attributes names self.newAttributeNames: set[ str ] = set() - def SetLoggerHandler( self: Self, handler: Logger ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, be sure to have at least the same 4 levels. + def SetSurfaceName( self: Self, name: str ) -> None: + """Set a name for the input surface. For logging purpose only. Args: - handler (logging.Handler): The handler to add. + name (str): The identifier for the surface. """ - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) + self.name = name def SetRockCohesion( self: Self, rockCohesion: float ) -> None: """Set rock cohesion value. Defaults to 0.0 Pa. diff --git a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py index 2e0eddcc..f1eedccc 100644 --- a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Antoine Mazuyer, Martin Lemay -import logging from typing_extensions import Self from vtkmodules.vtkCommonCore import vtkIntArray @@ -55,7 +54,6 @@ class CellTypeCounterEnhanced(): def __init__( self: Self, inputMesh: vtkUnstructuredGrid, - speHandler: bool = False, ) -> None: """CellTypeCounterEnhanced filter computes mesh stats. @@ -68,40 +66,8 @@ def __init__( self.outTable: vtkTable = vtkTable() self._counts: CellTypeCounts = CellTypeCounts() - # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) - - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, - be sure to have at least the same 4 levels. - - Args: - handler (logging.Handler): The handler to add. - """ - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) + # Logger. + self.logger: Logger = getLogger( loggerTitle ) def applyFilter( self: Self ) -> None: """Apply CellTypeCounterEnhanced filter. diff --git a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py index 6690fbb3..4e8209e5 100644 --- a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Antoine Mazuyer, Martin Lemay, Paloma Martinez -import logging import numpy as np import numpy.typing as npt from typing import Optional, cast @@ -102,13 +101,11 @@ class MeshQualityEnhanced(): def __init__( self: Self, inputMesh: vtkUnstructuredGrid, - speHandler: bool = False, ) -> None: """Enhanced vtkMeshQuality filter. Args: inputMesh (vtkUnstructuredGrid): Input mesh - speHandler (bool, optional): True to use a specific handler, False to use the internal handler. Defaults to False. """ self.inputMesh: vtkUnstructuredGrid = inputMesh @@ -131,51 +128,12 @@ def __init__( # Static members that can be loaded once to save computational times self._allCellTypesExtended: tuple[ int, ...] = getAllCellTypesExtended() self._allCellTypes: tuple[ int, ...] = getAllCellTypes() - self.speHandler: bool = speHandler - self.handler: logging.Handler - # Logger - self.logger: Logger - if not speHandler: - self.logger = getLogger( loggerTitle, True ) - else: - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.propagate = False - handlers: list[ logging.Handler ] = self.logger.handlers - # Get the handler to specify if the logger already exist and has it - for handler in handlers: - # The CountVerbosityHandler can't be the handler to specify - if type( handler ) is not type( CountVerbosityHandler() ): - self.handler = handler - break - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) - - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: - """Set a specific handler for the filter logger. - - In this filter 4 log levels are use, .info, .error, .warning and .critical, - be sure to have at least the same 4 levels. + #deps + self.cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( self._outputMesh ) - Args: - handler (logging.Handler): The handler to add. - """ - self.handler = handler - if not isHandlerInLogger( handler, self.logger ): - self.logger.addHandler( handler ) - else: - self.logger.warning( "The logger already has this handler, it has not been added." ) + # Logger. + self.logger: Logger = getLogger( loggerTitle ) def GetQualityMetricSummary( self: Self ) -> QualityMetricSummary: """Get QualityMetricSummary object. @@ -347,15 +305,12 @@ def _computeCellTypeCounts( self: Self ) -> None: cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( self._outputMesh, self.speHandler ) - if self.speHandler and not isHandlerInLogger( self.handler, cellTypeCounterEnhancedFilter.logger ): - cellTypeCounterEnhancedFilter.setLoggerHandler( self.handler ) - cellTypeCounterEnhancedFilter.applyFilter() # Add to the warning counter the number of warning logged with the call of CelltypeCounterEnhanced filter self.counter.addExternalWarningCount( cellTypeCounterEnhancedFilter.nbWarnings ) - counts: CellTypeCounts = cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() + counts: CellTypeCounts = self.cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() if counts is None: raise AttributeError( "CellTypeCounts is undefined" ) diff --git a/geos-pv/pyproject.toml b/geos-pv/pyproject.toml index 7a79bc45..a943ee65 100644 --- a/geos-pv/pyproject.toml +++ b/geos-pv/pyproject.toml @@ -9,7 +9,9 @@ description = "geos-pv is a Python package that gathers Paraview plugins and ded authors = [{name = "GEOS Contributors" }] maintainers = [{name = "Alexandre Benedicto", email = "alexandre.benedicto@external.totalenergies.com" }, {name = "Romain Baville", email = "romain.baville@external.totalenergies.com" }, - {name = "Paloma Martinez", email = "paloma.martinez@external.totalenergies.com" }] + {name = "Paloma Martinez", email = "paloma.martinez@external.totalenergies.com" }, + {name = "Jacques Franc", email = "jacques.franc@external.totalenergies.com" }, + ] license = {text = "Apache-2.0"} classifiers = [ "Development Status :: 4 - Beta", diff --git a/geos-pv/src/geos/pv/plugins/generic_processing/PVAttributeMapping.py b/geos-pv/src/geos/pv/plugins/generic_processing/PVAttributeMapping.py index 20c29a0b..cdc9015c 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVAttributeMapping.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVAttributeMapping.py @@ -15,13 +15,11 @@ update_paths() -from geos.processing.generic_processing_tools.AttributeMapping import AttributeMapping - +from geos.processing.generic_processing_tools.AttributeMapping import AttributeMapping, loggerTitle +from geos.utils.Logger import addPluginLogSupport from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy ) -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py + VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy, +) from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector from vtkmodules.vtkCommonDataModel import vtkCompositeDataSet, vtkDataSet, vtkMultiBlockDataSet @@ -69,6 +67,7 @@ dataTypes=[ "vtkDataSet", "vtkMultiBlockDataSet" ], composite_data_supported=True, ) +@addPluginLogSupport( loggerTitles=[ loggerTitle ] ) class PVAttributeMapping( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -190,10 +189,6 @@ def RequestData( attributeMappingFilter: AttributeMapping = AttributeMapping( meshFrom, outData, set( self.attributeNames ), self.piece, True ) - - if not isHandlerInLogger( HANDLER, attributeMappingFilter.logger ): - attributeMappingFilter.setLoggerHandler( HANDLER ) - try: attributeMappingFilter.applyFilter() except ( ValueError, AttributeError ) as e: diff --git a/geos-pv/src/geos/pv/plugins/generic_processing/PVClipToMainFrame.py b/geos-pv/src/geos/pv/plugins/generic_processing/PVClipToMainFrame.py index 3461b134..28aad654 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVClipToMainFrame.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVClipToMainFrame.py @@ -6,10 +6,9 @@ import logging from pathlib import Path -from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] + VTKPythonAlgorithmBase, +) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet @@ -21,8 +20,8 @@ update_paths() from geos.pv.utils.details import ( SISOFilter, FilterCategory ) -from geos.processing.generic_processing_tools.ClipToMainFrame import ClipToMainFrame -from geos.utils.Logger import isHandlerInLogger +from geos.processing.generic_processing_tools.ClipToMainFrame import ClipToMainFrame, loggerTitle, getLogger +from geos.utils.Logger import Logger, addPluginLogSupport __doc__ = f""" Clip the input mesh to the main frame applying the correct LandmarkTransform @@ -36,20 +35,16 @@ """ -HANDLER: logging.Handler = VTKHandler() - - @SISOFilter( category=FilterCategory.GENERIC_PROCESSING, decoratedLabel="Clip to the main frame", decoratedType=[ "vtkMultiBlockDataSet", "vtkDataSet" ] ) +@addPluginLogSupport( loggerTitles=[ loggerTitle ] ) class PVClipToMainFrame( VTKPythonAlgorithmBase ): def __init__( self ) -> None: """Init motherclass, filter and logger.""" - self._realFilter = ClipToMainFrame( speHandler=True ) - - if not isHandlerInLogger( HANDLER, self._realFilter.logger ): - self._realFilter.SetLoggerHandler( HANDLER ) + self._realFilter = ClipToMainFrame() + self.logger: Logger = getLogger( loggerTitle ) def ApplyFilter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBlockDataSet ) -> None: """Is applying clipToMainFrame filter. @@ -59,6 +54,8 @@ def ApplyFilter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBloc outputMesh : A mesh transformed. """ # struct + self.logger.info( f"Applying plugin {self.logger.name}." ) + self._realFilter.SetInputData( inputMesh ) self._realFilter.ComputeTransform() self._realFilter.Update() diff --git a/geos-pv/src/geos/pv/plugins/generic_processing/PVCreateConstantAttributePerRegion.py b/geos-pv/src/geos/pv/plugins/generic_processing/PVCreateConstantAttributePerRegion.py index bb8973aa..8d85bb88 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVCreateConstantAttributePerRegion.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVCreateConstantAttributePerRegion.py @@ -10,10 +10,9 @@ from typing import Any from typing_extensions import Self -from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] + VTKPythonAlgorithmBase, smdomain, smproperty, +) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py import vtkmodules.util.numpy_support as vnp from vtkmodules.vtkCommonDataModel import vtkDataSet @@ -25,9 +24,8 @@ update_paths() -from geos.processing.generic_processing_tools.CreateConstantAttributePerRegion import CreateConstantAttributePerRegion -from geos.pv.utils.details import ( SISOFilter, FilterCategory ) -from geos.utils.Logger import isHandlerInLogger +from geos.processing.generic_processing_tools.CreateConstantAttributePerRegion import CreateConstantAttributePerRegion, loggerTitle +from geos.utils.Logger import addPluginLogSupport __doc__ = f""" PVCreateConstantAttributePerRegion is a Paraview plugin that allows to create an attribute @@ -50,12 +48,11 @@ """ -HANDLER: logging.Handler = VTKHandler() - @SISOFilter( category=FilterCategory.GENERIC_PROCESSING, decoratedLabel="Create Constant Attribute Per Region", decoratedType=[ "vtkMultiBlockDataSet", "vtkDataSet" ] ) +@addPluginLogSupport( loggerTitles=[ loggerTitle ] ) class PVCreateConstantAttributePerRegion( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -72,9 +69,6 @@ def __init__( self: Self ) -> None: self.nbComponents: int = 1 self.componentNames: tuple[ str, ...] = () - # Use the handler of paraview for the log. - self.speHandler: bool = True - # Settings of the attribute with the region indexes: @smproperty.stringvector( name="ChooseRegionAttribute", @@ -290,12 +284,8 @@ def ApplyFilter( self, inputMesh: vtkDataSet, outputMesh: vtkDataSet ) -> None: self.valueNpType, self.nbComponents, self.componentNames, - self.speHandler, ) - if not isHandlerInLogger( HANDLER, createConstantAttributePerRegionFilter.logger ): - createConstantAttributePerRegionFilter.setLoggerHandler( HANDLER ) - try: createConstantAttributePerRegionFilter.applyFilter() except ( ValueError, AttributeError ) as e: diff --git a/geos-pv/src/geos/pv/plugins/generic_processing/PVFillPartialArrays.py b/geos-pv/src/geos/pv/plugins/generic_processing/PVFillPartialArrays.py index 4a6e27d2..1f0449bc 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVFillPartialArrays.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVFillPartialArrays.py @@ -8,12 +8,11 @@ from typing import Any, Optional, Union from typing_extensions import Self -from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smproperty # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py - -from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet +from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] + VTKPythonAlgorithmBase, smproperty, +) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from vtkmodules.vtkCommonDataModel import ( + vtkMultiBlockDataSet, ) # update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent.parent @@ -22,9 +21,10 @@ update_paths() -from geos.utils.Logger import isHandlerInLogger -from geos.pv.utils.details import ( SISOFilter, FilterCategory ) -from geos.processing.generic_processing_tools.FillPartialArrays import FillPartialArrays +from geos.pv.utils.details import SISOFilter, FilterCategory +from geos.processing.generic_processing_tools.FillPartialArrays import FillPartialArrays, loggerTitle + +from geos.utils.Logger import addPluginLogSupport __doc__ = f""" Fill partial arrays of input mesh. @@ -41,12 +41,10 @@ """ -HANDLER: logging.Handler = VTKHandler() - - @SISOFilter( category=FilterCategory.GENERIC_PROCESSING, decoratedLabel="Fill Partial Arrays", decoratedType="vtkMultiBlockDataSet" ) +@addPluginLogSupport( loggerTitles=[ loggerTitle ] ) class PVFillPartialArrays( VTKPythonAlgorithmBase ): def __init__( self: Self, ) -> None: @@ -106,12 +104,8 @@ def ApplyFilter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBloc fillPartialArraysFilter: FillPartialArrays = FillPartialArrays( outputMesh, self.dictAttributesValues, - speHandler=True, ) - if not isHandlerInLogger( HANDLER, fillPartialArraysFilter.logger ): - fillPartialArraysFilter.setLoggerHandler( HANDLER ) - try: fillPartialArraysFilter.applyFilter() except ( ValueError, AttributeError ) as e: diff --git a/geos-pv/src/geos/pv/plugins/generic_processing/PVMergeBlocksEnhanced.py b/geos-pv/src/geos/pv/plugins/generic_processing/PVMergeBlocksEnhanced.py index 33017052..aff9818a 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVMergeBlocksEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVMergeBlocksEnhanced.py @@ -9,13 +9,17 @@ from typing_extensions import Self from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy ) -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py - -from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector -from vtkmodules.vtkCommonDataModel import vtkCompositeDataSet, vtkMultiBlockDataSet, vtkUnstructuredGrid + VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy, +) +from vtkmodules.vtkCommonCore import ( + vtkInformation, + vtkInformationVector, +) +from vtkmodules.vtkCommonDataModel import ( + vtkCompositeDataSet, + vtkMultiBlockDataSet, + vtkUnstructuredGrid, +) # Update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent.parent @@ -24,10 +28,8 @@ update_paths() -from geos.processing.generic_processing_tools.MergeBlockEnhanced import MergeBlockEnhanced -from geos.utils.Errors import VTKError -from geos.utils.Logger import isHandlerInLogger -from geos.pv.utils.details import FilterCategory +from geos.processing.generic_processing_tools.MergeBlockEnhanced import MergeBlockEnhanced, loggerTitle +from geos.utils.Logger import addPluginLogSupport __doc__ = f""" Merge Blocks Keeping Partial Attributes is a Paraview plugin filter that allows to merge blocks from a multiblock dataset while keeping partial attributes. @@ -53,13 +55,12 @@ - nan for float data. """ -HANDLER: logging.Handler = VTKHandler() - @smproxy.filter( name="PVMergeBlocksEnhanced", label="Merge Blocks Keeping Partial Attributes" ) @smhint.xml( f'' ) @smproperty.input( name="Input", port_index=0, label="Input" ) @smdomain.datatype( dataTypes=[ "vtkMultiBlockDataSet" ], composite_data_supported=True ) +@addPluginLogSupport( loggerTitles=[ loggerTitle, f"{loggerTitle}.vtkErrorLogger" ] ) class PVMergeBlocksEnhanced( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -117,10 +118,7 @@ def RequestData( assert inputMesh is not None, "Input mesh is null." assert outputMesh is not None, "Output pipeline is null." - mergeBlockEnhancedFilter: MergeBlockEnhanced = MergeBlockEnhanced( inputMesh, True ) - - if not isHandlerInLogger( HANDLER, mergeBlockEnhancedFilter.logger ): - mergeBlockEnhancedFilter.setLoggerHandler( HANDLER ) + mergeBlockEnhancedFilter: MergeBlockEnhanced = MergeBlockEnhanced( inputMesh ) try: mergeBlockEnhancedFilter.applyFilter() diff --git a/geos-pv/src/geos/pv/plugins/generic_processing/PVSplitMesh.py b/geos-pv/src/geos/pv/plugins/generic_processing/PVSplitMesh.py index 7a3b15d5..389d4fd4 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVSplitMesh.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVSplitMesh.py @@ -8,9 +8,6 @@ from typing_extensions import Self from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py from vtkmodules.vtkCommonDataModel import vtkPointSet @@ -21,9 +18,10 @@ update_paths() -from geos.processing.generic_processing_tools.SplitMesh import SplitMesh -from geos.utils.Logger import isHandlerInLogger +from geos.processing.generic_processing_tools.SplitMesh import ( SplitMesh, loggerTitle ) +from geos.processing.pre_processing.CellTypeCounterEnhanced import loggerTitle as cloggerTitle from geos.pv.utils.details import ( SISOFilter, FilterCategory ) +from geos.utils.Logger import addPluginLogSupport __doc__ = f""" Split each cell of input mesh to smaller cells. @@ -39,10 +37,9 @@ """ -HANDLER: logging.Handler = VTKHandler() - -@SISOFilter( category=FilterCategory.GENERIC_PROCESSING, decoratedLabel="Split Mesh", decoratedType="vtkPointSet" ) +@SISOFilter( category=FilterCategory.GEOS_UTILS, decoratedLabel="Split Mesh", decoratedType="vtkPointSet" ) +@addPluginLogSupport( loggerTitles=[ loggerTitle, cloggerTitle ] ) class PVSplitMesh( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -55,9 +52,7 @@ def ApplyFilter( self: Self, inputMesh: vtkPointSet, outputMesh: vtkPointSet ) - inputMesh(vtkPointSet): Input mesh. outputMesh: Output mesh. """ - splitMeshFilter: SplitMesh = SplitMesh( inputMesh, True ) - if not isHandlerInLogger( HANDLER, splitMeshFilter.logger ): - splitMeshFilter.setLoggerHandler( HANDLER ) + splitMeshFilter: SplitMesh = SplitMesh( inputMesh ) try: splitMeshFilter.applyFilter() diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py index e93c707e..f9fd90a0 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py @@ -9,10 +9,9 @@ from pathlib import Path from typing_extensions import Self -from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] + VTKPythonAlgorithmBase, smdomain, smproperty +) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid, vtkMultiBlockDataSet @@ -27,8 +26,9 @@ from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_GRAIN_BULK_MODULUS, DEFAULT_ROCK_COHESION, WATER_DENSITY ) from geos.mesh.utils.multiblockHelpers import ( getBlockElementIndexesFlatten, getBlockNameFromIndex ) -from geos.processing.post_processing.GeomechanicsCalculator import GeomechanicsCalculator +from geos.processing.post_processing.GeomechanicsCalculator import GeomechanicsCalculator, loggerTitle from geos.pv.utils.details import ( SISOFilter, FilterCategory ) +from geos.utils.Logger import addPluginLogSupport __doc__ = f""" PVGeomechanicsCalculator is a paraview plugin that allows to compute additional geomechanics properties from existing ones in the mesh. @@ -81,6 +81,7 @@ @SISOFilter( category=FilterCategory.GEOS_POST_PROCESSING, decoratedLabel="GEOS Geomechanics Calculator", decoratedType=[ "vtkUnstructuredGrid", "vtkMultiBlockDataSet" ] ) +@addPluginLogSupport( loggerTitles=[ loggerTitle ] ) class PVGeomechanicsCalculator( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -264,18 +265,39 @@ def ApplyFilter( geomechanicsCalculatorFilter = GeomechanicsCalculator( outputMesh, self.computeAdvancedProperties, - loggerName="Geomechanics Calculators on the unstructured grid", - speHandler=True, ) - if not isHandlerInLogger( HANDLER, geomechanicsCalculatorFilter.logger ): - geomechanicsCalculatorFilter.setLoggerHandler( HANDLER ) + # if not geomechanicsCalculatorFilter.logger.hasHandlers(): + # geomechanicsCalculatorFilter.setLoggerHandler( GEOSHandler() ) geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus geomechanicsCalculatorFilter.physicalConstants.specificDensity = self.specificDensity geomechanicsCalculatorFilter.physicalConstants.rockCohesion = self.rockCohesion geomechanicsCalculatorFilter.physicalConstants.frictionAngle = self.frictionAngle + geomechanicsCalculatorFilter.applyFilter() + outputMesh.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) + elif isinstance( outputMesh, vtkMultiBlockDataSet ): + volumeBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( outputMesh ) + for blockIndex in volumeBlockIndexes: + volumeBlock: vtkUnstructuredGrid = vtkUnstructuredGrid.SafeDownCast( + outputMesh.GetDataSet( blockIndex ) ) + # volumeBlockName: str = getBlockNameFromIndex( outputMesh, blockIndex ) + # filterName: str = f"Geomechanics Calculator for the block { volumeBlockName }" + + geomechanicsCalculatorFilter = GeomechanicsCalculator( + volumeBlock, + self.computeAdvancedProperties, + ) + + # if not geomechanicsCalculatorFilter.logger.hasHandlers(): + # geomechanicsCalculatorFilter.setLoggerHandler( GEOSHandler() ) + + geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus + geomechanicsCalculatorFilter.physicalConstants.specificDensity = self.specificDensity + geomechanicsCalculatorFilter.physicalConstants.rockCohesion = self.rockCohesion + geomechanicsCalculatorFilter.physicalConstants.frictionAngle = self.frictionAngle + try: geomechanicsCalculatorFilter.applyFilter() # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py index 6ead0b62..939f59cb 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py @@ -29,9 +29,8 @@ from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] VTKPythonAlgorithmBase, smdomain, smproperty, smproxy ) -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py + +from geos.utils.Logger import GEOSHandler __doc__ = f""" PVGeomechanicsWorkflow is a Paraview plugin that executes multiple plugins: @@ -141,8 +140,7 @@ def __init__( self: Self ) -> None: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) - self.logger.addHandler( HANDLER ) - self.logger.propagate = False + self.logger.addHandler( GEOSHandler() ) counter: CountVerbosityHandler = CountVerbosityHandler() self.counter: CountVerbosityHandler diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py index cdcfe8b0..a9e59690 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py @@ -36,9 +36,7 @@ from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] VTKPythonAlgorithmBase, smdomain, smproperty, smproxy ) -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from geos.utils.Logger import GEOSHandler __doc__ = f""" PVGeosBlockExtractAndMerge is a Paraview plugin processing the input mesh at the current time in two steps: @@ -132,7 +130,7 @@ def __init__( self: Self ) -> None: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) - self.logger.addHandler( HANDLER ) + self.logger.addHandler( GEOSHandler() ) self.logger.propagate = False counter: CountVerbosityHandler = CountVerbosityHandler() diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py index e99812d0..802f1922 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py @@ -11,6 +11,12 @@ import numpy as np import numpy.typing as npt +from paraview.simple import ( # type: ignore[import-not-found] + Render, ) +from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] + VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy, +) + from paraview.simple import Render # type: ignore[import-not-found] from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] @@ -30,14 +36,17 @@ update_paths() -from geos.geomechanics.model.MohrCircle import MohrCircle -from geos.utils.pieceEnum import Piece -from geos.utils.Logger import CountVerbosityHandler +from geos.geomechanics.model.MohrCircle import MohrCircle, loggerTitle from geos.utils.enumUnits import Pressure, enumerationDomainUnit -from geos.utils.GeosOutputsConstants import ( FAILURE_ENVELOPE, GeosMeshOutputsEnum ) -from geos.utils.Logger import ( getLoggerHandlerType ) -from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_FRICTION_ANGLE_RAD, - DEFAULT_ROCK_COHESION ) +from geos.utils.GeosOutputsConstants import ( + FAILURE_ENVELOPE, + GeosMeshOutputsEnum, +) +from geos.utils.PhysicalConstants import ( + DEFAULT_FRICTION_ANGLE_DEG, + DEFAULT_FRICTION_ANGLE_RAD, + DEFAULT_ROCK_COHESION, +) from geos.mesh.utils.arrayHelpers import getArrayInObject import geos.pv.utils.mohrCircles.functionsMohrCircle as mcf @@ -47,7 +56,7 @@ from geos.pv.pyplotUtils.matplotlibOptions import ( FontStyleEnum, FontWeightEnum, LegendLocationEnum, LineStyleEnum, MarkerStyleEnum, OptionSelectionEnum, optionEnumToXml ) from geos.pv.utils.mohrCircles.functionsMohrCircle import StressConventionEnum -from geos.pv.utils.details import FilterCategory +from geos.utils.Logger import ( addPluginLogSupport, getLogger ) __doc__ = f""" PVMohrCirclePlot is a ParaView plugin that allows to compute and plot @@ -91,7 +100,6 @@ * The attribute 'CellId' has to be used for the 'Selection Labels'. """ -HANDLER: logging.Handler = VTKHandler() loggerTitle: str = "Mohr Circle" @@ -105,6 +113,7 @@ dataTypes=[ "vtkUnstructuredGrid" ], composite_data_supported=False, ) +@addPluginLogSupport( loggerTitles=[ loggerTitle ] ) class PVMohrCirclePlot( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -181,23 +190,7 @@ def __init__( self: Self ) -> None: # Request data processing step - incremented each time RequestUpdateExtent is called self.requestDataStep: int = -1 - - self.logger = logging.getLogger( loggerTitle ) - self.logger.setLevel( logging.INFO ) - self.logger.addHandler( HANDLER ) - self.logger.propagate = False - - counter: CountVerbosityHandler = CountVerbosityHandler() - self.counter: CountVerbosityHandler - self.nbWarnings: int = 0 - try: - self.counter = getLoggerHandlerType( type( counter ), self.logger ) - self.counter.resetWarningCount() - except ValueError: - self.counter = counter - self.counter.setLevel( logging.INFO ) - - self.logger.addHandler( self.counter ) + self.logger: Logger = getLogger( loggerTitle ) @smproperty.xml( """ ' ) @smproperty.input( name="Input", port_index=0 ) @@ -51,6 +45,7 @@ dataTypes=[ "vtkUnstructuredGrid" ], composite_data_supported=True, ) +@addPluginLogSupport( loggerTitles=[ loggerTitle ] ) class PVCellTypeCounterEnhanced( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -140,12 +135,8 @@ def RequestData( assert inputMesh is not None, "Input server mesh is null." assert outputTable is not None, "Output pipeline is null." - cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( inputMesh, True ) - if not isHandlerInLogger( HANDLER, cellTypeCounterEnhancedFilter.logger ): - cellTypeCounterEnhancedFilter.setLoggerHandler( HANDLER ) - - try: - cellTypeCounterEnhancedFilter.applyFilter() + cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( inputMesh ) + if cellTypeCounterEnhancedFilter.applyFilter(): outputTable.ShallowCopy( cellTypeCounterEnhancedFilter.getOutput() ) # print counts in Output Messages view @@ -158,14 +149,14 @@ def RequestData( with open( self._filename, 'w' ) as fout: fout.write( self._countsAll.print() ) cellTypeCounterEnhancedFilter.logger.info( f"File {self._filename} was successfully written." ) + + except TypeError as e: + cellTypeCounterEnhancedFilter.logger.error( + f"The filter { cellTypeCounterEnhancedFilter.logger.name } failed due to:\n{ e }" ) + except Exception as e: cellTypeCounterEnhancedFilter.logger.info( f"Error while exporting the file due to:\n{ e }" ) - except TypeError as e: - cellTypeCounterEnhancedFilter.logger.error( - f"The filter { cellTypeCounterEnhancedFilter.logger.name } failed due to:\n{ e }" ) - except Exception as e: - mess: str = f"The filter { cellTypeCounterEnhancedFilter.logger.name } failed due to:\n{ e }" - cellTypeCounterEnhancedFilter.logger.critical( mess, exc_info=True ) + return 1 diff --git a/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py b/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py index 2c00aadc..06629341 100644 --- a/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py @@ -8,8 +8,6 @@ from typing_extensions import Self, Optional from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] -# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py from vtkmodules.vtkCommonCore import vtkDataArraySelection @@ -23,7 +21,8 @@ update_paths() from geos.mesh.model.QualityMetricSummary import QualityMetricSummary -from geos.processing.pre_processing.MeshQualityEnhanced import MeshQualityEnhanced +from geos.processing.pre_processing.MeshQualityEnhanced import MeshQualityEnhanced, loggerTitle +from geos.processing.pre_processing.CellTypeCounterEnhanced import loggerTitle as cloggerTitle from geos.mesh.stats.meshQualityMetricHelpers import ( getQualityMetricsOther, getQualityMeasureNameFromIndex, getQualityMeasureIndexFromName, getQuadQualityMeasure, getTriangleQualityMeasure, getCommonPolygonQualityMeasure, @@ -33,7 +32,7 @@ from geos.pv.utils.checkboxFunction import createModifiedCallback # type: ignore[attr-defined] from geos.pv.utils.paraviewTreatments import getArrayChoices from geos.pv.utils.details import ( SISOFilter, FilterCategory ) -from geos.utils.Logger import isHandlerInLogger +from geos.utils.Logger import addPluginLogSupport, GEOSHandler __doc__ = f""" The ``Mesh Quality Enhanced`` filter computes requested mesh quality metrics on meshes. Both surfaces and volumic metrics can be computed with this plugin. @@ -60,8 +59,10 @@ HANDLER: logging.Handler = VTKHandler() - -@SISOFilter( category=FilterCategory.QC, decoratedLabel="Mesh Quality Enhanced", decoratedType="vtkUnstructuredGrid" ) +@SISOFilter( category=FilterCategory.QC, + decoratedLabel="Mesh Quality Enhanced", + decoratedType="vtkUnstructuredGrid" ) +@addPluginLogSupport( loggerTitles=[ loggerTitle, cloggerTitle ] ) class PVMeshQualityEnhanced( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: @@ -231,10 +232,7 @@ def ApplyFilter( self, inputMesh: vtkUnstructuredGrid, outputMesh: vtkUnstructur self._getQualityMetricsToUse( self._HexQualityMetric ) ) otherMetrics: set[ int ] = self._getQualityMetricsToUse( self._commonMeshQualityMetric ) - meshQualityEnhancedFilter: MeshQualityEnhanced = MeshQualityEnhanced( inputMesh, True ) - if not isHandlerInLogger( HANDLER, meshQualityEnhancedFilter.logger ): - meshQualityEnhancedFilter.setLoggerHandler( HANDLER ) - + meshQualityEnhancedFilter: MeshQualityEnhanced = MeshQualityEnhanced( inputMesh ) meshQualityEnhancedFilter.SetCellQualityMetrics( triangleMetrics=triangleMetrics, quadMetrics=quadMetrics, tetraMetrics=tetraMetrics, diff --git a/geos-pv/src/geos/pv/pythonViewUtils/Figure2DGenerator.py b/geos-pv/src/geos/pv/pythonViewUtils/Figure2DGenerator.py index f3d41fb4..cabae69b 100755 --- a/geos-pv/src/geos/pv/pythonViewUtils/Figure2DGenerator.py +++ b/geos-pv/src/geos/pv/pythonViewUtils/Figure2DGenerator.py @@ -119,7 +119,7 @@ def changeAxisLimits( self: Self ) -> None: ax.set_ylim( ymin, ymax ) def getFigure( self: Self ) -> figure.Figure: - """access the m_fig attribute. + """Access the m_fig attribute. Returns: figure.Figure: Figure containing all the plots. diff --git a/geos-pv/src/geos/pv/pythonViewUtils/functionsFigure2DGenerator.py b/geos-pv/src/geos/pv/pythonViewUtils/functionsFigure2DGenerator.py index 167d6d88..36a27d00 100755 --- a/geos-pv/src/geos/pv/pythonViewUtils/functionsFigure2DGenerator.py +++ b/geos-pv/src/geos/pv/pythonViewUtils/functionsFigure2DGenerator.py @@ -618,7 +618,8 @@ def propertiesPerIdentifier( propertyNames: list[ str ] ) -> dict[ str, list[ st Args: propertyNames (list[str]): Property names. - Example + + Example: .. code-block:: python @@ -631,7 +632,8 @@ def propertiesPerIdentifier( propertyNames: list[ str ] ) -> dict[ str, list[ st Returns: dict[str, list[str]]: Property identifiers. - Example + + Example: .. code-block:: python @@ -666,7 +668,8 @@ def associationIdentifiers( propertyNames: list[ str ] ) -> dict[ str, dict[ str Args: propertyNames (list[str]): Property names. - Example + + Example: .. code-block:: python @@ -695,7 +698,8 @@ def associationIdentifiers( propertyNames: list[ str ] ) -> dict[ str, dict[ str Returns: dict[str, dict[str, list[str]]]: Property identifiers. - Example + + Example: .. code-block:: python @@ -1306,7 +1310,6 @@ def findPhasesLabel( label: str ) -> list[ str ]: # if legendLabel.startswith(pattern): # return legendLabel[len(pattern):] # return legendLabel - """ Other 2D tools for simplest figures """ diff --git a/geos-pv/src/geos/pv/utils/paraviewTreatments.py b/geos-pv/src/geos/pv/utils/paraviewTreatments.py index 36aad6b1..72168ae4 100644 --- a/geos-pv/src/geos/pv/utils/paraviewTreatments.py +++ b/geos-pv/src/geos/pv/utils/paraviewTreatments.py @@ -13,8 +13,6 @@ from paraview.simple import ( # type: ignore[import-not-found] FindSource, GetActiveView, GetAnimationScene, GetDisplayProperties, GetSources, servermanager, ) -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, ) import vtkmodules.util.numpy_support as vnp from vtkmodules.vtkCommonCore import ( vtkDataArray, @@ -37,7 +35,7 @@ ComponentNameEnum, GeosMeshOutputsEnum, ) -from geos.utils.Logger import ( CustomLoggerFormatter ) +from geos.utils.Logger import ( GEOSFormatter, GEOSHandler ) from geos.mesh.utils.multiblockModifiers import mergeBlocks # valid sources for Python view configurator @@ -487,8 +485,8 @@ def getVtkOriginalCellIds( mesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSe logger = logging.getLogger( "getVtkOriginalCellIds" ) if not logger.hasHandlers(): - handler = VTKHandler() - handler.setFormatter( CustomLoggerFormatter( False ) ) + handler = GEOSHandler() + handler.setFormatter( GEOSFormatter() ) logger.addHandler( handler ) # Merge blocks for vtkCompositeDataSet diff --git a/geos-pv/src/geos/pv/utils/workflowFunctions.py b/geos-pv/src/geos/pv/utils/workflowFunctions.py index b48866bd..66516d40 100644 --- a/geos-pv/src/geos/pv/utils/workflowFunctions.py +++ b/geos-pv/src/geos/pv/utils/workflowFunctions.py @@ -10,7 +10,7 @@ from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet -from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +from geos.utils.Logger import GEOSHandler HANDLER: logging.Handler = VTKHandler() @@ -42,8 +42,8 @@ def doExtractAndMerge( extractFault=extractFault, extractWell=extractWell, speHandler=True ) - if not isHandlerInLogger( HANDLER, blockExtractor.logger ): - blockExtractor.setLoggerHandler( HANDLER ) + if not blockExtractor.logger.hasHandlers(): + blockExtractor.setLoggerHandler( GEOSHandler() ) try: blockExtractor.applyFilter() @@ -100,9 +100,9 @@ def mergeBlocksFilter( """ loggerName = f"GEOS Block Merge for the domain { domainToMerge }" mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( mesh, convertSurfaces, True, loggerName ) - if not isHandlerInLogger( HANDLER, mergeBlockFilter.logger ): - mergeBlockFilter.setLoggerHandler( HANDLER ) + if not mergeBlockFilter.logger.hasHandlers(): + mergeBlockFilter.setLoggerHandler( GEOSHandler() ) try: mergeBlockFilter.applyFilter() except ( ValueError, VTKError ) as e: diff --git a/geos-utils/pyproject.toml b/geos-utils/pyproject.toml index 4ce1f94f..1803cdec 100644 --- a/geos-utils/pyproject.toml +++ b/geos-utils/pyproject.toml @@ -17,7 +17,9 @@ description = "geos-utils is a Python package that gathers utilities common to a authors = [{name = "GEOS Contributors" }] maintainers = [{name = "Alexandre Benedicto", email = "alexandre.benedicto@external.totalenergies.com" }, {name = "Romain Baville", email = "romain.baville@external.totalenergies.com" }, - {name = "Paloma Martinez", email = "paloma.martinez@external.totalenergies.com" }] + {name = "Paloma Martinez", email = "paloma.martinez@external.totalenergies.com" }, + {name = "Jacques Franc", email = "jacques.franc@external.totalenergies.com" }, + ] license = {text = "Apache-2.0"} classifiers = [ "Development Status :: 4 - Beta", diff --git a/geos-utils/src/geos/utils/Logger.py b/geos-utils/src/geos/utils/Logger.py index b3846e94..2161863a 100644 --- a/geos-utils/src/geos/utils/Logger.py +++ b/geos-utils/src/geos/utils/Logger.py @@ -2,14 +2,17 @@ # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Martin Lemay, Romain Baville, Jacques Franc import logging -from typing import Any, Union, Generator +from typing import Any, Generator from typing_extensions import Self +from functools import wraps +from typing import Type, TypeVar, Callable import os import re import tempfile from contextlib import contextmanager +from vtkmodules.vtkCommonCore import vtkLogger from geos.utils.Errors import VTKError __doc__ = """ @@ -41,6 +44,36 @@ """ +## decorators +T = TypeVar( 'T' ) + + +def addPluginLogSupport( loggerTitles: list ) -> Callable[ [ Type[ T ] ], Type[ T ] ]: + """Decorator to add logger support in the class following existing architecture. + + Args: + loggerTitle (str): Title to display in the logger + """ + + def decorator( cls: Type[ T ] ) -> Type[ T ]: + original_init = cls.__init__ + + @wraps( original_init ) + def new_init( self: T, *args: Any, **kwargs: Any ) -> None: + original_init( self, *args, **kwargs ) + + for logger in loggerTitles: + for hdlr in list( filter( lambda x: not isinstance( x, GEOSHandler ), getLogger(logger).handlers ) ): + getLogger(logger).removeHandler( hdlr ) + + + + cls.__init__ = new_init # type: ignore[assignment] + + return cls + + return decorator + class RegexExceptionFilter( logging.Filter ): """Class to regexp VTK messages rethrown into logger by VTKCaptureLog. @@ -240,22 +273,8 @@ def results( self: logging.Logger, message: str, *args: Any, **kws: Any ) -> Non Logger = logging.Logger # logger type -class CustomLoggerFormatter( logging.Formatter ): - """Custom formatter for the logger. - - .. WARNING:: Colors do not work in the output message window of Paraview. - - To use it: +class GEOSFormatter( logging.Formatter ): - .. code-block:: python - - logger = logging.getLogger( "Logger name", use_color=False ) - # Ensure handler is added only once, e.g., by checking logger.handlers - if not logger.handlers: - ch = logging.StreamHandler() - ch.setFormatter(CustomLoggerFormatter()) - logger.addHandler(ch) - """ # define color codes green: str = "\x1b[32;20m" grey: str = "\x1b[38;20m" @@ -265,73 +284,75 @@ class CustomLoggerFormatter( logging.Formatter ): reset: str = "\x1b[0m" # define prefix of log messages - format1: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" - format2: str = ( "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" ) + format_short: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + format_long: str = ( "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" ) format_results: str = "%(name)s - %(levelname)s - %(message)s" - #: format for each logger output type with colors - FORMATS_COLOR: dict[ int, str ] = { - DEBUG: grey + format2 + reset, - INFO: green + format1 + reset, - WARNING: yellow + format1 + reset, - ERROR: red + format1 + reset, - CRITICAL: bold_red + format2 + reset, - RESULTS_LEVEL_NUM: green + format_results + reset, - } - #: format for each logger output type without colors (e.g., for Paraview) - FORMATS_PLAIN: dict[ int, str ] = { - DEBUG: format2, - INFO: format1, - WARNING: format1, - ERROR: format1, - CRITICAL: format2, - RESULTS_LEVEL_NUM: format_results, - } - - # Pre-compiled formatters for efficiency - _compiled_formatters: dict[ int, logging.Formatter ] = { - level: logging.Formatter( fmt ) - for level, fmt in FORMATS_PLAIN.items() + _formatDict: dict[ int, str ] = { + DEBUG: grey + format_long + reset, + INFO: green + format_short + reset, + WARNING: yellow + format_short + reset, + ERROR: red + format_short + reset, + CRITICAL: bold_red + format_long + reset, + RESULTS_LEVEL_NUM: green + format_results + reset, } - _compiled_color_formatters: dict[ int, logging.Formatter ] = { - level: logging.Formatter( fmt ) - for level, fmt in FORMATS_COLOR.items() - } + def format( self: Self, record: logging.LogRecord ) -> str: + """Fomat using the above described format in color and style.""" + return logging.Formatter( fmt=self._formatDict.get( record.levelno ) ).format( record ) + + @staticmethod + def TrimColor( msg: str ) -> str: + """Helper function to discard bash color tag when throwing to vtk logger logic (C/C++).""" + return msg[ 8:-4 ] + + +class GEOSHandler( logging.StreamHandler ): + + @staticmethod + def get_vtk_level( level: int ) -> int: + """Translate logging levels to vtk taxonomy.""" + if level >= ERROR: + return vtkLogger.VERBOSITY_ERROR + elif level >= WARNING: + return vtkLogger.VERBOSITY_WARNING + elif level >= INFO: + return vtkLogger.VERBOSITY_INFO + elif level >= DEBUG: + return vtkLogger.VERBOSITY_TRACE + else: + return vtkLogger.VERBOSITY_MAX - def __init__( self: Self, use_color: bool = False ) -> None: - """Initialize the log formatter. + def emit( self: Self, record: logging.LogRecord ) -> None: + """Overload of emit to display in the Command Output windows UI.""" + try: + msg = self.format( record ) + lvl = GEOSHandler.get_vtk_level( record.levelno ) - Args: - use_color (bool): If True, use color-coded log formatters. - Defaults to False. - """ - super().__init__() - if use_color: - self.active_formatters = self._compiled_color_formatters - else: - self.active_formatters = self._compiled_formatters + from vtkmodules.vtkCommonCore import vtkOutputWindow as win + outwin = win.GetInstance() + if outwin: + #see https://www.paraview.org/paraview-docs/v5.13.3/python/_modules/paraview/detail/loghandler.html#VTKHandler + prevMode = outwin.GetDisplayMode() + outwin.SetDisplayModeToNever() - def format( self: Self, record: logging.LogRecord ) -> str: - """Return the format according to input record. + if lvl == vtkLogger.VERBOSITY_ERROR: + outwin.DisplayErrorText( GEOSFormatter.TrimColor( msg ) ) + elif lvl == vtkLogger.VERBOSITY_WARNING: + outwin.DisplayWarningText( GEOSFormatter.TrimColor( msg ) ) + elif lvl == vtkLogger.VERBOSITY_INFO: + outwin.DisplayText( GEOSFormatter.TrimColor( msg ) ) + elif lvl == vtkLogger.VERBOSITY_TRACE: + outwin.DisplayDebugText( GEOSFormatter.TrimColor( msg ) ) - Args: - record (logging.LogRecord): record + outwin.SetDisplayMode( prevMode ) - Returns: - str: format as a string - """ - # Defaulting to plain formatters as per original logic - log_fmt_obj: Union[ logging.Formatter, None ] = self.active_formatters.get( record.levelno ) - if log_fmt_obj: - return log_fmt_obj.format( record ) - else: - # Fallback for unknown levels or if a level is missing in the map - return logging.Formatter().format( record ) + except Exception: + self.handleError( record ) -def getLogger( title: str, use_color: bool = False ) -> Logger: +def getLogger( title: str ) -> Logger: """Return the Logger with pre-defined configuration. This function is now idempotent regarding handler addition. @@ -367,13 +388,21 @@ def getLogger( title: str, use_color: bool = False ) -> Logger: logger = logging.getLogger( title ) # Only configure the logger (add handlers, set level) if it hasn't been configured before. if len( logger.handlers ) == 0: - logger.setLevel( INFO ) # Set the desired default level for this logger + logger.setLevel( DEBUG ) # Set the desired default level for this logger # Create and add the stream handler - ch = logging.StreamHandler() - ch.setFormatter( CustomLoggerFormatter( use_color ) ) # Use your custom formatter - logger.addHandler( ch ) + geos_handler = GEOSHandler() + geos_handler.setFormatter( GEOSFormatter() ) + geos_handler.setLevel( logger.getEffectiveLevel() ) + logger.addHandler( geos_handler ) + + cli_handle = logging.StreamHandler() + cli_handle.setFormatter( GEOSFormatter() ) + cli_handle.setLevel( logger.getEffectiveLevel() ) + logger.addHandler( cli_handle ) + # Optional: Prevent messages from propagating to the root logger's handlers - logger.propagate = False + logger.propagate = True + # If you need to ensure a certain level is set every time getLogger is called, # even if handlers were already present, you can set the level outside the 'if' block. # However, typically, setLevel is part of the initial handler configuration.