Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
0ca3fe5
add a function to get the type of a vtk array
RomainBaville Jun 24, 2025
a905450
uptade the function createAttribute to preserve the type of the vtk a…
RomainBaville Jun 24, 2025
ec0302f
update the typing in the test of the function createAttribute
RomainBaville Jun 24, 2025
6c501c4
Update createAttribute and createConstantAttributeDataSet
RomainBaville Jun 26, 2025
510887d
Merge branch 'main' into RomainBaville/feature/update_geos-mesh_utils
RomainBaville Jun 26, 2025
490135c
update fillPartialAttribute and fillAllPartialAttributes
RomainBaville Jun 27, 2025
15a67fa
Add a function to get the vtk data type of an attribute of a multiblo…
RomainBaville Jun 27, 2025
5b17644
Formating for the CI
RomainBaville Jun 27, 2025
bd63003
Uptade functions calling utils functions
RomainBaville Jun 30, 2025
19ffa8d
Fix the doc issue
RomainBaville Jun 30, 2025
27b9c83
Create the two files one for the plugin, one for the filter
RomainBaville Jun 30, 2025
69dca82
Create the vtk filter from the paraview plugin
RomainBaville Jun 30, 2025
27b6abf
Fix build issue
RomainBaville Jul 1, 2025
dcadd7a
Merge branch 'RomainBaville/feature/update_geos-mesh_utils' into test
RomainBaville Jul 1, 2025
bcdf4bd
Apply suggestions from code review
RomainBaville Jul 15, 2025
e79f5ab
Generalize error message of copyAttribute
RomainBaville Jul 15, 2025
b17e2e5
Add a raise assertion error in case of the mesh doen't have the attri…
RomainBaville Jul 15, 2025
5941980
Update the default value for uint case for fillpartialattribute
RomainBaville Jul 15, 2025
f46fde5
Cleen and add logger to manadge output messages
RomainBaville Jul 16, 2025
614cafa
clear the tests and functions of arrayModifiers
RomainBaville Jul 18, 2025
1423482
Clean fillpartialattribute and its test
RomainBaville Jul 22, 2025
0e2ded2
clean the code and add a funtion to test if an attribute is partial.
RomainBaville Jul 22, 2025
68d6c3c
fix the test of isAttributeGlobal
RomainBaville Jul 22, 2025
57c9bd2
Clean the code
RomainBaville Jul 22, 2025
b4ff24e
Clean for ci
RomainBaville Jul 23, 2025
7da8f9b
Clean for the ci
RomainBaville Jul 23, 2025
3c8f5d6
Clean doc
RomainBaville Jul 23, 2025
1d16852
Clean for ci
RomainBaville Jul 23, 2025
b4e2084
Clean For ci
RomainBaville Jul 23, 2025
f052c14
Clean For ci
RomainBaville Jul 23, 2025
b6cfe25
Change the color of info to green
RomainBaville Jul 28, 2025
3cdda2f
create the filter to use without paraview
RomainBaville Jul 28, 2025
3c82b65
Move the paraview plugin to the good folder
RomainBaville Jul 28, 2025
75c1cdf
Some test for the filter CreateConstanteAttributePerRegion
RomainBaville Jul 28, 2025
0728db7
adapte some utils function for the filtre CreateConstanteAttributePer…
RomainBaville Jul 28, 2025
6fc4f5d
Apply suggestions from Paloma's code review
RomainBaville Jul 28, 2025
038d39a
Use the last verion of geos-mesh utils
RomainBaville Jul 28, 2025
80c08ae
Merge branch 'main' into RomainBaville/feature/update_geos-mesh_utils
RomainBaville Jul 28, 2025
36d715f
fix error in transferAttributes
RomainBaville Jul 28, 2025
fec2b63
Merge branch 'RomainBaville/feature/update_geos-mesh_utils' into Roma…
RomainBaville Jul 28, 2025
c8e5965
update default value for uint type
RomainBaville Jul 29, 2025
1acc3f1
Clean output message and optimization of the code
RomainBaville Jul 29, 2025
b8c1bc3
Clean the doc
RomainBaville Jul 29, 2025
f9baa6c
Start of the tests
RomainBaville Jul 29, 2025
8f0ed47
Merge branch 'main' into RomainBaville/feature/update_geos-mesh_utils
RomainBaville Jul 30, 2025
9bee4e2
Merge branch 'main' into RomainBaville/feature/VTK_filter_and_PVCreat…
RomainBaville Jul 30, 2025
9eb7454
Manadge the input region index
RomainBaville Jul 30, 2025
6956e97
Remove the use of VTKPythonAlgorithmBase in the filter CreateConstant…
RomainBaville Jul 31, 2025
1f99e6d
Update log to be more clear
RomainBaville Aug 1, 2025
1e2007f
Add a Handler to count warnings messages
RomainBaville Aug 6, 2025
1932910
Add the function to get the vtk data type of a mesh (single or multi …
RomainBaville Aug 6, 2025
c24c004
update test for the filter
RomainBaville Aug 6, 2025
c9ae028
Clean the log and the doc
RomainBaville Aug 6, 2025
e00c918
Clean variables names
RomainBaville Aug 6, 2025
2632df8
Clean the doc and the variables names
RomainBaville Aug 6, 2025
96f2237
Clean variables name and typing
RomainBaville Aug 6, 2025
2ac03bc
Remove the AsDF function
RomainBaville Aug 6, 2025
a021fa7
Change variables iter to iterator
RomainBaville Aug 6, 2025
f100bb8
Clean for ci
RomainBaville Aug 6, 2025
0d65425
Remove the plugin from geos_prep and update the doc.rst file
RomainBaville Aug 6, 2025
2eb0ebb
Fix doc
RomainBaville Aug 6, 2025
4fcbc27
Merge branch 'RomainBaville/feature/update_geos-mesh_utils' into Roma…
RomainBaville Aug 6, 2025
9b89251
Update to main
RomainBaville Aug 7, 2025
06f57f9
Clean for ci
RomainBaville Aug 7, 2025
5e305d2
Merge branch 'main' into RomainBaville/feature/VTK_filter_and_PVCreat…
RomainBaville Aug 12, 2025
4ea154e
Add the plugin to the doc.
RomainBaville Aug 12, 2025
901b108
Merge branch 'main' into RomainBaville/feature/VTK_filter_and_PVCreat…
alexbenedicto Aug 22, 2025
420db97
Apply suggestions from Paloma's review
RomainBaville Sep 9, 2025
3a7b650
fix: Remove geos prep and update pyproject maintainers (#127)
alexbenedicto Aug 27, 2025
ebc3e6f
Move the function checkValidValuesInDataSet in arrayHelpers
RomainBaville Sep 9, 2025
3c8d5eb
Move the fuctnion getAttributePieceInfo in arrayHelpers
RomainBaville Sep 9, 2025
1b669c2
Use the function getAttributePieceInfo of arrayHelpers
RomainBaville Sep 9, 2025
aa7ece6
Clean createNpArray
RomainBaville Sep 9, 2025
9c55956
add the tests for the new function
RomainBaville Sep 9, 2025
e2d7bd7
clean for ci
RomainBaville Sep 9, 2025
8434da9
Improve the doc
RomainBaville Sep 9, 2025
0b89558
Update to the last version of the main
RomainBaville Sep 10, 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
7 changes: 7 additions & 0 deletions docs/geos_mesh_docs/processing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ Processing filters

The `processing` module of `geos-mesh` package contains filters to process meshes.

geos.mesh.processing.CreateConstantAttributePerRegion filter
-------------------------------------------------------------

.. automodule:: geos.mesh.processing.CreateConstantAttributePerRegion
:members:
:undoc-members:
:show-inheritance:

geos.mesh.processing.FillPartialArrays filter
----------------------------------------------
Expand Down
6 changes: 0 additions & 6 deletions docs/geos_posp_docs/PVplugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ PVAttributeMapping plugin
.. automodule:: PVplugins.PVAttributeMapping


PVCreateConstantAttributePerRegion plugin
---------------------------------------------------

.. automodule:: PVplugins.PVCreateConstantAttributePerRegion


PVExtractMergeBlocksVolume plugin
-------------------------------------------

Expand Down
8 changes: 8 additions & 0 deletions docs/geos_pv_docs/processing.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
Post-/Pre-processing
=========================


PVCreateConstantAttributePerRegion
-----------------------------------

.. automodule:: geos.pv.plugins.PVCreateConstantAttributePerRegion


PVFillPartialArrays
--------------------

.. automodule:: geos.pv.plugins.PVFillPartialArrays


Expand Down
419 changes: 419 additions & 0 deletions geos-mesh/src/geos/mesh/processing/CreateConstantAttributePerRegion.py

Large diffs are not rendered by default.

35 changes: 9 additions & 26 deletions geos-mesh/src/geos/mesh/processing/FillPartialArrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from geos.utils.Logger import logging, Logger, getLogger
from geos.mesh.utils.arrayModifiers import fillPartialAttributes
from geos.mesh.utils.arrayHelpers import isAttributeInObject
from geos.mesh.utils.arrayHelpers import getAttributePieceInfo

from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet

Expand All @@ -23,7 +23,7 @@
0 for uint data, -1 for int data and nan for float data.

To use a handler of yours for the logger, set the variable 'speHandler' to True and add it to the filter
with the member function addLoggerHandler.
with the member function setLoggerHandler.

To use it:

Expand All @@ -42,7 +42,7 @@

# Set the handler of yours (only if speHandler is True).
yourHandler: logging.Handler
filter.addLoggerHandler( yourHandler )
filter.setLoggerHandler( yourHandler )

# Do calculations.
filter.applyFilter()
Expand Down Expand Up @@ -106,15 +106,17 @@ def applyFilter( self: Self ) -> bool:
"""
self.logger.info( f"Apply filter { self.logger.name }." )

onPoints: Union[ None, bool ]
onBoth: bool
for attributeName in self.dictAttributesValues:
self._setPieceRegionAttribute( attributeName )
if self.onPoints is None:
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 self.onBoth:
if onBoth:
self.logger.error(
f"Their is two attribute named { attributeName }, one on points and the other on cells. The attribute must be unique."
)
Expand All @@ -124,7 +126,7 @@ def applyFilter( self: Self ) -> bool:

if not fillPartialAttributes( self.multiBlockDataSet,
attributeName,
onPoints=self.onPoints,
onPoints=onPoints,
listValues=self.dictAttributesValues[ attributeName ],
logger=self.logger ):
self.logger.error( f"The filter { self.logger.name } failed." )
Expand All @@ -133,22 +135,3 @@ def applyFilter( self: Self ) -> bool:
self.logger.info( f"The filter { self.logger.name } succeed." )

return True

def _setPieceRegionAttribute( self: Self, attributeName: str ) -> None:
"""Set the attribute self.onPoints and self.onBoth.

self.onPoints is True if the region attribute is on points, False if it is on cells, None otherwise.

self.onBoth is True if a region attribute is on points and on cells, False otherwise.

Args:
attributeName (str): The name of the attribute to verify.
"""
self.onPoints: Union[ bool, None ] = None
self.onBoth: bool = False
if isAttributeInObject( self.multiBlockDataSet, attributeName, False ):
self.onPoints = False
if isAttributeInObject( self.multiBlockDataSet, attributeName, True ):
if self.onPoints is False:
self.onBoth = True
self.onPoints = True
114 changes: 114 additions & 0 deletions geos-mesh/src/geos/mesh/utils/arrayHelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,102 @@ def has_array( mesh: vtkUnstructuredGrid, array_names: list[ str ] ) -> bool:
return False


def getAttributePieceInfo(
mesh: Union[ vtkDataSet, vtkMultiBlockDataSet ],
attributeName: str,
) -> tuple[ Union[ None, bool ], bool ]:
"""Get the attribute piece information.

Two information are given:
- onPoints (Union[None, bool]): True if the attribute is on points or on both pieces, False if it is on cells, None otherwise.
- onBoth (bool): True if the attribute is on points and on cells, False otherwise.

Args:
mesh (Union[vtkDataSet, vtkMultiBlockDataSet]): The mesh with the attribute.
attributeName (str): The name of the attribute.

Returns:
tuple[Union[None, bool], bool]: The piece information of the attribute.
"""
onPoints: Union[ bool, None ] = None
onBoth: bool = False
if isAttributeInObject( mesh, attributeName, False ):
onPoints = False
if isAttributeInObject( mesh, attributeName, True ):
if onPoints is False:
onBoth = True
onPoints = True

return ( onPoints, onBoth )


def checkValidValuesInMultiBlock(
multiBlockDataSet: vtkMultiBlockDataSet,
attributeName: str,
listValues: list[ Any ],
onPoints: bool,
) -> tuple[ list[ Any ], list[ Any ] ]:
"""Check if each value is valid , ie if that value is a data of the attribute in at least one dataset of the multiblock.

Args:
multiBlockDataSet (vtkMultiBlockDataSet): The multiblock dataset mesh to check.
attributeName (str): The name of the attribute with the data.
listValues (list[Any]): The list of values to check.
onPoints (bool): True if the attribute is on points, False if on cells.

Returns:
tuple[list[Any], list[Any]]: Tuple containing the list of valid values and the list of the invalid ones.
"""
validValues: list[ Any ] = []
invalidValues: list[ Any ] = []
listFlatIdDataSet: list[ int ] = getBlockElementIndexesFlatten( multiBlockDataSet )
for flatIdDataSet in listFlatIdDataSet:
dataSet: vtkDataSet = vtkDataSet.SafeDownCast( multiBlockDataSet.GetDataSet( flatIdDataSet ) )
# Get the valid values of the dataset.
validValuesDataSet: list[ Any ] = checkValidValuesInDataSet( dataSet, attributeName, listValues, onPoints )[ 0 ]

# Keep the new true values.
for value in validValuesDataSet:
if value not in validValues:
validValues.append( value )

# Get the false indexes.
for value in listValues:
if value not in validValues:
invalidValues.append( value )

return ( validValues, invalidValues )


def checkValidValuesInDataSet(
dataSet: vtkDataSet,
attributeName: str,
listValues: list[ Any ],
onPoints: bool,
) -> tuple[ list[ Any ], list[ Any ] ]:
"""Check if each value is valid , ie if that value is a data of the attribute in the dataset.

Args:
dataSet (vtkDataSet): The dataset mesh to check.
attributeName (str): The name of the attribute with the data.
listValues (list[Any]): The list of values to check.
onPoints (bool): True if the attribute is on points, False if on cells.

Returns:
tuple[list[Any], list[Any]]: Tuple containing the list of valid values and the list of the invalid ones.
"""
attributeNpArray = getArrayInObject( dataSet, attributeName, onPoints )
validValues: list[ Any ] = []
invalidValues: list[ Any ] = []
for value in listValues:
if value in attributeNpArray:
validValues.append( value )
else:
invalidValues.append( value )

return ( validValues, invalidValues )


def getFieldType( data: vtkFieldData ) -> str:
"""Returns whether the data is "vtkFieldData", "vtkCellData" or "vtkPointData".

Expand Down Expand Up @@ -357,6 +453,24 @@ def getArrayInObject( dataSet: vtkDataSet, attributeName: str, onPoints: bool )
return npArray


def getVtkDataTypeInObject( multiBlockDataSet: Union[ vtkDataSet, vtkMultiBlockDataSet ], attributeName: str,
onPoints: bool ) -> int:
"""Return VTK type of requested array from input mesh.

Args:
multiBlockDataSet (Union[vtkDataSet, vtkMultiBlockDataSet]): Input multiBlockDataSet.
attributeName (str): Name of the attribute.
onPoints (bool): True if attributes are on points, False if they are on cells.

Returns:
int: The type of the vtk array corresponding to input attribute name.
"""
if isinstance( multiBlockDataSet, vtkDataSet ):
return getVtkArrayTypeInObject( multiBlockDataSet, attributeName, onPoints )
else:
return getVtkArrayTypeInMultiBlock( multiBlockDataSet, attributeName, onPoints )


def getVtkArrayTypeInObject( dataSet: vtkDataSet, attributeName: str, onPoints: bool ) -> int:
"""Return VTK type of requested array from dataset input.

Expand Down
122 changes: 122 additions & 0 deletions geos-mesh/tests/test_CreateConstantAttributePerRegion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
# SPDX-FileContributor: Romain Baville
# SPDX-License-Identifier: Apache 2.0
# ruff: noqa: E402 # disable Module level import not at top of file
# mypy: disable-error-code="operator"
import pytest
from typing import Union, Any
from vtkmodules.vtkCommonDataModel import ( vtkDataSet, vtkMultiBlockDataSet )

from geos.mesh.processing.CreateConstantAttributePerRegion import CreateConstantAttributePerRegion, np


@pytest.mark.parametrize(
"meshType, newAttributeName, regionName, dictRegionValues, componentNames, componentNamesTest, valueNpType, succeed",
[
# Test the name of the new attribute (new on the mesh, one present on the other piece).
## For vtkDataSet.
( "dataset", "newAttribute", "GLOBAL_IDS_POINTS", {}, (), (), np.float32, True ),
( "dataset", "CellAttribute", "GLOBAL_IDS_POINTS", {}, (), (), np.float32, True ),
## For vtkMultiBlockDataSet.
( "multiblock", "newAttribute", "GLOBAL_IDS_POINTS", {}, (), (), np.float32, True ),
( "multiblock", "CellAttribute", "GLOBAL_IDS_POINTS", {}, (), (), np.float32, True ),
( "multiblock", "GLOBAL_IDS_CELLS", "GLOBAL_IDS_POINTS", {}, (), (), np.float32, True ),
# Test if the region attribute is on cells or on points.
( "dataset", "newAttribute", "FAULT", {}, (), (), np.float32, True ),
# Test the component name.
( "dataset", "newAttribute", "FAULT", {}, ( "X" ), (), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {}, (), ( "Component0", "Component1" ), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {}, ( "X" ), ( "Component0", "Component1" ), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {}, ( "X", "Y" ), ( "X", "Y" ), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {}, ( "X", "Y", "Z" ), ( "X", "Y" ), np.float32, True ),
# Test the type of value.
( "dataset", "newAttribute", "FAULT", {}, (), (), np.int8, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.int16, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.int32, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.int64, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.uint8, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.uint16, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.uint32, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.uint64, True ),
( "dataset", "newAttribute", "FAULT", {}, (), (), np.float64, True ),
# Test index/value.
( "dataset", "newAttribute", "FAULT", {
0: [ 0 ],
100: [ 1 ]
}, (), (), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {
0: [ 0 ],
100: [ 1 ],
101: [ 2 ]
}, (), (), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {
0: [ 0 ],
100: [ 1 ],
101: [ 2 ],
2: [ 3 ]
}, (), (), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {
0: [ 0, 0 ],
100: [ 1, 1 ]
}, (), ( "Component0", "Component1" ), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {
0: [ 0, 0 ],
100: [ 1, 1 ],
101: [ 2, 2 ]
}, (), ( "Component0", "Component1" ), np.float32, True ),
( "dataset", "newAttribute", "FAULT", {
0: [ 0, 0 ],
100: [ 1, 1 ],
101: [ 2, 2 ],
2: [ 3, 3 ]
}, (), ( "Component0", "Component1" ), np.float32, True ),
# Test common error.
## Number of components.
( "dataset", "newAttribute", "FAULT", {
0: [ 0 ],
100: [ 1, 1 ]
}, (), (), np.float32, False ), # Number of value inconsistent.
( "dataset", "newAttribute", "FAULT", {
0: [ 0, 0 ],
100: [ 1, 1 ]
}, (), (), np.float32, False ), # More values than components.
( "dataset", "newAttribute", "FAULT", {
0: [ 0 ],
100: [ 1 ]
}, ( "X", "Y" ), ( "X", "Y" ), np.float32, False ), # More components than value.
## Attribute name.
( "dataset", "PERM", "FAULT", {}, (), (), np.float32, False ), # The attribute name already exist.
## Region attribute.
( "dataset", "newAttribute", "PERM", {}, (),
(), np.float32, False ), # Region attribute has too many components.
( "multiblock", "newAttribute", "FAULT", {}, (), (), np.float32, False ), # Region attribute is partial.
] )
def test_CreateConstantAttributePerRegion(
dataSetTest: Union[ vtkMultiBlockDataSet, vtkDataSet ],
meshType: str,
newAttributeName: str,
regionName: str,
dictRegionValues: dict[ Any, Any ],
componentNames: tuple[ str, ...],
componentNamesTest: tuple[ str, ...],
valueNpType: int,
succeed: bool,
) -> None:
"""Test CreateConstantAttributePerRegion."""
mesh: Union[ vtkMultiBlockDataSet, vtkDataSet ] = dataSetTest( meshType )
nbComponents: int = len( componentNamesTest )
if nbComponents == 0: # If the attribute has one component, the component has no name.
nbComponents += 1

filter: CreateConstantAttributePerRegion = CreateConstantAttributePerRegion(
mesh,
regionName,
dictRegionValues,
newAttributeName,
valueNpType=valueNpType,
nbComponents=nbComponents,
componentNames=componentNames,
)

assert filter.applyFilter() == succeed
Loading