Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f4f9bc6
update logger generic processing tool
RomainBaville Nov 17, 2025
d0b2bfb
Refactor SplitMesh without PVPythonAlgorytmBase
RomainBaville Nov 17, 2025
e5823f3
Merge branch 'main' into RomainBaville/refactor/AddAndCheckLoggerForF…
RomainBaville Nov 17, 2025
be96ffd
Uniform logger of posp-processing filters
RomainBaville Nov 17, 2025
cbba20b
Uniform logger of generic-processing-tools filters
RomainBaville Nov 17, 2025
313469d
Refactor the filter without VTKPythonAlgorythmBase
RomainBaville Nov 17, 2025
97010df
Update with CellTypeCounterEnhanced changes
RomainBaville Nov 17, 2025
5bdc8e0
Refactor the filter without VTKPythonAlgorythmBase
RomainBaville Nov 17, 2025
479813a
Uniform the logger in the paraview plugin
RomainBaville Nov 17, 2025
e8159d3
Merge branch 'main' into RomainBaville/refactor/AddAndCheckLoggerForF…
RomainBaville Nov 17, 2025
ebe20dd
Merge branch 'main' into RomainBaville/refactor/AddAndCheckLoggerForF…
RomainBaville Nov 18, 2025
33e8249
clean ruff and yapf
RomainBaville Nov 18, 2025
94537cb
remove PVPythonAlgorythmBase
RomainBaville Nov 18, 2025
533fce1
update logger
RomainBaville Nov 19, 2025
1e935ed
Uniform the import
RomainBaville Nov 19, 2025
cf9a437
Refactor SplitMesh
RomainBaville Nov 20, 2025
fe04cb2
Refactor CellTypeCounterEnhanced
RomainBaville Nov 20, 2025
380a693
Refactor MeshQualityEnhanced
RomainBaville Nov 20, 2025
934f734
Update to the last version of the main
RomainBaville Nov 20, 2025
5b7a2af
clean test
RomainBaville Nov 20, 2025
e14a065
fix ruff
RomainBaville Nov 20, 2025
1966e36
add source for the paraview handler
RomainBaville Nov 20, 2025
6ac33ec
improve try - except strategy
RomainBaville Nov 21, 2025
c62097c
Update to the last version of the base branch
RomainBaville Nov 21, 2025
d7f69d8
Uniform applyFilter to log messages
RomainBaville Nov 21, 2025
c6c1c9d
fix ruff and yapf
RomainBaville Nov 21, 2025
64c5c21
Fix test
RomainBaville Nov 24, 2025
4eaef30
fix test
RomainBaville Nov 24, 2025
af6e564
Update to the last version of the main
RomainBaville Nov 25, 2025
fa79fd4
Update to the last version of the main
RomainBaville Nov 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions geos-mesh/src/geos/mesh/utils/multiblockModifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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()
Expand All @@ -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
17 changes: 17 additions & 0 deletions geos-mesh/tests/test_multiblockModifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 ),
Expand All @@ -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 )
Comment on lines +44 to +54
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why in this PR ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I changed the filter MergeBlockEnhanced, its test needed to be change to, this test was usless with the new implementation of the filter so I move it to the test of the function mergeBlock

Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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'"
Expand All @@ -139,58 +140,58 @@ 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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure of try except and raise in the try.
Raising here is fine but capturing should be done in the caller or caller's caller tbf

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see here

Copy link
Contributor Author

@RomainBaville RomainBaville Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this pr I wanted to add or update the logger. To do that I used the same scheme try/except in all the plugins and filters. But your are right, the filtre may not use try/except. To keep "small" and "unitary" pr, I think it can be done in another pr (see pr #185 )

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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"
Expand Down
Loading