Documentation/Nightly/Developers/Tutorials/MigrationGuide/Slicer
Contents
- 1 Slicer backward incompatible changes
- 1.1 Slicer 5.0: API changes since 4.10
- 1.2 Slicer 4.9: Update of VTK version from 9.0 to 8.2
- 1.3 Slicer 4.9: ITK_LEGACY_REMOVE is now OFF
- 1.4 Slicer 4.9: vtkMRMLPlotDataNode renamed to vtkMRMLPlotSeriesNode
- 1.5 Slicer 4.9: CMake: Module MIDAS not available
- 1.6 Slicer 4.9: CMake: Module SlicerMacroCheckExternalProjectDependency not available
- 1.7 Slicer 4.9: CMake: Module SlicerMacroEmptyExternalProject not available
- 1.8 Slicer 4.9: CMake: Module SlicerBlockSetCMakeOSXVariables not available
- 1.9 Slicer 4.9: Application: isRelease() function not available
- 1.10 Slicer 4.9: slicer.util.getNode() raises exception if node not found
- 1.11 Slicer 4.8: Application: isRelease() function not available or deprecated
- 1.12 Slicer Python Module: modulewidget and others removed.
- 1.13 MRML: Slicer 4.6: Moved up vtkMRMLStorableNode in the MRML node hierarchy.
- 1.14 MRML: Slicer 4.5: Introduction of vtkMRMLLabelMapVolumeNode
- 1.15 CLI: Slicer 4.3: Add ITKFactoryRegistration library centralizing ITK IO factory registration
Slicer backward incompatible changes
Slicer 5.0: API changes since 4.10
- Removed protected method vtkMRMLModelDisplayableManager::FindPickedDisplayNodeFromMesh
Markups
- vtkCommand::Modified events are no longer invoked when control points are added/removed/modified to improve performance. Modules that need to know If a point position is modified need to add observers to vtkMRMLMarkupsNode::PointAddedEvent, vtkMRMLMarkupsNode::PointRemovedEvent, vtkMRMLMarkupsNode::PointModifiedEvent events.
Slicer 4.9: Update of VTK version from 9.0 to 8.2
Following kitware/VTK@b703d78be, VTK has updated to use version number 8.2 instead of 9.0. This was discussed in on the VTK mailing list in http://vtk.1045678.n5.nabble.com/Discussion-OK-to-change-VTK-s-version-number-from-9-0-to-8-2-tt5748702.html
At first, this VTK commit and its companion kitware/VTK@8a00b357e were both reverted from the Slicer/VTK fork. Then, since having the corresponding changes reverted in VTK was not possible, it was decided to also update Slicer. This was done in the following commits:
- r27472: COMP: Update c++ classes to support building against VTK >= 9 and VTK >= 8.2
- r27473: COMP: Update VTK to include version change from 9.0 to 8.2. Fixes #4623
This means that code depending on VTK must also be updated to include similar fixes.
Replace this:
#if VTK_MAJOR_VERSION >= 9
By this:
#if VTK_MAJOR_VERSION >= 9 || (VTK_MAJOR_VERSION >= 8 && VTK_MINOR_VERSION >= 2)
and
Replace this:
#if VTK_MAJOR_VERSION < 9
By this:
#if VTK_MAJOR_VERSION <= 7 || (VTK_MAJOR_VERSION <= 8 && VTK_MINOR_VERSION <= 1)
Slicer 4.9: ITK_LEGACY_REMOVE is now OFF
In preparation to switch to ITK 5.0, we disable legacy functionality in ITK. This might affect some modules which rely on ITK. Take a look at ITK 4 migration guide before ITK 5 migration guide.
Slicer 4.9: vtkMRMLPlotDataNode renamed to vtkMRMLPlotSeriesNode
Plotting was improved in this commit
Replace this:
vtkMRMLPlotDataNode
By this:
vtkMRMLPlotSeriesNode
Slicer 4.9: CMake: Module MIDAS not available
The test infrastructure of your project should be updated to use ExternalData built-in CMake module instead of the specific MIDAS module.
See EMSegment commit r17150 for an example of transition.
This means that instead of using midas_add_test with the MIDAS{path/to/file.ext.md5} syntax for addressing the test data, the function ExternalData_add_target is used by specifying both DATA{path/to/file.ext} and a download target name.
Replace this:
midas_add_test(NAME test1 COMMAND ...) midas_add_test(NAME test2 COMMAND ...)
By this:
ExternalData_add_test(EMSegmentData NAME test1 COMMAND ...) ExternalData_add_test(EMSegmentData NAME test2 COMMAND ...) [...] ExternalData_add_target(EMSegmentData)
A key difference with the former approaches is that instead of adding two tests (one named
<testName>_fetchData to downoad the data and one running the test command), only one
test is added but a common download target is added at the end using ExternalData_add_target
function.
This means that test data can now be downloaded in parallel (and cached) at build time instead of testing time.
Slicer 4.9: CMake: Module SlicerMacroCheckExternalProjectDependency not available
Since the module was removed in r26992, consider updating
your build system to use CMake module ExternalProjectDependency
Slicer 4.9: CMake: Module SlicerMacroEmptyExternalProject not available
Since the module was removed in r26991
Replace this:
include(SlicerMacroEmptyExternalProject) [...] SlicerMacroEmptyExternalProject("${proj}" "${${proj}_DEPENDENCIES}")
By this:
include(ExternalProjectDependency) [...] ExternalProject_Add_Empty(${proj} DEPENDS ${${proj}_DEPENDENCIES})
Slicer 4.9: CMake: Module SlicerBlockSetCMakeOSXVariables not available
Since it was renamed to SlicerInitializeOSXVariables in r26982
Replace this:
include(SlicerBlockSetCMakeOSXVariables)
By this:
include(SlicerInitializeOSXVariables)
Slicer 4.9: Application: isRelease() function not available
See #Slicer_4.8:_Application:_isRelease.28.29_function_not_available_or_deprecated
Slicer 4.9: slicer.util.getNode() raises exception if node not found
If slicer.util.getNode() is called and the node is not found then instead of just returning None (Slicer 4.8 behavior), the method now raises a MRMLNodeNotFoundException. This makes code debugging easier (the error is reported when it happens), and in general more consistent with Python conventions.
How to update existing code:
It is advisable to only use slicer.util.getNode in tests, or interactively in the Python console, as its behavior is somewhat unpredictable (it may either found a node by name or ID, and result of wildcard search is even less deterministic). In general, it is recommended to use the MRML scene's GetFirstNodeByName and GetNodeByID methods instead.
Replace this:
n = slicer.util.getNode(nodeNameOrID)
By one of these:
If node is to be found by name:
n = slicer.mrmlScene.GetFirstNodeByName(nodeName)
If node is to be found by ID:
n = slicer.mrmlScene.GetNodeByID(nodeID)
If node is to be found by name or ID (slower, less predictable, recommended for testing only):
try: n = slicer.util.getNode(nodeNameOrID) except slicer.util.MRMLNodeNotFoundException: n = None
More information: https://github.com/Slicer/Slicer/commit/b63484af1b1b413f35396f8f7efb73e870448bd4
Slicer 4.8: Application: isRelease() function not available or deprecated
Error message similar to:
Missing/deprecated qSlicerCoreApplication::isRelease()
or
Missing/deprecated slicer.app.isRelease()
Solution:
Use qSlicerCoreApplication::releaseType() == "Stable"
Summary:
Prior to r26420, the variable Slicer_VERSION_TWEAK was used to check if a "stable release" was built. The variable value was set by updating the sources and defining the variable to an integer greater or equal to 0. In other word, if the variable evaluated to an empty string, a nighty or experimental build was being done, if it evaluated to an integer, a stable release build was being done.
The approach had few issues:
- the name of the variable was confusing
- identifying a "stable release" only from a source tree revision was not enough. Indeed the environment defining a "release" is the one found on the build machines used to generate the installer.
- nightly build are also considered as release
To address this, the CMake variable Slicer_RELEASE_TYPE was introduced. As of 2017-10-04, it can be set to Experimental, Nightly or Stable with Experimental being the value hard-coded in the source.
Identifying a build as "stable" is now explicitly done by setting Slicer_RELEASE_TYPE to Stable at configure time.
Also, since the concept of release types was introduced, the function isRelease() has been removed in favor of releaseType().
References:
https://github.com/Slicer/Slicer/pull/354
Slicer Python Module: modulewidget and others removed.
Summary Python classes formerly in "slicer.moduledm", "slicer.modulelogic", "slicer.modulemrml" and "slicer.modulewidget" are now directly available in the slicer module.
See example of change here.
Rational:
See comments in commit messages referenced blow.
References:
https://github.com/Slicer/Slicer/commit/628f83fe7a6f4e0710e306bcaf7c04b9e3e5e6bd
https://github.com/Slicer/Slicer/commit/9cb5668fde1abc8f0430a91ca37fc29277ceeb4e
MRML: Slicer 4.6: Moved up vtkMRMLStorableNode in the MRML node hierarchy.
Rational:
vtkMRMLStorableNode is not a children of vtkMRMLTransformable node anymore, but directly a children of vtkMRMLNode.
This allows making a node storable without requiring it to be also transformable. It is important for several node types (color maps, tables, etc), which require separate storage node but are not transformable.
References:
- Changed introduced in r24891
Error message similar to:
/tmp/LongitudinalPETCT/MRML/vtkMRMLLongitudinalPETCTStudyNode.cxx: In member function ‘void vtkMRMLLongitudinalPETCTStudyNode::ObserveRegistrationTransform(bool)’: /tmp/LongitudinalPETCT/MRML/vtkMRMLLongitudinalPETCTStudyNode.cxx:478:28: error: ‘class vtkMRMLVolumePropertyNode’ has no member named ‘GetParentTransformNode’ && propNode->GetParentTransformNode() ^ /tmp/LongitudinalPETCT/MRML/vtkMRMLLongitudinalPETCTStudyNode.cxx:480:23: error: ‘class vtkMRMLVolumePropertyNode’ has no member named ‘SetAndObserveTransformNodeID’ propNode->SetAndObserveTransformNodeID( ^ /tmp/LongitudinalPETCT/MRML/vtkMRMLLongitudinalPETCTStudyNode.cxx:503:23: error: ‘class vtkMRMLVolumePropertyNode’ has no member named ‘SetAndObserveTransformNodeID’ propNode->SetAndObserveTransformNodeID(NULL); ^
Solution:
Removes lines and/or refactor code
MRML: Slicer 4.5: Introduction of vtkMRMLLabelMapVolumeNode
Rational:
Before vtkMRMLScalarVolumeNode was used for both scalar and label map volumes and the LabelMap custom MRML node attribute was used for distinguishing between them (0=scalar; 1=label map volume).
This made conversion between labelmap/scalar volumes very easy but made it difficult to customize behavior, display, processing of segmentation information.
Now a new vtkMRMLLabelMapVolumeNode class is used for storing segmentation information (still using vtkMRMLScalarVolume used as base class for backward compatibility; but in the future the base class may be changed to reflect that segmentation can be represented in various ways, not just as volumes).
Error message similar to:
error: ‘class vtkMRMLScalarVolumeNode’ has no member named ‘SetLabelMap’ outputVolumeNode->SetLabelMap(1); ^
Solution (part1: down cast to vtkMRMLLabelMapVolumeNode, remove call to SetLabelMap)
Replace lines like:
vtkMRMLNode* outputNode = d->OutputLabelVolumeMRMLNodeComboBox->currentNode(); vtkMRMLScalarVolumeNode* outputVolumeNode = vtkMRMLScalarVolumeNode::SafeDownCast(outputNode); [...] outputVolumeNode->SetLabelMap(1);
with:
vtkMRMLLabelMapVolumeNode* outputVolumeNode = vtkMRMLLabelMapVolumeNode::SafeDownCast(d->OutputLabelVolumeMRMLNodeComboBox->currentNode()); [...]
Solution (part2: Update UI file):
Replace lines like:
<widget class="qMRMLNodeComboBox" name="InputLabelVolumeMRMLNodeComboBox"> <property name="nodeTypes"> <stringlist> <string>vtkMRMLScalarVolumeNode</string> </stringlist> </property> [...] </widget>
with:
<widget class="qMRMLNodeComboBox" name="InputLabelVolumeMRMLNodeComboBox"> <property name="nodeTypes"> <stringlist> <string>vtkMRMLLabelMapVolumeNode</string> <------------- Update Here </stringlist> </property> [...] </widget>
Solution (part3: Update node selector configuration):
Replace lines like:
nodeSelector.setNodeTypes(QStringList("vtkMRMLScalarVolumeNode")); nodeSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", "1");
with:
nodeSelector.setNodeTypes(QStringList("vtkMRMLLabelMapVolumeNode"));
References:
- http://www.slicer.org/slicerWiki/index.php/Documentation/Labs/Segmentations#vtkMRMLLabelMapVolumeNode_integration
- http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=24291
CLI: Slicer 4.3: Add ITKFactoryRegistration library centralizing ITK IO factory registration
Rational:
Linking against ITKFactoryRegistration ensures that ITK IO factory are properly registered on all supported platforms.
Error message similar to:
Undefined symbols for architecture x86_64: "itk::itkFactoryRegistration()", referenced from: _main in ImageMakerTest.cxx.o ld: symbol(s) not found for architecture x86_64
Solution:
Replace lines like:
target_link_libraries(${CLP}Test ${CLP}Lib)
with:
target_link_libraries(${CLP}Test ${CLP}Lib ${SlicerExecutionModel_EXTRA_EXECUTABLE_TARGET_LIBRARIES})
References: