def onSaveButtonClicked(self): bundle = EditUtil.EditUtil().getParameterNode().GetParameter('QuickTCGAEffect,erich') tran = json.loads(bundle) layers = [] for key in tran: nn = tran[key] nn["file"] = key + '.tif' layers.append(tran[key]) j = {} j['layers'] = layers j['username'] = self.setupUserName.text j['sourcetile'] = self.tilename j['generator'] = "3DSlicer-4.5.0 with SlicerPathology v1.0a" j['timestamp'] = datetime.datetime.now().strftime("%Y%m%d%H%M%S") labelNodes = slicer.util.getNodes('vtkMRMLLabelMapVolumeNode*') savedMessage = 'Segmentations for the following series were saved:\n\n' for label in labelNodes.values(): labelName = label.GetName() labelFileName = os.path.join(self.dataDirButton.directory, labelName + '.tif') print "labelFileName : "+labelFileName sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.SetFileName(labelFileName) sNode.SetWriteFileFormat('tif') sNode.SetURI(None) success = sNode.WriteData(label) if success: print "successful writing "+labelFileName else: print "failed writing "+labelFileName jstr = json.dumps(j,sort_keys=True, indent=4, separators=(',', ': ')) f = open(os.path.join(self.dataDirButton.directory, self.tilename + '.json'),'w') f.write(jstr) f.close()
def readFrame(self, file): sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList() sNode.SetFileName(file) sNode.SetSingleFile(0) frame = slicer.vtkMRMLScalarVolumeNode() success = sNode.ReadData(frame) return (success, frame)
def readFrame(self, file): sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList() sNode.SetFileName(file) sNode.SetSingleFile(1) frame = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(frame) return frame
def loadFilesWithArchetype(self, files, name): """Load files in the traditional Slicer manner using the volume logic helper class and the vtkITK archetype helper code """ sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() vNode = slicer.vtkMRMLScalarVolumeNode() sNode.SetFileName(files[0]) sNode.ResetFileNameList() for f in files: sNode.AddFileName(f) sNode.SetSingleFile(0) res = sNode.ReadData(vNode) if res == 1: vNode.SetScene(slicer.mrmlScene) vNode.SetName(name) slicer.mrmlScene.AddNode(vNode) else: vNode = None return vNode
def DoIt(inputDir, labelFile, outputDir, forceLabel, forceResample): dbDir1 = slicer.app.temporaryPath+'/LabelConverter' if not hasattr(slicer.modules, 'reporting'): print 'The Reporting module has not been loaded into Slicer, script cannot run!\n\tTry setting the --additional-module-path parameter.' sys.exit(1) reportingLogic = slicer.modules.reporting.logic() print('Temporary directory location: '+dbDir1) qt.QDir().mkpath(dbDir1) dbDir0 = None if slicer.dicomDatabase: dbDir0 = os.path.split(slicer.dicomDatabase.databaseFilename)[0] dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(dbDir1) # import DICOM study indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir, None) indexer.waitForImportFinished() print('DICOM import finished!') # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(inputDir+'/'+dcm) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' sys.exit(1) inputVolume = scalarVolumePlugin.load(loadables[0]) print 'Input volume loaded! ID = ', inputVolume.GetID() # read the label volume labelVolume = slicer.vtkMRMLLabelMapVolumeNode() sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.SetFileName(labelFile) sNode.ReadData(labelVolume) if forceLabel>0: # print('Forcing label to '+str(forceLabel)) labelImage = labelVolume.GetImageData() thresh = vtk.vtkImageThreshold() if vtk.vtkVersion().GetVTKMajorVersion() < 6: thresh.SetInput(labelImage) else: thresh.SetInputData(labelImage) thresh.ThresholdBetween(1, labelImage.GetScalarRange()[1]) thresh.SetInValue(int(forceLabel)) thresh.SetOutValue(0) thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.Update() labelImage = thresh.GetOutput() labelVolume.SetAndObserveImageData(labelImage) slicer.mrmlScene.AddNode(labelVolume) print 'Label volume added, id = ', labelVolume.GetID() # ensure that the label volume scalar type is unsigned short if labelVolume.GetImageData() != None: scalarType = labelVolume.GetImageData().GetScalarType() if scalarType != vtk.VTK_UNSIGNED_SHORT: print 'Label volume has pixel type of ',vtk.vtkImageScalarTypeNameMacro(scalarType),', casting to unsigned short' cast = vtk.vtkImageCast() cast.SetOutputScalarTypeToUnsignedShort() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(labelVolume.GetImageData()) cast.Update() labelVolume.SetAndObserveImageData(cast.GetOutput()) else: cast.SetInputConnection(labelVolume.GetImageDataConnection()) cast.Update() labelVolume.SetImageDataConnection(cast.GetOutputPort()) if labelVolume.GetImageData().GetScalarType() != vtk.VTK_UNSIGNED_SHORT: print 'Failed to cast label volume to unsigned short, type is ', vtk.vtkImageScalarTypeNameMacro(labelVolume.GetImageData().GetScalarType()) sys.exit(1) volumesLogic = slicer.modules.volumes.logic() geometryCheckString = volumesLogic.CheckForLabelVolumeValidity(inputVolume, labelVolume) if geometryCheckString != "": # has the user specified that forced resampling is okay? if forceResample == False: print 'Label volume mismatch with input volume:\n',geometryCheckString,'\nForced resample not specified, aborting. Re-run with --force option to ignore geometric inconsistencies' sys.exit(1) # resample label to the input volume raster resampledLabel = slicer.vtkMRMLLabelMapVolumeNode() slicer.mrmlScene.AddNode(resampledLabel) print 'Resampled label added, id = ', resampledLabel.GetID() resampledLabel = volumesLogic.ResampleVolumeToReferenceVolume(labelVolume, inputVolume) labelVolume = resampledLabel displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID(reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) labelVolume.SetAttribute('AssociatedNodeID',inputVolume.GetID()) labelVolume.SetAndObserveDisplayNodeID(displayNode.GetID()) # initialize the DICOM DB for Reporting logic, save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(labelVolume) print('About to write DICOM SEG!') dbFileName = slicer.dicomDatabase.databaseFilename reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir) dicomWidget.onDatabaseDirectoryChanged(dbDir0) exit()
def load(self,loadable): """Load the selection as a MultiVolume, if multivolume attribute is present """ mvNode = '' try: mvNode = loadable.multivolume except AttributeError: return nFrames = int(mvNode.GetAttribute('MultiVolume.NumberOfFrames')) files = string.split(mvNode.GetAttribute('MultiVolume.FrameFileList'),',') nFiles = len(files) filesPerFrame = nFiles/nFrames frames = [] mvImage = vtk.vtkImageData() mvImageArray = None scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() # read each frame into scalar volume for frameNumber in range(nFrames): sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList(); frameFileList = files[frameNumber*filesPerFrame:(frameNumber+1)*filesPerFrame] # sv plugin will sort the filenames by geometric order svLoadables = scalarVolumePlugin.examine([frameFileList]) if len(svLoadables) == 0: return for f in svLoadables[0].files: sNode.AddFileName(f) sNode.SetFileName(frameFileList[0]) # only used when num files/frame = 1 sNode.SetSingleFile(0) frame = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(frame) if frame == None: print('Failed to read a multivolume frame!') return False if frameNumber == 0: frameImage = frame.GetImageData() frameExtent = frameImage.GetExtent() frameSize = frameExtent[1]*frameExtent[3]*frameExtent[5] mvImage.SetExtent(frameExtent) mvImage.SetNumberOfScalarComponents(nFrames) mvImage.AllocateScalars() mvImageArray = vtk.util.numpy_support.vtk_to_numpy(mvImage.GetPointData().GetScalars()) mvNode.SetScene(slicer.mrmlScene) mat = vtk.vtkMatrix4x4() frame.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy(frameImage.GetPointData().GetScalars()) mvImageArray.T[frameNumber] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount()-1) mvDisplayNode.SetScene(slicer.mrmlScene) mvDisplayNode.SetDefaultColorMap() slicer.mrmlScene.AddNode(mvDisplayNode) mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) slicer.mrmlScene.AddNode(mvNode) return True
def LoadAIMFile(newReportID, fileName): dom = xml.dom.minidom.parse(fileName) SlicerReportingModuleWidgetHelper.Debug('Parsed AIM report:') SlicerReportingModuleWidgetHelper.Debug(dom.toxml()) volumeList = [] ddb = slicer.dicomDatabase volId = 1 volume = None # get the annotation element and retrieve its name annotations = dom.getElementsByTagName('ImageAnnotation') if len(annotations) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM file does not contain any annotations!') return ann = annotations[0] desc = ann.getAttribute('name') # get the anatomic entity element and initialize the report node based on # it anatomics = dom.getElementsByTagName('AnatomicEntity') if len(anatomics) != 1: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM file does not contain any anatomic entities or contains more than one! This is not supported.') return anatomy = anatomics[0] labelValue = anatomy.getAttribute('codeValue') labelName = anatomy.getAttribute('codeMeaning') codingSchemeDesignator = anatomy.getAttribute('codingSchemeDesignator') if codingSchemeDesignator != '3DSlicer': SlicerReportingModuleWidgetHelper.WarningPopup('Code scheme designator '+codingSchemeDesignator+' is not supported. Default will be used instead.') labelValue = "1" newReport = slicer.mrmlScene.GetNodeByID(newReportID) newReport.SetFindingLabel(int(labelValue)) # pull all the volumes that are referenced into the scene for node in dom.getElementsByTagName('ImageSeries'): instanceUID = node.getAttribute('instanceUID') filelist = ddb.filesForSeries(instanceUID) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() scalarVolumeLoadables = scalarVolumePlugin.examine([filelist]) if len(scalarVolumeLoadables) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup('Error loading AIM: Failed to load the volume node reference in the file') volumeName = scalarVolumeLoadables[0].name newReport.SetName('Report for Volume '+volumeName) volume = scalarVolumePlugin.load(scalarVolumeLoadables[0]) volume.SetName(volumeName) if volume == None: SlicerReportingModuleWidgetHelper.Error('Failed to read series!') return if len(volumeList) != 0: SlicerReportingModuleWidgetHelper.ErrorPopup('Error importing AIM report: Report references more than one volume, which is not allowed!') return volumeList.append(volume) SlicerReportingModuleWidgetHelper.Debug('Volume read from AIM report:') slicer.modules.reporting.logic().AddVolumeToReport(volume) newReport.SetVolumeNodeID(volume.GetID()) if len(volumeList) > 1: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM does not allow to have more than one volume per file!') return if len(volumeList) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup('AIM file you requested to load does not reference any volumes, cannot process it!') return #if volume != None: # self.__volumeSelector.setCurrentNode(volume) instanceUIDs = volume.GetAttribute('DICOM.instanceUIDs') instanceUIDList = instanceUIDs.split() # AF: GeometricShape is inside geometricShapeCollection, but # there's no need to parse at that level, I think # # geometricShapeCollection # | # +-spatialCoordinateCollection # | # +-SpatialCoordinate # for node in dom.getElementsByTagName('GeometricShape'): ijCoordList = [] rasPointList = [] uidList = [] elementType = node.getAttribute('xsi:type') for child in node.childNodes: if child.nodeName == 'spatialCoordinateCollection': for coord in child.childNodes: if coord.nodeName == 'SpatialCoordinate': ijCoordList.append(float(coord.getAttribute('x'))) ijCoordList.append(float(coord.getAttribute('y'))) uid = coord.getAttribute('imageReferenceUID') uidList.append(uid) SlicerReportingModuleWidgetHelper.Debug('Coordinate list: '+str(ijCoordList)) ijk2ras = vtk.vtkMatrix4x4() volume.GetIJKToRASMatrix(ijk2ras) # convert each point from IJ to RAS for ij in range(len(uidList)): pointUID = uidList[ij] # locate the UID in the list assigned to the volume totalSlices = len(instanceUIDList) for k in range(len(instanceUIDList)): if pointUID == instanceUIDList[k]: break # print "k = ",k,", totalSlices = ",totalSlices pointIJK = [ijCoordList[ij*2], ijCoordList[ij*2+1], k, 1.] pointRAS = ijk2ras.MultiplyPoint(pointIJK) SlicerReportingModuleWidgetHelper.Debug('Input point: '+str(pointIJK)) SlicerReportingModuleWidgetHelper.Debug('Converted point: '+str(pointRAS)) rasPointList.append(pointRAS[0:3]) # instantiate the markup elements if elementType == 'Point': SlicerReportingModuleWidgetHelper.Debug("Importing a fiducial!") if len(ijCoordList) != 2: SlicerReportingModuleWidgetHelper.Error('Number of coordinates not good for a fiducial') return fiducial = slicer.mrmlScene.CreateNodeByClass('vtkMRMLAnnotationFiducialNode') fiducial.SetReferenceCount(fiducial.GetReferenceCount()-1) # associate it with the report fiducial.SetAttribute('ReportingReportNodeID', newReport.GetID()) # associate it with the volume fiducial.SetAttribute('AssociatedNodeID', volume.GetID()) # ??? Why the API is so inconsistent -- there's no SetPosition1() ??? fiducial.SetFiducialCoordinates(rasPointList[0]) fiducial.Initialize(slicer.mrmlScene) # adding to hierarchy is handled by the Reporting logic if elementType == 'MultiPoint': SlicerReportingModuleWidgetHelper.Debug("Importing a ruler!") if len(ijCoordList) != 4: SlicerReportingModuleWidgetHelper.Error('Number of coordinates not good for a ruler') return ruler = slicer.mrmlScene.CreateNodeByClass('vtkMRMLAnnotationRulerNode') ruler.SetReferenceCount(ruler.GetReferenceCount()-1) # associate it with the report ruler.SetAttribute('ReportingReportNodeID', newReport.GetID()) # associate it with the volume ruler.SetAttribute('AssociatedNodeID', volume.GetID()) SlicerReportingModuleWidgetHelper.Debug('Initializing with points '+str(rasPointList[0])+' and '+str(rasPointList[1])) ruler.SetPosition1(rasPointList[0]) ruler.SetPosition2(rasPointList[1]) ruler.Initialize(slicer.mrmlScene) # AF: Initialize() adds to the scene ... for node in dom.getElementsByTagName('Segmentation'): # read all labels that are available in the SEG object # check if the referenced volume is already in the scene # if not, load it # initialize AssociatedNodeID for the label node to point to the # reference SlicerReportingModuleWidgetHelper.Debug('Importing a segmentation') labelNodes = vtk.vtkCollection() referenceNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLScalarVolumeNode') referenceNode.SetReferenceCount(referenceNode.GetReferenceCount()-1) uid = node.getAttribute('sopInstanceUID') res = False colorNode = slicer.mrmlScene.GetNodeByID(newReport.GetColorNodeID()) res = slicer.modules.reporting.logic().DicomSegRead(labelNodes, uid, colorNode) SlicerReportingModuleWidgetHelper.Debug('Read this many labels from the seg object:'+str(labelNodes.GetNumberOfItems())) if labelNodes.GetNumberOfItems() == 0: print("Error loading segmentation object, have 0 labels") else: # read the reference node label0 = labelNodes.GetItemAsObject(0) referenceUIDs = label0.GetAttribute('DICOM.referenceInstanceUIDs') SlicerReportingModuleWidgetHelper.Debug('Seg object reference uids: '+referenceUIDs) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLLabelMapVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount()-1) displayNode.SetAndObserveColorNodeID(newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('ReportingReportNodeID', newReport.GetID()) labelNode.SetAttribute('AssociatedNodeID', volumeList[0].GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNode) # AF: this shuould not be necessary with the "proper" AIM input, since # only one volume should be present in the report, and only one item in # that volume should be annotated if 0: # if referenceUIDs != None: reader = slicer.vtkMRMLVolumeArchetypeStorageNode() reader.ResetFileNameList() for uid in string.split(referenceUIDs, ' '): fname = slicer.modules.reporting.logic().GetFileNameFromUID(uid) reader.AddFileName(fname) reader.SetFileName(string.split(referenceUIDs, ' ')[0]) reader.SetSingleFile(0) referenceVolume = slicer.mrmlScene.CreateNodeByClass('vtkMRMLScalarVolumeNode') referenceVolumeUIDs = referenceVolume.GetAttribute('DICOM.instanceUIDs') reader.ReadData(referenceVolume) nodeToAdd = referenceVolume allVolumeNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLScalarVolumeNode') allVolumeNodes.SetReferenceCount(allVolumeNodes.GetReferenceCount()-1) for i in range(allVolumeNodes.GetNumberOfItems()): v = allVolumeNodes.GetItemAsObject(i) uids = v.GetAttribute('DICOM.instanceUIDs') if uids == referenceNodeUIDs: print('Referenced node is already in the scene!') nodeToAdd = None referenceNode = v break if nodeToAdd != None: slicer.mrmlScene.AddNode(nodeToAdd) slicer.modules.reporting.logic().AddVolumeToReport(referenceNode) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLScalarVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount()-1) displayNode.SetAndObserveColorNodeID(newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('ReportingReportNodeID', newReport.GetID()) labelNode.SetAttribute('AssociatedNodeID', referenceNode.GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNodes.GetItemAsObject(i))
def DoIt(inputDir, rgbDir, outputDir): # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(inputDir+'/'+dcm) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() print 'Will examine: ',dcmList indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir) indexer.waitForImportFinished() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' exit() inputVolume = scalarVolumePlugin.load(loadables[0]) sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() ''' sNode.ResetFileNameList() for f in loadables[0].files: sNode.AddFileName(f) sNode.SetFileName(loadables[0].files[0]) sNode.SetSingleFile(0) inputVolume = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(inputVolume) ''' sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir,'input_volume.nrrd')) sNode.WriteData(inputVolume) # # Order the input RGBs and rename in a temp directory # rgbList = [] for rgb in os.listdir(rgbDir): if len(rgb)-rgb.rfind('.bmp') == 4: rgbList.append(rgb) tmpDir = slicer.app.settings().value('Modules/TemporaryDirectory') tmpDir = tmpDir+'/PNGStackLabelConverter' if not os.path.exists(tmpDir): os.mkdir(tmpDir) oldFiles = os.listdir(tmpDir) # just in case there is anything in that directory for f in oldFiles: os.unlink(tmpDir+'/'+f) rgbOrdered = [None] * len(loadables[0].files) rgbCnt = 0 rgbExt = rgbList[0][rgbList[0].rfind('.')+1:len(rgbList[0])] print 'Extension for RGBs: ',rgbExt dcmFileList = loadables[0].files rgbRenamedList = [] print 'Number of dcm files: ',len(dcmFileList), ' and rgb files: ',len(rgbOrdered) dcmIdx = 0 for dcm in dcmFileList: rgbIdx = 0 for rgb in rgbList: dcmPrefix = dcm[dcm.rfind('/')+1:dcm.rfind('.')] if rgb.find(dcmPrefix) != -1: name = string.zfill(str(dcmIdx),5) rgbCnt = rgbCnt+1 src = rgbDir+'/'+rgb dest = tmpDir+'/'+name+'.'+rgbExt rgbRenamedList.append(dest) shutil.copy(src,dest) break rgbIdx = rgbIdx+1 # remove the matched DICOM file from the list if rgbIdx == len(rgbList): print('ERROR: failed to find matching label file for DICOM file '+dcm) return del rgbList[rgbIdx] dcmIdx = dcmIdx+1 if len(rgbRenamedList) == 0: print 'Could not parse the DICOM Study!' return sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList() for f in rgbRenamedList: sNode.AddFileName(f) sNode.SetFileName(rgbRenamedList[0]) sNode.SetSingleFile(0) inputRGBVolume = slicer.vtkMRMLVectorVolumeNode() sNode.ReadData(inputRGBVolume) # run the filter # - extract the RGB portions extract = vtk.vtkImageExtractComponents() extract.SetComponents(0,1,2) if vtk.vtkVersion().GetVTKMajorVersion() < 6: extract.SetInput(inputRGBVolume.GetImageData()) else: extract.SetInputData(inputRGBVolume.GetImageData()) luminance = vtk.vtkImageLuminance() if vtk.vtkVersion().GetVTKMajorVersion() < 6: luminance.SetInput(extract.GetOutput()) else: luminance.SetInputData(extract.GetOutput()) cast = vtk.vtkImageCast() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(luminance.GetOutput()) else: cast.SetInputData(luminance.GetOutput()) cast.SetOutputScalarTypeToShort() cast.GetOutput().Update() ijkToRAS = vtk.vtkMatrix4x4() inputVolume.GetIJKToRASMatrix(ijkToRAS) outputLabel = slicer.vtkMRMLLabelMapVolumeNode() outputLabel.SetIJKToRASMatrix(ijkToRAS) outputLabel.SetAndObserveImageData(cast.GetOutput()) reportingLogic = slicer.modules.reporting.logic() displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID(reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) outputLabel.SetAndObserveDisplayNodeID(displayNode.GetID()) sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir,'label_output.nrrd')) sNode.WriteData(outputLabel) # save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(outputLabel) slicer.mrmlScene.AddNode(inputVolume) outputLabel.SetAttribute('AssociatedNodeID',inputVolume.GetID()) slicer.mrmlScene.AddNode(outputLabel) # initialize the DICOM DB for Reporting logic settings = qt.QSettings() dbFileName = settings.value('DatabaseDirectory','') if dbFileName =='': print('ERROR: database must be initialized') else: dbFileName = dbFileName +'/ctkDICOM.sql' reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir)
def writeVolume(self,volume,name): path = slicer.app.temporaryPath + '/%s.nrrd' % name s = slicer.vtkMRMLVolumeArchetypeStorageNode() s.SetFileName(path) s.WriteData(volume) return path
def DoIt(inputDir, rgbDir, outputDir): # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm) - dcm.rfind('.dcm') == 4: dcmList.append(inputDir + '/' + dcm) scalarVolumePlugin = slicer.modules.dicomPlugins[ 'DICOMScalarVolumePlugin']() print 'Will examine: ', dcmList indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir) indexer.waitForImportFinished() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' exit() inputVolume = scalarVolumePlugin.load(loadables[0]) sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() ''' sNode.ResetFileNameList() for f in loadables[0].files: sNode.AddFileName(f) sNode.SetFileName(loadables[0].files[0]) sNode.SetSingleFile(0) inputVolume = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(inputVolume) ''' sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir, 'input_volume.nrrd')) sNode.WriteData(inputVolume) # # Order the input RGBs and rename in a temp directory # rgbList = [] for rgb in os.listdir(rgbDir): if len(rgb) - rgb.rfind('.bmp') == 4: rgbList.append(rgb) tmpDir = slicer.app.settings().value('Modules/TemporaryDirectory') tmpDir = tmpDir + '/PNGStackLabelConverter' if not os.path.exists(tmpDir): os.mkdir(tmpDir) oldFiles = os.listdir(tmpDir) # just in case there is anything in that directory for f in oldFiles: os.unlink(tmpDir + '/' + f) rgbOrdered = [None] * len(loadables[0].files) rgbCnt = 0 rgbExt = rgbList[0][rgbList[0].rfind('.') + 1:len(rgbList[0])] print 'Extension for RGBs: ', rgbExt dcmFileList = loadables[0].files rgbRenamedList = [] print 'Number of dcm files: ', len(dcmFileList), ' and rgb files: ', len( rgbOrdered) dcmIdx = 0 for dcm in dcmFileList: rgbIdx = 0 for rgb in rgbList: dcmPrefix = dcm[dcm.rfind('/') + 1:dcm.rfind('.')] if rgb.find(dcmPrefix) != -1: name = string.zfill(str(dcmIdx), 5) rgbCnt = rgbCnt + 1 src = rgbDir + '/' + rgb dest = tmpDir + '/' + name + '.' + rgbExt rgbRenamedList.append(dest) shutil.copy(src, dest) break rgbIdx = rgbIdx + 1 # remove the matched DICOM file from the list if rgbIdx == len(rgbList): print('ERROR: failed to find matching label file for DICOM file ' + dcm) return del rgbList[rgbIdx] dcmIdx = dcmIdx + 1 if len(rgbRenamedList) == 0: print 'Could not parse the DICOM Study!' return sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList() for f in rgbRenamedList: sNode.AddFileName(f) sNode.SetFileName(rgbRenamedList[0]) sNode.SetSingleFile(0) inputRGBVolume = slicer.vtkMRMLVectorVolumeNode() sNode.ReadData(inputRGBVolume) # run the filter # - extract the RGB portions extract = vtk.vtkImageExtractComponents() extract.SetComponents(0, 1, 2) if vtk.vtkVersion().GetVTKMajorVersion() < 6: extract.SetInput(inputRGBVolume.GetImageData()) else: extract.SetInputData(inputRGBVolume.GetImageData()) luminance = vtk.vtkImageLuminance() if vtk.vtkVersion().GetVTKMajorVersion() < 6: luminance.SetInput(extract.GetOutput()) else: luminance.SetInputData(extract.GetOutput()) cast = vtk.vtkImageCast() if vtk.vtkVersion().GetVTKMajorVersion() < 6: cast.SetInput(luminance.GetOutput()) else: cast.SetInputData(luminance.GetOutput()) cast.SetOutputScalarTypeToShort() cast.GetOutput().Update() ijkToRAS = vtk.vtkMatrix4x4() inputVolume.GetIJKToRASMatrix(ijkToRAS) outputLabel = slicer.vtkMRMLLabelMapVolumeNode() outputLabel.SetIJKToRASMatrix(ijkToRAS) outputLabel.SetAndObserveImageData(cast.GetOutput()) reportingLogic = slicer.modules.reporting.logic() displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID( reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) outputLabel.SetAndObserveDisplayNodeID(displayNode.GetID()) sNode.SetWriteFileFormat('nrrd') sNode.SetFileName(os.path.join(outputDir, 'label_output.nrrd')) sNode.WriteData(outputLabel) # save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(outputLabel) slicer.mrmlScene.AddNode(inputVolume) outputLabel.SetAttribute('AssociatedNodeID', inputVolume.GetID()) slicer.mrmlScene.AddNode(outputLabel) # initialize the DICOM DB for Reporting logic settings = qt.QSettings() dbFileName = settings.value('DatabaseDirectory', '') if dbFileName == '': print('ERROR: database must be initialized') else: dbFileName = dbFileName + '/ctkDICOM.sql' reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir)
def load(self,loadable): """Load the selection as a MultiVolume, if multivolume attribute is present """ mvNode = '' try: mvNode = loadable.multivolume except AttributeError: return None nFrames = int(mvNode.GetAttribute('MultiVolume.NumberOfFrames')) files = string.split(mvNode.GetAttribute('MultiVolume.FrameFileList'),',') nFiles = len(files) filesPerFrame = nFiles/nFrames frames = [] mvImage = vtk.vtkImageData() mvImageArray = None scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() instanceUIDs = "" for file in files: uid = slicer.dicomDatabase.fileValue(file,self.tags['instanceUID']) if uid == "": uid = "Unknown" instanceUIDs += uid+" " instanceUIDs = instanceUIDs[:-1] mvNode.SetAttribute("DICOM.instanceUIDs", instanceUIDs) # read each frame into scalar volume for frameNumber in range(nFrames): sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList(); frameFileList = files[frameNumber*filesPerFrame:(frameNumber+1)*filesPerFrame] # sv plugin will sort the filenames by geometric order svLoadables = scalarVolumePlugin.examine([frameFileList]) if len(svLoadables) == 0: return None for f in svLoadables[0].files: sNode.AddFileName(f) sNode.SetFileName(frameFileList[0]) # only used when num files/frame = 1 sNode.SetSingleFile(0) frame = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(frame) if frame.GetImageData() == None: print('Failed to read a multivolume frame!') return None if frameNumber == 0: frameImage = frame.GetImageData() frameExtent = frameImage.GetExtent() frameSize = frameExtent[1]*frameExtent[3]*frameExtent[5] mvImage.SetExtent(frameExtent) if vtk.VTK_MAJOR_VERSION <= 5: mvImage.SetNumberOfScalarComponents(nFrames) mvImage.SetScalarType(frame.GetImageData().GetScalarType()) mvImage.AllocateScalars() else: mvImage.AllocateScalars(frame.GetImageData().GetScalarType(), nFrames) mvImageArray = vtk.util.numpy_support.vtk_to_numpy(mvImage.GetPointData().GetScalars()) mvNode.SetScene(slicer.mrmlScene) mat = vtk.vtkMatrix4x4() frame.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy(frameImage.GetPointData().GetScalars()) mvImageArray.T[frameNumber] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount()-1) mvDisplayNode.SetScene(slicer.mrmlScene) mvDisplayNode.SetDefaultColorMap() slicer.mrmlScene.AddNode(mvDisplayNode) mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) mvNode.SetName(loadable.name) slicer.mrmlScene.AddNode(mvNode) # # automatically select the volume to display # appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetReferenceActiveVolumeID(mvNode.GetID()) appLogic.PropagateVolumeSelection() # file list is no longer needed - remove the attribute mvNode.RemoveAttribute('MultiVolume.FrameFileList') return mvNode
def DoIt(inputDir, labelFile, outputDir, forceLabel): dbDir1 = slicer.app.temporaryPath+'/LabelConverter' reportingLogic = slicer.modules.reporting.logic() print('Temporary directory location: '+dbDir1) qt.QDir().mkpath(dbDir1) dbDir0 = None if slicer.dicomDatabase: dbDir0 = os.path.split(slicer.dicomDatabase.databaseFilename)[0] try: dicomWidget = slicer.modules.dicom.widgetRepresentation().self() dicomWidget.onDatabaseDirectoryChanged(dbDir1) # import DICOM study indexer = ctk.ctkDICOMIndexer() indexer.addDirectory(slicer.dicomDatabase, inputDir, None) indexer.waitForImportFinished() print('DICOM import finished!') # # Read the input DICOM series as a volume # dcmList = [] for dcm in os.listdir(inputDir): if len(dcm)-dcm.rfind('.dcm') == 4: dcmList.append(inputDir+'/'+dcm) scalarVolumePlugin = slicer.modules.dicomPlugins['DICOMScalarVolumePlugin']() loadables = scalarVolumePlugin.examine([dcmList]) if len(loadables) == 0: print 'Could not parse the DICOM Study!' exit() inputVolume = scalarVolumePlugin.load(loadables[0]) slicer.mrmlScene.AddNode(inputVolume) print('Input volume loaded!') # read the label volume labelVolume = slicer.vtkMRMLScalarVolumeNode() sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.SetFileName(labelFile) sNode.ReadData(labelVolume) labelVolume.LabelMapOn() if forceLabel>0: print('Forcing label to '+str(forceLabel)) labelImage = labelVolume.GetImageData() thresh = vtk.vtkImageThreshold() thresh.SetInput(labelImage) thresh.ThresholdBetween(1, labelImage.GetScalarRange()[1]) thresh.SetInValue(int(forceLabel)) thresh.SetOutValue(0) thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.Update() labelImage = thresh.GetOutput() labelVolume.SetAndObserveImageData(labelImage) slicer.mrmlScene.AddNode(labelVolume) # resample label to the input volume raster resampledLabel = slicer.vtkMRMLScalarVolumeNode() slicer.mrmlScene.AddNode(resampledLabel) eye = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(eye) parameters = {} parameters['inputVolume'] = labelVolume.GetID() parameters['referenceVolume'] = inputVolume.GetID() parameters['outputVolume'] = resampledLabel.GetID() parameters['warpTransform'] = eye.GetID() parameters['interpolationMode'] = 'NearestNeighbor' parameters['pixelType'] = 'ushort' cliNode = None cliNode = slicer.cli.run(slicer.modules.brainsresample, None, parameters, 1) labelVolume = resampledLabel displayNode = slicer.vtkMRMLLabelMapVolumeDisplayNode() displayNode.SetAndObserveColorNodeID(reportingLogic.GetDefaultColorNode().GetID()) slicer.mrmlScene.AddNode(displayNode) labelVolume.SetAttribute('AssociatedNodeID',inputVolume.GetID()) labelVolume.LabelMapOn() labelVolume.SetAndObserveDisplayNodeID(displayNode.GetID()) # initialize the DICOM DB for Reporting logic, save as DICOM SEG labelCollection = vtk.vtkCollection() labelCollection.AddItem(labelVolume) print('About to write DICOM SEG!') dbFileName = slicer.dicomDatabase.databaseFilename reportingLogic.InitializeDICOMDatabase(dbFileName) reportingLogic.DicomSegWrite(labelCollection, outputDir) except: print('Error occurred!') dicomWidget.onDatabaseDirectoryChanged(dbDir0) exit()
def writeVolume(self, volume, name): path = slicer.app.temporaryPath + '/%s.nrrd' % name s = slicer.vtkMRMLVolumeArchetypeStorageNode() s.SetFileName(path) s.WriteData(volume) return path
def LoadAIMFile(newReportID, fileName): dom = xml.dom.minidom.parse(fileName) SlicerReportingModuleWidgetHelper.Debug('Parsed AIM report:') SlicerReportingModuleWidgetHelper.Debug(dom.toxml()) volumeList = [] ddb = slicer.dicomDatabase volId = 1 volume = None # get the annotation element and retrieve its name annotations = dom.getElementsByTagName('ImageAnnotation') if len(annotations) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM file does not contain any annotations!') return ann = annotations[0] desc = ann.getAttribute('name') # get the anatomic entity element and initialize the report node based on # it anatomics = dom.getElementsByTagName('AnatomicEntity') if len(anatomics) != 1: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM file does not contain any anatomic entities or contains more than one! This is not supported.' ) return anatomy = anatomics[0] labelValue = anatomy.getAttribute('codeValue') labelName = anatomy.getAttribute('codeMeaning') codeSchemeDesignator = anatomy.getAttribute('codeSchemeDesignator') if codeSchemeDesignator != '3DSlicer': SlicerReportingModuleWidgetHelper.WarningPopup( 'Code scheme designator ' + codeSchemeDesignator + ' is not supported. Default will be used instead.') labelValue = "1" newReport = slicer.mrmlScene.GetNodeByID(newReportID) newReport.SetFindingLabel(int(labelValue)) # pull all the volumes that are referenced into the scene for node in dom.getElementsByTagName('ImageSeries'): instanceUID = node.getAttribute('instanceUID') filelist = ddb.filesForSeries(instanceUID) scalarVolumePlugin = slicer.modules.dicomPlugins[ 'DICOMScalarVolumePlugin']() scalarVolumeLoadables = scalarVolumePlugin.examine([filelist]) if len(scalarVolumeLoadables) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'Error loading AIM: Failed to load the volume node reference in the file' ) volumeName = scalarVolumeLoadables[0].name newReport.SetName('Report for Volume ' + volumeName) volume = scalarVolumePlugin.load(scalarVolumeLoadables[0]) volume.SetName(volumeName) if volume == None: SlicerReportingModuleWidgetHelper.Error( 'Failed to read series!') return if len(volumeList) != 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'Error importing AIM report: Report references more than one volume, which is not allowed!' ) return volumeList.append(volume) SlicerReportingModuleWidgetHelper.Debug( 'Volume read from AIM report:') slicer.modules.reporting.logic().InitializeHierarchyForVolume( volume) newReport.SetVolumeNodeID(volume.GetID()) if len(volumeList) > 1: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM does not allow to have more than one volume per file!') return if len(volumeList) == 0: SlicerReportingModuleWidgetHelper.ErrorPopup( 'AIM file you requested to load does not reference any volumes, cannot process it!' ) return #if volume != None: # self.__volumeSelector.setCurrentNode(volume) instanceUIDs = volume.GetAttribute('DICOM.instanceUIDs') instanceUIDList = instanceUIDs.split() # AF: GeometricShape is inside geometricShapeCollection, but # there's no need to parse at that level, I think # # geometricShapeCollection # | # +-spatialCoordinateCollection # | # +-SpatialCoordinate # for node in dom.getElementsByTagName('GeometricShape'): ijCoordList = [] rasPointList = [] uidList = [] elementType = node.getAttribute('xsi:type') for child in node.childNodes: if child.nodeName == 'spatialCoordinateCollection': for coord in child.childNodes: if coord.nodeName == 'SpatialCoordinate': ijCoordList.append(float(coord.getAttribute('x'))) ijCoordList.append(float(coord.getAttribute('y'))) uid = coord.getAttribute('imageReferenceUID') uidList.append(uid) SlicerReportingModuleWidgetHelper.Debug('Coordinate list: ' + str(ijCoordList)) ijk2ras = vtk.vtkMatrix4x4() volume.GetIJKToRASMatrix(ijk2ras) # convert each point from IJ to RAS for ij in range(len(uidList)): pointUID = uidList[ij] # locate the UID in the list assigned to the volume totalSlices = len(instanceUIDList) for k in range(len(instanceUIDList)): if pointUID == instanceUIDList[k]: break # print "k = ",k,", totalSlices = ",totalSlices pointIJK = [ ijCoordList[ij * 2], ijCoordList[ij * 2 + 1], k, 1. ] pointRAS = ijk2ras.MultiplyPoint(pointIJK) SlicerReportingModuleWidgetHelper.Debug('Input point: ' + str(pointIJK)) SlicerReportingModuleWidgetHelper.Debug('Converted point: ' + str(pointRAS)) rasPointList.append(pointRAS[0:3]) # instantiate the markup elements if elementType == 'Point': SlicerReportingModuleWidgetHelper.Debug( "Importing a fiducial!") if len(ijCoordList) != 2: SlicerReportingModuleWidgetHelper.Error( 'Number of coordinates not good for a fiducial') return fiducial = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLAnnotationFiducialNode') fiducial.SetReferenceCount(fiducial.GetReferenceCount() - 1) # associate it with the volume fiducial.SetAttribute("AssociatedNodeID", volume.GetID()) # ??? Why the API is so inconsistent -- there's no SetPosition1() ??? fiducial.SetFiducialCoordinates(rasPointList[0]) fiducial.Initialize(slicer.mrmlScene) # adding to hierarchy is handled by the Reporting logic if elementType == 'MultiPoint': SlicerReportingModuleWidgetHelper.Debug("Importing a ruler!") if len(ijCoordList) != 4: SlicerReportingModuleWidgetHelper.Error( 'Number of coordinates not good for a ruler') return ruler = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLAnnotationRulerNode') ruler.SetReferenceCount(ruler.GetReferenceCount() - 1) # associate it with the volume ruler.SetAttribute("AssociatedNodeID", volume.GetID()) SlicerReportingModuleWidgetHelper.Debug( 'Initializing with points ' + str(rasPointList[0]) + ' and ' + str(rasPointList[1])) ruler.SetPosition1(rasPointList[0]) ruler.SetPosition2(rasPointList[1]) ruler.Initialize(slicer.mrmlScene) # AF: Initialize() adds to the scene ... for node in dom.getElementsByTagName('Segmentation'): # read all labels that are available in the SEG object # check if the referenced volume is already in the scene # if not, load it # initialize AssociatedNodeID for the label node to point to the # reference SlicerReportingModuleWidgetHelper.Debug('Importing a segmentation') labelNodes = vtk.vtkCollection() referenceNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLScalarVolumeNode') referenceNode.SetReferenceCount(referenceNode.GetReferenceCount() - 1) uid = node.getAttribute('sopInstanceUID') res = False colorNode = slicer.mrmlScene.GetNodeByID( newReport.GetColorNodeID()) res = slicer.modules.reporting.logic().DicomSegRead( labelNodes, uid, colorNode) SlicerReportingModuleWidgetHelper.Debug( 'Read this many labels from the seg object:' + str(labelNodes.GetNumberOfItems())) # read the reference node label0 = labelNodes.GetItemAsObject(0) referenceUIDs = label0.GetAttribute('DICOM.referenceInstanceUIDs') SlicerReportingModuleWidgetHelper.Debug( 'Seg object reference uids: ' + referenceUIDs) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLLabelMapVolumeDisplayNode') displayNode.SetReferenceCount(displayNode.GetReferenceCount() - 1) displayNode.SetAndObserveColorNodeID( newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('AssociatedNodeID', volumeList[0].GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNode) # AF: this shuould not be necessary with the "proper" AIM input, since # only one volume should be present in the report, and only one item in # that volume should be annotated if 0: # if referenceUIDs != None: reader = slicer.vtkMRMLVolumeArchetypeStorageNode() reader.ResetFileNameList() for uid in string.split(referenceUIDs, ' '): fname = slicer.modules.reporting.logic( ).GetFileNameFromUID(uid) reader.AddFileName(fname) reader.SetFileName(string.split(referenceUIDs, ' ')[0]) reader.SetSingleFile(0) referenceVolume = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLScalarVolumeNode') referenceVolumeUIDs = referenceVolume.GetAttribute( 'DICOM.instanceUIDs') reader.ReadData(referenceVolume) nodeToAdd = referenceVolume allVolumeNodes = slicer.mrmlScene.GetNodesByClass( 'vtkMRMLScalarVolumeNode') allVolumeNodes.SetReferenceCount( allVolumeNodes.GetReferenceCount() - 1) for i in range(allVolumeNodes.GetNumberOfItems()): v = allVolumeNodes.GetItemAsObject(i) uids = v.GetAttribute('DICOM.instanceUIDs') if uids == referenceNodeUIDs: print('Referenced node is already in the scene!') nodeToAdd = None referenceNode = v break if nodeToAdd != None: slicer.mrmlScene.AddNode(nodeToAdd) slicer.modules.reporting.logic().InitializeHierarchyForVolume( referenceNode) for i in range(labelNodes.GetNumberOfItems()): displayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLScalarVolumeDisplayNode') displayNode.SetReferenceCount( displayNode.GetReferenceCount() - 1) displayNode.SetAndObserveColorNodeID( newReport.GetColorNodeID()) slicer.mrmlScene.AddNode(displayNode) labelNode = labelNodes.GetItemAsObject(i) labelNode.SetAttribute('AssociatedNodeID', referenceNode.GetID()) labelNode.SetAndObserveDisplayNodeID(displayNode.GetID()) slicer.mrmlScene.AddNode(labelNodes.GetItemAsObject(i))
def load(self, loadable): """Load the selection as a MultiVolume, if multivolume attribute is present """ mvNode = '' try: mvNode = loadable.multivolume except AttributeError: return None nFrames = int(mvNode.GetAttribute('MultiVolume.NumberOfFrames')) files = string.split(mvNode.GetAttribute('MultiVolume.FrameFileList'), ',') nFiles = len(files) filesPerFrame = nFiles / nFrames frames = [] mvImage = vtk.vtkImageData() mvImageArray = None scalarVolumePlugin = slicer.modules.dicomPlugins[ 'DICOMScalarVolumePlugin']() instanceUIDs = "" for file in files: uid = slicer.dicomDatabase.fileValue(file, self.tags['instanceUID']) if uid == "": uid = "Unknown" instanceUIDs += uid + " " instanceUIDs = instanceUIDs[:-1] mvNode.SetAttribute("DICOM.instanceUIDs", instanceUIDs) # read each frame into scalar volume for frameNumber in range(nFrames): sNode = slicer.vtkMRMLVolumeArchetypeStorageNode() sNode.ResetFileNameList() frameFileList = files[frameNumber * filesPerFrame:(frameNumber + 1) * filesPerFrame] # sv plugin will sort the filenames by geometric order svLoadables = scalarVolumePlugin.examine([frameFileList]) if len(svLoadables) == 0: return None for f in svLoadables[0].files: sNode.AddFileName(f) sNode.SetFileName( frameFileList[0]) # only used when num files/frame = 1 sNode.SetSingleFile(0) frame = slicer.vtkMRMLScalarVolumeNode() sNode.ReadData(frame) if frame.GetImageData() == None: print('Failed to read a multivolume frame!') return None if frameNumber == 0: frameImage = frame.GetImageData() frameExtent = frameImage.GetExtent() frameSize = frameExtent[1] * frameExtent[3] * frameExtent[5] mvImage.SetExtent(frameExtent) if vtk.VTK_MAJOR_VERSION <= 5: mvImage.SetNumberOfScalarComponents(nFrames) mvImage.SetScalarType(frame.GetImageData().GetScalarType()) mvImage.AllocateScalars() else: mvImage.AllocateScalars( frame.GetImageData().GetScalarType(), nFrames) mvImageArray = vtk.util.numpy_support.vtk_to_numpy( mvImage.GetPointData().GetScalars()) mvNode.SetScene(slicer.mrmlScene) mat = vtk.vtkMatrix4x4() frame.GetRASToIJKMatrix(mat) mvNode.SetRASToIJKMatrix(mat) frame.GetIJKToRASMatrix(mat) mvNode.SetIJKToRASMatrix(mat) frameImage = frame.GetImageData() frameImageArray = vtk.util.numpy_support.vtk_to_numpy( frameImage.GetPointData().GetScalars()) mvImageArray.T[frameNumber] = frameImageArray mvDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetScene(slicer.mrmlScene) mvDisplayNode.SetDefaultColorMap() slicer.mrmlScene.AddNode(mvDisplayNode) mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(mvImage) mvNode.SetNumberOfFrames(nFrames) mvNode.SetName(loadable.name) slicer.mrmlScene.AddNode(mvNode) # # automatically select the volume to display # appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetReferenceActiveVolumeID(mvNode.GetID()) appLogic.PropagateVolumeSelection() # file list is no longer needed - remove the attribute mvNode.RemoveAttribute('MultiVolume.FrameFileList') return mvNode