Difference between revisions of "Documentation/Nightly/Modules/Markups"

From Slicer Wiki
Jump to: navigation, search
m (Text replacement - "\[https:\/\/www\.slicer\.org\/slicerWiki\/index.php\/([^ ]+) ([^]]+)]" to "$2")
Tag: 2017 source edit
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
<noinclude>{{documentation/versioncheck}}</noinclude>
 
<noinclude>{{documentation/versioncheck}}</noinclude>
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-header}}
 
<!-- ---------------------------- -->
 
  
<!-- ---------------------------- -->
+
{{documentation/banner
{{documentation/{{documentation/version}}/module-section|Introduction and Acknowledgements}}
+
| text  = [https://slicer.readthedocs.io/en/latest/user_guide/modules/markups.html This page has been moved to read-the-docs.]
{{documentation/{{documentation/version}}/module-introduction-start|{{documentation/modulename}}}}
+
| background-color = 8FBC8F }}
{{documentation/{{documentation/version}}/module-introduction-row}}
 
This work is part of the National Alliance for Medical Image Computing (NA-MIC), funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149. Information on NA-MIC can be obtained from the [http://www.na-mic.org/ NA-MIC website].<br>
 
Author: Nicole Aucoin, SPL, BWH<br>
 
Contact: Nicole Aucoin, <email>nicole@bwh.harvard.edu</email><br>
 
{{documentation/{{documentation/version}}/module-introduction-row}}
 
{{documentation/{{documentation/version}}/module-introduction-logo-gallery
 
|{{collaborator|logo|spl}}|{{collaborator|longname|spl}}
 
}}
 
{{documentation/{{documentation/version}}/module-introduction-end}}
 
 
 
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-section|Module Description}}
 
This module is used to manage markups in Slicer.
 
 
 
It is based on the functionality in the Slicer 3.6 Fiducials module, with elements from the Slicer 4.2 Annotations module.
 
 
 
Currently, only fiducials are supported.
 
 
 
{{documentation/{{documentation/version}}/module-description}}
 
 
 
Development history can be found in the [[documentation/{{documentation/version}}/Modules/{{documentation/modulename}}#References|references]].
 
 
 
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-section|Use Cases}}
 
 
 
This module allows you to add new markups, edit markups in a list, delete markups and modify display properties of markups.
 
 
 
 
 
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-section|How To Use}}
 
 
 
<gallery widths=300px heights=250px class="center">
 
File:Markups-ModifyList.png | 1. Select the active list, set visibility and lock flags, set uniform scale.
 
File:Markups-JumpSlices-44.png | 2. Jump the 2D slice view windows to the coordinates of the highlighted markup.
 
File:Markups-ModifyMarkupsInList.png | 3. Modify Markups in list: toggle visibility, selected, and lock flags, delete.
 
File:Markups-Table.png | 4. Table showing the fiducials in the active Markups list
 
File:Markups-Advanced.png | 5. Advanced panel: move markups up or down, add a markup, name format, convert annotation fiducials, display properties for the list of markups
 
File:Markups-DisplayProperties.png | 6. Display properties, inside the Advanced panel, there are 2D projection settings.
 
File:Markups-MouseToolbar.png | 7. Place Markup fiducials by setting the Mouse mode in the tool bar
 
</gallery>
 
 
 
'''Note:''' Markups can be passed to command line modules (CLIs) using the <pre>--point</pre> or <pre>--pointfile</pre> argument.
 
 
 
'''Note: '''The Mouse mode tool bar can be used to place new markups by positioning the mouse and left clicking in the viewers. Once you are in Place mode and placing Markups fiducials, you can use the 'p' key to place a new fiducial while the Markups GUI is open. You can also use a right button click to stop placing fiducials when in persistent mode.
 
 
 
'''Note: '''You can place fiducials and use the GUI to jump slices or the 3D view to those locations. If you select fiducials in the table, you can right click to get the summed linear distance between their locations.
 
 
 
'''Note: '''The Markups module can convert Annotation fiducials into Markups fiducials, and will offer the user the option of doing it automatically when the Markups GUI is entered. There is also a manual button under the Advanced tab.
 
 
 
 
 
{{documentation/{{documentation/version}}/module-section|Panels and their use}}
 
 
 
{{documentation/{{documentation/version}}/module-parametersdescription}}
 
 
 
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-section|Similar Modules}}
 
 
 
*[[Documentation/Nightly/Modules/Annotations | Annotations]] module is similar, and will be deprecated as the functionality is moved to the Markups module.
 
*[https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/Endoscopy/Endoscopy.py#L303 Endoscopy module] uses fiducials
 
 
 
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-section|References}}
 
 
 
*[http://wiki.na-mic.org/Wiki/index.php/2013_Summer_Project_Week:MarkupsModuleSummer2013 Summer 2013 Project Week project page]
 
*[http://wiki.na-mic.org/Wiki/index.php/2013_Project_Week:MarkupsModule Winter 2013 Project Week project page]
 
*[http://wiki.na-mic.org/Wiki/index.php/2012_Summer_Project_Week:AnnotationModule Summer 2012 Project Week project page]
 
 
 
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-section|Information for Developers}}
 
The Simple Markups Widget can be integrated into slicelets. It is lightweight and can access the Markups features. An example of this use is in [[Documentation/Nightly/Modules/GelDosimetry|Gel Dosimetry.]] To use this, access it at [https://github.com/Slicer/Slicer/blob/master/Modules/Loadable/Markups/Widgets/qSlicerSimpleMarkupsWidget.h GitHub.]
 
 
 
== Python ==
 
 
 
=== Open the Markups Module ===
 
 
 
You can set the Markups module gui to be the current module gui using this command:
 
 
 
  slicer.util.mainWindow().moduleSelector().selectModule('Markups')
 
 
 
=== Load From File ===
 
 
 
Markups fiducials can be loaded from file:
 
 
 
  slicer.util.loadMarkupsFiducialList('/path/to/list/F.fcsv')
 
 
 
=== Adding Fiducials Programatically ===
 
 
 
Markups fiducials can be added to the currently active list from the python console by using the following module logic command:
 
 
 
  slicer.modules.markups.logic().AddFiducial()
 
 
 
The command with no arguments will place a new fiducial at the origin. You can also pass it an initial location:
 
 
 
  slicer.modules.markups.logic().AddFiducial(1.0, -2.0, 3.3)
 
 
 
=== Add a button to module GUI to activate fiducial placement ===
 
 
 
This code snippet creates a toggle button, which activates fiducial placement when pressed (and deactivates when released).
 
The [http://apidocs.slicer.org/master/classqSlicerMarkupsPlaceWidget.html qSlicerMarkupsPlaceWidget widget] can automatically activate placement of multiple points and can show buttons for deleting points, changing colors, lock, and hide points.
 
 
 
<pre>
 
w=slicer.qSlicerMarkupsPlaceWidget()
 
w.setMRMLScene(slicer.mrmlScene)
 
markupsNodeID = slicer.modules.markups.logic().AddNewFiducialNode()
 
w.setCurrentNode(slicer.mrmlScene.GetNodeByID(markupsNodeID))
 
# Hide all buttons and only show place button
 
w.buttonsVisible=False
 
w.placeButton().show()
 
w.show()
 
</pre>
 
 
 
=== Adding Fiducials via Mouse Clicks ===
 
 
 
You can also set the mouse mode into Markups fiducial placement by calling:
 
 
 
  placeModePersistence = 1
 
  slicer.modules.markups.logic().StartPlaceMode(placeModePersistence)
 
 
 
A lower level way to do this is via the selection and interaction nodes:
 
  selectionNode = slicer.mrmlScene.GetNodeByID("vtkMRMLSelectionNodeSingleton")
 
  selectionNode.SetReferenceActivePlaceNodeClassName("vtkMRMLMarkupsFiducialNode")
 
  interactionNode = slicer.mrmlScene.GetNodeByID("vtkMRMLInteractionNodeSingleton")
 
  placeModePersistence = 1
 
  interactionNode.SetPlaceModePersistence(placeModePersistence)
 
  # mode 1 is Place, can also be accessed via slicer.vtkMRMLInteractionNode().Place
 
  interactionNode.SetCurrentInteractionMode(1)
 
 
 
To switch back to view transform once you're done placing fiducials:
 
  interactionNode = slicer.mrmlScene.GetNodeByID("vtkMRMLInteractionNodeSingleton")
 
  interactionNode.SwitchToViewTransformMode()
 
  # also turn off place mode persistence if required
 
  interactionNode.SetPlaceModePersistence(0)
 
 
 
=== Access to Fiducial Properties ===
 
 
 
Each vtkMRMLMarkupsFiducialNode has a vector of points in it which can be accessed from python:
 
 
 
  fidNode = getNode("vtkMRMLMarkupsFiducialNode1")
 
  n = fidNode.AddFiducial(4.0, 5.5, -6.0)
 
  fidNode.SetNthFiducialLabel(n, "new label")
 
  # each markup is given a unique id which can be accessed from the superclass level
 
  id1 = fidNode.GetNthMarkupID(n)
 
  # manually set the position
 
  fidNode.SetNthFiducialPosition(n, 6.0, 7.0, 8.0)
 
  # set the label
 
  fidNode.SetNthFiducialLabel(n, "New label")
 
  # set the selected flag, only selected = 1 fiducials will be passed to CLIs
 
  fidNode.SetNthFiducialSelected(n, 1)
 
  # set the visibility flag
 
  fidNode.SetNthFiducialVisibility(n, 0) 
 
 
 
You can loop over the fiducials in a list and get the coordinates:
 
 
 
  fidList = slicer.util.getNode('F')
 
  numFids = fidList.GetNumberOfFiducials()
 
  for i in range(numFids):
 
    ras = [0,0,0]
 
    fidList.GetNthFiducialPosition(i,ras)
 
    # the world position is the RAS position with any transform matrices applied
 
    world = [0,0,0,0]
 
    fidList.GetNthFiducialWorldCoordinates(0,world)
 
    print(i,": RAS =",ras,", world =",world)
 
 
 
You can also look at the sample code in the [https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/Endoscopy/Endoscopy.py#L287  Endoscopy module] to see how python is used to access fiducials from a scripted module.
 
 
 
=== VTK Widget access ===
 
 
 
The Markups 3D fiducial displayable manager can be accessed from python allowing debugging of the vtkSeedWidget:
 
 
 
  fidNode = slicer.mrmlScene.GetNodeByID("vtkMRMLMarkupsFiducialNode1")
 
  lm = slicer.app.layoutManager()
 
  td = lm.threeDWidget(0)
 
  ms = vtk.vtkCollection()
 
  td.getDisplayableManagers(ms)
 
  for i in range(ms.GetNumberOfItems()):
 
    m = ms.GetItemAsObject(i)
 
    if m.GetClassName() == "vtkMRMLMarkupsFiducialDisplayableManager3D":
 
      print(i, m.GetClassName())
 
      h = m.GetHelper()
 
      seedWidget = h.GetWidget(fidNode)
 
      seedRepresentation = seedWidget.GetSeedRepresentation()
 
      handleRep2 = seedRepresentation.GetHandleRepresentation(2)
 
      print(handleRep2.GetDisplayPosition())
 
      print(handleRep2.GetWorldPosition())
 
 
 
 
 
The Markups 2D fiducial displayable manager can be accessed from python as well to debug the seed widget in 2D. For the Red slice viewer:
 
 
 
  fidNode = slicer.mrmlScene.GetNodeByID("vtkMRMLMarkupsFiducialNode1")
 
  lm = slicer.app.layoutManager()
 
  redWidget = lm.sliceWidget("Red")
 
  redView = redWidget.sliceView()
 
  ms = vtk.vtkCollection()
 
  redView.getDisplayableManagers(ms)
 
  for i in range(ms.GetNumberOfItems()):
 
  m = ms.GetItemAsObject(i)
 
  if m.GetClassName() == "vtkMRMLMarkupsFiducialDisplayableManager2D":
 
    print(i, m.GetClassName())
 
    h = m.GetHelper()
 
    seedWidget = h.GetWidget(fidNode)
 
    seedRepresentation = seedWidget.GetSeedRepresentation()
 
    handleRep = seedRepresentation.GetHandleRepresentation(0)
 
    print(handleRep.GetDisplayPosition())
 
 
 
== C++ ==
 
 
 
===Selection and Interaction===
 
 
 
For the selection and interaction nodes, make sure that you access the singleton nodes already in the scene (rather than making your own) via (caveat: this call works on displayable managers, you may have to go a different route to get at the application logic):
 
  vtkMRMLApplicationLogic *mrmlAppLogic = this->GetMRMLApplicationLogic();
 
  vtkMRMLInteractionNode *inode = mrmlAppLogic->GetInteractionNode();
 
  vtkMRMLSelectionNode *snode = mrmlAppLogic->GetSelectionNode();
 
If you can't get at the mrml application logic, you can get the nodes from the scene:
 
  vtkMRMLInteractionNode *interactionNode = vtkMRMLInteractionNode::SafeDownCast(this->GetMRMLScene()->GetNodeByID("vtkMRMLInteractionNodeSingleton"));
 
 
 
You can then call methods on the nodes or add your own event observers as in
 
  vtkSlicerMarkupsModuleLogic::ObserveMRMLScene
 
You can see vtkSlicerMarkupsModuleLogic::ProcessMRMLNodesEvents to see how to respond to interaction node changes.
 
 
 
Slicer4/Base/QTGUI/qSlicerMouseModeToolBar.cxx has a lot of the code you'll need as well, with a slightly different way of getting at the mrml app logic to access the nodes.
 
 
 
The calls you need to make to switch into placing fiducials with the mouse are:
 
  selectionNode->SetReferenceActivePlaceNodeClassName("vtkMRMLMarkupsFiducialNode");
 
  interactionNode->SetCurrentInteractionMode(vtkMRMLInteractionNode::Place);
 
If you don't set PlaceModePersistence on the interaction node to 1, the mouse mode/current interaction mode will automatically go back to view transform after one fiducial has been placed, and you just need to reset the current interaction mode for future placing (the active place node class name and ID are persistent).
 
 
 
=== Programmatic Access to Fiducials ===
 
 
 
This section explains how to access fiducial nodes added into the scene by the user.
 
 
 
In your module's Logic class, overwrite SetMRMLSceneInternal to observe the NodeAddedEvent of the scene:
 
void vtkSlicerMYMODULEModuleLogic::SetMRMLSceneInternal(vtkMRMLScene * newScene)
 
  {
 
  vtkNew<vtkIntArray> events;
 
  events->InsertNextValue(vtkMRMLScene::NodeAddedEvent);
 
  // Optionally you can add more events here,
 
  // such as vtkMRMLScene::NodeRemovedEvent
 
  this->SetAndObserveMRMLSceneEventsInternal(newScene, events.GetPointer());
 
  }
 
Via the set and observe mrml scene macro, anytime a node is added into the scene, it will trigger the base Logic class method
 
[http://slicer.org/doc/html/classvtkMRMLAbstractLogic.html#a51fdf00ecfc18c1a1465d4bccb789ef1 vtkMRMLAbstractLogic::ProcessMRMLNodesEvents] which calls the virtual method <code>vtkMRMLAbstractLogic::OnMRMLSceneNodeAdded(vtkMRMLNode* node)</code>
 
Reimplement that method in your logic class:
 
void vtkSlicerMYMODULEModuleLogic::OnMRMLSceneNodeAdded(vtkMRMLNode* addedNode)
 
  {
 
  vtkMRMLMarkupsFiducialNode* fidNode =
 
    vtkMRMLMarkupsFiducialNode::SafeDownCast(addedNode);
 
  if (fidNode)
 
    {
 
    // here you write what you need to do when a
 
    // fiducial node is added into the scene
 
    }
 
  }
 
 
 
=== File Format===
 
 
 
The Markups Fiducial storage node uses a comma separated value file to store the fiducials on disk. The format is:
 
 
 
A leading comment line giving the Slicer version number:
 
  # Markups fiducial file version = 4.5
 
A comment line giving the coordinate system, RAS = 0, LPS = 1, IJK = 2 (IJK is currently not supported, RAS is printed instead)
 
  # CoordinateSystem = 0
 
A comment line explaining the fields in the csv
 
  # columns = id,x,y,z,ow,ox,oy,oz,vis,sel,lock,label,desc,associatedNodeID
 
Then comes the fiducials, one per line, for example:
 
  vtkMRMLMarkupsFiducialNode_0,1.29,-40.18,60.15,0,0,0,1,1,1,0,F-1,,
 
*id = a string giving a unique id for this fiducial, usually based on the class name
 
*x,y,z = the floating point coordinate of the fiducial point
 
*ow,ox,oy,oz = the orientation quaternion of this fiducial, angle and axis, default 0,0,0,1 (or 0,0,0,0,0,0,1.0)
 
*vis = the visibility flag for this fiducial, 0 or 1, default 1
 
*sel = the selected flag for this fiducial, 0 or 1, default 1
 
*lock = the locked flag for this fiducial, 0 or 1, default 0
 
*label = the name for this fiducial, displayed beside the glyph, with quotes around it if there is a comma in the field
 
*desc = a string description for this fiducial, optional
 
*associatedNodeID = an id of a node in the scene with which the fiducial is associated, for example the volume or model on which the fiducial was placed, optional
 
 
 
The file can be parsed using stringstream and getline:
 
 
 
  std::fstream fstr;
 
  fstr.open(fileName.c_str(), std::fstream::in);
 
  char line[1024];
 
  while (fstr.good())
 
    {
 
    fstr.getline(line, 1024);
 
    std::stringstream ss(line);
 
    std::string component;
 
    getline(ss, component, ',');
 
    [...]
 
    }
 
 
 
<!-- ---------------------------- -->
 
{{documentation/{{documentation/version}}/module-footer}}
 
<!-- ---------------------------- -->
 

Latest revision as of 23:24, 22 May 2020

Home < Documentation < Nightly < Modules < Markups