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 d1bf2185..fd563a8f 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.pieceEnum import Piece __doc__ = """ @@ -111,8 +111,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -209,6 +209,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() 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 4654e6ee..2bb34fde 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.genericHelpers import getMultiBlockBounds __doc__ = """ @@ -237,8 +237,8 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -259,6 +259,7 @@ def Update( self ) -> None: # type: ignore[override] else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() 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 da781558..d9aa75a3 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.arrayHelpers import ( getArrayInObject, getComponentNames, getAttributePieceInfo, getVtkArrayTypeInObject, getNumberOfComponents, checkValidValuesInObject ) from geos.mesh.utils.arrayModifiers import ( createAttribute, createConstantAttribute ) @@ -129,8 +129,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -407,6 +407,7 @@ def _logOutputMessage( self: Self, trueIndexes: list[ Any ] ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() 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 2c901473..284c0a81 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.arrayModifiers import fillPartialAttributes from geos.mesh.utils.arrayHelpers import getAttributePieceInfo @@ -98,8 +98,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -162,6 +162,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() 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 88f366fc..88e33ab6 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.mesh.utils.multiblockModifiers import mergeBlocks from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkUnstructuredGrid @@ -91,8 +91,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -134,6 +134,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() 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 2695c8f8..886d2c9c 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.processing.pre_processing.CellTypeCounterEnhanced import CellTypeCounterEnhanced from geos.mesh.model.CellTypeCounts import CellTypeCounts @@ -84,8 +84,8 @@ def __init__( self, inputMesh: vtkUnstructuredGrid, speHandler: bool = False ) - self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -189,6 +189,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() diff --git a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py index 8b902092..70630458 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, 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,8 +712,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -768,6 +768,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the CountVerbosityHandler in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py index b0adcf06..5f78037a 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.GeosOutputsConstants import GeosDomainNameEnum from geos.mesh.utils.arrayHelpers import getCellDimension from geos.mesh.utils.multiblockHelpers import getBlockIndexFromName @@ -193,8 +193,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -245,6 +245,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py index 57074422..3ee1e79d 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.GeosOutputsConstants import ( PHASE_SEP, PhaseTypeEnum, FluidPrefixEnum, PostProcessingOutputsEnum, getRockSuffixRenaming ) @@ -111,8 +111,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -198,6 +198,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() diff --git a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py index 7fbf71a5..cf1d97d7 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_ROCK_COHESION ) from geos.utils.GeosOutputsConstants import ( ComponentNameEnum, GeosMeshOutputsEnum, PostProcessingOutputsEnum ) @@ -65,7 +65,7 @@ # Do calculations try: sg.applyFilter() - except ( ValueError, VTKError, AttributeError, AssertionError ) as e: + except ( ValueError, VTKError, AttributeError, AssertionError, TypeError ) as e: sg.logger.error( f"The filter { sg.logger.name } failed due to: { e }" ) except Exception as e: mess: str = f"The filter { sg.logger.name } failed due to: { e }" @@ -119,8 +119,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -131,9 +131,6 @@ def __init__( 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.inputMesh: vtkPolyData = surfacicMesh # Identification of the input surface (logging purpose) self.name: Union[ str, None ] = None @@ -241,6 +238,7 @@ def applyFilter( self: Self ) -> None: """Compute Geomechanical properties on input surface. Raises: + TypeError: Error With the type of the input mesh. ValueError: Errors during the creation of an attribute. VTKError: Error raises during the call of VTK function. AttributeError: Attributes must be on cell. @@ -248,6 +246,10 @@ def applyFilter( self: Self ) -> None: """ self.logger.info( f"Apply filter { self.logger.name }." ) + # Input surfacic mesh + if not self.inputMesh.IsA( "vtkPolyData" ): + raise TypeError( f"Input surface is expected to be a vtkPolyData, not a { type( self.inputMesh ) }." ) + self.outputMesh = vtkPolyData() self.outputMesh.ShallowCopy( self.inputMesh ) @@ -265,6 +267,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() @@ -352,6 +355,9 @@ def __computeXYZCoordinates( Returns: npt.NDArray[np.float64]: Vector of new coordinates of the attribute. + + Raises: + ValueError: Error with the shape of attrArray or the computation of the attribute coordinate. """ attrXYZ: npt.NDArray[ np.float64 ] = np.full_like( attrArray, np.nan ) @@ -369,17 +375,12 @@ def __computeXYZCoordinates( attrXYZ[ i ] = convertAttributeFromLocalToXYZForOneCell( cellAttribute, cellLocalBasis ) if not np.any( np.isfinite( attrXYZ ) ): - self.logger.error( "Attribute new coordinate calculation failed." ) + raise ValueError( "Attribute new coordinate calculation failed." ) return attrXYZ def computeShearCapacityUtilization( self: Self ) -> None: - """Compute the shear capacity utilization (SCU) on surface. - - Raises: - ValueError: Something went wrong during the creation of an attribute. - AssertionError: Something went wrong during the shearCapacityUtilization computation. - """ + """Compute the shear capacity utilization (SCU) on surface.""" SCUAttributeName: str = PostProcessingOutputsEnum.SCU.attributeName if not isAttributeInObject( self.outputMesh, SCUAttributeName, self.attributePiece ): diff --git a/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py b/geos-processing/src/geos/processing/pre_processing/CellTypeCounterEnhanced.py index 6f739109..107a77cb 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) __doc__ = """ CellTypeCounterEnhanced module is a vtk filter that computes cell type counts. @@ -77,8 +77,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -139,6 +139,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() diff --git a/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py b/geos-processing/src/geos/processing/pre_processing/MeshQualityEnhanced.py index 0e75daff..d299bdc6 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( getLogger, Logger, CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) from geos.utils.pieceEnum import Piece __doc__ = """ @@ -142,8 +142,8 @@ def __init__( self.logger.setLevel( logging.INFO ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) @@ -324,6 +324,7 @@ def applyFilter( self: Self ) -> None: else: self.logger.info( f"{ result }." ) + # Keep number of warnings logged during the filter application and reset the warnings count in case the filter is apply again. self.nbWarnings = self.counter.warningCount self.counter.resetWarningCount() diff --git a/geos-processing/tests/test_SurfaceGeomechanics.py b/geos-processing/tests/test_SurfaceGeomechanics.py index a073ad48..e59191e1 100644 --- a/geos-processing/tests/test_SurfaceGeomechanics.py +++ b/geos-processing/tests/test_SurfaceGeomechanics.py @@ -6,7 +6,7 @@ import pytest from typing import Any -from vtkmodules.vtkCommonDataModel import vtkPolyData +from vtkmodules.vtkCommonDataModel import vtkPolyData, vtkUnstructuredGrid from geos.processing.post_processing.SurfaceGeomechanics import SurfaceGeomechanics @@ -23,7 +23,14 @@ def test_SurfaceGeomechanics( dataSetTest: Any ) -> None: assert mesh.GetCellData().HasArray( "displacementJump_XYZ" ) -def test_failingSurfaceGeomechanics() -> None: +def test_SurfaceGeomechanicsTypeError() -> None: + """Test failing of SurfaceGeomechanics with a vtkUnstructuredGrid as input mesh.""" + sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( vtkUnstructuredGrid() ) + with pytest.raises( TypeError ): + sgFilter.applyFilter() + + +def test_SurfaceGeomechanicsAttributeError() -> None: """Test failing of SurfaceGeomechanics due to absence of attributes in the mesh.""" sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( vtkPolyData() ) with pytest.raises( AttributeError ): 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 693a5f5f..6cee2983 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, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( CountVerbosityHandler, 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 ) @@ -99,12 +99,14 @@ def __init__( self: Self ) -> None: self.logger.addHandler( self.handler ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 + self.nbErrors: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() + self.counter.resetErrorCount() except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) @@ -275,64 +277,82 @@ 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) + # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.nbWarnings ) outputMesh.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) except ( ValueError, AttributeError ) as e: geomechanicsCalculatorFilter.logger.error( f"The filter { geomechanicsCalculatorFilter.logger.name } failed due to:\n{ e }" ) + # The logger of the filter is used to log the error, the CountVerbosityHandler of the plugin must be updated + self.counter.addExternalErrorCount( 1 ) except Exception as e: mess = f"The filter { geomechanicsCalculatorFilter.logger.name } failed due to:\n{ e }" geomechanicsCalculatorFilter.logger.critical( mess, exc_info=True ) + # The logger of the filter is used to log the error, the CountVerbosityHandler of the plugin must be updated + self.counter.addExternalErrorCount( 1 ) elif isinstance( outputMesh, vtkMultiBlockDataSet ): self.logger.info( f"Apply plugin { self.logger.name }." ) - volumeBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( outputMesh ) - for blockIndex in volumeBlockIndexes: - volumeBlock: vtkUnstructuredGrid = vtkUnstructuredGrid.SafeDownCast( - outputMesh.GetDataSet( blockIndex ) ) - volumeBlockName: str = getBlockNameFromIndex( outputMesh, blockIndex ) - filterName: str = f"Geomechanics Calculator for the block { volumeBlockName }" - - geomechanicsCalculatorFilter = GeomechanicsCalculator( - volumeBlock, - self.computeAdvancedProperties, - filterName, - True, - ) - - if not isHandlerInLogger( self.handler, geomechanicsCalculatorFilter.logger ): - geomechanicsCalculatorFilter.setLoggerHandler( self.handler ) - - geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus - geomechanicsCalculatorFilter.physicalConstants.specificDensity = self.specificDensity - geomechanicsCalculatorFilter.physicalConstants.rockCohesion = self.rockCohesion - geomechanicsCalculatorFilter.physicalConstants.frictionAngle = self.frictionAngle - - try: - geomechanicsCalculatorFilter.applyFilter() - # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter - self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.nbWarnings ) - - volumeBlock.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) - volumeBlock.Modified() - except ( ValueError, AttributeError ) as e: - geomechanicsCalculatorFilter.logger.error( - f"The filter { geomechanicsCalculatorFilter.logger.name } failed due to:\n{ e }" ) - except Exception as e: - mess = f"The filter { geomechanicsCalculatorFilter.logger.name } failed due to:\n{ e }" - geomechanicsCalculatorFilter.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 }." ) + try: + volumeBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( outputMesh ) + for blockIndex in volumeBlockIndexes: + volumeBlock: vtkUnstructuredGrid = vtkUnstructuredGrid.SafeDownCast( + outputMesh.GetDataSet( blockIndex ) ) + volumeBlockName: str = getBlockNameFromIndex( outputMesh, blockIndex ) + filterName: str = f"Geomechanics Calculator for the block { volumeBlockName }" + + geomechanicsCalculatorFilter = GeomechanicsCalculator( + volumeBlock, + self.computeAdvancedProperties, + filterName, + True, + ) + + if not isHandlerInLogger( self.handler, geomechanicsCalculatorFilter.logger ): + geomechanicsCalculatorFilter.setLoggerHandler( self.handler ) + + geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus + geomechanicsCalculatorFilter.physicalConstants.specificDensity = self.specificDensity + geomechanicsCalculatorFilter.physicalConstants.rockCohesion = self.rockCohesion + geomechanicsCalculatorFilter.physicalConstants.frictionAngle = self.frictionAngle + + try: + geomechanicsCalculatorFilter.applyFilter() + # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator filter + self.counter.addExternalWarningCount( geomechanicsCalculatorFilter.nbWarnings ) + + volumeBlock.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) + volumeBlock.Modified() + except ( ValueError, AttributeError ) as e: + geomechanicsCalculatorFilter.logger.error( f"The filter { filterName } failed due to:\n{ e }" ) + raise ChildProcessError( f"Error during the processing of: { filterName }." ) from e + except Exception as e: + mess = f"The filter { filterName } failed due to:\n{ e }" + geomechanicsCalculatorFilter.logger.critical( mess, exc_info=True ) + raise ChildProcessError( f"Critical error during the processing of: { filterName }." ) from e + + result: str = f"The plugin { 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 ChildProcessError as e: + self.logger.error( f"The plugin { self.logger.name } failed due to:\n{ e }" ) + except Exception as e: + mess = f"The plugin { self.logger.name } failed due to:\n{ e }" + self.logger.critical( mess, exc_info=True ) outputMesh.Modified() + + # Keep number of verbosity logged during the plugin application self.nbWarnings = self.counter.warningCount + self.nbErrors = self.counter.errorCount + + # Reset the CountVerbosityHandler in case the plugin is apply again self.counter.resetWarningCount() + self.counter.resetErrorCount() 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 0b446062..2dc17cf2 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeomechanicsWorkflow.py @@ -15,8 +15,7 @@ update_paths() -from geos.utils.Errors import VTKError -from geos.utils.Logger import ( CountWarningHandler, getLoggerHandlerType ) +from geos.utils.Logger import ( CountVerbosityHandler, getLoggerHandlerType ) from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_GRAIN_BULK_MODULUS, DEFAULT_ROCK_COHESION, WATER_DENSITY ) @@ -145,12 +144,14 @@ def __init__( self: Self ) -> None: self.logger.addHandler( self.handler ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 + self.nbErrors: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() + self.counter.resetErrorCount() except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) @@ -355,14 +356,19 @@ def RequestData( else: self.logger.info( f"{ result }." ) - except ( ValueError, VTKError, AttributeError, AssertionError ) as e: + except ChildProcessError as e: self.logger.error( f"The plugin { self.logger.name } failed due to:\n{ e }" ) except Exception as e: mess: str = f"The plugin { self.logger.name } failed due to:\n{ e }" self.logger.critical( mess, exc_info=True ) + # Keep number of verbosity logged during the plugin application self.nbWarnings = self.counter.warningCount + self.nbErrors = self.counter.errorCount + + # Reset the CountVerbosityHandler in case the plugin is apply again self.counter.resetWarningCount() + self.counter.resetErrorCount() return 1 @@ -373,6 +379,10 @@ def applyPVGeosBlockExtractAndMerge( self: Self ) -> None: extractAndMergeFilter.Update() # Add to the warning counter the number of warning logged with the call of GeosBlockExtractAndMerge plugin self.counter.addExternalWarningCount( extractAndMergeFilter.nbWarnings ) + # Add to the error counter the number of error logged with the call of GeosBlockExtractAndMerge plugin + self.counter.addExternalErrorCount( extractAndMergeFilter.nbErrors ) + if self.counter.errorCount != 0: + raise ChildProcessError( "Error during the processing of the plugin PVGeosBlockExtractAndMerge." ) self.volumeMesh.ShallowCopy( extractAndMergeFilter.GetOutputDataObject( 0 ) ) self.volumeMesh.Modified() @@ -402,6 +412,10 @@ def applyPVGeomechanicsCalculator( self: Self ) -> None: geomechanicsCalculatorPlugin.Update() # Add to the warning counter the number of warning logged with the call of GeomechanicsCalculator plugin self.counter.addExternalWarningCount( geomechanicsCalculatorPlugin.nbWarnings ) + # Add to the error counter the number of error logged with the call of GeomechanicsCalculator plugin + self.counter.addExternalErrorCount( geomechanicsCalculatorPlugin.nbErrors ) + if self.counter.errorCount != 0: + raise ChildProcessError( "Error during the processing of the plugin PVGeomechanicsCalculators." ) self.volumeMesh.ShallowCopy( geomechanicsCalculatorPlugin.GetOutputDataObject( 0 ) ) self.volumeMesh.Modified() @@ -418,6 +432,10 @@ def applyPVSurfaceGeomechanics( self: Self ) -> None: surfaceGeomechanicsPlugin.Update() # Add to the warning counter the number of warning logged with the call of SurfaceGeomechanics plugin self.counter.addExternalWarningCount( surfaceGeomechanicsPlugin.nbWarnings ) + # Add to the error counter the number of error logged with the call of SurfaceGeomechanics plugin + self.counter.addExternalErrorCount( surfaceGeomechanicsPlugin.nbErrors ) + if self.counter.errorCount != 0: + raise ChildProcessError( "Error during the processing of the plugin PVSurfaceGeomechanics." ) 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 dff27de7..131bd649 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, getLoggerHandlerType ) +from geos.utils.Logger import ( CountVerbosityHandler, getLoggerHandlerType ) from geos.utils.GeosOutputsConstants import ( GeosMeshOutputsEnum, GeosDomainNameEnum, getAttributeToTransferFromInitialTime ) @@ -135,12 +135,14 @@ def __init__( self: Self ) -> None: self.logger.addHandler( self.handler ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 + self.nbErrors: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() + self.counter.resetErrorCount() except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) @@ -289,12 +291,17 @@ def RequestData( try: doExtractAndMerge( inputMesh, self.outputCellsT0, vtkMultiBlockDataSet(), vtkMultiBlockDataSet(), self.extractFault, self.extractWell, self.counter ) + # Initialize time step iteration 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 }" ) + self.resetPlugin() + return 1 except Exception as e: mess = f"The plugin { self.logger.name } failed due to:\n{ e }" self.logger.critical( mess, exc_info=True ) + self.resetPlugin() + return 1 # Current time step, extract, merge, rename and transfer properties if self.requestDataStep == self.currentTimeStepIndex: @@ -322,24 +329,34 @@ def RequestData( if cellCenterAttributeName not in meshAttributes: createCellCenterAttribute( outputCells, cellCenterAttributeName, logger=self.logger ) - # Stop the time step iteration - request.Remove( executive.CONTINUE_EXECUTING() ) - - # Set to -2 in case time changes on Paraview - self.requestDataStep = -2 - result: str = f"The plugin { 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: + except ChildProcessError as e: self.logger.error( f"The plugin { self.logger.name } failed due to:\n{ e }" ) except Exception as e: 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() + # Stop the time step iteration + request.Remove( executive.CONTINUE_EXECUTING() ) + self.resetPlugin() return 1 + + def resetPlugin( self: Self ) -> None: + """Reset the plugin variable to be apply again.""" + # Set to -2 in case time changes on Paraview + self.requestDataStep = -2 + + # Keep number of verbosity logged during the plugin application + self.nbWarnings = self.counter.warningCount + self.nbErrors = self.counter.errorCount + + # Reset the CountVerbosityHandler in case the plugin is apply again + self.counter.resetWarningCount() + self.counter.resetErrorCount() + + return 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 4b8aea9f..0626496c 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVGeosLogReader.py @@ -39,7 +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.utils.Logger import ( CountVerbosityHandler, getLoggerHandlerType ) from geos.pv.utils.checkboxFunction import createModifiedCallback # type: ignore[attr-defined] from geos.pv.utils.paraviewTreatments import strListToEnumerationDomainXml @@ -156,8 +156,8 @@ def __init__( self: Self ) -> None: self.logger.addHandler( self.handler ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) 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 e3ff2585..ae9e7561 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVMohrCirclePlot.py @@ -32,7 +32,7 @@ from geos.geomechanics.model.MohrCircle import MohrCircle from geos.utils.pieceEnum import Piece -from geos.utils.Logger import CountWarningHandler +from geos.utils.Logger import CountVerbosityHandler from geos.utils.enumUnits import Pressure, enumerationDomainUnit from geos.utils.GeosOutputsConstants import ( FAILURE_ENVELOPE, GeosMeshOutputsEnum ) from geos.utils.Logger import ( getLoggerHandlerType ) @@ -187,8 +187,8 @@ def __init__( self: Self ) -> None: self.logger.addHandler( self.handler ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) 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 2cbc5ba2..93ccc1ee 100644 --- a/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py +++ b/geos-pv/src/geos/pv/plugins/post_processing/PVSurfaceGeomechanics.py @@ -22,7 +22,7 @@ update_paths() from geos.utils.Errors import VTKError -from geos.utils.Logger import ( CountWarningHandler, isHandlerInLogger, getLoggerHandlerType ) +from geos.utils.Logger import ( CountVerbosityHandler, isHandlerInLogger, getLoggerHandlerType ) 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 ) @@ -76,12 +76,14 @@ def __init__( self: Self ) -> None: self.logger.addHandler( self.handler ) self.logger.propagate = False - counter: CountWarningHandler = CountWarningHandler() - self.counter: CountWarningHandler + counter: CountVerbosityHandler = CountVerbosityHandler() + self.counter: CountVerbosityHandler self.nbWarnings: int = 0 + self.nbErrors: int = 0 try: self.counter = getLoggerHandlerType( type( counter ), self.logger ) self.counter.resetWarningCount() + self.counter.resetErrorCount() except ValueError: self.counter = counter self.counter.setLevel( logging.INFO ) @@ -140,48 +142,60 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul self.logger.info( f"Apply plugin { self.logger.name }." ) outputMesh.ShallowCopy( inputMesh ) - - surfaceBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( inputMesh ) - for blockIndex in surfaceBlockIndexes: - surfaceBlock: vtkPolyData = vtkPolyData.SafeDownCast( getBlockFromFlatIndex( outputMesh, blockIndex ) ) - - loggerName: str = f"Surface geomechanics for the blockIndex { blockIndex }" - sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( surfaceBlock, loggerName, True ) - - if not isHandlerInLogger( self.handler, sgFilter.logger ): - sgFilter.SetLoggerHandler( self.handler ) - - sgFilter.SetRockCohesion( self._getRockCohesion() ) - sgFilter.SetFrictionAngle( self._getFrictionAngle() ) - - try: - sgFilter.applyFilter() - # Add to the warning counter the number of warning logged with the call of SurfaceGeomechanics filter - self.counter.addExternalWarningCount( sgFilter.nbWarnings ) - - outputSurface: vtkPolyData = sgFilter.GetOutputMesh() - - # add attributes to output surface mesh - for attributeName in sgFilter.GetNewAttributeNames(): - attr: vtkDataArray = outputSurface.GetCellData().GetArray( attributeName ) - surfaceBlock.GetCellData().AddArray( attr ) - surfaceBlock.GetCellData().Modified() - surfaceBlock.Modified() - except ( ValueError, VTKError, AttributeError, AssertionError ) as e: - sgFilter.logger.error( f"The filter { sgFilter.logger.name } failed due to:\n{ e }" ) - except Exception as e: - mess: str = f"The filter { sgFilter.logger.name } failed due to:\n{ e }" - sgFilter.logger.critical( mess, exc_info=True ) - - result: str = f"The plugin { 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() + try: + surfaceBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( inputMesh ) + for blockIndex in surfaceBlockIndexes: + surfaceBlock: vtkPolyData = vtkPolyData.SafeDownCast( getBlockFromFlatIndex( outputMesh, blockIndex ) ) + + loggerName: str = f"Surface geomechanics for the blockIndex { blockIndex }" + sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( surfaceBlock, loggerName, True ) + + if not isHandlerInLogger( self.handler, sgFilter.logger ): + sgFilter.SetLoggerHandler( self.handler ) + + sgFilter.SetRockCohesion( self._getRockCohesion() ) + sgFilter.SetFrictionAngle( self._getFrictionAngle() ) + + try: + sgFilter.applyFilter() + # Add to the warning counter the number of warning logged with the call of SurfaceGeomechanics filter + self.counter.addExternalWarningCount( sgFilter.nbWarnings ) + + outputSurface: vtkPolyData = sgFilter.GetOutputMesh() + + # add attributes to output surface mesh + for attributeName in sgFilter.GetNewAttributeNames(): + attr: vtkDataArray = outputSurface.GetCellData().GetArray( attributeName ) + surfaceBlock.GetCellData().AddArray( attr ) + surfaceBlock.GetCellData().Modified() + surfaceBlock.Modified() + except ( ValueError, VTKError, AttributeError, AssertionError, TypeError ) as e: + sgFilter.logger.error( f"The filter { loggerName } failed due to:\n{ e }" ) + raise ChildProcessError( f"Error during the processing of: { loggerName }." ) from e + except Exception as e: + mess: str = f"The filter { loggerName } failed due to:\n{ e }" + sgFilter.logger.critical( mess, exc_info=True ) + raise ChildProcessError( f"Critical error during the processing of: { loggerName }." ) from e + + result: str = f"The plugin { 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 ChildProcessError as e: + self.logger.error( f"The plugin { self.logger.name } failed due to:\n{ e }" ) + except Exception as e: + mess = f"The plugin { self.logger.name } failed due to:\n{ e }" + self.logger.critical( mess, exc_info=True ) + + # Keep number of verbosity logged during the plugin application self.nbWarnings = self.counter.warningCount + self.nbErrors = self.counter.errorCount + + # Reset the CountVerbosityHandler in case the plugin is apply again self.counter.resetWarningCount() + self.counter.resetErrorCount() return diff --git a/geos-pv/src/geos/pv/utils/workflowFunctions.py b/geos-pv/src/geos/pv/utils/workflowFunctions.py index 1a66f1a7..460e2028 100644 --- a/geos-pv/src/geos/pv/utils/workflowFunctions.py +++ b/geos-pv/src/geos/pv/utils/workflowFunctions.py @@ -5,7 +5,8 @@ import logging from geos.processing.post_processing.GeosBlockExtractor import GeosBlockExtractor from geos.processing.post_processing.GeosBlockMerge import GeosBlockMerge -from geos.utils.Logger import ( CountWarningHandler, isHandlerInLogger ) +from geos.utils.Logger import ( CountVerbosityHandler, isHandlerInLogger ) +from geos.utils.Errors import VTKError from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet @@ -19,7 +20,7 @@ def doExtractAndMerge( outputWells: vtkMultiBlockDataSet, extractFault: bool, extractWell: bool, - warningCounter: CountWarningHandler, + verbosityCounter: CountVerbosityHandler, ) -> None: """Apply block extraction and merge. @@ -30,7 +31,10 @@ 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. + verbosityCounter (logging.Handler): The plugin Handler to update with the number of verbosity logged during the call of the extract and merge filters. + + Raises: + ChildProcessError: Error during the call of GeosBlockMerge or GeosBlockExtractor filter. """ # Extract blocks blockExtractor: GeosBlockExtractor = GeosBlockExtractor( mesh, @@ -41,23 +45,32 @@ def doExtractAndMerge( 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.nbWarnings ) + try: + blockExtractor.applyFilter() + except ( ValueError, TypeError ) as e: + blockExtractor.logger.error( f"The filter { blockExtractor.logger.name } failed due to: { e }." ) + raise ChildProcessError( f"Error during the processing of: { blockExtractor.logger.name }." ) from e + except Exception as e: + mess: str = f"The filter { blockExtractor.logger.name } failed du to: { e }" + blockExtractor.logger.critical( mess, exc_info=True ) + raise ChildProcessError( f"Critical error during the processing of: { blockExtractor.logger.name }." ) from e + + # Add to the warning count the number of warning logged with the call of GeosBlockExtractor filter + verbosityCounter.addExternalWarningCount( blockExtractor.nbWarnings ) # recover output objects from GeosBlockExtractor filter and merge internal blocks volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume - outputCells.ShallowCopy( mergeBlocksFilter( volumeBlockExtracted, warningCounter, False, "Volume" ) ) + outputCells.ShallowCopy( mergeBlocksFilter( volumeBlockExtracted, verbosityCounter, False, "Volume" ) ) outputCells.Modified() if extractFault: faultBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.fault - outputFaults.ShallowCopy( mergeBlocksFilter( faultBlockExtracted, warningCounter, True, "Fault" ) ) + outputFaults.ShallowCopy( mergeBlocksFilter( faultBlockExtracted, verbosityCounter, True, "Fault" ) ) outputFaults.Modified() if extractWell: wellBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.well - outputWells.ShallowCopy( mergeBlocksFilter( wellBlockExtracted, warningCounter, False, "Well" ) ) + outputWells.ShallowCopy( mergeBlocksFilter( wellBlockExtracted, verbosityCounter, False, "Well" ) ) outputWells.Modified() return @@ -65,7 +78,7 @@ def doExtractAndMerge( def mergeBlocksFilter( mesh: vtkMultiBlockDataSet, - warningCounter: CountWarningHandler, + verbosityCounter: CountVerbosityHandler, convertSurfaces: bool = False, domainToMerge: str = "Volume", ) -> vtkMultiBlockDataSet: @@ -73,7 +86,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. + verbosityCounter (logging.Handler): The plugin Handler to update with the number of verbosity logged during the call of the 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. @@ -81,6 +94,9 @@ def mergeBlocksFilter( Returns: vtkMultiBlockDataSet: Mesh composed of internal merged blocks. + + Raises: + ChildProcessError: Error during the call of GeosBlockMerge filter. """ loggerName = f"GEOS Block Merge for the domain { domainToMerge }" mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( mesh, convertSurfaces, True, loggerName ) @@ -88,9 +104,18 @@ def mergeBlocksFilter( 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.nbWarnings ) + try: + mergeBlockFilter.applyFilter() + except ( ValueError, VTKError ) as e: + mergeBlockFilter.logger.error( f"The filter { mergeBlockFilter.logger.name } failed due to: { e }" ) + raise ChildProcessError( f"Error during the processing of: { loggerName }." ) from e + except Exception as e: + mess: str = f"The filter { mergeBlockFilter.logger.name } failed due to: { e }" + mergeBlockFilter.logger.critical( mess, exc_info=True ) + raise ChildProcessError( f"Critical error during the processing of: { loggerName }." ) from e + + # Add to the warning count the number of warning logged with the call of GeosBlockMerge filter + verbosityCounter.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 fdb4dcff..b3846e94 100644 --- a/geos-utils/src/geos/utils/Logger.py +++ b/geos-utils/src/geos/utils/Logger.py @@ -97,13 +97,14 @@ def VTKCaptureLog() -> Generator[ Any, Any, Any ]: os.close( savedStderrFd ) -class CountWarningHandler( logging.Handler ): - """Create an handler to count the warnings logged.""" +class CountVerbosityHandler( logging.Handler ): + """Create an handler to count verbosity logged.""" def __init__( self: Self ) -> None: """Init the handler.""" super().__init__() - self.warningCount = 0 + self.warningCount: int = 0 + self.errorCount: int = 0 def resetWarningCount( self: Self, value: int = 0 ) -> None: """Set the warning counter to a specific value. @@ -114,6 +115,15 @@ def resetWarningCount( self: Self, value: int = 0 ) -> None: """ self.warningCount = value + def resetErrorCount( self: Self, value: int = 0 ) -> None: + """Set the error counter to a specific value. + + Args: + value (optional, int): The value to set for the error counter. + Defaults to 0. + """ + self.errorCount = value + def addExternalWarningCount( self: Self, externalWarningCount: int ) -> None: """Add external warning count. @@ -122,8 +132,16 @@ def addExternalWarningCount( self: Self, externalWarningCount: int ) -> None: """ self.warningCount += externalWarningCount + def addExternalErrorCount( self: Self, externalErrorCount: int ) -> None: + """Add external error count. + + Args: + externalErrorCount (int): An external error count to add to the internal one. + """ + self.errorCount += externalErrorCount + def emit( self: Self, record: logging.LogRecord ) -> None: - """Count all the warnings logged. + """Count all verbosity (warning, error and higher) logged. Args: record (logging.LogRecord): Record. @@ -131,6 +149,9 @@ def emit( self: Self, record: logging.LogRecord ) -> None: if record.levelno == logging.WARNING: self.warningCount += 1 + if record.levelno >= logging.ERROR: + self.errorCount += 1 + def getLoggerHandlerType( handlerType: type, logger: logging.Logger ) -> logging.Handler: """Get the logger handler with a certain type. diff --git a/geos-utils/tests/test_Logger.py b/geos-utils/tests/test_Logger.py index ba9adf18..6b3edde7 100644 --- a/geos-utils/tests/test_Logger.py +++ b/geos-utils/tests/test_Logger.py @@ -10,12 +10,12 @@ def test_CountWarningHandler() -> None: - """Test the counter handler class and its methods.""" + """Test the verbosity counter handler class and its methods for the verbosity warning.""" loggerTest: logging.Logger = logging.getLogger( "Test CountWarningHandler" ) loggerTest.setLevel( logging.INFO ) loggerTest.propagate = False - countWarningHandler: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + countWarningHandler: internLogger.CountVerbosityHandler = internLogger.CountVerbosityHandler() countWarningHandler.setLevel( logging.INFO ) loggerTest.addHandler( countWarningHandler ) @@ -37,6 +37,37 @@ def test_CountWarningHandler() -> None: assert countWarningHandler.warningCount == resetValue + 1 +def test_CountErrorHandler() -> None: + """Test the verbosity counter handler class and its methods for the verbosity error and higher.""" + loggerTest: logging.Logger = logging.getLogger( "Test CountErrorHandler" ) + loggerTest.setLevel( logging.INFO ) + loggerTest.propagate = False + + countErrorHandler: internLogger.CountVerbosityHandler = internLogger.CountVerbosityHandler() + countErrorHandler.setLevel( logging.INFO ) + + loggerTest.addHandler( countErrorHandler ) + + nbErrors: int = random.randint( 0, 10 ) + for error in range( nbErrors ): + loggerTest.error( f"Error number { error }." ) + assert countErrorHandler.errorCount == nbErrors + + additionalErrors: int = random.randint( 1, 10 ) + countErrorHandler.addExternalErrorCount( additionalErrors ) + assert countErrorHandler.errorCount == nbErrors + additionalErrors + + resetValue: int = random.randint( 0, 10 ) + countErrorHandler.resetErrorCount( resetValue ) + assert countErrorHandler.errorCount == resetValue + + loggerTest.error( "Add an error after the handler reset." ) + assert countErrorHandler.errorCount == resetValue + 1 + + loggerTest.critical( "Add a critical error, higher than error but style an error." ) + assert countErrorHandler.errorCount == resetValue + 2 + + def test_getLoggerHandlerType() -> None: """Test the function to get a logger's handler with a certain type.""" loggerTest: logging.Logger = logging.getLogger( "Test getLoggerHandlerType" ) @@ -48,7 +79,7 @@ def test_getLoggerHandlerType() -> None: handlerType1: type = type( handler1 ) loggerTest.addHandler( handler1 ) - handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2: internLogger.CountVerbosityHandler = internLogger.CountVerbosityHandler() handler2.setLevel( logging.INFO ) handlerType2: type = type( handler2 ) loggerTest.addHandler( handler2 ) @@ -84,7 +115,7 @@ def test_getLoggerHandlerTypeValueError() -> None: loggerTest.addHandler( handler1 ) - handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2: internLogger.CountVerbosityHandler = internLogger.CountVerbosityHandler() handler2.setLevel( logging.INFO ) handlerType2: type = type( handler2 ) @@ -104,7 +135,7 @@ def test_hasLoggerHandlerType() -> None: handlerType1: type = type( handler1 ) loggerTest.addHandler( handler1 ) - handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2: internLogger.CountVerbosityHandler = internLogger.CountVerbosityHandler() handler2.setLevel( logging.INFO ) handlerType2: type = type( handler2 ) @@ -122,7 +153,7 @@ def test_isHandlerInLogger() -> None: handler1.setLevel( logging.INFO ) loggerTest.addHandler( handler1 ) - handler2: internLogger.CountWarningHandler = internLogger.CountWarningHandler() + handler2: internLogger.CountVerbosityHandler = internLogger.CountVerbosityHandler() handler2.setLevel( logging.INFO ) handler3: logging.Handler = logging.Handler()