Medical Imaging Interaction Toolkit  2023.04.00
Medical Imaging Interaction Toolkit
The MITK Style Guide and Technical Notes

The following document is a description of the accepted coding style for the Medical Imaging Interaction Toolkit (MITK). Developers who wish to contribute code to MITK should read and adhere to the standards described here.

Naming Conventions

  • Using case change to indicate separate words
    ImageFilter
    PixelType
    DataStorage
    NodePredicateProperty
  • Underscores are not used e.g. Image_Filer, _Node
  • Variable names should convey the meaning behind the code
    BoundingBox::Pointer boundingBox = BoundingBox::New();
  • Abbreviation are allowable when in common use e.g. ROI for Region of Interest

Naming Classes

  • Classes are named beginning with a capital letter
  • Classes are named according to the following general rule:
    class name = <algorithm><input><concept>
  • Examples of concepts
    Accessor: Access and convert between types e.g. NullScalarAccessor
    Container: A container of objects such as points or images e.g. VectorContainer
    Filter: A class that participates in the data processing pipeline e.g. AddImageFilter
    Mapper: Transform data from one form into another e.g. ContourMapper2D
    Reader/Writer: A class that reads/writes a single data object e.g. VtkSurfaceReader

Naming Files

  • MITK classes like ExampleClass should be in namespace mitk and their corresponding files should be named mitkExampleClass.h/.cpp.
  • Qt specific MITK classes like QmitkListView should have the prefix Qmitk in their class names and their corresponding files should be named QmitkListView.h/.cpp.
  • Header Files ends with an .h and
  • Implementation Files with an .cpp or .txx for a template class

Naming Methods and Functions

  • Functions and methods are named beginning with a capital letter
  • Referring to class methods in code, an explicit this-> pointer should be used
    mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetAll();

Naming Signal/Slots Methods and Functions

  • Slots are named according to the following general rule
    On[variable name who send the signal][signal]();
  • Example
    connect( loadImagePushButton, SIGNAL( clicked(bool ) ),
    SLOT( OnLoadImagePushButtonClicked( bool ) ) );
    void mitk::Image::OnLoadImagePushButtonClicked( bool )
    {
    ... Do something ...
    }
  • Signals are named according to the following general rule
    Signal[MethodName]();
  • Example
    emit SignalFinishedSegmentation();

Naming Class Data Members

  • Class data members are prefixed with m_
    m_Volumes
    m_OffsetTable
    m_ImageMask
  • An exception to this rule, Qt class Data members are not prefixed and begin with a lower-case letter
    loadImageButton
    closeImageAction

Naming Local Variables

  • Local variables first letter is lower-case
    offset
    data
    slicesIt

Naming Qt Variables

  • GUI variables ends with name of used QT tool.
    QPushButton* loadImagePushButton;
    QAction* closeImageAction;
    QCheckBox* hideImageCheckBox;
    QRadioButton* binaryImageRadioButton;

Naming Typedefs

  • Typedefs must end in the word Type
    typedef TPixel PixelType;
    typedef itk::Image< TPixel, VImageDimension > ImageType;
    typedef std::list<mitk::Image::Pointer> ImageListType;

Pointer

Declaration of Pointers

  • Position of * pointers are connected with the variable
    int *counter;
  • Analog to references
    int &counter;

SmartPointer

  • SmartPointers must be used for classes that have itk::Object as a base class.
  • Assignment of a just created instance to a normal pointer results in a crash, since the reference count is decreased immediately to zero and the object is destroyed.
    itk::Object::Pointer object = itk::Object::New();
  • Static declarations are also forbidden and result into an exception when the scope of the variable is left, because the destructor is called while the reference count is still greater than zero.
  • Note that using smart pointers requires using real (normal) pointers when setting input. If you want to return a newly created smart pointer that is not also kept within the class (e.g., if you write a Clone method), you have to return a smart pointer on output (compare itkMacro.h). If the smart pointer is kept within the class, returning a real (normal) pointer is sufficient.
  • Testing a SmartPointer against NULL is done with the IsNull() and Is- NotNull() methods. A simple ==NULL issues a warning.

Namespace

  • MITK classes should be in namespace mitk
    mitk::Image::Pointer mitk::ImageGenerator::MakeImage()
    {
    // already in namespace mitk here!
    ImageDecorator::Pointer decorator = mitk::ImageDecorator::New();
    d->Decorate( image );
    return image;
    }

Code Layout and Indentation

General Layout

  • Each line of code should take no more than 120 characters.
  • Use lots of whitespace to separate logical blocks of code, intermixed with comments
  • DO NOT USE TABS. The standard indention is 2 spaces (see ITK Style Guide). Configure your editor accordingly.
  • DO NOT USE trailing whitespaces
  • Declaration of variables should be one declaration per line
    int sliceNumber;
    char* stringName;
    ImageType::Pointer image;

Class Layout

  • Copyright
    /*============================================================================
    The Medical Imaging Interaction Toolkit (MITK)
    Copyright (c) German Cancer Research Center (DKFZ)
    All rights reserved.
    Use of this source code is governed by a 3-clause BSD license that can be
    found in the LICENSE file.
    ============================================================================*/
  • Includes [A .. Z]
    #include "... .h"
  • Namespace
    namespace mitk
    {
    DO NOT litter your header with "using namespace;"!
  • Class (Template)
    template <class TType>
    class ClassName : public ImageBase<VImageDimension>
    {
  • Typedefs
    public:
    ....typedefs....
  • Methods
    public:
    ....methods....
    protected:
    ....methods....
    private:
    ....methods....
  • QT Signals
    signals:
    Signal...();
  • QT Slots
    public slots:
    On...();
    protected slots:
    On...();
  • Data Member
    private/protected:
    ....class data members....
    };
    }
    #endif

Use of Braces

  • Used to delimit the scope of an if, for, while, switch.
  • Braces are placed on a line by themselves:
    for ( unsigned int i = 0; i < 3; ++i )
    {
    ... do something ...
    }
    or
    if ( condition )
    {
    ... do something ...
    }
    else if ( other condition )
    {
    ... do something ...
    }
    else
    {
    ... do something ...
    }
  • You can choose to use braces on a line with a code block when the block consists of a single line:
    if ( condition ) { foo = 1; }
    else if ( condition2 ) { foo = 3; }
    else { return; }
    or
    for ( unsigned int i = 0; i < 3; ++i) { x[i] = 0.0; }

Include Guards

  • #include guard is a particular construct used to avoid the problem of double inclusion when dealing with the #include directive.
  • Naming convention for #include guards is: ClassName_h
  • Following example demonstrates a problem that can arise if #include guards are missing: Here, the file child.cpp has indirectly included two copies of the text in the header file grandfather.h. This causes a compilation error, since the structure type foo is apparently defined twice.
    grandfather.h struct foo
    {
    int m Member;
    };
    father.h #include "grandfather.h"
    child.h #include "grandfather.h"
    #include "father.h"

Use of #include guards

  • Here, the first inclusion of grandfather.h causes the macro grandfather h to be defined. Then, when child.cpp includes grandfather.h the second time, the #ifndef test fails, and the preprocessor skips down to the #endif, thus avoiding the second definition of struct foo. The program compiles correctly.
    grandfather.h #ifndef grandfather h
    #define grandfather h
    struct foo
    {
    int m Member;
    };
    father.h #include "grandfather.h"
    child.h #include "grandfather.h"
    #include "father.h"

Some Technical Notes

  • Use forward declarations in header files wherever possible. Only include those header files in a header file that are really necessary. Include the rest in the implementation file.
  • For classes inheriting directly or indirectly from itk::LightObject (most of the MITK-classes do so), the class definition should include the mitkClassMacro. Additionally, if the class can be instantiated (normally the case, if the class is not abstract) and has only a constructor without parameters, the constructor should be declared protected and the itkFactorylessNewMacro should be used to create a New() method for instantiation. Here is an example:
    class ExampleClass : public SuperClassOfTheExampleClass
    {
    public:
    mitkClassMacro(ExampleClass, SuperClassOfTheExampleClass)
    itkFactorylessNewMacro(Self)
    [...]
    protected:
    ExampleClass();
    virtual ~ExampleClass();
    }
  • Set- and Get-methods can be created with the macros itkSetObjectMacro(name,type) and itkGetObjectMacro(name,type), respectively, if the type is derived from itk::LightObject or itk::Object.
  • When using inner classes of a parent class which is templated, you have to use the keyword typename for gcc 3.x and standard compliance. For example, TreeChangeListener is an inner class of Tree, therefore use:
    class LinkedTree : public Tree<T>
    {
    public:
    typedef typename LinkedTree<T>::TreeChangeListener TreeChangeListener;
    [...]
    }
    Another example:
    typename std::vector<TreeChangeListener*>::iterator pos = treeChangeListenerList.begin();
    iterator is an inner class of vector.

Automatic Code Formatting

We offer a .clang-format file, which can be used to automatically format code acceptably.

For an explanation of the different options check out https://clang.llvm.org/docs/ClangFormatStyleOptions.html

mitk::Image::New
static Pointer New()
itk::SmartPointer< Self >
mitk
DataCollection - Class to facilitate loading/accessing structured data.
Definition: RenderingTests.dox:1
mitk::AcMOVESELECTED
@ AcMOVESELECTED
Definition: mitkInteractionConst.h:307
mitk::Image::Pointer
itk::SmartPointer< Self > Pointer
Definition: mitkImage.h:81
mitk::DataStorage
Data management class that handles 'was created by' relations.
Definition: mitkDataStorage.h:43
QmitkDataStorageComboBox
Displays all or a subset (defined by a predicate) of nodes of the Data Storage.
Definition: QmitkDataStorageComboBox.h:38
mitkClassMacro
#define mitkClassMacro(className, SuperClassName)
Definition: mitkCommon.h:36
mitk::DataNode
Class for nodes of the DataTree.
Definition: mitkDataNode.h:63