def _downloadTestData(self): """ download DICOM PET scan and add to DICOM database """ import urllib quantity = slicer.vtkCodedEntry() quantity.SetFromString('CodeValue:126400|CodingSchemeDesignator:DCM|CodeMeaning:Standardized Uptake Value') units = slicer.vtkCodedEntry() units.SetFromString('CodeValue:{SUVbw}g/ml|CodingSchemeDesignator:UCUM|CodeMeaning:Standardized Uptake Value body weight') url = 'http://slicer.kitware.com/midas3/download/item/257234/QIN-HEADNECK-01-0139-PET.zip' zipFile = 'QIN-HEADNECK-01-0139-PET.zip' suvNormalizationFactor = 0.00040166400000000007 destinationDirectory = self.tempDicomDatabase filePath = os.path.join(destinationDirectory, zipFile) # download dataset if necessary if not len(slicer.dicomDatabase.filesForSeries(self.UID)): filePath = os.path.join(destinationDirectory, zipFile) if not os.path.exists(os.path.dirname(filePath)): os.makedirs(os.path.dirname(filePath)) logging.debug('Saving download %s to %s ' % (url, filePath)) if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: slicer.util.delayDisplay('Requesting download of %s...\n' % url, 1000) urllib.urlretrieve(url, filePath) if os.path.exists(filePath) and os.path.splitext(filePath)[1]=='.zip': success = slicer.app.applicationLogic().Unzip(filePath, destinationDirectory) if not success: logging.error("Archive %s was NOT unzipped successfully." % filePath) indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, destinationDirectory, None) indexer.waitForImportFinished()
def importDirectory(self, inputDir): print('Input directory: %s' % inputDir) self.indexer = getattr(self, "indexer", None) if not self.indexer: self.indexer = ctk.ctkDICOMIndexer() self.indexer.addDirectory(self.dicomDatabase, inputDir) print('Import completed, total %s patients imported' % len(self.patients))
def importDICOMSeries(self, newFileList): indexer = ctk.ctkDICOMIndexer() newSeries = [] for currentIndex, currentFile in enumerate(newFileList, start=1): self.invokeEvent( SlicerDevelopmentToolboxEvents.NewFileIndexedEvent, [ "Indexing file %s" % currentFile, len(newFileList), currentIndex ].__str__()) slicer.app.processEvents() currentFile = os.path.join(self.intraopDICOMDirectory, currentFile) indexer.addFile(slicer.dicomDatabase, currentFile, None) series = self.makeSeriesNumberDescription(currentFile) if series not in self.seriesList: self.seriesTimeStamps[series] = self.getTime() self.seriesList.append(series) newSeries.append(series) self.loadableList[ series] = self.createLoadableFileListForSeries(series) self.seriesList = sorted( self.seriesList, key=lambda s: RegistrationResult.getSeriesNumberFromString(s)) if len(newFileList): self.verifyPatientIDEquality(newFileList) self.invokeEvent(self.NewImageSeriesReceivedEvent, newSeries.__str__())
def TestSection_02_LoadInputData(self): indexer = ctk.ctkDICOMIndexer() self.assertIsNotNone( indexer ) # Import study to database indexer.addDirectory( slicer.dicomDatabase, self.dicomDataDir ) indexer.waitForImportFinished() self.assertEqual( len(slicer.dicomDatabase.patients()), 1 ) self.assertIsNotNone( slicer.dicomDatabase.patients()[0] ) # Choose first patient from the patient list patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [slicer.dicomDatabase.seriesForStudy(study) for study in studies] seriesUIDs = [uid for uidList in series for uid in uidList] self.dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') self.dicomWidget.detailsPopup.examineForLoading() loadables = self.dicomWidget.detailsPopup.loadableTable.loadables self.assertTrue( len(loadables) > 0 ) # Load into Slicer self.dicomWidget.detailsPopup.loadCheckedLoadables() self.inputSegmentationNode = slicer.util.getNode('vtkMRMLSegmentationNode1') self.assertIsNotNone(self.inputSegmentationNode) # Change master representation to closed surface (so that conversion is possible when adding segment) self.inputSegmentationNode.GetSegmentation().SetMasterRepresentationName(self.closedSurfaceReprName)
def loadLoadables(loadablesByPlugin, messages=None, progressCallback=None): """Load each DICOM loadable item. Returns loaded node IDs. """ # Find a plugin for each loadable that will load it # (the last plugin that has that loadable selected wins) selectedLoadables = {} for plugin in loadablesByPlugin: for loadable in loadablesByPlugin[plugin]: if loadable.selected: selectedLoadables[loadable] = plugin loadedNodeIDs = [] @vtk.calldata_type(vtk.VTK_OBJECT) def onNodeAdded(caller, event, calldata): node = calldata if not isinstance(node, slicer.vtkMRMLStorageNode) and not isinstance(node, slicer.vtkMRMLDisplayNode): loadedNodeIDs.append(node.GetID()) sceneObserverTag = slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded) for step, (loadable, plugin) in enumerate(selectedLoadables.items(), start=1): if progressCallback: cancelled = progressCallback(loadable.name, step*100/len(selectedLoadables)) if cancelled: break try: loadSuccess = plugin.load(loadable) except: loadSuccess = False import traceback logging.error("DICOM plugin failed to load '" + loadable.name + "' as a '" + plugin.loadType + "'.\n" + traceback.format_exc()) if (not loadSuccess) and (messages is not None): messages.append('Could not load: %s as a %s' % (loadable.name, plugin.loadType)) cancelled = False try: # DICOM reader plugins (for example, in PETDICOM extension) may generate additional DICOM files # during loading. These must be added to the database. for derivedItem in loadable.derivedItems: indexer = ctk.ctkDICOMIndexer() if progressCallback: cancelled = progressCallback("{0} ({1})".format(loadable.name, derivedItem), step*100/len(selectedLoadables)) if cancelled: break indexer.addFile(slicer.dicomDatabase, derivedItem) except AttributeError: # no derived items or some other attribute error pass if cancelled: break slicer.mrmlScene.RemoveObserver(sceneObserverTag) return loadedNodeIDs
def TestSection_02_LoadInputData(self): indexer = ctk.ctkDICOMIndexer() self.assertIsNotNone(indexer) # Import study to database indexer.addDirectory(slicer.dicomDatabase, self.dicomDataDir) indexer.waitForImportFinished() self.assertEqual(len(slicer.dicomDatabase.patients()), 1) self.assertIsNotNone(slicer.dicomDatabase.patients()[0]) # Choose first patient from the patient list patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [ slicer.dicomDatabase.seriesForStudy(study) for study in studies ] seriesUIDs = [uid for uidList in series for uid in uidList] self.dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') self.dicomWidget.detailsPopup.examineForLoading() loadables = self.dicomWidget.detailsPopup.loadableTable.loadables self.assertTrue(len(loadables) > 0) # Load into Slicer self.dicomWidget.detailsPopup.loadCheckedLoadables() self.inputSegmentationNode = slicer.util.getNode( 'vtkMRMLSegmentationNode1') self.assertIsNotNone(self.inputSegmentationNode) # Change master representation to closed surface (so that conversion is possible when adding segment) self.inputSegmentationNode.GetSegmentation( ).SetMasterRepresentationName(self.closedSurfaceReprName)
def __init__(self, database, fileToBeAddedCallback=None, fileAddedCallback=None): super(DICOMListener, self).__init__() self.dicomDatabase = database self.indexer = ctk.ctkDICOMIndexer() self.fileToBeAddedCallback = fileToBeAddedCallback self.fileAddedCallback = fileAddedCallback self.lastFileAdded = None settings = qt.QSettings() dir = settings.value('DatabaseDirectory') if not dir: raise (UserWarning( 'Database directory not set: cannot start DICOMListener')) if not os.path.exists(dir): os.mkdir(dir) self.incomingDir = dir + "/incoming" if not os.path.exists(self.incomingDir): os.mkdir(self.incomingDir) self.port = settings.value('StoragePort') if not self.port: settings.setValue('StoragePort', '11112') self.port = settings.value('StoragePort')
def switchToDICOMModule(self): self.delayDisplay('Importing DICOM') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') dicomFilesDirectory = slicer.app.temporaryPath + '/DICOMFilesDirectory' indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished()
def section_LoadDicomData(self): try: # Download and unzip test CT DICOM data import urllib downloads = ( ('http://slicer.kitware.com/midas3/download/item/137843/TestDicomCT.zip', self.dicomZipFilePath), ) downloaded = 0 for url,filePath in downloads: if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: if downloaded == 0: self.delayDisplay('Downloading input data to folder\n' + self.dicomZipFilePath + '.\n\n It may take a few minutes...',self.delayMs) print('Requesting download from %s...' % (url)) urllib.urlretrieve(url, filePath) downloaded += 1 else: self.delayDisplay('Input data has been found in folder ' + self.dicomZipFilePath, self.delayMs) if downloaded > 0: self.delayDisplay('Downloading input data finished',self.delayMs) numOfFilesInDicomDataDir = len([name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name)]) if (numOfFilesInDicomDataDir != self.expectedNumOfFilesInDicomDataDir): slicer.app.applicationLogic().Unzip(self.dicomZipFilePath, self.dicomDataDir) self.delayDisplay("Unzipping done",self.delayMs) numOfFilesInDicomDataDirTest = len([name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name)]) self.assertEqual( numOfFilesInDicomDataDirTest, self.expectedNumOfFilesInDicomDataDir ) # Open test database and empty it with DICOMUtils.TemporaryDICOMDatabase(self.dicomDatabaseDir, True) as db: self.assertTrue( db.isOpen ) self.assertEqual( slicer.dicomDatabase, db) # Import test data in database indexer = ctk.ctkDICOMIndexer() self.assertIsNotNone( indexer ) indexer.addDirectory( slicer.dicomDatabase, self.dicomDataDir ) self.assertEqual( len(slicer.dicomDatabase.patients()), 1 ) self.assertIsNotNone( slicer.dicomDatabase.patients()[0] ) # Load test data numOfScalarVolumeNodesBeforeLoad = len( slicer.util.getNodes('vtkMRMLScalarVolumeNode*') ) numOfSubjectHierarchyNodesBeforeLoad = len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*') ) patient = slicer.dicomDatabase.patients()[0] DICOMUtils.loadPatientByUID(patient) self.assertEqual( len( slicer.util.getNodes('vtkMRMLScalarVolumeNode*') ), numOfScalarVolumeNodesBeforeLoad + 1 ) self.assertEqual( len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*') ), numOfSubjectHierarchyNodesBeforeLoad + 3 ) except Exception, e: import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e),self.delayMs*2)
def section_LoadDicomData(self): try: # Download and unzip test CT DICOM data import urllib downloads = ( ('http://slicer.kitware.com/midas3/download/item/137843/TestDicomCT.zip', self.dicomZipFilePath), ) downloaded = 0 for url,filePath in downloads: if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: if downloaded == 0: self.delayDisplay('Downloading input data to folder\n' + self.dicomZipFilePath + '.\n\n It may take a few minutes...',self.delayMs) print('Requesting download from %s...' % (url)) urllib.urlretrieve(url, filePath) downloaded += 1 else: self.delayDisplay('Input data has been found in folder ' + self.dicomZipFilePath, self.delayMs) if downloaded > 0: self.delayDisplay('Downloading input data finished',self.delayMs) numOfFilesInDicomDataDir = len([name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name)]) if (numOfFilesInDicomDataDir != self.expectedNumOfFilesInDicomDataDir): slicer.app.applicationLogic().Unzip(self.dicomZipFilePath, self.dicomDataDir) self.delayDisplay("Unzipping done",self.delayMs) numOfFilesInDicomDataDirTest = len([name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name)]) self.assertEqual( numOfFilesInDicomDataDirTest, self.expectedNumOfFilesInDicomDataDir ) # Open test database and empty it with DICOMUtils.TemporaryDICOMDatabase(self.dicomDatabaseDir, True) as db: self.assertTrue( db.isOpen ) self.assertEqual( slicer.dicomDatabase, db) # Import test data in database indexer = ctk.ctkDICOMIndexer() self.assertIsNotNone( indexer ) indexer.addDirectory( slicer.dicomDatabase, self.dicomDataDir ) self.assertEqual( len(slicer.dicomDatabase.patients()), 1 ) self.assertIsNotNone( slicer.dicomDatabase.patients()[0] ) # Load test data numOfScalarVolumeNodesBeforeLoad = len( slicer.util.getNodes('vtkMRMLScalarVolumeNode*') ) self.assertEqual( len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*') ), 1 ) patient = slicer.dicomDatabase.patients()[0] DICOMUtils.loadPatientByUID(patient) self.assertEqual( len( slicer.util.getNodes('vtkMRMLScalarVolumeNode*') ), numOfScalarVolumeNodesBeforeLoad + 1 ) self.assertEqual( len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*') ), 1 ) except Exception, e: import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e),self.delayMs*2)
def addFilesToDatabase(self): self.progress('Adding to DICOM Database...') indexer = ctk.ctkDICOMIndexer() destinationDir = os.path.dirname(slicer.dicomDatabase.databaseFilename) if self.sdbFile: files = [self.sdbFile] else: files = glob.glob('%s/*' % self.dicomDirectory) for file in files: indexer.addFile( slicer.dicomDatabase, file, destinationDir ) slicer.util.showStatusMessage("Loaded: %s" % file, 1000)
def addFilesToDatabase(self): self.progress('Adding to DICOM Database...') indexer = ctk.ctkDICOMIndexer() destinationDir = os.path.dirname(slicer.dicomDatabase.databaseFilename) if self.sdbFile: files = [self.sdbFile] else: files = glob.glob('%s/*' % self.dicomDirectory) for file in files: indexer.addFile(slicer.dicomDatabase, file, destinationDir) slicer.util.showStatusMessage("Loaded: %s" % file, 1000)
def TestSection_2ImportStudy(self): self.delayDisplay("Import study",self.delayMs) indexer = ctk.ctkDICOMIndexer() self.assertIsNotNone( indexer ) # Import study to database indexer.addDirectory( slicer.dicomDatabase, self.dataDir ) indexer.waitForImportFinished() self.assertEqual( len(slicer.dicomDatabase.patients()), 1 ) self.assertIsNotNone( slicer.dicomDatabase.patients()[0] )
def addFilesToDatabase(self): if not slicer.dicomDatabase.isOpen: slicer.util.warningDisplay("DICOM database is not open, so the (otherwise successfully) exported dataset cannot be imported back") return self.progress('Adding to DICOM Database...') indexer = ctk.ctkDICOMIndexer() destinationDir = os.path.dirname(slicer.dicomDatabase.databaseFilename) if self.sdbFile: files = [self.sdbFile] else: files = glob.glob('%s/*' % self.dicomDirectory) indexer.addListOfFiles( slicer.dicomDatabase, files, True)
def TestSection_ImportStudy(self): # slicer.util.delayDisplay("Import study",self.delayMs) logging.info("Import study") indexer = ctk.ctkDICOMIndexer() self.assertIsNotNone(indexer) # Import study to database indexer.addDirectory(slicer.dicomDatabase, self.dataDir) indexer.waitForImportFinished() self.assertEqual(len(slicer.dicomDatabase.patients()), 1) self.assertIsNotNone(slicer.dicomDatabase.patients()[0])
def addFilesToDatabase(self): if not slicer.dicomDatabase: slicer.util.warningDisplay("No DICOM database is set, so the (otherwise successfully) exported dataset cannot be imported back") return self.progress('Adding to DICOM Database...') indexer = ctk.ctkDICOMIndexer() destinationDir = os.path.dirname(slicer.dicomDatabase.databaseFilename) if self.sdbFile: files = [self.sdbFile] else: files = glob.glob('%s/*' % self.dicomDirectory) for file in files: indexer.addFile( slicer.dicomDatabase, file, destinationDir )
def importStudy(self, inputDir, progressCallback=None): self.progressCallback = progressCallback self.canceled = False print('Database location: '+self.dicomDatabaseDir) print('FIXME: revert back to the original DB location when done!') self.openDatabase() print('Input directory: ' + inputDir) if not self.indexer: self.indexer = ctk.ctkDICOMIndexer() self.indexer.connect("progress(int)", self.updateProgress) self.indexer.addDirectory(slicer.dicomDatabase, inputDir) self.patients = slicer.dicomDatabase.patients() print('Import completed, total '+str(len(slicer.dicomDatabase.patients()))+' patients imported')
def _importStudy(self, inputDir, progressCallback=None): self.progressCallback = progressCallback logging.debug('Input directory: %s' % inputDir) self.indexer = getattr(self, "indexer", None) if not self.indexer: self.indexer = ctk.ctkDICOMIndexer() def updateProgress(progress): if self.progressCallback: self.progressCallback(windowTitle='DICOMIndexer', labelText='Processing files', value=progress) self.indexer.connect("progress(int)", updateProgress) self.indexer.addDirectory(self.dicomDatabase, inputDir) logging.debug('Import completed, total %s patients imported' % len(self.patients))
def __init__(self, database, fileToBeAddedCallback=None, fileAddedCallback=None): self.dicomDatabase = database self.indexer = ctk.ctkDICOMIndexer() self.fileToBeAddedCallback = fileToBeAddedCallback self.fileAddedCallback = fileAddedCallback self.lastFileAdded = None settings = qt.QSettings() databaseDirectory = settings.value('DatabaseDirectory') if not databaseDirectory: raise UserWarning('Database directory not set: cannot start DICOMListener') if not os.path.exists(databaseDirectory): os.mkdir(databaseDirectory) incomingDir = databaseDirectory + "/incoming" super(DICOMListener,self).__init__(incomingDataDir=incomingDir)
def saveReport(self, completed=False): self._metadata = self.retrieveMetaDataFromUser() if not self._metadata: return False, "Saving process canceled. Meta-information was not confirmed by user." try: dcmSegPath = self.createSEG() dcmSRPath = self.createDICOMSR(dcmSegPath, completed) if dcmSegPath and dcmSRPath: indexer = ctk.ctkDICOMIndexer() indexer.addFile(slicer.dicomDatabase, dcmSegPath, "copy") indexer.addFile(slicer.dicomDatabase, dcmSRPath, "copy") except (RuntimeError, ValueError, AttributeError) as exc: return False, exc.message finally: self.cleanupTemporaryData() return True, None
def saveReport(self, completed=False): self._metadata = self.retrieveMetaDataFromUser() if not self._metadata: return False, "Saving process canceled. Meta-information was not confirmed by user." try: dcmSegPath = self.createSEG() dcmSRPath = self.createDICOMSR(dcmSegPath, completed) if dcmSegPath and dcmSRPath: indexer = ctk.ctkDICOMIndexer() indexer.addFile(slicer.dicomDatabase, dcmSegPath, "copy") indexer.addFile(slicer.dicomDatabase, dcmSRPath, "copy") except (RuntimeError, ValueError, AttributeError) as exc: return False, exc.args finally: self.cleanupTemporaryData() return True, None
def importDicom(dicomDataDir, dicomDatabase=None, copyFiles=False): """ Import DICOM files from folder into Slicer database """ try: indexer = ctk.ctkDICOMIndexer() assert indexer is not None if dicomDatabase is None: dicomDatabase = slicer.dicomDatabase indexer.addDirectory(dicomDatabase, dicomDataDir, copyFiles) indexer.waitForImportFinished() except Exception as e: import traceback traceback.print_exc() logging.error('Failed to import DICOM folder ' + dicomDataDir) return False return True
def importDicom(dicomDataDir, dicomDatabase=None): """ Import DICOM files from folder into Slicer database """ try: slicer.util.selectModule('DICOM') dicomWidget = slicer.modules.dicom.widgetRepresentation().self() indexer = ctk.ctkDICOMIndexer() assert indexer is not None indexer.addDirectory(slicer.dicomDatabase, dicomDataDir) indexer.waitForImportFinished() except Exception, e: import traceback traceback.print_exc() logging.error('Failed to import DICOM folder ' + dicomDataDir) return False
def __init__(self, database, fileToBeAddedCallback=None, fileAddedCallback=None): self.dicomDatabase = database self.indexer = ctk.ctkDICOMIndexer() self.fileToBeAddedCallback = fileToBeAddedCallback self.fileAddedCallback = fileAddedCallback self.lastFileAdded = None databaseDirectory = self.dicomDatabase.databaseDirectory if not databaseDirectory: raise UserWarning( 'Database directory not set: cannot start DICOMListener') if not os.path.exists(databaseDirectory): os.mkdir(databaseDirectory) incomingDir = databaseDirectory + "/incoming" super(DICOMListener, self).__init__(incomingDataDir=incomingDir)
def importDicom(dicomDataDir, dicomDatabase=None): """ Import DICOM files from folder into Slicer database """ try: slicer.util.selectModule('DICOM') dicomWidget = slicer.modules.dicom.widgetRepresentation().self() indexer = ctk.ctkDICOMIndexer() assert indexer is not None if dicomDatabase is None: dicomDatabase = slicer.dicomDatabase indexer.addDirectory( dicomDatabase, dicomDataDir ) indexer.waitForImportFinished() except Exception, e: import traceback traceback.print_exc() logging.error('Failed to import DICOM folder ' + dicomDataDir) return False
def __init__(self, database, fileToBeAddedCallback=None, fileAddedCallback=None): self.dicomDatabase = database self.indexer = ctk.ctkDICOMIndexer() # Enable background indexing to improve performance. self.indexer.backgroundImportEnabled = True self.fileToBeAddedCallback = fileToBeAddedCallback self.fileAddedCallback = fileAddedCallback self.lastFileAdded = None # A timer is used to ensure that indexing is completed after new files come in, # but without enforcing completing the indexing after each file (because # waiting for indexing to be completed has an overhead). autoUpdateDelaySec = 10.0 self.delayedAutoUpdateTimer = qt.QTimer() self.delayedAutoUpdateTimer.setSingleShot(True) self.delayedAutoUpdateTimer.interval = autoUpdateDelaySec * 1000 self.delayedAutoUpdateTimer.connect('timeout()', self.completeIncomingFilesIndexing) # List of received files that are being indexed self.incomingFiles = [] # After self.incomingFiles reaches maximumIncomingFiles, indexing will be forced # to limit disk space usage (until indexing is completed, the file is present both # in the incoming folder and in the database) and make sure some updates are visible # in the DICOM browser (even if files are continuously coming in). # Smaller values result in more frequent updates, slightly less disk space usage, # slightly slower import. self.maximumIncomingFiles = 400 databaseDirectory = self.dicomDatabase.databaseDirectory if not databaseDirectory: raise UserWarning( 'Database directory not set: cannot start DICOMListener') if not os.path.exists(databaseDirectory): os.mkdir(databaseDirectory) incomingDir = databaseDirectory + "/incoming" super().__init__(incomingDataDir=incomingDir)
def generateReport(self, obj): """ Generates a qiicrx DICOM report from an existing studyID and adds resulting series to DICOMDatabase Args: obj: studyID or list of series UIDs that is used as the input for creating a qiicrx DICOM report Todo: add option to add predecessor """ if type(obj) is str: seriesUIDs = DICOMQIICRXLoaderPluginClass.getEligibleSeriesForStudy( obj) if not seriesUIDs: raise StudyNotEligibleError elif type(obj) in [tuple, list]: seriesUIDs = obj else: raise ValueError("Value of type %s is not supported" % type(obj)) try: params = self._generateJSON(seriesUIDs) except StudyNotEligibleError: logging.error("Series '%s' is not eligible for PIRADS reading" % seriesUIDs) return outputSRPath = os.path.join(self.tempDir, "sr.dcm") params.update({"outputFileName": outputSRPath}) logging.debug(params) cliNode = slicer.cli.run(slicer.modules.qiicrxsr, None, params, wait_for_completion=True) if cliNode.GetStatusString() != 'Completed': raise Exception("qiicrxsr CLI did not complete cleanly") else: indexer = ctk.ctkDICOMIndexer() indexer.addFile(self.db, outputSRPath, "copy")
def __init__(self,database,fileToBeAddedCallback=None,fileAddedCallback=None): super(DICOMListener,self).__init__() self.dicomDatabase = database self.indexer = ctk.ctkDICOMIndexer() self.fileToBeAddedCallback = fileToBeAddedCallback self.fileAddedCallback = fileAddedCallback self.lastFileAdded = None settings = qt.QSettings() dir = settings.value('DatabaseDirectory') if not dir: raise( UserWarning('Database directory not set: cannot start DICOMListener') ) if not os.path.exists(dir): os.mkdir(dir) self.incomingDir = dir + "/incoming" if not os.path.exists(self.incomingDir): os.mkdir(self.incomingDir) self.port = settings.value('StoragePort') if not self.port: settings.setValue('StoragePort', '11112') self.port = settings.value('StoragePort')
def _loadTestData_WithPETDICOMExtension(self): """ load SUV normalized PET scan from DICOM fileassuming Slicer-PETDICOM extension is installed and enabled """ from DICOMLib import DICOMUtils import urllib data = { 'PETVolume': { 'UID': '1.3.6.1.4.1.14519.5.2.1.2744.7002.886851941687931416391879144903', 'url': 'http://slicer.kitware.com/midas3/download/item/257234/QIN-HEADNECK-01-0139-PET.zip', 'zipFile': 'QIN-HEADNECK-01-0139-PET.zip', 'SUVNormalizationFactor': 0.00040166400000000007 } } destinationDirectory = self.tempDataDir for key, value in data.iteritems(): # download data if necessary UID = value['UID'] if not len(slicer.dicomDatabase.filesForSeries(UID)): url = value['url'] zipFile = value['zipFile'] filePath = os.path.join(destinationDirectory, zipFile) if not os.path.exists(os.path.dirname(filePath)): os.makedirs(os.path.dirname(filePath)) logging.debug('Saving download %s to %s ' % (url, filePath)) if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: slicer.util.delayDisplay('Requesting download of %s...\n' % url, 1000) urllib.urlretrieve(url, filePath) if os.path.exists(filePath) and os.path.splitext(filePath)[1]=='.zip': success = slicer.app.applicationLogic().Unzip(filePath, destinationDirectory) if not success: logging.error("Archive %s was NOT unzipped successfully." % filePath) indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, destinationDirectory, None) indexer.waitForImportFinished() # load dataset success=DICOMUtils.loadSeriesByUID([data['PETVolume']['UID']]) if not success: logging.error("Unable to load dicom data %s\n." % data['PETVolume']['UID']) return slicer.mrmlScene.GetFirstNodeByClass('vtkMRMLScalarVolumeNode')
def importIntoDICOMDatabase(dicomFilesDirectory): indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished()
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)
def proceedWithReferencedLoadablesSelection(self): # each check box corresponds to a referenced loadable # that was selected by examine; if the user confirmed # that reference should be loaded, add it to the self.loadablesByPlugin # dictionary if self.referencesDialog: children = self.referencesDialog.children() loadableCnt = 0 for plugin in self.referencedLoadables: for loadable in self.referencedLoadables[plugin]: if loadable.selected: if children[loadableCnt+2].checked: self.loadablesByPlugin[plugin].append(loadable) self.referencesDialog.close() self.referencesDialog = None loadableCount = 0 for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if loadable.selected: loadableCount += 1 self.progress = slicer.util.createProgressDialog(parent=self.window, value=0, maximum=loadableCount) step = 0 loadingResult = '' loadedNodeIDs = [] @vtk.calldata_type(vtk.VTK_OBJECT) def onNodeAdded(caller, event, calldata): node = calldata if isinstance(node, slicer.vtkMRMLVolumeNode): loadedNodeIDs.append(node.GetID()) self.addObserver(slicer.mrmlScene, slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded); for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if self.progress.wasCanceled: break slicer.app.processEvents() self.progress.setValue(step) slicer.app.processEvents() if loadable.selected: self.progress.labelText = '\nLoading %s' % loadable.name slicer.app.processEvents() if not plugin.load(loadable): loadingResult = '%s\nCould not load: %s as a %s' % (loadingResult,loadable.name,plugin.loadType) step += 1 self.progress.setValue(step) slicer.app.processEvents() try: for derivedItem in loadable.derivedItems: indexer = ctk.ctkDICOMIndexer() self.progress.labelText = '\nIndexing %s' % derivedItem slicer.app.processEvents() indexer.addFile(slicer.dicomDatabase, derivedItem) except AttributeError: # no derived items or some other attribute error pass self.removeObserver(slicer.mrmlScene, slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded); loadedFileParameters = {} loadedFileParameters['nodeIDs'] = loadedNodeIDs slicer.app.ioManager().emitNewFileLoaded(loadedFileParameters) self.progress.close() self.progress = None if loadingResult: slicer.util.warningDisplay(loadingResult, windowTitle='DICOM loading') if not self.browserPersistent: self.close() return
def test_SEGExporterSelfTest1(self): """ Test DICOM import, segmentation, export """ self.messageDelay = 50 import os self.delayDisplay("Starting the DICOM SEG Export test") # # first, get the data - a zip file of dicom data # filePath = self.logic.downloadSampleData() self.delayDisplay('Finished with download\n') self.delayDisplay("Unzipping") dicomFilesDirectory = self.logic.unzipSampleData(filePath) try: self.delayDisplay("Switching to temp database directory") tempDatabaseDirectory = slicer.app.temporaryPath + '/tempDICOMDatabase' import shutil try: shutil.rmtree(tempDatabaseDirectory) except OSError: pass qt.QDir().mkpath(tempDatabaseDirectory) if slicer.dicomDatabase: originalDatabaseDirectory = os.path.split(slicer.dicomDatabase.databaseFilename)[0] else: originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', tempDatabaseDirectory) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(tempDatabaseDirectory) self.delayDisplay('Importing DICOM') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') self.logic.importIntoDICOMDatabase(dicomFilesDirectory) dicomWidget.detailsPopup.open() # load the data by series UID mrHeadSeriesUID = "2.16.840.1.113662.4.4168496325.1025306170.548651188813145058" dicomWidget.detailsPopup.offerLoadables(mrHeadSeriesUID, 'Series') dicomWidget.detailsPopup.examineForLoading() self.delayDisplay('Loading Selection') dicomWidget.detailsPopup.loadCheckedLoadables() # # create a label map and set it for editing # masterNode = slicer.util.getNode('2: SAG*') volumesLogic = slicer.modules.volumes.logic() mergeNode = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, masterNode, masterNode.GetName() + '-label' ) mergeNode.GetDisplayNode().SetAndObserveColorNodeID('vtkMRMLColorTableNodeFileGenericAnatomyColors.txt') selectionNode = slicer.app.applicationLogic().GetSelectionNode() selectionNode.SetReferenceActiveVolumeID( masterNode.GetID() ) selectionNode.SetReferenceActiveLabelVolumeID( mergeNode.GetID() ) slicer.app.applicationLogic().PropagateVolumeSelection(0) # # go to the editor and do some drawing # slicer.util.selectModule('Editor') import EditorLib from EditorLib.EditUtil import EditUtil parameterNode = EditUtil.getParameterNode() parameterNode.SetParameter("LabelEffect,paintThreshold", "1") parameterNode.SetParameter("LabelEffect,paintThresholdMin", "70.0") parameterNode.SetParameter("LabelEffect,paintThresholdMax", "279.75") parameterNode.SetParameter("PaintEffect,radius", "40") parameterNode.SetParameter("PaintEffect,sphere", "1") self.delayDisplay("Paint some things") parameterNode = EditUtil.getParameterNode() lm = slicer.app.layoutManager() paintEffect = EditorLib.PaintEffectOptions() paintEffect.setMRMLDefaults() paintEffect.__del__() sliceWidget = lm.sliceWidget('Red') paintTool = EditorLib.PaintEffectTool(sliceWidget) EditUtil.setLabel(1) paintTool.paintAddPoint(100,100) paintTool.paintApply() EditUtil.setLabel(2) paintTool.paintAddPoint(200,200) paintTool.paintApply() paintTool.cleanup() paintTool = None # save these to compare with the one we read back originalSegmentationArray = slicer.util.array(mergeNode.GetID()) originalSegmentationNodeCopy = slicer.vtkMRMLLabelMapVolumeNode() originalSegmentationNodeCopy.CopyOrientation(mergeNode) # export the volumes into a SEG tempSEGDirectory = slicer.app.temporaryPath + '/tempDICOMSEG' qt.QDir().mkpath(tempSEGDirectory) segFilePath = os.path.join(tempSEGDirectory, "test.SEG.dcm") self.delayDisplay('spliting...', 200) EditUtil.splitPerStructureVolumes(masterNode, mergeNode) self.delayDisplay('exporting...', 200) EditUtil.exportAsDICOMSEG(masterNode) # close scene re-load the input data and SEG slicer.mrmlScene.Clear(0) indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, tempSEGDirectory, None) indexer.waitForImportFinished() mrHeadStudyUID = "2.16.840.1.113662.4.4168496325.1025305873.7118351817185979330" dicomWidget.detailsPopup.offerLoadables(mrHeadStudyUID, 'Study') dicomWidget.detailsPopup.examineForLoading() self.delayDisplay('Loading Selection') dicomWidget.detailsPopup.loadCheckedLoadables() # confirm that segmentations are correctly reloaded headLabelName = '2: SAG/RF-FAST/VOL/FLIP 30-label' reloadedLabel = slicer.util.getNode(headLabelName) reloadedSegmentationArray = slicer.util.array(reloadedLabel.GetID()) import numpy self.assertTrue(numpy.alltrue(originalSegmentationArray == reloadedSegmentationArray)) geometryWarnings = volumesLogic.CompareVolumeGeometry(mergeNode, reloadedLabel) print(geometryWarnings) self.assertTrue(geometryWarnings == '') # re-export # close scene re-load the input data and SEG # confirm that segmentations are available again as per-structure volumes self.delayDisplay('Test passed!') except Exception, e: import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e))
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))
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", "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", "expectedFailures": ["GDCM", "Archetype"], "voxelValueQuantity": "(110852, DCM, \"MR signal intensity\")", "voxelValueUnits": "(1, UCUM, \"no units\")" }, { "url": "http://slicer.kitware.com/midas3/download?items=294857", "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'])[0] self.delayDisplay('Finished with download') # # insert the data into th database # 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() # # select the series # detailsPopup = slicer.modules.DICOMWidget.detailsPopup detailsPopup.open() # load the data by series UID detailsPopup.offerLoadables(dataset['seriesUID'], 'Series') detailsPopup.examineForLoading() loadable = detailsPopup.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 = 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, e: import traceback traceback.print_exc() self.delayDisplay('%s Test caused exception!\n' % dataset['name'] + str(e)) testPass = False
def test_Part1DICOM(self): """ Test the DICOM loading of sample testing data """ testPass = True import os, json self.delayDisplay("Starting the DICOM test", 100) referenceData = json.JSONDecoder().decode('''[ { "url": "http://slicer.kitware.com/midas3/download/item/292839/Mouse-MR-example-where-GDCM_fails.zip", "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", "expectedFailures": ["GDCM", "Archetype"] }, { "url": "http://slicer.kitware.com/midas3/download/item/294857/deidentifiedMRHead-dcm-one-series.zip", "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": [] } ]''') # 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", 100) for dataset in referenceData: try: filePath = slicer.app.temporaryPath + '/' + dataset['fileName'] if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: self.delayDisplay('Requesting download %s from %s...\n' % (dataset['fileName'], dataset['url']), 100) urllib.urlretrieve(dataset['url'], filePath) self.delayDisplay('Finished with download\n', 100) self.delayDisplay("Unzipping", 100) dicomFilesDirectory = slicer.app.temporaryPath + dataset['name'] qt.QDir().mkpath(dicomFilesDirectory) slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory) # # insert the data into th database # self.delayDisplay("Switching to temp database directory", 100) originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase') self.delayDisplay('Importing DICOM', 100) mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished() # # selct the series # detailsPopup = slicer.modules.DICOMWidget.detailsPopup detailsPopup.open() # load the data by series UID detailsPopup.offerLoadables(dataset['seriesUID'],'Series') detailsPopup.examineForLoading() loadable = detailsPopup.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, 100) 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 # # for each approach that loaded as expected, compare the volumes # to ensure they match in terms of pixel data and metadata # failedComparisons = {} approachesThatLoaded = 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'], 200) except Exception, e: import traceback traceback.print_exc() self.delayDisplay('%s Test caused exception!\n' % dataset['name'] + str(e), 2000) testPass = False
def importStudy(dicomDataDir): indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomDataDir) indexer.waitForImportFinished()
def test_SEGExporterSelfTest1(self): """ Test DICOM import, segmentation, export """ self.messageDelay = 50 import os self.delayDisplay("Starting the DICOM SEG Export test") # # first, get the data - a zip file of dicom data # import urllib downloads = (( 'http://slicer.kitware.com/midas3/download/item/220834/PieperMRHead.zip', 'PieperMRHead.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") tempDatabaseDirectory = slicer.app.temporaryPath + '/tempDICOMDatabase' import shutil shutil.rmtree(tempDatabaseDirectory) qt.QDir().mkpath(tempDatabaseDirectory) if slicer.dicomDatabase: originalDatabaseDirectory = os.path.split( slicer.dicomDatabase.databaseFilename)[0] else: originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', tempDatabaseDirectory) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(tempDatabaseDirectory) self.delayDisplay('Importing DICOM') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished() dicomWidget.detailsPopup.open() # load the data by series UID mrHeadSeriesUID = "2.16.840.1.113662.4.4168496325.1025306170.548651188813145058" dicomWidget.detailsPopup.offerLoadables(mrHeadSeriesUID, 'Series') dicomWidget.detailsPopup.examineForLoading() self.delayDisplay('Loading Selection') dicomWidget.detailsPopup.loadCheckedLoadables() # # create a label map and set it for editing # masterNode = slicer.util.getNode('2: SAG*') volumesLogic = slicer.modules.volumes.logic() mergeNode = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, masterNode, masterNode.GetName() + '-label') mergeNode.GetDisplayNode().SetAndObserveColorNodeID( 'vtkMRMLColorTableNodeFileGenericAnatomyColors.txt') selectionNode = slicer.app.applicationLogic().GetSelectionNode() selectionNode.SetReferenceActiveVolumeID(masterNode.GetID()) selectionNode.SetReferenceActiveLabelVolumeID(mergeNode.GetID()) slicer.app.applicationLogic().PropagateVolumeSelection(0) # # go to the editor and do some drawing # slicer.util.selectModule('Editor') import EditorLib from EditorLib.EditUtil import EditUtil parameterNode = EditUtil.getParameterNode() parameterNode.SetParameter("LabelEffect,paintThreshold", "1") parameterNode.SetParameter("LabelEffect,paintThresholdMin", "70.0") parameterNode.SetParameter("LabelEffect,paintThresholdMax", "279.75") parameterNode.SetParameter("PaintEffect,radius", "40") parameterNode.SetParameter("PaintEffect,sphere", "1") self.delayDisplay("Paint some things") parameterNode = EditUtil.getParameterNode() lm = slicer.app.layoutManager() paintEffect = EditorLib.PaintEffectOptions() paintEffect.setMRMLDefaults() paintEffect.__del__() sliceWidget = lm.sliceWidget('Red') paintTool = EditorLib.PaintEffectTool(sliceWidget) EditUtil.setLabel(1) paintTool.paintAddPoint(100, 100) paintTool.paintApply() EditUtil.setLabel(2) paintTool.paintAddPoint(200, 200) paintTool.paintApply() paintTool.cleanup() paintTool = None # save these to compare with the one we read back originalSegmentationArray = slicer.util.array(mergeNode.GetID()) originalSegmentationNodeCopy = slicer.vtkMRMLLabelMapVolumeNode() originalSegmentationNodeCopy.CopyOrientation(mergeNode) # export the volumes into a SEG tempSEGDirectory = slicer.app.temporaryPath + '/tempDICOMSEG' qt.QDir().mkpath(tempSEGDirectory) segFilePath = os.path.join(tempSEGDirectory, "test.SEG.dcm") self.delayDisplay('spliting...', 200) EditUtil.splitPerStructureVolumes(masterNode, mergeNode) self.delayDisplay('exporting...', 200) EditUtil.exportAsDICOMSEG(masterNode) # close scene re-load the input data and SEG slicer.mrmlScene.Clear(0) indexer.addDirectory(slicer.dicomDatabase, tempSEGDirectory, None) indexer.waitForImportFinished() mrHeadStudyUID = "2.16.840.1.113662.4.4168496325.1025305873.7118351817185979330" dicomWidget.detailsPopup.offerLoadables(mrHeadStudyUID, 'Study') dicomWidget.detailsPopup.examineForLoading() self.delayDisplay('Loading Selection') dicomWidget.detailsPopup.loadCheckedLoadables() # confirm that segmentations are correctly reloaded headLabelName = '2: SAG/RF-FAST/VOL/FLIP 30-label' reloadedLabel = slicer.util.getNode(headLabelName) reloadedSegmentationArray = slicer.util.array( reloadedLabel.GetID()) import numpy self.assertTrue( numpy.alltrue( originalSegmentationArray == reloadedSegmentationArray)) geometryWarnings = volumesLogic.CompareVolumeGeometry( mergeNode, reloadedLabel) print(geometryWarnings) self.assertTrue(geometryWarnings == '') # re-export # close scene re-load the input data and SEG # confirm that segmentations are available again as per-structure volumes self.delayDisplay('Test passed!') except Exception, e: import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e))
def test_AlternateReaders(self): """ Test the DICOM loading of sample testing data """ testPass = True import os, json self.delayDisplay("Starting the DICOM test", 100) referenceData = json.JSONDecoder().decode('''[ { "url": "http://slicer.kitware.com/midas3/download/item/292839/Mouse-MR-example-where-GDCM_fails.zip", "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", "expectedFailures": ["GDCM", "Archetype"], "voxelValueQuantity": "(110852, DCM, \\"MR signal intensity\\")", "voxelValueUnits": "(1, UCUM, \\"no units\\")" }, { "url": "http://slicer.kitware.com/midas3/download/item/294857/deidentifiedMRHead-dcm-one-series.zip", "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", 100) for dataset in referenceData: try: filePath = slicer.app.temporaryPath + '/' + dataset['fileName'] if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: self.delayDisplay('Requesting download %s from %s...\n' % (dataset['fileName'], dataset['url']), 100) urllib.urlretrieve(dataset['url'], filePath) self.delayDisplay('Finished with download\n', 100) self.delayDisplay("Unzipping", 100) dicomFilesDirectory = slicer.app.temporaryPath + dataset['name'] qt.QDir().mkpath(dicomFilesDirectory) slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory) # # insert the data into th database # self.delayDisplay("Switching to temp database directory", 100) originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase') self.delayDisplay('Importing DICOM', 100) mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished() # # select the series # detailsPopup = slicer.modules.DICOMWidget.detailsPopup detailsPopup.open() # load the data by series UID detailsPopup.offerLoadables(dataset['seriesUID'],'Series') detailsPopup.examineForLoading() loadable = detailsPopup.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, 100) 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 = 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'], 200) except Exception, e: import traceback traceback.print_exc() self.delayDisplay('%s Test caused exception!\n' % dataset['name'] + str(e), 2000) testPass = False
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', checksums= 'SHA256:17a4199aad03a373dab27dc17e5bfcf84fc194d0a30975b4073e5b595d43a56a' )[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)
def section_LoadDicomData(self): try: # Download and unzip test CT DICOM data import urllib downloads = (( 'http://slicer.kitware.com/midas3/download/item/137843/TestDicomCT.zip', self.dicomZipFilePath), ) downloaded = 0 for url, filePath in downloads: if not os.path.exists(filePath) or os.stat( filePath).st_size == 0: if downloaded == 0: self.delayDisplay( 'Downloading input data to folder\n' + self.dicomZipFilePath + '.\n\n It may take a few minutes...', self.delayMs) print('Requesting download from %s...' % (url)) urllib.urlretrieve(url, filePath) downloaded += 1 else: self.delayDisplay( 'Input data has been found in folder ' + self.dicomZipFilePath, self.delayMs) if downloaded > 0: self.delayDisplay('Downloading input data finished', self.delayMs) numOfFilesInDicomDataDir = len([ name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name) ]) if (numOfFilesInDicomDataDir != self.expectedNumOfFilesInDicomDataDir): slicer.app.applicationLogic().Unzip(self.dicomZipFilePath, self.dicomDataDir) self.delayDisplay("Unzipping done", self.delayMs) numOfFilesInDicomDataDirTest = len([ name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name) ]) self.assertTrue(numOfFilesInDicomDataDirTest == self.expectedNumOfFilesInDicomDataDir) # Open test database and empty it qt.QDir().mkpath(self.dicomDatabaseDir) if slicer.dicomDatabase: originalDatabaseDirectory = os.path.split( slicer.dicomDatabase.databaseFilename)[0] else: originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', self.dicomDatabaseDir) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(self.dicomDatabaseDir) self.assertTrue(slicer.dicomDatabase.isOpen) # Import test data in database indexer = ctk.ctkDICOMIndexer() self.assertTrue(indexer) indexer.addDirectory(slicer.dicomDatabase, self.dicomDataDir) self.assertTrue(len(slicer.dicomDatabase.patients()) == 1) self.assertTrue(slicer.dicomDatabase.patients()[0]) # Load test data numOfScalarVolumeNodesBeforeLoad = len( slicer.util.getNodes('vtkMRMLScalarVolumeNode*')) numOfSubjectHierarchyNodesBeforeLoad = len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*')) patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [ slicer.dicomDatabase.seriesForStudy(study) for study in studies ] seriesUIDs = [uid for uidList in series for uid in uidList] dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') dicomWidget.detailsPopup.loadCheckedLoadables() self.assertTrue( len(slicer.util.getNodes('vtkMRMLScalarVolumeNode*')) == numOfScalarVolumeNodesBeforeLoad + 1) self.assertTrue( len(slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*')) == numOfSubjectHierarchyNodesBeforeLoad + 3) if originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged( originalDatabaseDirectory) except Exception, e: import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e), self.delayMs * 2)
def ImportStudy(self, dicomDataDir): indexer = ctk.ctkDICOMIndexer() # Import study to database indexer.addDirectory(slicer.dicomDatabase, dicomDataDir) indexer.waitForImportFinished()
def section_LoadDicomData(self): try: # Download and unzip test CT DICOM data import urllib downloads = ( ('http://slicer.kitware.com/midas3/download/item/137843/TestDicomCT.zip', self.dicomZipFilePath), ) downloaded = 0 for url,filePath in downloads: if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: if downloaded == 0: self.delayDisplay('Downloading input data to folder\n' + self.dicomZipFilePath + '.\n\n It may take a few minutes...',self.delayMs) print('Requesting download from %s...' % (url)) urllib.urlretrieve(url, filePath) downloaded += 1 else: self.delayDisplay('Input data has been found in folder ' + self.dicomZipFilePath, self.delayMs) if downloaded > 0: self.delayDisplay('Downloading input data finished',self.delayMs) numOfFilesInDicomDataDir = len([name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name)]) if (numOfFilesInDicomDataDir != self.expectedNumOfFilesInDicomDataDir): slicer.app.applicationLogic().Unzip(self.dicomZipFilePath, self.dicomDataDir) self.delayDisplay("Unzipping done",self.delayMs) numOfFilesInDicomDataDirTest = len([name for name in os.listdir(self.dicomDataDir) if os.path.isfile(self.dicomDataDir + '/' + name)]) self.assertTrue( numOfFilesInDicomDataDirTest == self.expectedNumOfFilesInDicomDataDir ) # Open test database and empty it qt.QDir().mkpath(self.dicomDatabaseDir) if slicer.dicomDatabase: originalDatabaseDirectory = os.path.split(slicer.dicomDatabase.databaseFilename)[0] else: originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', self.dicomDatabaseDir) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(self.dicomDatabaseDir) self.assertTrue( slicer.dicomDatabase.isOpen ) # Import test data in database indexer = ctk.ctkDICOMIndexer() self.assertTrue( indexer ) indexer.addDirectory( slicer.dicomDatabase, self.dicomDataDir ) self.assertTrue( len(slicer.dicomDatabase.patients()) == 1 ) self.assertTrue( slicer.dicomDatabase.patients()[0] ) # Load test data numOfScalarVolumeNodesBeforeLoad = len( slicer.util.getNodes('vtkMRMLScalarVolumeNode*') ) numOfSubjectHierarchyNodesBeforeLoad = len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*') ) patient = slicer.dicomDatabase.patients()[0] studies = slicer.dicomDatabase.studiesForPatient(patient) series = [slicer.dicomDatabase.seriesForStudy(study) for study in studies] seriesUIDs = [uid for uidList in series for uid in uidList] dicomWidget.detailsPopup.offerLoadables(seriesUIDs, 'SeriesUIDList') dicomWidget.detailsPopup.loadCheckedLoadables() self.assertTrue( len( slicer.util.getNodes('vtkMRMLScalarVolumeNode*') ) == numOfScalarVolumeNodesBeforeLoad + 1 ) self.assertTrue( len( slicer.util.getNodes('vtkMRMLSubjectHierarchyNode*') ) == numOfSubjectHierarchyNodesBeforeLoad + 3 ) if originalDatabaseDirectory: dicomWidget.onDatabaseDirectoryChanged(originalDatabaseDirectory) except Exception, e: import traceback traceback.print_exc() self.delayDisplay('Test caused exception!\n' + str(e),self.delayMs*2)
def ImportStudy(self,dicomDataDir): indexer = ctk.ctkDICOMIndexer() # Import study to database indexer.addDirectory( slicer.dicomDatabase, dicomDataDir ) indexer.waitForImportFinished()
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") import SampleData dicomFilesDirectory = SampleData.downloadFromURL( fileNames='deidentifiedMRHead-dcm-one-series.zip', uris='http://slicer.kitware.com/midas3/download?items=294857')[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') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished() # # select the series # detailsPopup = slicer.modules.DICOMWidget.detailsPopup detailsPopup.open() # load the data by series UID detailsPopup.offerLoadables(seriesUID, 'Series') detailsPopup.examineForLoading() loadable = detailsPopup.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, e: import traceback traceback.print_exc() self.delayDisplay('Missing Slices Test caused exception!\n' + str(e)) testPass = False
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", 100) datasetURL = "http://slicer.kitware.com/midas3/download/item/294857/deidentifiedMRHead-dcm-one-series.zip" fileName = "deidentifiedMRHead-dcm-one-series.zip" filePath = os.path.join(slicer.app.temporaryPath,fileName) 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: if not os.path.exists(filePath) or os.stat(filePath).st_size == 0: self.delayDisplay('Requesting download %s from %s...\n' % (fileName, datasetURL), 100) urllib.urlretrieve(datasetURL, filePath) self.delayDisplay('Finished with download\n', 100) self.delayDisplay("Unzipping", 100) dicomFilesDirectory = slicer.app.temporaryPath + 'MRhead' qt.QDir().mkpath(dicomFilesDirectory) slicer.app.applicationLogic().Unzip(filePath, dicomFilesDirectory) 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", 100) originalDatabaseDirectory = DICOMUtils.openTemporaryDatabase('tempDICOMDatabase') self.delayDisplay('Importing DICOM', 100) mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished() # # select the series # detailsPopup = slicer.modules.DICOMWidget.detailsPopup detailsPopup.open() # load the data by series UID detailsPopup.offerLoadables(seriesUID,'Series') detailsPopup.examineForLoading() loadable = detailsPopup.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!', 200) except Exception, e: import traceback traceback.print_exc() self.delayDisplay('Missing Slices Test caused exception!\n' + str(e), 2000) testPass = False
def addProducedDataToDICOMDatabase(self): indexer = ctk.ctkDICOMIndexer() indexer.addFile(slicer.dicomDatabase, os.path.join(self.tempDir,'seg.dcm'), "copy") # Note: doesn't really expect a destination dir indexer.addFile(slicer.dicomDatabase, os.path.join(self.tempDir,'sr.dcm'), "copy") # Note: doesn't really expect a destination dir
def proceedWithReferencedLoadablesSelection(self): # each check box corresponds to a referenced loadable # that was selected by examine; if the user confirmed # that reference should be loaded, add it to the self.loadablesByPlugin # dictionary if self.referencesDialog: children = self.referencesDialog.children() loadableCnt = 0 for plugin in self.referencedLoadables: for loadable in self.referencedLoadables[plugin]: if loadable.selected: if children[loadableCnt+2].checked: self.loadablesByPlugin[plugin].append(loadable) self.referencesDialog.close() self.referencesDialog = None loadableCount = 0 for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if loadable.selected: loadableCount += 1 self.progress = qt.QProgressDialog(self.window) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(loadableCount) step = 0 loadingResult = '' loadedNodeIDs = [] @vtk.calldata_type(vtk.VTK_OBJECT) def onNodeAdded(caller, event, calldata): node = calldata if isinstance(node, slicer.vtkMRMLVolumeNode): loadedNodeIDs.append(node.GetID()) self.addObserver(slicer.mrmlScene, slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded); for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if self.progress.wasCanceled: break slicer.app.processEvents() self.progress.setValue(step) slicer.app.processEvents() if loadable.selected: self.progress.labelText = '\nLoading %s' % loadable.name slicer.app.processEvents() if not plugin.load(loadable): loadingResult = '%s\nCould not load: %s as a %s' % (loadingResult,loadable.name,plugin.loadType) step += 1 self.progress.setValue(step) slicer.app.processEvents() try: for derivedItem in loadable.derivedItems: indexer = ctk.ctkDICOMIndexer() self.progress.labelText = '\nIndexing %s' % derivedItem slicer.app.processEvents() indexer.addFile(slicer.dicomDatabase, derivedItem) except AttributeError: # no derived items or some other attribute error pass self.removeObserver(slicer.mrmlScene, slicer.vtkMRMLScene.NodeAddedEvent, onNodeAdded); loadedFileParameters = {} loadedFileParameters['nodeIDs'] = loadedNodeIDs slicer.app.ioManager().emitNewFileLoaded(loadedFileParameters) self.progress.close() self.progress = None if loadingResult: qt.QMessageBox.warning(slicer.util.mainWindow(), 'DICOM loading', loadingResult) if not self.browserPersistent: self.close() return
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") tempDatabaseDirectory = slicer.app.temporaryPath + '/tempDICOMDatabase' qt.QDir().mkpath(tempDatabaseDirectory) if slicer.dicomDatabase: originalDatabaseDirectory = os.path.split(slicer.dicomDatabase.databaseFilename)[0] else: originalDatabaseDirectory = None settings = qt.QSettings() settings.setValue('DatabaseDirectory', tempDatabaseDirectory) dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(tempDatabaseDirectory) self.delayDisplay('Importing DICOM') mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('DICOM') indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, dicomFilesDirectory, None) indexer.waitForImportFinished() 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') self.clickAndDrag(redWidget,start=(10,10),end=(10,40)) self.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) self.clickAndDrag(redWidget,button='Right',start=(10,10),end=(10,40)) self.takeScreenshot('LoadingADICOMVolume-Zoom','Zoom',-1) threeDView = layoutManager.threeDWidget(0).threeDView() self.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() self.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))