11. Python Expressions
This tutorial describes using Python expressions. Python expressions are an advanced feature and should olny be used if the needed functionality is not available in the standard expression system.
11.1. Python Expressions Overview
When the available expressions fail to provide needed functionality, users can extend VisIt’s expression system in arbitrary ways using Python expressions. However, Python expressions require users to become somewhat converscent in detailed aspects of how mesh and variable data is represented in terms of VTK objects as well as how they are decomposed and processed in parallel. Nonetheless, Python expressions provide a powerful approach to filling in gaps in needed functionality.
Python expressions are run on the compute engine and will run in parallel whenever a) the compute engine is parallel and b) the input dataset is decomposed for parallel.
Python expressions operate on vtkDataSets
, which provide access to mesh variables as well as the mesh coordinates and topology.
Python expression also have access to VisIt’s metadata as well as access to MPI when running in parallel.
Python expressions return a vtkDataArray
, which allows returning new variables.
It is not possible to change the mesh topology or coordinates within a Python expression.
However, it is possible to combine Python expressions with Cross Mesh Field Evaluation (CMFE) functions which can have the effect of changing mesh topology and coordinates.
The functionality is available through the GUI and the CLI.
When using the GUI, they can be created in the Expressions window.
When using the CLI, they can be created with the DefinePythonExpression function.
11.2. Creating a Python Expression with the GUI
We will now go through the steps required to create a Python expression using the GUI.
Let us start by opening a file and creating a plot.
Open the file
curv2d.silo
.Create a Psuedocolor plot of
d
.
Now let us go ahead and create the Python expression.
Go to Controls->Expressions.
This brings up the Expressions window.
Click New in the Expression list to create a new expression.
Change the Name in the Definition section to “MyExpression”.
Click on the Python expression editor tab in the Definition section.
Select Insert variable…->Scalars->d to add
d
to the Arguments text field.Select Insert variable…->Scalars->p to add
p
to the Arguments text field. Note that the variable names are seperated by a comma. If the variable names are not separated by commas you will get a cryptic error message when you try to plot the expression.Click Load script->Template->Simple filter to add a template of a Python expression in the Python expression script editor.
At this point you modify the template to create your expression. A common practice is to make modifications to the script and test it using the Pseudocolor plot. Changes to the script can be made either by modifying the script in the Python expression script editor or modifying it in an external text editor and then reloading the script. Generaly speaking, modifying the script in the Python expression script editor is easier than doing it in an external text editor except that it is difficult to tell how many spaces are at the beginning of the line since the editor does not use a fixed width font.
11.2.1. Developing the script in the Python expression script editor
The following steps can be used to iteratively develop your script using the Python expression script editor.
Edit the script.
Click the Apply button.
Go to Variables->d to change the variable to
d
. The first time you try your script this will not be necessary since the variable is alreadyd
.Go to Variables->MyExpression to change the variable to “MyExpression” and execute the script.
11.2.2. Developing the script in a text editor
The following steps can be used to iteratively develop your script using a text editor.
Before you can modify the script you will need to save it.
Click Save script to save the script.
Now you are ready to modify the script.
Edit the script with your favorit editor.
Go to Load script->File to load the script.
Click the Apply button.
Go to Variables->d to change the variable to
d
. The first time you try your script this will not be necessary since the variable is alreadyd
.Go to Variables->MyExpression to change the variable to “MyExpression” and execute the script.
11.3. Python Expression Example 1
This example adds two cell centered variables. It demonstrates accessing multiple variables and performing simple operations with them to generate a result.
Here is the example script.
class MyExpression(SimplePythonExpression):
def __init__(self):
SimplePythonExpression.__init__(self)
self.name = "PythonExpression"
self.description = "Add two scalar variables together"
self.output_is_point_var = False
self.output_dimension = 1
def modify_contract(self,contract):
pass
def derive_variable(self,ds_in,domain_id):
# ds_in is the input data set
# Get the data array for the first variable
cell_vals1 = ds_in.GetCellData().GetArray(self.input_var_names[0])
# Get the data array for the second variable
cell_vals2 = ds_in.GetCellData().GetArray(self.input_var_names[1])
# Get the number of values in the variables
ncells = ds_in.GetNumberOfCells()
# Create a scalar float array with ncells values for the result
res = vtk.vtkFloatArray()
res.SetNumberOfComponents(1)
res.SetNumberOfTuples(ncells)
for i in range(ncells):
# Add the i'th value from the first variable to the i'th
# value for the second variable
val = cell_vals1.GetTuple1(i) + cell_vals2.GetTuple1(i)
# Store the value in the i'th value in the result
res.SetTuple1(i, val)
return res
py_filter = MyExpression
Let us start off by creating a Pseudocolor plot from the expression.
Copy the script into the Python expression script editor.
Click the Apply button.
Go to Variables->MyExpression to change the variable to the expression.
Now let us take a look at the script and see what each portion does.
The __init__
method provides information about the expression, including
That it inherits from
SimplePythonExpression
.The name of the expression.
A description of the expression.
A flag indicating that the output is not a point centered value.
A flag that the output is a scalar.
def __init__(self):
SimplePythonExpression.__init__(self)
self.name = "PythonExpression"
self.description = "Add two scalar variables together"
self.output_is_point_var = False
self.output_dimension = 1
The modify_contract
method can be used to request special information for the expression from VisIt.
In this case it is a no-op.
def modify_contract(self,contract):
pass
The derive_variable
method performs the real work of the expression.
It is passed the input vtkDataSet
and the domain_id
.
def derive_variable(self,ds_in,domain_id):
# ds_in is the input data set
The following lines get the vtkDataArrays
for the cell values for the two variables and the number of cells.
# Get the data array for the first variable
cell_vals1 = ds_in.GetCellData().GetArray(self.input_var_names[0])
# Get the data array for the second variable
cell_vals2 = ds_in.GetCellData().GetArray(self.input_var_names[1])
# Get the number of values in the variables
ncells = ds_in.GetNumberOfCells()
The following lines set the output vtkDataArray
to be an array of floats with 1 component and ncells values.
# Create a scalar float array with ncells values for the result
res = vtk.vtkFloatArray()
res.SetNumberOfComponents(1)
res.SetNumberOfTuples(ncells)
Now we loop over the cells, setting the output value for each cell.
for i in range(ncells):
The following lines add the two variables for the current cell.
# Add the i'th value from the first variable to the i'th
# value for the second variable
val = cell_vals1.GetTuple1(i) + cell_vals2.GetTuple1(i)
The following lines set the result value for the current cell.
# Store the value in the i'th value in the result
res.SetTuple1(i, val)
Once we have finished processing all the cells, we return the vtkDataArray
.
return res
11.3.1. Using your Python Expression with the CLI
The Python expression we just created can also be used with the CLI.
We will start by saving the script we just created.
Click Save script and save the script with the name
MyExpression.py
.
The following script will open curv2d.silo
and create a Pseudocolor plot of the expression.
OpenDatabase("/usr/gapps/visit/data/curv2d.silo")
DefinePythonExpression("MyExpression", ['d', 'p'], file="MyExpression.py")
AddPlot("Pseudocolor", "MyExpression")
DrawPlots()
11.4. Python Expression Example 2
This example operates on 2D meshes and takes the distance around the edges of each cell and multiplies it by the value of the cell. It demonstrates accessing the coordinates and topology of the mesh as well as a variable.
Here is the example script.
from math import sqrt
class MyExpression(SimplePythonExpression):
def __init__(self):
SimplePythonExpression.__init__(self)
self.name = "PythonExpression"
self.description = "Multiply the variable by sum of cell edge lengths in 2D"
self.output_is_point_var = False
self.output_dimension = 1
def modify_contract(self,contract):
pass
def derive_variable(self,ds_in,domain_id):
# ds_in is the input data set
# Get the data array for the variable
cell_vals = ds_in.GetCellData().GetArray(self.input_var_names[0])
# Get the number of values in the variable
ncells = ds_in.GetNumberOfCells()
# Create a scalar float array with ncells values for the result
res = vtk.vtkFloatArray()
res.SetNumberOfComponents(1)
res.SetNumberOfTuples(ncells)
for i in range(ncells):
# Get the i'th cell
cell = ds_in.GetCell(i)
# Get the number of edges in the cell
nedges = cell.GetNumberOfEdges()
# Sum up the lengths of the edges
sum = 0.
for j in range(nedges):
# Get the j'th edge
edge = cell.GetEdge(j)
# Calculate the edge length from the end points
pt1 = ds_in.GetPoint(edge.GetPointId(0))
pt2 = ds_in.GetPoint(edge.GetPointId(1))
len = sqrt((pt2[0] - pt1[0]) * (pt2[0] - pt1[0]) +
(pt2[1] - pt1[1]) * (pt2[1] - pt1[1]) +
(pt2[2] - pt1[2]) * (pt2[2] - pt1[2]))
sum = sum + len
# Multiply the sum by the i'th value of the variable
sum *= cell_vals.GetTuple1(i)
# Store the value in the i'th value in the result
res.SetTuple1(i, sum)
return res
py_filter = MyExpression
Let us start off by creating a Pseudocolor plot from the expression.
Copy the script into the Python expression script editor.
Click the Apply button.
Go to Variables->MyExpression to change the variable to the expression.
The __init__
and modify_contract
methods are the same as the previous example, so we will only look at the derive_variable
method.
def derive_variable(self,ds_in,domain_id):
# ds_in is the input data set
The following lines get the vtkDataArray
for the cell values and the number of cells.
# Get the data array for the variable
cell_vals = ds_in.GetCellData().GetArray(self.input_var_names[0])
# Get the number of values in the variable
ncells = ds_in.GetNumberOfCells()
The following lines set the output vtkDataArray
to be an array of floats with 1 component and ncells values.
# Create a scalar float array with ncells values for the result
res = vtk.vtkFloatArray()
res.SetNumberOfComponents(1)
res.SetNumberOfTuples(ncells)
Now we loop over the cells, setting the output value for each cell.
for i in range(ncells):
The following lines get the current cell and the number of edges in the cell.
# Get the i'th cell
cell = ds_in.GetCell(i)
# Get the number of edges in the cell
nedges = cell.GetNumberOfEdges()
Now we loop over the edges, calculating the sum of the lengths of the edges.
# Sum up the lengths of the edges
sum = 0.
for j in range(nedges):
We calculate the length of the edge from the 3D coordinates of the end points of the edge, which we add to the sum.
# Get the j'th edge
edge = cell.GetEdge(j)
# Calculate the edge length from the end points
pt1 = ds_in.GetPoint(edge.GetPointId(0))
pt2 = ds_in.GetPoint(edge.GetPointId(1))
len = sqrt((pt2[0] - pt1[0]) * (pt2[0] - pt1[0]) +
(pt2[1] - pt1[1]) * (pt2[1] - pt1[1]) +
(pt2[2] - pt1[2]) * (pt2[2] - pt1[2]))
sum = sum + len
Once we have summed the lengths of the edges we multiply the sum by the cell value and set it in the result.
# Multiply the sum by the i'th value of the variable
sum *= cell_vals.GetTuple1(i)
# Store the value in the i'th value in the result
res.SetTuple1(i, sum)
Once we have finished processing all the cells, we return the vtkDataArray
.
return res
11.4.1. Using your Python Expression with the CLI
This Python expression can also be used with the CLI, just as the one in the first example, except the specification of the variables to use is slightly different.
Since you are only passing a single variable you would use ("d")
for the list of variables.
OpenDatabase("/usr/gapps/visit/data/curv2d.silo")
DefinePythonExpression("MyExpression", ("d"), file="MyExpression.py")
AddPlot("Pseudocolor", "MyExpression")
DrawPlots()
11.5. Using VTK in Python
The VTK Python interface mirrors the C++ interface.
To find out information on a particular VTK class, type the name of the class in your favorite search engine.
Here are links to some VTK classes that will be of most use to you.