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
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)
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)
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)
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
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
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)
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)
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)
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)