Python API
From InfovisWiki
Contents |
Overview
Because Titan is built upon VTK, it inherits the existing infrastructure for automatically "wrapping" classes to produce bindings for languages other than C++. Thus, Titan automatically has a Python binding "for free". Although this capability has existed from the start, we are only just beginning to exercise it. This page provides a simple "how to" to get started programming Titan in Python. Keep in mind that similar bindings are available for TCL and Java (although they're similarly untested).
Useful Python Language Resources
There are many useful tutorials and reference guides available for the Python language. The O'Reilly printed books such as Learning Python, Python in a Nutshell, and Python Cookbook are useful.
There are also many online books and guides available as well.
- http://www.python.org/doc - The documentation page at the official Python site.
- http://pydoc.org - Very useful reference site. Provides language references broken down by Python version. The Index of Library Modules links offer Doxygen like online class references.
- http://diveintopython.org - free online book, can be downloaded as a pdf or viewed online. Has not been updated since 2004, so it's a bit dated but the examples are nice and explained in good detail for the beginner.
- http://www.python.org/dev/peps/pep-0008/ - Style guide
- http://aspn.activestate.com/ASPN/Python/Cookbook/ - lots of examples and sample codes.
Building Titan/Python
To use Titan in Python, you'll need to ensure that you have a VTK build with infovis and Python-wrapping enabled:
- Set VTK_USE_BOOST "ON".
- Set VTK_USE_INFOVIS "ON".
- Set VTK_WRAP_PYTHON "ON".
- Optional: For database support, set VTK_USE_MYSQL "ON".
- Build VTK.
Note for ParaView developers: the ParaView build does not generate Python wrappers for the infovis libraries; currently, you will need to download and build VTK separately if you wish to use Titan/Python.
Building vtkSNL/Python
Most Titan components are staged in the vtkSNL repository during development, then moved into VTK when ready for production. For a variety of reasons, some components never make the "jump" from vtkSNL to VTK. As a consequence, many Titan/Python users will wish to build the vtkSNL repository with Python-wrapping:
- Point VTK_DIR to a VTK build with Python-wrapping enabled (described above).
- Set VTKSNL_WRAP_PYTHON "ON".
- To use the Multi-Threaded Graph Library (MTGL) algorithms, set VTKSNL_USE_MTGL "ON".
- You will need to obtain the MTGL sources from svn+ssh://software.sandia.gov/svn/private/mtgl/trunk. Contact Jon Berry for access.
- Build vtkSNL.
Note for ThreatView developers: when you build vtkSNL against a ParaView build (required for ThreatView), the VTKSNL_WRAP_PYTHON option will not be available. Currently, you must build vtkNSL against a "vanilla" VTK to use vtkSNL/Python.
Installing PyQt (Advanced not necessary at first)
There are many graphical user interface toolkits available for Python, and any can be combined with the Titan / Python components in a script. That said, a significant amount of VTK-related development relies on the Trolltech Qt libraries for cross-platform GUI development. For this reason, we recommend PyQt (http://www.riverbankcomputing.co.uk/pyqt/index.php) as the basis for writing Titan / Python scripts with graphical user interfaces. Note that you can download and use the GPL'd version of PyQt iff you are using the GPL'd version of Qt. Similarly, if you are using a paid commercial version of Qt for development, you must purchase a commercial license for PyQt.
Executing Titan/Python Scripts
Setting up the Python Environment
Python needs to know where to find the VTK and vtkSNL libraries. Basically, this means making Python aware of the path to both the VTK and vtkSNL libraries and Python wrappers.
Windows
In Windows the paths to the Python wrappers and compiled libraries must be added to your PYTHONPATH for both VTK and vtkSNL. The following steps should result in four paths being included in your PYTHONPATH:
First, make python aware of VTK:
- Python Wrappers:
- Add <VTK build directory>\Wrapping\Python to your PYTHONPATH
- VTK Libraries (choose Debug or release)
- Debug build:
- Add <VTK build directory>\bin\Debug to your PYTHONPATH
- Release build:
- Add <VTK build directory>\bin\release to your PYTHONPATH
- Debug build:
Next, do the same thing for vtkSNL:
- Python Wrappers:
- Add <vtkSNL build directory>\Wrapping\Python to your PYTHONPATH
- vtkSNL Libraries (choose Debug or release):
- Debug build:
- Add <vtkSNL build directory>\bin\Debug to your PYTHONPATH
- Release build:
- Add <vtkSNL build directory>\bin\release to your PYTHONPATH
- Debug build:
Linux/Mac OSX
Linux and Mac OSX systems don't have the debug/release distinction that the windows build environment has. Here, we just add the VTK/vtkSNL bin and wrapper directories to the PYTHONPATH environment variable. The PYTHONPATH variable is a comma-separated (:) list of paths and might be set in cshell in the following manner:
$ setenv PYTHONPATH "path1:path2:path3:path4"
The following steps will add four paths to your PYTHONPATH.
First, add the VTK paths:
- Python Wrappers:
- Add <VTK build directory>/Wrapping/Python to PYTHONPATH
- VTK compiled libraries:
- Add <VTL build directory>/bin to PYTHONPATH
Next, add the vtkSNL paths:
- Python Wrappers:
- Add <vtkSNL build directory>/Wrapping/Python to PYTHONPATH
- vtkSNL compiled libraries:
- Add <vtkSNL build directory>/bin to PYTHONPATH
Troubleshooting the Python Environment
A situation may occur on Linux in which the Python interpreter complains that it cannot locate the libvtkCommonPythonD.so.x.x file. This can happen when the system cannot find the proper library file in its search path. If this occurs, try adding the following to your .cshrc file (if using CSHELL).
if (! $?LD_LIBRARY_PATH ) then
setenv LD_LIBRARY_PATH "<path to vtk build dir>/bin"
else
setenv LD_LIBRARY_PATH "<path to vtk build dir>/bin:$LD_LIBRARY_PATH"
endif
Executing Scripts
Once the environment is set, there are multiple mechanisms to execute Titan code from within Python:
- All Platforms: You can run the normal python binary without arguments, starting an interactive interpreter where you can import the VTK and vtkSNL modules, enter commands, and inspect objects manually - extremely useful for interactive experimentation and learning.
- All Platforms: You can run the normal python binary with a single filename argument, executing the given script file.
- All Platforms: If you pass the -i argument to python when running a script, it will enter the interactive interpreter after the script completes, allowing you to inspect objects created by the script, debug errors, etc. For example:
$ python -i my_buggy_script.py
- Mac OSX: On this platform, VTK windows do not receive a titlebar from the window manager by default, making it difficult to terminate a script. To avoid this issue, substitute the vtkpython binary for the normal python binary.
VTK Examples
The following examples use only Titan components that are part of VTK.
Note: these files can be found in the VTK/Examples/Infovis/Python directory:
hello_world.py
|
The following code provides a minimalist introduction to Titan/Python ... a random graph source is connected to a graph view and displayed in a window. You may use a mouse to interact with the window contents, selecting with the left mouse button and zooming the display with the right mouse button: from vtk import * source = vtkRandomGraphSource() view = vtkGraphLayoutView() view.AddRepresentationFromInputConnection(source.GetOutputPort()) view.GetRenderWindow().SetSize(600, 600) view.ResetCamera() view.Render() view.GetInteractor().Start() |
theme.py
|
Use themes to control the display attributes of a view, as demonstrated here:
rom vtk import *
source = vtkRandomGraphSource()
view = vtkGraphLayoutView()
view.AddRepresentationFromInputConnection(source.GetOutputPort())
theme = vtkViewTheme.CreateMellowTheme()
view.ApplyViewTheme(theme)
theme.FastDelete()
view.GetRenderWindow().SetSize(600, 600)
view.SetVertexColorArrayName("VertexDegree");
view.SetColorVertices(True);
view.ResetCamera()
view.Render()
view.GetInteractor().Start()
|
filters.py
|
This code expands on the previous example, adding filters to the pipeline to create a semantic graph then labelling and coloring based on graph attributes:
from vtk import *
source = vtkRandomGraphSource()
source.SetIncludeEdgeWeights(True)
degree = vtkVertexDegree()
degree.AddInputConnection(source.GetOutputPort())
view = vtkGraphLayoutView()
view.AddRepresentationFromInputConnection(degree.GetOutputPort())
view.SetVertexLabelArrayName("VertexDegree")
view.SetVertexLabelVisibility(True)
view.SetVertexColorArrayName("VertexDegree")
view.SetColorVertices(True)
view.SetEdgeLabelArrayName("edge weight")
view.SetEdgeLabelVisibility(True)
view.SetEdgeColorArrayName("edge weight")
view.SetColorEdges(True)
view.SetLayoutStrategyToSimple2D()
theme = vtkViewTheme.CreateMellowTheme()
theme.SetLineWidth(4)
view.ApplyViewTheme(theme)
theme.FastDelete()
view.GetRenderWindow().SetSize(600, 600)
view.ResetCamera()
view.Render()
view.GetInteractor().Start()
|
programmable_pipeline.py
|
In the previous examples we've used Python to construct a Titan pipeline and display its results in a Window, but all of the components in the pipeline have been Titan filters written in C++. Next, we will use the vtkProgrammableFilter component to "embed" Python code into the pipeline. In this way we can prototype new "components" entirely in Python, then rewrite them in C++ on an as-needed basis (typically for performance). In this example, we use vtkProgrammableFilter to generate arrays of vertex and edge attributes, which are useful for debugging. Note that we insert the vtkProgrammableFilter object into the pipeline like any other filter, but we also define a "callback function" that is called by the programmable filter when it needs to update its output. The callback function does not take any parameters, so it must get the filter's inputs and outputs from the filter object itself. The callback function is then free to perform any operation desired to define the filter output. Note that there is also a vtkProgrammableSource that can be used in similar fashion to bring arbitrary data into the pipeline - this is an excellent way to work with unusual or "one-off" data import scenarios. Since you have the complete Python API to work with, the sky's the limit on what a programmable filter can do. In this example, the programmable filter adds two new attribute arrays to a graph: a "vertex_id" array that contains a zero-based index for each vertex, and an "edge_target" array that contains a zero-based index for the target of each edge. We then use the new arrays to label the displayed graph:
from vtk import *
source = vtkRandomGraphSource()
source.SetNumberOfVertices(75)
source.SetEdgeProbability(0.02)
source.SetUseEdgeProbability(True)
source.SetStartWithTree(True)
create_index = vtkProgrammableFilter()
create_index.AddInputConnection(source.GetOutputPort())
def create_index_callback():
input = create_index.GetInput()
output = create_index.GetOutput()
output.ShallowCopy(input)
vertex_id_array = vtkIdTypeArray()
vertex_id_array.SetName("vertex_id")
vertex_id_array.SetNumberOfTuples(output.GetNumberOfVertices())
for i in range(output.GetNumberOfVertices()):
vertex_id_array.SetValue(i, i)
output.GetVertexData().AddArray(vertex_id_array)
edge_target_array = vtkIdTypeArray()
edge_target_array.SetName("edge_target")
edge_target_array.SetNumberOfTuples(output.GetNumberOfEdges())
edge_iterator = vtkEdgeListIterator()
output.GetEdges(edge_iterator)
while edge_iterator.HasNext():
edge = edge_iterator.NextGraphEdge()
edge_target_array.SetValue(edge.GetId(), edge.GetTarget())
output.GetEdgeData().AddArray(edge_target_array)
create_index.SetExecuteMethod(create_index_callback)
view = vtkGraphLayoutView()
view.AddRepresentationFromInputConnection(create_index.GetOutputPort())
view.SetVertexLabelArrayName("vertex_id")
view.SetVertexLabelVisibility(True)
view.SetEdgeLabelArrayName("edge_target")
view.SetEdgeLabelVisibility(True)
theme = vtkViewTheme.CreateMellowTheme()
view.ApplyViewTheme(theme)
theme.FastDelete()
view.GetRenderWindow().SetSize(600, 600)
view.ResetCamera()
view.Render()
view.GetInteractor().Start()
|
threshold.py
|
This example demonstrates how to extract a subgraph from a graph by thresholding based on an edge attribute. A graph source with random edge weights is created, and the programmable filter is used to assign vertex labels as in the previous example. A vtkSelectionSource is used to generate a vtkSelection that will threshold the "edge_weights" array, discarding edges with a value outside the range [0.8, 1.0]. The original graph and the selection are fed to a vtkExtractSelectedGraph filter, which extracts every entity (edges in this case) that are selected. The original graph and subgraph are then displayed in separate windows.
from vtk import *
source = vtkRandomGraphSource()
source.SetNumberOfVertices(10)
source.SetEdgeProbability(0.1)
source.SetUseEdgeProbability(True)
source.SetStartWithTree(True)
source.SetIncludeEdgeWeights(True)
create_index = vtkProgrammableFilter()
create_index.SetInputConnection(source.GetOutputPort())
def create_index_callback():
input = create_index.GetInput()
output = create_index.GetOutput()
output.ShallowCopy(input)
vertex_id_array = vtkIdTypeArray()
vertex_id_array.SetName("vertex_id")
vertex_id_array.SetNumberOfTuples(output.GetNumberOfVertices())
for i in range(output.GetNumberOfVertices()):
vertex_id_array.SetValue(i, i)
output.GetVertexData().AddArray(vertex_id_array)
create_index.SetExecuteMethod(create_index_callback)
selection = vtkSelectionSource()
selection.SetContentType(7) # vtkSelection::THRESHOLDS
selection.SetFieldType(4) # vtkSelection::EDGE
selection.SetArrayName("edge_weights")
selection.AddThreshold(0.8, 1.0)
create_index.Update()
selection.Update()
index_selection = vtkConvertSelection.ToIndexSelection(selection.GetOutput(), create_index.GetOutput())
print index_selection
subgraph = vtkExtractSelectedGraph()
subgraph.SetRemoveIsolatedVertices(False)
subgraph.SetInputConnection(create_index.GetOutputPort())
subgraph.SetSelectionConnection(selection.GetOutputPort())
view1 = vtkGraphLayoutView()
view1.AddRepresentationFromInputConnection(create_index.GetOutputPort())
view1.SetVertexLabelArrayName("vertex_id")
view1.SetVertexLabelVisibility(True)
view1.SetEdgeLabelArrayName("edge_weights")
view1.SetEdgeLabelVisibility(True)
view2 = vtkGraphLayoutView()
view2.AddRepresentationFromInputConnection(subgraph.GetOutputPort())
view2.SetVertexLabelArrayName("vertex_id")
view2.SetVertexLabelVisibility(True)
view2.SetEdgeLabelArrayName("edge_weights")
view2.SetEdgeLabelVisibility(True)
theme = vtkViewTheme.CreateMellowTheme()
view1.ApplyViewTheme(theme)
view2.ApplyViewTheme(theme)
theme.FastDelete()
window1 = vtkRenderWindow()
window1.SetSize(600, 600)
view1.SetupRenderWindow(window1)
window2 = vtkRenderWindow()
window2.SetSize(600, 600)
view2.SetupRenderWindow(window2)
window1.GetInteractor().Start()
|
|
|
We can also add multiple threshold ranges by adding more thresholds. For example: selection.AddThreshold(0.1, 0.2) would add an additional threshold to the selection to include edges between 0.1 and 0.2 in addition to the edges labeled with 0.8 to 1.0. In this manner, we can specify any number of discontinuous ranges in a selection. |
databases.py
|
It is common for informatics problems to use SQL databases as a pipeline source. This example uses data from the publicly-available Enron e-mail database to generate a graph. Two SQL queries are executed to return edge and vertex tables that are combined using vtkTableToGraph (a very common use-case). Note: This example requires that your VTK library was built with "VTK_USE_MYSQL" "ON".
from vtk import *
database = vtkSQLDatabase.CreateFromURL("mysql://enron:enron@vizdb.srn.sandia.gov:3306/enron")
database.Open()
edge_query = database.GetQueryInstance()
edge_query.SetQuery("select sendID, recvID, weight from email_arcs")
vertex_query = database.GetQueryInstance()
vertex_query.SetQuery("select firstName, lastName, eid from employeelist")
edge_table = vtkRowQueryToTable()
edge_table.SetQuery(edge_query)
vertex_table = vtkRowQueryToTable()
vertex_table.SetQuery(vertex_query)
source = vtkTableToGraph()
source.AddInputConnection(edge_table.GetOutputPort())
source.AddLinkVertex("sendID", "eid", False)
source.AddLinkVertex("recvID", "eid", False)
source.AddLinkEdge("sendID", "recvID")
source.SetVertexTableConnection(vertex_table.GetOutputPort())
view = vtkGraphLayoutView()
view.AddRepresentationFromInputConnection(source.GetOutputPort())
view.SetVertexLabelArrayName("lastName")
view.SetVertexLabelVisibility(True)
view.SetEdgeColorArrayName("weight")
view.SetColorEdges(True)
theme = vtkViewTheme.CreateMellowTheme()
theme.SetCellValueRange(0, 0)
theme.SetCellAlphaRange(0.1, 2)
theme.SetCellOpacity(1)
view.ApplyViewTheme(theme)
window = vtkRenderWindow()
window.SetSize(600, 600)
view.SetupRenderWindow(window)
window.GetInteractor().Start()
|
delimited_text_reader.py
The following code illustrates the use of the vtkDelimitedTextReader function to read in a Comma Separated Value (CSV) file.
table.csv
col1,col2,col3,col4 a,b,1,1.3 a,c,3,1.2 a,d,5,2.3 b,d,1,1.6 c,b,4,2.2
delimited_text_reader.py
from vtk import *
# load the "table.csv" file into a table
reader = vtkDelimitedTextReader()
reader.SetFileName("table.csv")
reader.SetFieldDelimiterCharacters(",")
reader.SetHaveHeaders(True)
reader.SetMaxRecords(1000)
reader.Update()
tbl = reader.GetOutput()
# print some info about the table
print "Number of Rows: %d"%(tbl.GetNumberOfRows())
print "Number of Cols: %d"%(tbl.GetNumberOfColumns())
for i in range( tbl.GetNumberOfColumns() ):
print "\tCol %d name = '%s'"%(i, tbl.GetColumnName(i) )
col = tbl.GetColumn(i)
s = ""
for i in range( col.GetNumberOfTuples() ):
s += "%s "%(col.GetValue(i))
print "\t\t", s
Executing this script gives the following result:
Number of Rows: 5 Number of Cols: 4 Col 0 name = 'col1' a a a b c Col 1 name = 'col2' b c d d b Col 2 name = 'col3' 1 3 5 1 4 Col 3 name = 'col4' 1.3 1.2 2.3 1.6 2.2
delimited_text_writer.py
Unfortunately, there is no vtkDelimitedTextWriter at the time the previous example was written. This makes writing data from a vtkTable into a CSV file a bit more tricky as we must write a python routine to do it.
Adding the following routine to the previous example and calling it will allow the writing a vtkTable object back out to a delimited text file. Note, the vtkTable::GetValue(row,col) method is currently not wrapped by Python requiring us to extract the columns of the table individually, which we can then iterate over.
def vtkTableToCsvWriter(tbl, fileName, delimiter=","):
"""
Writes a vtkTable into a CSV text file.
tbl : a vtkTable object
fileName : file name of output file
delimiter : [default=','] optional argument specifying the delimiter to use
to separate columns in the output file.
"""
ncols = tbl.GetNumberOfColumns()
nrows = tbl.GetNumberOfRows()
cols = []
headers = []
for i in range(ncols):
cols.append( tbl.GetColumn(i) )
headers.append( tbl.GetColumnName(i) )
OFP = open(fileName, "w")
OFP.write(delimiter.join(headers)+"\n")
for i in range(nrows):
rowi = []
for j in range(ncols):
rowi.append( cols[j].GetValue(i) )
OFP.write(delimiter.join(rowi)+"\n")
OFP.close()
vtkSNL Examples
The following examples use components provided by vtkSNL. Note that to run these examples you will have to build vtkSNL and add it to your PYTHONPATH as described in detail above.
Note: the following files are located in the vtkSNL/Examples/Python/Infovis directory.
selection.py
|
Many useful informatics algorithms either generate, modify, or use selections as arguments. This example demonstrates several aspects of working with selections. First, the graph from the previous example is generated, including an "index" array for both vertices and edges. Next, a vtkSelectionSource component is used to generate a selection containing two vertices from the source graph, "0" and "74". Next, the vtkMTGLSelectionFilterST component "expands" the selection from two vertices to the set of shortest paths between them. The expanded selection is used as an input to vtkExtractSelectedGraph, which extracts a subset of the original graph. Finally, the extracted graph is displayed in a separate window. Using the vertex and edge labels, you can compare the extracted graph to the original.
from vtk import *
from vtksnl import *
source = vtkRandomGraphSource()
source.SetNumberOfVertices(75)
source.SetEdgeProbability(0.02)
source.SetUseEdgeProbability(True)
source.SetStartWithTree(True)
create_index = vtkProgrammableFilter()
create_index.AddInputConnection(source.GetOutputPort())
def create_index_callback():
input = create_index.GetInput()
output = create_index.GetOutput()
output.ShallowCopy(input)
index_array = vtkIntArray()
index_array.SetName("index")
index_array.SetNumberOfTuples(output.GetNumberOfVertices())
for i in range(output.GetNumberOfVertices()):
index_array.SetValue(i, i)
output.GetVertexData().AddArray(index_array)
index_array = vtkIntArray()
index_array.SetName("index")
index_array.SetNumberOfTuples(output.GetNumberOfEdges())
for i in range(output.GetNumberOfEdges()):
index_array.SetValue(i, i)
output.GetEdgeData().AddArray(index_array)
create_index.SetExecuteMethod(create_index_callback)
selection = vtkSelectionSource()
selection.SetFieldType(3) # Generate a "vertex" selection
selection.AddID(0, 0) # Add vertex 0 to the selection
selection.AddID(0, 74) # Add vertex 74 to the selection
st_selection = vtkMTGLSelectionFilterST()
st_selection.AddInputConnection(selection.GetOutputPort())
st_selection.SetGraphConnection(create_index.GetOutputPort())
extract_graph = vtkExtractSelectedGraph()
extract_graph.AddInputConnection(create_index.GetOutputPort())
extract_graph.SetSelectionConnection(st_selection.GetOutputPort())
view = vtkGraphLayoutView()
view.AddRepresentationFromInputConnection(create_index.GetOutputPort())
view.SetVertexLabelArrayName("index")
view.SetVertexLabelVisibility(True)
view.SetEdgeLabelArrayName("index")
view.SetEdgeLabelVisibility(True)
view2 = vtkGraphLayoutView()
view2.AddRepresentationFromInputConnection(extract_graph.GetOutputPort())
view2.SetVertexLabelArrayName("index")
view2.SetVertexLabelVisibility(True)
view2.SetEdgeLabelArrayName("index")
view2.SetEdgeLabelVisibility(True)
theme = vtkViewTheme.CreateMellowTheme()
view.ApplyViewTheme(theme)
view2.ApplyViewTheme(theme)
theme.FastDelete()
window = vtkRenderWindow()
window.SetSize(600, 600)
view.SetupRenderWindow(window)
window2 = vtkRenderWindow()
window2.SetSize(600, 600)
view2.SetupRenderWindow(window2)
window.GetInteractor().Start()
|
statistics.py
The following example demonstrates vtkAverageVertexDegree, as an example of a "statistics" filter - i.e. a filter that accepts a graph as input and produces a single value as output, rather than per-vertex or per-edge attributes. Note that - unlike many of the other Titan / Python examples - this example does not connect the pipeline output to a view. Since the example calculation produces a single value as output, there is nothing to view except a number. Instead, we create the pipeline normally, then call Update() on the last component in the pipeline to force calculation. We then extract the pipeline's graph output, retrieve the single-element array that was produced by vtkAverageVertexDegree, and print its output to the console. Of course, we could extend the example by adding other filters to the pipeline and extracting the data they produce. If desired, we could also connect the pipeline to a view and visualize the graph for reference.
from vtk import *
from vtksnl import *
source = vtkRandomGraphSource()
source.SetNumberOfVertices(75)
average_degree = vtkAverageVertexDegree()
average_degree.AddInputConnection(source.GetOutputPort())
average_degree.Update()
array = average_degree.GetOutput().GetFieldData().GetArray("AverageVertexDegree")
print array.GetValue(0)
Output
0.266666666667
collapse.py
This example exercises the vtkCollapseGraph filter.
community.py
This example exercises the vtkHierarchicalCommunityFinder filter.
multilinear.py
This example exercises the vtkPARAFACGraphToTable straw-man filter, and is a work-in-progress.
Using NumPy with the Titan Python API
|
NumPy provides a multidimensional array type for scientific computing with Python. NumPy defines many scientific and statistical functions which operate on this array type. In addition, the SciPy Python library adds even more scientific and analysis functions which use the NumPy array as the basic data type. The Titan python interface provides a utility function to convert VTK array data to the NumPy format for processing with NumPy, and an inverse function to convert the resulting NumPy array back to VTK for further processing and visualization. These conversion functions allow the power and convenience of NumPy and SciPy to be easily integrated with the Titan Python API. Please consult the following page for NumPy with Titan examples and installation instructions for NumPy and SciPy. |
