def makeModel(self,volumeNode, labelNumber, smoothValue,namenode):
    #the volume need to present must valid
    if not volumeNode:
      return


    # set up the model maker node
    parameters = {}
    parameters['Name'] = "EditorModel"
    parameters["InputVolume"] = volumeNode.GetID()
    parameters['FilterType'] = "Sinc"

    # build only the currently selected model.
    parameters['Labels'] = labelNumber #using default label, that can further improved by using label that user selected
    parameters["StartLabel"] = -1
    parameters["EndLabel"] = -1

    parameters['GenerateAll'] = False
    parameters["JointSmoothing"] = False
    parameters["SplitNormals"] = True
    parameters["PointNormals"] = True
    parameters["SkipUnNamed"] = True
    parameters["Decimate"] = 0.25
    parameters["Smooth"] = smoothValue #defaul smooth parameter

    #
    # output
    # - make a new hierarchy node if needed
    #
    numNodes = slicer.mrmlScene.GetNumberOfNodesByClass( "vtkMRMLModelHierarchyNode" )
    outHierarchy = None
    for n in range(numNodes):
      node = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLModelHierarchyNode" )
      if node.GetName() == "Editor Models":
        outHierarchy = node
        break

    if not outHierarchy:
      outHierarchy = slicer.vtkMRMLModelHierarchyNode()
      outHierarchy.SetScene( slicer.mrmlScene )
      outHierarchy.SetName( namenode )
      slicer.mrmlScene.AddNode( outHierarchy )

    parameters["ModelSceneFile"] = outHierarchy

    modelMaker = slicer.modules.modelmaker

    #
    # run the task (in the background)
    # - use the GUI to provide progress feedback
    # - use the GUI's Logic to invoke the task
    # - model will show up when the processing is finished
    #
    slicer.cli.run(modelMaker, None, parameters)
  def makeModels(study, finding, colorTable):

    if (study is None) | (finding is None) | (colorTable is None):
      return    
     
    seg = finding.GetSegmentationMappedByStudyNodeID(study.GetID())
      
    if seg:
      labelVolume = seg.GetLabelVolumeNode()

      #create a temporary model hierarchy for generating models
      tempMH = slicer.vtkMRMLModelHierarchyNode()
      slicer.mrmlScene.AddNode(tempMH)
      
      if (labelVolume is not None) & (tempMH is not None):
        parameters = {'InputVolume': labelVolume.GetID(), 'ColorTable': colorTable.GetID(),
                      'ModelSceneFile': tempMH.GetID(), 'GenerateAll': False, 'StartLabel': finding.GetColorID(),
                      'EndLabel': finding.GetColorID(), 'Name': labelVolume.GetName() + "_" + finding.GetName() + "_M"}

        cliModelMaker = None
        cliModelMaker = slicer.cli.run(slicer.modules.modelmaker, cliModelMaker, parameters, wait_for_completion = True)  
        genModelNodes = vtk.vtkCollection()
        tempMH.GetChildrenModelNodes(genModelNodes)

        if genModelNodes.GetNumberOfItems() > 0:
          modelNode = genModelNodes.GetItemAsObject(0)
          if modelNode:
            if modelNode.IsA('vtkMRMLModelNode'):
              hnode = slicer.vtkMRMLHierarchyNode.GetAssociatedHierarchyNode(modelNode.GetScene(), modelNode.GetID())
              if hnode:
                if seg.GetModelHierarchyNode():
                  SlicerLongitudinalPETCTModuleViewHelper.removeModelHierarchyAndChildModelNodesFromScene(seg.GetModelHierarchyNode())
                  
                  hnode.SetName(seg.GetName()+"_Model")
                  seg.SetAndObserveModelHierarchyNodeID(hnode.GetID())
                  modelNode.SetName(labelVolume.GetName() + "_" + finding.GetName()+"_M")
                  if modelNode.GetDisplayNode():
                    modelNode.GetDisplayNode().SetName(labelVolume.GetName() + "_" + finding.GetName()+"_D")
                    modelNode.GetDisplayNode().AddViewNodeID(SlicerLongitudinalPETCTModuleViewHelper.getStandardViewNode().GetID())
                  hnode.SetName(labelVolume.GetName() + "_" + finding.GetName()+"_H")
                  modelNode.SetHideFromEditors(False)
                else:
                  seg.SetAndObserveModelHierarchyNodeID("")
                  slicer.mrmlScene.RemoveNode(modelNode)   
                  slicer.mrmlScene.RemoveNode(hnode)
   
          slicer.mrmlScene.RemoveNode(tempMH.GetDisplayNode())
          slicer.mrmlScene.RemoveNode(tempMH)        
    
    #return '#%02X%02X%02X' % (r,g,b)
    def _internalTest():
        # test loading of measurements file
        logic = lapdMouseVisualizerLogic()
        measurementsFile = '/home/christian/data/R01_lapdmousetest/m01/geometry_measurements.csv'
        slicer.util.loadNodeFromFile(measurementsFile, 'TableFile')
        measurementsTable = slicer.util.getFirstNodeByClassByName(
            'vtkMRMLTableNode', 'geometry_measurements')
        model = logic.measurementsTable2Model(measurementsTable)
        model.SetScene(slicer.mrmlScene)
        model.CreateDefaultDisplayNodes()
        slicer.mrmlScene.AddNode(model)

        # test loading of measurements file

        logic = lapdMouseVisualizerLogic()
        treeFilename = '/home/christian/data/R01_lapdmousetest/m01/m01_AirwayTree.meta'
        tree = logic.readMetaTree(treeFilename)
        modelHierarchy = slicer.vtkMRMLModelHierarchyNode()
        model = logic.tree2Model(tree)
        model.SetScene(slicer.mrmlScene)
        model.CreateDefaultDisplayNodes()
        slicer.mrmlScene.AddNode(model)

        self.delayDisplay('Test passed!')
Example #4
0
  def test_sceneImport24281(self):
    """ Ideally you should have several levels of tests.  At the lowest level
    tests should exercise the functionality of the logic with different inputs
    (both valid and invalid).  At higher levels your tests should emulate the
    way the user would interact with your code and confirm that it still works
    the way you intended.
    One of the most important features of the tests is that it should alert other
    developers when their changes will have an impact on the behavior of your
    module.  For example, if a developer removes a feature that you depend on,
    your test should break so they know that the feature is needed.
    """

    self.delayDisplay("Starting the test")
    #
    # first, get some data
    #
    self.delayDisplay("Getting Data")
    import SampleData
    head = SampleData.downloadSample("MRHead")

    #
    # create a label map and set it for editing
    #
    self.delayDisplay("Setting up LabelMap")
    volumesLogic = slicer.modules.volumes.logic()
    headLabel = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, head, head.GetName() + '-label' )
    selectionNode = slicer.app.applicationLogic().GetSelectionNode()
    selectionNode.SetActiveVolumeID( head.GetID() )
    selectionNode.SetActiveLabelVolumeID( headLabel.GetID() )
    slicer.app.applicationLogic().PropagateVolumeSelection(0)

    #
    # got to the editor and do some drawing
    #
    import EditorLib
    self.delayDisplay("Setting up Editor and drawing")
    editUtil = EditorLib.EditUtil.EditUtil()
    parameterNode = editUtil.getParameterNode()
    lm = slicer.app.layoutManager()
    paintEffectOptions = EditorLib.PaintEffectOptions()
    paintEffectOptions.setMRMLDefaults()
    paintEffectOptions.__del__()

    self.delayDisplay('Paint radius is %s' % parameterNode.GetParameter('PaintEffect,radius'))
    sliceWidget = lm.sliceWidget('Red')
    size = min(sliceWidget.width,sliceWidget.height)
    step = size / 12
    center = size / 2
    parameterNode.SetParameter('PaintEffect,radius', '20')
    paintTool = EditorLib.PaintEffectTool(sliceWidget)
    self.delayDisplay('Paint radius is %s, tool radius is %d' % (parameterNode.GetParameter('PaintEffect,radius'),paintTool.radius))
    for label in xrange(1,5):
      editUtil.setLabel(label)
      pos = center - 2*step + (step * label)
      self.delayDisplay('Painting %d, at  (%d,%d)' % (label,pos,pos),200)
      paintTool.paintAddPoint(pos,pos)
      paintTool.paintApply()
    paintTool.cleanup()
    paintTool = None

    #
    # now build:
    # create a model using the command line module
    # based on the current editor parameters
    # - make a new hierarchy node
    #

    self.delayDisplay( "Building..." )

    parameters = {}
    parameters["InputVolume"] = headLabel.GetID()
    # create models for all labels
    parameters["JointSmoothing"] = True
    parameters["StartLabel"] = -1
    parameters["EndLabel"] = -1
    outHierarchy = slicer.vtkMRMLModelHierarchyNode()
    outHierarchy.SetScene( slicer.mrmlScene )
    outHierarchy.SetName( "sceneImport2428Hierachy" )
    slicer.mrmlScene.AddNode( outHierarchy )
    parameters["ModelSceneFile"] = outHierarchy

    modelMaker = slicer.modules.modelmaker
    self.CLINode = None
    self.CLINode = slicer.cli.runSync(modelMaker, self.CLINode, parameters, delete_temporary_files=False)

    self.delayDisplay("Models built")

    success = self.verifyModels()

    success = success and (slicer.mrmlScene.GetNumberOfNodesByClass( "vtkMRMLModelNode" ) > 3)

    self.delayDisplay("Test finished")

    if success:
      self.delayDisplay("Ahh... test passed.")
    else:
      self.delayDisplay("!$!$!#!@#!@!@$%! Test Failed!!")

    self.assertTrue(success)
  def build(self):
    """make models of current merge volume"""

    #
    # get the image data for the label layer
    #

    self.statusText( "Building..." )
    merge = self.merge
    if not merge:
      return

    #
    # create a model using the command line module
    # based on the current editor parameters
    #

    parameters = {}
    parameters["InputVolume"] = merge.GetID()
    parameters['FilterType'] = "Sinc"
    parameters['GenerateAll'] = True

    # not needed: setting StartLabel and EndLabel instead
    #parameters['Labels'] = self.getPaintLabel()

    parameters["JointSmoothing"] = True
    parameters["SplitNormals"] = True
    parameters["PointNormals"] = True
    parameters["SkipUnNamed"] = True

    # create models for all labels
    parameters["StartLabel"] = -1
    parameters["EndLabel"] = -1

    parameters["Decimate"] = 0.25
    parameters["Smooth"] = 10

    #
    # output
    # - make a new hierarchy node if needed
    #
    numNodes = slicer.mrmlScene.GetNumberOfNodesByClass( "vtkMRMLModelHierarchyNode" )
    outHierarchy = None
    for n in xrange(numNodes):
      node = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLModelHierarchyNode" )
      if node.GetName() == "Editor Models":
        outHierarchy = node
        break

    if outHierarchy and self.replaceModels.checked and numNodes > 0:
      # user wants to delete any existing models, so take down hierarchy and
      # delete the model nodes
      rr = range(numNodes)
      rr.reverse()
      for n in rr:
        node = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLModelHierarchyNode" )
        if node.GetParentNodeID() == outHierarchy.GetID():
          slicer.mrmlScene.RemoveNode( node.GetModelNode() )
          slicer.mrmlScene.RemoveNode( node )

    if not outHierarchy:
      outHierarchy = slicer.vtkMRMLModelHierarchyNode()
      outHierarchy.SetScene( slicer.mrmlScene )
      outHierarchy.SetName( "Editor Models" )
      slicer.mrmlScene.AddNode( outHierarchy )

    parameters["ModelSceneFile"] = outHierarchy

    try:
      modelMaker = slicer.modules.modelmaker
      #
      # run the task (in the background)
      # - use the GUI to provide progress feedback
      # - use the GUI's Logic to invoke the task
      # - model will show up when the processing is finished
      #
      self.CLINode = slicer.cli.run(modelMaker, self.CLINode, parameters)
      self.statusText( "Model Making Started..." )
    except AttributeError:
      slicer.util.errorDisplay('The ModelMaker module is not available<p>Perhaps it was disabled in the application '
                               'settings or did not load correctly.', windowTitle='Editor')
Example #6
0
    def build(self):
        """make models of current merge volume"""

        #
        # get the image data for the label layer
        #

        self.statusText("Building...")
        merge = self.merge
        if not merge:
            return

        #
        # create a model using the command line module
        # based on the current editor parameters
        #

        parameters = {}
        parameters["InputVolume"] = merge.GetID()
        parameters['FilterType'] = "Sinc"
        parameters['GenerateAll'] = True

        # not needed: setting StartLabel and EndLabel instead
        #parameters['Labels'] = self.getPaintLabel()

        parameters["JointSmoothing"] = True
        parameters["SplitNormals"] = True
        parameters["PointNormals"] = True
        parameters["SkipUnNamed"] = True

        # create models for all labels
        parameters["StartLabel"] = -1
        parameters["EndLabel"] = -1

        parameters["Decimate"] = 0.25
        parameters["Smooth"] = 10

        #
        # output
        # - make a new hierarchy node if needed
        #
        numNodes = slicer.mrmlScene.GetNumberOfNodesByClass(
            "vtkMRMLModelHierarchyNode")
        outHierarchy = None
        for n in xrange(numNodes):
            node = slicer.mrmlScene.GetNthNodeByClass(
                n, "vtkMRMLModelHierarchyNode")
            if node.GetName() == "Editor Models":
                outHierarchy = node
                break

        if outHierarchy and self.replaceModels.checked and numNodes > 0:
            # user wants to delete any existing models, so take down hierarchy and
            # delete the model nodes
            rr = range(numNodes)
            rr.reverse()
            for n in rr:
                node = slicer.mrmlScene.GetNthNodeByClass(
                    n, "vtkMRMLModelHierarchyNode")
                if node.GetParentNodeID() == outHierarchy.GetID():
                    slicer.mrmlScene.RemoveNode(node.GetModelNode())
                    slicer.mrmlScene.RemoveNode(node)

        if not outHierarchy:
            outHierarchy = slicer.vtkMRMLModelHierarchyNode()
            outHierarchy.SetScene(slicer.mrmlScene)
            outHierarchy.SetName("Editor Models")
            slicer.mrmlScene.AddNode(outHierarchy)

        parameters["ModelSceneFile"] = outHierarchy

        try:
            modelMaker = slicer.modules.modelmaker
            #
            # run the task (in the background)
            # - use the GUI to provide progress feedback
            # - use the GUI's Logic to invoke the task
            # - model will show up when the processing is finished
            #
            self.CLINode = slicer.cli.run(modelMaker, self.CLINode, parameters)
            self.statusText("Model Making Started...")
        except AttributeError:
            slicer.util.errorDisplay(
                'The ModelMaker module is not available<p>Perhaps it was disabled in the application '
                'settings or did not load correctly.',
                windowTitle='Editor')
  def TestSection_2_qMRMLSegmentationGeometryWidget(self):
    logging.info('Test section 2: qMRMLSegmentationGeometryWidget')

    import vtkSegmentationCore
    binaryLabelmapReprName = vtkSegmentationCore.vtkSegmentationConverter.GetBinaryLabelmapRepresentationName()
    closedSurfaceReprName = vtkSegmentationCore.vtkSegmentationConverter.GetClosedSurfaceRepresentationName()

    # Use MRHead and Tinypatient for testing
    import SampleData
    sampleDataLogic = SampleData.SampleDataLogic()
    mrVolumeNode = sampleDataLogic.downloadMRHead()
    [tinyVolumeNode, tinySegmentationNode] = sampleDataLogic.downloadSample('TinyPatient')

    # Convert MRHead to oriented image data
    import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
    mrOrientedImageData = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.CreateOrientedImageDataFromVolumeNode(mrVolumeNode)
    mrOrientedImageData.UnRegister(None)

    # Create segmentation node with binary labelmap master and one segment with MRHead geometry
    segmentationNode = slicer.vtkMRMLSegmentationNode()
    segmentationNode.GetSegmentation().SetMasterRepresentationName(binaryLabelmapReprName)
    geometryStr = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(mrOrientedImageData)
    segmentationNode.GetSegmentation().SetConversionParameter(
      vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), geometryStr)
    slicer.mrmlScene.AddNode(segmentationNode)
    threshold = vtk.vtkImageThreshold()
    threshold.SetInputData(mrOrientedImageData)
    threshold.ThresholdByUpper(16.0)
    threshold.SetInValue(1)
    threshold.SetOutValue(0)
    threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR)
    threshold.Update()
    segmentOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()
    segmentOrientedImageData.DeepCopy(threshold.GetOutput())
    mrImageToWorldMatrix = vtk.vtkMatrix4x4()
    mrOrientedImageData.GetImageToWorldMatrix(mrImageToWorldMatrix)
    segmentOrientedImageData.SetImageToWorldMatrix(mrImageToWorldMatrix)
    segment = vtkSegmentationCore.vtkSegment()
    segment.SetName('Brain')
    segment.SetColor(0.0,0.0,1.0)
    segment.AddRepresentation(binaryLabelmapReprName, segmentOrientedImageData)
    segmentationNode.GetSegmentation().AddSegment(segment)

    # Create geometry widget
    geometryWidget = slicer.qMRMLSegmentationGeometryWidget()
    geometryWidget.setSegmentationNode(segmentationNode)
    geometryWidget.editEnabled = True
    geometryImageData = vtkSegmentationCore.vtkOrientedImageData() # To contain the output later

    # Volume source with no transforms
    geometryWidget.setSourceNode(tinyVolumeNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (248.8439, 248.2890, -123.75),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

    # Transformed volume source
    translationTransformMatrix = vtk.vtkMatrix4x4()
    translationTransformMatrix.SetElement(0,3,24.5)
    translationTransformMatrix.SetElement(1,3,24.5)
    translationTransformMatrix.SetElement(2,3,11.5)
    translationTransformNode = slicer.vtkMRMLLinearTransformNode()
    translationTransformNode.SetName('TestTranslation')
    slicer.mrmlScene.AddNode(translationTransformNode)
    translationTransformNode.SetMatrixTransformToParent(translationTransformMatrix)

    tinyVolumeNode.SetAndObserveTransformNodeID(translationTransformNode.GetID())
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (224.3439, 223.7890, -135.25),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 94)

    # Volume source with isotropic spacing
    tinyVolumeNode.SetAndObserveTransformNodeID(None)
    geometryWidget.setIsotropicSpacing(True)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (23,23,23), (248.8439, 248.2890, -123.75),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 414)

    # Volume source with oversampling
    geometryWidget.setIsotropicSpacing(False)
    geometryWidget.setOversamplingFactor(2.0)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (24.5, 24.5, 11.5), (261.0939, 260.5390, -129.5),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 751)
    slicer.util.delayDisplay('Volume source cases - OK')

    # Segmentation source with binary labelmap master
    geometryWidget.setOversamplingFactor(1.0)
    geometryWidget.setSourceNode(tinySegmentationNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (248.8439, 248.2890, -123.75),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

    # Segmentation source with closed surface master
    tinySegmentationNode.GetSegmentation().SetConversionParameter('Smoothing factor', '0.0')
    self.assertTrue(tinySegmentationNode.GetSegmentation().CreateRepresentation(closedSurfaceReprName))
    tinySegmentationNode.GetSegmentation().SetMasterRepresentationName(closedSurfaceReprName)
    tinySegmentationNode.Modified() # Trigger re-calculation of geometry (only generic Modified event is observed)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-167.156, -217.711, -135.75),
        [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5223846)
    slicer.util.delayDisplay('Segmentation source cases - OK')

    # Model source with no transform
    outputModelHierarchy = slicer.vtkMRMLModelHierarchyNode()
    slicer.mrmlScene.AddNode(outputModelHierarchy)
    success = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.ExportVisibleSegmentsToModelHierarchy(
      tinySegmentationNode, outputModelHierarchy )
    self.assertTrue(success)
    modelNode = slicer.util.getNode('Body_Contour')
    geometryWidget.setSourceNode(modelNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-167.156, -217.711, -135.75),
        [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5223846)

    # Transformed model source
    rotationTransform = vtk.vtkTransform()
    rotationTransform.RotateX(45)
    rotationTransformMatrix = vtk.vtkMatrix4x4()
    rotationTransform.GetMatrix(rotationTransformMatrix)
    rotationTransformNode = slicer.vtkMRMLLinearTransformNode()
    rotationTransformNode.SetName('TestRotation')
    slicer.mrmlScene.AddNode(rotationTransformNode)
    rotationTransformNode.SetMatrixTransformToParent(rotationTransformMatrix)

    modelNode.SetAndObserveTransformNodeID(rotationTransformNode.GetID())
    modelNode.Modified()
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-167.156, -58.6623, -249.228),
        [[0.0, 0.0, 1.0], [-0.7071, -0.7071, 0.0], [0.7071, -0.7071, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5221241)

    # ROI source
    roiNode = slicer.vtkMRMLAnnotationROINode()
    roiNode.SetName('SourceROI')
    slicer.mrmlScene.AddNode(roiNode)
    roiNode.UnRegister(None)
    xyz = [0]*3
    center = [0]*3
    slicer.vtkMRMLSliceLogic.GetVolumeRASBox(tinyVolumeNode, xyz, center)
    radius = map(lambda x: x/2.0, xyz)
    roiNode.SetXYZ(center)
    roiNode.SetRadiusXYZ(radius)
    geometryWidget.setSourceNode(roiNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-216.156, -217.711, -135.75),
        [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5223846)
    slicer.util.delayDisplay('Model and ROI source cases - OK')

    slicer.util.delayDisplay('Segmentation geometry widget test passed')
Example #8
0
  def test_sceneImport24281(self):
    """ Ideally you should have several levels of tests.  At the lowest level
    tests should exercise the functionality of the logic with different inputs
    (both valid and invalid).  At higher levels your tests should emulate the
    way the user would interact with your code and confirm that it still works
    the way you intended.
    One of the most important features of the tests is that it should alert other
    developers when their changes will have an impact on the behavior of your
    module.  For example, if a developer removes a feature that you depend on,
    your test should break so they know that the feature is needed.
    """

    self.delayDisplay("Starting the test")
    #
    # first, get some data
    #
    self.delayDisplay("Getting Data")
    import SampleData
    head = SampleData.downloadSample("MRHead")

    #
    # create a label map and set it for editing
    #
    self.delayDisplay("Setting up LabelMap")
    volumesLogic = slicer.modules.volumes.logic()
    headLabel = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, head, head.GetName() + '-label' )
    selectionNode = slicer.app.applicationLogic().GetSelectionNode()
    selectionNode.SetActiveVolumeID( head.GetID() )
    selectionNode.SetActiveLabelVolumeID( headLabel.GetID() )
    slicer.app.applicationLogic().PropagateVolumeSelection(0)

    #
    # got to the editor and do some drawing
    #
    self.delayDisplay("Setting up Editor and drawing")
    parameterNode = EditUtil.getParameterNode()
    lm = slicer.app.layoutManager()
    paintEffectOptions = EditorLib.PaintEffectOptions()
    paintEffectOptions.setMRMLDefaults()
    paintEffectOptions.__del__()

    self.delayDisplay('Paint radius is %s' % parameterNode.GetParameter('PaintEffect,radius'))
    sliceWidget = lm.sliceWidget('Red')
    size = min(sliceWidget.width,sliceWidget.height)
    step = int(size / 12)
    center = int(size / 2)
    parameterNode.SetParameter('PaintEffect,radius', '20')
    paintTool = EditorLib.PaintEffectTool(sliceWidget)
    self.delayDisplay('Paint radius is %s, tool radius is %d' % (parameterNode.GetParameter('PaintEffect,radius'),paintTool.radius))
    for label in range(1,5):
      EditUtil.setLabel(label)
      pos = center - 2*step + (step * label)
      self.delayDisplay('Painting %d, at  (%d,%d)' % (label,pos,pos),200)
      paintTool.paintAddPoint(pos,pos)
      paintTool.paintApply()
    paintTool.cleanup()
    paintTool = None

    #
    # now build:
    # create a model using the command line module
    # based on the current editor parameters
    # - make a new hierarchy node
    #

    self.delayDisplay( "Building..." )

    parameters = {}
    parameters["InputVolume"] = headLabel.GetID()
    # create models for all labels
    parameters["JointSmoothing"] = True
    parameters["StartLabel"] = -1
    parameters["EndLabel"] = -1
    outHierarchy = slicer.vtkMRMLModelHierarchyNode()
    outHierarchy.SetScene( slicer.mrmlScene )
    outHierarchy.SetName( "sceneImport2428Hierachy" )
    slicer.mrmlScene.AddNode( outHierarchy )
    parameters["ModelSceneFile"] = outHierarchy

    modelMaker = slicer.modules.modelmaker
    self.CLINode = None
    self.CLINode = slicer.cli.runSync(modelMaker, self.CLINode, parameters, delete_temporary_files=False)

    self.delayDisplay("Models built")

    success = self.verifyModels()

    success = success and (slicer.mrmlScene.GetNumberOfNodesByClass( "vtkMRMLModelNode" ) > 3)

    self.delayDisplay("Test finished")

    if success:
      self.delayDisplay("Ahh... test passed.")
    else:
      self.delayDisplay("!$!$!#!@#!@!@$%! Test Failed!!")

    self.assertTrue(success)
Example #9
0
  def makeModel(self,modelName='EditorModel',smooth=True):
    #
    # create a model using the command line module
    # based on the current editor parameters
    #

    volumeNode = EditUtil.getLabelVolume()
    if not volumeNode:
      return

    #
    # set up the model maker node
    #

    parameters = {}
    parameters['Name'] = modelName
    parameters["InputVolume"] = volumeNode.GetID()
    parameters['FilterType'] = "Sinc"

    # build only the currently selected model.
    parameters['Labels'] = EditUtil.getLabel()
    parameters["StartLabel"] = -1
    parameters["EndLabel"] = -1

    parameters['GenerateAll'] = False
    parameters["JointSmoothing"] = False
    parameters["SplitNormals"] = True
    parameters["PointNormals"] = True
    parameters["SkipUnNamed"] = True

    if smooth:
      parameters["Decimate"] = 0.25
      parameters["Smooth"] = 10
    else:
      parameters["Decimate"] = 0
      parameters["Smooth"] = 0

    #
    # output
    # - make a new hierarchy node if needed
    #
    numNodes = slicer.mrmlScene.GetNumberOfNodesByClass( "vtkMRMLModelHierarchyNode" )
    outHierarchy = None
    for n in xrange(numNodes):
      node = slicer.mrmlScene.GetNthNodeByClass( n, "vtkMRMLModelHierarchyNode" )
      if node.GetName() == "Editor Models":
        outHierarchy = node
        break

    if not outHierarchy:
      outHierarchy = slicer.vtkMRMLModelHierarchyNode()
      outHierarchy.SetScene( slicer.mrmlScene )
      outHierarchy.SetName( "Editor Models" )
      slicer.mrmlScene.AddNode( outHierarchy )

    parameters["ModelSceneFile"] = outHierarchy

    modelMaker = slicer.modules.modelmaker

    #
    # run the task (in the background)
    # - use the GUI to provide progress feedback
    # - use the GUI's Logic to invoke the task
    # - model will show up when the processing is finished
    #
    slicer.cli.run(modelMaker, None, parameters)

    slicer.util.showStatusMessage( "Model Making Started...", 2000 )
Example #10
0
    def test_sceneImport24281(self):
        """ Ideally you should have several levels of tests.  At the lowest level
    tests should exercise the functionality of the logic with different inputs
    (both valid and invalid).  At higher levels your tests should emulate the
    way the user would interact with your code and confirm that it still works
    the way you intended.
    One of the most important features of the tests is that it should alert other
    developers when their changes will have an impact on the behavior of your
    module.  For example, if a developer removes a feature that you depend on,
    your test should break so they know that the feature is needed.
    """

        self.delayDisplay("Starting the test")
        #
        # first, get some data
        #
        self.delayDisplay("Getting Data")
        import SampleData
        head = SampleData.downloadSample("MRHead")

        # Create segmentation
        segmentationNode = slicer.vtkMRMLSegmentationNode()
        slicer.mrmlScene.AddNode(segmentationNode)
        segmentationNode.CreateDefaultDisplayNodes()  # only needed for display
        segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(head)

        # Add a few segments
        segments = [["Segment A", [0, 65, 32], 25, [1.0, 0.0, 0.0]],
                    ["Segment B", [1, -14, 30], 30, [1.0, 1.0, 0.0]],
                    ["Segment C", [0, 28, -7], 15, [0.0, 1.0, 1.0]],
                    ["Segment D", [31, 33, 27], 25, [0.0, 0.0, 1.0]]]
        for [name, position, radius, color] in segments:
            seed = vtk.vtkSphereSource()
            seed.SetCenter(position)
            seed.SetRadius(radius)
            seed.Update()
            segmentationNode.AddSegmentFromClosedSurfaceRepresentation(
                seed.GetOutput(), name, color)

        # Export to labelmap volume
        headLabel = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLLabelMapVolumeNode')
        slicer.modules.segmentations.logic(
        ).ExportVisibleSegmentsToLabelmapNode(segmentationNode, headLabel,
                                              head)

        selectionNode = slicer.app.applicationLogic().GetSelectionNode()
        selectionNode.SetActiveVolumeID(head.GetID())
        selectionNode.SetActiveLabelVolumeID(headLabel.GetID())
        slicer.app.applicationLogic().PropagateVolumeSelection(0)

        #
        # now build:
        # create a model using the command line module
        # based on the current editor parameters
        # - make a new hierarchy node
        #

        self.delayDisplay("Building...")

        parameters = {}
        parameters["InputVolume"] = headLabel.GetID()
        # create models for all labels
        parameters["JointSmoothing"] = True
        parameters["StartLabel"] = -1
        parameters["EndLabel"] = -1
        outHierarchy = slicer.vtkMRMLModelHierarchyNode()
        outHierarchy.SetScene(slicer.mrmlScene)
        outHierarchy.SetName("sceneImport2428Hierachy")
        slicer.mrmlScene.AddNode(outHierarchy)
        parameters["ModelSceneFile"] = outHierarchy

        modelMaker = slicer.modules.modelmaker
        self.CLINode = None
        self.CLINode = slicer.cli.runSync(modelMaker,
                                          self.CLINode,
                                          parameters,
                                          delete_temporary_files=False)

        self.delayDisplay("Models built")

        success = self.verifyModels()

        success = success and (
            slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLModelNode") > 3)

        self.delayDisplay("Test finished")

        if success:
            self.delayDisplay("Ahh... test passed.")
        else:
            self.delayDisplay("!$!$!#!@#!@!@$%! Test Failed!!")

        self.assertTrue(success)
Example #11
0
    def TestSection_03_qMRMLSegmentationGeometryWidget(self):
        logging.info('Test section 2: qMRMLSegmentationGeometryWidget')

        import vtkSegmentationCore
        binaryLabelmapReprName = vtkSegmentationCore.vtkSegmentationConverter.GetBinaryLabelmapRepresentationName(
        )
        closedSurfaceReprName = vtkSegmentationCore.vtkSegmentationConverter.GetClosedSurfaceRepresentationName(
        )

        # Use MRHead and Tinypatient for testing
        import SampleData
        mrVolumeNode = SampleData.downloadSample("MRHead")
        [tinyVolumeNode,
         tinySegmentationNode] = SampleData.downloadSamples('TinyPatient')

        # Convert MRHead to oriented image data
        import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
        mrOrientedImageData = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.CreateOrientedImageDataFromVolumeNode(
            mrVolumeNode)
        mrOrientedImageData.UnRegister(None)

        # Create segmentation node with binary labelmap master and one segment with MRHead geometry
        segmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLSegmentationNode')
        segmentationNode.GetSegmentation().SetMasterRepresentationName(
            binaryLabelmapReprName)
        geometryStr = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(
            mrOrientedImageData)
        segmentationNode.GetSegmentation().SetConversionParameter(
            vtkSegmentationCore.vtkSegmentationConverter.
            GetReferenceImageGeometryParameterName(), geometryStr)

        threshold = vtk.vtkImageThreshold()
        threshold.SetInputData(mrOrientedImageData)
        threshold.ThresholdByUpper(16.0)
        threshold.SetInValue(1)
        threshold.SetOutValue(0)
        threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR)
        threshold.Update()
        segmentOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()
        segmentOrientedImageData.DeepCopy(threshold.GetOutput())
        mrImageToWorldMatrix = vtk.vtkMatrix4x4()
        mrOrientedImageData.GetImageToWorldMatrix(mrImageToWorldMatrix)
        segmentOrientedImageData.SetImageToWorldMatrix(mrImageToWorldMatrix)
        segment = vtkSegmentationCore.vtkSegment()
        segment.SetName('Brain')
        segment.SetColor(0.0, 0.0, 1.0)
        segment.AddRepresentation(binaryLabelmapReprName,
                                  segmentOrientedImageData)
        segmentationNode.GetSegmentation().AddSegment(segment)

        # Create geometry widget
        geometryWidget = slicer.qMRMLSegmentationGeometryWidget()
        geometryWidget.setSegmentationNode(segmentationNode)
        geometryWidget.editEnabled = True
        geometryImageData = vtkSegmentationCore.vtkOrientedImageData(
        )  # To contain the output later

        # Volume source with no transforms
        geometryWidget.setSourceNode(tinyVolumeNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

        # Transformed volume source
        translationTransformMatrix = vtk.vtkMatrix4x4()
        translationTransformMatrix.SetElement(0, 3, 24.5)
        translationTransformMatrix.SetElement(1, 3, 24.5)
        translationTransformMatrix.SetElement(2, 3, 11.5)
        translationTransformNode = slicer.vtkMRMLLinearTransformNode()
        translationTransformNode.SetName('TestTranslation')
        slicer.mrmlScene.AddNode(translationTransformNode)
        translationTransformNode.SetMatrixTransformToParent(
            translationTransformMatrix)

        tinyVolumeNode.SetAndObserveTransformNodeID(
            translationTransformNode.GetID())
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (224.3439, 223.7890, -135.25),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 94)

        # Volume source with isotropic spacing
        tinyVolumeNode.SetAndObserveTransformNodeID(None)
        geometryWidget.setIsotropicSpacing(True)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (23, 23, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 414)

        # Volume source with oversampling
        geometryWidget.setIsotropicSpacing(False)
        geometryWidget.setOversamplingFactor(2.0)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (24.5, 24.5, 11.5),
                (261.0939, 260.5390, -129.5),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 751)
        slicer.util.delayDisplay('Volume source cases - OK')

        # Segmentation source with binary labelmap master
        geometryWidget.setOversamplingFactor(1.0)
        geometryWidget.setSourceNode(tinySegmentationNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

        # Segmentation source with closed surface master
        tinySegmentationNode.GetSegmentation().SetConversionParameter(
            'Smoothing factor', '0.0')
        self.assertTrue(
            tinySegmentationNode.GetSegmentation().CreateRepresentation(
                closedSurfaceReprName))
        tinySegmentationNode.GetSegmentation().SetMasterRepresentationName(
            closedSurfaceReprName)
        tinySegmentationNode.Modified(
        )  # Trigger re-calculation of geometry (only generic Modified event is observed)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-167.156, -217.711, -135.75),
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223846)
        slicer.util.delayDisplay('Segmentation source cases - OK')

        # Model source with no transform
        outputModelHierarchy = slicer.vtkMRMLModelHierarchyNode()
        slicer.mrmlScene.AddNode(outputModelHierarchy)
        success = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.ExportVisibleSegmentsToModelHierarchy(
            tinySegmentationNode, outputModelHierarchy)
        self.assertTrue(success)
        modelNode = slicer.util.getNode('Body_Contour')
        geometryWidget.setSourceNode(modelNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-167.156, -217.711, -135.75),
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223846)

        # Transformed model source
        rotationTransform = vtk.vtkTransform()
        rotationTransform.RotateX(45)
        rotationTransformMatrix = vtk.vtkMatrix4x4()
        rotationTransform.GetMatrix(rotationTransformMatrix)
        rotationTransformNode = slicer.vtkMRMLLinearTransformNode()
        rotationTransformNode.SetName('TestRotation')
        slicer.mrmlScene.AddNode(rotationTransformNode)
        rotationTransformNode.SetMatrixTransformToParent(
            rotationTransformMatrix)

        modelNode.SetAndObserveTransformNodeID(rotationTransformNode.GetID())
        modelNode.Modified()
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-167.156, -58.6623, -249.228),
                [[0.0, 0.0, 1.0], [-0.7071, -0.7071, 0.0],
                 [0.7071, -0.7071, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5221241)

        # ROI source
        roiNode = slicer.vtkMRMLAnnotationROINode()
        roiNode.SetName('SourceROI')
        slicer.mrmlScene.AddNode(roiNode)
        roiNode.UnRegister(None)
        xyz = [0] * 3
        center = [0] * 3
        slicer.vtkMRMLSliceLogic.GetVolumeRASBox(tinyVolumeNode, xyz, center)
        radius = [x / 2.0 for x in xyz]
        roiNode.SetXYZ(center)
        roiNode.SetRadiusXYZ(radius)
        geometryWidget.setSourceNode(roiNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-216.156, -217.711, -135.75),
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223846)
        slicer.util.delayDisplay('Model and ROI source cases - OK')

        slicer.util.delayDisplay('Segmentation geometry widget test passed')
Example #12
0
    def makeModel(self, modelName='EditorModel', smooth=True):
        #
        # create a model using the command line module
        # based on the current editor parameters
        #

        volumeNode = EditUtil.getLabelVolume()
        if not volumeNode:
            return

        #
        # set up the model maker node
        #

        parameters = {}
        parameters['Name'] = modelName
        parameters["InputVolume"] = volumeNode.GetID()
        parameters['FilterType'] = "Sinc"

        # build only the currently selected model.
        parameters['Labels'] = EditUtil.getLabel()
        parameters["StartLabel"] = -1
        parameters["EndLabel"] = -1

        parameters['GenerateAll'] = False
        parameters["JointSmoothing"] = False
        parameters["SplitNormals"] = True
        parameters["PointNormals"] = True
        parameters["SkipUnNamed"] = True

        if smooth:
            parameters["Decimate"] = 0.25
            parameters["Smooth"] = 10
        else:
            parameters["Decimate"] = 0
            parameters["Smooth"] = 0

        #
        # output
        # - make a new hierarchy node if needed
        #
        numNodes = slicer.mrmlScene.GetNumberOfNodesByClass(
            "vtkMRMLModelHierarchyNode")
        outHierarchy = None
        for n in xrange(numNodes):
            node = slicer.mrmlScene.GetNthNodeByClass(
                n, "vtkMRMLModelHierarchyNode")
            if node.GetName() == "Editor Models":
                outHierarchy = node
                break

        if not outHierarchy:
            outHierarchy = slicer.vtkMRMLModelHierarchyNode()
            outHierarchy.SetScene(slicer.mrmlScene)
            outHierarchy.SetName("Editor Models")
            slicer.mrmlScene.AddNode(outHierarchy)

        parameters["ModelSceneFile"] = outHierarchy

        modelMaker = slicer.modules.modelmaker

        #
        # run the task (in the background)
        # - use the GUI to provide progress feedback
        # - use the GUI's Logic to invoke the task
        # - model will show up when the processing is finished
        #
        slicer.cli.run(modelMaker, None, parameters)

        slicer.util.showStatusMessage("Model Making Started...", 2000)