mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
116 lines
5.0 KiB
Python
116 lines
5.0 KiB
Python
r"""This module is used by vtkPythonExtractSelection to extract query-based
|
|
selections. It relies on the python-calculator (vtkPythonCalculator),
|
|
specifically, the Python code used by that class, to compute a mask array from
|
|
the query expression. Once the mask array is obtained, this filter will either
|
|
extract the selected ids, or mark those elements as requested.
|
|
"""
|
|
try:
|
|
import numpy as np
|
|
except ImportError:
|
|
raise RuntimeError, "'numpy' module is not found. numpy is needed for "\
|
|
"this functionality to work. Please install numpy and try again."
|
|
|
|
import re
|
|
import vtk
|
|
import vtk.numpy_interface.dataset_adapter as dsa
|
|
import vtk.numpy_interface.algorithms as algos
|
|
from paraview import calculator
|
|
|
|
def _create_id_array(dataobject, attributeType):
|
|
"""Returns a VTKArray or VTKCompositeDataArray for the ids"""
|
|
if not dataobject:
|
|
raise RuntimeError, "dataobject cannot be None"
|
|
if dataobject.IsA("vtkCompositeDataSet"):
|
|
ids = []
|
|
for ds in dataobject:
|
|
ids.append(_create_id_array(ds, attributeType))
|
|
return dsa.VTKCompositeDataArray(ids)
|
|
else:
|
|
return dsa.VTKArray(\
|
|
np.arange(dataobject.GetNumberOfElements(attributeType)))
|
|
|
|
def maskarray_is_valid(maskArray):
|
|
"""Validates that the maskArray is either a VTKArray or a
|
|
VTKCompositeDataArrays or a NoneArray other returns false."""
|
|
return maskArray is dsa.NoneArray or \
|
|
isinstance(maskArray, dsa.VTKArray) or \
|
|
isinstance(maskArray, dsa.VTKCompositeDataArray)
|
|
|
|
def execute(self):
|
|
inputDO = self.GetInputDataObject(0, 0)
|
|
inputSEL = self.GetInputDataObject(1, 0)
|
|
outputDO = self.GetOutputDataObject(0)
|
|
|
|
assert inputSEL.GetNumberOfNodes() >= 1
|
|
|
|
selectionNode = inputSEL.GetNode(0)
|
|
field_type = selectionNode.GetFieldType()
|
|
if field_type == selectionNode.CELL:
|
|
attributeType = vtk.vtkDataObject.CELL
|
|
elif field_type == selectionNode.POINT:
|
|
attributeType = vtk.vtkDataObject.POINT
|
|
elif field_type == selectionNode.ROW:
|
|
attributeType = vtk.vtkDataObject.ROW
|
|
else:
|
|
raise RuntimeError, "Unsupported field attributeType %r" % field_type
|
|
|
|
# evaluate expression on the inputDO.
|
|
# this is equivalent to executing the Python Calculator on the input dataset
|
|
# to produce a mask array.
|
|
inputs = []
|
|
inputs.append(dsa.WrapDataObject(inputDO))
|
|
|
|
query = selectionNode.GetQueryString()
|
|
|
|
# get a dictionary for arrays in the dataset attributes. We pass that
|
|
# as the variables in the eval namespace for calculator.compute().
|
|
elocals = calculator.get_arrays(inputs[0].GetAttributes(attributeType))
|
|
if not elocals.has_key("id") and re.search(r'\bid\b', query):
|
|
# add "id" array if the query string refers to id.
|
|
# This is a temporary fix. We should look into
|
|
# accelerating id-based selections in the future.
|
|
elocals["id"] = _create_id_array(inputs[0], attributeType)
|
|
try:
|
|
maskArray = calculator.compute(inputs, query, ns=elocals)
|
|
except:
|
|
from sys import stderr
|
|
print >> stderr, "Error: Failed to evaluate Expression '%s'. "\
|
|
"The following exception stack should provide additional developer "\
|
|
"specific information. This typically implies a malformed "\
|
|
"expression. Verify that the expression is valid.\n" % query
|
|
raise
|
|
|
|
if not maskarray_is_valid(maskArray):
|
|
raise RuntimeError,\
|
|
"Expression '%s' did not produce a valid mask array. The value "\
|
|
"produced is of the type '%s'. This typically implies a malformed "\
|
|
"expression. Verify that the expression is valid." % \
|
|
(query, type(maskArray))
|
|
|
|
# if inverse selection is requested, just logical_not the mask array.
|
|
if selectionNode.GetProperties().Has(selectionNode.INVERSE()) and \
|
|
selectionNode.GetProperties().Get(selectionNode.INVERSE()) == 1:
|
|
maskArray = algos.logical_not(maskArray)
|
|
|
|
output = dsa.WrapDataObject(outputDO)
|
|
if self.GetPreserveTopology():
|
|
# when preserving topology, just add the mask array as
|
|
# vtkSignedCharArray to the output. vtkPythonExtractSelection should
|
|
# have already ensured that the input is shallow copied over properly
|
|
# before this method gets called.
|
|
|
|
# note: since mask array is a bool-array, we multiply it by int8(1) to
|
|
# make it a type of array that can be represented as vtkSignedCharArray.
|
|
output.GetAttributes(attributeType).append(maskArray * np.int8(1), "vtkInsidedness")
|
|
else:
|
|
# handle extraction.
|
|
# flatnonzero() will give is array of indices where the arrays is
|
|
# non-zero (or non-False in our case). We then pass that to
|
|
# vtkPythonExtractSelection to extract the selected ids.
|
|
nonzero_indices = algos.flatnonzero(maskArray)
|
|
output.FieldData.append(nonzero_indices, "vtkSelectedIds");
|
|
#print output.FieldData["vtkSelectedIds"]
|
|
self.ExtractElements(attributeType, inputDO, outputDO)
|
|
del nonzero_indices
|
|
del maskArray
|