-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add FillPartialArrays vtk filter and paraview plugin #105
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
Open
RomainBaville
wants to merge
15
commits into
main
Choose a base branch
from
RomainBaville/feature/VTK_filter_and_PVFillPartialArray
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
a8a6b9b
add the VTK filter to fill a partial arrays of an input mesh
RomainBaville e948b20
add the pv plugin to fill a partial arrays of an input mesh
RomainBaville 35c3b74
fixing bugs by removing the use of the abstract class
RomainBaville 5633fce
Add the possibility to choose the atribute to fill without using para…
RomainBaville 919351b
add the possibility to choose the value to fill in the function fillp…
RomainBaville 10bfc75
add the possibility to choose a value to fill the partial array
RomainBaville 839821a
add the possibility to choose the value to fill in the partial attrib…
RomainBaville 870fb25
Update the documentation and upgrade the name of the variables
RomainBaville 798003c
Small modifications of the doc
RomainBaville 1494d5b
Update of the tests
RomainBaville f69e853
Formatting for the ci
RomainBaville 4d9468e
Add the test file for the FillPartialArrays vtk filter
RomainBaville d44bc56
Formatting for the ci
RomainBaville 5e0da35
Fix the lin with yapft issue
RomainBaville a0a2092
Apply suggestions from code review
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
There are no files selected for viewing
166 changes: 166 additions & 0 deletions
166
geos-mesh/src/geos/mesh/processing/FillPartialArrays.py
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,166 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. | ||
# SPDX-FileContributor: Romain Baville, Martin Lemay | ||
|
||
from typing_extensions import Self | ||
from typing import Union, Tuple | ||
from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase | ||
|
||
from geos.utils.Logger import Logger, getLogger | ||
from geos.mesh.utils.arrayModifiers import fillPartialAttributes | ||
from geos.mesh.utils.arrayHelpers import ( | ||
getNumberOfComponents, | ||
isAttributeInObject, | ||
) | ||
|
||
from vtkmodules.vtkCommonCore import ( | ||
vtkInformation, | ||
vtkInformationVector, | ||
) | ||
|
||
from vtkmodules.vtkCommonDataModel import ( | ||
vtkMultiBlockDataSet, ) | ||
|
||
import numpy as np | ||
|
||
__doc__ = """ | ||
Fill partial arrays of input mesh with values (defaults to nan). | ||
Several arrays can be filled in one application if the value is the same. | ||
|
||
Input and output meshes are vtkMultiBlockDataSet. | ||
|
||
To use it: | ||
|
||
.. code-block:: python | ||
|
||
from geos.mesh.processing.FillPartialArrays import FillPartialArrays | ||
|
||
# filter inputs | ||
input_mesh: vtkMultiBlockDataSet | ||
input_attributesNameList: list[str] | ||
input_valueToFill: float, optional defaults to nan | ||
|
||
# Instanciate the filter | ||
filter: FillPartialArrays = FillPartialArrays() | ||
# Set the list of the partial atributes to fill | ||
filter._SetAttributesNameList( input_attributesNameList ) | ||
# Set the value to fill in the partial attributes if not nan | ||
filter._SetValueToFill( input_valueToFill ) | ||
# Set the mesh | ||
filter.SetInputDataObject( input_mesh ) | ||
# Do calculations | ||
filter.Update() | ||
|
||
# get output object | ||
output: vtkMultiBlockDataSet = filter.GetOutputDataObject( 0 ) ) | ||
""" | ||
|
||
|
||
class FillPartialArrays( VTKPythonAlgorithmBase ): | ||
|
||
def __init__( self: Self ) -> None: | ||
"""Map the properties of a server mesh to a client mesh.""" | ||
super().__init__( nInputPorts=1, | ||
nOutputPorts=1, | ||
inputType="vtkMultiBlockDataSet", | ||
outputType="vtkMultiBlockDataSet" ) | ||
|
||
# Initialisation of an empty list of the attribute's name | ||
self._SetAttributesNameList() | ||
|
||
# Initialisation of the value (nan) to fill in the partial attributes | ||
self._SetValueToFill() | ||
|
||
# Logger | ||
self.m_logger: Logger = getLogger( "Fill Partial Attributes" ) | ||
|
||
def RequestDataObject( | ||
self: Self, | ||
request: vtkInformation, | ||
inInfoVec: list[ vtkInformationVector ], | ||
outInfoVec: vtkInformationVector, | ||
) -> int: | ||
"""Inherited from VTKPythonAlgorithmBase::RequestDataObject. | ||
|
||
Args: | ||
request (vtkInformation): Request | ||
inInfoVec (list[vtkInformationVector]): Input objects | ||
outInfoVec (vtkInformationVector): Output objects | ||
|
||
Returns: | ||
int: 1 if calculation successfully ended, 0 otherwise. | ||
""" | ||
inData = self.GetInputData( inInfoVec, 0, 0 ) | ||
outData = self.GetOutputData( outInfoVec, 0 ) | ||
assert inData is not None | ||
if outData is None or ( not outData.IsA( inData.GetClassName() ) ): | ||
outData = inData.NewInstance() | ||
outInfoVec.GetInformationObject( 0 ).Set( outData.DATA_OBJECT(), outData ) | ||
return super().RequestDataObject( request, inInfoVec, outInfoVec ) # type: ignore[no-any-return] | ||
|
||
def RequestData( | ||
self: Self, | ||
request: vtkInformation, # noqa: F841 | ||
inInfoVec: list[ vtkInformationVector ], | ||
outInfoVec: vtkInformationVector, | ||
) -> int: | ||
"""Inherited from VTKPythonAlgorithmBase::RequestData. | ||
|
||
Args: | ||
request (vtkInformation): Request | ||
inInfoVec (list[vtkInformationVector]): Input objects | ||
outInfoVec (vtkInformationVector): Output objects | ||
|
||
Returns: | ||
int: 1 if calculation successfully ended, 0 otherwise. | ||
""" | ||
self.m_logger.info( f"Apply filter {__name__}" ) | ||
try: | ||
inputMesh: vtkMultiBlockDataSet = self.GetInputData( inInfoVec, 0, 0 ) | ||
outData: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 ) | ||
|
||
assert inputMesh is not None, "Input mesh is null." | ||
assert outData is not None, "Output pipeline is null." | ||
|
||
outData.ShallowCopy( inputMesh ) | ||
for attributeName in self._attributesNameList: | ||
# cell and point arrays | ||
for onPoints in ( False, True ): | ||
if isAttributeInObject( outData, attributeName, onPoints ): | ||
nbComponents = getNumberOfComponents( outData, attributeName, onPoints ) | ||
fillPartialAttributes( outData, attributeName, nbComponents, onPoints, self._valueToFill ) | ||
outData.Modified() | ||
|
||
mess: str = "Fill Partial arrays were successfully completed. " + str( | ||
self._attributesNameList ) + " filled with value " + str( self._valueToFill ) | ||
self.m_logger.info( mess ) | ||
except AssertionError as e: | ||
mess1: str = "Partial arrays filling failed due to:" | ||
self.m_logger.error( mess1 ) | ||
self.m_logger.error( e, exc_info=True ) | ||
return 0 | ||
except Exception as e: | ||
mess0: str = "Partial arrays filling failed due to:" | ||
self.m_logger.critical( mess0 ) | ||
self.m_logger.critical( e, exc_info=True ) | ||
return 0 | ||
|
||
return 1 | ||
|
||
def _SetAttributesNameList( self: Self, attributesNameList: Union[ list[ str ], Tuple ] = () ) -> None: | ||
"""Set the list of the partial attributes to fill. | ||
|
||
Args: | ||
attributesNameList (Union[list[str], Tuple], optional): List of all the attributes name. | ||
Defaults to a empty list | ||
""" | ||
self._attributesNameList: Union[ list[ str ], Tuple ] = attributesNameList | ||
|
||
def _SetValueToFill( self: Self, valueToFill: float = np.nan ) -> None: | ||
"""Set the value to fill in the partial attribute. | ||
|
||
Args: | ||
valueToFill (float, optional): The filling value. | ||
Defaults to nan. | ||
""" | ||
self._valueToFill: float = valueToFill |
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 |
---|---|---|
|
@@ -51,4 +51,4 @@ def _get_dataset( datasetType: str ): | |
|
||
return reader.GetOutput() | ||
|
||
return _get_dataset | ||
return _get_dataset |
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,75 @@ | ||
# 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, Tuple, cast | ||
|
||
import numpy as np | ||
import numpy.typing as npt | ||
|
||
import vtkmodules.util.numpy_support as vnp | ||
from vtkmodules.vtkCommonDataModel import ( vtkDataSet, vtkMultiBlockDataSet, vtkPointData, vtkCellData ) | ||
|
||
from geos.mesh.processing.FillPartialArrays import FillPartialArrays | ||
|
||
|
||
@pytest.mark.parametrize( "onpoints, attributesList, value_test", [ | ||
( False, ( ( 0, "PORO", 1 ), ), np.nan ), | ||
( True, ( ( 0, "PointAttribute", 3 ), ( 1, "collocated_nodes", 2 ) ), 2. ), | ||
( False, ( ( 0, "CELL_MARKERS", 1 ), ( 0, "CellAttribute", 3 ), ( 0, "FAULT", 1 ), ( 0, "PERM", 3 ), | ||
( 0, "PORO", 1 ) ), 2. ), | ||
( False, ( ( 0, "PORO", 1 ), ), 2.0 ), | ||
( True, ( ( 0, "PointAttribute", 3 ), ( 1, "collocated_nodes", 2 ) ), np.nan ), | ||
( False, ( ( 0, "CELL_MARKERS", 1 ), ( 0, "CellAttribute", 3 ), ( 0, "FAULT", 1 ), ( 0, "PERM", 3 ), | ||
( 0, "PORO", 1 ) ), np.nan ), | ||
] ) | ||
def test_FillPartialArrays( | ||
dataSetTest: vtkMultiBlockDataSet, | ||
onpoints: bool, | ||
attributesList: Tuple[ Tuple[ int, str, int ], ...], | ||
value_test: float, | ||
) -> None: | ||
"""Test FillPartialArrays vtk filter.""" | ||
vtkMultiBlockDataSetTestRef: vtkMultiBlockDataSet = dataSetTest( "multiblock" ) | ||
vtkMultiBlockDataSetTest: vtkMultiBlockDataSet = dataSetTest( "multiblock" ) | ||
attributesNameList: list[ str ] = [ attributesList[ i ][ 1 ] for i in range( len( attributesList ) ) ] | ||
|
||
filter: FillPartialArrays = FillPartialArrays() | ||
filter._SetAttributesNameList( attributesNameList ) | ||
filter._SetValueToFill( value_test ) | ||
filter.SetInputDataObject( vtkMultiBlockDataSetTest ) | ||
filter.Update() | ||
|
||
nbBlock: int = vtkMultiBlockDataSetTestRef.GetNumberOfBlocks() | ||
for block_id in range( nbBlock ): | ||
datasetRef: vtkDataSet = cast( vtkDataSet, vtkMultiBlockDataSetTestRef.GetBlock( block_id ) ) | ||
dataset: vtkDataSet = cast( vtkDataSet, filter.GetOutputDataObject( 0 ).GetBlock( block_id ) ) | ||
expected_array: npt.NDArray[ np.float64 ] | ||
array: npt.NDArray[ np.float64 ] | ||
dataRef: Union[ vtkPointData, vtkCellData ] | ||
data: Union[ vtkPointData, vtkCellData ] | ||
nbElements: list[ int ] | ||
if onpoints: | ||
dataRef = datasetRef.GetPointData() | ||
data = dataset.GetPointData() | ||
nbElements = [ 212, 4092 ] | ||
else: | ||
dataRef = datasetRef.GetCellData() | ||
data = dataset.GetCellData() | ||
nbElements = [ 156, 1740 ] | ||
|
||
for inBlock, attribute, nbComponents in attributesList: | ||
array = vnp.vtk_to_numpy( data.GetArray( attribute ) ) | ||
if block_id == inBlock: | ||
expected_array = vnp.vtk_to_numpy( dataRef.GetArray( attribute ) ) | ||
assert ( array == expected_array ).all() | ||
else: | ||
expected_array = np.array( [ [ value_test for i in range( nbComponents ) ] | ||
for _ in range( nbElements[ inBlock ] ) ] ) | ||
if np.isnan( value_test ): | ||
assert np.all( np.isnan( array ) == np.isnan( expected_array ) ) | ||
else: | ||
assert ( array == expected_array ).all() |
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not defining multiple parameters instead of one tuple containing them all 3 ?