def onDatabaseDirectoryChanged(self,databaseDirectory): if not hasattr(slicer, 'dicomDatabase') or not slicer.dicomDatabase: slicer.dicomDatabase = ctk.ctkDICOMDatabase() DICOM.setDatabasePrecacheTags(self.dicomBrowser) databaseFilepath = databaseDirectory + "/ctkDICOM.sql" messages = "" if not os.path.exists(databaseDirectory): try: os.mkdir(databaseDirectory) except OSError: messages += "Directory does not exist and cannot be created. " else: if not os.access(databaseDirectory, os.W_OK): messages += "Directory not writable. " if not os.access(databaseDirectory, os.R_OK): messages += "Directory not readable. " if messages != "": self.messageBox('The database file path "%s" cannot be used. %s\nPlease pick a different database directory using the LocalDatabase button in the DICOM Browser.' % (databaseFilepath,messages)) else: slicer.dicomDatabase.openDatabase(databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: self.messageBox('The database file path "%s" cannot be opened.\nPlease pick a different database directory using the LocalDatabase button in the DICOM Browser.' % databaseFilepath) self.dicomDatabase = None else: if self.dicomBrowser: if self.dicomBrowser.databaseDirectory != databaseDirectory: self.dicomBrowser.databaseDirectory = databaseDirectory else: settings = qt.QSettings() settings.setValue('DatabaseDirectory', databaseDirectory) settings.sync() if slicer.dicomDatabase: slicer.app.setDICOMDatabase(slicer.dicomDatabase)
def onDatabaseDirectoryChanged(self, databaseDirectory): if not hasattr(slicer, 'dicomDatabase') or not slicer.dicomDatabase: slicer.dicomDatabase = ctk.ctkDICOMDatabase() self.setDatabasePrecacheTags() databaseFilepath = databaseDirectory + "/ctkDICOM.sql" messages = "" if not os.path.exists(databaseDirectory): messages += "Directory does not exist. " else: if not os.access(databaseDirectory, os.W_OK): messages += "Directory not writable. " if not os.access(databaseDirectory, os.R_OK): messages += "Directory not readable. " if messages != "": self.messageBox( 'The database file path "%s" cannot be used. %s\nPlease pick a different database directory using the LocalDatabase button in the DICOM Browser.' % (databaseFilepath, messages)) else: slicer.dicomDatabase.openDatabase( databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: self.messageBox( 'The database file path "%s" cannot be opened.\nPlease pick a different database directory using the LocalDatabase button in the DICOM Browser.' % databaseFilepath) self.dicomDatabase = None else: if self.dicomApp: if self.dicomApp.databaseDirectory != databaseDirectory: self.dicomApp.databaseDirectory = databaseDirectory else: settings = qt.QSettings() settings.setValue('DatabaseDirectory', databaseDirectory) settings.sync() if slicer.dicomDatabase: slicer.app.setDICOMDatabase(slicer.dicomDatabase)
def __init__(self, parent): parent.title = "DICOM" parent.category = "Work in Progress" parent.contributor = "Steve Pieper" parent.helpText = """ The DICOM module is a place to experiment a bit with dicom classes from CTK (based on DCMTK). It is a 'tent' because it is meant to be suitable for explorers, but may not be robust enough for civilized people. Warning: all data directories are temporary and data may be gone next time you look! """ parent.acknowledgementText = """ This work is supported by NA-MIC, NAC, BIRN, NCIGT, and the Slicer Community. See <a>http://www.slicer.org</a> for details. Module implemented by Steve Pieper. Based on work from CommonTK (http://www.commontk.org). """ self.parent = parent if slicer.mrmlScene.GetTagByClassName( "vtkMRMLScriptedModuleNode" ) != 'ScriptedModule': slicer.mrmlScene.RegisterNodeClass(vtkMRMLScriptedModuleNode()) # initialize the dicom infrastructure settings = qt.QSettings() # the dicom listener is also global, but only started on app start if # the user so chooses if settings.contains('DICOM/RunListenerAtStart'): if bool(settings.value('DICOM/RunListenerAtStart')): # the dicom database is a global object for slicer databaseDirectory = settings.value('DatabaseDirectory') if databaseDirectory: slicer.dicomDatabase = ctk.ctkDICOMDatabase() slicer.dicomDatabase.openDatabase(databaseDirectory + "/ctkDICOM.sql", "SLICER") if not hasattr(slicer, 'dicomListener'): try: slicer.dicomListener = DICOMLib.DICOMListener(slicer.dicomDatabase) except UserWarning as message: # TODO: how to put this into the error log? print ('Problem trying to start DICOMListener:\n %s' % message) slicer.dicomListener.start()
def onDatabaseDirectoryChanged(self, databaseDirectory): if not hasattr(slicer, 'dicomDatabase') or not slicer.dicomDatabase: slicer.dicomDatabase = ctk.ctkDICOMDatabase() self.setDatabasePrecacheTags() databaseFilepath = databaseDirectory + "/ctkDICOM.sql" if not (os.access(databaseDirectory, os.W_OK) and os.access(databaseDirectory, os.R_OK)): self.messageBox('The database file path "%s" cannot be opened.' % databaseFilepath) else: slicer.dicomDatabase.openDatabase( databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: self.messageBox( 'The database file path "%s" cannot be opened.' % databaseFilepath) self.dicomDatabase = None else: if self.dicomApp: if self.dicomApp.databaseDirectory != databaseDirectory: self.dicomApp.databaseDirectory = databaseDirectory else: settings = qt.QSettings() settings.setValue('DatabaseDirectory', databaseDirectory) settings.sync() if slicer.dicomDatabase: slicer.app.setDICOMDatabase(slicer.dicomDatabase)
def __init__(self, parent): import string parent.title = "DICOM" parent.categories = ["", "Informatics"] # top level module parent.contributors = ["Steve Pieper (Isomics)"] parent.helpText = string.Template(""" The DICOM module integrates DICOM classes from CTK (based on DCMTK). See <a href=\"$a/Documentation/$b.$c/Modules/DICOM\">the documentaiton</a> for more information. """).substitute({ 'a': parent.slicerWikiUrl, 'b': slicer.app.majorVersion, 'c': slicer.app.minorVersion }) parent.acknowledgementText = """ This work is supported by NA-MIC, NAC, BIRN, NCIGT, and the Slicer Community. See <a href=http://www.slicer.org>http://www.slicer.org</a> for details. Module implemented by Steve Pieper. Based on work from CommonTK (http://www.commontk.org). """ parent.icon = qt.QIcon(':Icons/Medium/SlicerLoadDICOM.png') self.parent = parent if slicer.mrmlScene.GetTagByClassName( "vtkMRMLScriptedModuleNode") != 'ScriptedModule': slicer.mrmlScene.RegisterNodeClass(vtkMRMLScriptedModuleNode()) # initialize the dicom infrastructure slicer.dicomDatabase = None settings = qt.QSettings() # the dicom database is a global object for slicer if settings.contains('DatabaseDirectory'): databaseDirectory = settings.value('DatabaseDirectory') if databaseDirectory: slicer.dicomDatabase = ctk.ctkDICOMDatabase() slicer.dicomDatabase.openDatabase( databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: # can't open the database, so prompt the user later if they enter module slicer.dicomDatabase = None else: # the dicom listener is also global, but only started on app start if # the user so chooses if settings.contains('DICOM/RunListenerAtStart'): if settings.value( 'DICOM/RunListenerAtStart') == 'true': if not hasattr(slicer, 'dicomListener'): try: slicer.dicomListener = DICOMLib.DICOMListener( slicer.dicomDatabase) slicer.dicomListener.start() except (UserWarning, OSError) as message: # TODO: how to put this into the error log? print( 'Problem trying to start DICOMListener:\n %s' % message) if slicer.dicomDatabase: slicer.app.setDICOMDatabase(slicer.dicomDatabase) # Trigger the menu to be added when application has started up if not slicer.app.commandOptions().noMainWindow: qt.QTimer.singleShot(0, self.addMenu) # set the dicom pre-cache tags once all plugin classes have been initialized qt.QTimer.singleShot(0, DICOM.setDatabasePrecacheTags)
def onDatabaseDirectoryChanged(self,databaseDirectory): if not hasattr(slicer, 'dicomDatabase'): slicer.dicomDatabase = ctk.ctkDICOMDatabase() databaseFilepath = databaseDirectory + "/ctkDICOM.sql" if not (os.access(databaseDirectory, os.W_OK) and os.access(databaseDirectory, os.R_OK)): self.messageBox('The database file path "%s" cannot be opened.' % databaseFilepath) return slicer.dicomDatabase.openDatabase(databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: self.messageBox('The database file path "%s" cannot be opened.' % databaseFilepath)
def __init__(self, parent): ScriptedLoadableModule.__init__(self, parent) import string self.parent.title = "DICOM" self.parent.categories = ["", "Informatics"] # top level module self.parent.contributors = ["Steve Pieper (Isomics)"] self.parent.helpText = string.Template(""" The DICOM module integrates DICOM classes from CTK (based on DCMTK). See <a href=\"$a/Documentation/$b.$c/Modules/DICOM\">the documentaiton</a> for more information. """).substitute({ 'a':parent.slicerWikiUrl, 'b':slicer.app.majorVersion, 'c':slicer.app.minorVersion }) self.parent.acknowledgementText = """ This work is supported by NA-MIC, NAC, BIRN, NCIGT, and the Slicer Community. See <a href=http://www.slicer.org>http://www.slicer.org</a> for details. Module implemented by Steve Pieper. Based on work from CommonTK (http://www.commontk.org). """ self.parent.icon = qt.QIcon(':Icons/Medium/SlicerLoadDICOM.png') self.parent.dependencies = ["SubjectHierarchy"] if slicer.mrmlScene.GetTagByClassName( "vtkMRMLScriptedModuleNode" ) != 'ScriptedModule': slicer.mrmlScene.RegisterNodeClass(vtkMRMLScriptedModuleNode()) # initialize the dicom infrastructure slicer.dicomDatabase = None settings = qt.QSettings() # the dicom database is a global object for slicer if settings.contains('DatabaseDirectory'): databaseDirectory = settings.value('DatabaseDirectory') if databaseDirectory: slicer.dicomDatabase = ctk.ctkDICOMDatabase() slicer.dicomDatabase.openDatabase(databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: # can't open the database, so prompt the user later if they enter module slicer.dicomDatabase = None else: # the dicom listener is also global, but only started on app start if # the user so chooses if settings.contains('DICOM/RunListenerAtStart'): if settings.value('DICOM/RunListenerAtStart') == 'true': if not hasattr(slicer, 'dicomListener'): try: slicer.dicomListener = DICOMLib.DICOMListener(slicer.dicomDatabase) slicer.dicomListener.start() except (UserWarning,OSError) as message: # TODO: how to put this into the error log? print ('Problem trying to start DICOMListener:\n %s' % message) if slicer.dicomDatabase: slicer.app.setDICOMDatabase(slicer.dicomDatabase) # Trigger the menu to be added when application has started up if not slicer.app.commandOptions().noMainWindow : qt.QTimer.singleShot(0, self.addMenu) # set the dicom pre-cache tags once all plugin classes have been initialized qt.QTimer.singleShot(0, DICOM.setDatabasePrecacheTags)
def onDatabaseDirectoryChanged(self, databaseDirectory): if not hasattr(slicer, 'dicomDatabase'): slicer.dicomDatabase = ctk.ctkDICOMDatabase() databaseFilepath = databaseDirectory + "/ctkDICOM.sql" if not (os.access(databaseDirectory, os.W_OK) and os.access(databaseDirectory, os.R_OK)): self.messageBox('The database file path "%s" cannot be opened.' % databaseFilepath) return slicer.dicomDatabase.openDatabase(databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: self.messageBox('The database file path "%s" cannot be opened.' % databaseFilepath)
def __init__(self, parent): import string parent.title = "DICOM" parent.categories = ["", "Informatics"] # top level module parent.contributors = ["Steve Pieper (Isomics)"] parent.helpText = string.Template( """ The DICOM module integrates DICOM classes from CTK (based on DCMTK). See <a href=\"$a/Documentation/$b.$c/Modules/DICOM\">$a/Documentation/$b.$c/Modules/DICOM</a> for more information. """ ).substitute({"a": parent.slicerWikiUrl, "b": slicer.app.majorVersion, "c": slicer.app.minorVersion}) parent.acknowledgementText = """ This work is supported by NA-MIC, NAC, BIRN, NCIGT, and the Slicer Community. See <a>http://www.slicer.org</a> for details. Module implemented by Steve Pieper. Based on work from CommonTK (http://www.commontk.org). """ parent.icon = qt.QIcon(":Icons/Medium/SlicerLoadDICOM.png") self.parent = parent if slicer.mrmlScene.GetTagByClassName("vtkMRMLScriptedModuleNode") != "ScriptedModule": slicer.mrmlScene.RegisterNodeClass(vtkMRMLScriptedModuleNode()) # initialize the dicom infrastructure settings = qt.QSettings() # the dicom database is a global object for slicer if settings.contains("DatabaseDirectory"): databaseDirectory = settings.value("DatabaseDirectory") if databaseDirectory: slicer.dicomDatabase = ctk.ctkDICOMDatabase() slicer.dicomDatabase.openDatabase(databaseDirectory + "/ctkDICOM.sql", "SLICER") # the dicom listener is also global, but only started on app start if # the user so chooses if settings.contains("DICOM/RunListenerAtStart"): if bool(settings.value("DICOM/RunListenerAtStart")): if not hasattr(slicer, "dicomListener"): try: slicer.dicomListener = DICOMLib.DICOMListener(slicer.dicomDatabase) slicer.dicomListener.start() except (UserWarning, OSError) as message: # TODO: how to put this into the error log? print("Problem trying to start DICOMListener:\n %s" % message) else: slicer.dicomDatabase = None # Trigger the menu to be added when application has started up if not slicer.app.commandOptions().noMainWindow: qt.QTimer.singleShot(0, self.addMenu)
def __init__(self, parent=None): self.testingServer = None self.dicomDatabase = ctk.ctkDICOMDatabase() # TODO: are these wrapped so we can avoid magic numbers? self.dicomModelUIDRole = 32 self.dicomModelTypeRole = self.dicomModelUIDRole + 1 self.dicomModelTypes = ('Root', 'Patient', 'Study', 'Series', 'Image') if not parent: self.parent = slicer.qMRMLWidget() self.parent.setLayout(qt.QVBoxLayout()) self.parent.setMRMLScene(slicer.mrmlScene) self.layout = self.parent.layout() self.setup() self.parent.show() else: self.parent = parent self.layout = parent.layout()
def onDatabaseDirectoryChanged(self,databaseDirectory): if not hasattr(slicer, 'dicomDatabase') or not slicer.dicomDatabase: slicer.dicomDatabase = ctk.ctkDICOMDatabase() self.setDatabasePrecacheTags() databaseFilepath = databaseDirectory + "/ctkDICOM.sql" if not (os.access(databaseDirectory, os.W_OK) and os.access(databaseDirectory, os.R_OK)): self.messageBox('The database file path "%s" cannot be opened.' % databaseFilepath) return slicer.dicomDatabase.openDatabase(databaseDirectory + "/ctkDICOM.sql", "SLICER") if not slicer.dicomDatabase.isOpen: self.messageBox('The database file path "%s" cannot be opened.' % databaseFilepath) self.dicomDatabase = None return if self.dicomApp: if self.dicomApp.databaseDirectory != databaseDirectory: self.dicomApp.databaseDirectory = databaseDirectory else: settings = qt.QSettings() settings.setValue('DatabaseDirectory', databaseDirectory) settings.sync()
def __init__(self, parent): parent.title = "DICOM" parent.category = "" # top level module parent.contributor = "Steve Pieper" parent.helpText = """ The DICOM module is a place to experiment a bit with dicom classes from CTK (based on DCMTK). It is a 'tent' because it is meant to be suitable for explorers, but may not be robust enough for civilized people. Warning: all data directories are temporary and data may be gone next time you look! """ parent.acknowledgementText = """ This work is supported by NA-MIC, NAC, BIRN, NCIGT, and the Slicer Community. See <a>http://www.slicer.org</a> for details. Module implemented by Steve Pieper. Based on work from CommonTK (http://www.commontk.org). """ self.parent = parent if slicer.mrmlScene.GetTagByClassName( "vtkMRMLScriptedModuleNode") != 'ScriptedModule': slicer.mrmlScene.RegisterNodeClass(vtkMRMLScriptedModuleNode()) # initialize the dicom infrastructure settings = qt.QSettings() # the dicom database is a global object for slicer databaseDirectory = settings.value('DatabaseDirectory') if databaseDirectory: slicer.dicomDatabase = ctk.ctkDICOMDatabase() slicer.dicomDatabase.openDatabase( databaseDirectory + "/ctkDICOM.sql", "SLICER") # the dicom listener is also global, but only started on app start if # the user so chooses if settings.contains('DICOM/RunListenerAtStart'): if bool(settings.value('DICOM/RunListenerAtStart')): if not hasattr(slicer, 'dicomListener'): try: slicer.dicomListener = DICOMLib.DICOMListener( slicer.dicomDatabase) except UserWarning as message: # TODO: how to put this into the error log? print( 'Problem trying to start DICOMListener:\n %s' % message) slicer.dicomListener.start()
def test_RoundTrip(self): """ Test fiducial round trip to and from AIM XML file on disk """ print("ctest, please don't truncate my output: CTEST_FULL_OUTPUT") # enter the module mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('Reporting') # l = slicer.modulelogic.vtkSlicerReportingModuleLogic() l = slicer.modules.reporting.logic() l.GUIHiddenOff() # testDataPath = os.path.normpath(os.path.join(os.path.realpath(__file__), "..", "..", "Prototype/TestData/DICOM.CT/") print("Reporting round trip test, current working directory = " + os.getcwd()) testDataPath = os.path.join(os.getcwd(), "../../Testing/Temporary/DICOM.CT") # testDataPath = "/projects/birn/nicole/Slicer4/Reporting/Prototype/TestData/DICOM.CT" print("test data path = " + testDataPath) # set up a new DICOM database print("Creating a dicomDatabase!") ddb = ctk.ctkDICOMDatabase() if not ddb: print("ERROR: failed to create a new dicom database!") return dbpath = slicer.app.slicerHome + '/Testing/Temporary/TestingDCMDB/ctkDICOM.sql' print('database path set to ' + dbpath) if not os.path.exists(os.path.dirname(dbpath)): print('Creating dir ' + os.path.dirname(dbpath)) os.makedirs(os.path.dirname(dbpath)) ddb.openDatabase(dbpath, "ReportingTesting") if not ddb.isOpen: print("ERROR: failed to open a new dicom database at path " + dbpath) return retval = ddb.initializeDatabase() if not retval: print("ERROR: failed to init database") return l.InitializeDICOMDatabase(dbpath) testFileNames = [] for n in [487, 488, 489]: filename = os.path.join(testDataPath, "instance_" + str(n) + ".dcm") print("Adding file " + filename) testFileNames.append(filename) # check to see if the test data is already in it patients = ddb.patients() if len(patients) == 0: # add the files for filename in testFileNames: print("Inserting file " + filename) retval = ddb.insert(filename) patients = ddb.patients() if len(patients) == 0: print("ERROR: unable to add test files to database!") print(str(testFileNames)) return # get the UID for the series study = ddb.studiesForPatient(patients[0]) series = ddb.seriesForStudy(study[0]) seriesUID = series[0] # seriesUID = "1.2.392.200103.20080913.113635.2.2009.6.22.21.43.10.23432.1" # seriesUID = "2.16.840.1.114362.1.759508.1251415878280.192" # seriesUID = "1.3.12.2.1107.5.1.4.53031.30000011032906120157800000219" print("For test, using the AIM sample volume with series UID of " + seriesUID) fileList = ddb.filesForSeries(seriesUID) print("fileList = " + str(fileList)) if not fileList: print("ERROR: sample series with id " + seriesUID + " not found in database!") return # add a parameter node parameterNode = slicer.vtkMRMLScriptedModuleNode() parameterNode.SetModuleName('Reporting') slicer.mrmlScene.AddNode(parameterNode) # set it to be the active parameter node l.SetActiveParameterNodeID(parameterNode.GetID()) # # create a new report, make it the report in the parameter node, set up hierarchy # reportNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLReportingReportNode") reportNode.SetReferenceCount(reportNode.GetReferenceCount() - 1) # set the color id colorID = 'vtkMRMLColorTableNodeFileGenericAnatomyColors.txt' reportNode.SetColorNodeID(colorID) reportNode.SetDICOMDatabaseFileName(dbpath) slicer.mrmlScene.AddNode(reportNode) parameterNode.SetParameter("reportID", reportNode.GetID()) print( "Init hierarchy for report node, set parameter node to report id of " + reportNode.GetID()) l.InitializeHierarchyForReport(reportNode) # # get some sample data from the database # volId = 1 volumeNode = None volName = 'AIM volume ' + str(volId) print("Dicom data base = " + ddb) slicer.dicomDatabase = ddb scalarVolumePlugin = slicer.modules.dicomPlugins[ 'DICOMScalarVolumePlugin']() scalarVolumeLoadables = scalarVolumePlugin.examine([filelist]) volumeNode = scalarVolumePlugin.load(scalarVolumeLoadables[0]) volumeNode.SetName(volName) # print "volumeNode = ",volumeNode print("Initialize Hierarchy For Volume with id " + volumeNode.GetID()) l.InitializeHierarchyForVolume(volumeNode) print("---Now active mark up is " + l.GetActiveMarkupHierarchyID()) print("adding a fiducial") # # define a fiducial # fidNode = slicer.vtkMRMLAnnotationFiducialNode() fidName = "AIM Round Trip Test Fiducial" fidNode.SetName(fidName) fidNode.SetSelected(1) fidNode.SetVisible(1) fidNode.SetLocked(0) print("Calling set fid coords") startCoords = [15.8, 70.8, -126.7] fidNode.SetFiducialCoordinates(startCoords[0], startCoords[1], startCoords[2]) print("Starting fiducial coordinates: " + str(startCoords)) # point it to the volume fidNode.SetAttribute("AssociatedNodeID", volumeNode.GetID()) fidNode.SetScene(slicer.mrmlScene) print("Adding text disp node") fidNode.CreateAnnotationTextDisplayNode() print("Adding point display node") fidNode.CreateAnnotationPointDisplayNode() print("add node:") # slicer.mrmlScene.DebugOn() # l.DebugOn() slicer.mrmlScene.AddNode(fidNode) print("getting slice uid") uid = l.GetSliceUIDFromMarkUp(fidNode) print("fidNode uid = " + uid) # # create a label volume # volumesLogic = slicer.modules.volumes.logic() labelNode = volumesLogic.CreateLabelVolume(slicer.mrmlScene, volumeNode, "Segmentation") labelDisplayNode = labelNode.GetDisplayNode() labelDisplayNode.SetAndObserveColorNodeID( 'vtkMRMLColorTableNodeFileGenericAnatomyColors.txt') l.AddNodeToReport(labelNode) # initialize image content labelImage = labelNode.GetImageData() extent = labelImage.GetExtent() pixelCounter = 0 for k in range(extent[5]): for j in range(extent[3]): for i in range(extent[1]): if pixelCounter in initializedSegmentationVoxels: labelImage.SetScalarComponentFromFloat(i, j, k, 0, 1) else: labelImage.SetScalarComponentFromFloat(i, j, k, 0, 0) pixelCounter = pixelCounter + 1 # test save to mrml # slicer.mrmlScene.SetURL('/spl/tmp/nicole/Testing/aim/RoundTripTest.mrml') # slicer.mrmlScene.Commit() # # output AIM XML # dirName = slicer.app.slicerHome + '/Testing/Temporary/' reportNode.SetStorageDirectoryName(dirName) print("Saving report to " + dirName) retval = l.SaveReportToAIM(reportNode) if (retval != 0): print("ERROR: unable to save report to aim file " + dirName + ", retval=" + retval) else: print("Saved report to " + dirName) self.assertEqual(retval, 0) print("\n\n\nReloading aim file...") # # now clear the scene so can read in # # TBD: this causes a crash # slicer.mrmlScene.Clear(0) # # load in the aim file # newReport = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLReportingReportNode") newReport.SetReferenceCount(newReport.GetReferenceCount() - 1) # set the default color map newReport.SetColorNodeID(colorID) newReport.SetDICOMDatabaseFileName(dbpath) slicer.mrmlScene.AddNode(newReport) parameterNode.SetParameter("reportID", newReport.GetID()) Helper.LoadAIMFile(newReport.GetID(), aimFileName) # check the fiducial endCoords = [0, 0, 0] col = slicer.mrmlScene.GetNodesByClass("vtkMRMLAnnotationFiducialNode") col.SetReferenceCount(col.GetReferenceCount() - 1) # if the scene is not cleared, we should have 2 fiducials nFiducials = col.GetNumberOfItems() if nFiducials != 2: print("Failed to read fiducial form the saved report!") self.assertTrue(False) f = col.GetItemAsObject(1) f.GetFiducialCoordinates(endCoords) print("Start Coords = " + str(startCoords[0]) + "," + str(startCoords[1]) + "," + str(startCoords[2])) print("End Coords = " + str(endCoords)) xdiff = endCoords[0] - startCoords[0] ydiff = endCoords[1] - startCoords[1] zdiff = endCoords[2] - startCoords[2] diffTotal = xdiff + ydiff + zdiff print( "Difference between coordinates after loaded the aim file and value from before stored the aim file: " + str(xdiff) + "," + str(ydiff) + "," + str(zdiff) + ". Total difference = " + str(diffTotal)) if diffTotal > 0.1: print("Fiducial coordinates error exceeds the allowed bounds") self.assertTrue(False) # check the label node sceneVolumes = slicer.mrmlScene.GetNodesByClass( "vtkMRMLScalarVolumeNode") sceneVolumes.SetReferenceCount(sceneVolumes.GetReferenceCount() - 1) sceneLabels = [] for i in range(sceneVolumes.GetNumberOfItems()): vol = sceneVolumes.GetItemAsObject(i) if vol.GetLabelMap(): sceneLabels.append(vol) if len(sceneLabels) != 2: print( "Scene does not have two label nodes after reloading from AIM!" ) self.assertTrue(False) newLabelNode = sceneLabels[1] newLabelImage = newLabelNode.GetImageData() extent = newLabelImage.GetExtent() pixelCounter = 0 for k in range(extent[5]): for j in range(extent[3]): for i in range(extent[1]): pixel = newLabelImage.GetScalarComponentAsFloat(i, j, k, 0) if ((pixelCounter in initializedSegmentationVoxels) and pixel != 1) or (not ( pixelCounter in initializedSegmentationVoxels) and pixel != 0): print("Segmentation content not recovered correctly!") print("Pixel counter " + str(pixelCounter) + " is set to " + str(pixel)) self.assertTrue(False) pixelCounter = pixelCounter + 1 self.assertTrue(True)
def test_RoundTrip(self): """ Test fiducial round trip to and from AIM XML file on disk """ print("ctest, please don't truncate my output: CTEST_FULL_OUTPUT") # enter the module mainWindow = slicer.util.mainWindow() mainWindow.moduleSelector().selectModule('Reporting') # l = slicer.modulelogic.vtkSlicerReportingModuleLogic() l = slicer.modules.reporting.logic() l.GUIHiddenOff() # testDataPath = os.path.normpath(os.path.join(os.path.realpath(__file__), "..", "..", "Prototype/TestData/DICOM.CT/") print("Reporting round trip test, current working directory = "+os.getcwd()) testDataPath = os.path.join(os.getcwd(),"../../Testing/Temporary/DICOM.CT") # testDataPath = "/projects/birn/nicole/Slicer4/Reporting/Prototype/TestData/DICOM.CT" print("test data path = "+testDataPath) # set up a new DICOM database print("Creating a dicomDatabase!") ddb = ctk.ctkDICOMDatabase() if not ddb: print("ERROR: failed to create a new dicom database!") return dbpath = slicer.app.slicerHome + '/Testing/Temporary/TestingDCMDB/ctkDICOM.sql' print('database path set to '+dbpath) if not os.path.exists(os.path.dirname(dbpath)): print('Creating dir '+os.path.dirname(dbpath)) os.makedirs(os.path.dirname(dbpath)) ddb.openDatabase(dbpath,"ReportingTesting") if not ddb.isOpen: print("ERROR: failed to open a new dicom database at path "+dbpath) return retval = ddb.initializeDatabase() if not retval: print("ERROR: failed to init database") return l.InitializeDICOMDatabase(dbpath) testFileNames = [] for n in [487, 488, 489]: filename = os.path.join(testDataPath, "instance_" + str(n) + ".dcm") print("Adding file "+filename) testFileNames.append(filename) # check to see if the test data is already in it patients = ddb.patients() if len(patients) == 0: # add the files for filename in testFileNames: print("Inserting file "+filename) retval = ddb.insert(filename) patients = ddb.patients() if len(patients) == 0: print("ERROR: unable to add test files to database!") print(str(testFileNames)) return # get the UID for the series study = ddb.studiesForPatient(patients[0]) series = ddb.seriesForStudy(study[0]) seriesUID = series[0] # seriesUID = "1.2.392.200103.20080913.113635.2.2009.6.22.21.43.10.23432.1" # seriesUID = "2.16.840.1.114362.1.759508.1251415878280.192" # seriesUID = "1.3.12.2.1107.5.1.4.53031.30000011032906120157800000219" print("For test, using the AIM sample volume with series UID of "+seriesUID) fileList = ddb.filesForSeries(seriesUID) print("fileList = "+str(fileList)) if not fileList: print("ERROR: sample series with id "+seriesUID+" not found in database!") return # add a parameter node parameterNode = slicer.vtkMRMLScriptedModuleNode() parameterNode.SetModuleName('Reporting') slicer.mrmlScene.AddNode(parameterNode) # set it to be the active parameter node l.SetActiveParameterNodeID(parameterNode.GetID()) # # create a new report, make it the report in the parameter node, set up hierarchy # reportNode = slicer.mrmlScene.CreateNodeByClass("vtkMRMLReportingReportNode") reportNode.SetReferenceCount(reportNode.GetReferenceCount() - 1) # set the color id colorID = 'vtkMRMLColorTableNodeFileGenericAnatomyColors.txt' reportNode.SetColorNodeID(colorID) reportNode.SetDICOMDatabaseFileName(dbpath) slicer.mrmlScene.AddNode(reportNode) parameterNode.SetParameter("reportID", reportNode.GetID()) # # get some sample data from the database # volId = 1 volumeNode = None volName = 'AIM volume '+str(volId) # print("Dicom data base = "+ddb) slicer.dicomDatabase = ddb scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() scalarVolumeLoadables = scalarVolumePlugin.examine([fileList]) volumeNode = scalarVolumePlugin.load(scalarVolumeLoadables[0]) volumeNode.SetName(volName) # print "volumeNode = ",volumeNode print("Adding to Report: Volume with id "+volumeNode.GetID()) l.AddVolumeToReport(volumeNode) # set it on the report reportNode.SetVolumeNodeID(volumeNode.GetID()) print("adding a fiducial") # # define a fiducial # fidNode = slicer.vtkMRMLAnnotationFiducialNode() fidName = "AIM Round Trip Test Fiducial" fidNode.SetName(fidName) fidNode.SetSelected(1) fidNode.SetDisplayVisibility(1) fidNode.SetLocked(0) print("Calling set fid coords") startCoords = [15.8, 70.8, -126.7] fidNode.SetFiducialCoordinates(startCoords[0],startCoords[1],startCoords[2]) print("Starting fiducial coordinates: "+str(startCoords)) # point it to the volume fidNode.SetAttribute("AssociatedNodeID", volumeNode.GetID()) # point it to the report fidNode.SetAttribute("ReportingReportNodeID", reportNode.GetID()) fidNode.SetScene(slicer.mrmlScene) print("Adding text disp node") fidNode.CreateAnnotationTextDisplayNode() print("Adding point display node") fidNode.CreateAnnotationPointDisplayNode() print("add node:") # slicer.mrmlScene.DebugOn() # l.DebugOn() slicer.mrmlScene.AddNode(fidNode) print("getting slice uid") uid = l.GetSliceUIDFromMarkUp(fidNode) print("fidNode uid = "+uid) # # create a label volume # volumesLogic = slicer.modules.volumes.logic() labelNode = volumesLogic.CreateAndAddLabelVolume(slicer.mrmlScene, volumeNode, "Segmentation") labelDisplayNode = labelNode.GetDisplayNode() labelDisplayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeFileGenericAnatomyColors.txt') l.AddNodeToReport(labelNode) # initialize image content labelImage = labelNode.GetImageData() extent = labelImage.GetExtent() pixelCounter = 0 for k in range(extent[5]): for j in range(extent[3]): for i in range(extent[1]): if pixelCounter in initializedSegmentationVoxels: labelImage.SetScalarComponentFromFloat(i,j,k,0,1) else: labelImage.SetScalarComponentFromFloat(i,j,k,0,0) pixelCounter = pixelCounter + 1 # test save to mrml # slicer.mrmlScene.SetURL('/spl/tmp/nicole/Testing/aim/RoundTripTest.mrml') # slicer.mrmlScene.Commit() # # output AIM XML # dirName = slicer.app.slicerHome + '/Testing/Temporary/' reportNode.SetStorageDirectoryName(dirName) print("Saving report to "+dirName) retval = l.SaveReportToAIM(reportNode) if (retval != 0): print("ERROR: unable to save report to aim file "+dirName+", retval="+retval) else: print("Saved report to "+dirName+" in file "+reportNode.GetAIMFileName()) self.assertEqual(retval, 0) print("\n\n\nReloading aim file"+reportNode.GetAIMFileName()) # # now clear the scene so can read in # # TBD: this causes a crash # slicer.mrmlScene.Clear(0) # # load in the aim file # newReport = slicer.mrmlScene.CreateNodeByClass("vtkMRMLReportingReportNode") newReport.SetReferenceCount(newReport.GetReferenceCount()-1) # set the default color map newReport.SetColorNodeID(colorID) newReport.SetDICOMDatabaseFileName(dbpath) slicer.mrmlScene.AddNode(newReport) parameterNode.SetParameter("reportID", newReport.GetID()) Helper.LoadAIMFile(newReport.GetID(),reportNode.GetAIMFileName()) # check the fiducial endCoords = [0,0,0] col = slicer.mrmlScene.GetNodesByClass("vtkMRMLAnnotationFiducialNode") col.SetReferenceCount(col.GetReferenceCount() - 1) # if the scene is not cleared, we should have 2 fiducials nFiducials = col.GetNumberOfItems() if nFiducials != 2: print("Failed to read a fiducial from the saved report! Expect 2 in the non cleared scene, have " + str(nFiducials)) self.assertTrue(False) f = col.GetItemAsObject(1) f.GetFiducialCoordinates(endCoords) print("Start Coords = "+str(startCoords[0])+","+str(startCoords[1])+","+str(startCoords[2])) print("End Coords = "+str(endCoords)) xdiff = endCoords[0] - startCoords[0] ydiff = endCoords[1] - startCoords[1] zdiff = endCoords[2] - startCoords[2] diffTotal = xdiff + ydiff + zdiff print("Difference between coordinates after loaded the aim file and value from before stored the aim file: "+str(xdiff)+","+str(ydiff)+","+str(zdiff)+". Total difference = "+str(diffTotal)) if diffTotal > 0.1: print("Fiducial coordinates error exceeds the allowed bounds") self.assertTrue(False) # check the label node sceneVolumes = slicer.mrmlScene.GetNodesByClass("vtkMRMLScalarVolumeNode") sceneVolumes.SetReferenceCount(sceneVolumes.GetReferenceCount() - 1) sceneLabels = [] for i in range(sceneVolumes.GetNumberOfItems()): vol = sceneVolumes.GetItemAsObject(i) if vol.GetLabelMap(): sceneLabels.append(vol) if len(sceneLabels) != 2: print("Scene does not have two label nodes after reloading from AIM!") self.assertTrue(False) newLabelNode = sceneLabels[1] newLabelImage = newLabelNode.GetImageData() extent = newLabelImage.GetExtent() pixelCounter = 0 for k in range(extent[5]): for j in range(extent[3]): for i in range(extent[1]): pixel = newLabelImage.GetScalarComponentAsFloat(i,j,k,0) if ((pixelCounter in initializedSegmentationVoxels) and pixel != 1) or (not(pixelCounter in initializedSegmentationVoxels) and pixel != 0): print("Segmentation content not recovered correctly!") print("Pixel counter "+str(pixelCounter)+" is set to "+str(pixel)) self.assertTrue(False) pixelCounter = pixelCounter + 1 self.assertTrue(True)