Commit 22beccad authored by Utkarsh Ayachit's avatar Utkarsh Ayachit

Added new vtkAnnotateAttributeDataFilter.

Added new vtkAnnotateAttributeDataFilter that can be used to generate
annotation text using data from any element in the dataset. By picking
the ElementId as a property, we can setup animations where the ElementId
changes over the course of the animation to show different elements from
a dataarray as annotation text!

Change-Id: I3d05f7fdb54e8bfaa9581a0b3f79bcde306686ec
parent 8074bd08
......@@ -106,10 +106,15 @@
<Proxy group="filters" name="QuadratureSchemeDictionaryGenerator" />
</Category>
<Category name="Annotation" menu_label="Annotation">
<Proxy group="filters" name="AnnotateGlobalData" />
<Proxy group="filters" name="AnnotateAttributeData" />
<Proxy group="filters" name="PythonAnnotation" />
<Proxy group="filters" name="TimeToTextConvertor" />
</Category>
<Proxy group="filters" name="ImageDataToAMR" />
<Proxy group="filters" name="UniformGridPartitioner" />
<Proxy group="filters" name="AnnotateGlobalData" />
<Proxy group="filters" name="Append" />
<Proxy group="filters" name="AppendAttributes" />
<Proxy group="filters" name="AppendPolyData" />
......@@ -185,7 +190,6 @@
<Proxy group="filters" name="ProgrammableFilter" />
<Proxy group="filters" name="PVConnectivityFilter" />
<Proxy group="filters" name="PythonCalculator" />
<Proxy group="filters" name="PythonAnnotation" />
<Proxy group="filters" name="PythonExtractSelection" />
<Proxy group="filters" name="QuadricClustering" />
......@@ -213,7 +217,6 @@
<Proxy group="filters" name="TextureMapToPlane" />
<Proxy group="filters" name="TextureMapToSphere" />
<Proxy group="filters" name="Threshold" />
<Proxy group="filters" name="TimeToTextConvertor" />
<Proxy group="filters" name="TransformFilter" />
<Proxy group="filters" name="TriangleFilter" />
<Proxy group="filters" name="TubeFilter" />
......
......@@ -23,6 +23,7 @@ if (numpy_found)
NO_DATA NO_VALID NO_OUTPUT NO_RT
TestPythonAnnotationFilter.py
TestPythonAnnotationFilterNoMerge.py
TestAnnotateAttributeData.py
)
set(PARAVIEW_PYTHON_ARGS)
......@@ -64,12 +65,25 @@ if (PARAVIEW_USE_MPI AND VTK_MPIRUN_EXE)
JUST_VALID
${PVBATCH_TESTS}
)
if (numpy_found)
paraview_add_test_pvbatch_mpi(
NO_DATA NO_VALID NO_OUTPUT NO_RT
TestAnnotateAttributeData.py
)
endif()
else()
# run the test serially
paraview_add_test_pvbatch(
JUST_VALID
${PVBATCH_TESTS}
)
if (numpy_found)
paraview_add_test_pvbatch(
NO_DATA NO_VALID NO_OUTPUT NO_RT
TestAnnotateAttributeData.py
)
endif()
endif()
# Python Multi-servers test
......
from paraview.simple import *
s = Sphere()
e = Elevation(LowPoint=[-0.5,-0.5,-0.5],
HighPoint=[0.5, 0.5, 0.5])
UpdatePipeline()
a = AnnotateAttributeData(
Prefix="Hello: ",
ArrayName= "Elevation",
ArrayAssociation="Point Data",
ElementId=0,
ProcessId=0
)
UpdatePipeline()
assert a.GetClientSideObject().GetComputedAnnotationValue() == "Hello: 0.666667"
......@@ -42,6 +42,7 @@ if (PARAVIEW_ENABLE_PYTHON)
list(APPEND Module_SRCS
vtkAnnotateGlobalDataFilter.cxx
vtkPythonCalculator.cxx
vtkAnnotateAttributeDataFilter.cxx
)
endif()
......
/*=========================================================================
Program: ParaView
Module: vtkAnnotateAttributeDataFilter.cxx
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.
=========================================================================*/
#include "vtkAnnotateAttributeDataFilter.h"
#include "vtkDataObject.h"
#include "vtkMultiProcessController.h"
#include "vtkMultiProcessStream.h"
#include "vtkObjectFactory.h"
#include "vtkPythonInterpreter.h"
#include <string>
#include <sstream>
#include <vtksys/SystemTools.hxx>
//----------------------------------------------------------------------------
static std::string vtkGetReferenceAsString(void* ref)
{
// Set self to point to this
char addrofthis[1024];
sprintf(addrofthis, "%p", ref);
char *aplus = addrofthis;
if ((addrofthis[0] == '0') && ((addrofthis[1] == 'x') || addrofthis[1] == 'X'))
{
aplus += 2; //skip over "0x"
}
return std::string(aplus);
}
vtkStandardNewMacro(vtkAnnotateAttributeDataFilter);
//----------------------------------------------------------------------------
vtkAnnotateAttributeDataFilter::vtkAnnotateAttributeDataFilter()
{
this->ArrayName = NULL;
this->Prefix = NULL;
this->ElementId = 0;
this->ProcessId = 0;
this->SetArrayAssociation(vtkDataObject::ROW);
}
//----------------------------------------------------------------------------
vtkAnnotateAttributeDataFilter::~vtkAnnotateAttributeDataFilter()
{
this->SetArrayName(NULL);
this->SetPrefix(NULL);
}
//----------------------------------------------------------------------------
void vtkAnnotateAttributeDataFilter::EvaluateExpression()
{
vtkMultiProcessController* controller = vtkMultiProcessController::GetGlobalController();
bool evaluate_locally = (controller == NULL) ||
(controller->GetLocalProcessId() == this->ProcessId) ||
(this->ProcessId == -1);
std::ostringstream stream;
stream
<< "def vtkAnnotateAttributeDataFilter_EvaluateExpression():" << endl
<< " from paraview import annotation as pv_ann" << endl
<< " from vtkPVClientServerCoreDefaultPython import vtkAnnotateAttributeDataFilter" << endl
<< " me = vtkAnnotateAttributeDataFilter('" << vtkGetReferenceAsString(this) << " ')" << endl
<< " pv_ann.execute_on_attribute_data(me," << (evaluate_locally? "True" : "False")
<< ")" << endl
<< " del me" << endl
<< "vtkAnnotateAttributeDataFilter_EvaluateExpression()" << endl
<< "del vtkAnnotateAttributeDataFilter_EvaluateExpression" << endl;
// ensure Python is initialized.
vtkPythonInterpreter::Initialize();
vtkPythonInterpreter::RunSimpleString(stream.str().c_str());
if (controller &&
controller->GetNumberOfProcesses() > 1 &&
this->ProcessId != -1)
{
vtkMultiProcessStream stream;
if (this->ProcessId == controller->GetLocalProcessId())
{
stream << (this->GetComputedAnnotationValue()? this->GetComputedAnnotationValue() : "");
}
controller->Broadcast(stream, this->ProcessId);
std::string val;
stream >> val;
this->SetComputedAnnotationValue(val.c_str());
}
}
//----------------------------------------------------------------------------
void vtkAnnotateAttributeDataFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "ArrayName: " << (this->ArrayName? this->ArrayName : "(none)") << endl;
os << indent << "Prefix: " << (this->Prefix? this->Prefix : "(none)") << endl;
os << indent << "ElementId: " << this->ElementId << endl;
os << indent << "ProcessId: " << this->ProcessId << endl;
}
/*=========================================================================
Program: ParaView
Module: vtkAnnotateAttributeDataFilter.h
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.
=========================================================================*/
// .NAME vtkAnnotateAttributeDataFilter - specialization of
// vtkPythonAnnotationFilter to work with element data.
// .SECTION Description
// vtkAnnotateAttributeDataFilter is a specialization of
// vtkPythonAnnotationFilter which makes it easier to annotate using data values
// from any input dataset.
#ifndef __vtkAnnotateAttributeDataFilter_h
#define __vtkAnnotateAttributeDataFilter_h
#include "vtkPythonAnnotationFilter.h"
#include "vtkPVClientServerCoreDefaultModule.h" //needed for exports
class VTKPVCLIENTSERVERCOREDEFAULT_EXPORT vtkAnnotateAttributeDataFilter : public vtkPythonAnnotationFilter
{
public:
static vtkAnnotateAttributeDataFilter* New();
vtkTypeMacro(vtkAnnotateAttributeDataFilter, vtkPythonAnnotationFilter);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Set the attribute array name to annotate with.
vtkSetStringMacro(ArrayName);
vtkGetStringMacro(ArrayName);
// Description:
// Set the element number to annotate with.
vtkSetMacro(ElementId, vtkIdType);
vtkGetMacro(ElementId, vtkIdType);
// Description:
// Set the rank to extract the data from.
// Default is 0.
vtkSetMacro(ProcessId, int);
vtkGetMacro(ProcessId, int);
// Description:
// Set the text prefix to display in front of the Field value
vtkSetStringMacro(Prefix);
vtkGetStringMacro(Prefix);
//BTX
protected:
vtkAnnotateAttributeDataFilter();
~vtkAnnotateAttributeDataFilter();
virtual void EvaluateExpression();
char* ArrayName;
char* Prefix;
int ProcessId;
vtkIdType ElementId;
private:
vtkAnnotateAttributeDataFilter(const vtkAnnotateAttributeDataFilter&); // Not implemented
void operator=(const vtkAnnotateAttributeDataFilter&); // Not implemented
//ETX
};
#endif
......@@ -113,6 +113,92 @@
</Hints>
<!-- End AnnotateGlobalData -->
</SourceProxy>
<SourceProxy class="vtkAnnotateAttributeDataFilter"
label="Annotate Attribute Data"
name="AnnotateAttributeData">
<Documentation>
This filter can be used to add a text annotation to a Render View (or similar)
using a tuple from any attribute array (point/cell/field/row etc.) from a specific rank
(when running in parallel). Use 'ArrayName' property to select the array association and
array name. Use 'ElementId' property to set the element number to extract the value to label
with. When running on multiple ranks, use 'ProcessId' property to select the rank of interest.
The 'Prefix' property can be used to specify a string that will be used as the prefix to the
generated annotation text.
</Documentation>
<InputProperty clean_command="RemoveAllInputs"
command="AddInputConnection"
name="Input">
<ProxyGroupDomain name="groups" >
<Group name="sources" />
<Group name="filters" />
</ProxyGroupDomain>
<DataTypeDomain name="input_type" composite_data_supported="0">
<DataType value="vtkDataSet" />
<DataType value="vtkTable" />
</DataTypeDomain>
<InputArrayDomain attribute_type="any"
name="input_array"
number_of_components="1" />
<Documentation>
Set the input of the filter. To avoid the complications/confusion when identifying
elements in a composite dataset, this filter doesn't support composite datasets
currently.
</Documentation>
</InputProperty>
<IntVectorProperty command="SetArrayAssociation"
default_values="2"
name="ArrayAssociation"
number_of_elements="1">
<Documentation>Select the attribute to use to popular array names from.</Documentation>
<EnumerationDomain name="enum">
<Entry text="Point Data" value="0" />
<Entry text="Cell Data" value="1" />
<Entry text="Field Data" value="2" />
<Entry text="Row Data" value="6" />
</EnumerationDomain>
</IntVectorProperty>
<StringVectorProperty command="SetArrayName"
name="ArrayName"
number_of_elements="1">
<ArrayListDomain name="array_list">
<RequiredProperties>
<Property function="Input"
name="Input" />
</RequiredProperties>
</ArrayListDomain>
<Documentation>Choose arrays that is going to be displayed</Documentation>
</StringVectorProperty>
<IntVectorProperty name="ElementId"
command="SetElementId"
number_of_elements="1"
default_values="0">
<!-- this should really be an IdTypeVectorProperty, but the UI doesn't
support those yet -->
<IntRangeDomain name="range"/>
<Documentation>
Set the element index to annotate with.
</Documentation>
</IntVectorProperty>
<IntVectorProperty name="ProcessId"
command="SetProcessId"
number_of_elements="1"
default_values="0">
<IntRangeDomain name="range" min="0" />
<Documentation>
Set the process rank to extract element from.
</Documentation>
</IntVectorProperty>
<StringVectorProperty command="SetPrefix"
default_values="Value is: "
name="Prefix"
number_of_elements="1">
<Documentation>Text that is used as a prefix to the field value</Documentation>
</StringVectorProperty>
<Hints>
<Visibility replace_input="0" />
<OutputPort index="0" name="Output-0" type="text" />
</Hints>
</SourceProxy>
<SourceProxy class="vtkPythonAnnotationFilter"
label="Python Annotation"
name="PythonAnnotation">
......
......@@ -125,3 +125,26 @@ def execute_on_global_data(self):
expression += str(chosen_element)
self.SetComputedAnnotationValue(expression)
return True
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 >> stderr, "Failed to locate array '%s'." % self.GetArrayName()
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment