diff --git a/.hooks/pre-commit.example b/.hooks/pre-commit.example
new file mode 100755
index 00000000..f4f188d7
--- /dev/null
+++ b/.hooks/pre-commit.example
@@ -0,0 +1,23 @@
+#!/bin/bash -e
+
+function run_precommit_checks
+{
+ echo "running mypy"
+ python -m mypy --config-file ./.mypy.ini --check-untyped-defs $1
+ echo "running ruff"
+ python -m ruff check --unsafe-fixes --config .ruff.toml $1
+ echo "running yapf"
+ python -m yapf -r -i --style .style.yapf $1
+
+ return 0
+}
+
+
+source ${ENV_PYTHON}/bin/activate
+
+#sphinx-build -b html docs/ docs/_build -W
+for file in $(git diff --name-only --cached | grep -e "modified\|added" | grep py)
+do
+ run_precommit_checks $file
+done
+
diff --git a/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py b/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py
index 8c0cfdb2..cb29430f 100644
--- a/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py
+++ b/geos-pv/src/geos/pv/plugins/PVClipToMainFrame.py
@@ -4,24 +4,16 @@
# ruff: noqa: E402 # disable Module level import not at top of file
import sys
from pathlib import Path
-from typing import Union
from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
+ VTKPythonAlgorithmBase,
) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py
from paraview.detail.loghandler import ( # type: ignore[import-not-found]
VTKHandler,
) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
from vtkmodules.vtkCommonDataModel import (
- vtkMultiBlockDataSet,
- vtkUnstructuredGrid,
-)
-
-from vtkmodules.vtkCommonCore import (
- vtkInformation,
- vtkInformationVector,
-)
+ vtkMultiBlockDataSet, )
# update sys.path to load all GEOS Python Package dependencies
geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent
@@ -30,6 +22,7 @@
update_paths()
+from geos.pv.utils.details import SISOFilter, FilterCategory
from geos.mesh.processing.ClipToMainFrame import ClipToMainFrame
__doc__ = """
@@ -43,67 +36,28 @@
"""
-@smproxy.filter( name="PVClipToMainFrame", label="Clip to the main frame" )
-@smhint.xml( '' )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype(
- dataTypes=[ "vtkMultiBlockDataSet", "vtkUnstructuredGrid" ],
- composite_data_supported=True,
-)
+@SISOFilter( category=FilterCategory.GEOS_UTILS,
+ decoratedLabel="Clip to the main frame",
+ decoratedType=[ "vtkMultiBlockDataSet", "vtkDataSet" ] )
class PVClipToMainFrame( VTKPythonAlgorithmBase ):
def __init__( self ) -> None:
"""Init motherclass, filter and logger."""
- VTKPythonAlgorithmBase.__init__( self,
- nInputPorts=1,
- nOutputPorts=1,
- inputType="vtkDataObject",
- outputType="vtkDataObject" )
-
self._realFilter = ClipToMainFrame( speHandler=True )
if not self._realFilter.logger.hasHandlers():
self._realFilter.SetLoggerHandler( VTKHandler() )
- #ensure I/O consistency
- def RequestDataObject( self, request: vtkInformation, inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
+ def Filter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBlockDataSet ) -> None:
+ """Is applying CreateConstantAttributePerRegion filter.
Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
+ inputMesh : A mesh to transform.
+ outputMesh : A mesh transformed.
"""
- 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, request: vtkInformation, inInfo: list[ vtkInformationVector ],
- outInfo: vtkInformationVector ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestData. Apply ClipToMainFrame filter.
-
- Args:
- request (vtkInformation): Request
- inInfo (list[vtkInformationVector]): Input objects
- outInfo (vtkInformationVector): Output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
- """
- inputMesh: Union[ vtkMultiBlockDataSet, vtkUnstructuredGrid ] = self.GetInputData( inInfo, 0, 0 )
- outputMesh: Union[ vtkMultiBlockDataSet, vtkUnstructuredGrid ] = self.GetOutputData( outInfo, 0 )
-
# struct
self._realFilter.SetInputData( inputMesh )
self._realFilter.ComputeTransform()
self._realFilter.Update()
outputMesh.ShallowCopy( self._realFilter.GetOutputDataObject( 0 ) )
- return 1
+ return
diff --git a/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py b/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py
index fe6a61b4..aabb2e56 100644
--- a/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py
+++ b/geos-pv/src/geos/pv/plugins/PVCreateConstantAttributePerRegion.py
@@ -3,36 +3,31 @@
# SPDX-FileContributor: Martin Lemay, Romain Baville
# ruff: noqa: E402 # disable Module level import not at top of file
import sys
+import numpy as np
from pathlib import Path
-from typing import Union, Any
+from typing import Any
from typing_extensions import Self
from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- smdomain, smhint, smproperty, smproxy,
+ VTKPythonAlgorithmBase, smdomain, smproperty,
) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py
from paraview.detail.loghandler import ( # type: ignore[import-not-found]
VTKHandler,
) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
-from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase
-from vtkmodules.vtkCommonCore import (
- vtkInformation,
- vtkInformationVector,
-)
+import vtkmodules.util.numpy_support as vnp
+
from vtkmodules.vtkCommonDataModel import (
- vtkMultiBlockDataSet,
- vtkDataSet,
-)
+ vtkDataSet, )
# update sys.path to load all GEOS Python Package dependencies
geos_pv_path: Path = Path( __file__ ).parent.parent.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.CreateConstantAttributePerRegion import ( CreateConstantAttributePerRegion )
-from geos.mesh.processing.CreateConstantAttributePerRegion import CreateConstantAttributePerRegion, vnp, np
+from geos.pv.utils.details import SISOFilter, FilterCategory
__doc__ = """
PVCreateConstantAttributePerRegion is a Paraview plugin that allows to create an attribute
@@ -42,7 +37,7 @@
Input mesh is either vtkMultiBlockDataSet or vtkDataSet and the region attribute must have one component.
The relation index/values is given by a dictionary. Its keys are the indexes and its items are the list of values for each component.
-.. Warning::
+.. Warning::
The input mesh should contain an attribute corresponding to the regions.
To use it:
@@ -56,22 +51,13 @@
"""
-@smproxy.filter(
- name="PVCreateConstantAttributePerRegion",
- label="Create Constant Attribute Per Region",
-)
-@smhint.xml( """""" )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype(
- dataTypes=[ "vtkMultiBlockDataSet", "vtkDataSet" ],
- composite_data_supported=True,
-)
+@SISOFilter( category=FilterCategory.GEOS_PROP,
+ decoratedLabel="Create Constant Attribute Per Region",
+ decoratedType=[ "vtkMultiBlockDataSet", "vtkDataSet" ] )
class PVCreateConstantAttributePerRegion( VTKPythonAlgorithmBase ):
def __init__( self: Self ) -> None:
"""Create an attribute with constant value per region."""
- super().__init__( nInputPorts=1, nOutputPorts=1, inputType="vtkDataObject", outputType="vtkDataObject" )
-
self.clearDictRegionValues: bool = True
# Region attribute settings.
@@ -111,7 +97,7 @@ def __init__( self: Self ) -> None:
""" )
- def _setRegionAttributeName( self: Self, regionName: str ) -> None:
+ def setRegionAttributeName( self: Self, regionName: str ) -> None:
"""Set region attribute name.
Args:
@@ -124,7 +110,7 @@ def _setRegionAttributeName( self: Self, regionName: str ) -> None:
@@ -142,7 +128,7 @@ def _setRegionAttributeName( self: Self, regionName: str ) -> None:
""" )
- def _setDictRegionValues( self: Self, regionIndex: str, value: str ) -> None:
+ def setDictRegionValues( self: Self, regionIndex: str, value: str ) -> None:
"""Set the dictionary with the region indexes and its corresponding list of values for each components.
Args:
@@ -166,7 +152,7 @@ def _setDictRegionValues( self: Self, regionIndex: str, value: str ) -> None:
""" )
- def _groupRegionAttributeSettingsWidgets( self: Self ) -> None:
+ def groupRegionAttributeSettingsWidgets( self: Self ) -> None:
"""Group the widgets to set the settings of the region attribute."""
self.Modified()
@@ -183,7 +169,7 @@ def _groupRegionAttributeSettingsWidgets( self: Self ) -> None:
""" )
- def _setAttributeName( self: Self, newAttributeName: str ) -> None:
+ def setAttributeName( self: Self, newAttributeName: str ) -> None:
"""Set attribute name.
Args:
@@ -216,7 +202,7 @@ def _setAttributeName( self: Self, newAttributeName: str ) -> None:
The requested numpy scalar type for values of the new attribute.
""" )
- def _setValueType( self: Self, valueType: int ) -> None:
+ def setValueType( self: Self, valueType: int ) -> None:
"""Set the type for the value used to create the new attribute.
Args:
@@ -238,7 +224,7 @@ def _setValueType( self: Self, valueType: int ) -> None:
The number of components for the new attribute to create.
""" )
- def _setNbComponent( self: Self, nbComponents: int ) -> None:
+ def setNbComponent( self: Self, nbComponents: int ) -> None:
"""Set the number of components of the attribute to create.
Args:
@@ -261,7 +247,7 @@ def _setNbComponent( self: Self, nbComponents: int ) -> None:
Names of components: X, Y, Z
""" )
- def _setComponentNames( self: Self, componentNames: str ) -> None:
+ def setComponentNames( self: Self, componentNames: str ) -> None:
"""Set the names of the components of the attribute to create.
Args:
@@ -283,57 +269,17 @@ def _setComponentNames( self: Self, componentNames: str ) -> None:
""" )
- def _groupNewAttributeSettingsWidgets( self: Self ) -> None:
+ def groupNewAttributeSettingsWidgets( self: Self ) -> None:
"""Group the widgets to set the settings of the new attribute."""
self.Modified()
- def RequestDataObject(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
+ def Filter( self, inputMesh: vtkDataSet, outputMesh: vtkDataSet ) -> None:
+ """Is applying CreateConstantAttributePerRegion filter.
Args:
- request (vtkInformation): request
- inInfoVec (list[vtkInformationVector]): input objects
- outInfoVec (vtkInformationVector): output objects
-
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
+ inputMesh : A mesh to transform
+ outputMesh : A mesh transformed.
"""
- 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 ], # noqa: F841
- outInfoVec: vtkInformationVector, # noqa: F841
- ) -> 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: Union[ vtkDataSet, vtkMultiBlockDataSet ] = self.GetInputData( inInfoVec, 0, 0 )
- outputMesh: Union[ vtkDataSet, vtkMultiBlockDataSet ] = self.GetOutputData( outInfoVec, 0 )
-
- assert inputMesh is not None, "Input mesh is null."
- assert outputMesh is not None, "Output pipeline is null."
-
- outputMesh.ShallowCopy( inputMesh )
filter: CreateConstantAttributePerRegion = CreateConstantAttributePerRegion(
outputMesh,
self.regionName,
@@ -352,4 +298,4 @@ def RequestData(
self.clearDictRegion = True
- return 1
+ return
diff --git a/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py b/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py
index 218d6bfc..b5c60dc8 100644
--- a/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py
+++ b/geos-pv/src/geos/pv/plugins/PVFillPartialArrays.py
@@ -8,20 +8,15 @@
from typing_extensions import Self
from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
-) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py
+ VTKPythonAlgorithmBase, smproperty,
+) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py
from paraview.detail.loghandler import ( # type: ignore[import-not-found]
VTKHandler,
-) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
+) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/detail/loghandler.py
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.parent.parent
sys.path.insert( 0, str( geos_pv_path / "src" ) )
@@ -29,6 +24,7 @@
update_paths()
+from geos.pv.utils.details import SISOFilter, FilterCategory
from geos.mesh.processing.FillPartialArrays import FillPartialArrays
__doc__ = """
@@ -47,31 +43,21 @@
"""
-@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,
-)
+@SISOFilter( category=FilterCategory.GEOS_UTILS,
+ decoratedLabel="Fill Partial Arrays",
+ decoratedType="vtkMultiBlockDataSet" )
class PVFillPartialArrays( VTKPythonAlgorithmBase ):
def __init__( self: Self, ) -> None:
"""Fill a partial attribute with constant value per component."""
- super().__init__( nInputPorts=1,
- nOutputPorts=1,
- inputType="vtkMultiBlockDataSet",
- outputType="vtkMultiBlockDataSet" )
-
self.clearDictAttributesValues: bool = True
self.dictAttributesValues: dict[ str, Union[ list[ Any ], None ] ] = {}
-
- @smproperty.xml("""
+ @smproperty.xml( """
@@ -79,7 +65,7 @@ def __init__( self: Self, ) -> None:
attributeName | fillingValueComponent1 fillingValueComponent2 ...\n
To fill the attribute with the default value, live a blanc. The default value is:\n
0 for uint type, -1 for int type and nan for float type.
-
+
@@ -89,7 +75,7 @@ def __init__( self: Self, ) -> None:
""" )
- def _setDictAttributesValues( self: Self, attributeName: str, values: str ) -> None:
+ def setDictAttributesValues( self: Self, attributeName: str, values: str ) -> None:
"""Set the dictionary with the region indexes and its corresponding list of value for each components.
Args:
@@ -99,72 +85,34 @@ def _setDictAttributesValues( self: Self, attributeName: str, values: str ) -> N
if self.clearDictAttributesValues:
self.dictAttributesValues = {}
self.clearDictAttributesValues = False
-
+
if attributeName is not None:
- if values is not None :
+ if values is not None:
self.dictAttributesValues[ attributeName ] = list( values.split( "," ) )
else:
- self.dictAttributesValues[ attributeName ] = None
-
- self.Modified()
-
- def RequestDataObject(
- self: Self,
- request: vtkInformation,
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestDataObject.
+ self.dictAttributesValues[ attributeName ] = None #ignore : type[unreachable]
- Args:
- request (vtkInformation): Request
- inInfoVec (list[vtkInformationVector]): Input objects
- outInfoVec (vtkInformationVector): Output objects
+ self.Modified()
- 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.
+ def Filter( self, inputMesh: vtkMultiBlockDataSet, outputMesh: vtkMultiBlockDataSet ) -> None:
+ """Is applying FillPartialArrays to the mesh and return with the class's dictionnary for attributes values.
Args:
- request (vtkInformation): Request
- inInfoVec (list[vtkInformationVector]): Input objects
- outInfoVec (vtkInformationVector): Output objects
+ inputMesh : A mesh to transform.
+ outputMesh : A mesh transformed.
- 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."
-
- outputMesh.ShallowCopy( inputMesh )
-
- filter: FillPartialArrays = FillPartialArrays( outputMesh,
- self.dictAttributesValues,
- True,
+ filter: FillPartialArrays = FillPartialArrays(
+ outputMesh,
+ self.dictAttributesValues,
+ speHandler=True,
)
-
+
if not filter.logger.hasHandlers():
filter.setLoggerHandler( VTKHandler() )
-
+
filter.applyFilter()
self.clearDictAttributesValues = True
- return 1
+ return
diff --git a/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py b/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py
index a82b0a49..2145fc1d 100644
--- a/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py
+++ b/geos-pv/src/geos/pv/plugins/PVMeshQualityEnhanced.py
@@ -7,13 +7,10 @@
from typing_extensions import Self, Optional
from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
+ VTKPythonAlgorithmBase, smdomain, smproperty,
)
from vtkmodules.vtkCommonCore import (
- vtkInformation,
- vtkInformationVector,
- vtkDataArraySelection,
-)
+ vtkDataArraySelection, )
from vtkmodules.vtkCommonDataModel import (
vtkUnstructuredGrid, )
@@ -44,6 +41,8 @@
createModifiedCallback, )
from geos.pv.utils.paraviewTreatments import getArrayChoices
+from geos.pv.utils.details import SISOFilter, FilterCategory
+
__doc__ = """
The ``Mesh Quality Enhanced`` filter computes requested mesh quality metrics on meshes. Both surfaces and volumic metrics can be computed with this plugin.
@@ -67,19 +66,13 @@
"""
-@smproxy.filter( name="PVMeshQualityEnhanced", label="Mesh Quality Enhanced" )
-@smhint.xml( '' )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype(
- dataTypes=[ "vtkUnstructuredGrid" ],
- composite_data_supported=True,
-)
+@SISOFilter( category=FilterCategory.GEOS_QC,
+ decoratedLabel="Mesh Quality Enhanced",
+ decoratedType="vtkUnstructuredGrid" )
class PVMeshQualityEnhanced( VTKPythonAlgorithmBase ):
def __init__( self: Self ) -> None:
"""Merge collocated points."""
- super().__init__( nInputPorts=1, nOutputPorts=1, outputType="vtkUnstructuredGrid" )
-
self._filename: Optional[ str ] = None
self._saveToFile: bool = True
self._blockIndex: int = 0
@@ -172,7 +165,7 @@ def b01SetSaveToFile( self: Self, saveToFile: bool ) -> None:
"""
if self._saveToFile != saveToFile:
self._saveToFile = saveToFile
- self.Modified()
+ PVMeshQualityEnhanced.Modified( self )
@smproperty.stringvector( name="FilePath", label="File Path" )
@smdomain.xml( """
@@ -191,7 +184,7 @@ def b02SetFileName( self: Self, fname: str ) -> None:
"""
if self._filename != fname:
self._filename = fname
- self.Modified()
+ PVMeshQualityEnhanced.Modified( self )
@smproperty.xml( """
None:
""" )
def b03GroupAdvancedOutputParameters( self: Self ) -> None:
"""Organize groups."""
- self.Modified()
+ PVMeshQualityEnhanced.Modified( self )
def Modified( self: Self ) -> None:
"""Overload Modified method to reset _blockIndex."""
self._blockIndex = 0
- super().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 )
+ VTKPythonAlgorithmBase.Modified( self )
def _getQualityMetricsToUse( self: Self, selection: vtkDataArraySelection ) -> set[ int ]:
"""Get mesh quality metric indexes from user selection.
@@ -247,27 +216,14 @@ def _getQualityMetricsToUse( self: Self, selection: vtkDataArraySelection ) -> s
metricsNames: set[ str ] = getArrayChoices( selection )
return { getQualityMeasureIndexFromName( name ) for name in metricsNames }
- def RequestData(
- self: Self,
- request: vtkInformation, # noqa: F841
- inInfoVec: list[ vtkInformationVector ],
- outInfoVec: vtkInformationVector,
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestData.
+ def Filter( self, inputMesh: vtkUnstructuredGrid, outputMesh: vtkUnstructuredGrid ) -> None:
+ """Is applying MeshQualityEnhanced to the input Mesh.
Args:
- request (vtkInformation): Request
- inInfoVec (list[vtkInformationVector]): Input objects
- outInfoVec (vtkInformationVector): Output objects
+ inputMesh : A mesh to transform.
+ outputMesh : A mesh transformed.
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
"""
- inputMesh: vtkUnstructuredGrid = self.GetInputData( inInfoVec, 0, 0 )
- outputMesh: vtkUnstructuredGrid = vtkUnstructuredGrid.GetData( outInfoVec, 0 )
- assert inputMesh is not None, "Input server mesh is null."
- assert outputMesh is not None, "Output pipeline is null."
-
triangleMetrics: set[ int ] = self._getQualityMetricsToUse( self._commonCellSurfaceQualityMetric ).union(
self._getQualityMetricsToUse( self._triangleQualityMetric ) )
quadMetrics: set[ int ] = self._getQualityMetricsToUse( self._commonCellSurfaceQualityMetric ).union(
@@ -302,7 +258,7 @@ def RequestData(
stats: QualityMetricSummary = filter.GetQualityMetricSummary()
self.saveFile( stats )
self._blockIndex += 1
- return 1
+ return
def saveFile( self: Self, stats: QualityMetricSummary ) -> None:
"""Export mesh quality metric summary file."""
diff --git a/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py b/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py
index 5ba12bd1..a2467a88 100755
--- a/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py
+++ b/geos-pv/src/geos/pv/plugins/PVPythonViewConfigurator.py
@@ -16,6 +16,7 @@
update_paths()
+from geos.mesh.utils.multiblockModifiers import mergeBlocks
import geos.pv.utils.paraviewTreatments as pvt
from geos.pv.utils.checkboxFunction import ( # type: ignore[attr-defined]
createModifiedCallback, )
@@ -34,14 +35,22 @@
GetActiveSource, GetActiveView, Render, Show, servermanager,
)
from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
+ smdomain, smproperty,
)
from vtkmodules.vtkCommonCore import (
vtkDataArraySelection,
vtkInformation,
- vtkInformationVector,
)
+from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
+ VTKPythonAlgorithmBase )
+
+from vtkmodules.vtkCommonDataModel import (
+ vtkDataObject,
+ vtkMultiBlockDataSet,
+)
+from geos.pv.utils.details import SISOFilter, FilterCategory
+
__doc__ = """
PVPythonViewConfigurator is a Paraview plugin that allows to create cross-plots
from input data using the PythonView.
@@ -59,10 +68,9 @@
"""
-@smproxy.filter( name="PVPythonViewConfigurator", label="Python View Configurator" )
-@smhint.xml( '' )
-@smproperty.input( name="Input" )
-@smdomain.datatype( dataTypes=[ "vtkDataObject" ], composite_data_supported=True )
+@SISOFilter( category=FilterCategory.GEOS_UTILS,
+ decoratedLabel="Python View Configurator",
+ decoratedType="vtkDataObject" )
class PVPythonViewConfigurator( VTKPythonAlgorithmBase ):
def __init__( self: Self ) -> None:
@@ -70,7 +78,7 @@ def __init__( self: Self ) -> None:
Input is a vtkDataObject.
"""
- super().__init__( nInputPorts=1, nOutputPorts=1 )
+ # super().__init__( nInputPorts=1, nOutputPorts=1 )
# Python view layout and object.
self.m_layoutName: str = ""
self.m_pythonView: Any
@@ -80,6 +88,9 @@ def __init__( self: Self ) -> None:
# Input source and curve names.
inputSource = GetActiveSource()
dataset = servermanager.Fetch( inputSource )
+ # Handle vtkMultiBlockDataSet by merging blocks first
+ if isinstance( dataset, vtkMultiBlockDataSet ):
+ dataset = mergeBlocks( dataset, keepPartialAttributes=True )
dataframe: pd.DataFrame = pvt.vtkToDataframe( dataset )
self.m_pathPythonViewScript: Path = geos_pv_path / "src/geos/pv/pythonViewUtils/mainPythonView.py"
@@ -806,47 +817,14 @@ def FillInputPortInformation( self: Self, port: int, info: vtkInformation ) -> i
info.Set( self.INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject" )
return 1
- 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 ], # noqa: F841
- outInfoVec: vtkInformationVector, # noqa: F841
- ) -> int:
- """Inherited from VTKPythonAlgorithmBase::RequestData.
+ def Filter( self, inputMesh: vtkDataObject, outputMesh: vtkDataObject ) -> None:
+ """Dummy interface for plugin to fit decorator reqs.
Args:
- request (vtkInformation): Request.
- inInfoVec (list[vtkInformationVector]): Input objects.
- outInfoVec (vtkInformationVector): Output objects.
+ inputMesh : A dummy mesh to transform.
+ outputMesh : A dummy mesh transformed.
- Returns:
- int: 1 if calculation successfully ended, 0 otherwise.
"""
- # pythonViewGeneration
assert self.m_pythonView is not None, "No Python View was found."
viewSize = GetActiveView().ViewSize
self.m_userChoices[ "ratio" ] = viewSize[ 0 ] / viewSize[ 1 ]
@@ -855,4 +833,4 @@ def RequestData(
self.defineCurvesAspect()
self.m_pythonView.Script = self.buildPythonViewScript()
Render()
- return 1
+ return
diff --git a/geos-pv/src/geos/pv/plugins/PVSplitMesh.py b/geos-pv/src/geos/pv/plugins/PVSplitMesh.py
index e6e3d55e..089e6a8f 100644
--- a/geos-pv/src/geos/pv/plugins/PVSplitMesh.py
+++ b/geos-pv/src/geos/pv/plugins/PVSplitMesh.py
@@ -7,8 +7,7 @@
from typing_extensions import Self
from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- smdomain, smhint, smproperty, smproxy,
-)
+ VTKPythonAlgorithmBase )
from vtkmodules.vtkCommonDataModel import (
vtkPointSet, )
@@ -21,7 +20,7 @@
update_paths()
from geos.mesh.processing.SplitMesh import SplitMesh
-from geos.pv.utils.AbstractPVPluginVtkWrapper import AbstractPVPluginVtkWrapper
+from geos.pv.utils.details import SISOFilter, FilterCategory
__doc__ = """
Split each cell of input mesh to smaller cells.
@@ -37,32 +36,23 @@
"""
-@smproxy.filter( name="PVSplitMesh", label="Split Mesh" )
-@smhint.xml( '' )
-@smproperty.input( name="Input", port_index=0 )
-@smdomain.datatype(
- dataTypes=[ "vtkPointSet" ],
- composite_data_supported=True,
-)
-class PVSplitMesh( AbstractPVPluginVtkWrapper ):
+@SISOFilter( category=FilterCategory.GEOS_UTILS,
+ decoratedLabel="Split Mesh",
+ decoratedType="vtkPointSet" )
+class PVSplitMesh( VTKPythonAlgorithmBase ):
def __init__( self: Self ) -> None:
"""Split mesh cells."""
- super().__init__()
+ pass
- def applyVtkFilter(
- self: Self,
- input: vtkPointSet,
- ) -> vtkPointSet:
+ def Filter( self: Self, inputMesh: vtkPointSet, outputMesh: vtkPointSet ) -> None:
"""Apply vtk filter.
Args:
- input (vtkPointSet): input mesh
-
- Returns:
- vtkPointSet: output mesh
+ inputMesh(vtkPointSet): Input mesh.
+ outputMesh: Output mesh.
"""
filter: SplitMesh = SplitMesh()
- filter.SetInputDataObject( input )
+ filter.SetInputDataObject( inputMesh )
filter.Update()
- return filter.GetOutputDataObject( 0 )
+ outputMesh.ShallowCopy( filter.GetOutputDataObject( 0 ) )
diff --git a/geos-pv/src/geos/pv/utils/AbstractPVPluginVtkWrapper.py b/geos-pv/src/geos/pv/utils/AbstractPVPluginVtkWrapper.py
deleted file mode 100644
index 8ae8c27f..00000000
--- a/geos-pv/src/geos/pv/utils/AbstractPVPluginVtkWrapper.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
-# SPDX-FileContributor: Martin Lemay
-# ruff: noqa: E402 # disable Module level import not at top of file
-from typing import Any
-from typing_extensions import Self
-
-from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
- VTKPythonAlgorithmBase, )
-
-from vtkmodules.vtkCommonCore import (
- vtkInformation,
- vtkInformationVector,
-)
-
-__doc__ = """
-AbstractPVPluginVtkWrapper module defines the parent Paraview plugin from which inheritates PV plugins that directly wrap a vtk filter.
-
-To use it, make children PV plugins inherited from AbstractPVPluginVtkWrapper. Output mesh is of same type as input mesh.
-If output type needs to be specified, this must be done in the child class.
-"""
-
-
-class AbstractPVPluginVtkWrapper( VTKPythonAlgorithmBase ):
-
- def __init__( self: Self ) -> None:
- """Abstract Paraview Plugin class."""
- super().__init__( nInputPorts=1, nOutputPorts=1, outputType="vtkPointSet" )
-
- 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 )
-
- 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.
- """
- try:
- inputMesh: Any = self.GetInputData( inInfoVec, 0, 0 )
- outputMesh: Any = self.GetOutputData( outInfoVec, 0 )
- assert inputMesh is not None, "Input server mesh is null."
- assert outputMesh is not None, "Output pipeline is null."
-
- tmpMesh = self.applyVtkFilter( inputMesh )
- assert tmpMesh is not None, "Output mesh is null."
- outputMesh.ShallowCopy( tmpMesh )
- print( "Filter was successfully applied." )
- except ( AssertionError, Exception ) as e:
- print( f"Filter failed due to: {e}" )
- return 0
- return 1
-
- def applyVtkFilter(
- self: Self,
- input: Any,
- ) -> Any:
- """Apply vtk filter.
-
- Args:
- input (Any): input object
-
- Returns:
- Any: output mesh
- """
- pass
diff --git a/geos-pv/src/geos/pv/utils/details.py b/geos-pv/src/geos/pv/utils/details.py
new file mode 100644
index 00000000..44cb102c
--- /dev/null
+++ b/geos-pv/src/geos/pv/utils/details.py
@@ -0,0 +1,195 @@
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies.
+# SPDX-FileContributor: Martin Lemay, Romain Baville, Jacques Franc
+# ruff: noqa: E402 # disable Module level import not at top of file
+# mypy: disable-error-code="misc"
+import sys
+from pathlib import Path
+# Add Enum for filter categories
+from functools import update_wrapper
+from typing import Protocol, Any, Type, TypeVar, Callable, runtime_checkable, Union
+from abc import abstractmethod
+from enum import Enum
+
+from paraview.util.vtkAlgorithm import ( # type: ignore[import-not-found]
+ VTKPythonAlgorithmBase, smdomain, smhint, smproperty, smproxy,
+) # source: https://github.com/Kitware/ParaView/blob/master/Wrapping/Python/paraview/util/vtkAlgorithm.py
+
+from vtkmodules.vtkCommonDataModel import (
+ vtkMultiBlockDataSet,
+ vtkDataObject,
+)
+
+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.parent.parent
+sys.path.insert( 0, str( geos_pv_path / "src" ) )
+from geos.pv.utils.config import update_paths
+
+update_paths()
+
+__doc__ = """
+Set of decorators that allows quicker generation of DataSet derived to the same DataSet derived filters. If it a list of type is provided, then the unique output type is set to vtkDataObject.
+
+Usage is:
+
+ from geos.pv.utils.details import SISOFilter, FilterCategory
+
+ @SISO(category=FilterCategory.GEOS_UTILS,decoratedLabel='Awesome Filter',decoratedType='vtkMultiBlockDataSet')
+ class PVMyFilter:
+ ...
+
+"""
+
+
+# Enum for filter categories
+class FilterCategory( str, Enum ):
+ """String Enum to sort into category in PV task bar under Plugins."""
+ GEOS_PROP = '0- Geos Pre-processing'
+ GEOS_MESH = '1- Geos Mesh'
+ GEOS_GEOMECHANICS = '2- Geos Geomechanics'
+ GEOS_PV = '3- Geos PV'
+ GEOS_UTILS = '4- Geos Utils'
+ GEOS_QC = '5- Geos QC'
+ # Add more as needed
+
+
+U = TypeVar( 'U', bound='vtkDataObject' )
+
+@runtime_checkable
+class IsSISOFilter( Protocol[ U ] ):
+ """Protocol to ensure that the wrapped filter defines the correct Filter core function."""
+
+ @abstractmethod
+ def Filter(
+ self,
+ inputMesh: U,
+ outputMesh: U,
+ ) -> None:
+ """Define filter here.
+
+ Args:
+ inputMesh : A mesh to transform
+ outputMesh : A mesh transformed
+
+ """
+ raise NotImplementedError
+
+
+T = TypeVar( 'T', bound='IsSISOFilter' )
+
+
+def SISOFilter( category: FilterCategory, decoratedLabel: str,
+ decoratedType: Union[ str, list ] ) -> Callable[ [ Type[ T ] ], Type[ T ] ]:
+ """Decorate Single Input Single Output (SISO) filter."""
+
+ def decoratedClass( cls: Type[ T ] ) -> Type[ T ]:
+ """Outer wrapper function. All is in the WrappingClass below."""
+ originalInit = cls.__init__
+
+ class WrappingClass( cls ): # type: ignore[valid-type]
+
+ def __init__( self, *ar: Any, **kw: Any ) -> None:
+ """Pre-init the filter with the Base algo and I/O single type (usually vtkMultiBlockDataSet).
+
+ Args:
+ ar : Fowarded arguments
+ kw : Forwarded keywords args
+ """
+ VTKPythonAlgorithmBase.__init__(
+ self,
+ nInputPorts=1,
+ nOutputPorts=1,
+ inputType=decoratedType if isinstance( decoratedType, str ) else "vtkDataObject",
+ outputType=decoratedType if isinstance( decoratedType, str ) else "vtkDataObject" )
+
+ #If wrapped class has more to init there it is applied
+ #avoid the overwritten init by decorator taking place of the cls
+ if originalInit is not object.__init__:
+ originalInit( self, *ar, **kw )
+
+ def RequestDataObject(
+ 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 VTKPythonAlgorithmBase.RequestDataObject( self, request, inInfoVec,
+ outInfoVec ) # type: ignore[no-any-return]
+
+ def RequestData(
+ 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."
+
+ outputMesh.ShallowCopy( inputMesh )
+
+ cls.Filter( self, inputMesh, outputMesh )
+ return 1
+
+ # Copy all methods and attributes from cls, including decorator metadata
+ for attrName in dir( cls ):
+ if attrName.startswith( '_' ):
+ continue # Skip private/magic methods (already handled or inherited)
+
+ attr = getattr( cls, attrName )
+ # Copy methods with their decorators
+ if callable( attr ) and attrName not in WrappingClass.__dict__:
+ setattr( WrappingClass, attrName, attr )
+
+ # Copy metadata
+ WrappingClass.__name__ = cls.__name__
+ WrappingClass.__qualname__ = cls.__qualname__
+ WrappingClass.__module__ = cls.__module__
+ WrappingClass.__doc__ = cls.__doc__
+ update_wrapper( WrappingClass, cls, updated=[] )
+
+ #decorate it old fashion way
+ WrappingClass = smdomain.datatype(
+ dataTypes=[ decoratedType ] if isinstance( decoratedType, str ) else decoratedType,
+ composite_data_supported=True,
+ )( WrappingClass )
+ WrappingClass = smproperty.input( name="Input", port_index=0 )( WrappingClass )
+ # Use enum value for category
+ WrappingClass = smhint.xml( f'' )( WrappingClass )
+ WrappingClass = smproxy.filter( name=getattr( cls, '__name__', str( cls ) ),
+ label=decoratedLabel )( WrappingClass )
+ return WrappingClass
+
+ return decoratedClass
diff --git a/geos-pv/src/geos/pv/utils/paraviewTreatments.py b/geos-pv/src/geos/pv/utils/paraviewTreatments.py
index 41894e4f..2856aee7 100644
--- a/geos-pv/src/geos/pv/utils/paraviewTreatments.py
+++ b/geos-pv/src/geos/pv/utils/paraviewTreatments.py
@@ -37,6 +37,7 @@
vtkTable,
vtkUnstructuredGrid,
)
+from vtkmodules.vtkFiltersParallelDIY2 import vtkGenerateGlobalIds
from geos.utils.GeosOutputsConstants import (
ComponentNameEnum,
@@ -122,8 +123,18 @@ def vtkUnstructuredGridCellsToDataframe( grid: vtkUnstructuredGrid ) -> pd.DataF
Returns:
pd.DataFrame: Pandas dataframe.
"""
- cellIdAttributeName = GeosMeshOutputsEnum.VTK_ORIGINAL_CELL_ID.attributeName
+ cellIdAttributeName: str = GeosMeshOutputsEnum.VTK_ORIGINAL_CELL_ID.attributeName
cellData = grid.GetCellData()
+ if not cellData.HasArray( GeosMeshOutputsEnum.VTK_ORIGINAL_CELL_ID.attributeName ):
+ print( "We have to create global ids." )
+ idFilter = vtkGenerateGlobalIds()
+ idFilter.SetInputData( grid )
+ idFilter.Update()
+ grid = idFilter.GetOutput()
+ cellData = grid.GetCellData() # Update cellData to point to the new grid's cell data
+ cellIdAttributeName = "GlobalCellIds"
+ assert cellData.HasArray(cellIdAttributeName), "Invalid global ids array name selected."
+
numberCells: int = grid.GetNumberOfCells()
data: dict[ str, Any ] = {}
for i in range( cellData.GetNumberOfArrays() ):