diff --git a/geos-mesh/src/geos/mesh/processing/FillPartialArrays.py b/geos-mesh/src/geos/mesh/processing/FillPartialArrays.py
new file mode 100644
index 0000000..0b1f2e7
--- /dev/null
+++ b/geos-mesh/src/geos/mesh/processing/FillPartialArrays.py
@@ -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
diff --git a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py
index 6d9a738..5e5ef50 100644
--- a/geos-mesh/src/geos/mesh/utils/arrayModifiers.py
+++ b/geos-mesh/src/geos/mesh/utils/arrayModifiers.py
@@ -39,56 +39,54 @@
"""
-def fillPartialAttributes(
- multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
- attributeName: str,
- nbComponents: int,
- onPoints: bool = False,
-) -> bool:
- """Fill input partial attribute of multiBlockMesh with nan values.
+def fillPartialAttributes( multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
+ attributeName: str,
+ nbComponents: int,
+ onPoints: bool = False,
+ value: float = np.nan ) -> bool:
+ """Fill input partial attribute of multiBlockMesh with values (defaults to nan).
Args:
multiBlockMesh (vtkMultiBlockDataSet | vtkCompositeDataSet | vtkDataObject): multiBlock
- mesh where to fill the attribute
- attributeName (str): attribute name
- nbComponents (int): number of components
- onPoints (bool, optional): Attribute is on Points (False) or
- on Cells.
-
+ mesh where to fill the attribute.
+ attributeName (str): Attribute name.
+ nbComponents (int): Number of components.
+ onPoints (bool, optional): Attribute is on Points (True) or on Cells (False).
Defaults to False.
+ value (float, optional): The filling value.
+ Defaults to nan.
Returns:
- bool: True if calculation successfully ended, False otherwise
+ bool: True if calculation successfully ended, False otherwise.
"""
componentNames: tuple[ str, ...] = ()
if nbComponents > 1:
componentNames = getComponentNames( multiBlockMesh, attributeName, onPoints )
- values: list[ float ] = [ np.nan for _ in range( nbComponents ) ]
+ values: list[ float ] = [ value for _ in range( nbComponents ) ]
createConstantAttribute( multiBlockMesh, values, attributeName, componentNames, onPoints )
multiBlockMesh.Modified()
return True
-def fillAllPartialAttributes(
- multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
- onPoints: bool = False,
-) -> bool:
- """Fill all the partial attributes of multiBlockMesh with nan values.
+def fillAllPartialAttributes( multiBlockMesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ],
+ onPoints: bool = False,
+ value: float = np.nan ) -> bool:
+ """Fill all the partial attributes of multiBlockMesh with values (defaults to nan).
Args:
multiBlockMesh (vtkMultiBlockDataSet | vtkCompositeDataSet | vtkDataObject):
multiBlockMesh where to fill the attribute
- onPoints (bool, optional): Attribute is on Points (False) or
- on Cells.
-
+ onPoints (bool, optional): Attribute is on Points (True) or on Cells (False).
Defaults to False.
+ value (float, optional): The filling value.
+ Defaults to nan.
Returns:
bool: True if calculation successfully ended, False otherwise
"""
attributes: dict[ str, int ] = getAttributesWithNumberOfComponents( multiBlockMesh, onPoints )
for attributeName, nbComponents in attributes.items():
- fillPartialAttributes( multiBlockMesh, attributeName, nbComponents, onPoints )
+ fillPartialAttributes( multiBlockMesh, attributeName, nbComponents, onPoints, value )
multiBlockMesh.Modified()
return True
diff --git a/geos-mesh/tests/conftest.py b/geos-mesh/tests/conftest.py
index 56a1de0..dd2bdc6 100644
--- a/geos-mesh/tests/conftest.py
+++ b/geos-mesh/tests/conftest.py
@@ -51,4 +51,4 @@ def _get_dataset( datasetType: str ):
return reader.GetOutput()
- return _get_dataset
\ No newline at end of file
+ return _get_dataset
diff --git a/geos-mesh/tests/test_FillPartialArrays.py b/geos-mesh/tests/test_FillPartialArrays.py
new file mode 100644
index 0000000..31af570
--- /dev/null
+++ b/geos-mesh/tests/test_FillPartialArrays.py
@@ -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()
diff --git a/geos-mesh/tests/test_arrayModifiers.py b/geos-mesh/tests/test_arrayModifiers.py
index 5f90bb1..e82cb26 100644
--- a/geos-mesh/tests/test_arrayModifiers.py
+++ b/geos-mesh/tests/test_arrayModifiers.py
@@ -22,61 +22,109 @@
from geos.mesh.utils import arrayModifiers
-@pytest.mark.parametrize( "attributeName, onpoints", [ ( "CellAttribute", False ), ( "PointAttribute", True ) ] )
+@pytest.mark.parametrize( "attributeName, nbComponents, onpoints, value_test", [
+ ( "CellAttribute", 3, False, np.nan ),
+ ( "PointAttribute", 3, True, np.nan ),
+ ( "CELL_MARKERS", 1, False, np.nan ),
+ ( "PORO", 1, False, np.nan ),
+ ( "CellAttribute", 3, False, 2. ),
+ ( "PointAttribute", 3, True, 2. ),
+ ( "CELL_MARKERS", 1, False, 2. ),
+ ( "PORO", 1, False, 2. ),
+] )
def test_fillPartialAttributes(
dataSetTest: vtkMultiBlockDataSet,
attributeName: str,
+ nbComponents: int,
onpoints: bool,
+ value_test: float,
) -> None:
- """Test filling a partial attribute from a multiblock with nan values."""
+ """Test filling a partial attribute from a multiblock with values."""
+ vtkMultiBlockDataSetTestRef: vtkMultiBlockDataSet = dataSetTest( "multiblock" )
vtkMultiBlockDataSetTest: vtkMultiBlockDataSet = dataSetTest( "multiblock" )
- arrayModifiers.fillPartialAttributes( vtkMultiBlockDataSetTest, attributeName, nbComponents=3, onPoints=onpoints )
-
- iter: vtkDataObjectTreeIterator = vtkDataObjectTreeIterator()
- iter.SetDataSet( vtkMultiBlockDataSetTest )
- iter.VisitOnlyLeavesOn()
- iter.GoToFirstItem()
- while iter.GetCurrentDataObject() is not None:
- dataset: vtkDataSet = vtkDataSet.SafeDownCast( iter.GetCurrentDataObject() )
- data: Union[ vtkPointData, vtkCellData ]
+ arrayModifiers.fillPartialAttributes( vtkMultiBlockDataSetTest,
+ attributeName,
+ nbComponents,
+ onPoints=onpoints,
+ value=value_test )
+
+ nbBlock: int = vtkMultiBlockDataSetTestRef.GetNumberOfBlocks()
+ for block_id in range( nbBlock ):
+ datasetRef: vtkDataSet = cast( vtkDataSet, vtkMultiBlockDataSetTestRef.GetBlock( block_id ) )
+ dataset: vtkDataSet = cast( vtkDataSet, vtkMultiBlockDataSetTest.GetBlock( block_id ) )
+ expected_array: npt.NDArray[ np.float64 ]
+ array: npt.NDArray[ np.float64 ]
if onpoints:
- data = dataset.GetPointData()
+ array = vnp.vtk_to_numpy( dataset.GetPointData().GetArray( attributeName ) )
+ if block_id == 0:
+ expected_array = vnp.vtk_to_numpy( datasetRef.GetPointData().GetArray( attributeName ) )
+ else:
+ expected_array = np.array( [ [ value_test for i in range( nbComponents ) ] for _ in range( 212 ) ] )
else:
- data = dataset.GetCellData()
- assert data.HasArray( attributeName ) == 1
-
- iter.GoToNextItem()
-
-
-@pytest.mark.parametrize( "onpoints, expectedArrays", [
- ( True, ( "PointAttribute", "collocated_nodes" ) ),
- ( False, ( "CELL_MARKERS", "CellAttribute", "FAULT", "PERM", "PORO" ) ),
+ array = vnp.vtk_to_numpy( dataset.GetCellData().GetArray( attributeName ) )
+ if block_id == 0:
+ expected_array = vnp.vtk_to_numpy( datasetRef.GetCellData().GetArray( attributeName ) )
+ else:
+ expected_array = np.array( [ [ value_test for i in range( nbComponents ) ] for _ in range( 156 ) ] )
+
+ if block_id == 0:
+ assert ( array == expected_array ).all()
+ else:
+ if np.isnan( value_test ):
+ assert np.all( np.isnan( array ) == np.isnan( expected_array ) )
+ else:
+ assert ( array == expected_array ).all()
+
+
+@pytest.mark.parametrize( "onpoints, attributesList, value_test", [
+ ( 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. ),
+ ( 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_fillAllPartialAttributes(
dataSetTest: vtkMultiBlockDataSet,
onpoints: bool,
- expectedArrays: tuple[ str, ...],
+ attributesList: Tuple[ Tuple[ int, str, int ], ...],
+ value_test: float,
) -> None:
- """Test filling all partial attributes from a multiblock with nan values."""
+ """Test filling all partial attributes from a multiblock with values."""
+ vtkMultiBlockDataSetTestRef: vtkMultiBlockDataSet = dataSetTest( "multiblock" )
vtkMultiBlockDataSetTest: vtkMultiBlockDataSet = dataSetTest( "multiblock" )
- arrayModifiers.fillAllPartialAttributes( vtkMultiBlockDataSetTest, onpoints )
-
- iter: vtkDataObjectTreeIterator = vtkDataObjectTreeIterator()
- iter.SetDataSet( vtkMultiBlockDataSetTest )
- iter.VisitOnlyLeavesOn()
- iter.GoToFirstItem()
- while iter.GetCurrentDataObject() is not None:
- dataset: vtkDataSet = vtkDataSet.SafeDownCast( iter.GetCurrentDataObject() )
+ arrayModifiers.fillAllPartialAttributes( vtkMultiBlockDataSetTest, onpoints, value_test )
+
+ nbBlock: int = vtkMultiBlockDataSetTestRef.GetNumberOfBlocks()
+ for block_id in range( nbBlock ):
+ datasetRef: vtkDataSet = cast( vtkDataSet, vtkMultiBlockDataSetTestRef.GetBlock( block_id ) )
+ dataset: vtkDataSet = cast( vtkDataSet, vtkMultiBlockDataSetTest.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()
-
- for attribute in expectedArrays:
- assert data.HasArray( attribute ) == 1
-
- iter.GoToNextItem()
+ 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()
@pytest.mark.parametrize( "attributeName, dataType, expectedDatatypeArray", [
diff --git a/geos-pv/src/PVplugins/PVFillPartialArrays.py b/geos-pv/src/PVplugins/PVFillPartialArrays.py
new file mode 100644
index 0000000..a3b0017
--- /dev/null
+++ b/geos-pv/src/PVplugins/PVFillPartialArrays.py
@@ -0,0 +1,193 @@
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
+# SPDX-FileContributor: Martin Lemay, Romain Baville
+# ruff: noqa: E402 # disable Module level import not at top of file
+import sys
+from pathlib import Path
+from typing_extensions import Self
+
+import numpy as np
+
+from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
+ VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
+)
+
+from vtkmodules.vtkCommonDataModel import (
+ vtkMultiBlockDataSet, )
+
+from vtkmodules.vtkCommonCore import (
+ vtkInformation,
+ vtkInformationVector,
+)
+
+# update sys.path to load all GEOS Python Package dependencies
+geos_pv_path: Path = Path( __file__ ).parent.parent.parent
+sys.path.insert( 0, str( geos_pv_path / "src" ) )
+from geos.pv.utils.config import update_paths
+
+update_paths()
+
+from geos.mesh.processing.FillPartialArrays import FillPartialArrays
+
+__doc__ = """
+Fill partial arrays of input mesh.
+
+Input and output are vtkMultiBlockDataSet.
+
+To use it:
+
+* Load the module in Paraview: Tools>Manage Plugins...>Load new>PVFillPartialArrays.
+* Select the input mesh.
+* Select the partial arrays to fill.
+* Set the filling value (defaults to nan).
+* Apply.
+
+"""
+
+
+@smproxy.filter( name="PVFillPartialArrays", label="Fill Partial Arrays" )
+@smhint.xml( '' )
+@smproperty.input( name="Input", port_index=0 )
+@smdomain.datatype(
+ dataTypes=[ "vtkMultiBlockDataSet" ],
+ composite_data_supported=True,
+)
+class PVFillPartialArrays( 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._clearSelectedAttributeMulti: bool = True
+ self._attributesNameList: list[ str ] = []
+
+ # Initialisation of the value (nan) to fill in the partial attributes
+ self._valueToFill: float = np.nan
+
+ @smproperty.stringvector(
+ name="SelectMultipleAttribute",
+ label="Select Attributes to fill",
+ repeat_command=1,
+ number_of_elements_per_command="1",
+ element_types="2",
+ default_values="N/A",
+ panel_visibility="default",
+ )
+ @smdomain.xml( """
+
+
+
+
+
+
+ Select all the attributes to fill. If several attributes
+ are selected, they will be filled with the same value.
+
+
+
+
+ """ )
+ def a02SelectMultipleAttribute( self: Self, name: str ) -> None:
+ """Set the list of the names of the selected attributes to fill.
+
+ Args:
+ name (str): Input value
+ """
+ if self._clearSelectedAttributeMulti:
+ self._attributesNameList.clear()
+ self._clearSelectedAttributeMulti = False
+
+ if name != "N/A":
+ self._attributesNameList.append( name )
+ self.Modified()
+
+ @smproperty.stringvector(
+ name="StringSingle",
+ label="Value to fill",
+ number_of_elements="1",
+ default_values="nan",
+ panel_visibility="default",
+ )
+ @smdomain.xml( """
+
+ Enter the value to fill in the partial attributes. The
+ default value is nan
+
+ """ )
+ def a01StringSingle( self: Self, value: str ) -> None:
+ """Set the value to fill in the attributes.
+
+ Args:
+ value (str): Input
+ """
+ assert value is not None, "Enter a number or nan"
+ assert "," not in value, "Use '.' not ',' for decimal numbers"
+
+ value_float: float
+ value_float = np.nan if value.lower() == "nan" else float( value )
+
+ if value_float != self._valueToFill:
+ self._valueToFill = value_float
+ self.Modified()
+
+ 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.
+ """
+ inputMesh: vtkMultiBlockDataSet = self.GetInputData( inInfoVec, 0, 0 )
+ outputMesh: vtkMultiBlockDataSet = self.GetOutputData( outInfoVec, 0 )
+ assert inputMesh is not None, "Input server mesh is null."
+ assert outputMesh is not None, "Output pipeline is null."
+
+ filter: FillPartialArrays = FillPartialArrays()
+ filter._SetAttributesNameList( self._attributesNameList )
+ filter._SetValueToFill( self._valueToFill )
+ filter.SetInputDataObject( inputMesh )
+ filter.Update()
+ outputMesh.ShallowCopy( filter.GetOutputDataObject( 0 ) )
+
+ self._clearSelectedAttributeMulti = True
+ return 1