Commit 797ae3a1 authored by Cory Quammen's avatar Cory Quammen

Added Python view that enables plotting data with matplotlib

This view is compiled only if Python is enabled.

The Python view accepts a Python script that can be used to plot
data in a matplotlib figure. The script must contain two functions
described below:

- setup_data(view)

  The setup_data function supplies the current Python view as an
  argument. This is the native VTK object on which all methods that
  have been wrapped in Python may be called. The Python view supplies
  some methods that can be used to select which data arrays to
  transfer from the server side to the client side (all rendering is
  performed on the client). No arrays are selected by default.

- render(view, figure):

  The render function supplies the current Python view as the first
  argument and a matplotlib FigureCanvasAgg as the second argument.
  The render function is typically expected to create one or more
  subplots in the figure that will be used for rendering.

The functions setup_data and render may be defined in the script
(e.g., when defined through the GUI settings for the Python View) or
in the global Python interpreter (e.g. when defined in a script run by
pvpython). They are invoked when needed by the Python view when
rendering is needed.

Removed unused saveImage() method from various views.

Updated VTK to origin/master

Change-Id: I882fa8eeacc81e8120762bf1312f568523559b09
parent 8bab4fd9
......@@ -13,10 +13,22 @@ if (PARAVIEW_DATA_ROOT)
--enable-bt
--data=${PARAVIEW_DATA_ROOT}/Data/can.ex2
${CMAKE_CURRENT_SOURCE_DIR}/TestPythonAnnotationFilterNoMerge.py)
set_tests_properties(
pvpython.TestPythonAnnotationFilter
pvpython.TestPythonAnnotationFilterNoMerge
PROPERTIES LABELS "PARAVIEW")
if (PARAVIEW_ENABLE_MATPLOTLIB AND PYTHON_MODULE_matplotlib_FOUND)
add_test(NAME pvpython.TestPythonView
COMMAND pvpython
--enable-bt
${CMAKE_CURRENT_SOURCE_DIR}/TestPythonView.py)
set_tests_properties(
pvpython.TestPythonView
PROPERTIES LABELS "PARAVIEW")
endif()
endif()
# these tests could run safely in serial and
......
# Set up a basic scene for rendering.
from paraview.simple import *
import sys
script = """
import paraview.numpy_support
# Utility to get next color
def getNextColor():
colors = 'bgrcmykw'
for c in colors:
yield c
# This function must be defined. It is where specific data arrays are requested.
def setup_data(view):
print "Setting up data"
# This function must be defined. It is where the actual rendering commands for matplotlib go.
def render(view,figure):
ax = figure.add_subplot(111)
ax.hold = True
numObjects = view.GetNumberOfVisibleDataObjects()
print "num visible objects: ", numObjects
for i, color in zip(xrange(0,numObjects), getNextColor()):
dataObject = view.GetVisibleDataObjectForRendering(i)
if dataObject:
vtk_points = dataObject.GetPoints()
if vtk_points:
vtk_points_data = vtk_points.GetData()
pts = paraview.numpy_support.vtk_to_numpy(vtk_points_data)
x, y = pts[:,0], pts[:,1]
ax.scatter(x, y, color=color)
ax.hold = False
"""
if len(sys.argv) > 2:
server = sys.argv[2]
if not Connect(server):
print "Could not connect to server", server
view = CreateView("PythonView")
view.Script = script
cone = Cone()
Show(cone, view)
sphere = Sphere()
Show(sphere, view)
Render()
WriteImage("pvpython.png", view)
Delete(cone)
del cone
Delete(sphere)
del sphere
......@@ -166,6 +166,9 @@ if(PARAVIEW_ENABLE_PYTHON)
${TESTS_WITH_BASELINES}
${CMAKE_CURRENT_SOURCE_DIR}/SelectionLabels.xml
)
if (PARAVIEW_ENABLE_MATPLOTLIB AND PYTHON_MODULE_matplotlib_FOUND)
list(APPEND TESTS_WITH_BASELINES ${CMAKE_CURRENT_SOURCE_DIR}/TestPythonView.xml)
endif()
endif()
#------------------------------------------------------------------------------
......
This diff is collapsed.
......@@ -23,7 +23,6 @@ public:
~MyView();
/// don't support save images
bool saveImage(int, int, const QString& ) { return false; }
vtkImageData* captureImage(int) { return NULL; }
vtkImageData* captureImage(const QSize&) { return NULL; }
......
......@@ -94,6 +94,14 @@ set (Module_SRCS
vtkXYChartRepresentation.cxx
)
if (PARAVIEW_ENABLE_PYTHON AND PARAVIEW_ENABLE_MATPLOTLIB)
list(APPEND Module_SRCS
vtkMatplotlibUtilities.cxx
vtkPythonRepresentation.cxx
vtkPythonView.cxx)
endif()
if (PARAVIEW_USE_ICE_T)
list(APPEND Module_SRCS
vtkIceTSynchronizedRenderers.cxx)
......
......@@ -10,6 +10,7 @@ vtk_module(vtkPVClientServerCoreRendering
vtkDomainsChemistry
vtkFiltersAMR
vtkPVClientServerCoreCore
vtkPVVTKExtensionsDefault
vtkPVVTKExtensionsRendering
vtkWebGLExporter
vtkRenderingLabel
......
/*=========================================================================
Program: ParaView
Module: vtkMatplotlibUtilities.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 vtkMatplotlibUtilities
// .SECTION Description
// vtkMatplotlibUtilities is a utility class for generating vtkImageData objects from
// a matplotlib script. It requires that Python and matplotlib be
// available on your system.
#ifndef __vtkMatplotlibUtilities_h
#define __vtkMatplotlibUtilities_h
#include "vtkPVClientServerCoreRenderingModule.h" //needed for exports
#include "vtkObject.h"
struct _object;
typedef struct _object PyObject;
class vtkImageData;
class vtkPythonInterpreter;
class VTKPVCLIENTSERVERCORERENDERING_EXPORT vtkMatplotlibUtilities : public vtkObject
{
public:
static vtkMatplotlibUtilities* New();
vtkTypeMacro(vtkMatplotlibUtilities, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
// Renders a matplotlib plot to a VTK image. The Python script
// defines a canvas (must be a matplotlib.backends.backend_agg.FigureCanvasAgg)
// to which a plot is rendered. The resulting vtkImageData is returned.
vtkImageData* ImageFromScript(const char* script, const char* canvasName,
int width, int height);
protected:
vtkMatplotlibUtilities();
virtual ~vtkMatplotlibUtilities();
vtkPythonInterpreter* Interpreter;
// Used for runtime checking of matplotlib's mathtext availability.
enum Availability
{
NOT_TESTED = 0,
AVAILABLE,
UNAVAILABLE
};
// Function used to check matplotlib availability and update MatplotlibAvailable.
// This will do tests only the first time this method is called.
static void CheckMatplotlibAvailability();
// Initialize matplotlib. This loads the matplotlib module into the python interpreter.
bool InitializeMatplotlib();
// Sets up a matplotlib canvas and figure object
void InitializeCanvas(const char* canvasName);
// Destroys matplotlib canvas and figure object
void DestroyCanvas(const char* canvasName);
// Determine the DPI (matplotlib lies about DPI, so we need to figure it out).
bool DetermineDPI();
// Cleanup and destroy any python objects. This is called during destructor as
// well as when the Python interpreter is finalized. Thus this class must
// handle the case where the internal python objects disappear between calls.
void CleanupPythonObjects();
// Check for errors in Python
bool CheckForPythonError(PyObject* object);
bool CheckForPythonError();
// Get a vtkImageData object from a named matplotlib canvas. The
// caller must call Delete() on the returned value when finished with it.
vtkImageData* ImageFromCanvas(const char* canvasName);
private:
vtkMatplotlibUtilities(const vtkMatplotlibUtilities&); // Not implemented.
void operator=(const vtkMatplotlibUtilities&); // Not implemented.
static Availability MatplotlibAvailable;
int DPI;
};
#endif // __vtkMatplotlibUtilities_h
/*=========================================================================
Program: ParaView
Module: vtkPythonRepresentation.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 vtkPythonRepresentation
// .SECTION Description
// Representation for showing data in a vtkPythonView. This representation
// does not create any intermediate data for display. Instead, it simply
// fetches data from the server.
#ifndef __vtkPythonRepresentation_h
#define __vtkPythonRepresentation_h
#include "vtkPVDataRepresentation.h"
#include "vtkPVClientServerCoreRenderingModule.h" //needed for exports
class vtkReductionFilter;
class VTKPVCLIENTSERVERCORERENDERING_EXPORT vtkPythonRepresentation : public vtkPVDataRepresentation
{
public:
static vtkPythonRepresentation* New();
vtkTypeMacro(vtkPythonRepresentation, vtkPVDataRepresentation);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// vtkAlgorithm::ProcessRequest() equivalent for rendering passes. This is
// typically called by the vtkView to request meta-data from the
// representations or ask them to perform certain tasks e.g.
// PrepareForRendering.
// Overridden to skip processing when visibility if off.
virtual int ProcessViewRequest(vtkInformationRequestKey* request_type,
vtkInformation* inInfo,
vtkInformation* outInfo);
// Description:
// Gets local copy of the input. This will be NULL on the client when running in client-only
// mode until after Update() is called.
vtkGetMacro(LocalInput, vtkDataObject*);
// Description:
// Gets the client's copy of the input
vtkGetMacro(ClientDataObject, vtkDataObject*);
// Description:
// Get number of arrays in an attribute (e.g., vtkDataObject::POINT,
// vtkDataObject::CELL, vtkDataObject::ROW, vtkDataObject::FIELD_DATA).
int GetNumberOfAttributeArrays(int attributeType);
// Description:
// From the input data, get the name of attribute array at index for
// the given attribute type.
const char* GetAttributeArrayName(int attributeType, int arrayIndex);
// Description:
// Set the array status for the input data object. A
// status of 1 means that the array with the given name for the
// given attribute will be copied to the client. A status of 0 means
// the array will not be copied to the client. The status is 0 by
// default.
void SetAttributeArrayStatus(int attributeType, const char* name, int status);
// Description:
// Get the status indicating whether the array with the given name
// and attribute type in the input will be copied to the
// client. Status is 0 by default.
int GetAttributeArrayStatus( int attributeType, const char* name);
// Description:
// Disable all arrays. When called, no arrays will be transferred to the client
// until GetAttributeArrayStatus() is called.
void DisableAllAttributeArrays();
//BTX
protected:
vtkPythonRepresentation();
~vtkPythonRepresentation();
// Description:
// Overridden to make input optional.
int FillInputPortInformation(int port, vtkInformation* info);
// Description:
// Overridden to copy data from the server to the client
int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
private:
vtkPythonRepresentation(const vtkPythonRepresentation&); // Not implemented
void operator=(const vtkPythonRepresentation&); // Not implemented
//ETX
// Description:
// Local input for each processor.
vtkDataObject* LocalInput;
// Description:
// Data object located on the client.
vtkDataObject* ClientDataObject;
// Description:
// Internal data for the representation.
class vtkPythonRepresentationInternal;
vtkPythonRepresentationInternal* Internal;
//BTX
// Description:
// Sets the pre-gather helper on the reduction filter based on the
// data object
void InitializePreGatherHelper(vtkReductionFilter* reductionFilter, vtkDataObject* input);
// Description:
// Sets the post-gather helper on the reduction filter based on the
// data object
void InitializePostGatherHelper(vtkReductionFilter* reductionFilter, vtkDataObject* input);
// Description:
// Query whether this process has a particular role.
bool HasProcessRole(vtkTypeUInt32 role);
// Description:
// Query whether this process is a client
bool IsClientProcess();
// Description:
// Query whether this process is a data server
bool IsDataServerProcess();
// Description:
// Sends the data type from the root node of the server to the client
int SendDataTypeToClient(int & dataType);
// Description:
// Transfers local data from the server nodes to the client.
void TransferLocalDataToClient();
//ETX
};
#endif // __vtkPythonRepresentation_h
This diff is collapsed.
/*=========================================================================
Program: ParaView
Module: vtkPythonView.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 vtkPythonView
// .SECTION Description
// vtkPythonView is a view for displaying data via a Python script
// that uses matplotlib to generate a plot.
#ifndef __vtkPythonView_h
#define __vtkPythonView_h
#include "vtkPVView.h"
#include "vtkPVClientServerCoreRenderingModule.h" //needed for exports
#include "vtkSmartPointer.h" //needed for member variables
class vtkImageData;
class vtkInformationRequestKey;
class vtkMatplotlibUtilities;
class vtkPythonRepresentation;
class vtkRenderer;
class vtkRenderWindow;
class vtkTexture;
struct _object;
typedef struct _object PyObject;
class VTKPVCLIENTSERVERCORERENDERING_EXPORT vtkPythonView : public vtkPVView
{
public:
static vtkPythonView* New();
vtkTypeMacro(vtkPythonView, vtkPVView);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// This is a pass for delivering data from the server nodes to the client.
static vtkInformationRequestKey* REQUEST_DELIVER_DATA_TO_CLIENT();
// Description:
// Overrides the base class method to request an addition pass that moves data from the
// server to the client.
virtual void Update();
// Description:
// Gets the renderer for this view.
virtual vtkRenderer* GetRenderer();
// Sets the renderer for this view.
virtual void SetRenderer(vtkRenderer* ren);
// Description:
// Get a handle to the render window.
virtual vtkRenderWindow* GetRenderWindow();
// Description:
// Set the render window for this view. Note that this requires special
// handling in order to do correctly - see the notes in the detailed
// description of vtkRenderViewBase.
virtual void SetRenderWindow(vtkRenderWindow *win);
// Description:
// Get/Set the Python script.
vtkSetStringMacro(Script);
vtkGetStringMacro(Script);
// Description:
// Magnification is needed to inform matplotlib of the requested size of the plot
vtkSetMacro(Magnification, int);
vtkGetMacro(Magnification, int);
// Description:
// Gets the number of visible data objects in the view.
int GetNumberOfVisibleDataObjects();
// Description:
// Get the representation for the visible data object at the given index.
vtkPythonRepresentation* GetVisibleRepresentation(int visibleObjectIndex);
// Description:
// Get a local copy of the visible data object at an index. The
// index must be between 0 and this->GetNumberOfVisibleDataObjects().
// If outside this range, returns NULL. This will return a shallow
// copy of the data object input to the representation.
//
// WARNING: this method is intended to be called only from within
// the setup_data() function in the Python Script set for this instance.
vtkDataObject* GetVisibleDataObjectForSetup(int visibleObjectIndex);
// Description:
// Get the client's copy of the visible data object at an index. The
// index must be between 0 and this->GetNumberOfVisibleDataObjects().
// If outside this range, returns NULL.
//
// WARNING: this method should be called only from within the render()
// function in the Python Script set for this instance.
vtkDataObject* GetVisibleDataObjectForRendering(int visibleObjectIndex);
// Description:
// Get number of arrays in an attribute (e.g., vtkDataObject::POINT,
// vtkDataObject::CELL, vtkDataObject::ROW, vtkDataObject::FIELD_DATA)
// for the visible object at the given index.
int GetNumberOfAttributeArrays(int visibleObjectIndex, int attributeType);
// Description:
// From the visible object at the given index, get the name of
// attribute array at index for the given attribute type.
const char* GetAttributeArrayName(int visibleObjectIndex,
int attributeType,
int arrayIndex);
// Description:
// Set the array status for the visible object at the given index. A
// status of 1 means that the array with the given name for the
// given attribute will be copied to the client. A status of 0 means
// the array will not be copied to the client. The status is 0 by
// default.
void SetAttributeArrayStatus(int visibleObjectIndex,
int attributeType,
const char* name,
int status);
// Description:
// Get the status indicating whether the array with the given name
// and attribute type in the visible object will be copied to the
// client. Status is 0 by default.
int GetAttributeArrayStatus(int visibleObjectIndex,
int attributeType,
const char* name);
// Description:
// Disable all attribute arrays.
void DisableAllAttributeArrays();
virtual void StillRender();
virtual void InteractiveRender();
//BTX
protected:
vtkPythonView();
virtual ~vtkPythonView();
vtkSmartPointer<vtkTexture> RenderTexture;
vtkSmartPointer<vtkRenderer> Renderer;
vtkSmartPointer<vtkRenderWindow> RenderWindow;
// Needed to handle rendering at different magnifications
int Magnification;
vtkSmartPointer<vtkMatplotlibUtilities> MatplotlibUtilities;
vtkImageData* GenerateImage();
// Description:
// Is local data available?
bool IsLocalDataAvailable();
private:
vtkPythonView(const vtkPythonView&); // Not implemented
void operator=(const vtkPythonView&); // Not implemented
//ETX
char * Script;
};
#endif
......@@ -60,5 +60,9 @@ set (Module_SRCS
vtkSMWidgetRepresentationProxy.cxx
)
if (PARAVIEW_ENABLE_PYTHON AND PARAVIEW_ENABLE_MATPLOTLIB)
list(APPEND Module_SRCS vtkSMPythonViewProxy.cxx)
endif()
vtk_module_library(vtkPVServerManagerRendering
${Module_SRCS})
/*=========================================================================
Program: ParaView
Module: vtkSMPythonViewProxy.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 "vtkSMPythonViewProxy.h"
#include "vtkClientServerStream.h"
#include "vtkDataArray.h"
#include "vtkMultiProcessController.h"
#include "vtkObjectFactory.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkPointData.h"
#include "vtkProcessModule.h"
#include "vtkPythonView.h"
#include "vtkWindowToImageFilter.h"
vtkStandardNewMacro(vtkSMPythonViewProxy);
//----------------------------------------------------------------------------
vtkSMPythonViewProxy::vtkSMPythonViewProxy()
{
}
//----------------------------------------------------------------------------
vtkSMPythonViewProxy::~vtkSMPythonViewProxy()
{
}
//----------------------------------------------------------------------------
vtkRenderer* vtkSMPythonViewProxy::GetRenderer()
{
this->CreateVTKObjects();
vtkPythonView* pv = vtkPythonView::SafeDownCast(
this->GetClientSideObject());
return pv ? pv->GetRenderer() : NULL;
}
//----------------------------------------------------------------------------
vtkRenderWindow* vtkSMPythonViewProxy::GetRenderWindow()
{
this->CreateVTKObjects();
vtkPythonView* pv = vtkPythonView::SafeDownCast(
this->GetClientSideObject());
return pv ? pv->GetRenderWindow() : NULL;
}
//----------------------------------------------------------------------------
bool vtkSMPythonViewProxy::LastRenderWasInteractive()
{
return false;
}
//----------------------------------------------------------------------------
vtkImageData * vtkSMPythonViewProxy::CaptureWindowInternal(int magnification)
{
this->GetRenderWindow()->SwapBuffersOff();
this->CreateVTKObjects();
vtkPythonView* pv = vtkPythonView::SafeDownCast(
this->GetClientSideObject());
if (pv)
{
pv->SetMagnification(magnification);
}
this->StillRender();
if (pv)
{
pv->SetMagnification(1);
}
vtkSmartPointer<vtkWindowToImageFilter> w2i =
vtkSmartPointer<vtkWindowToImageFilter>::New();
w2i->SetInput(this->GetRenderWindow());
w2i->SetMagnification(magnification);
w2i->ReadFrontBufferOff();
w2i->ShouldRerenderOff();
w2i->FixBoundaryOn();
// BUG #8715: We go through this indirection since the active connection needs
// to be set during update since it may request re-renders if magnification >1.
vtkClientServerStream stream;
stream << vtkClientServerStream::Invoke
<< w2i.GetPointer() << "Update"
<< vtkClientServerStream::End;
this->ExecuteStream(stream, false, vtkProcessModule::CLIENT);
this->GetRenderWindow()->SwapBuffersOn();
vtkImageData* capture = vtkImageData::New();
capture->ShallowCopy(w2i->GetOutput());
this->GetRenderWindow()->Frame();
return capture;
}
//----------------------------------------------------------------------------
void vtkSMPythonViewProxy::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: ParaView
Module: vtkSMViewProxy.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 vtkSMPythonViewProxy - Superclass for all view proxies
// .SECTION Description
// vtkSMPythonViewProxy is a view proxy for the vtkPythonView.