Group

Sidre Group objects are used to define a tree-like hierarchical organization for application data, such as meshes and fields used in a simulation. Each group has a name and one parent group (except for the root group, which has no parent) and contains zero or more child groups and zero or more data views. A Sidre datastore has exactly one root group that is created when the datastore is created. The root group’s name is initially the empty string. See DataStore for more information.

A group hierarchy is constructed by creating child groups of the root group, children of those groups, and so on. All groups in a subtree rooted at a particular group are considered descendants of that group. View objects can be created in groups to hold or provide access to data of various types.

Note

Group and View objects can only be created and destroyed using Group class methods. The Group and View class constructors and destructors are private.

A group or view is owned by the group that created it; i.e., its parent group or owning group, respectively. Groups and views maintain pointers to their parent/owning group. Thus, one may walk up or down a group hierarchy to access groups and views in it, as needed.

Note

  • The name (string) of a group or view must be unique within its parent/owning Group.

  • A group or view has a unique integer identifier within its parent/owning group, which is generated when it is created.

  • Views and child groups in a group can be accessed by name or integer id.

A group can be moved or copied to another group. When a group is moved to another group, it is removed from its original parent and the group to which it is moved becomes its parent. This implies that the entire subtree of groups and views within the moved group is moved as well and can no longer be accessed via the original parent group. When a group is copied to another group, a copy of the entire group subtree rooted at the copied group is added to the group to which it is copied. A shallow copy is performed for the data in each view. Specifically, a new view objects is created in the destination, but the data is shared by the original and new view.

Note

View object copy operations perform shallow copies of the data in a view.

Some methods for creating, destroying, querying, and retrieving groups and views take a string with path syntax, where parent and child group names are joined with the path separator character ‘/’. Other methods take the name of an immediate child of a group. Methods that require the name of an immediate child are marked with ‘Child’ in their name, such as hasChildView() and hasChildGroup(). When a path string is passed to a method that accepts path syntax, the last item in the path indicates the item to be created, destroyed, accessed, etc. For example,:

View* view = group->createView("foo/bar/baz");

is equivalent to:

View* view = group->createGroup("foo")->createGroup("bar")->createView("baz");

In particular, intermediate groups “foo” and “bar” will be created in this case if they don’t already exist. The path syntax is similar to a Unix filesystem, but the path string may not contain the parent entry, such as “../foo”, or current group, such as “./bar”.

Methods to Operate on Groups

The following lists summarize Group class methods that support operations related to groups.

Note

  • Methods that access groups by index only work with the immediate children of the current group because an id has no meaning outside of the indexing of the current group. None of these methods is marked with ‘Child’ in its name.

  • When a group is created, destroyed, copied, or moved, ids of other views and groups in its parent group may become invalid. This is analogous to iterator invalidation for containers when the container contents change.

Create, Modify, and Destroy Groups

  • Create a child group given a name (child) or path (other descendant). If a path is given, intermediate groups in path are created, if needed.

  • Rename a group. A group cannot be renamed to the empty string, to a string containing the path separator character, or to the name of another group or view owned by the same parent.

  • Destroy a descendant group with given id (child), or name/path (child or other descendant).

  • Destroy all child groups in a group.

Note

When a Group object is destroyed, all groups and views in the subtree rooted at the destroyed group are also destroyed. However, the data associated with the views will remain intact.

Group Properties

  • Retrieve the name or id of a group

  • Retrieve the full path name from the root of the tree to a group

  • Get a pointer to the parent group of a group

  • Query the number of child groups of a group

  • Query whether a group has a descendant group with a given name or path

  • Query whether a group has an immediate child group with a given integer id

  • Query the name of a child group with a given id, or the id of a child group with a given name

  • Get a pointer to the datastore that owns the hierarchy in which a group resides

Group Access

  • Retrieve an immediate child group with a given name or id, or a descendant group with a given path

  • Iterate over the set of child groups of a group. One can use the “range-for” syntax or the iterator syntax

// 'range-for' syntax:

for(auto& grp: someGroup->groups()) { /* ... */ }

// 'iterator' syntax:
for(auto it = someGroup->groups().begin(),
      itEnd = someGroup->groups().end(); it != itEnd; ++it)
 {
   auto& grp = *it;
   /* ... */
 }

Move and Copy Groups

  • Move a group, and its associated subtree, from its parent group and make it a child of another group

  • Create a copy of group subtree rooted at some group and make it a child of another group

  • Query whether a group subtree is equivalent to another; i.e., identical subtree structures with same names for all groups and views, and views are also equivalent (see View Property Operations).

Methods to Operate on Views

Group class methods that support operations related to View objects are summarized below. For more details on View concepts and operations, please see View.

Note

Methods that access views by index work only with the views owned by the current group because an id has no meaning outside of the indexing of the current group. None of these methods is marked with ‘Child’ in its name.

Create Views

  • Create a view in the group with a name only.

  • Create a view in the group with a name and data description.

  • Create a view in the group with a name and with a Buffer attached. The View may or may not have a data description.

  • Create a view in the group with a name and an external data pointer. The data may or may not be described.

  • Create a view in the group with a name and data description, and allocate the data. Implicitly the data is held in a buffer that is attached to the view.

  • Create a view in the group with a name holding a given scalar or string.

Destroy Views

  • Destroy view with given id (child), or name/path (view in the group or some descendant group), and leave view data intact.

  • Destroy all views in the group, and leave their data intact.

  • Destroy view with given id, or name/path, and destroy their data.

  • Destroy all views in the group and destroy their data.

View Queries

  • Query the number of views in a group.

  • Query whether a group subtree has a view with a given name or path.

  • Query whether a group has a view with a given integer id.

  • Query the name of a view with a given id, or the id of a view with a given name.

View Access

  • Retrieve a view in the group with a given name or id, or a descendant view (somewhere in the subtree) with a given path.

  • Iterate over the set of views owned by the group. One can use the “range-for” syntax or the iterator syntax

// 'range-for' syntax:
for(auto& view: someGroup->views()) { /* ... */ }

// 'iterator' syntax:
for(auto it = someGroup->views().begin(),
      itEnd = someGroup->views().end(); it != itEnd; ++it)
 {
   auto& view = *it;
   /* ... */
 }

Move and Copy Views

  • Move a view from its owning group to another group (removed from original owning group).

  • Copy a view to another group. Note that this is a shallow copy of the view data; i.e., it is shared by the original and the new view in the destination group.

List Format

The list format is an alternate way for a group to hold its child groups and views. In list format, any number of child group or view items can be created. Each can be accessed, in order of creation, using an iterator over groups or over views. Child groups and views held in list format cannot be accessed by name.

To create a group that uses the list format, the optional argument is_list must be set to true in the call to createGroup.

// list_group will hold its child items in the list format.
Group* list_group = group->createGroup("my_list", true);

It is recommended but not required that the items held in the list format be created without names. String names may be assigned to these items, but the names will not be useful for accessing them from their parent group, and none of the methods that access child items by name or path will return a valid pointer. The method createUnnamedGroup is available to create an unnamed child group, while unnammed views can be created by passing an empty string to any of the several createView methods in the Group class.

Group* g0 = list_group->createUnnamedGroup();
Group* g1 = list_group->createUnnamedGroup();
Group* g2 = list_group->createUnnamedGroup();
View* v0 = list_group->createView("");
View* v1 = list_group->createViewScalar("", 1.0);
View* v2 = list_group->createViewString("", "foo");
View* v3 = list_group->createView("", type, num_elems, buffer);

While it is allowed to pass a non-empty string to be the name of a child item held in the list format, a string with path syntax, like "foo/bar/baz", will be considered invalid, and the object creation methods will return a nullptr if such a string is provided.

// This is valid, but the string name will not be useful for future access.
View* foo = list_group->createView("foo");
// This is invalid due to the path syntax, a nullptr will be returned.
View* baz = list_group->createView("bar/baz");

Group I/O Operations

The group interface provides methods to perform data I/O operations on views in the group subtree rooted at any group.

  • Copy a description of a group subtree to a conduit::Node.

  • Create native and external data layouts in conduit::Node hierarchies (used mainly for I/O operations)

  • Save and load group subtrees, including data in associated views, to and from files. A variety of methods are provided to support different I/O operations, different I/O protocols, etc.

I/O methods on the group class use Conduit to write the data (sub)tree rooted in a group to a file, HDF5 handle, or other Conduit protocol, or to an in-memory Conduit data structure. Please see Sidre Interaction with Conduit for more information. An application may provide an attribute to the method call, so only views with that attribute explicitly set will be written. See Parallel File I/O for more information.