vtkDICOMReader - Cache series/speed up files loading

I’m opening a study with multiple series using vtkDICOMDirectory and vtkDICOMReader.
Everything works well, but opening a series each time causes a delay because the files need to be loaded from scratch (using reader->SetFileNames and reader->Update).
I was wondering if it is possible to speed up this process. I’ve thought about two options:

  • cache the series’ files after they’ve been loaded once
  • pre-load all the series of the study at launch

Is it possible to implement one of these?
I’ve tried exploring the latter by setting up multiple vtkDICOMReader objects, but when I try to use one of them it doesn’t work.

If you have an application that loads multiple series, then using a cache is a very common way of keeping track of the data so that you don’t have to re-load a series every time you want to view it.

For our in-house applications, we have a class called the “DataManager” that acts as a cache. This class keeps a list of data nodes, where each node contains a vtkImageData along with any labels, metadata, transforms, etc. that we want to associate with that image data. The Slicer folks use MRML for this kind of thing, but it’s the same basic idea (though MRML is much more sophisticated).

So that’s my advice. Devise a cache that sits between the reader and your visualization/analysis pipelines. After the reader has finished reading the data, you can get rid of the reader… all that you need to keep in memory is the data/metadata.

1 Like

Thank you for the suggestion! I’m trying to follow your concept.

If I understood correctly, I should call:

vtkImageData *data = reader->GetOutput();

to get the vtkImageData and then store it somehow (is there an array type I can use?).
Then I can call imageMapper->SetInputData(_) with one of the stored vtkImageData objects to have it loaded onto my display chain.

I’m having difficulties figuring out how to store the image data; I’ve tried wrapping it in an NSObject and then saving the wrapper in an NSArray (I’m using VTK in a Cocoa app with Objective-C++ and Swift), but got EXC_BAD_ACCESS errors when trying to load the objects using SetInputData(_).

Use vtkSmartPointer when you store it.

1 Like

I was able to do it!
However I had to copy the reader’s output instead of using it directly:

vtkSmartPointer<vtkImageData> newImageData = vtkSmartPointer<vtkImageData>::New();

Sorry for bumping an older topic. To further speed up the first loading of a series, I was wondering whether it was possible for VTK to load images asynchronously like some other viewers do?
In other words, rather than waiting for all the images of a series to be ready, would it be possible to load them lazily when they are requested on screen?

There is no simple way to answer your question, but I’ll do my best.

The VTK pipeline wasn’t designed to be asynchronous. An Update() call will not return until the update is complete, there’s certainly no easy way for an Update() to provide you with part of the data but keep loading the rest of the data as a background task. In general, the VTK design philosophy is to keep things synchronous and to use multithreading to reduce the processing time.

So the most natural way in VTK to accelerate the reading of DICOMs would be to multithread the reader, so that when the reader updates, it loads all the DICOM files in parallel. I’ve considered adding this feature to vtkDICOMReader.

VTK also supports a feature called “streaming” where just part of the dataset is processed by the pipeline. This can be used to load and view just a single slice, without loading the whole dataset. You can enable this feature by calling the StreamingOn() method of the image mapper that you are using, e.g. the vtkImageSliceMapper or vtkImageResliceMapper. But there’s nothing asynchronous about this feature, and since nothing is cached, it doesn’t really speed things up.

For proper asynchronous IO, you’d have to design your own cache to handle the asynchronous operations. VTK itself doesn’t provide any tools for this.

1 Like