# SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
# SPDX-License-Identifier: BSD-3-Clause
r"""
This module is used by vtkPythonAnnotationFilter.
"""
from __future__ import absolute_import, print_function
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.")
from . import calculator
from vtkmodules.vtkCommonDataModel import vtkDataObject
from vtkmodules.numpy_interface import dataset_adapter as dsa
# import vtkPVVTKExtensionsFiltersPython so vtkAnnotateAttributeDataFilter wrapping
# is registered.
import paraview.modules.vtkPVVTKExtensionsFiltersPython
import sys # also for sys.stderr
if sys.version_info >= (3,):
xrange = range
def _get_ns(self, do, association):
if association == vtkDataObject.FIELD:
# For FieldData, it gets tricky. In general, one would think we are going
# to look at field data in inputDO directly -- same for composite datasets.
# However, ExodusIIReader likes to put field data on leaf nodes instead.
# So we also check leaf nodes, if the FieldData on the root is empty.
# We explicitly call dsa.DataObject.GetFieldData to ensure that
# when dealing with composite datasets, we get the FieldData on the
# vtkCompositeDataSet itself, not in the leaf nodes.
fieldData = dsa.DataObject.GetFieldData(do)
if len(fieldData.keys()) == 0:
# if this is a composite dataset, use field data from the first block with some
# field data.
if isinstance(do, dsa.CompositeDataSet):
for dataset in do:
fieldData = dataset.GetFieldData()
if (not fieldData is None) and (len(fieldData.keys()) > 0): break
else:
fieldData = do.GetAttributes(association)
arrays = calculator.get_arrays(fieldData)
ns = {}
ns["input"] = do
if self.GetDataTimeValid():
ns["time_value"] = self.GetDataTime()
ns["t_value"] = ns["time_value"]
if self.GetNumberOfTimeSteps() > 0:
ns["time_steps"] = [self.GetTimeStep(x) for x in range(self.GetNumberOfTimeSteps())]
ns["t_steps"] = ns["time_steps"]
if self.GetTimeRangeValid():
ns["time_range"] = self.GetTimeRange()
ns["t_range"] = ns["time_range"]
if self.GetDataTimeValid() and self.GetNumberOfTimeSteps() > 0:
try:
ns["time_index"] = ns["time_steps"].index(ns["time_value"])
ns["t_index"] = ns["time_index"]
except ValueError:
pass
ns.update(arrays)
return ns
[docs]def execute(self):
"""Called by vtkPythonAnnotationFilter."""
expression = self.GetExpression()
inputDO = self.GetCurrentInputDataObject()
if not expression or not inputDO:
return True
inputs = [dsa.WrapDataObject(inputDO)]
association = self.GetArrayAssociation()
ns = _get_ns(self, inputs[0], association)
try:
result = calculator.compute(inputs, expression, ns=ns)
except:
print("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\n" \
"Variables in current scope are %s \n" % (expression, list(ns)), file=sys.stderr)
raise
self.SetComputedAnnotationValue("%s" % result)
return True
[docs]def execute_on_attribute_data(self, evaluate_locally):
"""Called by vtkAnnotateAttributeDataFilter."""
inputDO = self.GetCurrentInputDataObject()
if not inputDO:
return True
inputs = [dsa.WrapDataObject(inputDO)]
info = self.GetInputArrayInformation(0)
association = info.Get(vtkDataObject.FIELD_ASSOCIATION())
# sanitize name
array_name = paraview.make_name_valid(info.Get(vtkDataObject.FIELD_NAME()))
# note: _get_ns() needs to be called on all ranks to avoid deadlocks.
ns = _get_ns(self, inputs[0], association)
if array_name not in ns:
print("Failed to locate array '%s'." % array_name, file=sys.stderr)
raise RuntimeError("Failed to locate array")
if not evaluate_locally:
# don't evaluate the expression locally.
return True
array = ns[array_name]
if array.IsA("vtkStringArray"):
chosen_element = array.GetValue(self.GetElementId())
else:
chosen_element = array[self.GetElementId()]
expression = self.GetPrefix() if self.GetPrefix() else ""
expression += str(chosen_element)
self.SetComputedAnnotationValue(expression)
return True