Source code for paraview.annotation
#==============================================================================
#
# Program: ParaView
# Module: annotation.py
#
# Copyright (c) Kitware, Inc.
# All rights reserved.
# See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even
# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the above copyright notice for more information.
#
#==============================================================================
r"""
This module is used by vtkPythonAnnotationFilter.
"""
from __future__ 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 paraview import calculator
from vtk import vtkDataObject
from vtk.numpy_interface import dataset_adapter as dsa
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 insead.
# 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 xrange(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:
from sys import stderr
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, ns.keys()), file=sys.stderr)
raise
self.SetComputedAnnotationValue("%s" % result)
return True
[docs]def execute_on_global_data(self):
"""Called by vtkAnnotateGlobalDataFilter."""
inputDO = self.GetCurrentInputDataObject()
if not inputDO:
return True
inputs = [dsa.WrapDataObject(inputDO)]
association = self.GetArrayAssociation()
ns = _get_ns(self, inputs[0], association)
if not ns.has_key(self.GetFieldArrayName()):
print("Failed to locate global array '%s'." % self.GetFieldArrayName(), file=sys.stderr)
raise RuntimeError("Failed to locate global array")
array = ns[self.GetFieldArrayName()]
chosen_element = array
try:
# if the array has as many elements as the timesteps, pick the element
# matching the current timestep.
if self.GetNumberOfTimeSteps() > 0 and \
array.shape[0] == self.GetNumberOfTimeSteps():
chosen_element = array[ns["time_index"]]
# if the array has as many elements as the `mode_shape_range`, pick the
# element matching the `mode_shape` (BUG #0015322).
elif ns.has_key("mode_shape") and ns.has_key("mode_shape_range") and \
ns["mode_shape_range"].shape[1] == 2 and \
array.shape[0] == (ns["mode_shape_range"].GetValue(1) - ns["mode_shape_range"].GetValue(0) + 1):
chosen_element = array[ns["mode_shape"].GetValue(0) - ns["mode_shape_range"].GetValue(0)]
elif array.shape[0] == 1:
# for single element arrays, just extract the value.
# This avoids the extra () when converting to string
# (see BUG #15321).
chosen_element = array[0]
except AttributeError: pass
try:
# hack for string array.
if chosen_element.IsA("vtkStringArray"):
chosen_element = chosen_element.GetValue(0)
except: pass
expression = self.GetPrefix() if self.GetPrefix() else ""
expression += str(chosen_element)
expression += self.GetPostfix() if self.GetPostfix() else ""
self.SetComputedAnnotationValue(expression)
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)]
association = self.GetArrayAssociation()
ns = _get_ns(self, inputs[0], association)
if not ns.has_key(self.GetArrayName()):
print("Failed to locate array '%s'." % self.GetArrayName(), file=sys.stderr)
raise RuntimeError("Failed to locate array")
if not evaluate_locally:
return True
array = ns[self.GetArrayName()]
chosen_element = array[self.GetElementId()]
expression = self.GetPrefix() if self.GetPrefix() else ""
expression += str(chosen_element)
self.SetComputedAnnotationValue(expression)
return True