def tearDown(self):
   """ Close temporary DICOM database and remove temporary data
   """ 
   import shutil
   if self.originalDicomDatabase:
     DICOMUtils.closeTemporaryDatabase(self.originalDicomDatabase, True)
     shutil.rmtree(self.tempDicomDatabase) # closeTemporaryDatabase cleanup doesn't work. We need to do it manually
     self.originalDicomDatabase = None      
Example #2
0
class JRC2013VisTest(unittest.TestCase):
    """
  This is the test case for your scripted module.
  """
    def delayDisplay(self, message, msec=1000):
        """This utility method displays a small dialog and waits.
    This does two things: 1) it lets the event loop catch up
    to the state of the test so that rendering and widget updates
    have all taken place before the test continues and 2) it
    shows the user/developer/tester the state of the test
    so that we'll know when it breaks.
    """
        print(message)
        self.info = qt.QDialog()
        self.infoLayout = qt.QVBoxLayout()
        self.info.setLayout(self.infoLayout)
        self.label = qt.QLabel(message, self.info)
        self.infoLayout.addWidget(self.label)
        qt.QTimer.singleShot(msec, self.info.close)
        self.info.exec_()

    def setUp(self):
        """ Do whatever is needed to reset the state - typically a scene clear will be enough.
    """
        self.delayDisplay("Closing the scene")
        layoutManager = slicer.app.layoutManager()
        layoutManager.setLayout(
            slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
        slicer.mrmlScene.Clear(0)

    def clickAndDrag(self,
                     widget,
                     button='Left',
                     start=(10, 10),
                     end=(10, 40),
                     steps=20,
                     modifiers=[]):
        """Send synthetic mouse events to the specified widget (qMRMLSliceWidget or qMRMLThreeDView)
    button : "Left", "Middle", "Right", or "None"
    start, end : window coordinates for action
    steps : number of steps to move in
    modifiers : list containing zero or more of "Shift" or "Control"
    """
        style = widget.interactorStyle()
        interator = style.GetInteractor()
        if button == 'Left':
            down = style.OnLeftButtonDown
            up = style.OnLeftButtonUp
        elif button == 'Right':
            down = style.OnRightButtonDown
            up = style.OnRightButtonUp
        elif button == 'Middle':
            down = style.OnMiddleButtonDown
            up = style.OnMiddleButtonUp
        elif button == 'None' or not button:
            down = lambda: None
            up = lambda: None
        else:
            raise Exception("Bad button - should be Left or Right, not %s" %
                            button)
        if 'Shift' in modifiers:
            interator.SetShiftKey(1)
        if 'Control' in modifiers:
            interator.SetControlKey(1)
        interator.SetEventPosition(*start)
        down()
        for step in xrange(steps):
            frac = float(step) / steps
            x = int(start[0] + frac * (end[0] - start[0]))
            y = int(start[1] + frac * (end[1] - start[1]))
            interator.SetEventPosition(x, y)
            style.OnMouseMove()
        up()
        interator.SetShiftKey(0)
        interator.SetControlKey(0)

    def runTest(self):
        """Run as few or as many tests as needed here.
    """
        self.setUp()
        self.test_Part1DICOM()
        self.setUp()
        self.test_Part2Head()
        self.setUp()
        self.test_Part3Liver()
        self.setUp()
        self.test_Part4Lung()

    def test_Part1DICOM(self):
        """ Test the DICOM part of the test using the head atlas
    """

        import os
        self.delayDisplay("Starting the DICOM test")
        #
        # first, get the data - a zip file of dicom data
        #
        import urllib
        downloads = (('http://slicer.kitware.com/midas3/download?items=18822',
                      'Dcmtk-db.zip'), )

        self.delayDisplay("Downloading")
        for url, name in downloads:
            filePath = slicer.app.temporaryPath + '/' + name
            if not os.path.exists(filePath) or os.stat(filePath).st_size == 0:
                self.delayDisplay('Requesting download %s from %s...\n' %
                                  (name, url))
                urllib.urlretrieve(url, filePath)
        self.delayDisplay('Finished with download\n')

        self.delayDisplay("Unzipping")
        dicomFilesDirectory = slicer.app.temporaryPath + '/dicomFiles'
        qt.QDir().mkpath(dicomFilesDirectory)
        slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory)

        try:
            self.delayDisplay("Switching to temp database directory")
            originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase(
                'tempDICOMDatbase')

            self.delayDisplay('Start Local DICOM Q/R SCP')
            import subprocess
            import os
            configFilePath = dicomFilesDirectory + '/Dcmtk-db/dcmqrscp.cfg'
            processCurrentPath = dicomFilesDirectory + '/Dcmtk-db/'

            dcmqrscpExeOptions = (
                '/bin',
                '/../CTK-build/CMakeExternals/Install/bin',
                '/../DCMTK-install/bin',
                '/../DCMTK-build/bin',
            )

            dcmqrscpExePath = None
            dcmqrscpExeName = '/dcmqrscp'
            if slicer.app.os == 'win':
                dcmqrscpExeName = dcmqrscpExeName + '.exe'
            for path in dcmqrscpExeOptions:
                testPath = slicer.app.slicerHome + path + dcmqrscpExeName
                if os.path.exists(testPath):
                    dcmqrscpExePath = testPath
                    break
            if not dcmqrscpExePath:
                raise (UserWarning("Could not find dcmqrscp executable"))

            args = (dcmqrscpExePath, '-c', configFilePath)
            popen = subprocess.Popen(args,
                                     stdout=subprocess.PIPE,
                                     cwd=processCurrentPath)

            self.delayDisplay('Retrieve DICOM')
            mainWindow = slicer.util.mainWindow()
            mainWindow.moduleSelector().selectModule('DICOM')
            dicomRetrieve = ctk.ctkDICOMRetrieve()
            dicomRetrieve.setKeepAssociationOpen(True)
            dicomRetrieve.setDatabase(slicer.dicomDatabase)
            dicomRetrieve.setCallingAETitle('SlicerAE')
            dicomRetrieve.setCalledAETitle('DCMTK')
            dicomRetrieve.setPort(12345)
            dicomRetrieve.setHost('localhost')
            dicomRetrieve.getStudy(
                '1.2.124.113932.1.170.223.162.178.20050502.160340.12640015')
            popen.kill()
            dicomWidget.detailsPopup.open()
            # click on the first row of the tree
            index = dicomWidget.tree.indexAt(qt.QPoint(0, 0))
            dicomWidget.onTreeClicked(index)

            self.delayDisplay('Loading Selection')
            dicomWidget.detailsPopup.loadCheckedLoadables()

            self.delayDisplay('Change Level')
            layoutManager = slicer.app.layoutManager()
            redWidget = layoutManager.sliceWidget('Red')
            self.clickAndDrag(redWidget, start=(10, 10), end=(10, 40))

            self.delayDisplay('Change Window')
            self.clickAndDrag(redWidget, start=(10, 10), end=(40, 10))

            self.delayDisplay('Change Layout')
            layoutManager = slicer.app.layoutManager()
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)

            self.delayDisplay('Zoom')
            self.clickAndDrag(redWidget,
                              button='Right',
                              start=(10, 10),
                              end=(10, 40))

            self.delayDisplay('Pan')
            self.clickAndDrag(redWidget,
                              button='Middle',
                              start=(10, 10),
                              end=(40, 40))

            self.delayDisplay('Center')
            redWidget.sliceController().fitSliceToBackground()

            self.delayDisplay('Lightbox')
            redWidget.sliceController().setLightboxTo6x6()

            self.delayDisplay('Conventional Layout')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)

            self.delayDisplay('No Lightbox')
            redWidget.sliceController().setLightboxTo1x1()

            self.delayDisplay('Four Up Layout')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView)

            self.delayDisplay('Shift Mouse')
            self.clickAndDrag(redWidget,
                              button='None',
                              start=(100, 100),
                              end=(140, 140),
                              modifiers=['Shift'])

            self.delayDisplay('Conventional, Link, Slice Model')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
            redWidget.sliceController().setSliceLink(True)
            redWidget.sliceController().setSliceVisible(True)

            self.delayDisplay('Rotate')
            threeDView = layoutManager.threeDWidget(0).threeDView()
            self.clickAndDrag(threeDView)

            self.delayDisplay('Zoom')
            threeDView = layoutManager.threeDWidget(0).threeDView()
            self.clickAndDrag(threeDView, button='Right')

            self.delayDisplay('Test passed!')
        except Exception, e:
            import traceback
            traceback.print_exc()
            self.delayDisplay('Test caused exception!\n' + str(e))

        self.delayDisplay("Restoring original database directory")
        DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
Example #3
0
    def test_Part1DICOM(self):
        """ Test the DICOM part of the test using the head atlas
        """
        import os
        self.delayDisplay("Starting the DICOM test")
        #
        # first, get the data - a zip file of dicom data
        #
        import SampleData
        dicomFilesDirectory = SampleData.downloadFromURL(
            fileNames='Dcmtk-db.zip',
            uris=TESTING_DATA_URL + 'MD5/7a43d121a51a631ab0df02071e5ba6ed',
            checksums='MD5:7a43d121a51a631ab0df02071e5ba6ed')[0]

        try:
            self.delayDisplay("Switching to temp database directory")
            originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase(
                'tempDICOMDatbase')

            self.delayDisplay('Start Local DICOM Q/R SCP')
            import subprocess
            import os
            configFilePath = dicomFilesDirectory + '/Dcmtk-db/dcmqrscp.cfg'
            processCurrentPath = dicomFilesDirectory + '/Dcmtk-db/'
            print("configFilePath: " + os.path.abspath(configFilePath))
            print("processCurrentPath: " + os.path.abspath(processCurrentPath))

            dcmqrscpExeOptions = ('/bin',
                                  '/../CTK-build/CMakeExternals/Install/bin',
                                  '/../DCMTK-install/bin',
                                  '/../DCMTK-build/bin',
                                  '/../DCMTK-build/bin/Release',
                                  '/../DCMTK-build/bin/Debug',
                                  '/../DCMTK-build/bin/RelWithDebInfo'
                                  '/../DCMTK-build/bin/MinSizeRel')

            dcmqrscpExePath = None
            dcmqrscpExeName = '/dcmqrscp'
            if slicer.app.os == 'win':
                dcmqrscpExeName = dcmqrscpExeName + '.exe'
            for path in dcmqrscpExeOptions:
                testPath = slicer.app.slicerHome + path + dcmqrscpExeName
                if os.path.exists(testPath):
                    dcmqrscpExePath = testPath
                    break
            if not dcmqrscpExePath:
                raise UserWarning("Could not find dcmqrscp executable")

            args = (dcmqrscpExePath, '-c', configFilePath)
            popen = subprocess.Popen(args,
                                     stdout=subprocess.PIPE,
                                     cwd=processCurrentPath)

            self.delayDisplay('Retrieve DICOM')
            slicer.util.selectModule('DICOM')
            dicomRetrieve = ctk.ctkDICOMRetrieve()
            dicomRetrieve.setKeepAssociationOpen(True)
            dicomRetrieve.setDatabase(slicer.dicomDatabase)
            dicomRetrieve.setCallingAETitle('SlicerAE')
            dicomRetrieve.setCalledAETitle('DCMTK')
            dicomRetrieve.setPort(12345)
            dicomRetrieve.setHost('localhost')
            dicomRetrieve.getStudy(
                '1.2.124.113932.1.170.223.162.178.20050502.160340.12640015')
            popen.kill()

            # Select first patient
            browserWidget = slicer.modules.DICOMWidget.browserWidget
            browserWidget.dicomBrowser.dicomTableManager().patientsTable(
            ).selectFirst()
            browserWidget.examineForLoading()

            self.delayDisplay('Loading Selection')
            browserWidget.loadCheckedLoadables()

            self.delayDisplay('Change Level')
            layoutManager = slicer.app.layoutManager()
            redWidget = layoutManager.sliceWidget('Red')
            slicer.util.clickAndDrag(redWidget, start=(10, 10), end=(10, 40))

            self.delayDisplay('Change Window')
            slicer.util.clickAndDrag(redWidget, start=(10, 10), end=(40, 10))

            self.delayDisplay('Change Layout')
            layoutManager = slicer.app.layoutManager()
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)

            self.delayDisplay('Zoom')
            slicer.util.clickAndDrag(redWidget,
                                     button='Right',
                                     start=(10, 10),
                                     end=(10, 40))

            self.delayDisplay('Pan')
            slicer.util.clickAndDrag(redWidget,
                                     button='Middle',
                                     start=(10, 10),
                                     end=(40, 40))

            self.delayDisplay('Center')
            redWidget.sliceController().fitSliceToBackground()

            self.delayDisplay('Lightbox')
            redWidget.sliceController().setLightboxTo6x6()

            self.delayDisplay('Conventional Layout')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)

            self.delayDisplay('No Lightbox')
            redWidget.sliceController().setLightboxTo1x1()

            self.delayDisplay('Four Up Layout')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView)

            self.delayDisplay('Shift Mouse')
            slicer.util.clickAndDrag(redWidget,
                                     button='None',
                                     start=(100, 100),
                                     end=(140, 140),
                                     modifiers=['Shift'])

            self.delayDisplay('Conventional, Link, Slice Model')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
            redWidget.sliceController().setSliceLink(True)
            redWidget.sliceController().setSliceVisible(True)

            self.delayDisplay('Rotate')
            threeDView = layoutManager.threeDWidget(0).threeDView()
            slicer.util.clickAndDrag(threeDView)

            self.delayDisplay('Zoom')
            threeDView = layoutManager.threeDWidget(0).threeDView()
            slicer.util.clickAndDrag(threeDView, button='Right')

            self.delayDisplay('Test passed!')
        except Exception as e:
            import traceback
            traceback.print_exc()
            self.delayDisplay('Test caused exception!\n' + str(e))

        self.delayDisplay("Restoring original database directory")
        DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
Example #4
0
class JRC2013VisTestTest(ScriptedLoadableModuleTest):
    """
  This is the test case for your scripted module.
  """
    def setUp(self):
        """ Do whatever is needed to reset the state - typically a scene clear will be enough.
    """
        self.delayDisplay("Closing the scene")
        layoutManager = slicer.app.layoutManager()
        layoutManager.setLayout(
            slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
        slicer.mrmlScene.Clear(0)

    def runTest(self):
        """Run as few or as many tests as needed here.
    """
        self.setUp()
        self.test_Part1DICOM()
        self.setUp()
        self.test_Part2Head()
        self.setUp()
        self.test_Part3Liver()
        self.setUp()
        self.test_Part4Lung()

    def test_Part1DICOM(self):
        """ Test the DICOM part of the test using the head atlas
    """

        import os
        self.delayDisplay("Starting the DICOM test")
        #
        # first, get the data - a zip file of dicom data
        #
        import SampleData
        SampleData.downloadFromURL(
            fileNames='Dcmtk-db.zip',
            uris='http://slicer.kitware.com/midas3/download?items=18822')[0]

        try:
            self.delayDisplay("Switching to temp database directory")
            originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase(
                'tempDICOMDatbase')

            self.delayDisplay('Start Local DICOM Q/R SCP')
            import subprocess
            import os
            configFilePath = dicomFilesDirectory + '/Dcmtk-db/dcmqrscp.cfg'
            processCurrentPath = dicomFilesDirectory + '/Dcmtk-db/'

            dcmqrscpExeOptions = (
                '/bin',
                '/../CTK-build/CMakeExternals/Install/bin',
                '/../DCMTK-install/bin',
                '/../DCMTK-build/bin',
            )

            dcmqrscpExePath = None
            dcmqrscpExeName = '/dcmqrscp'
            if slicer.app.os == 'win':
                dcmqrscpExeName = dcmqrscpExeName + '.exe'
            for path in dcmqrscpExeOptions:
                testPath = slicer.app.slicerHome + path + dcmqrscpExeName
                if os.path.exists(testPath):
                    dcmqrscpExePath = testPath
                    break
            if not dcmqrscpExePath:
                raise (UserWarning("Could not find dcmqrscp executable"))

            args = (dcmqrscpExePath, '-c', configFilePath)
            popen = subprocess.Popen(args,
                                     stdout=subprocess.PIPE,
                                     cwd=processCurrentPath)

            self.delayDisplay('Retrieve DICOM')
            mainWindow = slicer.util.mainWindow()
            mainWindow.moduleSelector().selectModule('DICOM')
            dicomRetrieve = ctk.ctkDICOMRetrieve()
            dicomRetrieve.setKeepAssociationOpen(True)
            dicomRetrieve.setDatabase(slicer.dicomDatabase)
            dicomRetrieve.setCallingAETitle('SlicerAE')
            dicomRetrieve.setCalledAETitle('DCMTK')
            dicomRetrieve.setPort(12345)
            dicomRetrieve.setHost('localhost')
            dicomRetrieve.getStudy(
                '1.2.124.113932.1.170.223.162.178.20050502.160340.12640015')
            popen.kill()
            dicomWidget.detailsPopup.open()
            # click on the first row of the tree
            index = dicomWidget.tree.indexAt(qt.QPoint(0, 0))
            dicomWidget.onTreeClicked(index)

            self.delayDisplay('Loading Selection')
            dicomWidget.detailsPopup.loadCheckedLoadables()

            self.delayDisplay('Change Level')
            layoutManager = slicer.app.layoutManager()
            redWidget = layoutManager.sliceWidget('Red')
            slicer.util.clickAndDrag(redWidget, start=(10, 10), end=(10, 40))

            self.delayDisplay('Change Window')
            slicer.util.clickAndDrag(redWidget, start=(10, 10), end=(40, 10))

            self.delayDisplay('Change Layout')
            layoutManager = slicer.app.layoutManager()
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)

            self.delayDisplay('Zoom')
            slicer.util.clickAndDrag(redWidget,
                                     button='Right',
                                     start=(10, 10),
                                     end=(10, 40))

            self.delayDisplay('Pan')
            slicer.util.clickAndDrag(redWidget,
                                     button='Middle',
                                     start=(10, 10),
                                     end=(40, 40))

            self.delayDisplay('Center')
            redWidget.sliceController().fitSliceToBackground()

            self.delayDisplay('Lightbox')
            redWidget.sliceController().setLightboxTo6x6()

            self.delayDisplay('Conventional Layout')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)

            self.delayDisplay('No Lightbox')
            redWidget.sliceController().setLightboxTo1x1()

            self.delayDisplay('Four Up Layout')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView)

            self.delayDisplay('Shift Mouse')
            slicer.util.clickAndDrag(redWidget,
                                     button='None',
                                     start=(100, 100),
                                     end=(140, 140),
                                     modifiers=['Shift'])

            self.delayDisplay('Conventional, Link, Slice Model')
            layoutManager.setLayout(
                slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
            redWidget.sliceController().setSliceLink(True)
            redWidget.sliceController().setSliceVisible(True)

            self.delayDisplay('Rotate')
            threeDView = layoutManager.threeDWidget(0).threeDView()
            slicer.util.clickAndDrag(threeDView)

            self.delayDisplay('Zoom')
            threeDView = layoutManager.threeDWidget(0).threeDView()
            slicer.util.clickAndDrag(threeDView, button='Right')

            self.delayDisplay('Test passed!')
        except Exception, e:
            import traceback
            traceback.print_exc()
            self.delayDisplay('Test caused exception!\n' + str(e))

        self.delayDisplay("Restoring original database directory")
        DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
Example #5
0
  def test_AlternateReaders(self):
    """ Test the DICOM loading of sample testing data
    """
    testPass = True
    import os, json
    self.delayDisplay("Starting the DICOM test")

    referenceData = [
      { "url": "http://slicer.kitware.com/midas3/download?items=292839",
        "checksum": "SHA256:3450ef9372a3460a2f181c8d3bb35a74b4f0acb10c6e18cfcf7804e1d99bf843",
        "fileName": "Mouse-MR-example-where-GDCM_fails.zip",
        "name": "Mouse-MR-example-where-GDCM_fails",
        "seriesUID": "1.3.6.1.4.1.9590.100.1.2.366426457713813178933224342280246227461",
        # GDCM rejects loading. 
        # DCMTK reads it but then ITK rejects loading the image with 0 spacing.
        "expectedFailures": ["GDCM", "Archetype", "DCMTK", "GDCM with DCMTK fallback"],
        "voxelValueQuantity": "(110852, DCM, \"MR signal intensity\")",
        "voxelValueUnits": "(1, UCUM, \"no units\")"
      },
      { "url": "http://slicer.kitware.com/midas3/download?items=294857",
        "checksum": "SHA256:899f3f8617ca53bad7dca0b2908478319e708b48ff41dfa64b6bac1d76529928",
        "fileName": "deidentifiedMRHead-dcm-one-series.zip",
        "name": "deidentifiedMRHead-dcm-one-series",
        "seriesUID": "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.270.0",
        "expectedFailures": [],
        "voxelValueQuantity": "(110852, DCM, \"MR signal intensity\")",
        "voxelValueUnits": "(1, UCUM, \"no units\")"
      }
    ]

    # another dataset that could be added in the future - currently fails for all readers
    # due to invalid format - see https://issues.slicer.org/view.php?id=3569
      #{ "url": "http://slicer.kitware.com/midas3/download/item/293587/RIDER_bug.zip",
        #"fileName": "RIDER_bug.zip",
        #"name": "RIDER_bug",
        #"seriesUID": "1.3.6.1.4.1.9328.50.7.261772317324041365541450388603508531852",
        #"expectedFailures": []
      #}

    loadingResult = {}
    #
    # first, get the data - a zip file of dicom data
    #
    self.delayDisplay("Downloading")
    for dataset in referenceData:
      try:
        import SampleData
        dicomFilesDirectory = SampleData.downloadFromURL(
          fileNames=dataset['fileName'], uris=dataset['url'], checksums=dataset['checksum'])[0]
        self.delayDisplay('Finished with download')

        #
        # insert the data into the database
        #
        self.delayDisplay("Switching to temp database directory")
        originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase')

        self.delayDisplay('Importing DICOM')
        slicer.util.selectModule("DICOM")

        browserWidget = slicer.modules.DICOMWidget.browserWidget
        dicomBrowser = browserWidget.dicomBrowser
        dicomBrowser.importDirectory(dicomFilesDirectory, dicomBrowser.ImportDirectoryAddLink)
        dicomBrowser.waitForImportFinished()

        #
        # select the series
        #
        browserWidget.onSeriesSelected([dataset['seriesUID']])
        # load the data by series UID
        browserWidget.examineForLoading()
        loadable = list(browserWidget.getAllSelectedLoadables().keys())[0]

        #
        # try loading using each of the selected readers, fail
        # on enexpected load issue
        #
        scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']()
        readerApproaches = scalarVolumePlugin.readerApproaches()
        basename = loadable.name
        volumesByApproach = {}
        for readerApproach in readerApproaches:
          self.delayDisplay('Loading Selection with approach: %s' % readerApproach)
          loadable.name = basename + "-" + readerApproach
          volumeNode = scalarVolumePlugin.load(loadable,readerApproach)
          if not volumeNode and readerApproach not in dataset['expectedFailures']:
            raise Exception("Expected to be able to read with %s, but couldn't" % readerApproach)
          if volumeNode and readerApproach in dataset['expectedFailures']:
            raise Exception("Expected to NOT be able to read with %s, but could!" % readerApproach)
          if volumeNode:
            volumesByApproach[readerApproach] = volumeNode

            self.delayDisplay('Test quantity and unit')
            if 'voxelValueQuantity' in dataset.keys():
              self.assertEqual(volumeNode.GetVoxelValueQuantity().GetAsPrintableString(), dataset['voxelValueQuantity'])
            if 'voxelValueUnits' in dataset.keys():
              self.assertEqual(volumeNode.GetVoxelValueUnits().GetAsPrintableString(), dataset['voxelValueUnits'])


        #
        # for each approach that loaded as expected, compare the volumes
        # to ensure they match in terms of pixel data and metadata
        #
        failedComparisons = {}
        approachesThatLoaded = list(volumesByApproach.keys())
        print('approachesThatLoaded %s' % approachesThatLoaded)
        for approachIndex in range(len(approachesThatLoaded)):
          firstApproach = approachesThatLoaded[approachIndex]
          firstVolume = volumesByApproach[firstApproach]
          for secondApproachIndex in range(approachIndex+1,len(approachesThatLoaded)):
            secondApproach = approachesThatLoaded[secondApproachIndex]
            secondVolume = volumesByApproach[secondApproach]
            print('comparing  %s,%s' % (firstApproach, secondApproach))
            comparison = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin'].compareVolumeNodes(firstVolume,secondVolume)
            if comparison != "":
              print(('failed: %s', comparison))
              failedComparisons[firstApproach,secondApproach] = comparison

        if len(failedComparisons.keys()) > 0:
          raise Exception("Loaded volumes don't match: %s" % failedComparisons)

        self.delayDisplay('%s Test passed!' % dataset['name'])

      except Exception as e:
        import traceback
        traceback.print_exc()
        self.delayDisplay('%s Test caused exception!\n' % dataset['name'] + str(e))
        testPass = False

    self.delayDisplay("Restoring original database directory")
    DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
    slicer.util.selectModule('DICOMReaders')

    logging.info(loadingResult)

    return testPass
Example #6
0
  def test_MissingSlices(self):
    """ Test behavior of the readers when slices are missing

    To edit and run this test from the python console, paste this below:

reloadScriptedModule('DICOMReaders'); import DICOMReaders; tester = DICOMReaders.DICOMReadersTest(); tester.setUp(); tester.test_MissingSlices()

    """
    testPass = True
    import os, json
    self.delayDisplay("Starting the DICOM test")

    settings = qt.QSettings()
    settings.setValue("DICOM/ScalarVolume/AcquisitionGeometryRegularization", "transform")

    import SampleData
    dicomFilesDirectory = SampleData.downloadFromURL(
      fileNames='deidentifiedMRHead-dcm-one-series.zip',
      uris='http://slicer.kitware.com/midas3/download?items=294857',
      checksums='SHA256:899f3f8617ca53bad7dca0b2908478319e708b48ff41dfa64b6bac1d76529928')[0]
    self.delayDisplay('Finished with download\n')

    seriesUID = "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.270.0"
    seriesRASBounds = [-87.29489517211913, 81.70450973510744,
                       -121.57139587402344, 134.42860412597656,
                       -138.71430206298828, 117.28569793701172]
    seriesDirectory = "Series 004 [MR - SAG RF FAST VOL FLIP 20]"
    lastSliceCorners = [[[81.05451202, 133.92860413, 116.78569794], [81.05451202, -122.07139587, 116.78569794]],
                        [[81.05451202, 133.92860413, -139.21429443], [81.05451202, -122.07139587, -139.21429443]]]
    filesToRemove = [
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.361.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.362.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.363.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.364.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.365.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.366.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.367.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.368.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.369.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.370.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.371.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.372.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.373.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.374.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.375.0.dcm",
      "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.376.0.dcm",
    ]

    try:

      print('Removing %d files from the middle of the series' % len(filesToRemove))
      for file in filesToRemove:
        filePath = os.path.join(dicomFilesDirectory, seriesDirectory, file)
        os.remove(filePath)

      #
      # insert the data into the database
      #
      self.delayDisplay("Switching to temp database directory")
      originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase')

      self.delayDisplay('Importing DICOM')
      slicer.util.selectModule("DICOM")

      browserWidget = slicer.modules.DICOMWidget.browserWidget
      dicomBrowser = browserWidget.dicomBrowser
      dicomBrowser.importDirectory(dicomFilesDirectory, dicomBrowser.ImportDirectoryAddLink)
      dicomBrowser.waitForImportFinished()

      #
      # select the series
      #
      browserWidget.onSeriesSelected([seriesUID])
      # load the data by series UID
      browserWidget.examineForLoading()
      loadable = list(browserWidget.getAllSelectedLoadables().keys())[0]

      if len(loadable.warning) == 0:
        raise Exception("Expected warning about geometry issues due to missing slices!")

      #
      # load and correct for acquisition then check the geometry
      #
      scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']()
      volumeNode = scalarVolumePlugin.load(loadable)

      if not numpy.allclose(scalarVolumePlugin.acquisitionModeling.fixedCorners[-1], lastSliceCorners):
        raise Exception("Acquisition transform didn't fix slice corners!")

      self.delayDisplay('test_MissingSlices passed!')

    except Exception as e:
      import traceback
      traceback.print_exc()
      self.delayDisplay('Missing Slices Test caused exception!\n' + str(e))
      testPass = False

    self.delayDisplay("Restoring original database directory")
    DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
    slicer.util.selectModule('DICOMReaders')

    return testPass
Example #7
0
  def test_Part1DICOM(self,enableScreenshotsFlag=0,screenshotScaleFactor=1):
    """ Test the DICOM part of the test using the head atlas
    """

    logic = RSNAVisTutorialLogic()
    logic.enableScreenshots = enableScreenshotsFlag
    logic.screenshotScaleFactor = screenshotScaleFactor

    import os
    self.delayDisplay("Starting the DICOM test")
    #
    # first, get the data - a zip file of dicom data
    #
    import SampleData
    dicomFilesDirectory = SampleData.downloadFromURL(
      fileNames='dataset1_Thorax_Abdomen.zip',
      uris='http://slicer.kitware.com/midas3/download?items=124183')[0]

    try:
      self.delayDisplay("Switching to temp database directory")
      originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase')

      self.delayDisplay('Importing DICOM')
      mainWindow = slicer.util.mainWindow()
      mainWindow.moduleSelector().selectModule('DICOM')

      indexer = ctk.ctkDICOMIndexer()
      indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None)
      indexer.waitForImportFinished()

      dicomWidget = slicer.modules.DICOMWidget
      dicomWidget.detailsPopup.open()

      # load the data by series UID
      dicomWidget.detailsPopup.offerLoadables('1.3.12.2.1107.5.1.4.50025.30000005060811542834300000776','Series')
      dicomWidget.detailsPopup.examineForLoading()

      self.delayDisplay('Loading Selection')
      dicomWidget.detailsPopup.loadCheckedLoadables()

      logic.takeScreenshot('LoadingADICOMVolume-Loaded','Loaded DICOM Volume',-1)

      layoutManager = slicer.app.layoutManager()
      redWidget = layoutManager.sliceWidget('Red')
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(10,40))
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(40,10))

      logic.takeScreenshot('LoadingADICOMVolume-WL','Changed level and window',-1)

      redWidget.sliceController().setSliceLink(True)
      redWidget.sliceController().setSliceVisible(True);
      logic.takeScreenshot('LoadingADICOMVolume-LinkView','Linked and visible',-1)

      slicer.util.clickAndDrag(redWidget,button='Right',start=(10,10),end=(10,40))
      logic.takeScreenshot('LoadingADICOMVolume-Zoom','Zoom',-1)

      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView)
      logic.takeScreenshot('LoadingADICOMVolume-Rotate','Rotate',-1)

      threeDView.resetFocalPoint()
      logic.takeScreenshot('LoadingADICOMVolume-Center','Center the view',-1)

      layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalWidescreenView)
      logic.takeScreenshot('LoadingADICOMVolume-ConventionalWidescreen','Conventional Widescreen Layout',-1)

      slicer.util.mainWindow().moduleSelector().selectModule('VolumeRendering')
      logic.takeScreenshot('VolumeRendering-Module','Volume Rendering',-1)

      volumeRenderingWidgetRep = slicer.modules.volumerendering.widgetRepresentation()
      abdomenVolume = slicer.mrmlScene.GetFirstNodeByName('6: CT_Thorax_Abdomen')
      volumeRenderingWidgetRep.setMRMLVolumeNode(abdomenVolume)
      logic.takeScreenshot('VolumeRendering-SelectVolume','Select the volume 6: CT_Thorax_Abdomen',-1)

      presetsScene = slicer.modules.volumerendering.logic().GetPresetsScene()
      ctCardiac3 = presetsScene.GetFirstNodeByName('CT-Cardiac3')
      volumeRenderingWidgetRep.applyPreset(ctCardiac3)
      logic.takeScreenshot('VolumeRendering-SelectPreset','Select the Preset CT-Cardiac-3')

      self.delayDisplay('Skipping: Select VTK CPU Ray Casting')

      volumeRenderingNode = slicer.mrmlScene.GetFirstNodeByName('VolumeRendering')
      volumeRenderingNode.SetVisibility(1)
      logic.takeScreenshot('VolumeRendering-ViewRendering','View Volume Rendering',-1)

      self.delayDisplay('Skipping Move the Shift slider')

      redWidget.sliceController().setSliceVisible(False);
      logic.takeScreenshot('VolumeRendering-SlicesOff','Turn off visibility of slices in 3D',-1)

      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView)
      logic.takeScreenshot('VolumeRendering-RotateVolumeRendering','Rotate volume rendered image',-1)

      volumeRenderingNode.SetVisibility(0)
      logic.takeScreenshot('VolumeRendering-TurnOffVolumeRendering','Turn off volume rendered image',-1)

      volumeRenderingNode.SetCroppingEnabled(1)
      annotationROI = slicer.mrmlScene.GetFirstNodeByName('AnnotationROI')
      annotationROI.SetDisplayVisibility(1)
      logic.takeScreenshot('VolumeRendering-DisplayROI','Enable cropping and display ROI',-1)

      redWidget.sliceController().setSliceVisible(True)
      logic.takeScreenshot('VolumeRendering-SlicesOn','Turn on visibility of slices in 3D',-1)

      annotationROI.SetXYZ(-79.61,154.16,-232.591)
      annotationROI.SetRadiusXYZ(43.4,65.19,70.5)
      logic.takeScreenshot('VolumeRendering-SizedROI','Position the ROI over a kidney',-1)

      volumeRenderingNode.SetVisibility(1)
      logic.takeScreenshot('VolumeRendering-ROIRendering','ROI volume rendered',-1)

      annotationROI.SetXYZ(15,146,-186)
      annotationROI.SetRadiusXYZ(138,57,61)
      logic.takeScreenshot('VolumeRendering-BothKidneys','Rendered both kidneys',-1)

      self.delayDisplay('Test passed!')
    except Exception as e:
      import traceback
      traceback.print_exc()
      self.delayDisplay('Test caused exception!\n' + str(e))

    self.delayDisplay("Restoring original database directory")
    DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
Example #8
0
class RSNAVisTutorialTest(unittest.TestCase):
  """
  This is the test case for your scripted module.
  """

  def delayDisplay(self,message,msec=1000):
    """This utility method displays a small dialog and waits.
    This does two things: 1) it lets the event loop catch up
    to the state of the test so that rendering and widget updates
    have all taken place before the test continues and 2) it
    shows the user/developer/tester the state of the test
    so that we'll know when it breaks.
    """
    print(message)
    self.info = qt.QDialog()
    self.infoLayout = qt.QVBoxLayout()
    self.info.setLayout(self.infoLayout)
    self.label = qt.QLabel(message,self.info)
    self.infoLayout.addWidget(self.label)
    qt.QTimer.singleShot(msec, self.info.close)
    self.info.exec_()

  def takeScreenshot(self,name,description,type=-1):
    # show the message even if not taking a screen shot
    self.delayDisplay(description)

    if self.enableScreenshots == 0:
      return

    lm = slicer.app.layoutManager()
    # switch on the type to get the requested window
    widget = 0
    if type == slicer.qMRMLScreenShotDialog.FullLayout:
      # full layout
      widget = lm.viewport()
    elif type == slicer.qMRMLScreenShotDialog.ThreeD:
      # just the 3D window
      widget = lm.threeDWidget(0).threeDView()
    elif type == slicer.qMRMLScreenShotDialog.Red:
      # red slice window
      widget = lm.sliceWidget("Red")
    elif type == slicer.qMRMLScreenShotDialog.Yellow:
      # yellow slice window
      widget = lm.sliceWidget("Yellow")
    elif type == slicer.qMRMLScreenShotDialog.Green:
      # green slice window
      widget = lm.sliceWidget("Green")
    else:
      # default to using the full window
      widget = slicer.util.mainWindow()
      # reset the type so that the node is set correctly
      type = slicer.qMRMLScreenShotDialog.FullLayout

    # grab and convert to vtk image data
    qpixMap = qt.QPixmap().grabWidget(widget)
    qimage = qpixMap.toImage()
    imageData = vtk.vtkImageData()
    slicer.qMRMLUtils().qImageToVtkImageData(qimage,imageData)

    annotationLogic = slicer.modules.annotations.logic()
    annotationLogic.CreateSnapShot(name, description, type, self.screenshotScaleFactor, imageData)

  def setUp(self):
    """ Do whatever is needed to reset the state - typically a scene clear will be enough.
    """
    self.delayDisplay("Closing the scene")
    layoutManager = slicer.app.layoutManager()
    layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
    slicer.mrmlScene.Clear(0)

  def runTest(self):
    """Run as few or as many tests as needed here.
    """
    self.setUp()
    self.test_Part1DICOM()
    self.setUp()
    self.test_Part2Head()
    self.setUp()
    self.test_Part3Liver()
    self.setUp()
    self.test_Part4Lung()

  def test_Part1DICOM(self,enableScreenshotsFlag=0,screenshotScaleFactor=1):
    """ Test the DICOM part of the test using the head atlas
    """

    self.enableScreenshots = enableScreenshotsFlag
    self.screenshotScaleFactor = screenshotScaleFactor

    import os
    self.delayDisplay("Starting the DICOM test")
    #
    # first, get the data - a zip file of dicom data
    #
    import urllib
    downloads = (
        ('http://slicer.kitware.com/midas3/download?items=124183', 'dataset1_Thorax_Abdomen.zip'),
        )

    self.delayDisplay("Downloading")
    for url,name in downloads:
      filePath = slicer.app.temporaryPath + '/' + name
      if not os.path.exists(filePath) or os.stat(filePath).st_size == 0:
        self.delayDisplay('Requesting download %s from %s...\n' % (name, url))
        urllib.urlretrieve(url, filePath)
    self.delayDisplay('Finished with download\n')

    self.delayDisplay("Unzipping")
    dicomFilesDirectory = slicer.app.temporaryPath + '/dicomFiles'
    qt.QDir().mkpath(dicomFilesDirectory)
    slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory)

    try:
      self.delayDisplay("Switching to temp database directory")
      originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase')

      self.delayDisplay('Importing DICOM')
      mainWindow = slicer.util.mainWindow()
      mainWindow.moduleSelector().selectModule('DICOM')

      indexer = ctk.ctkDICOMIndexer()
      indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None)
      indexer.waitForImportFinished()

      dicomWidget = slicer.modules.DICOMWidget
      dicomWidget.detailsPopup.open()

      # load the data by series UID
      dicomWidget.detailsPopup.offerLoadables('1.3.12.2.1107.5.1.4.50025.30000005060811542834300000776','Series')
      dicomWidget.detailsPopup.examineForLoading()

      self.delayDisplay('Loading Selection')
      dicomWidget.detailsPopup.loadCheckedLoadables()

      self.takeScreenshot('LoadingADICOMVolume-Loaded','Loaded DICOM Volume',-1)

      layoutManager = slicer.app.layoutManager()
      redWidget = layoutManager.sliceWidget('Red')
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(10,40))
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(40,10))

      self.takeScreenshot('LoadingADICOMVolume-WL','Changed level and window',-1)

      redWidget.sliceController().setSliceLink(True)
      redWidget.sliceController().setSliceVisible(True);
      self.takeScreenshot('LoadingADICOMVolume-LinkView','Linked and visible',-1)

      slicer.util.clickAndDrag(redWidget,button='Right',start=(10,10),end=(10,40))
      self.takeScreenshot('LoadingADICOMVolume-Zoom','Zoom',-1)

      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView)
      self.takeScreenshot('LoadingADICOMVolume-Rotate','Rotate',-1)

      threeDView.resetFocalPoint()
      self.takeScreenshot('LoadingADICOMVolume-Center','Center the view',-1)

      layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalWidescreenView)
      self.takeScreenshot('LoadingADICOMVolume-ConventionalWidescreen','Conventional Widescreen Layout',-1)

      slicer.util.mainWindow().moduleSelector().selectModule('VolumeRendering')
      self.takeScreenshot('VolumeRendering-Module','Volume Rendering',-1)

      volumeRenderingWidgetRep = slicer.modules.volumerendering.widgetRepresentation()
      abdomenVolume = slicer.mrmlScene.GetFirstNodeByName('6: CT_Thorax_Abdomen')
      volumeRenderingWidgetRep.setMRMLVolumeNode(abdomenVolume)
      self.takeScreenshot('VolumeRendering-SelectVolume','Select the volume 6: CT_Thorax_Abdomen',-1)

      presetsScene = slicer.modules.volumerendering.logic().GetPresetsScene()
      ctCardiac3 = presetsScene.GetFirstNodeByName('CT-Cardiac3')
      volumeRenderingWidgetRep.applyPreset(ctCardiac3)
      self.takeScreenshot('VolumeRendering-SelectPreset','Select the Preset CT-Cardiac-3')

      self.delayDisplay('Skipping: Select VTK CPU Ray Casting')

      volumeRenderingNode = slicer.mrmlScene.GetFirstNodeByName('VolumeRendering')
      volumeRenderingNode.SetVisibility(1)
      self.takeScreenshot('VolumeRendering-ViewRendering','View Volume Rendering',-1)

      self.delayDisplay('Skipping Move the Shift slider')

      redWidget.sliceController().setSliceVisible(False);
      self.takeScreenshot('VolumeRendering-SlicesOff','Turn off visibility of slices in 3D',-1)

      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView)
      self.takeScreenshot('VolumeRendering-RotateVolumeRendering','Rotate volume rendered image',-1)

      volumeRenderingNode.SetVisibility(0)
      self.takeScreenshot('VolumeRendering-TurnOffVolumeRendering','Turn off volume rendered image',-1)

      volumeRenderingNode.SetCroppingEnabled(1)
      annotationROI = slicer.mrmlScene.GetFirstNodeByName('AnnotationROI')
      annotationROI.SetDisplayVisibility(1)
      self.takeScreenshot('VolumeRendering-DisplayROI','Enable cropping and display ROI',-1)

      redWidget.sliceController().setSliceVisible(True)
      self.takeScreenshot('VolumeRendering-SlicesOn','Turn on visibility of slices in 3D',-1)

      annotationROI.SetXYZ(-79.61,154.16,-232.591)
      annotationROI.SetRadiusXYZ(43.4,65.19,70.5)
      self.takeScreenshot('VolumeRendering-SizedROI','Position the ROI over a kidney',-1)

      volumeRenderingNode.SetVisibility(1)
      self.takeScreenshot('VolumeRendering-ROIRendering','ROI volume rendered',-1)

      annotationROI.SetXYZ(15,146,-186)
      annotationROI.SetRadiusXYZ(138,57,61)
      self.takeScreenshot('VolumeRendering-BothKidneys','Rendered both kidneys',-1)

      self.delayDisplay('Test passed!')
    except Exception, e:
      import traceback
      traceback.print_exc()
      self.delayDisplay('Test caused exception!\n' + str(e))

    self.delayDisplay("Restoring original database directory")
    DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
Example #9
0
class RSNAVisTutorialTest(ScriptedLoadableModuleTest):
  """
  This is the test case for your scripted module.
  Uses ScriptedLoadableModuleTest base class, available at:
  https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
  """

  def setUp(self):
    """ Do whatever is needed to reset the state - typically a scene clear will be enough.
    """
    self.delayDisplay("Closing the scene")
    layoutManager = slicer.app.layoutManager()
    layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
    slicer.mrmlScene.Clear(0)

  def runTest(self):
    """Run as few or as many tests as needed here.
    """
    self.setUp()
    self.test_Part1DICOM()
    self.setUp()
    self.test_Part2Head()
    self.setUp()
    self.test_Part3Liver()
    self.setUp()
    self.test_Part4Lung()

  def test_Part1DICOM(self,enableScreenshotsFlag=0,screenshotScaleFactor=1):
    """ Test the DICOM part of the test using the head atlas
    """

    logic = RSNAVisTutorialLogic()
    logic.enableScreenshots = enableScreenshotsFlag
    logic.screenshotScaleFactor = screenshotScaleFactor

    import os
    self.delayDisplay("Starting the DICOM test")
    #
    # first, get the data - a zip file of dicom data
    #
    import SampleData
    dicomFilesDirectory = SampleData.downloadFromURL(
      fileNames='dataset1_Thorax_Abdomen.zip',
      uris='http://slicer.kitware.com/midas3/download?items=124183')[0]

    try:
      self.delayDisplay("Switching to temp database directory")
      originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase')

      self.delayDisplay('Importing DICOM')
      mainWindow = slicer.util.mainWindow()
      mainWindow.moduleSelector().selectModule('DICOM')

      indexer = ctk.ctkDICOMIndexer()
      indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None)
      indexer.waitForImportFinished()

      dicomWidget = slicer.modules.DICOMWidget
      dicomWidget.detailsPopup.open()

      # load the data by series UID
      dicomWidget.detailsPopup.offerLoadables('1.3.12.2.1107.5.1.4.50025.30000005060811542834300000776','Series')
      dicomWidget.detailsPopup.examineForLoading()

      self.delayDisplay('Loading Selection')
      dicomWidget.detailsPopup.loadCheckedLoadables()

      logic.takeScreenshot('LoadingADICOMVolume-Loaded','Loaded DICOM Volume',-1)

      layoutManager = slicer.app.layoutManager()
      redWidget = layoutManager.sliceWidget('Red')
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(10,40))
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(40,10))

      logic.takeScreenshot('LoadingADICOMVolume-WL','Changed level and window',-1)

      redWidget.sliceController().setSliceLink(True)
      redWidget.sliceController().setSliceVisible(True);
      logic.takeScreenshot('LoadingADICOMVolume-LinkView','Linked and visible',-1)

      slicer.util.clickAndDrag(redWidget,button='Right',start=(10,10),end=(10,40))
      logic.takeScreenshot('LoadingADICOMVolume-Zoom','Zoom',-1)

      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView)
      logic.takeScreenshot('LoadingADICOMVolume-Rotate','Rotate',-1)

      threeDView.resetFocalPoint()
      logic.takeScreenshot('LoadingADICOMVolume-Center','Center the view',-1)

      layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalWidescreenView)
      logic.takeScreenshot('LoadingADICOMVolume-ConventionalWidescreen','Conventional Widescreen Layout',-1)

      slicer.util.mainWindow().moduleSelector().selectModule('VolumeRendering')
      logic.takeScreenshot('VolumeRendering-Module','Volume Rendering',-1)

      volumeRenderingWidgetRep = slicer.modules.volumerendering.widgetRepresentation()
      abdomenVolume = slicer.mrmlScene.GetFirstNodeByName('6: CT_Thorax_Abdomen')
      volumeRenderingWidgetRep.setMRMLVolumeNode(abdomenVolume)
      logic.takeScreenshot('VolumeRendering-SelectVolume','Select the volume 6: CT_Thorax_Abdomen',-1)

      presetsScene = slicer.modules.volumerendering.logic().GetPresetsScene()
      ctCardiac3 = presetsScene.GetFirstNodeByName('CT-Cardiac3')
      volumeRenderingWidgetRep.applyPreset(ctCardiac3)
      logic.takeScreenshot('VolumeRendering-SelectPreset','Select the Preset CT-Cardiac-3')

      self.delayDisplay('Skipping: Select VTK CPU Ray Casting')

      volumeRenderingNode = slicer.mrmlScene.GetFirstNodeByName('VolumeRendering')
      volumeRenderingNode.SetVisibility(1)
      logic.takeScreenshot('VolumeRendering-ViewRendering','View Volume Rendering',-1)

      self.delayDisplay('Skipping Move the Shift slider')

      redWidget.sliceController().setSliceVisible(False);
      logic.takeScreenshot('VolumeRendering-SlicesOff','Turn off visibility of slices in 3D',-1)

      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView)
      logic.takeScreenshot('VolumeRendering-RotateVolumeRendering','Rotate volume rendered image',-1)

      volumeRenderingNode.SetVisibility(0)
      logic.takeScreenshot('VolumeRendering-TurnOffVolumeRendering','Turn off volume rendered image',-1)

      volumeRenderingNode.SetCroppingEnabled(1)
      annotationROI = slicer.mrmlScene.GetFirstNodeByName('AnnotationROI')
      annotationROI.SetDisplayVisibility(1)
      logic.takeScreenshot('VolumeRendering-DisplayROI','Enable cropping and display ROI',-1)

      redWidget.sliceController().setSliceVisible(True)
      logic.takeScreenshot('VolumeRendering-SlicesOn','Turn on visibility of slices in 3D',-1)

      annotationROI.SetXYZ(-79.61,154.16,-232.591)
      annotationROI.SetRadiusXYZ(43.4,65.19,70.5)
      logic.takeScreenshot('VolumeRendering-SizedROI','Position the ROI over a kidney',-1)

      volumeRenderingNode.SetVisibility(1)
      logic.takeScreenshot('VolumeRendering-ROIRendering','ROI volume rendered',-1)

      annotationROI.SetXYZ(15,146,-186)
      annotationROI.SetRadiusXYZ(138,57,61)
      logic.takeScreenshot('VolumeRendering-BothKidneys','Rendered both kidneys',-1)

      self.delayDisplay('Test passed!')
    except Exception, e:
      import traceback
      traceback.print_exc()
      self.delayDisplay('Test caused exception!\n' + str(e))

    self.delayDisplay("Restoring original database directory")
    DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
    def test_Part1DICOM(self,
                        enableScreenshotsFlag=0,
                        screenshotScaleFactor=1):
        """ Test the DICOM part of the test using the head atlas
    """

        logic = RSNAVisTutorialLogic()
        logic.enableScreenshots = enableScreenshotsFlag
        logic.screenshotScaleFactor = screenshotScaleFactor

        import os
        self.delayDisplay("Starting the DICOM test")
        #
        # first, get the data - a zip file of dicom data
        #
        import SampleData
        dicomFilesDirectory = SampleData.downloadFromURL(
            fileNames='dataset1_Thorax_Abdomen.zip',
            uris=TESTING_DATA_URL +
            'SHA256/17a4199aad03a373dab27dc17e5bfcf84fc194d0a30975b4073e5b595d43a56a',
            checksums=
            'SHA256:17a4199aad03a373dab27dc17e5bfcf84fc194d0a30975b4073e5b595d43a56a'
        )[0]

        try:
            self.delayDisplay("Switching to temp database directory")
            originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase(
                'tempDICOMDatabase')

            slicer.util.selectModule('DICOM')
            browserWidget = slicer.modules.DICOMWidget.browserWidget
            dicomBrowser = browserWidget.dicomBrowser
            dicomBrowser.importDirectory(dicomFilesDirectory,
                                         dicomBrowser.ImportDirectoryAddLink)
            dicomBrowser.waitForImportFinished()

            # load the data by series UID
            dicomBrowser.dicomTableManager().patientsTable().selectFirst()
            browserWidget.examineForLoading()

            self.delayDisplay('Loading Selection')
            browserWidget.loadCheckedLoadables()

            logic.takeScreenshot('LoadingADICOMVolume-Loaded',
                                 'Loaded DICOM Volume', -1)

            layoutManager = slicer.app.layoutManager()
            redWidget = layoutManager.sliceWidget('Red')
            slicer.util.clickAndDrag(redWidget, start=(10, 10), end=(10, 40))
            slicer.util.clickAndDrag(redWidget, start=(10, 10), end=(40, 10))

            logic.takeScreenshot('LoadingADICOMVolume-WL',
                                 'Changed level and window', -1)

            redWidget.sliceController().setSliceLink(True)
            redWidget.sliceController().setSliceVisible(True)
            logic.takeScreenshot('LoadingADICOMVolume-LinkView',
                                 'Linked and visible', -1)

            slicer.util.clickAndDrag(redWidget,
                                     button='Right',
                                     start=(10, 10),
                                     end=(10, 40))
            logic.takeScreenshot('LoadingADICOMVolume-Zoom', 'Zoom', -1)

            threeDView = layoutManager.threeDWidget(0).threeDView()
            slicer.util.clickAndDrag(threeDView)
            logic.takeScreenshot('LoadingADICOMVolume-Rotate', 'Rotate', -1)

            threeDView.resetFocalPoint()
            logic.takeScreenshot('LoadingADICOMVolume-Center',
                                 'Center the view', -1)

            layoutManager.setLayout(slicer.vtkMRMLLayoutNode.
                                    SlicerLayoutConventionalWidescreenView)
            logic.takeScreenshot('LoadingADICOMVolume-ConventionalWidescreen',
                                 'Conventional Widescreen Layout', -1)

            slicer.util.mainWindow().moduleSelector().selectModule(
                'VolumeRendering')
            logic.takeScreenshot('VolumeRendering-Module', 'Volume Rendering',
                                 -1)

            volumeRenderingWidgetRep = slicer.modules.volumerendering.widgetRepresentation(
            )
            abdomenVolume = slicer.mrmlScene.GetFirstNodeByName(
                '6: CT_Thorax_Abdomen')
            volumeRenderingWidgetRep.setMRMLVolumeNode(abdomenVolume)
            logic.takeScreenshot('VolumeRendering-SelectVolume',
                                 'Select the volume 6: CT_Thorax_Abdomen', -1)

            presetsScene = slicer.modules.volumerendering.logic(
            ).GetPresetsScene()
            ctCardiac3 = presetsScene.GetFirstNodeByName('CT-Cardiac3')
            volumeRenderingWidgetRep.mrmlVolumePropertyNode().Copy(ctCardiac3)
            logic.takeScreenshot('VolumeRendering-SelectPreset',
                                 'Select the Preset CT-Cardiac-3')

            self.delayDisplay('Skipping: Select VTK CPU Ray Casting')

            volumeRenderingNode = slicer.mrmlScene.GetFirstNodeByName(
                'VolumeRendering')
            volumeRenderingNode.SetVisibility(1)
            logic.takeScreenshot('VolumeRendering-ViewRendering',
                                 'View Volume Rendering', -1)

            self.delayDisplay('Skipping Move the Shift slider')

            redWidget.sliceController().setSliceVisible(False)
            logic.takeScreenshot('VolumeRendering-SlicesOff',
                                 'Turn off visibility of slices in 3D', -1)

            threeDView = layoutManager.threeDWidget(0).threeDView()
            slicer.util.clickAndDrag(threeDView)
            logic.takeScreenshot('VolumeRendering-RotateVolumeRendering',
                                 'Rotate volume rendered image', -1)

            volumeRenderingNode.SetVisibility(0)
            logic.takeScreenshot('VolumeRendering-TurnOffVolumeRendering',
                                 'Turn off volume rendered image', -1)

            volumeRenderingNode.SetCroppingEnabled(1)
            annotationROI = slicer.mrmlScene.GetFirstNodeByName(
                'AnnotationROI')
            annotationROI.SetDisplayVisibility(1)
            logic.takeScreenshot('VolumeRendering-DisplayROI',
                                 'Enable cropping and display ROI', -1)

            redWidget.sliceController().setSliceVisible(True)
            logic.takeScreenshot('VolumeRendering-SlicesOn',
                                 'Turn on visibility of slices in 3D', -1)

            annotationROI.SetXYZ(-79.61, 154.16, -232.591)
            annotationROI.SetRadiusXYZ(43.4, 65.19, 70.5)
            logic.takeScreenshot('VolumeRendering-SizedROI',
                                 'Position the ROI over a kidney', -1)

            volumeRenderingNode.SetVisibility(1)
            logic.takeScreenshot('VolumeRendering-ROIRendering',
                                 'ROI volume rendered', -1)

            annotationROI.SetXYZ(15, 146, -186)
            annotationROI.SetRadiusXYZ(138, 57, 61)
            logic.takeScreenshot('VolumeRendering-BothKidneys',
                                 'Rendered both kidneys', -1)

            self.delayDisplay('Test passed!')
        except Exception as e:
            import traceback
            traceback.print_exc()
            self.delayDisplay('Test caused exception!\n' + str(e))

        self.delayDisplay("Restoring original database directory")
        DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)
Example #11
0
  def test_Part1DICOM(self):
    """ Test the DICOM part of the test using the head atlas
    """

    import os
    self.delayDisplay("Starting the DICOM test")
    #
    # first, get the data - a zip file of dicom data
    #
    import SampleData
    SampleData.downloadFromURL(
      fileNames='Dcmtk-db.zip',
      uris='http://slicer.kitware.com/midas3/download?items=18822')[0]

    try:
      self.delayDisplay("Switching to temp database directory")
      originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatbase')

      self.delayDisplay('Start Local DICOM Q/R SCP')
      import subprocess
      import os
      configFilePath = dicomFilesDirectory + '/Dcmtk-db/dcmqrscp.cfg'
      processCurrentPath = dicomFilesDirectory + '/Dcmtk-db/'

      dcmqrscpExeOptions = (
        '/bin',
        '/../CTK-build/CMakeExternals/Install/bin',
        '/../DCMTK-install/bin',
        '/../DCMTK-build/bin',
        )

      dcmqrscpExePath = None
      dcmqrscpExeName = '/dcmqrscp'
      if slicer.app.os == 'win':
        dcmqrscpExeName = dcmqrscpExeName + '.exe'
      for path in dcmqrscpExeOptions:
        testPath = slicer.app.slicerHome + path + dcmqrscpExeName
        if os.path.exists(testPath):
          dcmqrscpExePath = testPath
          break
      if not dcmqrscpExePath:
        raise UserWarning("Could not find dcmqrscp executable")

      args = (dcmqrscpExePath, '-c', configFilePath)
      popen = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=processCurrentPath)

      self.delayDisplay('Retrieve DICOM')
      mainWindow = slicer.util.mainWindow()
      mainWindow.moduleSelector().selectModule('DICOM')
      dicomRetrieve = ctk.ctkDICOMRetrieve()
      dicomRetrieve.setKeepAssociationOpen(True)
      dicomRetrieve.setDatabase(slicer.dicomDatabase)
      dicomRetrieve.setCallingAETitle('SlicerAE')
      dicomRetrieve.setCalledAETitle('DCMTK')
      dicomRetrieve.setPort(12345)
      dicomRetrieve.setHost('localhost')
      dicomRetrieve.getStudy('1.2.124.113932.1.170.223.162.178.20050502.160340.12640015');
      popen.kill()
      dicomWidget.detailsPopup.open()
      # click on the first row of the tree
      index = dicomWidget.tree.indexAt(qt.QPoint(0,0))
      dicomWidget.onTreeClicked(index)

      self.delayDisplay('Loading Selection')
      dicomWidget.detailsPopup.loadCheckedLoadables()

      self.delayDisplay('Change Level')
      layoutManager = slicer.app.layoutManager()
      redWidget = layoutManager.sliceWidget('Red')
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(10,40))

      self.delayDisplay('Change Window')
      slicer.util.clickAndDrag(redWidget,start=(10,10),end=(40,10))

      self.delayDisplay('Change Layout')
      layoutManager = slicer.app.layoutManager()
      layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView)

      self.delayDisplay('Zoom')
      slicer.util.clickAndDrag(redWidget,button='Right',start=(10,10),end=(10,40))

      self.delayDisplay('Pan')
      slicer.util.clickAndDrag(redWidget,button='Middle',start=(10,10),end=(40,40))

      self.delayDisplay('Center')
      redWidget.sliceController().fitSliceToBackground()

      self.delayDisplay('Lightbox')
      redWidget.sliceController().setLightboxTo6x6()

      self.delayDisplay('Conventional Layout')
      layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)

      self.delayDisplay('No Lightbox')
      redWidget.sliceController().setLightboxTo1x1()

      self.delayDisplay('Four Up Layout')
      layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpView)

      self.delayDisplay('Shift Mouse')
      slicer.util.clickAndDrag(redWidget,button='None',start=(100,100),end=(140,140),modifiers=['Shift'])

      self.delayDisplay('Conventional, Link, Slice Model')
      layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutConventionalView)
      redWidget.sliceController().setSliceLink(True)
      redWidget.sliceController().setSliceVisible(True);

      self.delayDisplay('Rotate')
      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView)

      self.delayDisplay('Zoom')
      threeDView = layoutManager.threeDWidget(0).threeDView()
      slicer.util.clickAndDrag(threeDView,button='Right')

      self.delayDisplay('Test passed!')
    except Exception as e:
      import traceback
      traceback.print_exc()
      self.delayDisplay('Test caused exception!\n' + str(e))

    self.delayDisplay("Restoring original database directory")
    DICOMUtils.closeTemporaryDatabase(originalDatabaseDirectory)