EnSight command language native Python API#
Since its inception, EnSight has had a journaling language, commonly referred to as the command language. Every operation in EnSight can be captured in command language. Scripts can be generated using this language and played back in the GUI or in batch mode. Furthermore, features like context files (that capture a session state) do so using a command language variant. Command language is not documented, but it roughly follows the EnSight architecture. The :ref: native Python API <native_api_docs> is a binding to this command language interface.
Command language overview#
A command language call has this general form: class: command [values...]
.
For example, view_transf: rotate -4. 24. 0.
rotates the current view, and
data: replace data.case
loads a dataset into the current case.
Commands may also follow a begin/end or modify begin/end structure, where commands of the same class are used between the begin and end commands. This form is used to batch a collection of changes into a single update operation. Finally, there is a select begin/end form for expanding values onto multiple lines.
The language separates the specification of target objects and attribute changes into separate commands. Thus, there is always a current selection of all objects of a specific type, and many commands operate on the current selection. For example, this code sets the current part selection to part number 1 and then modifies the line width and part color:
part: select_begin
1
part: select_end
part: modify_begin
part: line_width 2
part: colorby_rgb 1.0 0.0 0.0
part: modify_end
Note
While most of the command language follows these two command forms, there are some commands that do not follow this form.
As noted previously, EnSight maintains a default object of every type. You can
use commands to modify most attributes on the default object. For example, you can
use the create
command to create a new object instance. The following code creates
a clip by selecting the default clip object and then setting up the type and clip position
value on the default clip. It then changes the current part selection to what parts should
become the parent of the clip and calls the clip: create
command to create the clip:
clip: select_default
clip: begin
clip: domain intersect
clip: tool xyz
clip: value 0.5
clip: end
part: select_begin
1
2
part: select_end
clip: create
PyEnSight command language binding#
The native Python API binding is a simple syntax conversion from command language
into Python syntax. The command
class is a module in Python under the session.ensight
module. All values are passed as native Python parameters. For the select/begin/end
command form, only the begin
command is used. All of the value lines can be specified
as Python parameters or a list. The previous example becomes this Python script:
session.ensight.clip.select_default()
session.ensight.clip.begin()
session.ensight.clip.domain("intersect")
session.ensight.clip.tool("xyz")
session.ensight.clip.value(0.5)
session.ensight.clip.end()
session.ensight.part.select_begin(1, 2)
session.ensight.clip.create()
Lists of objects can be used where multiple values are specified as parameters, which means that this syntax is also valid:
session.ensight.part.select_begin([1, 2])
session.ensight.part.modify_begin()
session.ensight.part.colorby_rgb([0.0, 0.0, 1.0])
session.ensight.part.modify_end()
Native API debugging#
Every command also returns an error code, which is 0
on success. For example,
err = session.ensight.part.colorby_rgb([0.0,0.0,"sad"])
sets err
to -1
.
You can use the attrtree
method to enable Python exception handling instead of returning an error code. You should
use the attrtree
method when debugging native API scripts.
Note
Because the exception setting is global, care should be taken to reset the error handling status on an error to ensure proper EnSight operation.
This example shows how you can convert error return values into exceptions:
try:
session.ensight.sendmesgoptions(exception=True)
session.ensight.part.select_begin([1, 2])
session.ensight.part.colorby_rgb([0.0,0.0,"sad"])
except RuntimeError as e:
print("Error", e)
finally:
session.ensight.sendmesgoptions(exception=False)
The code prints this error:
RuntimeError: Command: (part: colorby_rgb 0.0 0.0 sad ) returned: RGB color: bad parameter
GUI conversion#
There is a built-in mechanism to convert code in command language into Python. To do this, you first paste the command language into the Python editor. On EnSight’s Execution tab, you can use the right-mouse button menu to select and copy lines of command language.
Next, select the text in the editor and use the Edit menu to select either the Convert selection to sendmesg() or Convert selection to native Python option. In general, the native Python conversion results in much more readable Python code that is far easier to edit than the Convert selection to sendmesg() option. You should use the Convert selection to native Python option for all but legacy development.
The File menu provides two items to execute the current file text in the EnSight Python
interpreter. The Run script option causes the file contents to be executed in the global
namespace (for example, like the execfile()
function). The Import script as module
option first saves the current file to disk and then executes a Python import operation on the
file, which executes in a private namespace. Both options verify the syntax of the current
file and allow for rapid prototyping.
Special cases#
There are a number of commands in the EnSight command language that are not valid Python names. Here are a few examples:
function: #_of_levels 5
annotation: 3d_label_size 10.0
command: print "hello"
viewport: raise
Here are some reasons that a name might be invalid:
Name contains an invalid character (such as
#
).Name begins with a digit (such as
1
).Name is a Python-reserved word (such as
raise
).
Invalid names are transformed using these rules:
#
characters are replaced with the text number.Names that start with a digit are prefixed with an underscore (_).
Names that are the same as a Python-reserved word are prefixed with an underscore (_).
The previous examples are transformed as follows:
session.ensight.function.number_of_levels(5)
session.ensight.annotation._3d_label_size(10.0)
session.ensight.command.print("hello")
session.ensight.viewport._raise()
Selection and the object API#
The native API maintains a notion of a current selection with a collection
of commands to manipulate it, such as :func: select_begin()<ansys.api.pyensight.ensight_api.part.select_begin>.
The object API reflects the EnSight GUI via SELECTED attributes and selection ENS_GROUP
objects.
Due to the implicit nature of the native API, until it is used, the native selection
is not reflected in EnSight objects. When using both APIs in a single script, it can
become necessary to synchronize the two notions of selection. This is done with the
the get_mainpartlist_select()
command. This command sets the native selection to match the object selection. For example, this
code allows the object selection mechanisms to be used to set up the part selection for
subsequent native commands:
p = session.ensight.objs.core.PARTS["rear body"][0]
session.ensight.objs.core.selection().addchild(p, replace=1)
session.ensight.part.get_mainpartlist_select()
session.ensight.part.modify_begin()
session.ensight.part.colorby_rgb(0.0,1.0,0.0)
session.ensight.part.modify_end()
Convert existing EnSight scripts to PyEnSight#
PyEnSight has been designed to be fully compatible with the existing EnSight Python language,
supporting both the native Python API and the object API. Indeed, the ensight
attribute
of a PyEnSight session
object is a clone of the ensight
module generated via
introspection. This means that any attribute, object, instance, variable, and more
available in the ensight
module is also available in PyEnSight, which manages the
communication with EnSight and the conversion of a command to its corresponding EnSight counterpart.
However, you must make a few adjustments to port an existing EnSight script into
PyEnSight. Here is a list of operations to perform to make the conversion:
All the calls to the
ensight
module and its attributes must be pre-fixed with the current session instance. For example:
# Old syntax
# ensight.objs.core.PARTS
# New syntax
session.ensight.objs.core.PARTS
The
ensight
module cannot be imported anymore because it is an attribute of the PyEnSightsession
object. However, you can use thescoped_name
utility to mimic the syntax that you would obtain importing a module or a submodule:
# Remove previous imports
# import ensight
# from ensight.objs import *
# from ensight.objs import core
# Create a ``scoped_name`` instance
sn = session.ensight.utils.support.scoped_name
# Create a context manager with the ``scoped_name`` instance, where you can
# use the old syntax
with sn(session.ensight) as ensight, sn(session.ensight.objs.core) as core:
core.PARTS[0].DESCRIPTION
ensight.view.bounds("ON")
The main advantage of using the
scoped_Name
instance is that the new syntax is also supported directly in EnSight. This greatly simplifies the porting of a PyEnSight script into EnSight.