VTKm: Reading DataSet from Legacy .vtk-File

Hello!

In context of my final Bachelors work I’m trying to read a Legacy .VTK-File using the vtkm::io::reader::VTKDataSetReader and then run a Countour Filter on it. The DataSet successfully is read, although it throws two warnings:

2020-05-12 16:07:12.392 ( 6.164s) [main thread ] VTKDataSetReaderBase.h:515 WARN| Reader may not correctly read >v4.2 files. Reading version 5.0.
2020-05-12 16:07:12.395 ( 6.167s) [main thread ] VTKDataSetReaderBase.h:602 WARN| Support for COLOR_SCALARS is not implemented. Skipping.

Im not sure how to create 4.2 .VTK Files. The ones I use right now are created using ParaView from a .RAW File where I manually put in dimensions, word length and endian type.

When I further try to run a Contour-Filter on the DataSet I get a Exception thrown by the DataSet and my program crashes.
Code:

vtkm::io::reader::VTKDataSetReader reader(path.toStdString());
vtkmDataSet = reader.ReadDataSet();

vtkm::filter::Contour contour;
contour.SetActiveField("pointvar");

vtkm::cont::DataSet outData = contour.Execute(vtkmDataSet); // exception thrown on this line

vtkm::rendering::Actor actor(
    outData.GetCellSet(),
    outData.GetCoordinateSystem(),
    outData.GetField("pointvar")
);

Exception:
ErrorBadValue(No field with requested name: pointvar)

The filter seems to work when I use Mock-DataSets created at runtime by VTKm.

Running on Windows 10
VTKm 1.5.1
Compiled with VS 2017 Community
CMake 3.17.2

If you need further Information please tell me what exactly I can further provide. Im happy for all help I can receive.

Sending best regards,
David

Hello David,

If you are exporting your datasets using ParaView, I would recommend using its xml readers/writers over its legacy readers/writers. You will likely have more success reading in the generated dataset.

Sincerely,
T.J.

Hello T.J.,

Is there a special XML-ReaderClass, or does the VTKDataSetReader also the class I would use for that?

Thank you!
David

You would want to use vtkXMLReader.

Thank you, will try in a Minute.

This now makes me curious. In a completed older project I used vtkMetaImageReader to obtain Data from MHD-Files. How compatible are VTK and VTKm? Will I maybe be able to use the exat same code to import data into the VTKm Projekt? Is the vtkmDataSet compatible with the vtkDataSet?

Hi T.J.

So the import seems to be working just fine. But im still experiencing the issue with the ErrorBadValue-Exception from the Original question. Any idea on how I can further debug that?

Currently im using a XML Reader an then convert the data to a vtkmDataSet via the “DataSetConverters”-helpers provided in VTK:

vtkNew<vtkXMLRectilinearGridReader> reader;
reader->SetFileName(path.toLocal8Bit().data());
reader->Update();

vtkmDataSet = tovtkm::Convert(reader->GetOutputAsDataSet());
vtkmDataAvailable = true;

I also tried the same with an vtkMetaImageReader:

vtkNew<vtkMetaImageReader> reader;
reader->SetFileName(path.toLocal8Bit().data());
reader->Update();

vtkmDataSet = tovtkm::Convert(reader->GetOutput());
vtkmDataAvailable = true;

Both solutions still trigger the Exception.

Happy for any help and best regards,
David

Can you confirm that the dataset from reader->GetOutputAsDataSet() contains a field “pointvar”? My guess is either the vtkm converter is not passing this array through correctly, or there is no array in the first place.

Actually, sadly i can’t. To be honest im not sure how to successfully render one of my Datasets using vtkm. The same Datasets were successfully used in VTK but I can’t manage to get it working in VTK-m.

I already successfully setup an OpenGL pane in my GUI and I am able to render to it.

In my old project I was using the MarchingCubes algorithm for example. I can’t even seem to include that in VTK-m, do you know if I have to enable a option in CMake while compiling VTK-m to eanble that filter?

The tovtkm::Convert function has two signatures. The single parameter version converts only point coordinates and topology, all fields are not converted. To convert fields you need to use the two
parameter version like this:

vtkmDataSet = tovtkm::Convert(reader->GetOutputAsDataSet(), tovtkm::FieldsFlag::PointsAndCells);

An easy way to debug/see what is part of a vtkm::cont::DataSet is to use the PrintSummary method:

vtkmDataSet.PrintSummary(std::cout);

The VTK-m entry points for iso-contouring are vtkm::filter::Contour and vtkm::worklet::Contour. These classes will internally select an appropriate implementation such as MarchingCells or FlyingEdges based on the input data. It is not possible to explicitly call MarchingCubes

Thank you for your Help!

So this is the output of my program when I print the Dataset after I added the flags you suggested. How would I be able to determain how to create a contour over this?

MainWindow::onOpenMHDFile path=D:/Studium/Abschlussarbeit/raw/Lobster_u8_301_324_56_LE.mhd
DataSet:
  CoordSystems[1]
   Coordinate System    coords assoc= Points valueType=class vtkm::Vec<float,3> storageType=struct vtkm::cont::StorageTagVirtual numValues=5461344 bytes=65536128 [(0,0,0) (1,0,0) (2,0,0) ... (298,323,55) (299,323,55) (300,323,55)]
  CellSet
  StructuredCellSet:
   UniformConnectivity<3> pointDim[301 324 56]
  Fields[1]
   MetaImage assoc= Points valueType=unsigned char storageType=struct vtkm::cont::StorageTagVirtual numValues=5461344 bytes=5461344 [0 0 0 ... 0 0 10]

Your field name in VTK-m is MetaImage and not pointvar. Your original example should work with the correction for the field name.

Thank you, finally making progress, sadly running into the next issue rather quickly. When I execute the contour I get some (to me) rather cryptic error messages and then a crash:

16:03:06.986 (  17.858s) [main thread     ]         TryExecute.cxx:55     ERR| TryExecute encountered an error: ErrorBadValue (Input array to worklet invocation the wrong size.)
16:03:06.989 (  17.861s) [main thread     ]         TryExecute.cxx:55     ERR| Failing functor: struct vtkm::worklet::internal::detail::DispatcherBaseTryExecuteFunctor
16:03:06.991 (  17.863s) [main thread     ]         TryExecute.cxx:55     ERR| Failing device: Serial

The “Input array to worklet invocation the wrong size.” error message means that the MetaImage field length doesn’t match the number of points in the input data.

It sounds like the input data set being to VTK-m isn’t the exact same one as you read from disk, and therefore have a different number of points.

Thank you, but how can I control that? Why would the transformation create a DataSet not equal to the one loaded? Or did I specify a wrong dimension size? Last isn’t likely, since the MetaImage is read fine in plain VTK.

Should the number of cells and the number of points be the same?

vtkmDataSet.GetNumberOfPoints()

returns 5 461 344 (=301 x 324 x 56, matches dimensions)

vtkmDataSet.GetNumberOfCells()

returns 5 329 500 (=300 x 323 x 55, shoudlnt this be smaller? More like dimenX - 2 instead dimenX - 1?)

This confuses me, I’d expect the number of cells be smaller than the number of points since the points on the edges are part of less cells.

More like dimenX - 2 instead dimenX - 1?

The number of cells is always Dim-1 compared to the points. The way I think about it is to imagine two connected cells. You have 3 points in the connected direction, and two cells.

Okay. Then these values seem fine.

Do you mean that the vtkMetaImageReader reads the data incorrectly? I.e. that the .mhd file ist not setup correclty? An therefore the Conversion is done correctly with an non functioning data set.

This also makes me curios, why is the Coordinate System so massive? Is it supposed to be 65MB for 5.4 million 8 Byte values? Is the coordinatesystem to big for the actual MetaImage-Field?

DataSet:
  CoordSystems[1]
    Coordinate System    coords assoc= Points valueType=class vtkm::Vec<float,3> storageType=struct vtkm::cont::StorageTagVirtual numValues=5461344 bytes=65536128 [(0,0,0) (1,0,0) (2,0,0) ... (298,323,55) (299,323,55) (300,323,55)]
  CellSet
  StructuredCellSet:
   UniformConnectivity<3> pointDim[301 324 56]
  Fields[1]
   MetaImage assoc= Points valueType=unsigned char storageType=struct vtkm::cont::StorageTagVirtual numValues=5461344 bytes=5461344 [0 0 0 ... 0 0 10]
MainWindow::onLeftRender
  num cells=5329500, num fields=1, num points=5461344

The coordinate system has 5461344 entries which is = 301 x 324 x 56. The 65MB datasize is correct if the coordinate system is being treated as a fully explicit ( each point is stored as an x,y,z coordinate ) instead of using an optimized layout.

The reason for the explicit coordinates is that the tovtkm::Convert function doesn’t currently have optimized paths for RectilinearGrids, and instead converts them into fully ExplictGrids.