Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
Reader and Writer

This page is work in progress and will introduce you to the IO-System of MITK.

Introductory slides

Several Talks have been given on the IO-System. The following list should provide you with a good starting point.

Quick start: Reading and writing files using IOUtil

mitk::IOUtil class provides convenience methods for loading data into a data storage or just returning BaseData objects without user interaction. The mitk::IOUtil::Save() and mitk::IOUtil::Load() methods cover the typical use cases and automatically select the best matching mitk::IFileReader and mitk::IFileWriter instance. In most cases, this is the easiest way to read or write a file.

 // load files directly into datastorage
mitk::IOUtil::Load("/path/to/my/file.nrrd",*ds);

 // load basedata into local vector
std::vector< mitk::Basedata::Pointer > basedatas;
 basedatas = mitk::IOUtil::Load("/path/to/my/file.nrrd");

 // write basedata to file (here: surface as PLY
 mitk::IOUtil::Save(mySurface, "/Save/surface/here.ply");

 // write basedata to file (here: surface as STL
 mitk::IOUtil::Save(mySurface, "/Save/surface/here.stl");

When reading a file using IOUtil, the IO-Framework first determines the mime-type of the given file. Afterwards, the best reader is selected internally, instantiated, and executed. The resulting BaseData Objects are returned to the developer as the method result.

Quick start: Creating your own reader or writer

If you implement a new BaseData, usually matching readers and writers are required. The following guide will help you to quickly set up these up and get them working in MITK.

Create new classes for reader and writers. Optimally, place them in an extra IO-Module that is configured as autoload. This way, they are available to the application from the start. If you are working with common data, the appropriate module is MitkIOExt. You can either extend mitk::AbstractFileIO, which will allow you to implement a class with reader and writer abilities, or you can extend mitk::AbstractFileReader or mitk::AbstractFileWriter specifically.

reader_writer_classes.png

Implement the given Methods. A good example on how to write a simple reader and writer is the mitkPointSetReaderService.cpp and mitkPointSetWriterService.cpp class, from which you can take implementation cues. The following is a simplified version of the header file:

 namespace mitk
 {

 class PointSetReaderService: public AbstractFileReader // 2) Extend the Abstract File Reader
 {
 public:

   PointSetReaderService();  // 3) Provide Constructor and Destructor
   virtual ~PointSetReaderService();

   // 4) Overwrite the Read Method as seen here
   using AbstractFileReader::Read;
   virtual std::vector< itk::SmartPointer<BaseData> > Read();

 private:

   // 5) Provide a clone method
   PointSetReaderService(const PointSetReaderService& other);
   virtual PointSetReaderService* Clone() const;
 };

 }

Example

Follow these steps to implement a new Reader:

A) Create a new cpp and h file in an appropriate submodule. Usually, a reader or writer should be located in the same module as the BaseData derivate it reads/writes.

B) Extend AbstractFileReader . This is highly recommended because it enables integration of your Reader into the Registery. It will then automatically be used by the application to load this type of files.

C) Provide a constructor . It should contain a minimal amount of information and might look like this:

mitk::PointSetReaderService::PointSetReaderService()
  : AbstractFileReader(CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE_NAME()), "MITK Point Set Reader")
{
    RegisterService();
}

Note the call to the superclass constructor containing the MIME-type. You can either reuse an existent MIME type here or create your own MIME-type locally . Finally, register the service to make it available to MITK.

D) Provide a Clone Method: Readers are clones when the registry requires a new reader. Provide a clone method to accommodate for this. Use the mitkPointSetReaderService.cpp as a reference if necessary.

E) Instantiate it in the module activator. Open the module activator and make sure that the new Reader/Writer is instantiated and held somewhere in the code. Also, unregister the reader/writer in the unload function if necessary.

Reader/Writer Options

Options are a powerful concept to modify Reader/Writer behaviour and to automate user interaction with minimal development overhead. In principal, options are represented by a simple map and a few getter and setter functions:

typedef std::map<std::string, us::Any> Options;

virtual Options GetOptions();
virtual void SetOptions(const Options& options);
virtual us::Any GetOption(const std::string& name);
virtual void SetOptions(const Options& options);

In its constructor, a reader or writer can set its options as a number map entries consisting of an human-readable option name and a default value. When a user tries to read/write a file via the interface, an options menu is generate from the map.

io_options.png
The options dialog shown by the raw reader

The user can then modify these options, which are automatically set in the reader/writer. You can use raw-images to see this behaviour in action.

Mime Types

The MimeType class provides meta-data about a specific data format. Every mitk::IFileReader and mitk::IFileWriter instance must be associated with exactly one mime-type via a service property.

mimetypes.png

Mime-type are used for categorizing data formats and creating filter strings in file open and save dialogs. Hence they effectively control the accessible set of data formats from a graphical user interface. Minimally, mime-types should provide a name and a list of handled extensions in lower case. Additionally, it is highly encouraged to set a category and a comment which will provide user-readable strings for user interaction.

It is important to understand the difference between mitk::MimeType and mitk::CustomMimeType. The former is an immutable stack object and can be pulled from mitk::MimeTypeProvider. it should be used for all interaction with MimeTypes. mitk::CustomMimeType is the heap-object pendant which is wrapped by mitk::MimeType and should exclusively be used for registration purposes, i.e. when you register a new MimeType.

Additional Capabilities

You can extend your reader writer with useful capabilities. All of these are optional

  • Priority: Reader use a ranking with Get- and SetRanking in order to signify how well they are suited to read a file. If several readers are able to read a file, the one with the highest Ranking level will be chosen.
  • ProgressCallbacks : Readers are executed in a thread automatically. If the reader implements callbacks, the progress bar will be more accurate during loading of files. Note: Progress callbacks are work in progress.

Ranking strategies

Todo.

Convenience classes

Developers usually do not interact with the service registry directly to retrieve and select a matching mitk::IFileReader or mitk::IFileWriter instance.

QmitkIOUtil

The QmitkIOUtil class is a wrapper around mitk::IOUtil, providing file open and save dialogues for selecting a file name from a within a graphical user interface.

FileReaderRegistry and FileWriterRegistry

Access to mitk::IFileReader and mitk::IFileWriter objects and their service references.

Integrating external I/O mechanisms

The MITK I/O system integrates with several external I/O systems.

ITK Reader and Writer

The I/O classes from ITK are automatically added to the service registry of MITK. They can be transparently used via the mitk::IFileReader and mitk::IFileWriter interfaces or the mitk::IOUtil methods.

VTK Reader and Writer

VTK does not provide a mechanism to enumerate all available I/O classes. Hence MITK provides manual integration of a specific set of VTK readers and writers.

Error handling and recovery

Todo.