-
Notifications
You must be signed in to change notification settings - Fork 0
refactor: Move PVAttributeMappingto geos-pv and create corresponding VTK filter in geos-mesh
#128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
paloma-martinez
merged 50 commits into
main
from
RomainBaville/feature/VTK_filter_and_paraview_plugin_AttributeMapping
Sep 26, 2025
Merged
Changes from all commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
e4aa661
First commit, move the plugin and the filter
RomainBaville 702a3a4
fix issue with multiblock input
RomainBaville 79a1db4
Update logger and refactor - plugin with the VTKPythonAlgorithmBase -…
RomainBaville da614d1
Merge branch 'main' into RomainBaville/feature/VTK_filter_and_paravie…
RomainBaville 9b86c83
fix apply feature on paraview
RomainBaville 8a92269
Update the doc and add input checks
RomainBaville 2d778d8
update doc
RomainBaville 40fae76
Update the name of the filter
RomainBaville 8ba8e89
fix the function computeCellMapping, bounds are used instead of center
RomainBaville 7f6a8a2
adapte the plugin to deals with global attributes only
RomainBaville 975e86c
Add the function to get the vtk type of an attribute on a mesh
RomainBaville 1d38c90
Change the method, meshes are parsed instead of merged
RomainBaville 25b1fc3
add functions to compute the cellMapping from the coordinate between …
RomainBaville bebfdcd
clean for ci
RomainBaville 5bcc52d
move function to compute the cellMap in arrayHelpers
RomainBaville 4980797
clean for ci
RomainBaville 4d6b521
clean for ci
RomainBaville ad3ba4d
update doc files
RomainBaville 3521290
clean tests for computeElementMapping
RomainBaville d414a2d
Add the possibility to chose to map cell or point and use flat index …
RomainBaville 2bb18c1
add teh function to transfer an attribute from a mesh to another with…
RomainBaville 2f30167
update to choose the piece of the attribute to transefer
RomainBaville 8438fc7
test of the vtk filter AttributeMapping
RomainBaville b90e8f7
fix nullblocks issues
RomainBaville 147351e
add the test for the function transferAttribute
RomainBaville c93e188
fix for test
RomainBaville 424938e
Fix double apply
RomainBaville da83524
Clean for ci
RomainBaville 9d04059
Remove AttributeMappingFromCellId and clean the doc
RomainBaville 04e692a
Update to the last verion of the main.
RomainBaville de2e64e
fix block id
RomainBaville 8a2ef89
Apply suggestions from Paloma's review
RomainBaville e01211e
Clean the doc
RomainBaville 6a62c73
Add info to the logger
RomainBaville 36291c6
Clean the doc
RomainBaville 4865557
clean the doc
RomainBaville 484dcdd
clean the doc
RomainBaville b2cbc5e
Clean the doc and the plugin
RomainBaville fb325b7
Apply comments from Jacques review.
RomainBaville ea7e15e
Update to the last version of the main
RomainBaville f49880a
Clean for ci
RomainBaville e2822ec
Fix the tests
RomainBaville 8866dba
Fix the tests
RomainBaville c9320aa
Move files to new directory
RomainBaville bca66e7
Add a vtp file
RomainBaville 9849529
map volume to surface mesh
RomainBaville 79b5a07
Update AttributeMapping to transfer attribute between Surface and vol…
RomainBaville cc730e4
Fix ci
RomainBaville e0a46c9
Apply Paloma and Jacques suggestions
RomainBaville a19dce1
Merge branch 'main' into RomainBaville/feature/VTK_filter_and_paravie…
RomainBaville File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. | ||
| # SPDX-FileContributor: Raphaël Vinour, Martin Lemay, Romain Baville | ||
| # ruff: noqa: E402 # disable Module level import not at top of file | ||
| import numpy as np | ||
| import numpy.typing as npt | ||
| import logging | ||
|
|
||
| from geos.utils.Logger import ( Logger, getLogger ) | ||
| from typing_extensions import Self, Union, Set, List, Dict | ||
|
|
||
| from vtkmodules.vtkCommonDataModel import ( | ||
| vtkDataSet, | ||
| vtkMultiBlockDataSet, | ||
| ) | ||
|
|
||
| from geos.mesh.utils.arrayModifiers import transferAttributeWithElementMap | ||
| from geos.mesh.utils.arrayHelpers import ( computeElementMapping, getAttributeSet, isAttributeGlobal ) | ||
|
|
||
| __doc__ = """ | ||
| AttributeMapping is a vtk filter that transfers global attributes from a source mesh to a final mesh with same point/cell coordinates. The final mesh is updated directly, without creation of a copy. | ||
|
|
||
| Input meshes can be vtkDataSet or vtkMultiBlockDataSet. | ||
|
|
||
| .. Warning:: | ||
| For one application of the filter, the attributes to transfer should all be located on the same piece (all on points or all on cells). | ||
|
|
||
| .. Note:: | ||
| For cell, the coordinates of the points in the cell are compared. | ||
| If one of the two meshes is a surface and the other a volume, all the points of the surface must be points of the volume. | ||
|
|
||
| To use a logger handler of yours, set the variable 'speHandler' to True and add it using the member function setLoggerHandler. | ||
|
|
||
| To use the filter: | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| from geos.mesh.processing.AttributeMapping import AttributeMapping | ||
|
|
||
| # Filter inputs. | ||
| meshFrom: Union[ vtkDataSet, vtkMultiBlockDataSet ] | ||
| meshTo: Union[ vtkDataSet, vtkMultiBlockDataSet ] | ||
| attributeNames: Set[ str ] | ||
| # Optional inputs. | ||
| onPoints: bool # defaults to False | ||
| speHandler: bool # defaults to False | ||
|
|
||
| # Instantiate the filter | ||
| filter: AttributeMapping = AttributeMapping( meshFrom, | ||
| meshTo, | ||
| attributeNames, | ||
| onPoints, | ||
| speHandler, | ||
| ) | ||
|
|
||
| # Set the handler of yours (only if speHandler is True). | ||
| yourHandler: logging.Handler | ||
| filter.setLoggerHandler( yourHandler ) | ||
|
|
||
| # Do calculations. | ||
| filter.applyFilter() | ||
| """ | ||
|
|
||
| loggerTitle: str = "Attribute Mapping" | ||
|
|
||
|
|
||
| class AttributeMapping: | ||
|
|
||
| def __init__( | ||
| self: Self, | ||
| meshFrom: Union[ vtkDataSet, vtkMultiBlockDataSet ], | ||
| meshTo: Union[ vtkDataSet, vtkMultiBlockDataSet ], | ||
| attributeNames: Set[ str ], | ||
| onPoints: bool = False, | ||
| speHandler: bool = False, | ||
| ) -> None: | ||
| """Transfer global attributes from a source mesh to a final mesh, mapping the piece of the attributes to transfer. | ||
|
|
||
| Args: | ||
| meshFrom (Union[ vtkDataSet, vtkMultiBlockDataSet ]): The source mesh with attributes to transfer. | ||
| meshTo (Union[ vtkDataSet, vtkMultiBlockDataSet ]): The final mesh where to transfer attributes. | ||
| attributeNames (Set[str]): Names of the attributes to transfer. | ||
| onPoints (bool): True if attributes are on points, False if they are on cells. | ||
| Defaults to False. | ||
| speHandler (bool, optional): True to use a specific handler, False to use the internal handler. | ||
| Defaults to False. | ||
| """ | ||
| self.meshFrom: Union[ vtkDataSet, vtkMultiBlockDataSet ] = meshFrom | ||
| self.meshTo: Union[ vtkDataSet, vtkMultiBlockDataSet ] = meshTo | ||
| self.attributeNames: Set[ str ] = attributeNames | ||
| self.onPoints: bool = onPoints | ||
| #TODO/refact (@RomainBaville) make it an enum | ||
| self.piece: str = "points" if self.onPoints else "cells" | ||
|
|
||
| # cell map | ||
| self.ElementMap: Dict[ int, npt.NDArray[ np.int64 ] ] = {} | ||
|
|
||
| # Logger. | ||
| self.logger: Logger | ||
| if not speHandler: | ||
| self.logger = getLogger( loggerTitle, True ) | ||
| else: | ||
| self.logger = logging.getLogger( loggerTitle ) | ||
| self.logger.setLevel( logging.INFO ) | ||
|
|
||
| def setLoggerHandler( self: Self, handler: logging.Handler ) -> None: | ||
| """Set a specific handler for the filter logger. | ||
|
|
||
| In this filter 4 log levels are use, .info, .error, .warning and .critical, be sure to have at least the same 4 levels. | ||
|
|
||
| Args: | ||
| handler (logging.Handler): The handler to add. | ||
| """ | ||
| if not self.logger.hasHandlers(): | ||
| 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 getElementMap( self: Self ) -> Dict[ int, npt.NDArray[ np.int64 ] ]: | ||
| """Getter of the element mapping dictionary. | ||
|
|
||
| If attribute to transfer are on points it will be a pointMap, else it will be a cellMap. | ||
|
|
||
| Returns: | ||
| self.elementMap (Dict[int, npt.NDArray[np.int64]]): The element mapping dictionary. | ||
| """ | ||
| return self.ElementMap | ||
|
|
||
| def applyFilter( self: Self ) -> bool: | ||
| """Transfer global attributes from a source mesh to a final mesh, mapping the piece of the attributes to transfer. | ||
|
|
||
| Returns: | ||
| boolean (bool): True if calculation successfully ended, False otherwise. | ||
| """ | ||
| 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." ) | ||
RomainBaville marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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 | ||
|
|
||
| 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." ) | ||
RomainBaville marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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." ) | ||
RomainBaville marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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." | ||
| ) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.