Transition from EnSight 9 Groups

Miscellaneous ››
Parent Previous Next

EnSight 10 Groups

Prior to EnSight 10.0, EnSight used a simple 'group part' model for grouping parts.  This group was both a collection of groups and an actual EnSight part. It only allowed for a single level of grouping and could only be applied to parts. In 10.0, the grouping mechanism was changed.  EnSight now maintains a hierarchy of part and group objects and displays these as the part list and the variable list.  Users can now drag and drop objects in these lists and move objects between the groups more easily. Grouping is now allowed to any depth and for any type of object. 

These changes did come at a price. The command language used to describe groups became more complex and backward compatibility could not be maintained. Let's start with command language.

Command language groups

In 9.2, EnSight might generate command language like this:

part: select_begin
 1

part: select_end

part: group Hello

This would create a group named 'Hello' with a single part (1) placed into it.  It also created a new part and in other operations, one could use the group part for things like selection, etc.

 

In 10.0, EnSight generates command language like this:

ext: treecmd.treecmds begin
ext: treecmd.treecmds case 'Case 1'
ext: treecmd.treecmds path 'Hello'
ext: treecmd.treecmds create_group
ext: treecmd.treecmds begin
ext: treecmd.treecmds case 'Case 1'
ext: treecmd.treecmds path 'Hello'
ext: treecmd.treecmds part 'Computational mesh'
ext: treecmd.treecmds reparent_part
ext: treecmd.treecmds begin
ext: treecmd.treecmds case 'Case 1'
ext: treecmd.treecmds path 'Hello'
ext: treecmd.treecmds lpart 'Computational mesh'
ext: treecmd.treecmds reparent_lpart

 

All grouping commands are implemented as a Python extension named 'treecmd.treecmds'. All commands begin with a 'ext: treecmd.treecmds begin' command, set a number of parameters and end with a command in the form 'ext: treecmd.treecmds {action}'.  In the example the action 'create_group', creates a new group named 'Hello' inside of 'Case 1'.  The action 'reparent_part' places the part named 'Computational mesh' into the new group and 'reparent_lpart' similarly places the part loader part (lpart) into the group. Unlike the 9.2 example, no additional parts are created for the group and any situations that need to use the group as a selection must select all of the parts in the group.

 

To transition from 9.2 to 10.0, the three biggest issues are moving to the new syntax, recognizing that the part numbering might be different because the group part is not created and ensuring that operations that rely on the selection of the group part use the explicit list of parts in the group instead.

Python group interfaces

The EnSight Object Python API has a much simpler interface for working with groups, however, one must adopt the EnSight Object API which bears little resemblance to command language or the EnSight 'native' Python API. The grouping interface starts with the ENS_CASE and ENS_GROUP object 'creategroup()' methods. To create a group in the Object API one might use code like this:

 

from ensight.objs import *

cse = core.CURRENTCASE[0]

grp = cse.creategroup("Hello")

grp.addchild(core.PARTS[0])

 

This will create a group inside of the current case named 'Hello' and add the first EnSight part into that group. See the ENS_GROUP page for additional group methods.  One can add a group under the group using calls like this:

 

from ensight.objs import *

cse = core.CURRENTCASE[0]

grp = cse.creategroup("Hello")

grp2 = grp.creategroup("Bye")

grp3 = cse.creategroup("See ya")

grp.addchild(grp3)

 

which adds two groups under the 'Hello' group using different methods. 

EnSight includes both ENS_PART and ENS_LPART objects as leaves in the partlist.  If an lpart shares the same name as a part in the same group, the display of the lpart is suppressed by default.  When moving parts to other groups, it is not uncommon to want to move the associated (and often hidden) lpart as well.  So code list this can be used:


for p in part_list:
    par = p.PARENT
    lpart = p.LPART
    if (lpart):
        if (lpart.PARENT == par):
            target_group.addchild(lpart)
    target_group.addchild(p)

This can be slow, so in 10.0.3(a) and later, the addchild() method include the optional 'include_lpart' keyword.  The following is equivalent to the previous snippet:

target_group.addchild(part_list,include_lpart=1)

Finding objects

One of the most common issues when using this API is finding the proper list of objects to add to things.  The core.find_objs() method is an extremely powerful means to do this.  For example, to find all of the parts and part loader objects in the current case:

 

list = core.find_objs(core.CURRENTCASE[0],types=[ENS_PART, ENS_LPART],recurse=1)

 

or the immediate child groups in a case:

 

list = core.find_objs(core.CURRENTCASE[0],types=[ENS_GROUP])

 

One can also filter by any collection of additional attributes.  To find all of the nodal variables:

 

f = {enums.LOCATION: enums.ENS_VAR_NODE}

list = core.find_objs(core.VARIABLES,filter=f)

 

When working with groups, the ability of find_objs() to optionally recurse through groups and apply a collection of filtering options can be very useful.  See Core: ENS_GLOBALS for more details on this method.


There is also a list of all of the current groups (over all cases and for object types other than parts) located at ensight.objs.core.GROUPS.  This is an ensobjlist object, so one can use it to find a group by name fairly simply with:


g = core.GROUPS['groupname']


which will return the group object for which the DESCRIPTION attribute is 'groupname'.  See the Utility Classes: ensobjlist page for more information on how to simplify searching.  The following code snippet could be used to select all of the parts in a group with a specific name:


enscl.tmp = ensight.objs.core.find_objs(ensight.objs.core.GROUPS['car'],types=[ensight.objs.ENS_PART],recurse=1)

ensight.objs.core.selection().addchild(enscl.tmp,replace=1)


Roughly, this amounts to find the group named 'car' and get a list of all of the ENS_PART objects in it or the children of it. Next, get the default selection object and replace the current part selection (the default selection) with that list of parts. The above example is written using 'ensight' and 'enscl' prefixed lines.  This makes these two lines legal as both Python and command language, so one could use them in a .py or .enc file (note that the first line is one, single line). Examples of embedding Python code in .enc files can be seen here: Python in .enc Files.

Root groups

In the example, groups were being added under a case in the partlist. In this mode, the ENS_CASE object is the root of the tree. One can get the current case via core.CURRENTCASE[0] or a complete list of cases via core.CASES. 10.0 also allows for groups of variables.  The root of the variable tree is core.VARIABLETREE[0]. One can add groups under that root and move ENS_VAR objects around in that tree.  The example:

 

from ensight.objs import *

g = core.VARIABLETREE[0].creategroup("My vars")

list = core.find_objs(core.VARIABLETREE[0],type=[ENS_VAR])

g.addchild(list)

 

will place all of the variables at the root of the variable tree list into a group named "My vars".

Part selection

In the object API, part selection is handled a bit differently. There is a group object that always reflects the current object selection. core.selection(ENS_PART) is a group of the currently selected parts. For example, if one wanted to select all of the parts in EnSight:

 

core.selection(ENS_PART).addchild(core.PARTS)

 

will do that.  One can use the object searching API to narrow things down a bit.  To select all of the parts inside of a given group:

 

tmp = core.find_objs(group,types=[ENS_PART],recurse=1)

core.selection(ENS_PART).addchild(tmp)

 

The find_objs() call recursively walks the groups rooted at 'group', looking for objects of type ENS_PART.  It then makes that the current part selection.

Handy transitional tools

To aid in the transition, we have pulled together some handy script methods.

Some users have converted their .enc file to Python.  These conversions include commands like:

ensight.part.select_all()
ensight.part.group('new group')
ensight.part.select_lastcreatedpart()


Which will create a new group and set the selection to the group, but are not supported in 10.0.  Some helpful Python functions that wrapper similar functionality, and work in 10.0, are shown below:


from ensight.objs import *
from operator import attrgetter

 

def simple_group(name):
    g = core.CURRENTCASE[0].creategroup(name)
    g.addchild(core.selection().CHILDREN)
    return g


def select_lastcreatedgroup(name=None):
    top = core.CURRENTCASE[0]
    if name:

        # find the group by name
        f = {'DESCRIPTION': name}        
        glist = core.find_objs(top,filter=f,types=[ENS_GROUP],recurse=1)
        if len(glist) == 0:

            return
        g = glist[0]
    else:

        # find the last created group
        glist = core.find_objs(top,types=[ENS_GROUP],recurse=1)
        if len(glist) == 0:
            return
        g = sorted(glist,key=attrgetter('__objid__'))[-1:][0]

    # get the part objects in the group
    cp = core.find_objs(g.CHILDREN,types=[ENS_PART],recurse=1)

    # change the current selection to be those parts
    if len(cp):
        core.selection().addchild(cp, replace=1)

    
They allow you to create a new group from the current part selection and remember the last group that was created, so that one can use it to set the selection later.  With these functions, one can rewrite as:

 

ensight.part.select_all()
simple_group("NewGroup")
select_lastcreatedgroup()

 

or later, by group name:

 

select_lastcreatedgroup("NewGroup")

 

The EnSight Object Python API provides a strong set of tools that can be used to replace EnSight native Python API code used with versions of EnSight prior to 10.0.