Chapter 2. Detailed Class Overview and Usage

Table of Contents

2.1. Classes for Module Development
2.1.1. Module
2.1.2. Field
2.1.3. FieldContainer
2.1.4. Image Classes for Module Development
2.2. Administrative Classes
2.2.1. Host
2.2.2. Memory
2.2.3. Base
2.2.4. The Runtime Type System
2.2.5. Debugging and Error Handling Support
2.3. Image Classes
2.3.1. ImageProperties
2.3.2. MedicalImageProperties
2.3.3. ImagePropertyExtension
2.3.4. PagedImage
2.3.5. SubImage/TSubImage
2.3.6. BitImage
2.3.7. VirtualVolume
2.3.8. MemoryImage
2.4. Helper Classes
2.4.1. ImageVector, ImageVector
2.4.2. SubImageBox
2.5. APIs and Classes for Interfaces and Voxel Type Extensions
2.5.1. How Applications and the ML Work
2.5.2. The C-API
2.5.3. Registering and Using Self-Defined Data Types
2.6. Tools
2.6.1. MLLinearAlgebra(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)
2.6.2. MLUtilities
2.6.3. Other Classes
2.6.4. MLBase
2.6.5. MLKernel
2.6.6. MLTools
2.6.7. MLDiagnosis
2.6.8. MLImageFormat
2.6.9. MLDataCompressors
2.7. Registered Data Types
2.8. ML Data Types
2.8.1. Voxel Types and Their Enumerators
2.8.2. Index, Size and Offset Types

Chapter Objectives

This chapter will give you a detailed overview of most ML classes and tools:

2.1. Classes for Module Development

2.1.1.  Module

ml::Module is the base class all ML modules are derived from. It is crucial to know this class for being able to extend the ML module database. See Chapter 3, Deriving Your Own Module from Module for a detailed description of this class and how to derive own modules from it.

2.1.2.  Field

A field is a C++ class which simply encapsulates a data value such as an integer, a vector, a matrix, a string or even an image or a complex data structure. All fields are derived from the ml::Field base class. Currently, about 60 field types are available in the ML. Due to the following reasons, fields may be considered as one of the most powerful ML features:

  • A field's value can be set/retrieved as a string value from the base class, but each derived version has also set/get methods for typed values. The string value methods permit an application to work with field values without considering the field type.

  • Fields can be observed. Each time a field is modified, all observers are notified and can adapt themselves to the new field value. A standard observer is, for example, the module that contains the field. Other observers could be the user interface (of the module using the field) or other fields that update themselves if the value changes.

  • A field can be attached to other fields. Whenever the field is changed, the connected fields are notified and/or the new value is transferred to the connected field. In module networks, this is a powerful feature to hard-code information flows, i.e., to define how modules can communicate with each other. This heavily reduces code complexity of applications that use such networks.

  • Since fields support setting/reading their values as strings, all fields can accept values from other fields. A transferred value is scanned as far as possible, i.e., an integer value will accept float values (only the integer fraction) and vice versa. But also vectors accept integers, doubles, floats and vice versa; enumerated values can be set as integers, etc.

  • All ML modules use fields for their parameter interface. Each module includes a field container which can handle an individual list of fields. There is no need to know set or get methods to communicate with a module. Hence, the application MeVisLab can simply ask the field container of a module to return all fields, their names and their values, and can automatically create a user interface for the module or it can save/load the field values for persistence.

2.1.2.1. Standard Fields

The following derived field classes are part of the ML:

See the file mlFields.h for a detailed description of the Field classes.

2.1.2.2. Important Field Methods

The following list gives an overview of the most important Field methods:

  • void setStringValue(const std::string &value)

    Assigns the string value to the field.

  • std::string getStringValue() const

    Returns the value of the field as standard string.

  • void touch()

    Simulates a change of the field value so that all attached fields or field sensors are notified. Note that this method has no effect if notification handling (for this field or globally) is disabled.

See the file mlFields.h for further methods of the Field class.

2.1.2.3. Base Field

The ml::BaseField is used to transfer arbitrary data from one module to another and to check it there for its correct type. Do the following:

  • Derive a data object from the class Base.

  • Add a BaseField to your module (Section 2.1.3, “ FieldContainer).

  • Use the method setBaseValue() to set the address of your Base object as a value of the BaseField.

  • Add a BaseField to another (second) module and connect both fields.

  • In the second module, use the getBaseValue() to retrieve the BaseField value.

  • Cast the value of the base field with mlbase_cast<BaseType*>(fieldValue) to the target type BaseType. If the fieldValue is of a different type than BaseType*, NULL is returned by the cast.

Do not forget

  • to initialize each new BaseType subclass MyNewBaseField with a MyNewBaseType::initClass() statement in the library initialization and

  • to use "input" or "output" as first part of the field name to define the field as an input or output of your module.

The following examples show how to

  • derive a new class from Base,

  • create a module and to export an internal Base object via a BaseField,

  • create a module to which any Base object can be connected, and

  • check whether a Base object is of a certain or correct type.

Example 2.1. Deriving a New Class from Base

ML_START_NAMESPACE

class ML_BASE_EXAMPLE_EXPORT MyBaseObject : public Base
{

public:

  // Constructor which initializes the internal string.
  MyBaseObject() { _strValue = ""; }

  // Return value of string.
  const std::string &getValue() const { return _strValue; }

  // Set string value.
  void setValue(const std::string &strVal) { _strValue = strVal; }

  /*...*/

private:

  // Contents of your base object, in this case a string.
  std::string _strValue;

  // Define the interface of the class to the runtime type system of the ML.
  ML_CLASS_HEADER(MyBaseObject);
};

ML_END_NAMESPACE

// ***Source file: Implement the class interface for the runtime type system.
ML_START_NAMESPACE

  ML_CLASS_SOURCE(MyBaseObject, Base)

ML_END_NAMESPACE

Example 2.2. Making a Base Object Accessible via a BaseField

// ***Header File in class definition:

ML_START_NAMESPACE

class Export MyModule : public Module
{

public:

  MyModule::MyModule();

  // Create a base object which shall be passed to another module via a base field.
  MyBaseObject objectToTransfer;

  //! Handle field changes of the field field.
  virtual void handleNotification (Field *field);

private:

  // Pointer to a base field to which any base object can be connected.
  BaseField* _baseFld;

  // Define the interface of the class to the runtime type system of the ML.
  ML_MODULE_CLASS_HEADER(MyModule);
};

ML_END_NAMESPACE

Example 2.3. Getting a Base Object from a BaseField Connection and Checking its Type

// ***Source file:Construct the module.

ML_START_NAMESPACE

ML_MODULE_CLASS_SOURCE(MyModule, Module)

// Construct the module and initialize the objectToTransfer with a test string.
MyModule::MyModule() : Module(0,0)
{
  handleNotificationOff();

  /*...*/

  // Initialize base object
  objectToTransfer.setValue("TestString");

  // Add a base field and set the address of objectToTransfer as its value.
  _baseFld = addBase("outputBase")
  _baseField->setBaseValue(&objectToTransfer);

  /*...*/

  handleNotificationOn();
}


void MyModule::handleNotification(Field * fields)
{
  if (_baseFld == field){

    // Base field has changed, get its value.
    Base *baseValue = baseFld->getBaseValue();

    Cast to target type and by that, check for correct type.
    MyBaseObject* myBO = mlbase_cast<MyBaseObject*>(baseValue);

    // Check for validity.
    if (myBO != NULL){

      // Print value
      mlDebug(myBO->getValue().c_str());
    }
  }
}

ML_END_NAMESPACE

2.1.3.  FieldContainer

The ml::Module is derived from ml::FieldContainer which encapsulates a list of fields for the module (see also class Field ). So the Module provides field list access, removal, search and indexing. In a Module constructor, all interface parameters of the modules are added to this container. The most important methods are:

  • Field* addField(const char* name,const char* type, const char* value, bool createSensor = true)

    Adds a new field with name name, type type and value value (coded as a string) to the container. If createSensor is true (the default), the Module of the field container will be installed as an observer of the field so that field changes are passed to the Module as notification.

  • Field* addField(Field* field, bool createSensor = true)

    Adds the field field and installs the Module as an observer if createSensor is true (the default) so that field changes are passed to the Module as a notification.

  • Field *add[Bool | Int | Enum | Float | Progress | Double | String | Notify | InputConnector | OutputConnector | Base | SoNode | DicomTagList | Vector2 | Vector3 | Vector4 | Vector6 | ImageVector | SubImageBox | SubImageBoxd | Plane | Rotation | Color | Matrix | MLDataType | UniversalType ] (std::string name, ...)

    Creates a field of the specified type with the name name, adds it to Module and installs the Module as an observer so that its handleNotification() method is called on field changes.

  • Field* getField(std::string name) , Field *getField(int index)

    Returns the Field with name name or at index index; returns NULL if not found.

  • int getField(Field *field)

    Searches field with address field in list and returns its index. If not found, 0 is returned and a warning is sent to the ML error handler.

  • int getSize()

    Returns the number of fields in the container.

  • int getNumInputConnectorFields() const

    Returns the number of added InputConnectorFields.

  • int getNumOutputConnectorFields() const

    Returns the number of added OutputConnectorFields.

  • InputConnectorField *getInputConnectorField(int i) const

    Returns the ith InputConnectorField in the container. If not found, NULL is returned and ML_FATAL_ERROR is sent to the ML error handler.

  • OutputConnectorField *getOutputConnectorField(int i) const

    Returns the ith OutputConnectorField in the container. If not found, NULL is returned and ML_FATAL_ERROR is sent to the ML error handler.

  • std::string getValue(const std::string &name) const

    Returns the value of a field with name name as standard string. If the field is not found, a warning is sent to the ML error handler and an empty string ("") is returned.

  • std::string getValue(int index) const

    Returns the value of a field at position index in the container as standard string. If the field is not found, a warning is sent to the ML error handler and an empty string ("") is returned.

  • setValue(int i, const std::string &value)

    Assigns value value to a field at position index in container. If the field is not found, a warning is sent to the ML error handler and no value is assigned.

  • setValue(const std::string &name, const std::string &value)

    Assigns value value to a field with name name in container. If the field is not found, a warning is sent to the ML error handler and no value is assigned.

  • setValue(const std::string &name, int value)

    Assigns the integer value to a field with name name in container. If the field is not found, a warning is sent to the ML error handler and no value is assigned.

  • void activateAttachments()

    (Re)Enables the notification of attached fields and field sensors when field values are set or notified by e.g. touch() or set*Value() methods.

  • void deactivateAttachments()

    Disables the notification of attached fields and field sensors when field values are set or notified by e.g. touch() or set*Value() methods.

2.1.4. Image Classes for Module Development

See Section 2.3, “Image Classes” for a detailed image and subimage handling description.