Core Python API

Previous Next

The Core EnSight Python API

Not all of the EnSight Python API is objects.  These pages describe changes to the 'ensight', 'enve' and 'cei' modules that expand on the information in the Interface Manual, chapter 6.

ensight methods

Version

ensight.version(element): The caller passes an element string that selects the type of information to return. In the table examples, we assume EnSight version '2023  R2' which has an internal identification number of 232.  The currently defined element keys are:


Element string

Returned value

ip

System IP address as a string.

version-full

EnSight version display string. For example: '2023  R2'

numeric

EnSight version broken down as a list of integers and a single string in the form: [year, release, patch, beta]. For example: [2023, 1, 0, 'Beta']

year

Year portion of the 'numeric' list (e.g. 2023).

rel

Release portion of the 'numeric' list (e.g. 1).

patch

Patch number portion of the 'numeric' list (e.g. 0)

beta

Beta string from the 'numeric' list output (e.g. 'Beta')

suffix

Suffix number used internally for naming files/directories/etc (e.g. 232)

customer

Customer name from the licensing system (both flex and SLiM)

company

Company name from the licensing system

product

The current name of the EnSight product: 'EnSight', 'EnVision', etc.

mode

License type: "batch", "HPC", "Standard", etc

license

Same as 'mode'.

flavor

Same as 'mode'

arch

System architecture: 'linux_2.6_64', 'win64', etc.

CEI_HOME

Base installation directory.  For example: "C:\Program Files\ANSYS Inc\v232\CEI"

home

Same as 'CEI_HOME'.

lmtype

License manage name: "ANSYS", "SLiM" or "FSI"

haveServer

Boolean that will be True if a server or an SOS is connected.

haveSOS

Boolean that will be True if an SOS is connected.

slimversion

Version string for the SLiM license manager (e.g. '8.44') or None if not using SLiM.

keypath

Pathname of the SLiM key from the SLiM license manager or None if not using SLiM.

username

User name the license is checked out to.

hostname

Host name of the system EnSight is running on.


If a string is given as element that is not supported, a ValueError exception is thrown.

Deprecated ensight.version() Functionality

This functionality is still available for backward compatibility, but it is no longer being updated and may be removed from a future version of EnSight. If no element argument is specified, the function returns a list containing 10 items:


  1. The client version
  2. The license variant (HPC, Standard, etc.)
  3. The architecture
  4. The CEI installation directory (CEI_HOME)
  5. server version
  6. SOS version
  7. user and license dictionary
    The user and license dictionary contains the following items:
  8. major version string (used when naming directories)
  9. GUI type (only "Qt")
  10. apex release number (used when naming directories).


An example of such a list is: 

['2023  R2', 'standard', 'win64', 'C:\\Program Files (x86)\\CEI', '2023  R2', None, 

{'customer': 'FOO', 'username': 'BAR', 'hostid': ['JUNK'], 'ip': '192.168.1.1', 'company': 'FOO', 'expdate': 'June 26, 2014', 'host': 'HOSTNAME', 'contact': 'BOB', 'slimversion': '6.31', 'keypath': 'C:\\Program Files (x86)\\CEI\\license8\\slim8.key'}, 

'232', 'Qt', '232']


Qt window positioning

rect = ensight.qtposition(w, [xtgt,f0x,f1x], [ytgt,f0y,f1y] [,recalc=r] [,clamp=c] [,target=t] [,show=s] [,offset=[dx,dy]])

w = the Qt widget (toplevel) that you want to reposition. You can also pass a list of the form [x,y,dx,dy] (a rectangle) instead and the function will compute the output location of that rectangle.

xtgt, ytgt = the rectangle to move the widget with respect to. Note that different reference rectangles can be used for the horiz and vert alignment. Valid values include:

ensight.POS_TGT_MAINWIN - the is the rectangle of the main ensight window or the window registered by a python gui (e.g. CFD)

ensight.POS_TGT_CURSOR - this is a single pixel rectangle at the current mouse cursor location

ensight.POS_TGT_PRIMARYSCN - this is the "usable" rectangle of the system's "primary" screen (it does not include any boundary bars)

ensight.POS_TGT_CURSORSCN - this is similar to above, but for the system's screen the mouse is currently in

ensight.POS_TGT_WIDGET - if this is specified, you must specify a Qt Widget via the 'target=' keyword. The rectangle of that widget is used.

ensight.POS_TGT_WIDGETSCN - if this is specified, you must specify a Qt Widget via the 'target=' keyword. The rectangle of the screen that contains the widget is used.

ensight.POS_TGT_MAINWINSCN - the rectangle of the screen that contains the main window is used.


ensight.POS_TGT_NONE - no positioning is performed, but clamping and display operations may still be specified.

f0x, f0y = selects the point in widget w that should be aligned with the point in the target rectangle. These are normalized coords (0.0 to 1.0).

f1x, f1y = selects the point in target rectangle that should be aligned with the point in the widget. These are normalized coords (0.0 to 1.0).

clamp = defaults to ensight.POS_CLAMP_SCREEN.  If the position that would be selected placed the window offscreen, it will be snapped so at least the upper left corner is visible.  Clamp may also have the value ensight.POS_CLAMP_NONE and no screen clamping will be applied.

target = specifies the widget whose rectangle should be used with the POS_TGT_WIDGET

show = if set to a non-zero value, will cause the widget to have show() called on it before being moved.

offset = specifies an offset in pixels to be added to the window upper left corner after the position is selected, but before clamping.

The return value is the rectangle that the widget was sized/positioned to. If you pass a list of integers instead of a widget for 'w' in the form [x,y,dx,dy], that rectangle will be used for the computation in surrogate.

How about an example? 

from PyQt4 import QtGui

w = QtGui.QWidget(...)
...
xp = [ensight.POS_TGT_CURSORSCN,0.5,0.5]
yp = [ensight.POS_TGT_CURSORSCN,0.,0.]
rect = ensight.qtposition(w, xp, yp ,show=1)


will display the dialog centered horizontally, but at the top of the screen the cursor is currently in. The classic example of the tradition color dialog (to the left of the main window, aligned at the top) would be:

xp = [ensight.POS_TGT_MAINWIN,1.,0.]
yp = [ensight.POS_TGT_MAINWIN,0.,0.]
rect = ensight.qtposition(w, xp, yp, show=1)


Read [ensight.POS_TGT_MAINWIN,1.,0.] as the right (1.0) edge of the widget needs to be aligned with the left (0.0) edge of the main window.

Rendering Material Definition

ensight.update_userdefined_material(parent_name, name [,material=definition_dictionary]): EnSight includes a collection of pre-defined materials.  This API allows the caller to modify this list. The list is two-tiered with a parent string and a material name.  In the GUI, it looks like this:

The 'parent_name' and 'name' are required and select the material to edit.  For example:  'Paint', 'Satin'.  The 'material' keyword parameter defines the properties of the material.  If 'material' is not set, this function will remove the material from the list. If 'material' is specified and the named material does not exist, a new material will be added.  If it does exist, the definition of the material will be replaced.

The 'material' parameter is a dictionary with the following keys:

Key (string)

Values

"material_type" (default "PLASTIC")

"ENSIGHT"

"GLASS"

"KDSUBSURFACE"

"MATTE"

"MEASURED"

"METALLICPAINT"

"METAL"

"MIRROR"

"MIX"

"PLASTIC"

"SHINYMETAL"

"SUBSTRATE"

"SUBSURFACE"

"THINGLASS"

"TRANSLUCENT"

"UBER"

"VELVET"

The material type is primarily useful for raytracing renderers. It is used when exporting a material to a raytracer. The "ENSIGHT" material type is used by the base (non-material aware) EnSight rendering engine.

"gamma_corrected" (default 0)

0 if the values are in linear RGB, 1 if they are gamma corrected sRGB

"color" (default [0.92, 0.92, 0.92])

The base color of the material.  This value can be different from the Fresnel reflectance computed using eta and k.  It allows the user to modify the appearance of a material, even though it has been defined as a fixed type, such as ‘Copper’ with a green color. 

"eta" (default [1.52, 1.52, 1.52])

Index of refraction for the RGB components. Exact values can be looked up from a material handbook. All the values > 0.

"kta" (default [0.0, 0.0, 0.0])

Absorption coefficient for conductors. The computation of Fresnel reflectance is determined by the following: 

     

     

"ka" (default 0.2)

Ambient ratio. The ambient color is computed as base color * ka.

"kd" (default 0.4)

Diffuse ratio. The ambient color is computed as base color * kd.

"ks" (default 0.0)

Specular ratio. The specular color color_specular is computed using the tint value and the base color. Then, the specular color is color_specular * ks.

"kr" (default 0.0)

Reflection ratio. The reflected color is color_reflect * kr.

"smoothness" (default 0.5)

In the range [0.0..1.0], where 0.0 is coarsest and 1.0 is smoothest. 

"tint" (default 0.0)

For controlling the specular color and reflection color, which is mix( [1., 1., 1.], "color", "tint"). Usually plastic has a value 0, while metal has a value 1. 

"metallic" (default 0.0)

In the range [0.0..1.0], where 0 is dull and 1 is reflective metallic.

"opacity" (default 1.0)

Transparency of the material [0.0...1.0]. 0.0 is fully  transparent and 1.0 is fully opaque.

"reflection_map" (default 0)

Integer [0...9]:

   0 = no reflection map

   1-3 = light reflection maps

   4-6 = dark reflection maps

   7 = water 

   8 = sky/sea

   9 = environmental map

"uifilter" (default 0)

Select which sliders in the EnSight material GUI should be enabled.  The sliders to be enabled are selected by or-ing together the following:

    AMBIENT_COMPONENT = 1 : ambient slider

    DIFFUSE_COMPONENT = 2 : diffuse slider

    SPECULAR_COMPONENT = 4 : specular intensity slider

    SPECULARSHINE_COMPONENT = 8 : specular shininess slider

    SPECULARTINT_COMPONENT = 16 : specular tint slider

    REFLECTIVE_COMPONENT = 32 : reflection slider

    TRANSMITIVE_COMPONENT = 64 : opacity slider

    REFRACTONINDEX_COMPONENT= 128 : refraction index slider

"thumbnail" (default None)

If specified, this should be a 'bytes' object containing the contents of a .png file (the disk representation of a .png image).  This image will be displayed as an icon in the color editor instead of the rendered swatch.


An example of a new material with a thumbnail might be:

 with open("filename.png", "rb") as png:

     img = png.read()

 ensight.update_userdefined_material("Test", "MyColor", dict(color=[0., 1., 0.], uifilter=3, thumbnail=img))


Object Pixel Picking

ensight.query_pixelbuffer(x, y [,x2=x] [,y2=y] [,parts_only=False] [,deep_part_check=False]) : This method allows the caller to probe the rendered pixel buffer and determine which parts or other objects are visible at a point or within a rectangle of pixels. The method can work in two ways, "Object mode" or "Part mode".  In all cases, the x and y coordinates within the rendering window must be specified in pixels.  0,0 is the lower left corner of the window. ensight.objs.core.WINDOWSIZE[0]-1,ensight.objs.core.WINDOWSIZE[1]-1 is the upper-rightmost pixel.  Specifying a rectangle of pixels is done by including x2 and y2 keyword arguments

Object mode is select by only passing the x and y single pick point and no other options. In this mode, the returned value is a list of lists. For example:

[[partobj, [x,y,z]], [partobj, [x,y,z]], [annotobj, [x,y,z]]]

For a part, the x,y,z coordinates are the location on the part in model space.  For a 2D object like an annotation, x and y are the normalized screen coordinates and z is the normalized front clip plane.  Note that this operation can be slow if a rectangle is specified.

Part mode is selected by specifying 'parts_only=True' or 'deep_part_check=True'.  In part mode, the return value is a simple list of part objects. This is normally done by interrogating the rendered pixels for the target parts.  If deep_part_check is True, it is computed by intersecting the geometry with the point or rectangle.  This can pick parts hidden behind other parts. 


Dynamic Scene Graph Export Interface

The dynamic scene graph (DSG) interface is normally a gRPC API supported by EnSight. See this link for additional information about the DSG gRPC interface. It is also possible to capture all of the protocol buffers generated by a DSG scene update and save them into a zip format file. Such a file is usually named with the .dsgz suffix. The file can either be a complete dump of the current scene or it can be an incremental update. These APIs allow such files to be saved from the EnSight Python interface.


ensight.dsg_save_update(filename [,incremental=0] [,temporal=0] [,stream=None])


       This call will save a named file to disk containing the protocol buffers.  If the current EnSight scene is temporal and the 'temporal' keyword is set to non-zero, all of the timesteps will be saved into the file (vs the current timestep).  The interface also supports incremental saves. To generate an incremental update, the 'incremental' keyword should be set to a non-zero value and the context of the operation is specified using a stream. The 'stream' keyword may be set to a stream id, allocated using ensight.dsg_new_stream() which is passed to every update in the saving sequence.  Note: it is legal to save a non-incremental update in the middle of a stream. This can be used to 'reset' the scene state and reduce the number of updates needed to applied to achieve the current scene state. 


streamid = ensight.dsg_new_stream()


This call will allocate a new dsg stream id that can be passed to dsg_save_update() to provide update sequence control.


ensight.dsg_close_stream(streamid)


       Once an update stream is no longer needed, the id associated with the stream should be freed using this command.


Examples:

Simple saving of the current scene in a .dsgz file:


ensight.dsg_save_update("CurrentScene.dsgz", temporal=0)


This would be a complete copy of the scene, just for the current timestep.


Scene and a subsequent update:


streamid = ensight.dsg_new_stream()

ensight.dsg_save_update("SceneSequence_0.dsgz", temporal=0, incremental=1, stream=streamid)

...

ensight.dsg_save_update("SceneSequence_1.dsgz", temporal=0, incremental=1, stream=streamid)

ensight.dsg_close_stream(streamid)


The file SceneSequence_0.dsgz will be a complete representation of the dataset (as if incremental was specified as 0) because the previous streamid state was empty. The file SceneSequence_1.dsgz contains only the scene differences from when the first file was saved.  During subsequent display, rendering the two files in succession will result in the same scene state as when the dsg_close_stream() call was made.