Table of Contents
Chapter Objectives
This chapter will give you a detailed overview of most ML classes and tools:
Classes for Module Development
                Module
              ,
            the base class from which new modules are derived,
                Field
              , a
            class to encapsulate, manage and observe module parameters,
                FieldContainer
              , a
            parent class of module to manage a set of fields.
Classes for administering ML internals as well as for managing
        Base objects and modules
                Host
              , the
            core class managing image processing, data flow, parallelization,
            etc.,
                MLMemoryManager
              ,
            library to store temporary (image) pages for reuse,
                Memory
              
            providing an interface for reliable memory allocation and error
            handling on failures,
                Base
              , the
            base class for most ML classes, e.g., to implement a general
            persistence concept,
The Runtime Type System classes
            Runtime, RuntimeType
            and RuntimeDict for object factories and
            type management,
Debugging Classes.
Helper Classes for 6D (voxel) positions and subimage boxes
        (Section 2.4.1, “ImageVector, ImageVector”, Section 2.4.2, “
          SubImageBox
          
        ”
Image Classes to describe images, image properties (Section 2.3.1, “
          ImageProperties
          
        ”, Section 2.3.2, “
          MedicalImageProperties
          
        ”, Section 2.3.3, “
          ImagePropertyExtension
          
        ”), subimages (Section 2.3.5, “SubImage/TSubImage”) and paged images (Section 2.3.4, “
          PagedImage
          
        ”
                BitImage
               to
            handle packed flag and binary images,
                VirtualVolume
              
            for global page-based image processing,
                MemoryImage
              
            for special cases that require completely memory-mapped
            images.
Tools and helper classes to support advanced image processing
Some 
                Vector
               and
            matrix arithmetics (MLLinearAlgebra),
Classes and tools for kernel-based image processing (Section 2.6.5, “
          MLKernel
          
        ”),
A tool box with a set of frequently used helper functions
            (Section 2.6.6, “
          MLTools
          
        ”).
Several diagnosis modules (Section 2.6.7, “
          MLDiagnosis
          
        ”),
Classes to save, modify, load and query ML image data in a
            dedicated ML file format (Section 2.6.8, “
          MLImageFormat
          
        ”),
Data compressor classes (Section 2.6.9, “
          MLDataCompressors
          
        ”).
Classes that contain additional voxel data types (RegisteredDataTypeClasses)
Important data types used in ML sources (Section 2.8, “ML Data Types”).
            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.
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.
The following derived field classes are part of the ML:
BaseField - Contains a pointer to
              any Base object (Section 2.2.3, “
          Base
          
        ”). Using BaseFields,
              arbitrary Base data structures can be
              shared between modules.
FloatField- Contains a floating
              point number.
DoubleField - Contains a floating
              point value with double precision.
EnumField - Contains a list of
              strings that represents an enumeration value as well as an index
              to the currently selected entry.
InputConnectorField - Contains an
              input connector value which can be connected to the output
              connector value of other modules in order to establish image
              connections between modules.
MatrixField - Encapsulates a
              Matrix4 value (Section 2.6.1, “MLLinearAlgebra(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)”), a 4x4 matrix of
              double-type numbers.
NotifyField - Does not represent a
              value; it is used to propagate field changes or to implement
              buttons on user interfaces.
OutputConnectorField - Encapsulates
              an output connector of a module used for connections with input
              connectors of other modules in order to establish image data
              flows between modules. Note that this field also contains a
              PagedImage (Section 2.3.4, “
          PagedImage
          
        ”) to
              manage the paged output image of a module.
PlaneField - Encapsulates a plane
              described by a plane equation in 3D space.
RotationField - Encapsulates a
              rotation value described as quaternion of four floating point
              values.
SoNodeField - Encapsulates a
              pointer to an Open Inventor™ node to make
              scene graphs available at module outputs, e.g., for visualization
              purposes.
SubImageBoxField - Encapsulates a
              SubImageBox value (Section 2.4.2, “
          SubImageBox
          
        ”) with corners specified by integer
              vectors (Section 2.4.1, “ImageVector, ImageVector”).
SubImgBoxdField - Encapsulates a
              SubImageBoxd (Section 2.6.3.1, “
            SubImageBoxd
            
          ”) with corners specified by floating
              point vectors Vector6 (Section 2.6.1, “MLLinearAlgebra(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)”).
Vector2Field - Encapsulates
              Vector2 value (Section 2.6.1, “MLLinearAlgebra(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)”) .
Vector3Field - Encapsulates
              Vector3 value ( Section 2.6.1, “MLLinearAlgebra(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)”).
Vector4Field - Encapsulates a
              Vector4 value (Section 2.6.1, “MLLinearAlgebra(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)” ).
Vector6Field - Encapsulates a
              Vector6 value (Section 2.6.1, “MLLinearAlgebra(Vector2, ..., Vector10, Vector16, Matrix2, , ..., Matrix6, quaternion, ImageVector)” ).
ImageVectorField - Encapsulates a
              ImageVector value (Section 2.4.1, “ImageVector, ImageVector”).
MLDataTypeField - Encapsulates
              MLDataType( value Section 2.6.3.2.1, “MLDataType”). 
ProgressField - Contains a floating
              point value in [0...1] which can be
              incremented or reset to represent a progress/done
              indicator.
UniversalTypeField - Contains an
              arbitrary value of any of the available ML data types (Section 2.6.3.2.1, “MLDataType”). The managed type can be changed on
              runtime.
See the file mlFields.h for a detailed
          description of the Field classes.
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.
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.
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_NAMESPACEExample 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_NAMESPACEExample 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
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.
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.
See Section 2.3, “Image Classes” for a detailed image and subimage handling description.
          © 2025 MeVis Medical Solutions AG