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