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 BaseField
s,
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_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
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
i
th
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
i
th
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.
© 2024 MeVis Medical Solutions AG