Documentation/4.4/Developers/Slicelets

From Slicer Wiki
Jump to: navigation, search
Home < Documentation < 4.4 < Developers < Slicelets

For the latest Slicer developers documentation, visit the Nightly page.

Slicelets

Slicer application user interface is very rich and complex, to allow free experimentation with all available tools. However, if Slicer is used for implementing a well-defined workflow, it is more efficient to develop a custom user interface, that only shows the required user interfaced, in a streamlined, simplified fashion.

Slicelets are special Slicer modules that can provide full user interface, which can be used instead of Slicer's main application user interface.

Runnning a slicelet

There are not too many differences between slicelets and regular module. In fact, any regular module can be run standalone, without the main application user interface. The --no-main-window command-line argument has to be specified to prevent showing the main application user interface and --python-code has to be provided to start the module.

For example, to show the Command line module "Add", you could use (note: on Windows replace ./Slicer by Slicer.exe):

 ./Slicer --no-main-window --python-code "slicer.modules.add.widgetRepresentation().show()"

.... to show a Loadable module, you could use:

 ./Slicer --no-main-window --python-code "slicer.modules.models.widgetRepresentation().show()"

In general, additional user interface elements need to be added if a module is used without the main application user interface, for example for loading data and saving the results. A simple example is the Label Statistics module, which can run as a regular module in Slicer but also can be started as a Slicelet. When it is started as a slicelet, it has buttons for loading input data:

 ./Slicer --no-main-window --python-code "slicer.modules.labelstatistics.widgetRepresentation().show()"

A slicelet implemented in python can be started from a custom location (the advantage is that the module does not have to be added to the Slicer module paths, but a disadvantage is that the module location has to be known):

 ./Slicer --no-main-window --python-script lib/Slicer-4.3/qt-scripted-modules/LabelStatistics.py  

The line may be too complex to enter each time to start a slicelet. Either a shortcut or batch file can be created that runs the command or the command-line arguments can be hardcoded in the Slicer application settings:

Edit SlicerLauncherSettings.ini.

Before:

 ...
 [Application]
 path=<APPLAUNCHER_DIR>/bin/./SlicerQT-real
 arguments=
 ...

After:

 ...
 [Application]
 path=<APPLAUNCHER_DIR>/bin/./SlicerQT-real
 arguments=--no-main-window
 ...


Doing so, you wouldn't have to type the argument --no-main-window each time.

Similarly, you could also include the --python-code "..." arguments into the launcher settings file.

Alternatively, instead of adding the "--python-code" argument into the launcher settings, you could create a file named .slicerrc.py inside your home folder with the following content:

 modules = ["add", "models", "labelstatistics"]
 for module in modules:
   getattr(slicer.modules, module).widgetRepresentation().show()


Slicelet examples

SliceletTest example (slicelet with a single image viewer)

Simple example: Label Statistics module, see screenshot

Simple example with image viewer (see screenshot on the right): SliceletTest

More complex example: ScoliosisMonitoring

User interface examples

Three modules are within a tab widget:

import qt
import __main__

tabWidget = qt.QTabWidget()

modules = ["add", "models", "labelstatistics"]
for module in modules:
  tabWidget.addTab(getattr(slicer.modules, module).widgetRepresentation(), module)

tabWidget.show()

__main__.tabWidget = tabWidget # Keep track of the widget to avoid its premature destruction


Finally, to create a small UI including: - a 3D view - a button to load data - a tab widget - a module selector allowing to add any module to the tab widget ... the following could be done:

def onModuleSelected(modulename):
  global tabWidget
  tabWidget.addTab(getattr(slicer.modules, modulename.lower()).widgetRepresentation(), modulename)

import qt
import __main__

mainWidget = qt.QWidget()
vlayout = qt.QVBoxLayout()
mainWidget.setLayout(vlayout)

layoutManager = slicer.qMRMLLayoutWidget()
layoutManager.setMRMLScene(slicer.mrmlScene)
 layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUp3DView)
vlayout.addWidget(layoutManager)

hlayout = qt.QHBoxLayout()
vlayout.addLayout(hlayout)

loadDataButton = qt.QPushButton("Load Data")
 hlayout.addWidget(loadDataButton)
loadDataButton.connect('clicked()', slicer.util.openAddVolumeDialog)

saveDataButton = qt.QPushButton("Save Data")
hlayout.addWidget(saveDataButton)
saveDataButton.connect('clicked()', slicer.util.openSaveDataDialog)

moduleSelector = slicer.qSlicerModuleSelectorToolBar()
moduleSelector.setModuleManager(slicer.app.moduleManager())
hlayout.addWidget(moduleSelector)
moduleSelector.connect('moduleSelected(QString)', onModuleSelected)

tabWidget = qt.QTabWidget()
vlayout.addWidget(tabWidget)

modules = ["add", "models", "labelstatistics"]
for module in modules:
  onModuleSelected(module)

mainWidget.show()

__main__.mainWidget = mainWidget # Keep track of the widget to avoid its premature destruction