MultiBlockDataSet assign name to children

I have written a Python reader to load the files I am getting from my simulations. The file contains a hierarchy of groups and meshes and I create a vtkMultiBlockDataSet hierarchy with vtkUnstructuredGrids for the meshes.

The loader works fine, the only issue is that I don’t know how to assign a name to each VTK object the reader is creating.

Given a vtkMultiBlockDataSet or vtkUnstructuredGrid created in Python, how can I assign names to them? Right now the hierarchy looks okay in the MultiBlock Inspector, but its very difficult to understand what is each block without names.

vtkCompositeDataIterator has a GetCurrentMetaData() method. vtkCompositeDataSet::NAME() returns a string information key that holds a name for the matching dataset.

vtkCompositeDataIterator* it;
it->GetCurrentMetaData()->Set(vtkCompositeDataSet::NAME(), "Foo");

should do what you want.

Thanks. But, I should have mention I am using Python. Any way to do It in Python?

I have tried adding this in the Python code

                children_mb = frame_scene(group)
                print(group.name)
                children_mb.GetInformation().Set(
                    vtkMultiBlockDataSet.NAME(), "asdf")
                mb.SetBlock(id, children_mb)

So basically assigning “asdf” as name for each of the MultiBlockDataSet I am creating.
Executes fine, but in the Multi-Block Inspector, the name doesn’t appear, still says “Block0”

There are 2 places in composite data where vtkInformation objects are held:

  • in the data objects/set that are leaf nodes in the composite data (accessed with vtkDataObject::GetInformation)
  • in the parent composite dataset class (accessed via the iterator).

Your python code is adding a NAME key-value pair to the former; my C++ example to the latter. ParaView uses the latter to show names.

All the classes are python-wrapped, including the iterator.

How do I get the iterator? In the C++ example is default constructed

You ask the dataset to construct you one with its NewIterator() method. Note: you own the returned iterator and must Delete() it when done.

I still dont totally understand how to use the iterator to assign the names to the datasets I am loading.
I am creating MultiBlockDataSets following the hierarchy I have in an HDF5, using a recursive function.

def frame_scene(current_group):
    mb = vtkMultiBlockDataSet()
    # mb.SetName(current_group.name)
    mb.SetNumberOfBlocks(len(current_group))

    # Iterate on groups
    if type(current_group) == h5py.Group:
        for id, group in enumerate(current_group.values()):
            if "mesh" in group.attrs:
                mesh = parse_mesh_group(group)   # Returns None or a vtkUnstructuredGrid
                if mesh is not None:
                    mb.SetBlock(id, mesh)
            else:
                children_mb = frame_scene(group)  # Returns a vtkMultiBlockDataSet
                mb.SetBlock(id, children_mb)
                it = mb.NewIterator()
                it.GetCurrentMetaData().Set(vtkMultiBlockDataSet.NAME(), "adsf")
                it.Delete()

    return mb

This code only assigns “adsf” name to the first leaf node in each branch…

So how is the iterator working?

Hey @Juan_Jose_Casafranca

Your iterator is not iterating.
By default it points to the first block in your MBDS (flat index of 0), so you’re only setting the name of the first child each time. You need something like:

it = mb.NewIterator()
idx = 0
while not it.IsDoneWithTraversal():
    it.GetCurrentMetaData().Set(vtkMultiBlockDataSet.NAME(), "name"+str(idx))
    idx += 1
    it.GoToNextItem()

Hope that helps!

I don’t know if it is possible to use for loops with these type of iterators. I’ve never tried because I’ve never seen an example.

It would be great if one could, though. Often I forget the GoToNextItem method and get stuck in an infinite loop!

I did something similar to your suggestion.

                iter = frame.NewIterator()
                iter.SetVisitOnlyLeaves(False)
                iter.SetSkipEmptyNodes(False)
                iter.InitTraversal()

                while not iter.IsDoneWithTraversal():
                    currentIdx += 1
                    name = pathlib.PurePath(names[currentIdx]).name
                    iter.GetCurrentMetaData().Set(
                        vtkMultiBlockDataSet.NAME(), name)
                    iter.GoToNextItem()

being frame the root vtkMultiBlockDataSet. Is there any way to also set the name for this root? The code only sets the children (and children of children)