From 216e4d8cad7bcde4897bfcbc5e89d2a9c848102a Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Mon, 9 Feb 2026 16:24:46 +0100 Subject: [PATCH 1/4] Factorize getComponentNames* in one function --- geos-mesh/src/geos/mesh/utils/arrayHelpers.py | 58 +++++-------------- .../src/geos/mesh/utils/arrayModifiers.py | 3 +- geos-mesh/tests/test_arrayHelpers.py | 46 ++++++++------- 3 files changed, 41 insertions(+), 66 deletions(-) diff --git a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py index ad88ba02..c18f6a35 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py @@ -615,7 +615,9 @@ def getVtkArrayInObject( dataSet: vtkDataSet, attributeName: str, piece: Piece ) Returns: vtkDataArray: The vtk array corresponding to input attribute name. """ - assert isAttributeInObject( dataSet, attributeName, piece ), f"{attributeName} is not in input mesh." + if not isAttributeInObject( dataSet, attributeName, piece ): + raise AttributeError( f"{ attributeName } is not in input mesh." ) + dataArray: vtkDataArray if piece == Piece.POINTS: dataArray = dataSet.GetPointData().GetArray( attributeName ) @@ -708,55 +710,25 @@ def getComponentNames( tuple[str,...]: Names of the components. """ if isinstance( mesh, vtkDataSet ): - return getComponentNamesDataSet( mesh, attributeName, piece ) + array: vtkDataArray = getVtkArrayInObject( mesh, attributeName, piece ) + componentNames: list[ str ] = [] + if array.GetNumberOfComponents() > 1: + componentNames += [ array.GetComponentName( i ) for i in range( array.GetNumberOfComponents() ) ] elif isinstance( mesh, ( vtkMultiBlockDataSet, vtkCompositeDataSet ) ): - return getComponentNamesMultiBlock( mesh, attributeName, piece ) + elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( mesh ) + for blockIndex in elementaryBlockIndexes: + dataSet: vtkDataSet = vtkDataSet.SafeDownCast( mesh.GetDataSet( blockIndex ) ) + try: + return getComponentNames( dataSet, attributeName, piece ) + except: + continue + raise AttributeError( f"{ attributeName } is not in input mesh.") else: raise TypeError( "Mesh type is not managed." ) - -def getComponentNamesDataSet( dataSet: vtkDataSet, attributeName: str, piece: Piece ) -> tuple[ str, ...]: - """Get the name of the components of attribute attributeName in dataSet. - - Args: - dataSet (vtkDataSet): DataSet where the attribute is. - attributeName (str): Name of the attribute. - piece (Piece): The piece of the attribute. - - Returns: - tuple[str,...]: Names of the components. - """ - array: vtkDataArray = getVtkArrayInObject( dataSet, attributeName, piece ) - componentNames: list[ str ] = [] - - if array.GetNumberOfComponents() > 1: - componentNames += [ array.GetComponentName( i ) for i in range( array.GetNumberOfComponents() ) ] return tuple( componentNames ) -def getComponentNamesMultiBlock( - multiBlockDataSet: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet ], - attributeName: str, - piece: Piece, -) -> tuple[ str, ...]: - """Get the name of the components of attribute in MultiBlockDataSet. - - Args: - multiBlockDataSet (vtkMultiBlockDataSet | vtkCompositeDataSet): DataSet where the attribute is. - attributeName (str): Name of the attribute. - piece (Piece): The piece of the attribute. - - Returns: - tuple[str,...]: Names of the components. - """ - elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( multiBlockDataSet ) - for blockIndex in elementaryBlockIndexes: - dataSet: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSet.GetDataSet( blockIndex ) ) - if isAttributeInObject( dataSet, attributeName, piece ): - return getComponentNamesDataSet( dataSet, attributeName, piece ) - return () - - def getAttributeValuesAsDF( surface: vtkPolyData, attributeNames: tuple[ str, ...], piece: Piece = Piece.CELLS ) -> pd.DataFrame: diff --git a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py index 6bc763b3..11478895 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py @@ -29,7 +29,6 @@ from vtkmodules.vtkCommonCore import ( vtkDataArray, vtkPoints, vtkLogger ) from geos.mesh.utils.arrayHelpers import ( getComponentNames, - getComponentNamesDataSet, getAttributesWithNumberOfComponents, getArrayInObject, isAttributeInObject, @@ -635,7 +634,7 @@ def copyAttributeDataSet( raise AttributeError( f"The attribute { attributeNameFrom } is not in the source mesh." ) npArray: npt.NDArray[ Any ] = getArrayInObject( dataSetFrom, attributeNameFrom, piece ) - componentNames: tuple[ str, ...] = getComponentNamesDataSet( dataSetFrom, attributeNameFrom, piece ) + componentNames: tuple[ str, ...] = getComponentNames( dataSetFrom, attributeNameFrom, piece ) vtkArrayType: int = getVtkArrayTypeInObject( dataSetFrom, attributeNameFrom, piece ) createAttribute( dataSetTo, npArray, attributeNameTo, componentNames, piece, vtkArrayType, logger ) diff --git a/geos-mesh/tests/test_arrayHelpers.py b/geos-mesh/tests/test_arrayHelpers.py index 4c8a31c6..18dba6d5 100644 --- a/geos-mesh/tests/test_arrayHelpers.py +++ b/geos-mesh/tests/test_arrayHelpers.py @@ -497,33 +497,37 @@ def test_getNumberOfComponentsTypeError() -> None: arrayHelpers.getNumberOfComponents( mesh, "attribute", Piece.CELLS ) -@pytest.mark.parametrize( "attributeName, piece, expected", [ - ( "PERM", Piece.CELLS, ( "AX1", "AX2", "AX3" ) ), - ( "PORO", Piece.CELLS, () ), +@pytest.mark.parametrize( "meshName, attributeName, piece, expected", [ + ( "dataset", "PERM", Piece.CELLS, ( "AX1", "AX2", "AX3" ) ), + ( "dataset", "PORO", Piece.CELLS, () ), + ( "multiblock", "PERM", Piece.CELLS, ( "AX1", "AX2", "AX3" ) ), + ( "multiblock", "PORO", Piece.CELLS, () ), ] ) -def test_getComponentNamesDataSet( dataSetTest: vtkDataSet, attributeName: str, piece: Piece, - expected: tuple[ str, ...] ) -> None: - """Test getting the component names of an attribute from a dataset.""" - vtkDataSetTest: vtkDataSet = dataSetTest( "dataset" ) - obtained: tuple[ str, ...] = arrayHelpers.getComponentNamesDataSet( vtkDataSetTest, attributeName, piece ) +def test_getComponentNames( + dataSetTest: Any, + meshName: str, + attributeName: str, + piece: Piece, + expected: tuple[ str, ...] ) -> None: + """Test getting the component names of an attribute from a mesh.""" + vtkDataSetTest: Any = dataSetTest( meshName ) + obtained: tuple[ str, ...] = arrayHelpers.getComponentNames( vtkDataSetTest, attributeName, piece ) assert obtained == expected -@pytest.mark.parametrize( "attributeName, piece, expected", [ - ( "PERM", Piece.CELLS, ( "AX1", "AX2", "AX3" ) ), - ( "PORO", Piece.CELLS, () ), -] ) -def test_getComponentNamesMultiBlock( - dataSetTest: vtkMultiBlockDataSet, - attributeName: str, - piece: Piece, - expected: tuple[ str, ...], +def test_getComponentNamesRaises( + dataSetTest: Any, ) -> None: """Test getting the component names of an attribute from a multiblock.""" - vtkMultiBlockDataSetTest: vtkMultiBlockDataSet = dataSetTest( "multiblock" ) - obtained: tuple[ str, ...] = arrayHelpers.getComponentNamesMultiBlock( vtkMultiBlockDataSetTest, attributeName, - piece ) - assert obtained == expected + # TypeError + meshWrongType: vtkFieldData = vtkFieldData() + with pytest.raises( TypeError ): + arrayHelpers.getComponentNames( meshWrongType, "PORO", Piece.CELLS ) + + # AttributeError + mesh: vtkDataSet = dataSetTest( "dataset" ) + with pytest.raises( AttributeError ): + arrayHelpers.getComponentNames( mesh, "attributeName", Piece.POINTS ) @pytest.mark.parametrize( "attributeNames, piece, expected_columns", [ From 47e7eed4efc12e7abe7e89b8d83b1a4684f96a09 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Mon, 9 Feb 2026 16:28:26 +0100 Subject: [PATCH 2/4] Update the doc --- geos-mesh/src/geos/mesh/utils/arrayHelpers.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py index c18f6a35..b64242e3 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py @@ -26,7 +26,7 @@ The getter functions: - get the array of an attribute (one for dataset, one for multiblockDataset, one for the both and one for fieldData) - - get the component names of an attribute (one for dataset, one for multiblockDataset and one for the both) + - get the component names of an attribute - get the number of components of an attribute (one for dataset, one for multiblockDataset and one for the both) - get the piece of an attribute (for any meshes) - get the values of an attribute as data frame (for polyData only) @@ -699,7 +699,7 @@ def getComponentNames( attributeName: str, piece: Piece, ) -> tuple[ str, ...]: - """Get the name of the components of attribute attributeName in dataSet. + """Get the name of the components of the attribute 'attributeName' in a mesh. Args: mesh (vtkDataSet | vtkMultiBlockDataSet | vtkCompositeDataSet | vtkDataObject): Mesh where the attribute is. @@ -708,6 +708,10 @@ def getComponentNames( Returns: tuple[str,...]: Names of the components. + + Raises: + AttributeError: The attribute 'attributeName' is not in the mesh for the given piece. + TypeError: The mesh has to be inherited from vtkMultiBlockDataSet or vtkDataSet. """ if isinstance( mesh, vtkDataSet ): array: vtkDataArray = getVtkArrayInObject( mesh, attributeName, piece ) @@ -722,9 +726,9 @@ def getComponentNames( return getComponentNames( dataSet, attributeName, piece ) except: continue - raise AttributeError( f"{ attributeName } is not in input mesh.") + raise AttributeError( f"The attribute '{ attributeName }' is not in the mesh for the given piece { piece }.") else: - raise TypeError( "Mesh type is not managed." ) + raise TypeError( "The mesh has to be inherited from vtkMultiBlockDataSet or vtkDataSet." ) return tuple( componentNames ) From fbd5c3b01f62088c2a9b4ab8de45a0cd2562cbb5 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Mon, 9 Feb 2026 16:51:28 +0100 Subject: [PATCH 3/4] Factorize the function getNumberOfComponent* in one --- geos-mesh/src/geos/mesh/utils/arrayHelpers.py | 70 +++++++------------ .../src/geos/mesh/utils/arrayModifiers.py | 4 +- geos-mesh/tests/test_arrayHelpers.py | 67 +++++++----------- 3 files changed, 55 insertions(+), 86 deletions(-) diff --git a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py index b64242e3..eed81e1a 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py @@ -27,7 +27,7 @@ The getter functions: - get the array of an attribute (one for dataset, one for multiblockDataset, one for the both and one for fieldData) - get the component names of an attribute - - get the number of components of an attribute (one for dataset, one for multiblockDataset and one for the both) + - get the number of components of an attribute - get the piece of an attribute (for any meshes) - get the values of an attribute as data frame (for polyData only) - get the vtk type of an attribute (one for dataset, one for multiblockDataset and one for the both) @@ -637,7 +637,7 @@ def getNumberOfComponents( attributeName: str, piece: Piece, ) -> int: - """Get the number of components of attribute attributeName in dataSet. + """Get the number of components of the attribute 'attributeName' in the mesh for a given piece. Args: mesh (vtkMultiBlockDataSet | vtkCompositeDataSet | vtkDataSet): Mesh where the attribute is. @@ -646,52 +646,31 @@ def getNumberOfComponents( Returns: int: Number of components. + + Raises: + AttributeError: The attribute 'attributeName' is not in the mesh for the given piece. + TypeError: The mesh has to be inherited from vtkMultiBlockDataSet or vtkDataSet. + ValueError: The attribute's piece must be 'cells', 'points' or 'field'. """ + nbComponents: int = 0 if isinstance( mesh, vtkDataSet ): - return getNumberOfComponentsDataSet( mesh, attributeName, piece ) + array: vtkDataArray = getVtkArrayInObject( mesh, attributeName, piece ) + nbComponents = array.GetNumberOfComponents() elif isinstance( mesh, ( vtkMultiBlockDataSet, vtkCompositeDataSet ) ): - return getNumberOfComponentsMultiBlock( mesh, attributeName, piece ) + elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( mesh ) + for blockIndex in elementaryBlockIndexes: + dataSet: vtkDataSet = vtkDataSet.SafeDownCast( mesh.GetDataSet( blockIndex ) ) + try: + return getNumberOfComponents( dataSet, attributeName, piece ) + except ValueError as e: + raise e + except AttributeError: + continue + raise AttributeError( f"The attribute '{ attributeName }' is not in the mesh for the given piece { piece }.") else: raise TypeError( "The mesh has to be inherited from vtkMultiBlockDataSet or vtkDataSet." ) - -def getNumberOfComponentsDataSet( dataSet: vtkDataSet, attributeName: str, piece: Piece ) -> int: - """Get the number of components of attribute attributeName in dataSet. - - Args: - dataSet (vtkDataSet): DataSet where the attribute is. - attributeName (str): Name of the attribute. - piece (Piece): The piece of the attribute. - - Returns: - int: Number of components. - """ - array: vtkDataArray = getVtkArrayInObject( dataSet, attributeName, piece ) - return array.GetNumberOfComponents() - - -def getNumberOfComponentsMultiBlock( - multiBlockDataSet: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet ], - attributeName: str, - piece: Piece, -) -> int: - """Get the number of components of attribute attributeName in dataSet. - - Args: - multiBlockDataSet (vtkMultiBlockDataSet | vtkCompositeDataSet): multi block data Set where the attribute is. - attributeName (str): Name of the attribute. - piece (Piece): The piece of the attribute. - - Returns: - int: Number of components. - """ - elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( multiBlockDataSet ) - for blockIndex in elementaryBlockIndexes: - dataSet: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSet.GetDataSet( blockIndex ) ) - if isAttributeInObject( dataSet, attributeName, piece ): - array: vtkDataArray = getVtkArrayInObject( dataSet, attributeName, piece ) - return array.GetNumberOfComponents() - return 0 + return nbComponents def getComponentNames( @@ -712,10 +691,11 @@ def getComponentNames( Raises: AttributeError: The attribute 'attributeName' is not in the mesh for the given piece. TypeError: The mesh has to be inherited from vtkMultiBlockDataSet or vtkDataSet. + ValueError: The attribute's piece must be 'cells', 'points' or 'field'. """ + componentNames: list[ str ] = [] if isinstance( mesh, vtkDataSet ): array: vtkDataArray = getVtkArrayInObject( mesh, attributeName, piece ) - componentNames: list[ str ] = [] if array.GetNumberOfComponents() > 1: componentNames += [ array.GetComponentName( i ) for i in range( array.GetNumberOfComponents() ) ] elif isinstance( mesh, ( vtkMultiBlockDataSet, vtkCompositeDataSet ) ): @@ -724,7 +704,9 @@ def getComponentNames( dataSet: vtkDataSet = vtkDataSet.SafeDownCast( mesh.GetDataSet( blockIndex ) ) try: return getComponentNames( dataSet, attributeName, piece ) - except: + except ValueError as e: + raise e + except AttributeError: continue raise AttributeError( f"The attribute '{ attributeName }' is not in the mesh for the given piece { piece }.") else: diff --git a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py index 11478895..870502a5 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py @@ -38,7 +38,7 @@ getVtkArrayTypeInObject, getVtkArrayTypeInMultiBlock, getVtkDataTypeInObject, - getNumberOfComponentsMultiBlock, + getNumberOfComponents, ) from geos.mesh.utils.multiblockHelpers import getBlockElementIndexesFlatten from geos.utils.Errors import VTKError @@ -105,7 +105,7 @@ def fillPartialAttributes( # Get information of the attribute to fill. vtkDataType: int = getVtkArrayTypeInMultiBlock( multiBlockDataSet, attributeName, piece ) - nbComponents: int = getNumberOfComponentsMultiBlock( multiBlockDataSet, attributeName, piece ) + nbComponents: int = getNumberOfComponents( multiBlockDataSet, attributeName, piece ) componentNames: tuple[ str, ...] = () if nbComponents > 1: componentNames = getComponentNames( multiBlockDataSet, attributeName, piece ) diff --git a/geos-mesh/tests/test_arrayHelpers.py b/geos-mesh/tests/test_arrayHelpers.py index 18dba6d5..5add692f 100644 --- a/geos-mesh/tests/test_arrayHelpers.py +++ b/geos-mesh/tests/test_arrayHelpers.py @@ -438,44 +438,12 @@ def test_getVtkArrayInObject( request: pytest.FixtureRequest, arrayExpected: npt assert ( obtained_as_np == arrayExpected ).all() -@pytest.mark.parametrize( "attributeName, piece, expected", [ - ( "PORO", Piece.CELLS, 1 ), - ( "PERM", Piece.CELLS, 3 ), - ( "PointAttribute", Piece.POINTS, 3 ), -] ) -def test_getNumberOfComponentsDataSet( - dataSetTest: vtkDataSet, - attributeName: str, - piece: Piece, - expected: int, -) -> None: - """Test getting the number of components of an attribute from a dataset.""" - vtkDataSetTest: vtkDataSet = dataSetTest( "dataset" ) - obtained: int = arrayHelpers.getNumberOfComponentsDataSet( vtkDataSetTest, attributeName, piece ) - assert obtained == expected - - -@pytest.mark.parametrize( "attributeName, piece, expected", [ - ( "PORO", Piece.CELLS, 1 ), - ( "PERM", Piece.CELLS, 3 ), - ( "PointAttribute", Piece.POINTS, 3 ), -] ) -def test_getNumberOfComponentsMultiBlock( - dataSetTest: vtkMultiBlockDataSet, - attributeName: str, - piece: Piece, - expected: int, -) -> None: - """Test getting the number of components of an attribute from a multiblock.""" - vtkMultiBlockDataSetTest: vtkMultiBlockDataSet = dataSetTest( "multiblock" ) - obtained: int = arrayHelpers.getNumberOfComponentsMultiBlock( vtkMultiBlockDataSetTest, attributeName, piece ) - - assert obtained == expected - - @pytest.mark.parametrize( "meshName, attributeName, piece, expected", [ ( "dataset", "PORO", Piece.CELLS, 1 ), ( "dataset", "PERM", Piece.CELLS, 3 ), + ( "dataset", "PointAttribute", Piece.POINTS, 3 ), + ( "multiblock", "PORO", Piece.CELLS, 1 ), + ( "multiblock", "PERM", Piece.CELLS, 3 ), ( "multiblock", "PointAttribute", Piece.POINTS, 3 ), ] ) def test_getNumberOfComponents( @@ -490,11 +458,25 @@ def test_getNumberOfComponents( assert arrayHelpers.getNumberOfComponents( mesh, attributeName, piece ) == expected -def test_getNumberOfComponentsTypeError() -> None: - """Test getNumberOfComponents TypeError raises.""" - mesh: vtkCellData = vtkCellData() +def test_getNumberOfComponentsRaises( + dataSetTest: Any, +) -> None: + """Test getNumberOfComponents fails.""" + # TypeError + meshWrongType: vtkCellData = vtkCellData() with pytest.raises( TypeError ): - arrayHelpers.getNumberOfComponents( mesh, "attribute", Piece.CELLS ) + arrayHelpers.getNumberOfComponents( meshWrongType, "PORO", Piece.CELLS ) + + # AttributeError + mesh: vtkDataSet = dataSetTest( "dataset" ) + with pytest.raises( AttributeError ): + arrayHelpers.getNumberOfComponents( mesh, "attributeName", Piece.POINTS ) + + # TODO + # # ValueError + # with pytest.raises( ValueError ): + # arrayHelpers.getNumberOfComponents( mesh, "mass", Piece.BOTH ) + @pytest.mark.parametrize( "meshName, attributeName, piece, expected", [ @@ -518,7 +500,7 @@ def test_getComponentNames( def test_getComponentNamesRaises( dataSetTest: Any, ) -> None: - """Test getting the component names of an attribute from a multiblock.""" + """Test getting the component names fails.""" # TypeError meshWrongType: vtkFieldData = vtkFieldData() with pytest.raises( TypeError ): @@ -529,6 +511,11 @@ def test_getComponentNamesRaises( with pytest.raises( AttributeError ): arrayHelpers.getComponentNames( mesh, "attributeName", Piece.POINTS ) + # TODO + # # ValueError + # with pytest.raises( ValueError ): + # arrayHelpers.getComponentNames( mesh, "mass", Piece.BOTH ) + @pytest.mark.parametrize( "attributeNames, piece, expected_columns", [ ( ( "collocated_nodes", ), Piece.POINTS, ( "collocated_nodes_0", "collocated_nodes_1" ) ), From 5b6b0e1d7a37df154d8c5c0fdaa8342519fe1dd2 Mon Sep 17 00:00:00 2001 From: Romain Baville Date: Mon, 9 Feb 2026 17:10:02 +0100 Subject: [PATCH 4/4] factorize isAttributeInObject* in one --- geos-mesh/src/geos/mesh/utils/arrayHelpers.py | 74 ++++++------------- .../src/geos/mesh/utils/arrayModifiers.py | 24 +++--- geos-mesh/tests/test_arrayHelpers.py | 46 ++---------- 3 files changed, 42 insertions(+), 102 deletions(-) diff --git a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py index eed81e1a..a51ef053 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayHelpers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayHelpers.py @@ -450,7 +450,7 @@ def getAttributesFromDataSet( dataSet: vtkDataSet, piece: Piece ) -> dict[ str, def isAttributeInObject( mesh: Union[ vtkMultiBlockDataSet, vtkDataSet ], attributeName: str, piece: Piece ) -> bool: - """Check if an attribute is in the input object. + """Check if an attribute is in the input mesh for the given piece. Args: mesh (vtkMultiBlockDataSet | vtkDataSet): Input mesh. @@ -458,62 +458,34 @@ def isAttributeInObject( mesh: Union[ vtkMultiBlockDataSet, vtkDataSet ], attrib piece (Piece): The piece of the attribute. Returns: - bool: True if the attribute is in the table, False otherwise. + bool: True if the attribute is on the mesh, False otherwise. + + Raises: + TypeError: The mesh has to be inherited from vtkMultiBlockDataSet or vtkDataSet. """ - if isinstance( mesh, vtkMultiBlockDataSet ): - return isAttributeInObjectMultiBlockDataSet( mesh, attributeName, piece ) - elif isinstance( mesh, vtkDataSet ): - return isAttributeInObjectDataSet( mesh, attributeName, piece ) + if isinstance( mesh, vtkDataSet ): + if piece == Piece.FIELD: + return bool( mesh.GetFieldData().HasArray( attributeName ) ) + elif piece == Piece.POINTS: + return bool( mesh.GetPointData().HasArray( attributeName ) ) + elif piece == Piece.CELLS: + return bool( mesh.GetCellData().HasArray( attributeName ) ) + elif piece == Piece.BOTH: + onPoints: int = mesh.GetPointData().HasArray( attributeName ) + onCells: int = mesh.GetCellData().HasArray( attributeName ) + return onCells == onPoints == 1 + elif isinstance( mesh, vtkMultiBlockDataSet ): + elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( mesh ) + for blockIndex in elementaryBlockIndexes: + dataSet: vtkDataSet = vtkDataSet.SafeDownCast( mesh.GetDataSet( blockIndex ) ) + if isAttributeInObject( dataSet, attributeName, piece ): + return True else: raise TypeError( "Input object must be a vtkDataSet or vtkMultiBlockDataSet." ) - -def isAttributeInObjectMultiBlockDataSet( multiBlockDataSet: vtkMultiBlockDataSet, attributeName: str, - piece: Piece ) -> bool: - """Check if an attribute is in the input object. - - Args: - multiBlockDataSet (vtkMultiBlockDataSet): Input multiBlockDataSet. - attributeName (str): Name of the attribute. - piece (Piece): The piece of the attribute. - - Returns: - bool: True if the attribute is in the table, False otherwise. - """ - elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( multiBlockDataSet ) - for blockIndex in elementaryBlockIndexes: - dataSet: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSet.GetDataSet( blockIndex ) ) - if isAttributeInObjectDataSet( dataSet, attributeName, piece ): - return True - return False -def isAttributeInObjectDataSet( dataSet: vtkDataSet, attributeName: str, piece: Piece ) -> bool: - """Check if an attribute is in the input object for the input piece. - - Args: - dataSet (vtkDataSet): Input dataSet. - attributeName (str): Name of the attribute. - piece (Piece): The piece of the attribute. - - Returns: - bool: True if the attribute is in the table, False otherwise. - """ - if piece == Piece.FIELD: - return bool( dataSet.GetFieldData().HasArray( attributeName ) ) - elif piece == Piece.POINTS: - return bool( dataSet.GetPointData().HasArray( attributeName ) ) - elif piece == Piece.CELLS: - return bool( dataSet.GetCellData().HasArray( attributeName ) ) - elif piece == Piece.BOTH: - onPoints: int = dataSet.GetPointData().HasArray( attributeName ) - onCells: int = dataSet.GetCellData().HasArray( attributeName ) - return onCells == onPoints == 1 - else: - return False - - def isAttributeGlobal( multiBlockDataSet: vtkMultiBlockDataSet, attributeName: str, piece: Piece ) -> bool: """Check if an attribute is global in the input multiBlockDataSet. @@ -528,7 +500,7 @@ def isAttributeGlobal( multiBlockDataSet: vtkMultiBlockDataSet, attributeName: s elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( multiBlockDataSet ) for blockIndex in elementaryBlockIndexes: dataSet: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSet.GetDataSet( blockIndex ) ) - if not isAttributeInObjectDataSet( dataSet, attributeName, piece ): + if not isAttributeInObject( dataSet, attributeName, piece ): return False return True diff --git a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py index 870502a5..390a1537 100644 --- a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py +++ b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py @@ -32,8 +32,6 @@ getAttributesWithNumberOfComponents, getArrayInObject, isAttributeInObject, - isAttributeInObjectDataSet, - isAttributeInObjectMultiBlockDataSet, isAttributeGlobal, getVtkArrayTypeInObject, getVtkArrayTypeInMultiBlock, @@ -96,7 +94,7 @@ def fillPartialAttributes( raise TypeError( "Input mesh has to be inherited from vtkMultiBlockDataSet." ) # Check if the attribute exist in the input mesh. - if not isAttributeInObjectMultiBlockDataSet( multiBlockDataSet, attributeName, piece ): + if not isAttributeInObject( multiBlockDataSet, attributeName, piece ): raise AttributeError( f"The attribute { attributeName } is not in the mesh." ) # Check if the attribute is partial. @@ -153,7 +151,7 @@ def fillPartialAttributes( elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( multiBlockDataSet ) for blockIndex in elementaryBlockIndexes: dataSet: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSet.GetDataSet( blockIndex ) ) - if not isAttributeInObjectDataSet( dataSet, attributeName, piece ): + if not isAttributeInObject( dataSet, attributeName, piece ): createConstantAttributeDataSet( dataSet, listValues, attributeName, componentNames, piece, vtkDataType, logger ) @@ -332,7 +330,7 @@ def createConstantAttributeMultiBlock( raise ValueError( f"The attribute must be created on { Piece.POINTS.value } or { Piece.CELLS.value }." ) # Check if the attribute already exist in the input mesh. - if isAttributeInObjectMultiBlockDataSet( multiBlockDataSet, attributeName, piece ): + if isAttributeInObject( multiBlockDataSet, attributeName, piece ): raise AttributeError( f"The attribute { attributeName } is already present in the mesh." ) # Parse the multiBlockDataSet to create the constant attribute on each blocks. @@ -473,12 +471,12 @@ def createAttribute( raise TypeError( "Input dataSet has to be inherited from vtkDataSet." ) # Check if the attribute already exist in the input mesh. - if isAttributeInObjectDataSet( dataSet, attributeName, piece ): + if isAttributeInObject( dataSet, attributeName, piece ): raise AttributeError( f"The attribute { attributeName } is already present in the mesh." ) # Check if an attribute with the same name exist on the opposite piece (points or cells) on the input mesh. oppositePiece: Piece = Piece.CELLS if piece == Piece.POINTS else Piece.POINTS - if isAttributeInObjectDataSet( dataSet, attributeName, oppositePiece ): + if isAttributeInObject( dataSet, attributeName, oppositePiece ): logger.warning( f"The attribute { attributeName } exist on the opposite piece { oppositePiece.value }." ) # Check the coherency between the given array type and the vtk array type if it exist. @@ -573,11 +571,11 @@ def copyAttribute( raise TypeError( "Final mesh has to be inherited from vtkMultiBlockDataSet." ) # Check if the attribute exist in the multiBlockDataSetFrom. - if not isAttributeInObjectMultiBlockDataSet( multiBlockDataSetFrom, attributeNameFrom, piece ): + if not isAttributeInObject( multiBlockDataSetFrom, attributeNameFrom, piece ): raise AttributeError( f"The attribute { attributeNameFrom } is not present in the source mesh." ) # Check if the attribute already exist in the multiBlockDataSetTo. - if isAttributeInObjectMultiBlockDataSet( multiBlockDataSetTo, attributeNameTo, piece ): + if isAttributeInObject( multiBlockDataSetTo, attributeNameTo, piece ): raise AttributeError( f"The attribute { attributeNameTo } is already present in the final mesh." ) # Check if the two multiBlockDataSets are similar. @@ -591,7 +589,7 @@ def copyAttribute( dataSetFrom: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSetFrom.GetDataSet( idBlock ) ) dataSetTo: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSetTo.GetDataSet( idBlock ) ) - if isAttributeInObjectDataSet( dataSetFrom, attributeNameFrom, piece ): + if isAttributeInObject( dataSetFrom, attributeNameFrom, piece ): copyAttributeDataSet( dataSetFrom, dataSetTo, attributeNameFrom, attributeNameTo, piece, logger ) return @@ -630,7 +628,7 @@ def copyAttributeDataSet( raise TypeError( "Source mesh has to be inherited from vtkDataSet." ) # Check if the attribute exist in the dataSetFrom. - if not isAttributeInObjectDataSet( dataSetFrom, attributeNameFrom, piece ): + if not isAttributeInObject( dataSetFrom, attributeNameFrom, piece ): raise AttributeError( f"The attribute { attributeNameFrom } is not in the source mesh." ) npArray: npt.NDArray[ Any ] = getArrayInObject( dataSetFrom, attributeNameFrom, piece ) @@ -811,7 +809,7 @@ def transferAttributeWithElementMap( if isinstance( meshTo, vtkDataSet ): transferAttributeToDataSetWithElementMap( meshFrom, meshTo, elementMap, attributeName, piece, logger=logger ) elif isinstance( meshTo, vtkMultiBlockDataSet ): - if isAttributeInObjectMultiBlockDataSet( meshTo, attributeName, piece ): + if isAttributeInObject( meshTo, attributeName, piece ): raise AttributeError( f"The attribute { attributeName } is already in the final mesh." ) listFlatIdDataSetTo: list[ int ] = getBlockElementIndexesFlatten( meshTo ) @@ -918,7 +916,7 @@ def createCellCenterAttribute( logger = getLogger( "createCellCenterAttribute", True ) if isinstance( mesh, vtkMultiBlockDataSet ): - if isAttributeInObjectMultiBlockDataSet( mesh, cellCenterAttributeName, Piece.CELLS ): + if isAttributeInObject( mesh, cellCenterAttributeName, Piece.CELLS ): raise AttributeError( f"The attribute { cellCenterAttributeName } in already in the mesh." ) elementaryBlockIndexes: list[ int ] = getBlockElementIndexesFlatten( mesh ) diff --git a/geos-mesh/tests/test_arrayHelpers.py b/geos-mesh/tests/test_arrayHelpers.py index 5add692f..d275f15b 100644 --- a/geos-mesh/tests/test_arrayHelpers.py +++ b/geos-mesh/tests/test_arrayHelpers.py @@ -310,33 +310,6 @@ def test_isAttributeInObjectTypeError() -> None: arrayHelpers.isAttributeInObject( mesh, "Attribute", Piece.CELLS ) -@pytest.mark.parametrize( "attributeName, piece", [ - ( "rockPorosity_referencePorosity", Piece.CELLS ), - ( "ghostRank", Piece.POINTS ), - ( "TIME", Piece.FIELD ), - ( "ghostRank", Piece.BOTH ), -] ) -def test_isAttributeInObjectMultiBlockDataSet( dataSetTest: vtkMultiBlockDataSet, attributeName: str, - piece: Piece ) -> None: - """Test presence of attribute in a multiblock.""" - multiBlockDataset: vtkMultiBlockDataSet = dataSetTest( "multiblockGeosOutput" ) - obtained: bool = arrayHelpers.isAttributeInObjectMultiBlockDataSet( multiBlockDataset, attributeName, piece ) - assert obtained - - -@pytest.mark.parametrize( "attributeName, piece, expected", [ - ( "PointAttribute", Piece.POINTS, True ), - ( "PORO", Piece.CELLS, True ), - ( "PORO", Piece.POINTS, False ), -] ) -def test_isAttributeInObjectDataSet( dataSetTest: vtkDataSet, attributeName: str, piece: Piece, - expected: bool ) -> None: - """Test presence of attribute in a dataset.""" - vtkDataset: vtkDataSet = dataSetTest( "dataset" ) - obtained: bool = arrayHelpers.isAttributeInObjectDataSet( vtkDataset, attributeName, piece ) - assert obtained == expected - - @pytest.mark.parametrize( "attributeName, piece, expected", [ ( "PORO", Piece.CELLS, False ), ( "GLOBAL_IDS_POINTS", Piece.POINTS, True ), @@ -468,15 +441,13 @@ def test_getNumberOfComponentsRaises( arrayHelpers.getNumberOfComponents( meshWrongType, "PORO", Piece.CELLS ) # AttributeError - mesh: vtkDataSet = dataSetTest( "dataset" ) + mesh: vtkDataSet = dataSetTest( "multiblockGeosOutput" ) with pytest.raises( AttributeError ): arrayHelpers.getNumberOfComponents( mesh, "attributeName", Piece.POINTS ) - # TODO - # # ValueError - # with pytest.raises( ValueError ): - # arrayHelpers.getNumberOfComponents( mesh, "mass", Piece.BOTH ) - + # ValueError + with pytest.raises( ValueError ): + arrayHelpers.getNumberOfComponents( mesh, "ghostRank", Piece.BOTH ) @pytest.mark.parametrize( "meshName, attributeName, piece, expected", [ @@ -507,14 +478,13 @@ def test_getComponentNamesRaises( arrayHelpers.getComponentNames( meshWrongType, "PORO", Piece.CELLS ) # AttributeError - mesh: vtkDataSet = dataSetTest( "dataset" ) + mesh: vtkDataSet = dataSetTest( "multiblockGeosOutput" ) with pytest.raises( AttributeError ): arrayHelpers.getComponentNames( mesh, "attributeName", Piece.POINTS ) - # TODO - # # ValueError - # with pytest.raises( ValueError ): - # arrayHelpers.getComponentNames( mesh, "mass", Piece.BOTH ) + # ValueError + with pytest.raises( ValueError ): + arrayHelpers.getComponentNames( mesh, "ghostRank", Piece.BOTH ) @pytest.mark.parametrize( "attributeNames, piece, expected_columns", [