Documentation/4.1/Developers/Logics

From Slicer Wiki
Jump to: navigation, search
Home < Documentation < 4.1 < Developers < Logics

A logic is a collection of "algorithms" that mainly process MRML nodes within a scene.

Logics can be:

  • active: observe the scene and nodes to react when receiving events are fired
  • passive (helper): collection of utility functions to simplify the handling of nodes (e.g. AddArchetypeVolume in Volumes logic, Application logic.)
  • a mix of both: not ideal.

There are 5 types of logics within Slicer. Their role is usually dictated by their dependencies. The inheritance graph can be useful to understand the relationship between each logic types.

  1. MRML logics
    Location
    Slicer/Libs/MRML/Logics
    Dependencies
    MRMLCore
    no graphical dependency
    no Slicer dendendency (can by used by other projects)
    Role
    Contain the base classes for logics (vtkMRMLAbstractLogic, vtkMRMLApplicationLogic) and helper classes
    MRML logics don't have access to the application, and so shouldn't contain any Slicer specific code.
    Examples:
    • factories: for MRML nodes (vtkMRMLColorLogic creates default vtkMRMLColor*Nodes)
    • helpers: vtkMRMLModelHierarchyLogic
  2. Slicer Logics
    Location
    Slicer/Base/Logics
    Dependencies
    MRMLLogic
    Role
    Specialization of MRML Logics for the Slicer application.
    Examples:
    • vtkSlicerColorLogic: knows about the "application" default LUT IDs and custom application lut files.
  3. Application logics
    Location
    Slicer/Libs/MRML/Logics/vtkMRMLApplicationLogic.[h|cxx] and Slicer/Base/Logics/vtkSlicerApplicationLogic.[h|cxx]
    Dependencies
    vtkMRMLApplicationLogic doesn't depend about Slicer however vtkSlicerApplicationLogic does.
    Role
    Contains application specific information. vtkMRMLApplicationLogic is an abstract class that is specialized for the application using MRML (vtkSlicerApplicationLogic for Slicer)
    vtk[MRML/Slicer]ApplicationLogic is NOT a singleton, however, it can be accessed by any logics (see vtkMRMLAbstractLogic::SetApplicationLogic) so it can be considered as such. It currently contains a list of nodes/logics, unique in the application. It is here for historic reasons (Slicer3), but it should not be seen as a placeholder for everything. Querying a module to get its logic should be preferred to access logics.
  4. Module logics
    Location
    Slicer/Modules/Loadable/XYZ/Logic/vtkSlicerXXXLogic
    Dependencies
    Slicer logics, XYZ nodes and optionally other module logics
    Role
    A module logic is the module public API. While a module has typically (not necessarily) an associated widget/panel, no processing should be done within the widget, the widget is just the interface between the user and the logic/nodes. Modules can access other module logics (i.e. qSlicerCoreApplication::moduleManager()->module("Volumes")->logic()) if needed. There is maximum 1 module logic per module, however, it doesn't prevent the module logic to use helper logics (vtkSlicerModelsLogic can instantiate/use vtkMRMLModelHierarchyLogic).
  5. Displayable managers
    Location
    Slicer/Libs/MRML/DisplayableManager
    Dependencies
    MRMLLogic and vtkRendering
    Role
    They are logics that focus on representing nodes in a VTK renderer and handling user interaction within the view.
    Theoretically the slice logics should be displayable managers ( however, it might be a huge effort for just the sake of being consistent ).
    Displayable managers contain some limitations:
    • there is no control (yet?) over their creation, and once instantiated, it's not easy to control their behavior (properties can't be set externally on displayable managers).
    • they are not (yet?) well designed to communicate with each others.

A class (logic, widget...) should explicitly expose in its API the required logic(s) (e.g. qMRMLColorPickerwidget::setColorLogic(vtkMRMLColorLogic*)) instead of hiding the requirements by directly using the application logic (e.g. this->GetApplicationLogic()->GetModelHierarchyLogic() ).

It is the role of the class instantiator to pass the required logics to the created class (e.g. the module plugin sets the module logic to the module widget). For module logics depending on other module logics, it is resolved in the qSlicer*Module::setup() function, qSlicer*Modules have access to all modules and their logics that way (i.e. qSlicerCoreApplication::moduleManager()->module("Volumes")->logic()). Exposing the requirements in the API instead of using singleton has the advantage of having a scope well defined and contained, the code becomes more modular and easier to unit test.