Commit 87cfceb6 authored by Sebastien Jourdain's avatar Sebastien Jourdain

Add python annotation filter

Change-Id: I648cc58f15e8d0944066284f2d9760c725d5501d
parent b0eba067
......@@ -156,6 +156,7 @@
<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="QuadraturePointInterpolator" />
<Proxy group="filters" name="QuadraturePointsGenerator" />
......
......@@ -79,6 +79,13 @@ IF (PARAVIEW_DATA_ROOT)
# TODO: remote rendering tests and reverse connect tests.
# Add pvpython tests
add_test("pvpython.TestPythonAnnotationFilter"
${PARAVIEW_PYTHON_EXECUTABLE}
--data=${PARAVIEW_DATA_ROOT}/Data/can.ex2
${CMAKE_CURRENT_SOURCE_DIR}/TestPythonAnnotationFilter.py
)
ENDIF (PARAVIEW_DATA_ROOT)
# Python Multi-servers test
......
from paraview.simple import *
from paraview import servermanager
import time
# Make sure the test driver know that process has properly started
print "Process started"
errors = 0
#-------------------- Start testing --------------------------
print "Start PythonAnnotationFilter testing"
options = servermanager.vtkProcessModule.GetProcessModule().GetOptions()
dataToLoad = options.GetParaViewDataName()
# Load data file
reader = OpenDataFile(dataToLoad)
reader.GlobalVariables = ['KE', 'XMOM', 'YMOM', 'ZMOM', 'NSTEPS', 'TMSTEP']
reader.UpdatePipeline()
# Time management
#animationscene = GetAnimationScene()
tk = servermanager.ProxyManager().GetProxy('timekeeper','TimeKeeper')
#animationscene.PlayMode = 'Snap To TimeSteps'
#animationscene.AnimationTime = tk.TimestepValues[5]
tk.Time = tk.TimestepValues[5]
# Merge blocks
merge = MergeBlocks()
# Annotation filter
annotation = PythonAnnotation()
annotation.Expression = '"%f %f %f" % (XMOM[t_index], YMOM[t_index], ZMOM[t_index])'
annotation.UpdatePipeline()
Show()
# Update time and trigger pipeline execution
tk.Time = tk.TimestepValues[5]
Render()
annotation.SMProxy.UpdatePropertyInformation()
value = annotation.SMProxy.GetProperty('AnnotationValue').GetElement(0)
expected = "0.012132 0.001378 -1158.252808"
if ( value != expected):
errors += 1
print "Error Invalid active connection. Expected ", expected, " and got ", value
# Update time and trigger pipeline execution
tk.Time = tk.TimestepValues[7]
Render()
annotation.SMProxy.UpdatePropertyInformation()
value = annotation.SMProxy.GetProperty('AnnotationValue').GetElement(0)
expected = "0.013970 0.001319 -1141.020020"
if ( value != expected):
errors += 1
print "Error Invalid active connection. Expected ", expected, " and got ", value
# Check time infos
annotation.Expression = '"%i %f %s" % (t_index, t_value, str(t_range))'
annotation.UpdatePipeline()
# Update time and trigger pipeline execution
tk.Time = tk.TimestepValues[7]
Render()
annotation.SMProxy.UpdatePropertyInformation()
value = annotation.SMProxy.GetProperty('AnnotationValue').GetElement(0)
expected = "7 0.000700 [0, 0.00429999]"
if ( value != expected):
errors += 1
print "Error Invalid active connection. Expected ", expected, " and got ", value
# Update time and trigger pipeline execution
tk.Time = tk.TimestepValues[27]
Render()
annotation.SMProxy.UpdatePropertyInformation()
value = annotation.SMProxy.GetProperty('AnnotationValue').GetElement(0)
expected = "27 0.002700 [0, 0.00429999]"
if ( value != expected):
errors += 1
print "Error Invalid active connection. Expected ", expected, " and got ", value
# Update time and trigger pipeline execution
tk.Time = tk.TimestepValues[len(tk.TimestepValues)-1]
Render()
annotation.SMProxy.UpdatePropertyInformation()
value = annotation.SMProxy.GetProperty('AnnotationValue').GetElement(0)
expected = "43 0.004300 [0, 0.00429999]"
if ( value != expected):
errors += 1
print "Error Invalid active connection. Expected ", expected, " and got ", value
# Disconnect and quit application...
Disconnect()
if errors > 0:
raise RuntimeError, "An error occured during the execution"
......@@ -144,6 +144,7 @@ IF(PARAVIEW_ENABLE_PYTHON)
vtkPythonCalculator.cxx
vtkPythonProgrammableFilter.cxx
vtkPythonExtractSelection.cxx
vtkPythonAnnotationFilter.cxx
)
SET (KIT_LIBS ${KIT_LIBS} ${PYTHON_LIBRARIES} vtkPVPythonInterpretor)
INCLUDE_DIRECTORIES(
......
/*=========================================================================
Program: ParaView
Module: vtkPythonAnnotationFilter.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 "vtkPythonAnnotationFilter.h"
#include "vtkDataObjectTypes.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPVPythonInterpretor.h"
#include "vtkPythonProgrammableFilter.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include <assert.h>
#include <map>
#include <vector>
#include <vtksys/ios/sstream>
vtkStandardNewMacro(vtkPythonAnnotationFilter);
//----------------------------------------------------------------------------
vtkPythonAnnotationFilter::vtkPythonAnnotationFilter()
{
this->SetNumberOfInputPorts(1);
this->AnnotationValue = 0;
this->PythonExpression = 0;
this->TimeInformations = 0;
}
//----------------------------------------------------------------------------
vtkPythonAnnotationFilter::~vtkPythonAnnotationFilter()
{
this->SetTimeInformations(0);
this->SetPythonExpression(0);
this->SetAnnotationValue(0);
}
//----------------------------------------------------------------------------
int vtkPythonAnnotationFilter::RequestData(
vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
// Meta-data
vtkDataObject* input = vtkDataObject::GetData(inputVector[0]);
vtkInformation* inputInfo = input ? input->GetInformation() : 0;
vtkInformation* outInfo = this->GetExecutive()->GetOutputInformation(0);
// Extract time informations
vtksys_ios::ostringstream timeInfo;
if(inputInfo)
{
timeInfo << ",";
// Time
if(inputInfo->Has(vtkDataObject::DATA_TIME_STEPS()))
{
double time = inputInfo->Get(vtkDataObject::DATA_TIME_STEPS())[0];
timeInfo << time << ", ";
}
else
{
timeInfo << "0" << ", ";
}
// TimeSteps
if(outInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()))
{
const double* timeSteps =
outInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
int len = outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
timeInfo << "[";
for(int i=0; i < len; i++)
{
timeInfo << timeSteps[i] << ", ";
}
timeInfo << "], ";
}
else
{
timeInfo << "[0, 1], ";
}
// TimeRange
if(outInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_RANGE()))
{
double range[2];
outInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), range);
timeInfo << "[" << range[0] << ", " << range[1] << "]";
}
else
{
timeInfo << "[0, 1]";
}
}
this->SetTimeInformations(timeInfo.str().c_str());
// Execute the python script to process and generate the annotation
this->EvaluateExpression();
// Make sure a valid AnnotationValue is available
if(this->AnnotationValue == NULL || strlen(this->AnnotationValue) == 0)
{
this->SetAnnotationValue("Write a python expression like: 'Time index: %i' % t_index");
}
// Update the output data
vtkStringArray* data = vtkStringArray::New();
data->SetName("Text");
data->SetNumberOfComponents(1);
data->InsertNextValue(this->AnnotationValue);
vtkTable* output = vtkTable::GetData(outputVector);
output->AddColumn(data);
data->FastDelete();
return 1;
}
//----------------------------------------------------------------------------
int vtkPythonAnnotationFilter::FillInputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject");
return 1;
}
//----------------------------------------------------------------------------
void vtkPythonAnnotationFilter::EvaluateExpression()
{
// Set self to point to this
char addrofthis[1024];
sprintf(addrofthis, "%p", this);
char *aplus = addrofthis;
if ((addrofthis[0] == '0') &&
((addrofthis[1] == 'x') || addrofthis[1] == 'X'))
{
aplus += 2; //skip over "0x"
}
vtksys_ios::ostringstream stream;
stream << "import paraview" << endl
<< "paraview.fromFilter = True" << endl
<< "from paraview import annotation as pv_ann" << endl
<< "me = paraview.servermanager.vtkPythonAnnotationFilter('" << aplus << " ')" << endl
<< "pv_ann.ComputeAnnotation(me, me.GetInputDataObject(0, 0), me.GetPythonExpression()"
<< this->TimeInformations << ")" << endl
<< "del me" << endl;
vtkPythonProgrammableFilter::GetGlobalPipelineInterpretor()->RunSimpleString(
stream.str().c_str());
vtkPythonProgrammableFilter::GetGlobalPipelineInterpretor()->FlushMessages();
}
//----------------------------------------------------------------------------
void vtkPythonAnnotationFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: ParaView
Module: vtkPythonAnnotationFilter.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 vtkPythonAnnotationFilter
// .SECTION Description
// This filter allow the user to write an expression that can be use to
// extract any field information and represent the result as a text annotation
// in the 3D view
#ifndef __vtkPythonAnnotationFilter_h
#define __vtkPythonAnnotationFilter_h
#include "vtkTableAlgorithm.h"
class VTK_EXPORT vtkPythonAnnotationFilter : public vtkTableAlgorithm
{
public:
static vtkPythonAnnotationFilter* New();
vtkTypeMacro(vtkPythonAnnotationFilter, vtkTableAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Allow the user to customize the output annotation based on some arbitrary
// content processing
//
// Here is the set of preset variable available to you when you write your
// expression.
// - input
// - input.PointData['myArray']
// - input.CellData['myArray']
// - input.FieldData['myArray']
// - t_value
// - t_steps
// - t_range
// - t_index
//
// Here is a set of common expressions:
// - "Momentum %s" % str(Momentum[available_timesteps.index(provided_time)])
//
vtkSetStringMacro(PythonExpression);
vtkGetStringMacro(PythonExpression);
// Description:
// Set the value that is going to be printed to the output
vtkSetStringMacro(AnnotationValue);
vtkGetStringMacro(AnnotationValue);
//BTX
protected:
vtkPythonAnnotationFilter();
~vtkPythonAnnotationFilter();
virtual int FillInputPortInformation(int port, vtkInformation* info);
virtual int RequestData(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
// Description:
// For internal use only.
void EvaluateExpression();
char* AnnotationValue;
char* PythonExpression;
// Used internally to store time informations for Python
vtkSetStringMacro(TimeInformations);
char* TimeInformations;
private:
vtkPythonAnnotationFilter(const vtkPythonAnnotationFilter&); // Not implemented
void operator=(const vtkPythonAnnotationFilter&); // Not implemented
// Description:
// For internal use only.
static void ExecuteScript(void *);
//ETX
};
#endif
......@@ -87,6 +87,71 @@
<!-- End PythonCalculator -->
</SourceProxy>
<SourceProxy name="PythonAnnotation"
class="vtkPythonAnnotationFilter"
label="Python Annotation">
<Documentation
long_help="This filter evaluates a Python expression for a text annotation"
short_help="Evaluates a Python expression for a text annotation">
This filter uses Python to calculate an expression.
It depends heavily on the numpy and paraview.vtk modules.
To use the parallel functions, mpi4py is also necessary. The expression
is evaluated and the resulting scalar value or numpy array is added
to the output as an array. See numpy and paraview.vtk documentation
for the list of available functions.
This filter tries to make it easy for the user to write expressions
by defining certain variables. The filter tries to assign each array
to a variable of the same name. If the name of the array is not a
valid Python variable, it has to be accessed through a dictionary called
arrays (i.e. arrays['array_name']). The points can be accessed using the
points variable.
</Documentation>
<InputProperty
name="Input"
command="AddInputConnection"
clean_command="RemoveAllInputs"
multiple_input="1">
<ProxyGroupDomain name="groups">
<Group name="sources"/>
<Group name="filters"/>
</ProxyGroupDomain>
<DataTypeDomain name="input_type">
<DataType value="vtkDataSet"/>
</DataTypeDomain>
<Documentation>
Set the input of the filter.
</Documentation>
</InputProperty>
<StringVectorProperty
name="Expression"
command="SetPythonExpression"
number_of_elements="1">
<Documentation>
The Python expression evaluated during execution. FieldData arrays are direclty available through their name.
Set of provided variables [input, t_value, t_steps, t_range, t_index, FieldData, PointData, CellData]
(i.e.: "Momentum: (%f, %f, %f)" % (XMOM[t_index,0], YMOM[t_index,0], ZMOM[t_index,0]) )
</Documentation>
</StringVectorProperty>
<StringVectorProperty
name="AnnotationValue"
command="GetAnnotationValue"
information_only="1" >
<Documentation>
Text that is used as annotation
</Documentation>
</StringVectorProperty>
<Hints>
<Visibility replace_input="0" />
<OutputPort name="Output-0" index="0" type="text" />
</Hints>
<!-- End PythonAnnotation -->
</SourceProxy>
<SourceProxy name="ProgrammableFilter"
class="vtkPythonProgrammableFilter"
label="Programmable Filter">
......
......@@ -102,6 +102,7 @@ IF (PARAVIEW_ENABLE_PYTHON)
pvfilters
pvvtkextensions
extract_selection
annotation
)
# Now copy these files if necessary.
......
#==============================================================================
#
# 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.
"""
import paraview
from paraview import vtk
from paraview.vtk import dataset_adapter
from numpy import *
from paraview.vtk.algorithms import *
from paraview import servermanager
if servermanager.progressObserverTag:
servermanager.ToggleProgressPrinting()
def __vtk_in1d(a, b):
return array([item in b for item in a])
try:
contains = in1d
except NameError:
# older versions of numpy don't have in1d function.
# in1d was introduced in numpy 1.4.0.
contains = __vtk_in1d
def ComputeAnnotation(self, inputDS, expression, t_value = 0, t_steps = [0,1], t_range = [0,1]):
# init input object
input = dataset_adapter.WrapDataObject(inputDS)
# Add Fields names inside current namespace
numberOfFields = input.GetFieldData().GetNumberOfArrays()
for index in xrange(numberOfFields):
fieldName = input.GetFieldData().GetArray(index).GetName()
exec("%s = input.FieldData['%s']" % (fieldName, fieldName))
# Add time informations in current namespace
t_index = 0
try:
t_index = t_steps.index(t_value)
except:
pass
# Add extra naming
time_value = t_value
time_steps = t_steps
time_range = t_range
time_index = t_index
# Evaluate expression
exec("outputText = str(" + expression + ")")
self.SetAnnotationValue(outputText)
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