From a68bda1b16abed0ed0c82dd112a3a4affb14a786 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Wed, 28 Jan 2026 16:31:49 +0100 Subject: [PATCH 01/10] Update the log to get the number of warning --- .../AttributeMapping.py | 23 +++++++++------- .../ClipToMainFrame.py | 22 ++++++++++++++-- .../CreateConstantAttributePerRegion.py | 11 +++++--- .../FillPartialArrays.py | 26 ++++++++++++++++--- .../MergeBlockEnhanced.py | 14 ++++++++-- .../generic_processing_tools/SplitMesh.py | 18 ++++++++++--- 6 files changed, 91 insertions(+), 23 deletions(-) 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 1c8dbf401..170712209 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py @@ -9,7 +9,7 @@ from vtkmodules.vtkCommonDataModel import vtkDataSet, vtkMultiBlockDataSet from geos.mesh.utils.arrayModifiers import transferAttributeWithElementMap from geos.mesh.utils.arrayHelpers import ( computeElementMapping, getAttributeSet, isAttributeGlobal ) -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.utils.pieceEnum import Piece __doc__ = """ @@ -111,6 +111,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -147,6 +151,9 @@ def applyFilter( self: Self ) -> None: """ self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) + if len( self.attributeNames ) == 0: raise ValueError( "Please enter at least one attribute to transfer." ) @@ -185,13 +192,11 @@ def applyFilter( self: Self ) -> None: self.logger ) # Log the output message. - self._logOutputMessage() - - return - - def _logOutputMessage( self: Self ) -> None: - """Create and log result messages of the filter.""" - self.logger.info( f"The filter { self.logger.name } succeeded." ) self.logger.info( - f"The attributes { self.attributeNames } have been transferred from the source mesh to the final mesh with the { self.piece.value } mapping." + f"The attributes { self.attributeNames } have been transferred from the source mesh to the final mesh with a { self.piece.value } mapping.\n" ) + 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 }." ) 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 90a534111..8cd92c004 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py @@ -16,7 +16,7 @@ from vtkmodules.vtkCommonTransforms import vtkLandmarkTransform from vtkmodules.vtkFiltersGeneral import vtkTransformFilter -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.mesh.utils.genericHelpers import getMultiBlockBounds __doc__ = """ @@ -212,7 +212,7 @@ def __getFramePoints( self, vpts: vtkPoints ) -> tuple[ vtkPoints, vtkPoints ]: return ( sourcePts, targetPts ) -loggerTitle: str = "Clip mesh to main frame." +loggerTitle: str = "Clip mesh to main frame" class ClipToMainFrame( vtkTransformFilter ): @@ -236,8 +236,26 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + + 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 }." ) + def ComputeTransform( self ) -> None: """Update the transformation.""" + self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) + # dispatch to ClipToMainFrame depending on input type if isinstance( self.GetInput(), vtkMultiBlockDataSet ): # locate reference point 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 572f1f094..d2c0e4c1a 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py @@ -342,9 +342,6 @@ def _logOutputMessage( self: Self, trueIndexes: list[ Any ] ) -> None: Args: trueIndexes (list[Any]): The list of the true region indexes use to create the attribute. """ - # The Filter succeed. - self.logger.info( f"The filter { self.logger.name } succeeded." ) - # Info about the created attribute. # The piece where the attribute is created. self.logger.info( f"The new attribute { self.newAttributeName } is created on { self.piece.value }." ) @@ -409,3 +406,11 @@ def _logOutputMessage( self: Self, trueIndexes: list[ Any ] ) -> None: self.logger.warning( messValue ) else: self.logger.info( messValue ) + + 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 }." ) + + return 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 08b3356bf..1763fb929 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py @@ -6,7 +6,7 @@ from typing import Union, Any from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.mesh.utils.arrayModifiers import fillPartialAttributes from geos.mesh.utils.arrayHelpers import getAttributePieceInfo @@ -98,6 +98,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -121,8 +125,12 @@ def applyFilter( self: Self ) -> None: ValueError: Error during the filling of the attribute. """ self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) + piece: Piece - for attributeName in self.dictAttributesValues: + mess: str = "" + for attributeName, values in self.dictAttributesValues.items(): piece = getAttributePieceInfo( self.multiBlockDataSet, attributeName ) if piece == Piece.NONE: raise AttributeError( f"The attribute { attributeName } is not in the mesh." ) @@ -134,9 +142,19 @@ def applyFilter( self: Self ) -> None: fillPartialAttributes( self.multiBlockDataSet, attributeName, piece=piece, - listValues=self.dictAttributesValues[ attributeName ], + listValues=values, logger=self.logger ) + if values is None: + values = [ "the default value" ] + mess = f"{ mess }The attribute { attributeName } has been filled with { values }.\n" - self.logger.info( f"The filter { self.logger.name } succeed." ) + # Log the output message. + self.logger.info( mess ) + + 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 }." ) return 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 d44208265..416051bb5 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py @@ -6,7 +6,7 @@ from typing_extensions import Self -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.mesh.utils.multiblockModifiers import mergeBlocks from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkUnstructuredGrid @@ -91,6 +91,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -112,12 +116,18 @@ def applyFilter( self: Self ) -> None: VTKError (geos.utils.Errors): Errors captured if any from the VTK log. """ self.logger.info( f"Applying filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) outputMesh: vtkUnstructuredGrid outputMesh = mergeBlocks( self.inputMesh, keepPartialAttributes=True, logger=self.logger ) self.outputMesh = outputMesh - self.logger.info( f"The filter { self.logger.name } succeeded." ) + 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 }." ) return 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 bad8002ce..91f5ae55a 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py @@ -12,7 +12,7 @@ VTK_POLYHEDRON, VTK_POLYGON ) from vtkmodules.util.numpy_support import numpy_to_vtk, vtk_to_numpy -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.processing.pre_processing.CellTypeCounterEnhanced import CellTypeCounterEnhanced from geos.mesh.model.CellTypeCounts import CellTypeCounts @@ -84,6 +84,10 @@ def __init__( self, inputMesh: vtkUnstructuredGrid, speHandler: bool = False ) - self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -106,7 +110,10 @@ def applyFilter( self: Self ) -> None: TypeError: Errors due to objects with the wrong type. AttributeError: Errors with cell data. """ - self.logger.info( f"Applying filter { self.logger.name }." ) + self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) + # Count the number of cells before splitting. Then we will be able to know how many new cells and points # to allocate because each cell type is splitted in a known number of new cells and points. nbCells: int = self.inputMesh.GetNumberOfCells() @@ -170,7 +177,12 @@ def applyFilter( self: Self ) -> None: # Transfer all cell arrays self._transferCellArrays( self.outputMesh ) - self.logger.info( f"The filter { self.logger.name } succeeded." ) + + 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 }." ) return From e43a686a6efa44124d15e760718aaa7218fce84b Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Fri, 30 Jan 2026 10:48:47 +0100 Subject: [PATCH 02/10] Add warnings count at the end of the log --- .../pre_processing/CellTypeCounterEnhanced.py | 15 +++++++++++++-- .../pre_processing/MeshQualityEnhanced.py | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py index 3938a5978..f122d267e 100644 --- a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py @@ -9,7 +9,7 @@ from geos.mesh.model.CellTypeCounts import CellTypeCounts from geos.mesh.stats.meshQualityMetricHelpers import getAllCellTypes -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) __doc__ = """ CellTypeCounterEnhanced module is a vtk filter that computes cell type counts. @@ -77,6 +77,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -99,6 +103,8 @@ def applyFilter( self: Self ) -> None: TypeError: Errors with the type of the cells. """ self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) # Compute cell type counts self._counts.reset() @@ -121,7 +127,12 @@ def applyFilter( self: Self ) -> None: array.SetNumberOfValues( 1 ) array.SetValue( 0, self._counts.getTypeCount( cellType ) ) self.outTable.AddColumn( array ) - self.logger.info( f"The filter { self.logger.name } succeeded." ) + + 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 }." ) return diff --git a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py index 930c64c41..5274e1758 100644 --- a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py @@ -28,7 +28,7 @@ getChildrenCellTypes ) import geos.utils.geometryFunctions as geom -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.utils.pieceEnum import Piece __doc__ = """ @@ -143,6 +143,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -292,6 +296,8 @@ def getComputedMetricsFromCellType( self: Self, cellType: int ) -> Optional[ set def applyFilter( self: Self ) -> None: """Apply MeshQualityEnhanced filter.""" self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) self._outputMesh.ShallowCopy( self.inputMesh ) # Compute cell type counts @@ -308,7 +314,11 @@ def applyFilter( self: Self ) -> None: self._outputMesh.Modified() - self.logger.info( f"The filter { self.logger.name } succeeded." ) + 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 }." ) return @@ -356,6 +366,7 @@ def _evaluateCellQuality( self: Self, metricIndex: int ) -> None: """ arrayName: str = getQualityMetricArrayName( metricIndex ) if arrayName in getAttributesFromDataSet( self._outputMesh, piece=Piece.CELLS ): + self.logger.warning( "test" ) # Metric is already computed (by default computed for all cell types if applicable ) return From b6bf8fdfb45acff684afce0871cfe9ec55660706 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Fri, 30 Jan 2026 13:39:59 +0100 Subject: [PATCH 03/10] Update the plugin and the filters extract and merge blocks to get the number of warning log while using it --- .../post_processing/GeosBlockExtractor.py | 14 ++++++++++++-- .../post_processing/GeosBlockMerge.py | 14 ++++++++++++-- .../PVGeosBlockExtractAndMerge.py | 17 ++++++++++++++--- geos-pv/src/geos/pv/utils/workflowFunctions.py | 16 +++++++++++----- geos-utils/src/geos/utils/Logger.py | 8 ++++++++ 5 files changed, 57 insertions(+), 12 deletions(-) diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py index 925d23f2a..10dfdb00b 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from typing_extensions import Self -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.utils.GeosOutputsConstants import GeosDomainNameEnum from geos.mesh.utils.arrayHelpers import getCellDimension from geos.mesh.utils.multiblockHelpers import getBlockIndexFromName @@ -193,6 +193,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -216,6 +220,8 @@ def applyFilter( self: Self ) -> None: TypeError: The mesh extracted has the wrong dimension. """ self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) extractGeosDomain: GeosExtractDomainBlock = GeosExtractDomainBlock() extractGeosDomain.SetInputData( self.geosMesh ) @@ -229,6 +235,10 @@ def applyFilter( self: Self ) -> None: domainNames.append( domain.value ) self.logger.info( f"The GEOS domain { domainNames } have been extracted." ) - self.logger.info( f"The filter { self.logger.name } succeeded." ) + 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 }." ) return diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py index 61e018bf7..a10a57f31 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py @@ -8,7 +8,7 @@ from vtkmodules.vtkCommonDataModel import vtkCompositeDataSet, vtkMultiBlockDataSet, vtkPolyData, vtkUnstructuredGrid from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.utils.GeosOutputsConstants import ( PHASE_SEP, PhaseTypeEnum, FluidPrefixEnum, PostProcessingOutputsEnum, getRockSuffixRenaming ) @@ -112,6 +112,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -140,6 +144,8 @@ def applyFilter( self: Self ) -> None: VTKError: Error raises during the call of VTK function. """ self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) # Display phase names self.computePhaseNames() @@ -184,7 +190,11 @@ def applyFilter( self: Self ) -> None: else: self.outputMesh.SetBlock( newIndex, volumeMesh ) - self.logger.info( f"The filter { self.logger.name } succeeded." ) + 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 }." ) return 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 ee972080f..ce0ec4e3d 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py @@ -23,6 +23,7 @@ from geos.utils.Errors import VTKError from geos.utils.pieceEnum import Piece +from geos.utils.Logger import CountWarningHandler from geos.utils.GeosOutputsConstants import ( GeosMeshOutputsEnum, GeosDomainNameEnum, getAttributeToTransferFromInitialTime ) @@ -133,7 +134,13 @@ def __init__( self: Self ) -> None: self.logger.addHandler( VTKHandler() ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + self.logger.info( f"Apply plugin { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) def RequestDataObject( self: Self, @@ -276,7 +283,7 @@ def RequestData( f"Apply the plugin { self.logger.name } for the first time step to get the initial properties." ) try: doExtractAndMerge( inputMesh, self.outputCellsT0, vtkMultiBlockDataSet(), vtkMultiBlockDataSet(), - self.extractFault, self.extractWell ) + self.extractFault, self.extractWell, self.counter ) request.Set( executive.CONTINUE_EXECUTING(), 1 ) except ( ValueError, VTKError ) as e: self.logger.error( f"The plugin { self.logger.name } failed due to:\n{ e }" ) @@ -296,7 +303,7 @@ def RequestData( try: doExtractAndMerge( inputMesh, outputCells, outputFaults, outputWells, self.extractFault, - self.extractWell ) + self.extractWell, self.counter ) # Copy attributes from the initial time step meshAttributes: set[ str ] = getAttributeSet( self.outputCellsT0, piece=Piece.CELLS ) @@ -316,7 +323,11 @@ def RequestData( # Set to -2 in case time changes on Paraview self.requestDataStep = -2 - self.logger.info( f"The plugin { self.logger.name } succeeded." ) + 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 }." ) except ( ValueError, VTKError ) as e: self.logger.error( f"The plugin { self.logger.name } failed due to:\n{ e }" ) except Exception as e: diff --git a/geos-pv/src/geos/pv/utils/workflowFunctions.py b/geos-pv/src/geos/pv/utils/workflowFunctions.py index 753c981e8..c9dd23cc9 100644 --- a/geos-pv/src/geos/pv/utils/workflowFunctions.py +++ b/geos-pv/src/geos/pv/utils/workflowFunctions.py @@ -2,9 +2,9 @@ # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Romain Baville # ruff: noqa: E402 # disable Module level import not at top of file - from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge +from geos.utils.Logger import CountWarningHandler from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet @@ -18,6 +18,7 @@ def doExtractAndMerge( outputWells: vtkMultiBlockDataSet, extractFault: bool, extractWell: bool, + warningCounter: CountWarningHandler, ) -> None: """Apply block extraction and merge. @@ -28,6 +29,7 @@ def doExtractAndMerge( outputWells (vtkMultiBlockDataSet): Output well mesh extractFault (bool): True if SurfaceElementRegion needs to be extracted, False otherwise. extractWell (bool): True if WellElementRegion needs to be extracted, False otherwise. + warningCounter (logging.Handler): The plugin Handler to update with the number of warning log during the call of the extract and merge filters. """ # Extract blocks blockExtractor: GeosBlockExtractor = GeosBlockExtractor( mesh, @@ -38,20 +40,21 @@ def doExtractAndMerge( blockExtractor.setLoggerHandler( VTKHandler() ) blockExtractor.applyFilter() + warningCounter.addExternalWarningCount( blockExtractor.counter.warningCount ) # recover output objects from GeosBlockExtractor filter and merge internal blocks volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume - outputCells.ShallowCopy( mergeBlocksFilter( volumeBlockExtracted, False, "Volume" ) ) + outputCells.ShallowCopy( mergeBlocksFilter( volumeBlockExtracted, warningCounter, False, "Volume" ) ) outputCells.Modified() if extractFault: faultBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.fault - outputFaults.ShallowCopy( mergeBlocksFilter( faultBlockExtracted, True, "Fault" ) ) + outputFaults.ShallowCopy( mergeBlocksFilter( faultBlockExtracted, warningCounter, True, "Fault" ) ) outputFaults.Modified() if extractWell: wellBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.well - outputWells.ShallowCopy( mergeBlocksFilter( wellBlockExtracted, False, "Well" ) ) + outputWells.ShallowCopy( mergeBlocksFilter( wellBlockExtracted, warningCounter, False, "Well" ) ) outputWells.Modified() return @@ -59,6 +62,7 @@ def doExtractAndMerge( def mergeBlocksFilter( mesh: vtkMultiBlockDataSet, + warningCounter: CountWarningHandler, convertSurfaces: bool = False, domainToMerge: str = "Volume", ) -> vtkMultiBlockDataSet: @@ -66,6 +70,7 @@ def mergeBlocksFilter( Args: mesh (vtkMultiBlockDataSet): Mesh to merge. + warningCounter (logging.Handler): The plugin Handler to update with the number of warning log during the call of the extract and merge filters. convertSurfaces (bool, optional): True to convert surface from vtkUnstructuredGrid to vtkPolyData. Defaults to False. domainToMerge (str, optional): The name of the GEOS domain processed. @@ -74,11 +79,12 @@ def mergeBlocksFilter( Returns: vtkMultiBlockDataSet: Mesh composed of internal merged blocks. """ - loggerName = f"GEOS Block Merge for the domain { domainToMerge }." + loggerName = f"GEOS Block Merge for the domain { domainToMerge }" mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( mesh, convertSurfaces, True, loggerName ) if len( mergeBlockFilter.logger.handlers ) == 0: mergeBlockFilter.setLoggerHandler( VTKHandler() ) mergeBlockFilter.applyFilter() mergedBlocks: vtkMultiBlockDataSet = vtkMultiBlockDataSet() mergedBlocks.ShallowCopy( mergeBlockFilter.getOutput() ) + warningCounter.addExternalWarningCount( mergeBlockFilter.counter.warningCount ) return mergedBlocks diff --git a/geos-utils/src/geos/utils/Logger.py b/geos-utils/src/geos/utils/Logger.py index 68e35868d..fadfba9e8 100644 --- a/geos-utils/src/geos/utils/Logger.py +++ b/geos-utils/src/geos/utils/Logger.py @@ -105,6 +105,14 @@ def __init__( self: Self ) -> None: super().__init__() self.warningCount = 0 + def addExternalWarningCount( self: Self, externalWarningCount: int ) -> None: + """Add external warning count. + + Args: + externalWarningCount (int): An external warning count to add to the internal one. + """ + self.warningCount += externalWarningCount + def emit( self: Self, record: logging.LogRecord ) -> None: """Count all the warnings logged. From 0255916e3bf072e8fb151fddb9c9aa55241c7996 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Fri, 30 Jan 2026 13:59:38 +0100 Subject: [PATCH 04/10] Clean the count of warning for filters calling other filters --- .../geos/processing/generic_processing_tools/SplitMesh.py | 2 ++ .../geos/processing/pre_processing/MeshQualityEnhanced.py | 3 +++ geos-pv/src/geos/pv/utils/workflowFunctions.py | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-) 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 91f5ae55a..84ea9dc54 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py @@ -201,6 +201,8 @@ def _getCellCounts( self: Self ) -> CellTypeCounts: if self.speHandler and len( cellTypeCounterEnhancedFilter.logger.handlers ) == 0: 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.counter.warningCount ) return cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() def _addMidPoint( self: Self, ptA: int, ptB: int ) -> int: diff --git a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py index 5274e1758..e6d821fbb 100644 --- a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py @@ -334,6 +334,9 @@ def _computeCellTypeCounts( self: Self ) -> None: 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.counter.warningCount ) + counts: CellTypeCounts = cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() if counts is None: raise AttributeError( "CellTypeCounts is undefined" ) diff --git a/geos-pv/src/geos/pv/utils/workflowFunctions.py b/geos-pv/src/geos/pv/utils/workflowFunctions.py index c9dd23cc9..ed327354a 100644 --- a/geos-pv/src/geos/pv/utils/workflowFunctions.py +++ b/geos-pv/src/geos/pv/utils/workflowFunctions.py @@ -40,6 +40,7 @@ def doExtractAndMerge( blockExtractor.setLoggerHandler( VTKHandler() ) blockExtractor.applyFilter() + # Add to the warning counter the number of warning logged with the call of GeosBlockExtractor filter warningCounter.addExternalWarningCount( blockExtractor.counter.warningCount ) # recover output objects from GeosBlockExtractor filter and merge internal blocks @@ -84,7 +85,10 @@ def mergeBlocksFilter( if len( mergeBlockFilter.logger.handlers ) == 0: mergeBlockFilter.setLoggerHandler( VTKHandler() ) mergeBlockFilter.applyFilter() + # Add to the warning counter the number of warning logged with the call of GeosBlockMerge filter + warningCounter.addExternalWarningCount( mergeBlockFilter.counter.warningCount ) + mergedBlocks: vtkMultiBlockDataSet = vtkMultiBlockDataSet() mergedBlocks.ShallowCopy( mergeBlockFilter.getOutput() ) - warningCounter.addExternalWarningCount( mergeBlockFilter.counter.warningCount ) + return mergedBlocks From 472527d7461d32af090390d403c771d7f10348d8 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Fri, 30 Jan 2026 16:59:25 +0100 Subject: [PATCH 05/10] Update post-processing filter and plugins to log the number og warnings --- .../post_processing/GeomechanicsCalculator.py | 14 +++++- .../post_processing/SurfaceGeomechanics.py | 44 ++++++++++--------- .../PVGeomechanicsCalculator.py | 29 ++++++++++++ .../post_processing/PVGeomechanicsWorkflow.py | 19 +++++++- .../post_processing/PVMohrCirclePlot.py | 14 ++++++ .../post_processing/PVSurfaceGeomechanics.py | 30 ++++++++++++- 6 files changed, 124 insertions(+), 26 deletions(-) diff --git a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py index 0e89e6c23..238e500eb 100644 --- a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py +++ b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py @@ -16,7 +16,7 @@ from geos.mesh.utils.arrayHelpers import ( getArrayInObject, isAttributeInObject ) from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.utils.GeosOutputsConstants import ( AttributeEnum, ComponentNameEnum, GeosMeshOutputsEnum, PostProcessingOutputsEnum ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_GRAIN_BULK_MODULUS, @@ -712,6 +712,10 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + def applyFilter( self: Self ) -> None: """Compute the geomechanics properties and create attributes on the mesh. @@ -720,6 +724,8 @@ def applyFilter( self: Self ) -> None: ValueError: Something went wrong during the creation of an attribute. """ self.logger.info( f"Apply filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) self._checkMandatoryProperties() self._computeBasicProperties() @@ -750,7 +756,11 @@ def applyFilter( self: Self ) -> None: logger=self.logger ) self.logger.info( "All the geomechanics properties have been added to the mesh." ) - self.logger.info( f"The filter { self.logger.name } succeeded." ) + 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 }." ) return diff --git a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py index 377b9ba58..2a94c3598 100644 --- a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py +++ b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py @@ -16,7 +16,7 @@ from geos.mesh.utils.genericHelpers import ( getLocalBasisVectors, convertAttributeFromLocalToXYZForOneCell ) import geos.geomechanics.processing.geomechanicsCalculatorFunctions as fcts from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_ROCK_COHESION ) from geos.utils.GeosOutputsConstants import ( ComponentNameEnum, GeosMeshOutputsEnum, PostProcessingOutputsEnum ) @@ -88,12 +88,16 @@ Note that the dimension of the attributes to convert must be equal or greater than 3. """ -loggerTitle: str = "Surface Geomechanics" class SurfaceGeomechanics: - def __init__( self: Self, surfacicMesh: vtkPolyData, speHandler: bool = False ) -> None: + def __init__( + self: Self, + surfacicMesh: vtkPolyData, + loggerName: str = "Surface Geomechanics", + speHandler: bool = False, + ) -> None: """Vtk filter to compute geomechanical surfacic attributes. Input and Output objects are a vtkPolydata with surfaces @@ -101,18 +105,24 @@ def __init__( self: Self, surfacicMesh: vtkPolyData, speHandler: bool = False ) Args: surfacicMesh (vtkPolyData): The input surfacic mesh. + loggerName (str, optional): Name of the filter logger. + Defaults to "Surface Geomechanics". speHandler (bool, optional): True to use a specific handler, False to use the internal handler. Defaults to False. """ # Logger self.logger: Logger if not speHandler: - self.logger = getLogger( loggerTitle, True ) + self.logger = getLogger( loggerName, True ) else: - self.logger = logging.getLogger( loggerTitle ) + self.logger = logging.getLogger( loggerName ) self.logger.setLevel( logging.INFO ) self.logger.propagate = False + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + # Input surfacic mesh if not surfacicMesh.IsA( "vtkPolyData" ): self.logger.error( f"Input surface is expected to be a vtkPolyData, not a {type(surfacicMesh)}." ) @@ -151,14 +161,6 @@ def SetLoggerHandler( self: Self, handler: Logger ) -> None: "The logger already has an handler, to use yours set the argument 'speHandler' to True during the filter initialization." ) - def SetSurfaceName( self: Self, name: str ) -> None: - """Set a name for the input surface. For logging purpose only. - - Args: - name (str): The identifier for the surface. - """ - self.name = name - def SetRockCohesion( self: Self, rockCohesion: float ) -> None: """Set rock cohesion value. Defaults to 0.0 Pa. @@ -238,13 +240,9 @@ def applyFilter( self: Self ) -> None: AttributeError: Attributes must be on cell. AssertionError: Something went wrong during the shearCapacityUtilization computation. """ - msg = f"Applying filter {self.logger.name}" - if self.name is not None: - msg += f" on surface : {self.name}." - else: - msg += "." - - self.logger.info( msg ) + self.logger.info( f"Applying filter { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) self.outputMesh = vtkPolyData() self.outputMesh.ShallowCopy( self.inputMesh ) @@ -257,7 +255,11 @@ def applyFilter( self: Self ) -> None: # Compute shear capacity utilization self.computeShearCapacityUtilization() - self.logger.info( f"Filter {self.logger.name} successfully applied on surface {self.name}." ) + 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 }." ) return 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 80a1e5fe0..11438811b 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Martin Lemay, Romain Baville # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging import numpy as np from pathlib import Path @@ -22,6 +23,7 @@ update_paths() +from geos.utils.Logger import CountWarningHandler 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 ) @@ -71,6 +73,8 @@ """ +loggerTitle: str = "Geomechanics Calculator" + @SISOFilter( category=FilterCategory.GEOS_POST_PROCESSING, decoratedLabel="GEOS Geomechanics Calculator", @@ -89,6 +93,10 @@ def __init__( self: Self ) -> None: self.rockCohesion: float = DEFAULT_ROCK_COHESION self.frictionAngle: float = DEFAULT_FRICTION_ANGLE_DEG + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + @smproperty.doublevector( name="GrainBulkModulus", label="Grain bulk modulus (Pa)", @@ -252,6 +260,9 @@ def ApplyFilter( try: geomechanicsCalculatorFilter.applyFilter() + # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter (useful for the PVGeomechanicsWorkflow) + self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.counter.warningCount ) + outputMesh.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) except ( ValueError, AttributeError ) as e: geomechanicsCalculatorFilter.logger.error( @@ -261,6 +272,15 @@ def ApplyFilter( geomechanicsCalculatorFilter.logger.critical( mess, exc_info=True ) elif isinstance( outputMesh, vtkMultiBlockDataSet ): + logger = logging.getLogger( loggerTitle ) + logger.setLevel( logging.INFO ) + logger.addHandler( VTKHandler() ) + logger.propagate = False + + logger.info( f"Apply plugin { logger.name }." ) + # Add the handler to count warnings messages. + logger.addHandler( self.counter ) + volumeBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( outputMesh ) for blockIndex in volumeBlockIndexes: volumeBlock: vtkUnstructuredGrid = vtkUnstructuredGrid.SafeDownCast( @@ -285,6 +305,9 @@ def ApplyFilter( try: geomechanicsCalculatorFilter.applyFilter() + # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter + self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.counter.warningCount ) + volumeBlock.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) volumeBlock.Modified() except ( ValueError, AttributeError ) as e: @@ -294,6 +317,12 @@ def ApplyFilter( mess = f"The filter { geomechanicsCalculatorFilter.logger.name } failed due to:\n{ e }" geomechanicsCalculatorFilter.logger.critical( mess, exc_info=True ) + result: str = f"The filter { logger.name } succeeded" + if self.counter.warningCount > 0: + logger.warning( f"{ result } but { self.counter.warningCount } warnings have been logged." ) + else: + logger.info( f"{ result }." ) + outputMesh.Modified() return 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 d0a90a314..fdc1505db 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py @@ -16,6 +16,7 @@ update_paths() from geos.utils.Errors import VTKError +from geos.utils.Logger import CountWarningHandler from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_GRAIN_BULK_MODULUS, DEFAULT_ROCK_COHESION, WATER_DENSITY ) @@ -142,7 +143,13 @@ def __init__( self: Self ) -> None: self.logger.setLevel( logging.INFO ) self.logger.addHandler( VTKHandler() ) + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + self.logger.info( f"Apply plugin { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) @smproperty.doublevector( name="GrainBulkModulus", @@ -334,7 +341,11 @@ def RequestData( if self.extractFault: self.applyPVSurfaceGeomechanics() - self.logger.info( f"The plugin { self.logger.name } succeeded." ) + 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 }." ) except ( ValueError, VTKError, AttributeError, AssertionError ) as e: self.logger.error( f"The plugin { self.logger.name } failed due to:\n{ e }" ) @@ -349,6 +360,8 @@ def applyPVGeosBlockExtractAndMerge( self: Self ) -> None: extractAndMergeFilter: PVGeosBlockExtractAndMerge = PVGeosBlockExtractAndMerge() extractAndMergeFilter.SetInputConnection( self.GetInputConnection( 0, 0 ) ) extractAndMergeFilter.Update() + # Add to the warning counter the number of warning logged with the call of GeosBlockExtractAndMerge plugin + self.counter.addExternalWarningCount( extractAndMergeFilter.counter.warningCount ) self.volumeMesh.ShallowCopy( extractAndMergeFilter.GetOutputDataObject( 0 ) ) self.volumeMesh.Modified() @@ -376,6 +389,8 @@ def applyPVGeomechanicsCalculator( self: Self ) -> None: geomechanicsCalculatorPlugin.setRockCohesion( self.rockCohesion ) geomechanicsCalculatorPlugin.setFrictionAngle( self.frictionAngle ) geomechanicsCalculatorPlugin.Update() + # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator plugin + self.counter.addExternalWarningCount( geomechanicsCalculatorPlugin.counter.warningCount ) self.volumeMesh.ShallowCopy( geomechanicsCalculatorPlugin.GetOutputDataObject( 0 ) ) self.volumeMesh.Modified() @@ -390,6 +405,8 @@ def applyPVSurfaceGeomechanics( self: Self ) -> None: surfaceGeomechanicsPlugin.a01SetRockCohesion( self.rockCohesion ) surfaceGeomechanicsPlugin.a02SetFrictionAngle( self.frictionAngle ) surfaceGeomechanicsPlugin.Update() + # Add to the warning counter the number of warning logged with the call of SurfaceGeomechanics plugin + self.counter.addExternalWarningCount( surfaceGeomechanicsPlugin.counter.warningCount ) self.faultMesh.ShallowCopy( surfaceGeomechanicsPlugin.GetOutputDataObject( 0 ) ) self.faultMesh.Modified() 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 3fd6e48f2..5e765514c 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py @@ -32,6 +32,7 @@ from geos.geomechanics.model.MohrCircle import MohrCircle from geos.utils.pieceEnum import Piece +from geos.utils.Logger import CountWarningHandler from geos.utils.enumUnits import Pressure, enumerationDomainUnit from geos.utils.GeosOutputsConstants import ( FAILURE_ENVELOPE, GeosMeshOutputsEnum ) from geos.utils.Logger import CustomLoggerFormatter @@ -181,6 +182,14 @@ def __init__( self: Self ) -> None: self.logger.addHandler( handler ) + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + + self.logger.info( f"Apply plugin { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) + @smproperty.xml( """ 0: + self.logger.warning( f"{ result } but { self.counter.warningCount } warnings have been logged." ) + else: + self.logger.info( f"{ result }." ) except Exception as e: self.logger.error( "Mohr circles cannot be plotted due to:" ) self.logger.error( e ) diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py b/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py index 6548b37ee..4c541467f 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Martin Lemay, Paloma Martinez # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging from pathlib import Path import numpy as np from typing_extensions import Self @@ -21,6 +22,7 @@ update_paths() from geos.utils.Errors import VTKError +from geos.utils.Logger import CountWarningHandler from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_ROCK_COHESION ) from geos.processing.post_processing.SurfaceGeomechanics import SurfaceGeomechanics from geos.mesh.utils.multiblockHelpers import ( getBlockElementIndexesFlatten, getBlockFromFlatIndex ) @@ -50,6 +52,8 @@ """ +loggerTitle: str = "Surface Geomechanics" + @SISOFilter( category=FilterCategory.GEOS_POST_PROCESSING, decoratedLabel="GEOS Surface Geomechanics", @@ -66,6 +70,15 @@ def __init__( self: Self ) -> None: # friction angle (°) self.frictionAngle: float = DEFAULT_FRICTION_ANGLE_DEG + self.logger = logging.getLogger( loggerTitle ) + self.logger.setLevel( logging.INFO ) + self.logger.addHandler( VTKHandler() ) + self.logger.propagate = False + + # Warnings counter. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + @smproperty.doublevector( name="RockCohesion", label="Rock Cohesion (Pa)", @@ -115,14 +128,18 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul inputMesh (vtkMultiBlockDataSet): The input multiblock mesh with surfaces. outputMesh (vtkMultiBlockDataSet): The output multiblock mesh with converted attributes and SCU. """ + self.logger.info( f"Apply plugin { self.logger.name }." ) + # Add the handler to count warnings messages. + self.logger.addHandler( self.counter ) + outputMesh.ShallowCopy( inputMesh ) surfaceBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( inputMesh ) for blockIndex in surfaceBlockIndexes: surfaceBlock: vtkPolyData = vtkPolyData.SafeDownCast( getBlockFromFlatIndex( outputMesh, blockIndex ) ) - sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( surfaceBlock, True ) - sgFilter.SetSurfaceName( f"blockIndex {blockIndex}" ) + loggerName: str = f"Surface geomechanics for the blockIndex { blockIndex }" + sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( surfaceBlock, loggerName, True ) if len( sgFilter.logger.handlers ) == 0: sgFilter.SetLoggerHandler( VTKHandler() ) @@ -131,6 +148,9 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul try: sgFilter.applyFilter() + # Add to the warning counter the number of warning logged with the call of SurfaceGeomechanics filter + self.counter.addExternalWarningCount( sgFilter.counter.warningCount ) + outputSurface: vtkPolyData = sgFilter.GetOutputMesh() # add attributes to output surface mesh @@ -145,6 +165,12 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul mess: str = f"The filter { sgFilter.logger.name } failed due to:\n{ e }" sgFilter.logger.critical( mess, exc_info=True ) + 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 }." ) + outputMesh.Modified() return From 8a272a62eb2e0cc5b70dee9f7a55e0c057d41162 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Fri, 30 Jan 2026 18:00:23 +0100 Subject: [PATCH 06/10] Fix count reset issues --- .../generic_processing_tools/AttributeMapping.py | 9 +++------ .../generic_processing_tools/ClipToMainFrame.py | 8 +++----- .../CreateConstantAttributePerRegion.py | 9 +++------ .../generic_processing_tools/FillPartialArrays.py | 8 +++----- .../generic_processing_tools/MergeBlockEnhanced.py | 8 +++----- .../generic_processing_tools/SplitMesh.py | 8 +++----- .../post_processing/GeomechanicsCalculator.py | 8 +++----- .../post_processing/GeosBlockExtractor.py | 8 +++----- .../processing/post_processing/GeosBlockMerge.py | 8 +++----- .../post_processing/SurfaceGeomechanics.py | 8 +++----- .../pre_processing/CellTypeCounterEnhanced.py | 8 +++----- .../pre_processing/MeshQualityEnhanced.py | 8 +++----- .../post_processing/PVGeomechanicsCalculator.py | 11 +++++------ .../post_processing/PVGeomechanicsWorkflow.py | 14 ++++++-------- .../post_processing/PVGeosBlockExtractAndMerge.py | 14 ++++++-------- .../pv/plugins/post_processing/PVMohrCirclePlot.py | 14 +++++--------- .../post_processing/PVSurfaceGeomechanics.py | 8 +++----- geos-utils/src/geos/utils/Logger.py | 4 ++++ 18 files changed, 65 insertions(+), 98 deletions(-) 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 170712209..368693d29 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py @@ -111,10 +111,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -150,8 +146,9 @@ def applyFilter( self: Self ) -> None: AttributeError: Errors with the attribute of the mesh. """ self.logger.info( f"Apply filter { self.logger.name }." ) - - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) if len( self.attributeNames ) == 0: 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 8cd92c004..22f5fae9b 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py @@ -236,10 +236,6 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def Update( self ) -> None: # type: ignore[override] """Update the filter.""" super().Update() @@ -253,7 +249,9 @@ def Update( self ) -> None: # type: ignore[override] def ComputeTransform( self ) -> None: """Update the transformation.""" self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) # dispatch to ClipToMainFrame depending on input type 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 d2c0e4c1a..639f9a57a 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py @@ -122,10 +122,6 @@ def __init__( # Check if the new component have default values (information for the output message). self.useDefaultValue: bool = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - # Logger. self.logger: Logger if not speHandler: @@ -159,8 +155,9 @@ def applyFilter( self: Self ) -> None: AttributeError: Errors with the attribute of the mesh. """ self.logger.info( f"Apply filter { self.logger.name }." ) - - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) # Check the validity of the attribute region. 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 1763fb929..e3c8c38dd 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py @@ -98,10 +98,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -125,7 +121,9 @@ def applyFilter( self: Self ) -> None: ValueError: Error during the filling of the attribute. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) piece: Piece 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 416051bb5..c35b15cad 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py @@ -91,10 +91,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -116,7 +112,9 @@ def applyFilter( self: Self ) -> None: VTKError (geos.utils.Errors): Errors captured if any from the VTK log. """ self.logger.info( f"Applying filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) outputMesh: vtkUnstructuredGrid 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 84ea9dc54..f122079b8 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py @@ -84,10 +84,6 @@ def __init__( self, inputMesh: vtkUnstructuredGrid, speHandler: bool = False ) - self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -111,7 +107,9 @@ def applyFilter( self: Self ) -> None: AttributeError: Errors with cell data. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) # Count the number of cells before splitting. Then we will be able to know how many new cells and points diff --git a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py index 238e500eb..e7340783d 100644 --- a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py +++ b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py @@ -712,10 +712,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def applyFilter( self: Self ) -> None: """Compute the geomechanics properties and create attributes on the mesh. @@ -724,7 +720,9 @@ def applyFilter( self: Self ) -> None: ValueError: Something went wrong during the creation of an attribute. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) self._checkMandatoryProperties() diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py index 10dfdb00b..29e381d69 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py @@ -193,10 +193,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -220,7 +216,9 @@ def applyFilter( self: Self ) -> None: TypeError: The mesh extracted has the wrong dimension. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) extractGeosDomain: GeosExtractDomainBlock = GeosExtractDomainBlock() diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py index a10a57f31..30f68797d 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py @@ -112,10 +112,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -144,7 +140,9 @@ def applyFilter( self: Self ) -> None: VTKError: Error raises during the call of VTK function. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) # Display phase names diff --git a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py index 2a94c3598..3c2f32539 100644 --- a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py +++ b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py @@ -119,10 +119,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - # Input surfacic mesh if not surfacicMesh.IsA( "vtkPolyData" ): self.logger.error( f"Input surface is expected to be a vtkPolyData, not a {type(surfacicMesh)}." ) @@ -241,7 +237,9 @@ def applyFilter( self: Self ) -> None: AssertionError: Something went wrong during the shearCapacityUtilization computation. """ self.logger.info( f"Applying filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) self.outputMesh = vtkPolyData() diff --git a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py index f122d267e..5159078b5 100644 --- a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py @@ -77,10 +77,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -103,7 +99,9 @@ def applyFilter( self: Self ) -> None: TypeError: Errors with the type of the cells. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) # Compute cell type counts diff --git a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py index e6d821fbb..31d70eef6 100644 --- a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py @@ -143,10 +143,6 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -296,7 +292,9 @@ def getComputedMetricsFromCellType( self: Self, cellType: int ) -> Optional[ set def applyFilter( self: Self ) -> None: """Apply MeshQualityEnhanced filter.""" self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) self._outputMesh.ShallowCopy( self.inputMesh ) 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 11438811b..d86c9b9fc 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py @@ -93,10 +93,6 @@ def __init__( self: Self ) -> None: self.rockCohesion: float = DEFAULT_ROCK_COHESION self.frictionAngle: float = DEFAULT_FRICTION_ANGLE_DEG - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - @smproperty.doublevector( name="GrainBulkModulus", label="Grain bulk modulus (Pa)", @@ -240,6 +236,7 @@ def ApplyFilter( inputMesh (vtkUnstructuredGrid|vtkMultiBlockDataSet): A mesh to transform. outputMesh (vtkUnstructuredGrid|vtkMultiBlockDataSet): A mesh transformed. """ + self.counter: CountWarningHandler geomechanicsCalculatorFilter: GeomechanicsCalculator outputMesh.ShallowCopy( inputMesh ) mess: str @@ -261,7 +258,7 @@ def ApplyFilter( try: geomechanicsCalculatorFilter.applyFilter() # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter (useful for the PVGeomechanicsWorkflow) - self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.counter.warningCount ) + self.counter = geomechanicsCalculatorFilter.counter outputMesh.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) except ( ValueError, AttributeError ) as e: @@ -278,7 +275,9 @@ def ApplyFilter( logger.propagate = False logger.info( f"Apply plugin { logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) logger.addHandler( self.counter ) volumeBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( outputMesh ) 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 fdc1505db..45990eac6 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py @@ -143,14 +143,6 @@ def __init__( self: Self ) -> None: self.logger.setLevel( logging.INFO ) self.logger.addHandler( VTKHandler() ) - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - - self.logger.info( f"Apply plugin { self.logger.name }." ) - # Add the handler to count warnings messages. - self.logger.addHandler( self.counter ) - @smproperty.doublevector( name="GrainBulkModulus", label="Grain bulk modulus (Pa)", @@ -330,6 +322,12 @@ def RequestData( Returns: int: 1 if calculation successfully ended, 0 otherwise. """ + self.logger.info( f"Apply plugin { self.logger.name }." ) + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + self.logger.addHandler( self.counter ) + try: self.volumeMesh = self.GetOutputData( outInfoVec, 0 ) self.faultMesh = self.GetOutputData( outInfoVec, 1 ) 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 ce0ec4e3d..098fc3eed 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py @@ -134,14 +134,6 @@ def __init__( self: Self ) -> None: self.logger.addHandler( VTKHandler() ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - - self.logger.info( f"Apply plugin { self.logger.name }." ) - # Add the handler to count warnings messages. - self.logger.addHandler( self.counter ) - def RequestDataObject( self: Self, request: vtkInformation, @@ -279,6 +271,12 @@ def RequestData( # First time step, compute the initial properties (useful for geomechanics analyses) if self.requestDataStep == 0: + self.logger.info( f"Apply plugin { self.logger.name }." ) + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) + self.logger.addHandler( self.counter ) + self.logger.info( f"Apply the plugin { self.logger.name } for the first time step to get the initial properties." ) try: 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 5e765514c..7ea683160 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py @@ -176,20 +176,12 @@ def __init__( self: Self ) -> None: # Logger self.logger: logging.Logger = logging.getLogger( "MohrCircle" ) self.logger.setLevel( logging.INFO ) - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: handler = VTKHandler() handler.setFormatter( CustomLoggerFormatter( False ) ) self.logger.addHandler( handler ) - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - - self.logger.info( f"Apply plugin { self.logger.name }." ) - # Add the handler to count warnings messages. - self.logger.addHandler( self.counter ) - @smproperty.xml( """ None: self.logger.addHandler( VTKHandler() ) self.logger.propagate = False - # Warnings counter. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - @smproperty.doublevector( name="RockCohesion", label="Rock Cohesion (Pa)", @@ -129,7 +125,9 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul outputMesh (vtkMultiBlockDataSet): The output multiblock mesh with converted attributes and SCU. """ self.logger.info( f"Apply plugin { self.logger.name }." ) - # Add the handler to count warnings messages. + # Add the handler to count warnings messages to the logger. + self.counter: CountWarningHandler = CountWarningHandler() + self.counter.setLevel( logging.INFO ) self.logger.addHandler( self.counter ) outputMesh.ShallowCopy( inputMesh ) diff --git a/geos-utils/src/geos/utils/Logger.py b/geos-utils/src/geos/utils/Logger.py index fadfba9e8..aec057136 100644 --- a/geos-utils/src/geos/utils/Logger.py +++ b/geos-utils/src/geos/utils/Logger.py @@ -105,6 +105,10 @@ def __init__( self: Self ) -> None: super().__init__() self.warningCount = 0 + def resetWarningCount( self: Self ) -> None: + """Reset the warning counter to 0.""" + self.warningCount = 0 + def addExternalWarningCount( self: Self, externalWarningCount: int ) -> None: """Add external warning count. From 7c0a495e8da325fd73756c9b60b4636c3538c1ca Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Mon, 2 Feb 2026 17:25:35 +0100 Subject: [PATCH 07/10] Fix warning counter when multiple apply --- .../AttributeMapping.py | 30 ++++++--- .../ClipToMainFrame.py | 29 ++++++--- .../CreateConstantAttributePerRegion.py | 29 ++++++--- .../FillPartialArrays.py | 28 +++++--- .../MergeBlockEnhanced.py | 26 +++++--- .../generic_processing_tools/SplitMesh.py | 32 ++++++--- .../post_processing/GeomechanicsCalculator.py | 27 +++++--- .../post_processing/GeosBlockExtractor.py | 27 +++++--- .../post_processing/GeosBlockMerge.py | 29 +++++---- .../post_processing/SurfaceGeomechanics.py | 29 ++++++--- .../pre_processing/CellTypeCounterEnhanced.py | 28 +++++--- .../pre_processing/MeshQualityEnhanced.py | 37 +++++++---- .../generic_processing/PVAttributeMapping.py | 10 ++- .../generic_processing/PVClipToMainFrame.py | 8 ++- .../PVCreateConstantAttributePerRegion.py | 7 +- .../generic_processing/PVFillPartialArrays.py | 7 +- .../PVMergeBlocksEnhanced.py | 7 +- .../plugins/generic_processing/PVSplitMesh.py | 8 ++- .../PVGeomechanicsCalculator.py | 53 +++++++++------ .../post_processing/PVGeomechanicsWorkflow.py | 31 ++++++--- .../PVGeosBlockExtractAndMerge.py | 26 +++++--- .../post_processing/PVGeosLogReader.py | 33 ++++++++-- .../post_processing/PVMohrCirclePlot.py | 33 ++++++---- .../post_processing/PVSurfaceGeomechanics.py | 31 ++++++--- .../plugins/qc/PVCellTypeCounterEnhanced.py | 8 ++- .../pv/plugins/qc/PVMeshQualityEnhanced.py | 9 ++- .../src/geos/pv/utils/workflowFunctions.py | 18 +++-- geos-utils/src/geos/utils/Logger.py | 65 ++++++++++++++++++- 28 files changed, 500 insertions(+), 205 deletions(-) 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 368693d29..b58de2fb3 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py @@ -9,7 +9,7 @@ from vtkmodules.vtkCommonDataModel import vtkDataSet, vtkMultiBlockDataSet from geos.mesh.utils.arrayModifiers import transferAttributeWithElementMap from geos.mesh.utils.arrayHelpers import ( computeElementMapping, getAttributeSet, isAttributeGlobal ) -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.pieceEnum import Piece __doc__ = """ @@ -111,6 +111,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -120,11 +132,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler'" - " to True during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def getElementMap( self: Self ) -> dict[ int, npt.NDArray[ np.int64 ] ]: """Getter of the element mapping dictionary. @@ -146,10 +157,6 @@ def applyFilter( self: Self ) -> None: AttributeError: Errors with the attribute of the mesh. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) if len( self.attributeNames ) == 0: raise ValueError( "Please enter at least one attribute to transfer." ) @@ -188,6 +195,8 @@ def applyFilter( self: Self ) -> None: transferAttributeWithElementMap( self.meshFrom, self.meshTo, self.ElementMap, attributeName, self.piece, self.logger ) + self.logger.warning( "test" ) + # Log the output message. self.logger.info( f"The attributes { self.attributeNames } have been transferred from the source mesh to the final mesh with a { self.piece.value } mapping.\n" @@ -197,3 +206,8 @@ def applyFilter( self: Self ) -> None: self.logger.warning( f"{ result } but { self.counter.warningCount } warnings have been logged." ) else: self.logger.info( f"{ result }." ) + + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + + return 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 22f5fae9b..dde25e6f4 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py @@ -16,7 +16,7 @@ from vtkmodules.vtkCommonTransforms import vtkLandmarkTransform from vtkmodules.vtkFiltersGeneral import vtkTransformFilter -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.genericHelpers import getMultiBlockBounds __doc__ = """ @@ -227,7 +227,8 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: properties (kwargs): kwargs forwarded to vtkTransformFilter. """ super().__init__( **properties ) - # Logger. + + # Logger self.logger: Logger if not speHandler: self.logger = getLogger( loggerTitle, True ) @@ -236,6 +237,18 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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() @@ -246,13 +259,12 @@ def Update( self ) -> None: # type: ignore[override] else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + def ComputeTransform( self ) -> None: """Update the transformation.""" self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) # dispatch to ClipToMainFrame depending on input type if isinstance( self.GetInput(), vtkMultiBlockDataSet ): @@ -281,11 +293,10 @@ def SetLoggerHandler( self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler' to True" - " during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) 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 639f9a57a..89adbce7b 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py @@ -12,7 +12,7 @@ from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkDataSet from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.arrayHelpers import ( getArrayInObject, getComponentNames, getNumberOfComponents, getVtkDataTypeInObject, isAttributeGlobal, getAttributePieceInfo, checkValidValuesInDataSet, checkValidValuesInMultiBlock ) @@ -122,7 +122,7 @@ def __init__( # Check if the new component have default values (information for the output message). self.useDefaultValue: bool = False - # Logger. + # Logger self.logger: Logger if not speHandler: self.logger = getLogger( loggerTitle, True ) @@ -131,6 +131,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -140,12 +152,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - # This warning does not count for the number of warning created during the application of the filter. - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler' to True" - " during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def applyFilter( self: Self ) -> None: """Create a constant attribute per region in the mesh. @@ -155,10 +165,6 @@ def applyFilter( self: Self ) -> None: AttributeError: Errors with the attribute of the mesh. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) # Check the validity of the attribute region. if self.piece == Piece.NONE: @@ -410,4 +416,7 @@ def _logOutputMessage( self: Self, trueIndexes: list[ Any ] ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return 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 e3c8c38dd..4dbcc2b88 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py @@ -6,7 +6,7 @@ from typing import Union, Any from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.arrayModifiers import fillPartialAttributes from geos.mesh.utils.arrayHelpers import getAttributePieceInfo @@ -89,7 +89,7 @@ def __init__( self.multiBlockDataSet: vtkMultiBlockDataSet = multiBlockDataSet self.dictAttributesValues: dict[ str, Union[ list[ Any ], None ] ] = dictAttributesValues - # Logger. + # Logger self.logger: Logger if not speHandler: self.logger = getLogger( loggerTitle, True ) @@ -98,6 +98,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -107,11 +119,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler' to True" - " during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def applyFilter( self: Self ) -> None: """Create a constant attribute per region in the mesh. @@ -121,10 +132,6 @@ def applyFilter( self: Self ) -> None: ValueError: Error during the filling of the attribute. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) piece: Piece mess: str = "" @@ -155,4 +162,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return 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 c35b15cad..6e472396f 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py @@ -6,7 +6,7 @@ from typing_extensions import Self -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.multiblockModifiers import mergeBlocks from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkUnstructuredGrid @@ -91,6 +91,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -99,11 +111,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler' to True" - " during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def applyFilter( self: Self ) -> None: """Merge the blocks of a multiblock dataset mesh. @@ -112,10 +123,6 @@ def applyFilter( self: Self ) -> None: VTKError (geos.utils.Errors): Errors captured if any from the VTK log. """ self.logger.info( f"Applying filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) outputMesh: vtkUnstructuredGrid outputMesh = mergeBlocks( self.inputMesh, keepPartialAttributes=True, logger=self.logger ) @@ -127,6 +134,9 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def getOutput( self: Self ) -> vtkUnstructuredGrid: 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 f122079b8..77f358d3e 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py @@ -12,7 +12,7 @@ VTK_POLYHEDRON, VTK_POLYGON ) from vtkmodules.util.numpy_support import numpy_to_vtk, vtk_to_numpy -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.processing.pre_processing.CellTypeCounterEnhanced import CellTypeCounterEnhanced from geos.mesh.model.CellTypeCounts import CellTypeCounts @@ -84,6 +84,18 @@ def __init__( self, inputMesh: vtkUnstructuredGrid, speHandler: bool = False ) - self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -93,11 +105,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: handler (logging.Handler): The handler to add. """ self.handler = handler - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler' to True" - " during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def applyFilter( self: Self ) -> None: """Apply the filter SplitMesh. @@ -107,10 +118,6 @@ def applyFilter( self: Self ) -> None: AttributeError: Errors with cell data. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) # Count the number of cells before splitting. Then we will be able to know how many new cells and points # to allocate because each cell type is splitted in a known number of new cells and points. @@ -182,6 +189,9 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def getOutput( self: Self ) -> vtkUnstructuredGrid: @@ -196,11 +206,13 @@ def _getCellCounts( self: Self ) -> CellTypeCounts: """ cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( self.inputMesh, self.speHandler ) - if self.speHandler and len( cellTypeCounterEnhancedFilter.logger.handlers ) == 0: + 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.counter.warningCount ) + self.counter.addExternalWarningCount( cellTypeCounterEnhancedFilter.nbWarnings ) + return cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() def _addMidPoint( self: Self, ptA: int, ptB: int ) -> int: diff --git a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py index e7340783d..5c71438f7 100644 --- a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py +++ b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py @@ -16,7 +16,7 @@ from geos.mesh.utils.arrayHelpers import ( getArrayInObject, isAttributeInObject ) from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.GeosOutputsConstants import ( AttributeEnum, ComponentNameEnum, GeosMeshOutputsEnum, PostProcessingOutputsEnum ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_GRAIN_BULK_MODULUS, @@ -712,6 +712,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) + + self.logger.addHandler( self.counter ) + def applyFilter( self: Self ) -> None: """Compute the geomechanics properties and create attributes on the mesh. @@ -720,10 +732,6 @@ def applyFilter( self: Self ) -> None: ValueError: Something went wrong during the creation of an attribute. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) self._checkMandatoryProperties() self._computeBasicProperties() @@ -760,6 +768,9 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def getOutput( self: Self ) -> vtkUnstructuredGrid: @@ -778,12 +789,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( - "The logger already has an handler, to use yours set the argument 'speHandler' to True during the filter initialization." - ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def getOutputType( self: Self ) -> str: """Get output object type. diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py index 29e381d69..e5db0d4d0 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from typing_extensions import Self -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.GeosOutputsConstants import GeosDomainNameEnum from geos.mesh.utils.arrayHelpers import getCellDimension from geos.mesh.utils.multiblockHelpers import getBlockIndexFromName @@ -193,6 +193,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -201,12 +213,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( - "The logger already has an handler, to use yours set the argument 'speHandler' to True during the filter initialization." - ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def applyFilter( self: Self ) -> None: """Extract the volume, the fault or the well domain of the mesh from GEOS. @@ -216,10 +226,6 @@ def applyFilter( self: Self ) -> None: TypeError: The mesh extracted has the wrong dimension. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) extractGeosDomain: GeosExtractDomainBlock = GeosExtractDomainBlock() extractGeosDomain.SetInputData( self.geosMesh ) @@ -239,4 +245,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py index 30f68797d..ea67be97a 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py @@ -8,7 +8,7 @@ from vtkmodules.vtkCommonDataModel import vtkCompositeDataSet, vtkMultiBlockDataSet, vtkPolyData, vtkUnstructuredGrid from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.GeosOutputsConstants import ( PHASE_SEP, PhaseTypeEnum, FluidPrefixEnum, PostProcessingOutputsEnum, getRockSuffixRenaming ) @@ -95,7 +95,6 @@ def __init__( """ self.inputMesh: vtkMultiBlockDataSet = inputMesh self.convertFaultToSurface: bool = convertFaultToSurface - self.handler: None | logging.Handler = None self.outputMesh: vtkMultiBlockDataSet = vtkMultiBlockDataSet() self.phaseNameDict: dict[ str, set[ str ] ] = { @@ -112,6 +111,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -120,13 +131,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: - self.handler = handler + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( - "The logger already has an handler, to use yours set the argument 'speHandler' to True during the filter initialization." - ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def getOutput( self: Self ) -> vtkMultiBlockDataSet: """Get the mesh with the composite blocks merged.""" @@ -140,10 +148,6 @@ def applyFilter( self: Self ) -> None: VTKError: Error raises during the call of VTK function. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) # Display phase names self.computePhaseNames() @@ -194,6 +198,9 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def renameAttributes( diff --git a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py index 3c2f32539..9964971f4 100644 --- a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py +++ b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py @@ -16,7 +16,7 @@ from geos.mesh.utils.genericHelpers import ( getLocalBasisVectors, convertAttributeFromLocalToXYZForOneCell ) import geos.geomechanics.processing.geomechanicsCalculatorFunctions as fcts from geos.utils.pieceEnum import Piece -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_ROCK_COHESION ) from geos.utils.GeosOutputsConstants import ( ComponentNameEnum, GeosMeshOutputsEnum, PostProcessingOutputsEnum ) @@ -119,9 +119,21 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) + + self.logger.addHandler( self.counter ) + # Input surfacic mesh if not surfacicMesh.IsA( "vtkPolyData" ): - self.logger.error( f"Input surface is expected to be a vtkPolyData, not a {type(surfacicMesh)}." ) + 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 @@ -150,12 +162,10 @@ def SetLoggerHandler( self: Self, handler: Logger ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( - "The logger already has an handler, to use yours set the argument 'speHandler' to True during the filter initialization." - ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def SetRockCohesion( self: Self, rockCohesion: float ) -> None: """Set rock cohesion value. Defaults to 0.0 Pa. @@ -237,10 +247,6 @@ def applyFilter( self: Self ) -> None: AssertionError: Something went wrong during the shearCapacityUtilization computation. """ self.logger.info( f"Applying filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) self.outputMesh = vtkPolyData() self.outputMesh.ShallowCopy( self.inputMesh ) @@ -259,6 +265,9 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def convertAttributesFromLocalToXYZBasis( self: Self ) -> None: diff --git a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py index 5159078b5..8def50e9a 100644 --- a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py @@ -9,7 +9,7 @@ from geos.mesh.model.CellTypeCounts import CellTypeCounts from geos.mesh.stats.meshQualityMetricHelpers import getAllCellTypes -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) __doc__ = """ CellTypeCounterEnhanced module is a vtk filter that computes cell type counts. @@ -68,7 +68,7 @@ def __init__( self.outTable: vtkTable = vtkTable() self._counts: CellTypeCounts = CellTypeCounts() - # Logger. + # Logger self.logger: Logger if not speHandler: self.logger = getLogger( loggerTitle, True ) @@ -77,6 +77,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -86,11 +98,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler'" - " to True during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def applyFilter( self: Self ) -> None: """Apply CellTypeCounterEnhanced filter. @@ -99,10 +110,6 @@ def applyFilter( self: Self ) -> None: TypeError: Errors with the type of the cells. """ self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) # Compute cell type counts self._counts.reset() @@ -132,6 +139,9 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def GetCellTypeCountsObject( self: Self ) -> CellTypeCounts: diff --git a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py index 31d70eef6..af73dd9aa 100644 --- a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py @@ -28,7 +28,7 @@ getChildrenCellTypes ) import geos.utils.geometryFunctions as geom -from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) +from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.pieceEnum import Piece __doc__ = """ @@ -131,10 +131,9 @@ def __init__( # Static members that can be loaded once to save computational times self._allCellTypesExtended: tuple[ int, ...] = getAllCellTypesExtended() self._allCellTypes: tuple[ int, ...] = getAllCellTypes() - - # Logger. self.speHandler: bool = speHandler - self.handler: None | logging.Handler = None + + # Logger self.logger: Logger if not speHandler: self.logger = getLogger( loggerTitle, True ) @@ -143,6 +142,18 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + 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. @@ -153,11 +164,10 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: handler (logging.Handler): The handler to add. """ self.handler = handler - if len( self.logger.handlers ) == 0: + if not isHandlerInLogger( handler, self.logger ): self.logger.addHandler( handler ) else: - self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler'" - " to True during the filter initialization." ) + self.logger.warning( "The logger already has this handler, it has not be added." ) def GetQualityMetricSummary( self: Self ) -> QualityMetricSummary: """Get QualityMetricSummary object. @@ -292,10 +302,6 @@ def getComputedMetricsFromCellType( self: Self, cellType: int ) -> Optional[ set def applyFilter( self: Self ) -> None: """Apply MeshQualityEnhanced filter.""" self.logger.info( f"Apply filter { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) self._outputMesh.ShallowCopy( self.inputMesh ) # Compute cell type counts @@ -318,6 +324,9 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def getOutput( self: Self ) -> vtkUnstructuredGrid: @@ -328,12 +337,14 @@ def _computeCellTypeCounts( self: Self ) -> None: """Compute cell type counts.""" cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( self._outputMesh, self.speHandler ) - if self.speHandler and len( cellTypeCounterEnhancedFilter.logger.handlers ) == 0: + + 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.counter.warningCount ) + self.counter.addExternalWarningCount( cellTypeCounterEnhancedFilter.nbWarnings ) counts: CellTypeCounts = cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() if counts is None: 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 96c10685a..d6b07cab6 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVAttributeMapping.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVAttributeMapping.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Raphaël Vinour, Martin Lemay, Romain Baville # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging from pathlib import Path from typing import Union from typing_extensions import Self @@ -27,6 +28,7 @@ from geos.pv.utils.details import FilterCategory from geos.utils.pieceEnum import Piece +from geos.utils.Logger import isHandlerInLogger __doc__ = f""" AttributeMapping is a paraview plugin that transfers global attributes from a source mesh to a final mesh with same point/cell coordinates. @@ -74,6 +76,7 @@ def __init__( self: Self ) -> None: self.piece: Piece = Piece.CELLS self.clearAttributeNames = True self.attributeNames: list[ str ] = [] + self.handler: logging.Handler = VTKHandler() @smproperty.intvector( name="AttributePiece", @@ -187,12 +190,11 @@ def RequestData( attributeMappingFilter: AttributeMapping = AttributeMapping( meshFrom, outData, set( self.attributeNames ), self.piece, True ) - if len( attributeMappingFilter.logger.handlers ) == 0: - attributeMappingFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, attributeMappingFilter.logger ): + attributeMappingFilter.setLoggerHandler( self.handler ) try: attributeMappingFilter.applyFilter() - self.clearAttributeNames = True except ( ValueError, AttributeError ) as e: attributeMappingFilter.logger.error( f"The filter { attributeMappingFilter.logger.name } failed due to:\n{ e }" ) @@ -200,4 +202,6 @@ def RequestData( mess: str = f"The filter { attributeMappingFilter.logger.name } failed due to:\n{ e }" attributeMappingFilter.logger.critical( mess, exc_info=True ) + self.clearAttributeNames = True + return 1 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 acfdc2917..bc939e10e 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVClipToMainFrame.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVClipToMainFrame.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Jacques Franc # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging from pathlib import Path from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase # type: ignore[import-not-found] @@ -21,6 +22,7 @@ from geos.pv.utils.details import ( SISOFilter, FilterCategory ) from geos.processing.generic_processing_tools.ClipToMainFrame import ClipToMainFrame +from geos.utils.Logger import isHandlerInLogger __doc__ = f""" Clip the input mesh to the main frame applying the correct LandmarkTransform @@ -43,8 +45,10 @@ class PVClipToMainFrame( VTKPythonAlgorithmBase ): def __init__( self ) -> None: """Init motherclass, filter and logger.""" self._realFilter = ClipToMainFrame( speHandler=True ) - if len( self._realFilter.logger.handlers ) == 0: - self._realFilter.SetLoggerHandler( VTKHandler() ) + self.handler: logging.Handler = VTKHandler() + + if not isHandlerInLogger( self.handler, self._realFilter.logger ): + self._realFilter.SetLoggerHandler( self.handler ) def ApplyFilter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBlockDataSet ) -> None: """Is applying CreateConstantAttributePerRegion filter. 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 a809d1279..372ea2c3a 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVCreateConstantAttributePerRegion.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVCreateConstantAttributePerRegion.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Martin Lemay, Romain Baville # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging import numpy as np from pathlib import Path @@ -26,6 +27,7 @@ from geos.processing.generic_processing_tools.CreateConstantAttributePerRegion import CreateConstantAttributePerRegion from geos.pv.utils.details import ( SISOFilter, FilterCategory ) +from geos.utils.Logger import isHandlerInLogger __doc__ = f""" PVCreateConstantAttributePerRegion is a Paraview plugin that allows to create an attribute @@ -70,6 +72,7 @@ def __init__( self: Self ) -> None: # Use the handler of paraview for the log. self.speHandler: bool = True + self.handler: logging.Handler = VTKHandler() # Settings of the attribute with the region indexes: @smproperty.stringvector( @@ -289,8 +292,8 @@ def ApplyFilter( self, inputMesh: vtkDataSet, outputMesh: vtkDataSet ) -> None: self.speHandler, ) - if len( createConstantAttributePerRegionFilter.logger.handlers ) == 0: - createConstantAttributePerRegionFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, createConstantAttributePerRegionFilter.logger ): + createConstantAttributePerRegionFilter.setLoggerHandler( self.handler ) try: createConstantAttributePerRegionFilter.applyFilter() 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 35eda1607..547945aab 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVFillPartialArrays.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVFillPartialArrays.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Martin Lemay, Romain Baville # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging from pathlib import Path from typing import Any, Optional, Union from typing_extensions import Self @@ -21,6 +22,7 @@ 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 @@ -49,6 +51,7 @@ def __init__( self: Self, ) -> None: """Fill a partial attribute with constant value per component.""" self.clearDictAttributesValues: bool = True self.dictAttributesValues: dict[ str, Union[ list[ Any ], None ] ] = {} + self.handler: logging.Handler = VTKHandler() @smproperty.xml( """ None: inputType="vtkMultiBlockDataSet", outputType="vtkUnstructuredGrid", ) + self.handler: logging.Handler = VTKHandler() def RequestDataObject( self: Self, @@ -115,8 +118,8 @@ def RequestData( mergeBlockEnhancedFilter: MergeBlockEnhanced = MergeBlockEnhanced( inputMesh, True ) - if len( mergeBlockEnhancedFilter.logger.handlers ) == 0: - mergeBlockEnhancedFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, mergeBlockEnhancedFilter.logger ): + mergeBlockEnhancedFilter.setLoggerHandler( self.handler ) 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 e511d8471..81da5b814 100644 --- a/geos-pv/src/geos/pv/plugins/generic_processing/PVSplitMesh.py +++ b/geos-pv/src/geos/pv/plugins/generic_processing/PVSplitMesh.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Martin Lemay # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging from pathlib import Path from typing_extensions import Self @@ -21,6 +22,7 @@ update_paths() from geos.processing.generic_processing_tools.SplitMesh import SplitMesh +from geos.utils.Logger import isHandlerInLogger from geos.pv.utils.details import ( SISOFilter, FilterCategory ) __doc__ = f""" @@ -43,7 +45,7 @@ class PVSplitMesh( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: """Split mesh cells.""" - pass + self.handler: logging.Handler = VTKHandler() def ApplyFilter( self: Self, inputMesh: vtkPointSet, outputMesh: vtkPointSet ) -> None: """Apply vtk filter. @@ -53,8 +55,8 @@ def ApplyFilter( self: Self, inputMesh: vtkPointSet, outputMesh: vtkPointSet ) - outputMesh: Output mesh. """ splitMeshFilter: SplitMesh = SplitMesh( inputMesh, True ) - if len( splitMeshFilter.logger.handlers ) == 0: - splitMeshFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, splitMeshFilter.logger ): + splitMeshFilter.setLoggerHandler( self.handler ) 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 d86c9b9fc..2084de0a5 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py @@ -23,7 +23,7 @@ update_paths() -from geos.utils.Logger import CountWarningHandler +from geos.utils.Logger import ( CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) 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 ) @@ -93,6 +93,24 @@ def __init__( self: Self ) -> None: self.rockCohesion: float = DEFAULT_ROCK_COHESION self.frictionAngle: float = DEFAULT_FRICTION_ANGLE_DEG + self.handler: logging.Handler = VTKHandler() + self.logger = logging.getLogger( loggerTitle ) + self.logger.setLevel( logging.INFO ) + self.logger.addHandler( self.handler ) + self.logger.propagate = False + + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) + + self.logger.addHandler( self.counter ) + @smproperty.doublevector( name="GrainBulkModulus", label="Grain bulk modulus (Pa)", @@ -236,7 +254,6 @@ def ApplyFilter( inputMesh (vtkUnstructuredGrid|vtkMultiBlockDataSet): A mesh to transform. outputMesh (vtkUnstructuredGrid|vtkMultiBlockDataSet): A mesh transformed. """ - self.counter: CountWarningHandler geomechanicsCalculatorFilter: GeomechanicsCalculator outputMesh.ShallowCopy( inputMesh ) mess: str @@ -244,11 +261,12 @@ def ApplyFilter( geomechanicsCalculatorFilter = GeomechanicsCalculator( outputMesh, self.computeAdvancedProperties, + loggerName= "Geomechanics Calculators on the unstructured grid", speHandler=True, ) - if len( geomechanicsCalculatorFilter.logger.handlers ) == 0: - geomechanicsCalculatorFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, geomechanicsCalculatorFilter.logger ): + geomechanicsCalculatorFilter.setLoggerHandler( self.handler ) geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus geomechanicsCalculatorFilter.physicalConstants.specificDensity = self.specificDensity @@ -258,7 +276,7 @@ def ApplyFilter( try: geomechanicsCalculatorFilter.applyFilter() # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter (useful for the PVGeomechanicsWorkflow) - self.counter = geomechanicsCalculatorFilter.counter + self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.nbWarnings ) outputMesh.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) except ( ValueError, AttributeError ) as e: @@ -269,16 +287,7 @@ def ApplyFilter( geomechanicsCalculatorFilter.logger.critical( mess, exc_info=True ) elif isinstance( outputMesh, vtkMultiBlockDataSet ): - logger = logging.getLogger( loggerTitle ) - logger.setLevel( logging.INFO ) - logger.addHandler( VTKHandler() ) - logger.propagate = False - - logger.info( f"Apply plugin { logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - logger.addHandler( self.counter ) + self.logger.info( f"Apply plugin { self.logger.name }." ) volumeBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( outputMesh ) for blockIndex in volumeBlockIndexes: @@ -294,8 +303,8 @@ def ApplyFilter( True, ) - if len( geomechanicsCalculatorFilter.logger.handlers ) == 0: - geomechanicsCalculatorFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, geomechanicsCalculatorFilter.logger ): + geomechanicsCalculatorFilter.setLoggerHandler( self.handler ) geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus geomechanicsCalculatorFilter.physicalConstants.specificDensity = self.specificDensity @@ -305,7 +314,7 @@ def ApplyFilter( try: geomechanicsCalculatorFilter.applyFilter() # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter - self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.counter.warningCount ) + self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.nbWarnings ) volumeBlock.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) volumeBlock.Modified() @@ -316,12 +325,14 @@ def ApplyFilter( mess = f"The filter { geomechanicsCalculatorFilter.logger.name } failed due to:\n{ e }" geomechanicsCalculatorFilter.logger.critical( mess, exc_info=True ) - result: str = f"The filter { logger.name } succeeded" + result: str = f"The filter { self.logger.name } succeeded" if self.counter.warningCount > 0: - logger.warning( f"{ result } but { self.counter.warningCount } warnings have been logged." ) + self.logger.warning( f"{ result } but { self.counter.warningCount } warnings have been logged." ) else: - logger.info( f"{ result }." ) + self.logger.info( f"{ result }." ) outputMesh.Modified() + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() return 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 45990eac6..cde160269 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py @@ -16,7 +16,7 @@ update_paths() from geos.utils.Errors import VTKError -from geos.utils.Logger import CountWarningHandler +from geos.utils.Logger import ( CountWarningHandler, getLoggerHandlerType ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_GRAIN_BULK_MODULUS, DEFAULT_ROCK_COHESION, WATER_DENSITY ) @@ -139,9 +139,23 @@ def __init__( self: Self ) -> None: self.rockCohesion: float = DEFAULT_ROCK_COHESION self.frictionAngle: float = DEFAULT_FRICTION_ANGLE_DEG + self.handler: logging.Handler = VTKHandler() self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) - self.logger.addHandler( VTKHandler() ) + self.logger.addHandler( self.handler ) + self.logger.propagate = False + + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) + + self.logger.addHandler( self.counter ) @smproperty.doublevector( name="GrainBulkModulus", @@ -323,10 +337,6 @@ def RequestData( int: 1 if calculation successfully ended, 0 otherwise. """ self.logger.info( f"Apply plugin { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) try: self.volumeMesh = self.GetOutputData( outInfoVec, 0 ) @@ -351,6 +361,9 @@ def RequestData( mess: str = f"The filter { self.logger.name } failed due to:\n{ e }" self.logger.critical( mess, exc_info=True ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return 1 def applyPVGeosBlockExtractAndMerge( self: Self ) -> None: @@ -359,7 +372,7 @@ def applyPVGeosBlockExtractAndMerge( self: Self ) -> None: extractAndMergeFilter.SetInputConnection( self.GetInputConnection( 0, 0 ) ) extractAndMergeFilter.Update() # Add to the warning counter the number of warning logged with the call of GeosBlockExtractAndMerge plugin - self.counter.addExternalWarningCount( extractAndMergeFilter.counter.warningCount ) + self.counter.addExternalWarningCount( extractAndMergeFilter.nbWarnings ) self.volumeMesh.ShallowCopy( extractAndMergeFilter.GetOutputDataObject( 0 ) ) self.volumeMesh.Modified() @@ -388,7 +401,7 @@ def applyPVGeomechanicsCalculator( self: Self ) -> None: geomechanicsCalculatorPlugin.setFrictionAngle( self.frictionAngle ) geomechanicsCalculatorPlugin.Update() # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator plugin - self.counter.addExternalWarningCount( geomechanicsCalculatorPlugin.counter.warningCount ) + self.counter.addExternalWarningCount( geomechanicsCalculatorPlugin.nbWarnings ) self.volumeMesh.ShallowCopy( geomechanicsCalculatorPlugin.GetOutputDataObject( 0 ) ) self.volumeMesh.Modified() @@ -404,7 +417,7 @@ def applyPVSurfaceGeomechanics( self: Self ) -> None: surfaceGeomechanicsPlugin.a02SetFrictionAngle( self.frictionAngle ) surfaceGeomechanicsPlugin.Update() # Add to the warning counter the number of warning logged with the call of SurfaceGeomechanics plugin - self.counter.addExternalWarningCount( surfaceGeomechanicsPlugin.counter.warningCount ) + self.counter.addExternalWarningCount( surfaceGeomechanicsPlugin.nbWarnings ) self.faultMesh.ShallowCopy( surfaceGeomechanicsPlugin.GetOutputDataObject( 0 ) ) self.faultMesh.Modified() 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 098fc3eed..381f983b9 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py @@ -23,7 +23,7 @@ from geos.utils.Errors import VTKError from geos.utils.pieceEnum import Piece -from geos.utils.Logger import CountWarningHandler +from geos.utils.Logger import ( CountWarningHandler, getLoggerHandlerType ) from geos.utils.GeosOutputsConstants import ( GeosMeshOutputsEnum, GeosDomainNameEnum, getAttributeToTransferFromInitialTime ) @@ -129,11 +129,24 @@ def __init__( self: Self ) -> None: self.outputCellsT0: vtkMultiBlockDataSet = vtkMultiBlockDataSet() + self.handler: logging.Handler = VTKHandler() self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) - self.logger.addHandler( VTKHandler() ) + self.logger.addHandler( self.handler ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) + + self.logger.addHandler( self.counter ) + def RequestDataObject( self: Self, request: vtkInformation, @@ -271,12 +284,6 @@ def RequestData( # First time step, compute the initial properties (useful for geomechanics analyses) if self.requestDataStep == 0: - self.logger.info( f"Apply plugin { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) - self.logger.info( f"Apply the plugin { self.logger.name } for the first time step to get the initial properties." ) try: @@ -332,4 +339,7 @@ def RequestData( mess = f"The plugin { self.logger.name } failed due to:\n{ e }" self.logger.critical( mess, exc_info=True ) + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return 1 diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py index 6459db270..cd0deab47 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py @@ -39,6 +39,7 @@ from geos.pv.geosLogReaderUtils.GeosLogReaderWells import GeosLogReaderWells from geos.utils.enumUnits import ( Mass, MassRate, Pressure, Time, Unit, Volume, VolumetricRate, enumerationDomainUnit ) from geos.utils.UnitRepository import UnitRepository +from geos.utils.Logger import ( CountWarningHandler, getLoggerHandlerType ) from geos.pv.utils.checkboxFunction import createModifiedCallback # type: ignore[attr-defined] from geos.pv.utils.paraviewTreatments import strListToEnumerationDomainXml @@ -59,6 +60,8 @@ """ +loggerTitle: str = "Geos Log Reader" + @smproxy.reader( name="PVGeosLogReader", @@ -147,12 +150,23 @@ def __init__( self: Self ) -> None: for prop in propsSolvers: self.m_convergence.AddArray( prop ) - self.logger: logging.Logger = logging.getLogger( "Geos Log Reader" ) + self.handler: logging.Handler = VTKHandler() + self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) - if len( self.logger.handlers ) == 0: - self.logger.addHandler( VTKHandler() ) + self.logger.addHandler( self.handler ) self.logger.propagate = False - self.logger.info( f"Apply plugin { self.logger.name }." ) + + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) + + self.logger.addHandler( self.counter ) @smproperty.stringvector( name="DataFilepath", default_values="Enter a filepath to your data" ) @smdomain.filelist() @@ -577,8 +591,17 @@ def RequestData( array_type=VTK_DOUBLE ) # type: ignore[no-untyped-call] newAttr.SetName( column ) output.AddColumn( newAttr ) - self.logger.info( f"The plugin { self.logger.name } succeeded." ) + + 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 }." ) except Exception as e: self.logger.error( f"The plugin { self.logger.name } failed.\n{ e }" ) return 0 + + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return 1 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 7ea683160..c452a721d 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py @@ -35,7 +35,7 @@ from geos.utils.Logger import CountWarningHandler from geos.utils.enumUnits import Pressure, enumerationDomainUnit from geos.utils.GeosOutputsConstants import ( FAILURE_ENVELOPE, GeosMeshOutputsEnum ) -from geos.utils.Logger import CustomLoggerFormatter +from geos.utils.Logger import ( CountWarningHandler, getLoggerHandlerType ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_ROCK_COHESION ) from geos.mesh.utils.arrayHelpers import getArrayInObject @@ -88,6 +88,8 @@ * Click on `Refresh Data` (you may have to click twice to refresh the Python view correctly). """ +loggerTitle: str = "Mohr Circle" + @smproxy.filter( name="PVMohrCirclePlot", label="Plot Mohr's Circles" ) @smhint.xml( f""" @@ -173,14 +175,23 @@ def __init__( self: Self ) -> None: # Request data processing step - incremented each time RequestUpdateExtent is called self.requestDataStep: int = -1 - # Logger - self.logger: logging.Logger = logging.getLogger( "MohrCircle" ) + self.handler: logging.Handler = VTKHandler() + self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) - if len( self.logger.handlers ) == 0: - handler = VTKHandler() - handler.setFormatter( CustomLoggerFormatter( False ) ) + self.logger.addHandler( self.handler ) + self.logger.propagate = False + + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) - self.logger.addHandler( handler ) + self.logger.addHandler( self.counter ) @smproperty.xml( """ None: # friction angle (°) self.frictionAngle: float = DEFAULT_FRICTION_ANGLE_DEG + self.handler: logging.Handler = VTKHandler() self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) - self.logger.addHandler( VTKHandler() ) + self.logger.addHandler( self.handler ) self.logger.propagate = False + counter: CountWarningHandler = CountWarningHandler() + self.counter: CountWarningHandler + self.nbWarnings: int = 0 + try: + self.counter = getLoggerHandlerType( type( counter ), self.logger ) + self.counter.resetWarningCount() + except: + self.counter = counter + self.counter.setLevel( logging.INFO ) + + self.logger.addHandler( self.counter ) + @smproperty.doublevector( name="RockCohesion", label="Rock Cohesion (Pa)", @@ -125,10 +138,6 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul outputMesh (vtkMultiBlockDataSet): The output multiblock mesh with converted attributes and SCU. """ self.logger.info( f"Apply plugin { self.logger.name }." ) - # Add the handler to count warnings messages to the logger. - self.counter: CountWarningHandler = CountWarningHandler() - self.counter.setLevel( logging.INFO ) - self.logger.addHandler( self.counter ) outputMesh.ShallowCopy( inputMesh ) @@ -138,8 +147,9 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul loggerName: str = f"Surface geomechanics for the blockIndex { blockIndex }" sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( surfaceBlock, loggerName, True ) - if len( sgFilter.logger.handlers ) == 0: - sgFilter.SetLoggerHandler( VTKHandler() ) + + if not isHandlerInLogger( self.handler, sgFilter.logger ): + sgFilter.SetLoggerHandler( self.handler ) sgFilter.SetRockCohesion( self._getRockCohesion() ) sgFilter.SetFrictionAngle( self._getFrictionAngle() ) @@ -147,7 +157,7 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul try: sgFilter.applyFilter() # Add to the warning counter the number of warning logged with the call of SurfaceGeomechanics filter - self.counter.addExternalWarningCount( sgFilter.counter.warningCount ) + self.counter.addExternalWarningCount( sgFilter.nbWarnings ) outputSurface: vtkPolyData = sgFilter.GetOutputMesh() @@ -170,6 +180,9 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul self.logger.info( f"{ result }." ) outputMesh.Modified() + self.nbWarnings = self.counter.warningCount + self.counter.resetWarningCount() + return def _getFrictionAngle( self: Self ) -> float: diff --git a/geos-pv/src/geos/pv/plugins/qc/PVCellTypeCounterEnhanced.py b/geos-pv/src/geos/pv/plugins/qc/PVCellTypeCounterEnhanced.py index ac9fa837b..44e99ced4 100644 --- a/geos-pv/src/geos/pv/plugins/qc/PVCellTypeCounterEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/qc/PVCellTypeCounterEnhanced.py @@ -3,6 +3,7 @@ # SPDX-FileContributor: Martin Lemay # ruff: noqa: E402 # disable Module level import not at top of file import sys +import logging from pathlib import Path from typing_extensions import Self from typing import Optional @@ -26,6 +27,7 @@ from geos.processing.pre_processing.CellTypeCounterEnhanced import CellTypeCounterEnhanced from geos.mesh.model.CellTypeCounts import CellTypeCounts from geos.pv.utils.details import FilterCategory +from geos.utils.Logger import isHandlerInLogger __doc__ = f""" The ``Cell Type Counter Enhanced`` filter computes cell type counts. Counts can be exported into a file easily. @@ -58,6 +60,8 @@ def __init__( self: Self ) -> None: # used to concatenate results if vtkMultiBlockDataSet self._countsAll: CellTypeCounts = CellTypeCounts() + self.handler: logging.Handler = VTKHandler() + @smproperty.intvector( name="SetSaveToFile", label="Save to file", @@ -137,8 +141,8 @@ def RequestData( assert outputTable is not None, "Output pipeline is null." cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( inputMesh, True ) - if len( cellTypeCounterEnhancedFilter.logger.handlers ) == 0: - cellTypeCounterEnhancedFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, cellTypeCounterEnhancedFilter.logger ): + cellTypeCounterEnhancedFilter.setLoggerHandler( self.handler ) try: cellTypeCounterEnhancedFilter.applyFilter() diff --git a/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py b/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py index 90a40b990..421cbc1aa 100644 --- a/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py @@ -33,6 +33,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 __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. @@ -69,6 +70,8 @@ def __init__( self: Self ) -> None: self._saveToFile: bool = True self._blockIndex: int = 0 + self.handler: logging.Handler = VTKHandler() + # Used to concatenate results if vtkMultiBlockDataSet self._metricsAll: list[ float ] = [] @@ -231,8 +234,9 @@ def ApplyFilter( self, inputMesh: vtkUnstructuredGrid, outputMesh: vtkUnstructur otherMetrics: set[ int ] = self._getQualityMetricsToUse( self._commonMeshQualityMetric ) meshQualityEnhancedFilter: MeshQualityEnhanced = MeshQualityEnhanced( inputMesh, True ) - if len( meshQualityEnhancedFilter.logger.handlers ) == 0: - meshQualityEnhancedFilter.setLoggerHandler( VTKHandler() ) + if not isHandlerInLogger( self.handler, meshQualityEnhancedFilter.logger ): + meshQualityEnhancedFilter.setLoggerHandler( self.handler ) + meshQualityEnhancedFilter.SetCellQualityMetrics( triangleMetrics=triangleMetrics, quadMetrics=quadMetrics, tetraMetrics=tetraMetrics, @@ -240,6 +244,7 @@ def ApplyFilter( self, inputMesh: vtkUnstructuredGrid, outputMesh: vtkUnstructur wedgeMetrics=wedgeMetrics, hexaMetrics=hexaMetrics ) meshQualityEnhancedFilter.SetOtherMeshQualityMetrics( otherMetrics ) + try: meshQualityEnhancedFilter.applyFilter() outputMesh.ShallowCopy( meshQualityEnhancedFilter.getOutput() ) diff --git a/geos-pv/src/geos/pv/utils/workflowFunctions.py b/geos-pv/src/geos/pv/utils/workflowFunctions.py index ed327354a..1a66f1a78 100644 --- a/geos-pv/src/geos/pv/utils/workflowFunctions.py +++ b/geos-pv/src/geos/pv/utils/workflowFunctions.py @@ -2,9 +2,10 @@ # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Romain Baville # ruff: noqa: E402 # disable Module level import not at top of file +import logging from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge -from geos.utils.Logger import CountWarningHandler +from geos.utils.Logger import ( CountWarningHandler, isHandlerInLogger ) from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet @@ -36,12 +37,13 @@ def doExtractAndMerge( extractFault=extractFault, extractWell=extractWell, speHandler=True ) - if len( blockExtractor.logger.handlers ) == 0: - blockExtractor.setLoggerHandler( VTKHandler() ) + handler: logging.Handler = VTKHandler() + if not isHandlerInLogger( handler, blockExtractor.logger ): + blockExtractor.setLoggerHandler( handler ) blockExtractor.applyFilter() # Add to the warning counter the number of warning logged with the call of GeosBlockExtractor filter - warningCounter.addExternalWarningCount( blockExtractor.counter.warningCount ) + warningCounter.addExternalWarningCount( blockExtractor.nbWarnings ) # recover output objects from GeosBlockExtractor filter and merge internal blocks volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume @@ -82,11 +84,13 @@ def mergeBlocksFilter( """ loggerName = f"GEOS Block Merge for the domain { domainToMerge }" mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( mesh, convertSurfaces, True, loggerName ) - if len( mergeBlockFilter.logger.handlers ) == 0: - mergeBlockFilter.setLoggerHandler( VTKHandler() ) + handler: logging.Handler = VTKHandler() + if not isHandlerInLogger( handler, mergeBlockFilter.logger ): + mergeBlockFilter.setLoggerHandler( handler ) + mergeBlockFilter.applyFilter() # Add to the warning counter the number of warning logged with the call of GeosBlockMerge filter - warningCounter.addExternalWarningCount( mergeBlockFilter.counter.warningCount ) + warningCounter.addExternalWarningCount( mergeBlockFilter.nbWarnings ) mergedBlocks: vtkMultiBlockDataSet = vtkMultiBlockDataSet() mergedBlocks.ShallowCopy( mergeBlockFilter.getOutput() ) diff --git a/geos-utils/src/geos/utils/Logger.py b/geos-utils/src/geos/utils/Logger.py index aec057136..1d92191ac 100644 --- a/geos-utils/src/geos/utils/Logger.py +++ b/geos-utils/src/geos/utils/Logger.py @@ -105,8 +105,13 @@ def __init__( self: Self ) -> None: super().__init__() self.warningCount = 0 - def resetWarningCount( self: Self ) -> None: - """Reset the warning counter to 0.""" + def resetWarningCount( self: Self, value: int = 0 ) -> None: + """Set the warning counter to a specific value. + + Args: + value (optional, int): The value to set for the warning counter. + Defaults to 0. + """ self.warningCount = 0 def addExternalWarningCount( self: Self, externalWarningCount: int ) -> None: @@ -127,6 +132,62 @@ def emit( self: Self, record: logging.LogRecord ) -> None: self.warningCount += 1 +def getLoggerHandlerType( handlerType: type, logger: logging.Logger ) -> logging.Handler: + """Get the logger handler with a certain type. + + Args: + handlerType (type): The type of the handler of interest. + logger (logging.Logger): The logger to check. + + Returns: + logging.Handler: The first logger handler with the correct type. + + Raises: + ValueError: The logger has no handler with the wanted type. + """ + listLoggerHandlers: list[ logging.Handler ] = logger.handlers + for loggerHandler in listLoggerHandlers: + if type( loggerHandler ) == handlerType: + return loggerHandler + + raise ValueError( "The logger has no handler with the wanted type." ) + + +def hasLoggerHandlerType( handlerType: type, logger: logging.Logger ) -> bool: + """Check if the logger has a handler with a certain type. + + Args: + handlerType (type): The type of the handler of interest. + logger (logging.Logger): The logger to check. + + Returns: + bool: True if the logger has a handler with the same type, False otherwise. + """ + listLoggerHandlers: list[ logging.Handler ] = logger.handlers + for loggerHandler in listLoggerHandlers: + if type( loggerHandler ) == handlerType: + return True + + return False + +def isHandlerInLogger( handler: logging.Handler, logger: logging.Logger ) -> bool: + """Check if the handler is in the logger. + + Args: + handler (logging.Handler): The handler of interest. + logger (logging.Logger): The logger to check. + + Returns: + bool: True if the logger has the handler, False otherwise. + """ + listLoggerHandlers: list[ logging.Handler ] = logger.handlers + for loggerHandler in listLoggerHandlers: + if type( handler ) == type( loggerHandler ) and loggerHandler.__dict__ == handler.__dict__: + return True + + return False + + # Add the convenience method for the logger def results( self: logging.Logger, message: str, *args: Any, **kws: Any ) -> None: """Logs a message with the custom 'RESULTS' severity level. From bee55eb3cb1ba332718796fa46644cc30920bc6f Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Tue, 3 Feb 2026 09:24:01 +0100 Subject: [PATCH 08/10] Fix ruff --- .../generic_processing_tools/AttributeMapping.py | 2 +- .../generic_processing_tools/ClipToMainFrame.py | 2 +- .../CreateConstantAttributePerRegion.py | 2 +- .../generic_processing_tools/FillPartialArrays.py | 2 +- .../generic_processing_tools/MergeBlockEnhanced.py | 2 +- .../processing/generic_processing_tools/SplitMesh.py | 2 +- .../post_processing/GeomechanicsCalculator.py | 2 +- .../processing/post_processing/GeosBlockExtractor.py | 2 +- .../geos/processing/post_processing/GeosBlockMerge.py | 2 +- .../processing/post_processing/SurfaceGeomechanics.py | 2 +- .../pre_processing/CellTypeCounterEnhanced.py | 2 +- .../processing/pre_processing/MeshQualityEnhanced.py | 2 +- .../post_processing/PVGeomechanicsCalculator.py | 4 ++-- .../plugins/post_processing/PVGeomechanicsWorkflow.py | 2 +- .../post_processing/PVGeosBlockExtractAndMerge.py | 2 +- .../pv/plugins/post_processing/PVGeosLogReader.py | 2 +- .../pv/plugins/post_processing/PVMohrCirclePlot.py | 4 ++-- .../plugins/post_processing/PVSurfaceGeomechanics.py | 2 +- .../src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py | 4 +--- geos-utils/src/geos/utils/Logger.py | 11 ++++------- 20 files changed, 25 insertions(+), 30 deletions(-) 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 b58de2fb3..42841de7b 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py @@ -117,7 +117,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 dde25e6f4..88ad34efa 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py @@ -243,7 +243,7 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 89adbce7b..1e4d75bc0 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py @@ -137,7 +137,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 4dbcc2b88..044347708 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py @@ -104,7 +104,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 6e472396f..c311bc34a 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py @@ -97,7 +97,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 77f358d3e..c27204649 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/SplitMesh.py @@ -90,7 +90,7 @@ def __init__( self, inputMesh: vtkUnstructuredGrid, speHandler: bool = False ) - try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py index 5c71438f7..db9887f3a 100644 --- a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py +++ b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py @@ -718,7 +718,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py index e5db0d4d0..5c12bc193 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py @@ -199,7 +199,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py index ea67be97a..88afdf9a2 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py @@ -117,7 +117,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py index 9964971f4..fddd0218e 100644 --- a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py +++ b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py @@ -125,7 +125,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py index 8def50e9a..9dd791112 100644 --- a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py @@ -83,7 +83,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py index af73dd9aa..99855ef3d 100644 --- a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py +++ b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py @@ -148,7 +148,7 @@ def __init__( try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 2084de0a5..693a5f5f0 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsCalculator.py @@ -105,7 +105,7 @@ def __init__( self: Self ) -> None: try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) @@ -261,7 +261,7 @@ def ApplyFilter( geomechanicsCalculatorFilter = GeomechanicsCalculator( outputMesh, self.computeAdvancedProperties, - loggerName= "Geomechanics Calculators on the unstructured grid", + loggerName="Geomechanics Calculators on the unstructured grid", speHandler=True, ) 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 cde160269..a92d99d3e 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py @@ -151,7 +151,7 @@ def __init__( self: Self ) -> None: try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 381f983b9..b84c10b70 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosBlockExtractAndMerge.py @@ -141,7 +141,7 @@ def __init__( self: Self ) -> None: try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py index cd0deab47..9d25b940a 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py @@ -162,7 +162,7 @@ def __init__( self: Self ) -> None: try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) 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 ee22e8585..00fbe5b56 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py @@ -35,7 +35,7 @@ from geos.utils.Logger import CountWarningHandler from geos.utils.enumUnits import Pressure, enumerationDomainUnit from geos.utils.GeosOutputsConstants import ( FAILURE_ENVELOPE, GeosMeshOutputsEnum ) -from geos.utils.Logger import ( CountWarningHandler, getLoggerHandlerType ) +from geos.utils.Logger import ( getLoggerHandlerType ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_ROCK_COHESION ) from geos.mesh.utils.arrayHelpers import getArrayInObject @@ -193,7 +193,7 @@ def __init__( self: Self ) -> None: try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py b/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py index 88ed00a0e..96972f6b8 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py @@ -82,7 +82,7 @@ def __init__( self: Self ) -> None: try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() - except: + except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) diff --git a/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py b/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py index 421cbc1aa..d959b1e89 100644 --- a/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/qc/PVMeshQualityEnhanced.py @@ -59,9 +59,7 @@ """ -@SISOFilter( category=FilterCategory.QC, - decoratedLabel="Mesh Quality Enhanced", - decoratedType="vtkUnstructuredGrid" ) +@SISOFilter( category=FilterCategory.QC, decoratedLabel="Mesh Quality Enhanced", decoratedType="vtkUnstructuredGrid" ) class PVMeshQualityEnhanced( VTKPythonAlgorithmBase ): def __init__( self: Self ) -> None: diff --git a/geos-utils/src/geos/utils/Logger.py b/geos-utils/src/geos/utils/Logger.py index 1d92191ac..a3ef92b26 100644 --- a/geos-utils/src/geos/utils/Logger.py +++ b/geos-utils/src/geos/utils/Logger.py @@ -112,7 +112,7 @@ def resetWarningCount( self: Self, value: int = 0 ) -> None: value (optional, int): The value to set for the warning counter. Defaults to 0. """ - self.warningCount = 0 + self.warningCount = value def addExternalWarningCount( self: Self, externalWarningCount: int ) -> None: """Add external warning count. @@ -147,7 +147,7 @@ def getLoggerHandlerType( handlerType: type, logger: logging.Logger ) -> logging """ listLoggerHandlers: list[ logging.Handler ] = logger.handlers for loggerHandler in listLoggerHandlers: - if type( loggerHandler ) == handlerType: + if isinstance( type( loggerHandler ), handlerType ): return loggerHandler raise ValueError( "The logger has no handler with the wanted type." ) @@ -164,11 +164,8 @@ def hasLoggerHandlerType( handlerType: type, logger: logging.Logger ) -> bool: bool: True if the logger has a handler with the same type, False otherwise. """ listLoggerHandlers: list[ logging.Handler ] = logger.handlers - for loggerHandler in listLoggerHandlers: - if type( loggerHandler ) == handlerType: - return True + return any( isinstance( type( loggerHandler ), handlerType ) for loggerHandler in listLoggerHandlers ) - return False def isHandlerInLogger( handler: logging.Handler, logger: logging.Logger ) -> bool: """Check if the handler is in the logger. @@ -182,7 +179,7 @@ def isHandlerInLogger( handler: logging.Handler, logger: logging.Logger ) -> boo """ listLoggerHandlers: list[ logging.Handler ] = logger.handlers for loggerHandler in listLoggerHandlers: - if type( handler ) == type( loggerHandler ) and loggerHandler.__dict__ == handler.__dict__: + if isinstance( type( handler ), type( loggerHandler ) ) and loggerHandler.__dict__ == handler.__dict__: return True return False From 921118e8222dd43a00f42b5935d163d0fb98a6e9 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Tue, 3 Feb 2026 10:43:01 +0100 Subject: [PATCH 09/10] Add the tests for the new logger helper functions --- geos-utils/src/geos/utils/Logger.py | 6 +- geos-utils/tests/test_Logger.py | 132 ++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 geos-utils/tests/test_Logger.py diff --git a/geos-utils/src/geos/utils/Logger.py b/geos-utils/src/geos/utils/Logger.py index a3ef92b26..fdb4dcff6 100644 --- a/geos-utils/src/geos/utils/Logger.py +++ b/geos-utils/src/geos/utils/Logger.py @@ -147,7 +147,7 @@ def getLoggerHandlerType( handlerType: type, logger: logging.Logger ) -> logging """ listLoggerHandlers: list[ logging.Handler ] = logger.handlers for loggerHandler in listLoggerHandlers: - if isinstance( type( loggerHandler ), handlerType ): + if type( loggerHandler ) is handlerType: return loggerHandler raise ValueError( "The logger has no handler with the wanted type." ) @@ -164,7 +164,7 @@ def hasLoggerHandlerType( handlerType: type, logger: logging.Logger ) -> bool: bool: True if the logger has a handler with the same type, False otherwise. """ listLoggerHandlers: list[ logging.Handler ] = logger.handlers - return any( isinstance( type( loggerHandler ), handlerType ) for loggerHandler in listLoggerHandlers ) + return any( type( loggerHandler ) is handlerType for loggerHandler in listLoggerHandlers ) def isHandlerInLogger( handler: logging.Handler, logger: logging.Logger ) -> bool: @@ -179,7 +179,7 @@ def isHandlerInLogger( handler: logging.Handler, logger: logging.Logger ) -> boo """ listLoggerHandlers: list[ logging.Handler ] = logger.handlers for loggerHandler in listLoggerHandlers: - if isinstance( type( handler ), type( loggerHandler ) ) and loggerHandler.__dict__ == handler.__dict__: + if type( handler ) is type( loggerHandler ) and loggerHandler.__dict__ == handler.__dict__: return True return False diff --git a/geos-utils/tests/test_Logger.py b/geos-utils/tests/test_Logger.py new file mode 100644 index 000000000..087bf1f84 --- /dev/null +++ b/geos-utils/tests/test_Logger.py @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. +# SPDX-FileContributor: Romain Baville +# ruff: noqa: E402 # disable Module level import not at top of file +import pytest +import random +import logging + +import geos.utils.Logger as internLogger + +def test_CountWarningHandler() -> None: + """Test the counter handler class and its methods.""" + loggerTest: logging.Logger = logging.getLogger( "Test CountWarningHandler") + loggerTest.setLevel( logging.INFO ) + loggerTest.propagate = False + + countWarningHandler: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + countWarningHandler.setLevel( logging.INFO ) + + loggerTest.addHandler( countWarningHandler ) + + nbWarnings: int = random.randint( 0, 10 ) + for warning in range( nbWarnings ): + loggerTest.warning( f"Warning number { warning }." ) + assert countWarningHandler.warningCount == nbWarnings + + additionalWarnings: int = random.randint( 1, 10 ) + countWarningHandler.addExternalWarningCount( additionalWarnings ) + assert countWarningHandler.warningCount == nbWarnings + additionalWarnings + + resetValue: int = random.randint( 0, 10 ) + countWarningHandler.resetWarningCount( resetValue ) + assert countWarningHandler.warningCount == resetValue + + loggerTest.warning( "Add a warning after the handler reset." ) + assert countWarningHandler.warningCount == resetValue + 1 + + +def test_getLoggerHandlerType() -> None: + """Test the function to get a logger's handler with a certain type.""" + loggerTest: logging.Logger = logging.getLogger( "Test getLoggerHandlerType") + loggerTest.setLevel( logging.INFO ) + loggerTest.propagate = False + + handler1: logging.Handler = logging.Handler() + handler1.setLevel( logging.INFO ) + handlerType1: type = type( handler1 ) + loggerTest.addHandler( handler1 ) + + handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2.setLevel( logging.INFO ) + handlerType2: type = type( handler2 ) + loggerTest.addHandler( handler2 ) + + handler3: logging.Handler = logging.Handler() + handler3.setLevel( logging.INFO ) + handlerType3: type = type( handler3 ) + loggerTest.addHandler( handler3 ) + + handlerTest1: logging.Handler = internLogger.getLoggerHandlerType( handlerType1, loggerTest ) + handlerTest2: logging.Handler = internLogger.getLoggerHandlerType( handlerType2, loggerTest ) + handlerTest3: logging.Handler = internLogger.getLoggerHandlerType( handlerType3, loggerTest ) + + assert type( handlerTest1 ) is handlerType1 + assert type( handlerTest2 ) is handlerType2 + assert type( handlerTest3 ) is handlerType3 + assert handlerTest3.__dict__ == handler1.__dict__ # If multiple Handler have the same type the first one is return + + +def test_getLoggerHandlerTypeValueError() -> None: + """Test the ValueError raises of the getLoggerHandlerType function.""" + loggerTest: logging.Logger = logging.getLogger( "Test getLoggerHandlerType raises") + loggerTest.setLevel( logging.INFO ) + loggerTest.propagate = False + + handler1: logging.Handler = logging.Handler() + handler1.setLevel( logging.INFO ) + handlerType1: type = type( handler1 ) + + # Test with a empty logger + with pytest.raises( ValueError ): + handlerTest1: logging.Handler = internLogger.getLoggerHandlerType( handlerType1, loggerTest ) + + loggerTest.addHandler( handler1 ) + + handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2.setLevel( logging.INFO ) + handlerType2: type = type( handler2 ) + + # Test with a logger with an other type of handler + with pytest.raises( ValueError ): + handlerTest2: logging.Handler = internLogger.getLoggerHandlerType( handlerType2, loggerTest ) + + +def test_hasLoggerHandlerType() -> None: + """Test the function to check if a logger has a handler of a certain type.""" + loggerTest: logging.Logger = logging.getLogger( "Test hasLoggerHandlerType") + loggerTest.setLevel( logging.INFO ) + loggerTest.propagate = False + + handler1: logging.Handler = logging.Handler() + handler1.setLevel( logging.INFO ) + handlerType1: type = type( handler1 ) + loggerTest.addHandler( handler1 ) + + handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2.setLevel( logging.INFO ) + handlerType2: type = type( handler2 ) + + assert internLogger.hasLoggerHandlerType( handlerType1, loggerTest ) + assert not internLogger.hasLoggerHandlerType( handlerType2, loggerTest ) + + +def test_isHandlerInLogger() -> None: + """Test the function to check if a logger has a handler.""" + loggerTest: logging.Logger = logging.getLogger( "Test isHandlerInLogger") + loggerTest.setLevel( logging.INFO ) + loggerTest.propagate = False + + handler1: logging.Handler = logging.Handler() + handler1.setLevel( logging.INFO ) + loggerTest.addHandler( handler1 ) + + handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2.setLevel( logging.INFO ) + + handler3: logging.Handler = logging.Handler() + handler3.setLevel( logging.INFO ) + + assert internLogger.isHandlerInLogger( handler1, loggerTest ) + assert not internLogger.isHandlerInLogger( handler2, loggerTest ) + assert not internLogger.isHandlerInLogger( handler3, loggerTest ) # Same type but the handler is different From b67ca56aa5858fc1c040d8e06889847182dfebe7 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Tue, 3 Feb 2026 10:46:07 +0100 Subject: [PATCH 10/10] Fix ruff --- geos-utils/tests/test_Logger.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/geos-utils/tests/test_Logger.py b/geos-utils/tests/test_Logger.py index 087bf1f84..ba9adf188 100644 --- a/geos-utils/tests/test_Logger.py +++ b/geos-utils/tests/test_Logger.py @@ -8,9 +8,10 @@ import geos.utils.Logger as internLogger + def test_CountWarningHandler() -> None: """Test the counter handler class and its methods.""" - loggerTest: logging.Logger = logging.getLogger( "Test CountWarningHandler") + loggerTest: logging.Logger = logging.getLogger( "Test CountWarningHandler" ) loggerTest.setLevel( logging.INFO ) loggerTest.propagate = False @@ -38,7 +39,7 @@ def test_CountWarningHandler() -> None: def test_getLoggerHandlerType() -> None: """Test the function to get a logger's handler with a certain type.""" - loggerTest: logging.Logger = logging.getLogger( "Test getLoggerHandlerType") + loggerTest: logging.Logger = logging.getLogger( "Test getLoggerHandlerType" ) loggerTest.setLevel( logging.INFO ) loggerTest.propagate = False @@ -69,7 +70,7 @@ def test_getLoggerHandlerType() -> None: def test_getLoggerHandlerTypeValueError() -> None: """Test the ValueError raises of the getLoggerHandlerType function.""" - loggerTest: logging.Logger = logging.getLogger( "Test getLoggerHandlerType raises") + loggerTest: logging.Logger = logging.getLogger( "Test getLoggerHandlerType raises" ) loggerTest.setLevel( logging.INFO ) loggerTest.propagate = False @@ -79,7 +80,7 @@ def test_getLoggerHandlerTypeValueError() -> None: # Test with a empty logger with pytest.raises( ValueError ): - handlerTest1: logging.Handler = internLogger.getLoggerHandlerType( handlerType1, loggerTest ) + internLogger.getLoggerHandlerType( handlerType1, loggerTest ) loggerTest.addHandler( handler1 ) @@ -89,12 +90,12 @@ def test_getLoggerHandlerTypeValueError() -> None: # Test with a logger with an other type of handler with pytest.raises( ValueError ): - handlerTest2: logging.Handler = internLogger.getLoggerHandlerType( handlerType2, loggerTest ) + internLogger.getLoggerHandlerType( handlerType2, loggerTest ) def test_hasLoggerHandlerType() -> None: """Test the function to check if a logger has a handler of a certain type.""" - loggerTest: logging.Logger = logging.getLogger( "Test hasLoggerHandlerType") + loggerTest: logging.Logger = logging.getLogger( "Test hasLoggerHandlerType" ) loggerTest.setLevel( logging.INFO ) loggerTest.propagate = False @@ -113,7 +114,7 @@ def test_hasLoggerHandlerType() -> None: def test_isHandlerInLogger() -> None: """Test the function to check if a logger has a handler.""" - loggerTest: logging.Logger = logging.getLogger( "Test isHandlerInLogger") + loggerTest: logging.Logger = logging.getLogger( "Test isHandlerInLogger" ) loggerTest.setLevel( logging.INFO ) loggerTest.propagate = False