diff --git a/geos-mesh/src/geos/mesh/utils/multiblockModifiers.py b/geos-mesh/src/geos/mesh/utils/multiblockModifiers.py index fad5958e..352860bf 100644 --- a/geos-mesh/src/geos/mesh/utils/multiblockModifiers.py +++ b/geos-mesh/src/geos/mesh/utils/multiblockModifiers.py @@ -8,6 +8,7 @@ vtkUnstructuredGrid, vtkDataSet ) from packaging.version import Version from vtkmodules.vtkCommonCore import vtkLogger +from geos.utils.Errors import VTKError # TODO: remove this condition when all codes are adapted for VTK newest version. import vtk @@ -50,20 +51,21 @@ def mergeBlocks( .. Warning:: This function will not work properly if there are duplicated cell IDs in the different blocks of the input mesh. """ + vtkErrorLogger: Logger if logger is None: - logger = getLogger( "mergeBlocks" ) - # Creation of a child logger to deal with VTKErrors without polluting parent logger - mbLogger: Logger = getLogger( f"{logger.name}.vtkErrorLogger" ) - - mbLogger.propagate = False + vtkErrorLogger = getLogger( "Merge blocks", True ) + else: + vtkErrorLogger = logging.getLogger( f"{ logger.name } vtkError Logger" ) + vtkErrorLogger.setLevel( logging.INFO ) + vtkErrorLogger.addHandler( logger.handlers[ 0 ] ) + vtkErrorLogger.propagate = False vtkLogger.SetStderrVerbosity( vtkLogger.VERBOSITY_ERROR ) - mbLogger.addFilter( RegexExceptionFilter() ) # will raise VTKError if captured VTK Error - mbLogger.setLevel( logging.DEBUG ) + vtkErrorLogger.addFilter( RegexExceptionFilter() ) # will raise VTKError if captured VTK Error # Fill the partial attributes with default values to keep them during the merge. if keepPartialAttributes and not fillAllPartialAttributes( inputMesh, logger ): - logger.warning( "Failed to fill partial attributes. Merging without keeping partial attributes." ) + raise ValueError( "Failed to fill partial attributes. Merging without keeping partial attributes." ) outputMesh: vtkUnstructuredGrid @@ -76,9 +78,10 @@ def mergeBlocks( else: if inputMesh.IsA( "vtkDataSet" ): - logger.warning( "Input mesh is already a single block." ) + vtkErrorLogger.warning( "Input mesh is already a single block." ) outputMesh = vtkUnstructuredGrid.SafeDownCast( inputMesh ) else: + with VTKCaptureLog() as captured_log: af: vtkAppendDataSets = vtkAppendDataSets() @@ -95,8 +98,14 @@ def mergeBlocks( captured_log.seek( 0 ) captured = captured_log.read().decode() - mbLogger.debug( captured.strip() ) + if captured != "": + vtkErrorLogger.error( captured.strip() ) + # raise VTKError( captured.strip() ) + # pass outputMesh = af.GetOutputDataObject( 0 ) + if outputMesh is None: + raise VTKError( "Something went wrong in VTK" ) + return outputMesh diff --git a/geos-mesh/tests/test_multiblockModifiers.py b/geos-mesh/tests/test_multiblockModifiers.py index d240736e..4ae3a0e5 100644 --- a/geos-mesh/tests/test_multiblockModifiers.py +++ b/geos-mesh/tests/test_multiblockModifiers.py @@ -9,6 +9,12 @@ from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkUnstructuredGrid from geos.mesh.utils import multiblockModifiers +from unittest import TestCase +from geos.utils.Errors import VTKError + +import vtk +from packaging.version import Version + @pytest.mark.parametrize( "keepPartialAttributes, nbPointAttributes, nbCellAttributes, nbFieldAttributes", [ ( False, 0, 16, 1 ), @@ -35,3 +41,14 @@ def test_mergeBlocks( assert dataset.GetFieldData().GetNumberOfArrays( ) == nbFieldAttributes, f"Expected {nbFieldAttributes} field attributes after the merge, not {dataset.GetFieldData().GetNumberOfArrays()}." + + +class RaiseMergeBlocks( TestCase ): + """Test failure on empty multiBlockDataSet.""" + + def test_TypeError( self ) -> None: + """Test raise of TypeError.""" + multiBlockDataset = vtkMultiBlockDataSet() # should fail on empty data + if Version( vtk.__version__ ) < Version( "9.5" ): + with pytest.raises( VTKError ): + multiblockModifiers.mergeBlocks( multiBlockDataset, True ) 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 9eb7aa6f..ba7e5852 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/AttributeMapping.py @@ -103,6 +103,7 @@ def __init__( else: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -113,7 +114,7 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: self.logger.addHandler( handler ) else: self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler'" @@ -139,63 +140,64 @@ def applyFilter( self: Self ) -> bool: """ self.logger.info( f"Apply filter { self.logger.name }." ) - if len( self.attributeNames ) == 0: - self.logger.warning( f"Please enter at least one { self.piece } attribute to transfer." ) - self.logger.warning( f"The filter { self.logger.name } has not been used." ) - return False - - attributesInMeshFrom: set[ str ] = getAttributeSet( self.meshFrom, self.onPoints ) - wrongAttributeNames: set[ str ] = self.attributeNames.difference( attributesInMeshFrom ) - if len( wrongAttributeNames ) > 0: - self.logger.error( - f"The { self.piece } attributes { wrongAttributeNames } are not present in the source mesh." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - attributesInMeshTo: set[ str ] = getAttributeSet( self.meshTo, self.onPoints ) - attributesAlreadyInMeshTo: set[ str ] = self.attributeNames.intersection( attributesInMeshTo ) - if len( attributesAlreadyInMeshTo ) > 0: - self.logger.error( - f"The { self.piece } attributes { attributesAlreadyInMeshTo } are already present in the final mesh." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False + try: + if len( self.attributeNames ) == 0: + raise ValueError( f"Please enter at least one { self.piece } attribute to transfer." ) + + attributesInMeshFrom: set[ str ] = getAttributeSet( self.meshFrom, self.onPoints ) + wrongAttributeNames: set[ str ] = self.attributeNames.difference( attributesInMeshFrom ) + if len( wrongAttributeNames ) > 0: + raise AttributeError( + f"The { self.piece } attributes { wrongAttributeNames } are not present in the source mesh." ) + + attributesInMeshTo: set[ str ] = getAttributeSet( self.meshTo, self.onPoints ) + attributesAlreadyInMeshTo: set[ str ] = self.attributeNames.intersection( attributesInMeshTo ) + if len( attributesAlreadyInMeshTo ) > 0: + raise AttributeError( + f"The { self.piece } attributes { attributesAlreadyInMeshTo } are already present in the final mesh." + ) + + if isinstance( self.meshFrom, vtkMultiBlockDataSet ): + partialAttributes: list[ str ] = [] + for attributeName in self.attributeNames: + if not isAttributeGlobal( self.meshFrom, attributeName, self.onPoints ): + partialAttributes.append( attributeName ) + + if len( partialAttributes ) > 0: + raise AttributeError( + f"All { self.piece } attributes to transfer must be global, { partialAttributes } are partials." + ) + + self.ElementMap = computeElementMapping( self.meshFrom, self.meshTo, self.onPoints ) + sharedElement: bool = False + for key in self.ElementMap: + if np.any( self.ElementMap[ key ] > -1 ): + sharedElement = True + + if not sharedElement: + raise ValueError( f"The two meshes do not have any shared { self.piece }." ) - if isinstance( self.meshFrom, vtkMultiBlockDataSet ): - partialAttributes: list[ str ] = [] for attributeName in self.attributeNames: - if not isAttributeGlobal( self.meshFrom, attributeName, self.onPoints ): - partialAttributes.append( attributeName ) - - if len( partialAttributes ) > 0: - self.logger.error( - f"All { self.piece } attributes to transfer must be global, { partialAttributes } are partials." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - - self.ElementMap = computeElementMapping( self.meshFrom, self.meshTo, self.onPoints ) - sharedElement: bool = False - for key in self.ElementMap: - if np.any( self.ElementMap[ key ] > -1 ): - sharedElement = True - - if not sharedElement: - self.logger.warning( f"The two meshes do not have any shared { self.piece }." ) - self.logger.warning( f"The filter { self.logger.name } has not been used." ) + # TODO:: Modify arrayModifiers function to raise error. + if not transferAttributeWithElementMap( self.meshFrom, self.meshTo, self.ElementMap, attributeName, + self.onPoints, self.logger ): + raise + + # Log the output message. + self._logOutputMessage() + except ( TypeError, ValueError, AttributeError ) as e: + self.logger.error( f"The filter { self.logger.name } failed.\n{ e }" ) + return False + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) return False - - for attributeName in self.attributeNames: - if not transferAttributeWithElementMap( self.meshFrom, self.meshTo, self.ElementMap, attributeName, - self.onPoints, self.logger ): - self.logger.error( f"The attribute { attributeName } has not been mapped." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - # Log the output message. - self._logOutputMessage() return True 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 { self.piece } attributes { self.attributeNames } have been transferred from the source" - " mesh to the final mesh with the { self.piece } mapping." ) + self.logger.info( + f"The { self.piece } attributes { self.attributeNames } have been transferred from the source mesh to the final mesh with the { self.piece } mapping." + ) 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 6b95fbba..90a53411 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/ClipToMainFrame.py @@ -234,6 +234,7 @@ def __init__( self, speHandler: bool = False, **properties: str ) -> None: else: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False def ComputeTransform( self ) -> None: """Update the transformation.""" @@ -264,7 +265,7 @@ def SetLoggerHandler( self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: self.logger.addHandler( handler ) else: self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler' to True" 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 85e1fc74..c5fc2c38 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/CreateConstantAttributePerRegion.py @@ -9,10 +9,7 @@ from typing_extensions import Self import vtkmodules.util.numpy_support as vnp -from vtkmodules.vtkCommonDataModel import ( - vtkMultiBlockDataSet, - vtkDataSet, -) +from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkDataSet from geos.utils.Logger import ( getLogger, Logger, CountWarningHandler ) from geos.mesh.utils.arrayHelpers import ( getArrayInObject, getComponentNames, getNumberOfComponents, @@ -134,6 +131,7 @@ def __init__( else: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -144,7 +142,7 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: self.logger.addHandler( handler ) else: # This warning does not count for the number of warning created during the application of the filter. @@ -162,124 +160,119 @@ def applyFilter( self: Self ) -> bool: # Add the handler to count warnings messages. self.logger.addHandler( self.counter ) - # Check the validity of the attribute region. - if self.onPoints is None: - self.logger.error( f"{ self.regionName } is not in the mesh." ) - self.logger.error( f"The new attribute { self.newAttributeName } has not been added." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - if self.onBoth: - self.logger.error( f"There are two attributes named { self.regionName }, one on points" - "and the other on cells. The region attribute must be unique." ) - self.logger.error( f"The new attribute { self.newAttributeName } has not been added." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False + try: + # Check the validity of the attribute region. + if self.onPoints is None: + raise AttributeError( f"{ self.regionName } is not in the mesh." ) + + if self.onBoth: + raise ValueError( + f"There are two attributes named { self.regionName }, one on points and the other on cells. The region attribute must be unique." + ) + + nbComponentsRegion: int = getNumberOfComponents( self.mesh, self.regionName, self.onPoints ) + if nbComponentsRegion != 1: + raise ValueError( f"The region attribute { self.regionName } has to many components, one is requires." ) + + self._setInfoRegion() + # Check if the number of components and number of values for the region indexes are coherent. + for index in self.dictRegionValues: + if len( self.dictRegionValues[ index ] ) != self.nbComponents: + raise ValueError( + f"The number of value given for the region index { index } is not correct. You must set a value for each component, in this case { self.nbComponents }." + ) + + listIndexes: list[ Any ] = list( self.dictRegionValues.keys() ) + validIndexes: list[ Any ] = [] + invalidIndexes: list[ Any ] = [] + regionArray: npt.NDArray[ Any ] + newArray: npt.NDArray[ Any ] + if isinstance( self.mesh, vtkMultiBlockDataSet ): + # Check if the attribute region is global. + if not isAttributeGlobal( self.mesh, self.regionName, self.onPoints ): + raise AttributeError( f"The region attribute { self.regionName } has to be global." ) + + validIndexes, invalidIndexes = checkValidValuesInMultiBlock( self.mesh, self.regionName, listIndexes, + self.onPoints ) + if len( validIndexes ) == 0: + if len( self.dictRegionValues ) == 0: + self.logger.warning( "No region indexes entered." ) + else: + self.logger.warning( + f"The region indexes entered are not in the region attribute { self.regionName }." ) + + if not createConstantAttributeMultiBlock( self.mesh, + self.defaultValue, + self.newAttributeName, + componentNames=self.componentNames, + onPoints=self.onPoints, + logger=self.logger ): + raise - nbComponentsRegion: int = getNumberOfComponents( self.mesh, self.regionName, self.onPoints ) - if nbComponentsRegion != 1: - self.logger.error( f"The region attribute { self.regionName } has to many components, one is requires." ) - self.logger.error( f"The new attribute { self.newAttributeName } has not been added." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - self._setInfoRegion() - # Check if the number of components and number of values for the region indexes are coherent. - for index in self.dictRegionValues: - if len( self.dictRegionValues[ index ] ) != self.nbComponents: - self.logger.error( f"The number of value given for the region index { index } is not correct." - f" You must set a value for each component, in this case { self.nbComponents }." ) - return False - - listIndexes: list[ Any ] = list( self.dictRegionValues.keys() ) - validIndexes: list[ Any ] = [] - invalidIndexes: list[ Any ] = [] - regionArray: npt.NDArray[ Any ] - newArray: npt.NDArray[ Any ] - if isinstance( self.mesh, vtkMultiBlockDataSet ): - # Check if the attribute region is global. - if not isAttributeGlobal( self.mesh, self.regionName, self.onPoints ): - self.logger.error( f"The region attribute { self.regionName } has to be global." ) - self.logger.error( f"The new attribute { self.newAttributeName } has not been added." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - validIndexes, invalidIndexes = checkValidValuesInMultiBlock( self.mesh, self.regionName, listIndexes, - self.onPoints ) - if len( validIndexes ) == 0: - if len( self.dictRegionValues ) == 0: - self.logger.warning( "No region indexes entered." ) else: - self.logger.warning( - f"The region indexes entered are not in the region attribute { self.regionName }." ) - - if not createConstantAttributeMultiBlock( self.mesh, - self.defaultValue, - self.newAttributeName, - componentNames=self.componentNames, - onPoints=self.onPoints, - logger=self.logger ): - self.logger.error( f"The filter { self.logger.name } failed." ) - return False + if len( invalidIndexes ) > 0: + self.logger.warning( + f"The region indexes { invalidIndexes } are not in the region attribute { self.regionName }." + ) + + # Parse the mesh to add the attribute on each dataset. + listFlatIdDataSet: list[ int ] = getBlockElementIndexesFlatten( self.mesh ) + for flatIdDataSet in listFlatIdDataSet: + dataSet: vtkDataSet = vtkDataSet.SafeDownCast( self.mesh.GetDataSet( flatIdDataSet ) ) + + regionArray = getArrayInObject( dataSet, self.regionName, self.onPoints ) + newArray = self._createArrayFromRegionArrayWithValueMap( regionArray ) + if not createAttribute( dataSet, + newArray, + self.newAttributeName, + componentNames=self.componentNames, + onPoints=self.onPoints, + logger=self.logger ): + raise else: - if len( invalidIndexes ) > 0: - self.logger.warning( - f"The region indexes { invalidIndexes } are not in the region attribute { self.regionName }." ) + validIndexes, invalidIndexes = checkValidValuesInDataSet( self.mesh, self.regionName, listIndexes, + self.onPoints ) + if len( validIndexes ) == 0: + if len( self.dictRegionValues ) == 0: + self.logger.warning( "No region indexes entered." ) + else: + self.logger.warning( + f"The region indexes entered are not in the region attribute { self.regionName }." ) + + if not createConstantAttributeDataSet( self.mesh, + self.defaultValue, + self.newAttributeName, + componentNames=self.componentNames, + onPoints=self.onPoints, + logger=self.logger ): + raise - # Parse the mesh to add the attribute on each dataset. - listFlatIdDataSet: list[ int ] = getBlockElementIndexesFlatten( self.mesh ) - for flatIdDataSet in listFlatIdDataSet: - dataSet: vtkDataSet = vtkDataSet.SafeDownCast( self.mesh.GetDataSet( flatIdDataSet ) ) + else: + if len( invalidIndexes ) > 0: + self.logger.warning( + f"The region indexes { invalidIndexes } are not in the region attribute { self.regionName }." + ) - regionArray = getArrayInObject( dataSet, self.regionName, self.onPoints ) + regionArray = getArrayInObject( self.mesh, self.regionName, self.onPoints ) newArray = self._createArrayFromRegionArrayWithValueMap( regionArray ) - if not createAttribute( dataSet, + if not createAttribute( self.mesh, newArray, self.newAttributeName, componentNames=self.componentNames, onPoints=self.onPoints, logger=self.logger ): - self.logger.error( f"The filter { self.logger.name } failed." ) - return False + raise - else: - validIndexes, invalidIndexes = checkValidValuesInDataSet( self.mesh, self.regionName, listIndexes, - self.onPoints ) - if len( validIndexes ) == 0: - if len( self.dictRegionValues ) == 0: - self.logger.warning( "No region indexes entered." ) - else: - self.logger.warning( - f"The region indexes entered are not in the region attribute { self.regionName }." ) - - if not createConstantAttributeDataSet( self.mesh, - self.defaultValue, - self.newAttributeName, - componentNames=self.componentNames, - onPoints=self.onPoints, - logger=self.logger ): - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - else: - if len( invalidIndexes ) > 0: - self.logger.warning( - f"The region indexes { invalidIndexes } are not in the region attribute { self.regionName }." ) - - regionArray = getArrayInObject( self.mesh, self.regionName, self.onPoints ) - newArray = self._createArrayFromRegionArrayWithValueMap( regionArray ) - if not createAttribute( self.mesh, - newArray, - self.newAttributeName, - componentNames=self.componentNames, - onPoints=self.onPoints, - logger=self.logger ): - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - # Log the output message. - self._logOutputMessage( validIndexes ) + # Log the output message. + self._logOutputMessage( validIndexes ) + except ( ValueError, AttributeError ) as e: + self.logger.error( f"The filter { self.logger.name } failed.\n{ e }" ) + return False + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) + return False return True 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 feb56198..22d7275a 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/FillPartialArrays.py @@ -1,11 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Romain Baville, Martin Lemay - +import logging from typing_extensions import Self from typing import Union, Any -from geos.utils.Logger import logging, Logger, getLogger +from geos.utils.Logger import ( Logger, getLogger ) from geos.mesh.utils.arrayModifiers import fillPartialAttributes from geos.mesh.utils.arrayHelpers import getAttributePieceInfo @@ -89,6 +89,7 @@ def __init__( else: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -99,7 +100,7 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: self.logger.addHandler( handler ) else: self.logger.warning( "The logger already has an handler, to use yours set the argument 'speHandler' to True" @@ -112,32 +113,33 @@ def applyFilter( self: Self ) -> bool: boolean (bool): True if calculation successfully ended, False otherwise. """ self.logger.info( f"Apply filter { self.logger.name }." ) - - onPoints: Union[ None, bool ] - onBoth: bool - for attributeName in self.dictAttributesValues: - onPoints, onBoth = getAttributePieceInfo( self.multiBlockDataSet, attributeName ) - if onPoints is None: - self.logger.error( f"{ attributeName } is not in the mesh." ) - self.logger.error( f"The attribute { attributeName } has not been filled." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - if onBoth: - self.logger.error( f"There is two attribute named { attributeName }," - " one on points and the other on cells. The attribute must be unique." ) - self.logger.error( f"The attribute { attributeName } has not been filled." ) - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - if not fillPartialAttributes( self.multiBlockDataSet, - attributeName, - onPoints=onPoints, - listValues=self.dictAttributesValues[ attributeName ], - logger=self.logger ): - self.logger.error( f"The filter { self.logger.name } failed." ) - return False - - self.logger.info( f"The filter { self.logger.name } succeed." ) + try: + onPoints: Union[ None, bool ] + onBoth: bool + for attributeName in self.dictAttributesValues: + onPoints, onBoth = getAttributePieceInfo( self.multiBlockDataSet, attributeName ) + if onPoints is None: + raise ValueError( f"{ attributeName } is not in the mesh." ) + + if onBoth: + raise ValueError( + f"There is two attribute named { attributeName }, one on points and the other on cells. The attribute name must be unique." + ) + + if not fillPartialAttributes( self.multiBlockDataSet, + attributeName, + onPoints=onPoints, + listValues=self.dictAttributesValues[ attributeName ], + logger=self.logger ): + raise + + self.logger.info( f"The filter { self.logger.name } succeed." ) + except ( ValueError, AttributeError ) as e: + self.logger.error( f"The filter { self.logger.name } failed.\n{ e }" ) + return False + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) + return False return True 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 9bcfa573..4630d642 100644 --- a/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py +++ b/geos-processing/src/geos/processing/generic_processing_tools/MergeBlockEnhanced.py @@ -6,13 +6,11 @@ from typing_extensions import Self -from geos.utils.Logger import Logger, getLogger +from geos.utils.Logger import ( Logger, getLogger ) from geos.mesh.utils.multiblockModifiers import mergeBlocks +from geos.utils.Errors import VTKError -from vtkmodules.vtkCommonDataModel import ( - vtkMultiBlockDataSet, - vtkUnstructuredGrid, -) +from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkUnstructuredGrid __doc__ = """ Merge Blocks Keeping Partial Attributes is a filter that allows to merge blocks from a multiblock dataset @@ -34,7 +32,6 @@ from geos.processing.generic_processing_tools.MergeBlockEnhanced import MergeBlockEnhanced import logging - from geos.utils.Errors import VTKError # Define filter inputs multiblockdataset: vtkMultiblockDataSet @@ -48,10 +45,7 @@ mergeBlockEnhancedFilter.setLoggerHandler( yourHandler ) # Do calculations - try: - mergeBlockEnhancedFilter.applyFilter() - except VTKError: - logging.error("Something went wrong in VTK") + mergeBlockEnhancedFilter.applyFilter() # Get the merged mesh mergeBlockEnhancedFilter.getOutput() @@ -89,6 +83,7 @@ def __init__( else: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -98,26 +93,35 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: 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." ) - def applyFilter( self: Self ) -> None: + def applyFilter( self: Self ) -> bool: """Merge the blocks of a multiblock dataset mesh. Returns: bool: True if the blocks were successfully merged, False otherwise. - - Raises: - VTKError (geos.utils.Errors) : error captured if any from the VTK log """ self.logger.info( f"Applying filter { self.logger.name }." ) - outputMesh: vtkUnstructuredGrid - outputMesh = mergeBlocks( self.inputMesh, keepPartialAttributes=True, logger=self.logger ) - self.outputMesh = outputMesh + try: + outputMesh: vtkUnstructuredGrid + outputMesh = mergeBlocks( self.inputMesh, keepPartialAttributes=True, logger=self.logger ) + self.outputMesh = outputMesh + + self.logger.info( f"The filter { self.logger.name } succeeded." ) + except VTKError as e: + self.logger.error( f"The filter { self.logger.name } failed.\n{ e }" ) + return False + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) + return False + + return True def getOutput( self: Self ) -> vtkUnstructuredGrid: """Get the merged mesh. diff --git a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py index 05340469..2e7677a9 100644 --- a/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py +++ b/geos-processing/src/geos/processing/post_processing/GeomechanicsCalculator.py @@ -13,27 +13,13 @@ import geos.geomechanics.processing.geomechanicsCalculatorFunctions as fcts from geos.mesh.utils.arrayModifiers import createAttribute -from geos.mesh.utils.arrayHelpers import ( - getArrayInObject, - isAttributeInObject, -) - -from geos.utils.Logger import ( - Logger, - getLogger, -) -from geos.utils.GeosOutputsConstants import ( - AttributeEnum, - ComponentNameEnum, - GeosMeshOutputsEnum, - PostProcessingOutputsEnum, -) -from geos.utils.PhysicalConstants import ( - DEFAULT_FRICTION_ANGLE_RAD, - DEFAULT_GRAIN_BULK_MODULUS, - DEFAULT_ROCK_COHESION, - WATER_DENSITY, -) +from geos.mesh.utils.arrayHelpers import ( getArrayInObject, isAttributeInObject ) + +from geos.utils.Logger import ( Logger, getLogger ) +from geos.utils.GeosOutputsConstants import ( AttributeEnum, ComponentNameEnum, GeosMeshOutputsEnum, + PostProcessingOutputsEnum ) +from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_GRAIN_BULK_MODULUS, + DEFAULT_ROCK_COHESION, WATER_DENSITY ) from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid @@ -717,9 +703,14 @@ def __init__( else: self.logger = logging.getLogger( loggerName ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False + + def applyFilter( self: Self ) -> bool: + """Compute the geomechanics properties and create attributes on the mesh. - def applyFilter( self: Self ) -> None: - """Compute the geomechanics properties and create attributes on the mesh.""" + Returns: + bool: True if the filter succeeded, False otherwise. + """ self.logger.info( f"Apply filter { self.logger.name }." ) try: @@ -755,8 +746,13 @@ def applyFilter( self: Self ) -> None: self.logger.info( f"The filter { self.logger.name } succeeded." ) except ( ValueError, TypeError, NameError ) as e: self.logger.error( f"The filter { self.logger.name } failed.\n{ e }" ) + return False + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) + return False - return + return True def getOutput( self: Self ) -> vtkUnstructuredGrid: """Get the mesh with the geomechanics properties computed as attributes. @@ -774,7 +770,7 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: self.logger.addHandler( handler ) else: self.logger.warning( diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py index 985959aa..13d451e4 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockExtractor.py @@ -179,6 +179,7 @@ def __init__( else: self.logger = logging.getLogger( loggerName ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: """Set a specific handler for the filter logger. @@ -188,15 +189,19 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: 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." ) - def applyFilter( self: Self ) -> None: - """Extract the volume, the fault or the well domain of the mesh from GEOS.""" + def applyFilter( self: Self ) -> bool: + """Extract the volume, the fault or the well domain of the mesh from GEOS. + + Returns: + bool: True if the filter succeeded, False otherwise. + """ self.logger.info( f"Apply filter { self.logger.name }." ) try: @@ -216,5 +221,10 @@ def applyFilter( self: Self ) -> None: except ( ValueError, TypeError ) as e: self.logger.error( f"The filter { self.logger.name } failed.\n{ e }." ) + return False + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) + return False - return + return True diff --git a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py index fac8c108..f581ee20 100644 --- a/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py +++ b/geos-processing/src/geos/processing/post_processing/GeosBlockMerge.py @@ -5,8 +5,7 @@ import logging from typing_extensions import Self -from vtkmodules.vtkCommonDataModel import ( vtkCompositeDataSet, vtkMultiBlockDataSet, vtkPolyData, - vtkUnstructuredGrid ) +from vtkmodules.vtkCommonDataModel import vtkCompositeDataSet, vtkMultiBlockDataSet, vtkPolyData, vtkUnstructuredGrid from geos.utils.Errors import VTKError from geos.utils.Logger import ( Logger, getLogger ) @@ -114,7 +113,7 @@ def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: self.handler = handler self.logger.addHandler( handler ) else: @@ -126,8 +125,12 @@ def getOutput( self: Self ) -> vtkMultiBlockDataSet: """Get the mesh with the composite blocks merged.""" return self.outputMesh - def applyFilter( self: Self ) -> None: - """Apply the filter on the mesh.""" + def applyFilter( self: Self ) -> bool: + """Apply the filter on the mesh. + + Returns: + bool: True if the filter succeeded, False otherwise. + """ self.logger.info( f"Apply filter { self.logger.name }." ) try: @@ -178,8 +181,13 @@ def applyFilter( self: Self ) -> None: self.logger.info( f"The filter { self.logger.name } succeeded." ) except ( ValueError, TypeError, RuntimeError, AssertionError, VTKError ) as e: self.logger.error( f"The filter { self.logger.name } failed.\n{ e }" ) + return False + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) + return False - return + return True def renameAttributes( self: Self, diff --git a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py index 62fcd013..ed0a5a62 100644 --- a/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py +++ b/geos-processing/src/geos/processing/post_processing/SurfaceGeomechanics.py @@ -12,26 +12,12 @@ from vtkmodules.vtkCommonDataModel import vtkPolyData from geos.mesh.utils.arrayModifiers import createAttribute -from geos.mesh.utils.arrayHelpers import ( - getArrayInObject, - getAttributeSet, - isAttributeInObject, -) -from geos.mesh.utils.genericHelpers import ( - getLocalBasisVectors, - convertAttributeFromLocalToXYZForOneCell, -) +from geos.mesh.utils.arrayHelpers import ( getArrayInObject, getAttributeSet, isAttributeInObject ) +from geos.mesh.utils.genericHelpers import ( getLocalBasisVectors, convertAttributeFromLocalToXYZForOneCell ) import geos.geomechanics.processing.geomechanicsCalculatorFunctions as fcts from geos.utils.Logger import ( Logger, getLogger ) -from geos.utils.PhysicalConstants import ( - DEFAULT_FRICTION_ANGLE_RAD, - DEFAULT_ROCK_COHESION, -) -from geos.utils.GeosOutputsConstants import ( - ComponentNameEnum, - GeosMeshOutputsEnum, - PostProcessingOutputsEnum, -) +from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_RAD, DEFAULT_ROCK_COHESION ) +from geos.utils.GeosOutputsConstants import ( ComponentNameEnum, GeosMeshOutputsEnum, PostProcessingOutputsEnum ) __doc__ = """ SurfaceGeomechanics is a VTK filter that allows: @@ -117,6 +103,7 @@ def __init__( self: Self, surfacicMesh: vtkPolyData, speHandler: bool = False ) else: self.logger = logging.getLogger( loggerTitle ) self.logger.setLevel( logging.INFO ) + self.logger.propagate = False # Input surfacic mesh if not surfacicMesh.IsA( "vtkPolyData" ): @@ -149,7 +136,7 @@ def SetLoggerHandler( self: Self, handler: Logger ) -> None: Args: handler (logging.Handler): The handler to add. """ - if not self.logger.hasHandlers(): + if len( self.logger.handlers ) == 0: self.logger.addHandler( handler ) else: self.logger.warning( @@ -185,7 +172,7 @@ def ConvertAttributesOn( self: Self ) -> None: self.convertAttributesOn = True def ConvertAttributesOff( self: Self ) -> None: - """Deactivate the conversion of attributes from local to XYZ bais.""" + """Deactivate the conversion of attributes from local to XYZ basis.""" self.convertAttributesOn = False def GetConvertAttributes( self: Self ) -> bool: @@ -248,36 +235,34 @@ def applyFilter( self: Self ) -> bool: self.logger.info( msg ) - self.outputMesh = vtkPolyData() - self.outputMesh.ShallowCopy( self.inputMesh ) + try: + self.outputMesh = vtkPolyData() + self.outputMesh.ShallowCopy( self.inputMesh ) - # Conversion of attributes from Normal/Tangent basis to xyz basis - if self.convertAttributesOn: - self.logger.info( "Conversion of attributes from local to XYZ basis." ) - if not self.convertAttributesFromLocalToXYZBasis(): - self.logger.error( "Error while converting attributes from local to XYZ basis." ) - return False + # Conversion of attributes from Normal/Tangent basis to xyz basis + if self.convertAttributesOn: + self.logger.info( "Conversion of attributes from local to XYZ basis." ) + self.convertAttributesFromLocalToXYZBasis() - # Compute shear capacity utilization - if not self.computeShearCapacityUtilization(): - self.logger.error( "Error while computing SCU." ) + # Compute shear capacity utilization + self.computeShearCapacityUtilization() + + self.logger.info( f"Filter {self.logger.name} successfully applied on surface {self.name}." ) + except Exception as e: + mess: str = f"The filter { self.logger.name } failed.\n{ e }" + self.logger.critical( mess, exc_info=True ) return False - self.logger.info( f"Filter {self.logger.name} successfully applied on surface {self.name}." ) return True - def convertAttributesFromLocalToXYZBasis( self: Self ) -> bool: - """Convert attributes from local to XYZ basis. - - Returns: - bool: True if calculation successfully ended or no attributes, False otherwise. - """ + def convertAttributesFromLocalToXYZBasis( self: Self ) -> None: + """Convert attributes from local to XYZ basis.""" # Get the list of attributes to convert and filter attributesToConvert: set[ str ] = self.__filterAttributesToConvert() if len( attributesToConvert ) == 0: self.logger.warning( "No attribute to convert from local to XYZ basis were found." ) - return True + return # Do conversion from local to XYZ for each attribute for attrNameLocal in attributesToConvert: @@ -288,7 +273,7 @@ def convertAttributesFromLocalToXYZBasis( self: Self ) -> bool: continue if self.attributeOnPoints: - self.logger.error( + raise ValueError( "This filter can only convert cell attributes from local to XYZ basis, not point attributes." ) localArray: npt.NDArray[ np.float64 ] = getArrayInObject( self.outputMesh, attrNameLocal, self.attributeOnPoints ) @@ -304,8 +289,10 @@ def convertAttributesFromLocalToXYZBasis( self: Self ) -> bool: logger=self.logger ): self.logger.info( f"Attribute {attrNameXYZ} added to the output mesh." ) self.newAttributeNames.add( attrNameXYZ ) + else: + raise - return True + return def __filterAttributesToConvert( self: Self ) -> set[ str ]: """Filter the set of attribute names if they are vectorial and present. @@ -368,12 +355,8 @@ def __computeXYZCoordinates( return attrXYZ - def computeShearCapacityUtilization( self: Self ) -> bool: - """Compute the shear capacity utilization (SCU) on surface. - - Returns: - bool: True if calculation successfully ended, False otherwise. - """ + def computeShearCapacityUtilization( self: Self ) -> None: + """Compute the shear capacity utilization (SCU) on surface.""" SCUAttributeName: str = PostProcessingOutputsEnum.SCU.attributeName if not isAttributeInObject( self.outputMesh, SCUAttributeName, self.attributeOnPoints ): @@ -389,18 +372,18 @@ def computeShearCapacityUtilization( self: Self ) -> bool: traction, self.rockCohesion, self.frictionAngle ) except AssertionError: self.logger.error( f"Failed to compute {SCUAttributeName}." ) - return False + raise # Create attribute if not createAttribute( self.outputMesh, scuAttribute, SCUAttributeName, (), self.attributeOnPoints, logger=self.logger ): self.logger.error( f"Failed to create attribute {SCUAttributeName}." ) - return False + raise else: self.logger.info( "SCU computed and added to the output mesh." ) self.newAttributeNames.add( SCUAttributeName ) - return True + return def GetOutputMesh( self: Self ) -> vtkPolyData: """Get the output mesh with computed attributes. diff --git a/geos-processing/tests/test_CellTypeCounterEnhanced.py b/geos-processing/tests/test_CellTypeCounterEnhanced.py index 7883592c..7783ce70 100644 --- a/geos-processing/tests/test_CellTypeCounterEnhanced.py +++ b/geos-processing/tests/test_CellTypeCounterEnhanced.py @@ -60,7 +60,7 @@ def test_CellTypeCounterEnhanced_single( test_case: TestCase ) -> None: test_case (TestCase): Test case """ cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( test_case.mesh ) - cellTypeCounterEnhancedFilter.applyFilter() + assert cellTypeCounterEnhancedFilter.applyFilter() countsObs: CellTypeCounts = cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() assert countsObs is not None, "CellTypeCounts is undefined" @@ -118,7 +118,7 @@ def test_CellTypeCounterEnhanced_multi( test_case: TestCase ) -> None: test_case (TestCase): Test case """ cellTypeCounterEnhancedFilter: CellTypeCounterEnhanced = CellTypeCounterEnhanced( test_case.mesh ) - cellTypeCounterEnhancedFilter.applyFilter() + assert cellTypeCounterEnhancedFilter.applyFilter() countsObs: CellTypeCounts = cellTypeCounterEnhancedFilter.GetCellTypeCountsObject() assert countsObs is not None, "CellTypeCounts is undefined" diff --git a/geos-processing/tests/test_GeosExtractBlock.py b/geos-processing/tests/test_GeosExtractBlock.py index 2f47b1b2..bfdecf63 100644 --- a/geos-processing/tests/test_GeosExtractBlock.py +++ b/geos-processing/tests/test_GeosExtractBlock.py @@ -26,7 +26,7 @@ def test_GeosExtractBlock( multiBlockDataSet: vtkMultiBlockDataSet = dataSetTest( "meshGeosExtractBlockTmp" ) geosBlockExtractor: GeosBlockExtractor = GeosBlockExtractor( multiBlockDataSet, extractFault, extractWell ) - geosBlockExtractor.applyFilter() + assert geosBlockExtractor.applyFilter() extractedVolume: vtkMultiBlockDataSet = geosBlockExtractor.extractedGeosDomain.volume extractedFault: vtkMultiBlockDataSet = geosBlockExtractor.extractedGeosDomain.fault diff --git a/geos-processing/tests/test_MergeBlocksEnhanced.py b/geos-processing/tests/test_MergeBlocksEnhanced.py index 677a99d9..fee349f0 100644 --- a/geos-processing/tests/test_MergeBlocksEnhanced.py +++ b/geos-processing/tests/test_MergeBlocksEnhanced.py @@ -7,26 +7,13 @@ from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet from geos.processing.generic_processing_tools.MergeBlockEnhanced import MergeBlockEnhanced -from unittest import TestCase -from geos.utils.Errors import VTKError - -import vtk -from packaging.version import Version def test_MergeBlocksEnhancedFilter( dataSetTest: vtkMultiBlockDataSet, ) -> None: """Test MergeBlockEnhanced vtk filter.""" multiBlockDataset: vtkMultiBlockDataSet = dataSetTest( "multiblockGeosOutput" ) mergeBlockEnhancedFilter: MergeBlockEnhanced = MergeBlockEnhanced( multiBlockDataset ) - mergeBlockEnhancedFilter.applyFilter() - - -class RaiseMergeBlocksEnhanced( TestCase ): - """Test failure on empty multiBlockDataSet.""" + assert mergeBlockEnhancedFilter.applyFilter() - def test_TypeError( self ) -> None: - """Test raise of TypeError.""" - multiBlockDataset = vtkMultiBlockDataSet() # should fail on empty data - mergeBlockEnhancedFilter: MergeBlockEnhanced = MergeBlockEnhanced( multiBlockDataset ) - if Version( vtk.__version__ ) < Version( "9.5" ): - self.assertRaises( VTKError, mergeBlockEnhancedFilter.applyFilter ) + failedMergeBlockEnhancedFilter: MergeBlockEnhanced = MergeBlockEnhanced( vtkMultiBlockDataSet() ) + assert not failedMergeBlockEnhancedFilter.applyFilter() diff --git a/geos-processing/tests/test_MeshQualityEnhanced.py b/geos-processing/tests/test_MeshQualityEnhanced.py index 730ec173..2938c736 100644 --- a/geos-processing/tests/test_MeshQualityEnhanced.py +++ b/geos-processing/tests/test_MeshQualityEnhanced.py @@ -142,11 +142,10 @@ def test_MeshQualityEnhanced( test_case: TestCase ) -> None: meshQualityEnhancedFilter.SetWedgeMetrics( test_case.qualityMetrics ) elif test_case.cellType == VTK_HEXAHEDRON: meshQualityEnhancedFilter.SetHexaMetrics( test_case.qualityMetrics ) - meshQualityEnhancedFilter.applyFilter() + assert meshQualityEnhancedFilter.applyFilter() # test method getComputedMetricsFromCellType for i, cellType in enumerate( getAllCellTypesExtended() ): - print( cellType ) metrics: Optional[ set[ int ] ] = meshQualityEnhancedFilter.getComputedMetricsFromCellType( cellType ) if test_case.cellTypeCounts[ i ] > 0: assert metrics is not None, f"Metrics from {vtkCellTypes.GetClassNameFromTypeId(cellType)} cells is undefined." diff --git a/geos-processing/tests/test_SplitMesh.py b/geos-processing/tests/test_SplitMesh.py index 7fc8e607..fb175b30 100644 --- a/geos-processing/tests/test_SplitMesh.py +++ b/geos-processing/tests/test_SplitMesh.py @@ -143,7 +143,7 @@ def test_single_cell_split( test_case: TestCase ) -> None: """ cellTypeName: str = vtkCellTypes.GetClassNameFromTypeId( test_case.cellType ) splitMeshFilter: SplitMesh = SplitMesh( test_case.mesh ) - splitMeshFilter.applyFilter() + assert splitMeshFilter.applyFilter() output: vtkUnstructuredGrid = splitMeshFilter.getOutput() assert output is not None, "Output mesh is undefined." pointsOut: vtkPoints = output.GetPoints() @@ -201,8 +201,8 @@ def test_single_cell_split( test_case: TestCase ) -> None: cellDataInput: vtkCellData = test_case.mesh.GetCellData() assert cellDataInput is not None, "Cell data from input mesh should be defined." nbArrayInput: int = cellDataInput.GetNumberOfArrays() - nbArraySplited: int = cellData.GetNumberOfArrays() - assert nbArraySplited == nbArrayInput + 1, f"Number of arrays should be {nbArrayInput + 1}" + nbArraySplitted: int = cellData.GetNumberOfArrays() + assert nbArraySplitted == nbArrayInput + 1, f"Number of arrays should be {nbArrayInput + 1}" def test_multi_cells_mesh_split() -> None: @@ -234,7 +234,7 @@ def test_multi_cells_mesh_split() -> None: # Apply the split filter splitMeshFilter = SplitMesh( input_mesh ) - splitMeshFilter.applyFilter() + assert splitMeshFilter.applyFilter() output: vtkUnstructuredGrid = splitMeshFilter.getOutput() assert output is not None, "Output mesh should be defined" @@ -296,7 +296,7 @@ def test_multi_polygon_mesh_split() -> None: # Apply the split filter splitMeshFilter = SplitMesh( input_mesh ) - splitMeshFilter.applyFilter() + assert splitMeshFilter.applyFilter() output: vtkUnstructuredGrid = splitMeshFilter.getOutput() assert output is not None, "Output mesh should be defined" diff --git a/geos-pv/src/geos/pv/plugins/PVAttributeMapping.py b/geos-pv/src/geos/pv/plugins/PVAttributeMapping.py index a8dfc28c..cb5af13f 100644 --- a/geos-pv/src/geos/pv/plugins/PVAttributeMapping.py +++ b/geos-pv/src/geos/pv/plugins/PVAttributeMapping.py @@ -16,21 +16,13 @@ from geos.processing.generic_processing_tools.AttributeMapping import AttributeMapping from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy, -) -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py + VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy ) +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py -from vtkmodules.vtkCommonCore import ( - vtkInformation, - vtkInformationVector, -) -from vtkmodules.vtkCommonDataModel import ( - vtkCompositeDataSet, - vtkDataSet, - vtkMultiBlockDataSet, -) +from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector +from vtkmodules.vtkCommonDataModel import vtkCompositeDataSet, vtkDataSet, vtkMultiBlockDataSet __doc__ = """ AttributeMapping is a paraview plugin that transfers global attributes from a source mesh to a final mesh with same point/cell coordinates. @@ -191,7 +183,7 @@ def RequestData( attributeMappingFilter: AttributeMapping = AttributeMapping( meshFrom, outData, set( self.attributeNames ), self.onPoints, True ) - if not attributeMappingFilter.logger.hasHandlers(): + if len( attributeMappingFilter.logger.handlers ) == 0: attributeMappingFilter.setLoggerHandler( VTKHandler() ) attributeMappingFilter.applyFilter() diff --git a/geos-pv/src/geos/pv/plugins/PVCellTypeCounterEnhanced.py b/geos-pv/src/geos/pv/plugins/PVCellTypeCounterEnhanced.py index ad237bd8..bbf6178c 100644 --- a/geos-pv/src/geos/pv/plugins/PVCellTypeCounterEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/PVCellTypeCounterEnhanced.py @@ -9,7 +9,9 @@ from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy ) +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector from vtkmodules.vtkCommonDataModel import vtkPointSet, vtkTable diff --git a/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py b/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py index 1e52b050..dff25ed5 100644 --- a/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py +++ b/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py @@ -5,15 +5,12 @@ import sys from pathlib import Path -from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py -from vtkmodules.vtkCommonDataModel import ( - vtkMultiBlockDataSet, ) +from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet # update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent @@ -44,7 +41,7 @@ class PVClipToMainFrame( VTKPythonAlgorithmBase ): def __init__( self ) -> None: """Init motherclass, filter and logger.""" self._realFilter = ClipToMainFrame( speHandler=True ) - if not self._realFilter.logger.hasHandlers(): + if len( self._realFilter.logger.handlers ) == 0: self._realFilter.SetLoggerHandler( VTKHandler() ) def ApplyFilter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBlockDataSet ) -> None: diff --git a/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py b/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py index fb5782e9..95a7af0c 100644 --- a/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py +++ b/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py @@ -9,25 +9,20 @@ from typing import Any from typing_extensions import Self -from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smproperty, -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py import vtkmodules.util.numpy_support as vnp - -from vtkmodules.vtkCommonDataModel import ( - vtkDataSet, ) +from vtkmodules.vtkCommonDataModel import vtkDataSet # update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent sys.path.insert( 0, str( geos_pv_path / "src" ) ) from geos.processing.generic_processing_tools.CreateConstantAttributePerRegion import CreateConstantAttributePerRegion - -from geos.pv.utils.details import SISOFilter, FilterCategory +from geos.pv.utils.details import ( SISOFilter, FilterCategory ) __doc__ = """ PVCreateConstantAttributePerRegion is a Paraview plugin that allows to create an attribute @@ -291,7 +286,7 @@ def ApplyFilter( self, inputMesh: vtkDataSet, outputMesh: vtkDataSet ) -> None: self.speHandler, ) - if not createConstantAttributePerRegionFilter.logger.hasHandlers(): + if len( createConstantAttributePerRegionFilter.logger.handlers ) == 0: createConstantAttributePerRegionFilter.setLoggerHandler( VTKHandler() ) createConstantAttributePerRegionFilter.applyFilter() diff --git a/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py b/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py index 80d8fb93..ee7fa1b1 100644 --- a/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py +++ b/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py @@ -7,15 +7,12 @@ from typing import Any, Optional, Union from typing_extensions import Self -from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smproperty, -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smproperty # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py -from vtkmodules.vtkCommonDataModel import ( - vtkMultiBlockDataSet, ) +from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet # update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent @@ -24,7 +21,7 @@ update_paths() -from geos.pv.utils.details import SISOFilter, FilterCategory +from geos.pv.utils.details import ( SISOFilter, FilterCategory ) from geos.processing.generic_processing_tools.FillPartialArrays import FillPartialArrays __doc__ = """ @@ -108,7 +105,7 @@ def ApplyFilter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBloc speHandler=True, ) - if not fillPartialArraysFilter.logger.hasHandlers(): + if len( fillPartialArraysFilter.logger.handlers ) == 0: fillPartialArraysFilter.setLoggerHandler( VTKHandler() ) fillPartialArraysFilter.applyFilter() diff --git a/geos-pv/src/geos/pv/plugins/PVGeomechanicsCalculator.py b/geos-pv/src/geos/pv/plugins/PVGeomechanicsCalculator.py index 829eeaa9..d6b4fa4d 100644 --- a/geos-pv/src/geos/pv/plugins/PVGeomechanicsCalculator.py +++ b/geos-pv/src/geos/pv/plugins/PVGeomechanicsCalculator.py @@ -8,14 +8,12 @@ from pathlib import Path from typing_extensions import Self -from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smproperty -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler -) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py +from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py -from vtkmodules.vtkCommonDataModel import ( vtkUnstructuredGrid, vtkMultiBlockDataSet ) +from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid, vtkMultiBlockDataSet # update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent @@ -24,12 +22,8 @@ update_paths() -from geos.utils.PhysicalConstants import ( - DEFAULT_FRICTION_ANGLE_DEG, - DEFAULT_GRAIN_BULK_MODULUS, - DEFAULT_ROCK_COHESION, - WATER_DENSITY, -) +from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_GRAIN_BULK_MODULUS, + DEFAULT_ROCK_COHESION, WATER_DENSITY ) from geos.mesh.utils.multiblockHelpers import ( getBlockElementIndexesFlatten, getBlockNameFromIndex ) from geos.processing.post_processing.GeomechanicsCalculator import GeomechanicsCalculator from geos.pv.utils.details import ( SISOFilter, FilterCategory ) @@ -199,7 +193,7 @@ def setRockCohesion( self: Self, rockCohesion: float ) -> None: @smdomain.xml( """ Reference friction angle to compute critical pore pressure. - The unit is °. Default is no friction case (i.e., 0.°). + The unit is °. Default is no friction case (i.e., 10.°). """ ) def setFrictionAngle( self: Self, frictionAngle: float ) -> None: @@ -247,7 +241,7 @@ def ApplyFilter( speHandler=True, ) - if not geomechanicsCalculatorFilter.logger.hasHandlers(): + if len( geomechanicsCalculatorFilter.logger.handlers ) == 0: geomechanicsCalculatorFilter.setLoggerHandler( VTKHandler() ) geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus @@ -255,8 +249,8 @@ def ApplyFilter( geomechanicsCalculatorFilter.physicalConstants.rockCohesion = self.rockCohesion geomechanicsCalculatorFilter.physicalConstants.frictionAngle = self.frictionAngle - geomechanicsCalculatorFilter.applyFilter() - outputMesh.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) + if geomechanicsCalculatorFilter.applyFilter(): + outputMesh.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) elif isinstance( outputMesh, vtkMultiBlockDataSet ): volumeBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( outputMesh ) for blockIndex in volumeBlockIndexes: @@ -272,7 +266,7 @@ def ApplyFilter( True, ) - if not geomechanicsCalculatorFilter.logger.hasHandlers(): + if len( geomechanicsCalculatorFilter.logger.handlers ) == 0: geomechanicsCalculatorFilter.setLoggerHandler( VTKHandler() ) geomechanicsCalculatorFilter.physicalConstants.grainBulkModulus = self.grainBulkModulus @@ -280,9 +274,9 @@ def ApplyFilter( geomechanicsCalculatorFilter.physicalConstants.rockCohesion = self.rockCohesion geomechanicsCalculatorFilter.physicalConstants.frictionAngle = self.frictionAngle - geomechanicsCalculatorFilter.applyFilter() - volumeBlock.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) - volumeBlock.Modified() + if geomechanicsCalculatorFilter.applyFilter(): + volumeBlock.ShallowCopy( geomechanicsCalculatorFilter.getOutput() ) + volumeBlock.Modified() outputMesh.Modified() diff --git a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflow.py b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflow.py index 992a7302..3f674fa6 100644 --- a/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflow.py +++ b/geos-pv/src/geos/pv/plugins/PVGeomechanicsWorkflow.py @@ -15,24 +15,21 @@ update_paths() -from geos.utils.PhysicalConstants import ( - DEFAULT_FRICTION_ANGLE_DEG, - DEFAULT_GRAIN_BULK_MODULUS, - DEFAULT_ROCK_COHESION, - WATER_DENSITY, -) +from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_GRAIN_BULK_MODULUS, + DEFAULT_ROCK_COHESION, WATER_DENSITY ) from geos.pv.plugins.PVGeosBlockExtractAndMerge import PVGeosBlockExtractAndMerge from geos.pv.plugins.PVGeomechanicsCalculator import PVGeomechanicsCalculator from geos.pv.plugins.PVSurfaceGeomechanics import PVSurfaceGeomechanics -from vtkmodules.vtkCommonCore import ( vtkInformation, vtkInformationVector ) +from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] VTKPythonAlgorithmBase, smdomain, smproperty, smproxy ) -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler ) +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py __doc__ = """ PVGeomechanicsWorkflow is a Paraview plugin that executes multiple plugins: diff --git a/geos-pv/src/geos/pv/plugins/PVGeosBlockExtractAndMerge.py b/geos-pv/src/geos/pv/plugins/PVGeosBlockExtractAndMerge.py index c779c5eb..a2de08ea 100644 --- a/geos-pv/src/geos/pv/plugins/PVGeosBlockExtractAndMerge.py +++ b/geos-pv/src/geos/pv/plugins/PVGeosBlockExtractAndMerge.py @@ -27,13 +27,14 @@ from geos.pv.utils.paraviewTreatments import getTimeStepIndex from geos.pv.utils.workflowFunctions import doExtractAndMerge -from vtkmodules.vtkCommonCore import ( vtkInformation, vtkInformationVector ) +from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] VTKPythonAlgorithmBase, smdomain, smproperty, smproxy ) -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler ) +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py __doc__ = """ PVGeosBlockExtractAndMerge is a Paraview plugin processing the input mesh at the current time in two steps: diff --git a/geos-pv/src/geos/pv/plugins/PVGeosLogReader.py b/geos-pv/src/geos/pv/plugins/PVGeosLogReader.py index 743d6dc2..b3a1222e 100644 --- a/geos-pv/src/geos/pv/plugins/PVGeosLogReader.py +++ b/geos-pv/src/geos/pv/plugins/PVGeosLogReader.py @@ -4,6 +4,7 @@ # ruff: noqa: E402 # disable Module level import not at top of file import os import sys +import logging from pathlib import Path from enum import Enum from typing import Union, cast @@ -22,42 +23,24 @@ import vtkmodules.util.numpy_support as vnp from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy, -) -from vtk import VTK_DOUBLE # type: ignore[import-untyped] + VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy ) +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py + from vtkmodules.vtkCommonCore import vtkDataArraySelection as vtkDAS -from vtkmodules.vtkCommonCore import ( - vtkDoubleArray, - vtkInformation, - vtkInformationVector, -) +from vtkmodules.vtkCommonCore import vtkDoubleArray, vtkInformation, vtkInformationVector, VTK_DOUBLE from vtkmodules.vtkCommonDataModel import vtkTable -from geos.pv.geosLogReaderUtils.geosLogReaderFunctions import ( - identifyProperties, - transformUserChoiceToListPhases, -) - +from geos.pv.geosLogReaderUtils.geosLogReaderFunctions import ( identifyProperties, transformUserChoiceToListPhases ) from geos.pv.geosLogReaderUtils.GeosLogReaderAquifers import GeosLogReaderAquifers from geos.pv.geosLogReaderUtils.GeosLogReaderConvergence import GeosLogReaderConvergence from geos.pv.geosLogReaderUtils.GeosLogReaderFlow import GeosLogReaderFlow from geos.pv.geosLogReaderUtils.GeosLogReaderWells import GeosLogReaderWells -from geos.utils.enumUnits import ( - Mass, - MassRate, - Pressure, - Time, - Unit, - Volume, - VolumetricRate, - enumerationDomainUnit, -) - +from geos.utils.enumUnits import ( Mass, MassRate, Pressure, Time, Unit, Volume, VolumetricRate, enumerationDomainUnit ) from geos.utils.UnitRepository import UnitRepository -from geos.pv.utils.checkboxFunction import ( # type: ignore[attr-defined] - createModifiedCallback, ) -from geos.pv.utils.paraviewTreatments import ( - strListToEnumerationDomainXml, ) +from geos.pv.utils.checkboxFunction import createModifiedCallback # type: ignore[attr-defined] +from geos.pv.utils.paraviewTreatments import strListToEnumerationDomainXml __doc__ = """ ``PVGeosLogReader`` is a Paraview plugin that allows to read Geos output log. @@ -164,6 +147,13 @@ def __init__( self: Self ) -> None: for prop in propsSolvers: self.m_convergence.AddArray( prop ) + self.logger: logging.Logger = logging.getLogger( "Geos Log Reader" ) + self.logger.setLevel( logging.INFO ) + if len( self.logger.handlers ) == 0: + self.logger.addHandler( VTKHandler() ) + self.logger.propagate = False + self.logger.info( f"Apply plugin { self.logger.name }." ) + @smproperty.stringvector( name="DataFilepath", default_values="Enter a filepath to your data" ) @smdomain.filelist() @smhint.filechooser( extensions=[ "txt", "out" ], file_description="Data files" ) @@ -587,8 +577,8 @@ 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." ) except Exception as e: - print( "Error while reading Geos log file:" ) - print( str( e ) ) + self.logger.error( f"The plugin { self.logger.name } failed.\n{ e }" ) return 0 return 1 diff --git a/geos-pv/src/geos/pv/plugins/PVMergeBlocksEnhanced.py b/geos-pv/src/geos/pv/plugins/PVMergeBlocksEnhanced.py index 3ebcd7eb..ea96de82 100644 --- a/geos-pv/src/geos/pv/plugins/PVMergeBlocksEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/PVMergeBlocksEnhanced.py @@ -8,19 +8,13 @@ from typing_extensions import Self from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy, -) -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, ) -from vtkmodules.vtkCommonCore import ( - vtkInformation, - vtkInformationVector, -) -from vtkmodules.vtkCommonDataModel import ( - vtkCompositeDataSet, - vtkMultiBlockDataSet, - vtkUnstructuredGrid, -) + VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy ) +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py + +from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector +from vtkmodules.vtkCommonDataModel import vtkCompositeDataSet, vtkMultiBlockDataSet, vtkUnstructuredGrid # Update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent @@ -119,15 +113,11 @@ def RequestData( mergeBlockEnhancedFilter: MergeBlockEnhanced = MergeBlockEnhanced( inputMesh, True ) - if not mergeBlockEnhancedFilter.logger.hasHandlers(): + if len( mergeBlockEnhancedFilter.logger.handlers ) == 0: mergeBlockEnhancedFilter.setLoggerHandler( VTKHandler() ) - try: - mergeBlockEnhancedFilter.applyFilter() - except ( ValueError, TypeError, RuntimeError ) as e: - mergeBlockEnhancedFilter.logger.error( f"MergeBlock failed due to {e}", exc_info=True ) - return 0 - else: + if mergeBlockEnhancedFilter.applyFilter(): outputMesh.ShallowCopy( mergeBlockEnhancedFilter.getOutput() ) outputMesh.Modified() - return 1 + + return 1 diff --git a/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py b/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py index 9384f92f..4debf0a4 100644 --- a/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py +++ b/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py @@ -8,6 +8,7 @@ from typing_extensions import Self, Optional from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py diff --git a/geos-pv/src/geos/pv/plugins/PVMohrCirclePlot.py b/geos-pv/src/geos/pv/plugins/PVMohrCirclePlot.py index d6efdfd5..54871bbb 100644 --- a/geos-pv/src/geos/pv/plugins/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/PVMohrCirclePlot.py @@ -10,19 +10,18 @@ import numpy as np import numpy.typing as npt -from paraview.simple import ( # type: ignore[import-not-found] - Render, ) + +from paraview.simple import Render # type: ignore[import-not-found] from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy, -) -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, ) + VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy ) +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py from typing_extensions import Self from vtkmodules.vtkCommonCore import vtkDataArraySelection as vtkDAS from vtkmodules.vtkCommonCore import vtkInformation, vtkInformationVector -from vtkmodules.vtkCommonDataModel import ( - vtkUnstructuredGrid, ) +from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid # Update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent @@ -33,33 +32,18 @@ from geos.geomechanics.model.MohrCircle import MohrCircle from geos.utils.enumUnits import Pressure, enumerationDomainUnit -from geos.utils.GeosOutputsConstants import ( - FAILURE_ENVELOPE, - GeosMeshOutputsEnum, -) +from geos.utils.GeosOutputsConstants import ( FAILURE_ENVELOPE, GeosMeshOutputsEnum ) from geos.utils.Logger import CustomLoggerFormatter -from geos.utils.PhysicalConstants import ( - DEFAULT_FRICTION_ANGLE_DEG, - DEFAULT_FRICTION_ANGLE_RAD, - DEFAULT_ROCK_COHESION, -) +from geos.utils.PhysicalConstants import ( DEFAULT_FRICTION_ANGLE_DEG, DEFAULT_FRICTION_ANGLE_RAD, + DEFAULT_ROCK_COHESION ) from geos.mesh.utils.arrayHelpers import getArrayInObject import geos.pv.utils.mohrCircles.functionsMohrCircle as mcf import geos.pv.utils.paraviewTreatments as pvt -from geos.pv.utils.checkboxFunction import ( # type: ignore[attr-defined] - createModifiedCallback, ) -from geos.pv.utils.DisplayOrganizationParaview import ( - buildNewLayoutWithPythonView, ) -from geos.pv.pyplotUtils.matplotlibOptions import ( - FontStyleEnum, - FontWeightEnum, - LegendLocationEnum, - LineStyleEnum, - MarkerStyleEnum, - OptionSelectionEnum, - optionEnumToXml, -) +from geos.pv.utils.checkboxFunction import createModifiedCallback # type: ignore[attr-defined] +from geos.pv.utils.DisplayOrganizationParaview import buildNewLayoutWithPythonView +from geos.pv.pyplotUtils.matplotlibOptions import ( FontStyleEnum, FontWeightEnum, LegendLocationEnum, LineStyleEnum, + MarkerStyleEnum, OptionSelectionEnum, optionEnumToXml ) from geos.pv.utils.mohrCircles.functionsMohrCircle import StressConventionEnum __doc__ = """ @@ -303,7 +287,7 @@ def b05SetStressCompressionConvention( self: Self, useGeosConvention: bool ) -> @smproperty.intvector( name="AnnotateCircles", label="Annotate Circles", default_values=1 ) @smdomain.xml( """""" ) def b06SetAnnotateCircles( self: Self, boolean: bool ) -> None: - """Set option to add annotatations to circles. + """Set option to add annotations to circles. Args: boolean (bool): True to annotate circles, False otherwise. @@ -660,7 +644,7 @@ def RequestInformation( if self.requestDataStep < 0: # Get cell ids inData = self.GetInputData( inInfoVec, 0, 0 ) - self.cellIds = pvt.getVtkOriginalCellIds( inData, self.logger) + self.cellIds = pvt.getVtkOriginalCellIds( inData, self.logger ) # Update vtkDAS for circleId in self.cellIds: diff --git a/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py b/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py index b03f001b..aa7574fe 100755 --- a/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py +++ b/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py @@ -18,38 +18,19 @@ from geos.mesh.utils.multiblockModifiers import mergeBlocks import geos.pv.utils.paraviewTreatments as pvt -from geos.pv.utils.checkboxFunction import ( # type: ignore[attr-defined] - createModifiedCallback, ) -from geos.pv.utils.DisplayOrganizationParaview import ( - DisplayOrganizationParaview, ) -from geos.pv.pyplotUtils.matplotlibOptions import ( - FontStyleEnum, - FontWeightEnum, - LegendLocationEnum, - LineStyleEnum, - MarkerStyleEnum, - OptionSelectionEnum, - optionEnumToXml, -) +from geos.pv.utils.checkboxFunction import createModifiedCallback # type: ignore[attr-defined] +from geos.pv.utils.DisplayOrganizationParaview import DisplayOrganizationParaview +from geos.pv.pyplotUtils.matplotlibOptions import ( FontStyleEnum, FontWeightEnum, LegendLocationEnum, LineStyleEnum, + MarkerStyleEnum, OptionSelectionEnum, optionEnumToXml ) +from geos.pv.utils.details import ( SISOFilter, FilterCategory ) + from paraview.simple import ( # type: ignore[import-not-found] - GetActiveSource, GetActiveView, Render, Show, servermanager, -) -from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - smdomain, smproperty, -) -from vtkmodules.vtkCommonCore import ( - vtkDataArraySelection, - vtkInformation, -) - -from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase ) - -from vtkmodules.vtkCommonDataModel import ( - vtkDataObject, - vtkMultiBlockDataSet, -) -from geos.pv.utils.details import SISOFilter, FilterCategory + GetActiveSource, GetActiveView, Render, Show, servermanager ) +from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py + +from vtkmodules.vtkCommonCore import vtkDataArraySelection, vtkInformation +from vtkmodules.vtkCommonDataModel import vtkDataObject, vtkMultiBlockDataSet __doc__ = """ PVPythonViewConfigurator is a Paraview plugin that allows to create cross-plots diff --git a/geos-pv/src/geos/pv/plugins/PVSplitMesh.py b/geos-pv/src/geos/pv/plugins/PVSplitMesh.py index 697cc285..6b149538 100644 --- a/geos-pv/src/geos/pv/plugins/PVSplitMesh.py +++ b/geos-pv/src/geos/pv/plugins/PVSplitMesh.py @@ -7,6 +7,7 @@ from typing_extensions import Self from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py diff --git a/geos-pv/src/geos/pv/plugins/PVSurfaceGeomechanics.py b/geos-pv/src/geos/pv/plugins/PVSurfaceGeomechanics.py index 3999d620..0fc204a7 100644 --- a/geos-pv/src/geos/pv/plugins/PVSurfaceGeomechanics.py +++ b/geos-pv/src/geos/pv/plugins/PVSurfaceGeomechanics.py @@ -7,11 +7,10 @@ import numpy as np from typing_extensions import Self -from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found] - VTKPythonAlgorithmBase, smdomain, smproperty, -) -from paraview.detail.loghandler import ( # type: ignore[import-not-found] - VTKHandler, ) +from paraview.util.vtkAlgorithm import VTKPythonAlgorithmBase, smdomain, smproperty # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py +from paraview.detail.loghandler import VTKHandler # type: ignore[import-not-found] +# source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py # update sys.path to load all GEOS Python Package dependencies geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent @@ -21,21 +20,12 @@ update_paths() -from geos.utils.PhysicalConstants import ( - DEFAULT_FRICTION_ANGLE_DEG, - DEFAULT_ROCK_COHESION, -) +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, -) -from vtkmodules.vtkCommonCore import ( - vtkDataArray, ) -from vtkmodules.vtkCommonDataModel import ( - vtkMultiBlockDataSet, - vtkPolyData, -) +from geos.mesh.utils.multiblockHelpers import ( getBlockElementIndexesFlatten, getBlockFromFlatIndex ) + +from vtkmodules.vtkCommonCore import vtkDataArray +from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet, vtkPolyData __doc__ = """ PVSurfaceGeomechanics is a Paraview plugin that allows to compute @@ -50,7 +40,7 @@ To use it: * Load the module in Paraview: Tools>Manage Plugins...>Load new>PVSurfaceGeomechanics. -* Select any pipeline child of the second ouput from +* Select any pipeline child of the second output from GeosExtractMergeBlocksVolumeSurface* filter. * Select Filters > 3- Geos Geomechanics > Geos Surface Geomechanics. * (Optional) Set rock cohesion and/or friction angle. @@ -131,21 +121,21 @@ def ApplyFilter( self: Self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMul sgFilter: SurfaceGeomechanics = SurfaceGeomechanics( surfaceBlock, True ) sgFilter.SetSurfaceName( f"blockIndex {blockIndex}" ) - if not sgFilter.logger.hasHandlers(): + if len( sgFilter.logger.handlers ) == 0: sgFilter.SetLoggerHandler( VTKHandler() ) sgFilter.SetRockCohesion( self._getRockCohesion() ) sgFilter.SetFrictionAngle( self._getFrictionAngle() ) - sgFilter.applyFilter() + if sgFilter.applyFilter(): - outputSurface: vtkPolyData = sgFilter.GetOutputMesh() + 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() + # 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() outputMesh.Modified() return diff --git a/geos-pv/src/geos/pv/utils/workflowFunctions.py b/geos-pv/src/geos/pv/utils/workflowFunctions.py index 28602fce..b4fd87aa 100644 --- a/geos-pv/src/geos/pv/utils/workflowFunctions.py +++ b/geos-pv/src/geos/pv/utils/workflowFunctions.py @@ -36,8 +36,8 @@ def doExtractAndMerge( speHandler=True ) if not blockExtractor.logger.hasHandlers(): blockExtractor.setLoggerHandler( VTKHandler() ) - blockExtractor.applyFilter() - + if not blockExtractor.applyFilter(): + raise # recover output objects from GeosBlockExtractor filter and merge internal blocks volumeBlockExtracted: vtkMultiBlockDataSet = blockExtractor.extractedGeosDomain.volume outputCells.ShallowCopy( mergeBlocksFilter( volumeBlockExtracted, False, "Volume" ) ) @@ -77,7 +77,8 @@ def mergeBlocksFilter( mergeBlockFilter: GeosBlockMerge = GeosBlockMerge( mesh, convertSurfaces, True, loggerName ) if not mergeBlockFilter.logger.hasHandlers(): mergeBlockFilter.setLoggerHandler( VTKHandler() ) - mergeBlockFilter.applyFilter() + if not mergeBlockFilter.applyFilter(): + raise mergedBlocks: vtkMultiBlockDataSet = vtkMultiBlockDataSet() mergedBlocks.ShallowCopy( mergeBlockFilter.getOutput() ) return mergedBlocks