예제 #1
0
    def test_CompareVolumes2(self):
        """
    Test modes with view watcher class.
    """

        m = slicer.util.mainWindow()
        m.moduleSelector().selectModule('CompareVolumes')

        self.delayDisplay("Starting View Watcher test")

        watcher = ViewWatcher()

        # first with two volumes
        from SampleData import SampleDataLogic
        head = SampleDataLogic().downloadMRHead()
        brain = SampleDataLogic().downloadDTIBrain()
        logic = CompareVolumesLogic()
        logic.viewerPerVolume()
        self.delayDisplay('Should be one row with two columns')
        logic.viewerPerVolume(volumeNodes=(brain, head),
                              viewNames=('brain', 'head'))
        self.delayDisplay('Should be two columns, with names')

        watcher.tearDown()

        self.delayDisplay('Test passed!')
예제 #2
0
  def test_SubjectHierarchyReference(self):
    self.delayDisplay('Test that output node moved to referenced node location in subject hierarchy')

    self.delayDisplay('Load input volume')
    from SampleData import SampleDataLogic
    inputVolume = SampleDataLogic().downloadMRHead()

    self.delayDisplay('Create subject hierarchy of input volume')
    shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
    self.patientItemID = shNode.CreateSubjectItem(shNode.GetSceneItemID(), "John Doe")
    self.studyItemID = shNode.CreateStudyItem(self.patientItemID, "Some study")
    self.folderItemID = shNode.CreateFolderItem(self.studyItemID, "Some group")
    shNode.SetItemParent(shNode.GetItemByDataNode(inputVolume), self.folderItemID)

    outputVolume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode")
    # New node is expected to be created in the subject hierarchy root
    self.assertEqual(shNode.GetItemParent(shNode.GetItemByDataNode(outputVolume)), shNode.GetSceneItemID())

    self.delayDisplay('Run CLI module')
    cliParams = {'InputVolume': inputVolume.GetID(), 'OutputVolume': outputVolume.GetID(), 'ThresholdValue' : 100, 'ThresholdType' : 'Above'}
    cliNode = slicer.cli.run(slicer.modules.thresholdscalarvolume, None, cliParams, wait_for_completion=True)

    # After CLI execution is completed, output volume must be in the same folder as the referenced node
    self.assertEqual(shNode.GetItemParent(shNode.GetItemByDataNode(outputVolume)), shNode.GetItemParent(shNode.GetItemByDataNode(inputVolume)))

    # After pending events are processed, the output volume must be in the same subject hierarchy folder
    slicer.app.processEvents()
    self.assertEqual(shNode.GetItemParent(shNode.GetItemByDataNode(outputVolume)), shNode.GetItemParent(shNode.GetItemByDataNode(inputVolume)))
예제 #3
0
    def test_CompareVolumes1(self):
        """ Test modes with 3 volumes.
    """

        m = slicer.util.mainWindow()
        m.moduleSelector().selectModule('CompareVolumes')

        self.delayDisplay("Starting the test")

        # first with two volumes
        from SampleData import SampleDataLogic
        head = SampleDataLogic().downloadMRHead()
        brain = SampleDataLogic().downloadDTIBrain()
        logic = CompareVolumesLogic()
        logic.viewerPerVolume()
        self.delayDisplay('Should be one row with two columns')
        logic.viewerPerVolume(volumeNodes=(brain, head),
                              viewNames=('brain', 'head'))
        self.delayDisplay('Should be two columns, with names')

        # now with three volumes
        otherBrain = SampleDataLogic().downloadMRBrainTumor1()
        logic.viewerPerVolume()
        logic.viewerPerVolume(volumeNodes=(brain, head, otherBrain),
                              viewNames=('brain', 'head', 'otherBrain'))
        self.delayDisplay('Should be one row with three columns')

        logic.viewerPerVolume(volumeNodes=(brain, head, otherBrain),
                              viewNames=('brain', 'head', 'otherBrain'),
                              orientation='Sagittal')
        self.delayDisplay('same thing in sagittal')

        logic.viewerPerVolume(volumeNodes=(brain, head, otherBrain),
                              viewNames=('brain', 'head', 'otherBrain'),
                              orientation='Coronal')
        self.delayDisplay('same thing in coronal')

        anotherHead = SampleDataLogic().downloadMRHead()
        logic.viewerPerVolume(volumeNodes=(brain, head, otherBrain,
                                           anotherHead),
                              viewNames=('brain', 'head', 'otherBrain',
                                         'anotherHead'),
                              orientation='Coronal')
        self.delayDisplay('now four volumes, with three columns and two rows')

        logic.viewersPerVolume(volumeNodes=(brain, head))
        self.delayDisplay('now axi/sag/cor for two volumes')

        logic.viewersPerVolume(volumeNodes=(brain, head, otherBrain))
        self.delayDisplay('now axi/sag/cor for three volumes')

        self.delayDisplay('Test passed!')
예제 #4
0
    def test_CompareVolumes3(self):
        """
    Test LayerReveal

    From the python console:
slicer.util.mainWindow().moduleSelector().selectModule("CompareVolumes"); slicer.modules.CompareVolumesWidget.onReloadAndTest(scenario="LayerReveal"); reveal = LayerReveal()
    """

        self.delayDisplay("Starting LayerReveal test")

        # first with two volumes
        from SampleData import SampleDataLogic
        head = SampleDataLogic().downloadMRHead()
        dti = SampleDataLogic().downloadDTIBrain()
        tumor = SampleDataLogic().downloadMRBrainTumor1()
        logic = CompareVolumesLogic()
        logic.viewerPerVolume()
        self.delayDisplay('Should be one row with two columns')
        logic.viewerPerVolume(volumeNodes=(dti, tumor, head),
                              background=dti,
                              viewNames=('dti', 'tumor', 'head'))
        self.delayDisplay('Should be three columns, with dti in foreground')

        # the name of the view was givein the the call to viewerPerVolume above.
        # here we ask the layoutManager to give us the corresponding sliceWidget
        # from which we can get the interactorStyle so we can simulate events
        layoutManager = slicer.app.layoutManager()
        sliceWidget = layoutManager.sliceWidget('head')
        style = sliceWidget.sliceView().interactorStyle().GetInteractor()

        for scale in (False, True):
            for size in (100, 400):
                # create a reveal cursor to test
                reveal = LayerReveal(width=size, height=size, scale=scale)
                reveal.processEvent(style, "EnterEvent")
                steps = 300
                for step in range(0, steps):
                    t = step // float(steps)
                    px = int(t * sliceWidget.width)
                    py = int(t * sliceWidget.height)
                    style.SetEventPosition(px, py)
                    reveal.processEvent(style, "MouseMoveEvent")
                reveal.processEvent(style, "LeaveEvent")
                reveal.cleanup()
                self.delayDisplay(f'Scale {scale}, size {size}')

        self.delayDisplay(
            'Should have just seen reveal cursor move through head view')

        self.delayDisplay('Test passed!')
    def setUp(self):
        from SampleData import SampleDataLogic
        dtiSource = SampleDataLogic().sourceForSampleName('DTIBrain')
        self.file_name = SampleDataLogic().downloadSourceIntoCache(dtiSource)[0]

        self.ritk = vtkITK.vtkITKArchetypeDiffusionTensorImageReaderFile()
        self.ritk.SetUseOrientationFromFile(True)
        self.ritk.SetUseNativeOriginOn()
        self.ritk.SetOutputScalarTypeToNative()
        self.ritk.SetDesiredCoordinateOrientationToNative()
        self.ritk.SetArchetype(self.file_name)
        self.ritk.Update()

        self.rnrrd = vtkTeem.vtkTeemNRRDReader()
        self.rnrrd.SetFileName(self.file_name)
        self.rnrrd.Update()
예제 #6
0
    def test_HelloSharpen1(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")

        self.delayDisplay('Load input volume')
        from SampleData import SampleDataLogic
        inputVolume = SampleDataLogic().downloadMRHead()

        self.delayDisplay('Create output volume')
        outputVolume = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLScalarVolumeNode")

        self.delayDisplay('Compute results')
        logic = HelloSharpenLogic()
        success = logic.run(inputVolume, outputVolume)

        self.delayDisplay('Display output')
        slicer.util.setSliceViewerLayers(outputVolume)

        self.delayDisplay('Verify results')
        self.assertTrue(success)
        self.assertIsNotNone(outputVolume.GetImageData())

        self.delayDisplay('Test passed!')
예제 #7
0
  def test_BRAINSFitRigidRegistrationCrashIssue4139(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")

    logic = BRAINSFitRigidRegistrationCrashIssue4139Logic()

    import SampleData
    from SampleData import SampleDataLogic
    sampleDatalogic = SampleDataLogic()

    fixed = sampleDatalogic.downloadMRBrainTumor1()
    self.assertIsNotNone(logic.hasImageData(fixed))

    moving = sampleDatalogic.downloadMRBrainTumor2()
    self.assertIsNotNone(logic.hasImageData(moving))

    self.delayDisplay('Finished with download and loading')

    outputTransform = slicer.vtkMRMLLinearTransformNode()
    slicer.mrmlScene.AddNode(outputTransform)

    outputVolume = slicer.vtkMRMLScalarVolumeNode()
    slicer.mrmlScene.AddNode(outputVolume)

    parameters = {
      'fixedVolume' : fixed,
      'movingVolume' : moving,
      'linearTransform' : outputTransform,
      'outputVolume' : outputVolume,
      'useRigid' : True
    }
    cmdLineNode = slicer.cli.runSync(slicer.modules.brainsfit, parameters=parameters)
    self.assertIsNotNone(cmdLineNode)

    # If test reach this point without crashing it is a success

    self.delayDisplay('Test passed!')
    def setUp(self):
        from SampleData import SampleDataLogic
        brainSource = SampleDataLogic().sourceForSampleName('MRHead')
        self.file_name = SampleDataLogic().downloadSourceIntoCache(
            brainSource)[0]

        self.ritk = vtkITK.vtkITKArchetypeImageSeriesScalarReader()
        self.ritk.SetUseOrientationFromFile(True)
        self.ritk.SetUseNativeOriginOn()
        self.ritk.SetOutputScalarTypeToNative()
        self.ritk.SetDesiredCoordinateOrientationToNative()
        self.ritk.SetArchetype(self.file_name)
        self.ritk.Update()

        self.rnrrd = teem.vtkTeemNRRDReader()
        self.rnrrd.SetFileName(self.file_name)
        self.rnrrd.Update()

        self.assertTrue(
            compare_vtk_matrix(self.ritk.GetRasToIjkMatrix(),
                               self.rnrrd.GetRasToIjkMatrix()))
    def setUpClass(cls):
        slicer.mrmlScene.Clear(0)
        cls.tempDir = slicer.app.temporaryPath
        cls.watchedDirectory = os.path.join(cls.tempDir,
                                            "SlicerProstateTesting",
                                            cls.__class__.__name__)
        cls.createDirectory(cls.watchedDirectory)
        cls.watcher = DirectoryWatcher(cls.watchedDirectory)
        cls.sampleDataLogic = SampleDataLogic()

        cls.startedEventEmitted = False
        cls.stoppedEventEmitted = False
        cls.fileCountChangedEmitted = False
    def test_VolumeRenderThreeDOnlyLayout(self):
        """
        Test that the following workflow does not segfault:
        - Set 3D-only layout, reinitialize slice widgets
        - Load volume
        - Enter the volume rendering module
        """
        # Set 3D-only layout
        layoutManager = slicer.app.layoutManager()
        layoutManager.setLayout(
            slicer.vtkMRMLLayoutNode.SlicerLayoutOneUp3DView)

        # Reinitialize MRML scene to force re-creating slice widgets
        mrmlScene = layoutManager.mrmlScene()
        layoutManager.setMRMLScene(None)
        layoutManager.setMRMLScene(mrmlScene)

        # Load MRHead volume
        from SampleData import SampleDataLogic
        SampleDataLogic().downloadMRHead()

        # Enter the volume rendering module
        slicer.util.mainWindow().moduleSelector().selectModule(
            'VolumeRendering')
예제 #11
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        self.tutorials = {
            "ShapeAnalysisModule":
            "https://bit.ly/2Fyn97v",  # SPHARM-PDM Generator
            "GroupWiseRegistrationModule": "https://bit.ly/2WsFiun",
            "RegressionComputation": "https://bit.ly/2uVYche",
            "ShapeVariationAnalyzer":
            "https://bit.ly/2HYbHVA",  # Population Analysis
            "SRep": "https://bit.ly/3sTEG3H",
            "SRepCreator": "https://bit.ly/3sTEG3H",
            "SRepRefinement": "https://bit.ly/3sTEG3H",
        }

        # The anchor associated with each link corresponds to the name of the module to select.
        # For example, after the user click on the link associated with `href="#DataImporter"`,
        # the "DataImporter" module is selected.
        text = """
<br>
<u>Workflow quick-reference:</u><br>
<br>
The drop-down Modules are ordered to follow the basic workflow for choosing and using data.  As a quick reference, the basic steps involve:<br>
<br>
&nbsp; 1. Use the <a href="#DataImporter"><b>Data importer</b></a> module to load your segmentations from FreeSurf, FSL, Autoseg, or a bunch of vtp's<br><br>
&nbsp; 2. Use <a href="#ShapePopulationViewer"><b>Shape Population Viewer</b></a> to do a quality check on the imported data<br><br>
&nbsp; 3. Use <a href="#ShapeAnalysisModule"><b>SPHARM-PDM Generator</b></a> to do spherical harmonics based analysis<br><br>
&nbsp; 4. Use the <a href="#GroupWiseRegistrationModule"><b>Study-specific Shape Analysis</b></a> module.<br><br>
&nbsp; 5. Use the <a href="#SkeletalRepresentationVisualizer"><b>S-Rep Shape Analysis</b></a> module to do shape analysis via skeletal representations.<br><br>
&nbsp; 6. Use the <a href="#ShapeVariationAnalyzer"><b>Shape Evaluator</b></a> module to compute a mean shape and see how the population varies.<br><br>
&nbsp; 7. Use <a href="#RegressionComputation"><b>Shape Regressions</b></a> module to do regression based analysis.<br><br>
&nbsp; 8. Use the <a href="#MFSDA"><b>Shape Statistics</b></a> module.<br><br>
"""

        # TEXTEDIT
        self.HomeTextSection = qt.QTextBrowser()
        self.HomeTextSection.setHtml(text)
        self.HomeTextSection.setMinimumHeight(400)
        self.HomeTextSection.connect('anchorClicked(QUrl)',
                                     self.onAnchorClicked)
        self.layout.addWidget(self.HomeTextSection)

        # SPACER
        self.layout.addStretch()

        # SAMPLE DATA REGISTRATION
        for json_file in [
                'DataImporterInputData.json', 'MFSDAInputData.json',
                'ShapeRegressionInputData.json', 'SPHARM-PDMTestData.json',
                'SPHARM-PDMFiducials.json', 'SRepCreatorData.json',
                'SVAInputData.json'
        ]:
            with open(
                    self.resourcePath('SampleDataDescription/%s' % json_file),
                    'r') as json_data:
                source_data = json.load(json_data)
                if 'iconPath' in source_data:
                    iconPath = self.resourcePath(source_data['iconPath'])
                else:
                    iconPath = None

                SampleDataLogic.registerCustomSampleDataSource(
                    category=source_data['category'],
                    sampleName=source_data['sampleName'],
                    uris=source_data['uris'],
                    checksums=source_data.get('checksums', None),
                    fileNames=source_data['fileNames'],
                    nodeNames=None,
                    thumbnailFileName=iconPath,
                    loadFileType=None,
                    customDownloader=self.downloadSampleDataInFolder,
                )

        # HIDE SAMPLE DATA 'BUILTIN' CATEGORY
        slicer.modules.sampledata.widgetRepresentation().self(
        ).setCategoryVisible('BuiltIn', False)

        self.sampleDataModuleTab = None
        self.sampleDataTabTextEdit = None

        self.moduleNameToSampleDataCategory = {
            "DataImporter": "Data Importer",
            "MFSDA": "Covariate Significance Testing",
            "ShapeAnalysisModule": "SPHARM-PDM",
            "RegressionComputation": "Shape Regression",
            "ShapeVariationAnalyzer": "Population Analysis",
            "SRepCreator": "Skeletal Representation Creator"
        }

        self.sampleDataModuleTab = self.addSampleDataTab()
        self.updateSampleDataTab("Home")
        moduleMenu = slicer.util.mainWindow().moduleSelector().modulesMenu()
        moduleMenu.connect("currentModuleChanged(QString)",
                           self.updateSampleDataTab)
예제 #12
0
    def downloadSampleDataInFolder(source):

        if slicer.util.selectedModule() == "SampleData":
            sampleDataLogic = slicer.modules.sampledata.widgetRepresentation(
            ).self().logic
        else:
            sampleDataLogic = SampleDataLogic(
                logMessage=slicer.modules.HomeWidget.logSampleDataTabMessage)

        # Retrieve directory
        category = sampleDataLogic.categoryForSource(source)
        savedDirectory = slicer.app.userSettings().value(
            "SampleData/Last%sDownloadDirectory" % category,
            qt.QStandardPaths.writableLocation(
                qt.QStandardPaths.DocumentsLocation))

        destFolderPath = str(
            qt.QFileDialog.getExistingDirectory(slicer.util.mainWindow(),
                                                'Destination Folder',
                                                savedDirectory))
        if not os.path.isdir(destFolderPath):
            return

        print('Selected data folder: %s' % destFolderPath)

        for uri, fileName, checksum in zip(source.uris, source.fileNames,
                                           source.checksums):
            sampleDataLogic.downloadFile(uri,
                                         destFolderPath,
                                         fileName,
                                         checksum=checksum)

        # Save directory
        slicer.app.userSettings().setValue(
            "SampleData/Last%sDownloadDirectory" % category, destFolderPath)

        filepath = destFolderPath + "/setup.py"
        if (os.path.exists(filepath)):
            spec = importlib.util.spec_from_file_location("setup", filepath)
            setup = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(setup)
            setup.setup()

        # Pre-fill input/output fields in module
        currModule = slicer.util.selectedModule()
        outPath = os.path.join(destFolderPath, 'out')
        if not os.path.exists(outPath):
            os.mkdir(outPath)

        if currModule == slicer.moduleNames.DataImporter:
            slicer.modules.DataImporterWidget.FolderDirectoryButton.directory = destFolderPath
            slicer.modules.DataImporterWidget.inputShapeAnalysisPath = outPath
        elif currModule == slicer.moduleNames.ShapeAnalysisModule:
            slicer.modules.ShapeAnalysisModuleWidget.GroupProjectInputDirectory.directory = destFolderPath
            slicer.modules.ShapeAnalysisModuleWidget.RigidAlignmentFiducialsDirectory.directory = destFolderPath
            slicer.modules.ShapeAnalysisModuleWidget.GroupProjectOutputDirectory.directory = outPath
            if glob.glob(os.path.join(destFolderPath, '*_fid.fcsv')):
                slicer.modules.ShapeAnalysisModuleWidget.RigidAlignmentEnabled.checked = True
                slicer.modules.ShapeAnalysisModuleWidget.CollapsibleButton_RigidAlignment.checked = True
        elif currModule == slicer.moduleNames.ShapeVariationAnalyzer:
            slicer.modules.ShapeVariationAnalyzerWidget.collapsibleButton_PCA.collapsed = False
            slicer.modules.ShapeVariationAnalyzerWidget.pathLineEdit_CSVFilePCA.currentPath = os.path.join(
                destFolderPath, 'inputFiles.csv')
            slicer.modules.ShapeVariationAnalyzerWidget.DirectoryButton_PCASingleExport.directory = outPath
        elif currModule == slicer.moduleNames.RegressionComputation:
            slicer.modules.RegressionComputationWidget.shapeInputDirectory.directory = destFolderPath
            slicer.modules.RegressionComputationWidget.outputDirectory.directory = outPath
        elif currModule == slicer.moduleNames.MFSDA:
            slicer.modules.MFSDAWidget.lineEdit_csv.currentPath = os.path.join(
                destFolderPath, 'inputFiles.csv')
            slicer.modules.MFSDAWidget.lineEdit_pshape.currentPath = os.path.join(
                destFolderPath, 'g01', 'bump00.vtk')
            slicer.modules.MFSDAWidget.lineEdit_output.directory = os.path.join(
                destFolderPath, 'out')