|  | @@ -7,7 +7,8 @@ import datetime
 | 
	
		
			
				|  |  |  import sys
 | 
	
		
			
				|  |  |  import nixModule
 | 
	
		
			
				|  |  |  import pathlib
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +import chardet
 | 
	
		
			
				|  |  | +import re
 | 
	
		
			
				|  |  |  #
 | 
	
		
			
				|  |  |  # labkeySlicerPythonExtension
 | 
	
		
			
				|  |  |  #
 | 
	
	
		
			
				|  | @@ -69,6 +70,9 @@ class imageBrowserWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |          self.petField=qt.QLabel("petResampled")
 | 
	
		
			
				|  |  |          infoLayout.addRow("Data field (PET):",self.petField)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        self.userField=qt.QLabel("Loading")
 | 
	
		
			
				|  |  | +        infoLayout.addRow("User",self.userField)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          self.idField=qt.QLabel("Loading")
 | 
	
		
			
				|  |  |          infoLayout.addRow("ID",self.idField)
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -115,6 +119,10 @@ class imageBrowserWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |          self.patientLoad.clicked.connect(self.onPatientLoadButtonClicked)
 | 
	
		
			
				|  |  |          patientsFormLayout.addRow("Load patient",self.patientLoad)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        self.patientSave=qt.QPushButton("Save")
 | 
	
		
			
				|  |  | +        self.patientSave.clicked.connect(self.onPatientSaveButtonClicked)
 | 
	
		
			
				|  |  | +        patientsFormLayout.addRow("Save segmentation",self.patientSave)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          self.patientClear=qt.QPushButton("Clear")
 | 
	
		
			
				|  |  |          self.patientClear.clicked.connect(self.onPatientClearButtonClicked)
 | 
	
		
			
				|  |  |          patientsFormLayout.addRow("Clear patient",self.patientClear)
 | 
	
	
		
			
				|  | @@ -235,13 +243,14 @@ class imageBrowserWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |              pass 
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          self.idField.setText(status['id'])
 | 
	
		
			
				|  |  | +        self.userField.setText(status['displayName'])
 | 
	
		
			
				|  |  |          self.serverList.setStyleSheet('background-color: green')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def onPatientListChanged(self,i):
 | 
	
		
			
				|  |  |          idFilter={'variable':'PatientId',
 | 
	
		
			
				|  |  |              'value':self.patientList.currentText,
 | 
	
		
			
				|  |  |              'oper':'eq'}
 | 
	
		
			
				|  |  | -        ds=self.logic.getDataset([idFilter])
 | 
	
		
			
				|  |  | +        ds=self.logic.getDataset(dbFilter=[idFilter])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          seq=[int(row['SequenceNum']) for row in ds['rows']]
 | 
	
		
			
				|  |  |          self.visitList.clear()  
 | 
	
	
		
			
				|  | @@ -260,7 +269,7 @@ class imageBrowserWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |          idFilter={'variable':'PatientId',\
 | 
	
		
			
				|  |  |                'value':self.patientList.currentText,'oper':'eq'}
 | 
	
		
			
				|  |  |          sFilter={'variable':'SequenceNum','value':s,'oper':'eq'}
 | 
	
		
			
				|  |  | -        ds=self.logic.getDataset([idFilter,sFilter])
 | 
	
		
			
				|  |  | +        ds=self.logic.getDataset(dbFilter=[idFilter,sFilter])
 | 
	
		
			
				|  |  |          if not len(ds['rows'])==1:
 | 
	
		
			
				|  |  |              print("Found incorrect number {} of matches for [{}]/[{}]".\
 | 
	
		
			
				|  |  |                    format(len(ds['rows']),\
 | 
	
	
		
			
				|  | @@ -277,6 +286,7 @@ class imageBrowserWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |          print("Load")
 | 
	
		
			
				|  |  |          #delegate loading to logic
 | 
	
		
			
				|  |  |          self.logic.loadImages(self.currentRow,self.keepCached.isChecked())
 | 
	
		
			
				|  |  | +        self.logic.loadSegmentation(self.currentRow)
 | 
	
		
			
				|  |  |          #self.logic.loadReview(self.currentRow)
 | 
	
		
			
				|  |  |          #self.logic.loadAE(self.currentRow)
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -287,9 +297,9 @@ class imageBrowserWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def onPatientClearButtonClicked(self):
 | 
	
		
			
				|  |  |          self.logic.clearVolumesAndSegmentations()
 | 
	
		
			
				|  |  | -        #self.reviewSegment.clear()
 | 
	
		
			
				|  |  | -        #self.removeCompletedSegments()
 | 
	
		
			
				|  |  | -        #self.reviewComment.clear()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def onPatientSaveButtonClicked(self):
 | 
	
		
			
				|  |  | +        self.logic.saveSegmentation()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def cleanup(self):
 | 
	
		
			
				|  |  |          pass
 | 
	
	
		
			
				|  | @@ -348,6 +358,9 @@ class imageBrowserLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |          self.network=labkeyInterface.labkeyInterface() 
 | 
	
		
			
				|  |  |          self.dbBrowser=labkeyDatabaseBrowser
 | 
	
		
			
				|  |  |          self.fBrowser=labkeyFileBrowser
 | 
	
		
			
				|  |  | +        self.tempDir=os.path.join(os.path.expanduser('~'),'temp')
 | 
	
		
			
				|  |  | +        if not os.path.isdir(self.tempDir):
 | 
	
		
			
				|  |  | +            os.mkdir(self.tempDir)
 | 
	
		
			
				|  |  |          print('imageBrowserLogic setup complete')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -365,13 +378,16 @@ class imageBrowserLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |              return status
 | 
	
		
			
				|  |  |          fconfig=os.path.join(os.path.expanduser('~'),'.labkey',fileName)
 | 
	
		
			
				|  |  |          self.network.init(fconfig)
 | 
	
		
			
				|  |  | -        remoteId=self.network.getUserId()
 | 
	
		
			
				|  |  | +        self.remoteId=self.network.getUserId()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        if remoteId==None:
 | 
	
		
			
				|  |  | +        if self.remoteId==None:
 | 
	
		
			
				|  |  |              status['error']='ID ERROR'
 | 
	
		
			
				|  |  |              return status
 | 
	
		
			
				|  |  |       
 | 
	
		
			
				|  |  | -        status['id']=remoteId['displayName']
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        status['displayName']=self.remoteId['displayName']
 | 
	
		
			
				|  |  | +        status['id']=self.remoteId['id']
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          #reset db and fb (they are thin classes anyhow)
 | 
	
		
			
				|  |  |          self.db=self.dbBrowser.labkeyDB(self.network)
 | 
	
		
			
				|  |  |          self.fb=self.fBrowser.labkeyFileBrowser(self.network)
 | 
	
	
		
			
				|  | @@ -388,34 +404,41 @@ class imageBrowserLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |          with open(fileName,'r') as f:
 | 
	
		
			
				|  |  |              self.isetup=json.load(f)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        self.project=self.isetup['project']
 | 
	
		
			
				|  |  | +        #self.project=self.isetup['project']
 | 
	
		
			
				|  |  |          #"iPNUMMretro/Study"
 | 
	
		
			
				|  |  | -        self.schema='study'
 | 
	
		
			
				|  |  | -        self.dataset=self.isetup['query']
 | 
	
		
			
				|  |  | +        #self.schema='study'
 | 
	
		
			
				|  |  | +        #self.dataset=self.isetup['query']
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -        ds=self.getDataset([])
 | 
	
		
			
				|  |  | +        ds=self.getDataset()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          ids=[row[self.isetup['participantField']] for row in ds['rows']]
 | 
	
		
			
				|  |  |          status['ids']=list(set(ids))
 | 
	
		
			
				|  |  |          return status
 | 
	
		
			
				|  |  |          
 | 
	
		
			
				|  |  | -    def getDataset(self,dbFilter):
 | 
	
		
			
				|  |  | -        project=self.project
 | 
	
		
			
				|  |  | -        schema=self.schema
 | 
	
		
			
				|  |  | -        query=self.dataset
 | 
	
		
			
				|  |  | +    def getDataset(self,name="Imaging",dbFilter=[]):
 | 
	
		
			
				|  |  | +        dset=self.isetup['datasets'][name]
 | 
	
		
			
				|  |  | +        project=dset['project']
 | 
	
		
			
				|  |  | +        schema=dset['schema']
 | 
	
		
			
				|  |  | +        query=dset['query']
 | 
	
		
			
				|  |  |          try:
 | 
	
		
			
				|  |  |              return self.db.selectRows(project,schema,query, \
 | 
	
		
			
				|  |  | -                dbFilter,self.isetup['view'])
 | 
	
		
			
				|  |  | +                dbFilter,dset['view'])
 | 
	
		
			
				|  |  |          except KeyError:
 | 
	
		
			
				|  |  |              return self.db.selectRows(project,schema,query,dbFilter)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def loadImage(self,idx,path,tempDir,keepCached):
 | 
	
		
			
				|  |  | +    def loadImage(self,iData):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        localPath=os.path.join(tempDir,path[-1])
 | 
	
		
			
				|  |  | +        #unpack iData
 | 
	
		
			
				|  |  | +        idx=iData['idx']
 | 
	
		
			
				|  |  | +        path=iData['path']
 | 
	
		
			
				|  |  | +        keepCached=iData['keepCached']
 | 
	
		
			
				|  |  | +        dset=self.isetup['datasets'][iData['dataset']]
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        localPath=os.path.join(self.tempDir,path[-1])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if not os.path.isfile(localPath):
 | 
	
		
			
				|  |  |              #download from server
 | 
	
		
			
				|  |  | -            remotePath=self.fb.formatPathURL(self.project,'/'.join(path))
 | 
	
		
			
				|  |  | +            remotePath=self.fb.formatPathURL(dset['project'],'/'.join(path))
 | 
	
		
			
				|  |  |              if not self.fb.entryExists(remotePath):
 | 
	
		
			
				|  |  |                  print("Failed to get {}".format(remotePath))
 | 
	
		
			
				|  |  |                  return
 | 
	
	
		
			
				|  | @@ -423,13 +446,16 @@ class imageBrowserLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |              self.fb.readFileToFile(remotePath,localPath) 
 | 
	
		
			
				|  |  |            
 | 
	
		
			
				|  |  |          properties={}
 | 
	
		
			
				|  |  | +        filetype='VolumeFile'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          #make sure segmentation gets loaded as a labelmap
 | 
	
		
			
				|  |  |          if idx=="Segmentation":
 | 
	
		
			
				|  |  | -            properties["labelmap"]=1
 | 
	
		
			
				|  |  | +            filetype='SegmentationFile'
 | 
	
		
			
				|  |  | +            #properties["labelmap"]=1
 | 
	
		
			
				|  |  |                
 | 
	
		
			
				|  |  |            
 | 
	
		
			
				|  |  |          self.volumeNode[idx]=slicer.util.loadNodeFromFile(localPath,
 | 
	
		
			
				|  |  | -                        filetype='VolumeFile',properties=properties)
 | 
	
		
			
				|  |  | +                        filetype=filetype,properties=properties)
 | 
	
		
			
				|  |  |            
 | 
	
		
			
				|  |  |          if not keepCached:
 | 
	
		
			
				|  |  |              os.remove(localPath)
 | 
	
	
		
			
				|  | @@ -437,21 +463,19 @@ class imageBrowserLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def loadImages(self,row,keepCached):
 | 
	
		
			
				|  |  |        
 | 
	
		
			
				|  |  | -        tempDir=os.path.join(os.path.expanduser('~'),'temp')
 | 
	
		
			
				|  |  | -        if not os.path.isdir(tempDir):
 | 
	
		
			
				|  |  | -            os.mkdir(tempDir)
 | 
	
		
			
				|  |  |        
 | 
	
		
			
				|  |  |          #fields={'ctResampled':True,'petResampled':False}
 | 
	
		
			
				|  |  |          fields={"CT":self.parent.ctField.text,\
 | 
	
		
			
				|  |  |                "PET":self.parent.petField.text}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        path=['preprocessedImages',row['patientCode'],row['visitCode']]
 | 
	
		
			
				|  |  | +        path=[self.isetup['imageDir'],row['patientCode'],row['visitCode']]
 | 
	
		
			
				|  |  |          relativePaths={x:path+[row[y]] for (x,y) in fields.items()}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          self.volumeNode={}
 | 
	
		
			
				|  |  |          for f in relativePaths:
 | 
	
		
			
				|  |  | -            p=relativePaths[f]
 | 
	
		
			
				|  |  | -            self.loadImage(f,p,tempDir,keepCached)
 | 
	
		
			
				|  |  | +            iData={'idx':f,'path':relativePaths[f],
 | 
	
		
			
				|  |  | +                    'keepCached':keepCached,'dataset':'Imaging'}
 | 
	
		
			
				|  |  | +            self.loadImage(iData)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          #mimic abdominalCT standardized window setting
 | 
	
		
			
				|  |  |          self.volumeNode['CT'].GetScalarVolumeDisplayNode().\
 | 
	
	
		
			
				|  | @@ -462,12 +486,124 @@ class imageBrowserLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |              SetAndObserveColorNodeID(\
 | 
	
		
			
				|  |  |              slicer.util.getNode('PET-Heat').GetID())
 | 
	
		
			
				|  |  |          slicer.util.setSliceViewerLayers(background=self.volumeNode['CT'],\
 | 
	
		
			
				|  |  | -            foreground=self.volumeNode['PET'],foregroundOpacity=0.1,fit=True)
 | 
	
		
			
				|  |  | +            foreground=self.volumeNode['PET'],foregroundOpacity=0.5,fit=True)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def loadSegmentation(self,row):
 | 
	
		
			
				|  |  | +        userFilter={'variable':'User','value':'{}'.format(self.remoteId['id']),
 | 
	
		
			
				|  |  | +                'oper':'eq'}
 | 
	
		
			
				|  |  | +        pField=self.isetup['participantField']
 | 
	
		
			
				|  |  | +        idFilter={'variable':pField,'value':row[pField],'oper':'eq'}
 | 
	
		
			
				|  |  | +        visitFilter={'variable':'visitCode','value':row['visitCode'],'oper':'eq'}
 | 
	
		
			
				|  |  | +        ds=self.getDataset(name='SegmentationsMaster',
 | 
	
		
			
				|  |  | +                dbFilter=[idFilter,visitFilter,userFilter])
 | 
	
		
			
				|  |  | +        if len(ds['rows'])>1:
 | 
	
		
			
				|  |  | +            print('Multiple segmentations found!')
 | 
	
		
			
				|  |  | +            return
 | 
	
		
			
				|  |  | +        if len(ds['rows'])==1:
 | 
	
		
			
				|  |  | +            #update self.segmentationEntry
 | 
	
		
			
				|  |  | +            self.segmentationEntry=ds['rows'][0]
 | 
	
		
			
				|  |  | +            self.segmentationEntry['origin']='database'
 | 
	
		
			
				|  |  | +            self.loadSegmentationFromEntry()
 | 
	
		
			
				|  |  | +            return
 | 
	
		
			
				|  |  | +        #create new segmentation 
 | 
	
		
			
				|  |  | +        self.createSegmentation(row)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def getSegmentationPath(self):
 | 
	
		
			
				|  |  | +        path=[self.isetup['imageDir'],
 | 
	
		
			
				|  |  | +                self.segmentationEntry['patientCode'],
 | 
	
		
			
				|  |  | +                self.segmentationEntry['visitCode']]
 | 
	
		
			
				|  |  | +        path.append('Segmentations')
 | 
	
		
			
				|  |  | +        return path
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def loadSegmentationFromEntry(self):
 | 
	
		
			
				|  |  | +        #compile path
 | 
	
		
			
				|  |  | +        entry=self.segmentationEntry
 | 
	
		
			
				|  |  | +        path=self.getSegmentationPath()
 | 
	
		
			
				|  |  | +        path.append(entry['latestFile'])
 | 
	
		
			
				|  |  | +        iData={'idx':'Segmentation','path':path,
 | 
	
		
			
				|  |  | +                    'keepCached':0,'dataset':'SegmentationsMaster'}
 | 
	
		
			
				|  |  | +        self.loadImage(iData)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def saveSegmentation(self):
 | 
	
		
			
				|  |  | +        #get the latest key by adding an entry to SegmentationList
 | 
	
		
			
				|  |  | +        copyFields=['ParticipantId','patientCode','visitCode','User']
 | 
	
		
			
				|  |  | +        outRow={x:self.segmentationEntry[x] for x in copyFields}
 | 
	
		
			
				|  |  | +        sList=self.isetup['datasets']['SegmentationsList']
 | 
	
		
			
				|  |  | +        resp=self.db.modifyRows('insert',sList['project'],
 | 
	
		
			
				|  |  | +            sList['schema'],sList['query'],[outRow])
 | 
	
		
			
				|  |  | +        encoding=chardet.detect(resp)['encoding']
 | 
	
		
			
				|  |  | +        respJSON=json.loads(resp.decode(encoding))
 | 
	
		
			
				|  |  | +        outRow=respJSON['rows'][0]
 | 
	
		
			
				|  |  | +        #print(outRow)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #construct file name with known key
 | 
	
		
			
				|  |  | +        uName=re.sub(' ','_',self.remoteId['displayName'])
 | 
	
		
			
				|  |  | +        fName='Segmentation_{}-{}_{}_{}.nrrd'.format(
 | 
	
		
			
				|  |  | +                self.segmentationEntry['patientCode'],
 | 
	
		
			
				|  |  | +                self.segmentationEntry['visitCode'],
 | 
	
		
			
				|  |  | +                uName,outRow['Key'])
 | 
	
		
			
				|  |  | +        path=self.getSegmentationPath()
 | 
	
		
			
				|  |  | +        path.append(fName)
 | 
	
		
			
				|  |  | +        self.saveNode(self.volumeNode['Segmentation'],'SegmentationsMaster',path)
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        #update SegmentationList with know file name
 | 
	
		
			
				|  |  | +        outRow['Segmentation']=fName
 | 
	
		
			
				|  |  | +        self.db.modifyRows('update',sList['project'],
 | 
	
		
			
				|  |  | +            sList['schema'],sList['query'],[outRow])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #update SegmentationsMaster
 | 
	
		
			
				|  |  | +        self.segmentationEntry['latestFile']=fName
 | 
	
		
			
				|  |  | +        self.segmentationEntry['version']=outRow['Key']
 | 
	
		
			
				|  |  | +        des=self.isetup['datasets']['SegmentationsMaster']
 | 
	
		
			
				|  |  | +        op='insert'
 | 
	
		
			
				|  |  | +        if self.segmentationEntry['origin']=='database':
 | 
	
		
			
				|  |  | +            op='update'
 | 
	
		
			
				|  |  | +        self.db.modifyRows(op,des['project'],
 | 
	
		
			
				|  |  | +                des['schema'],des['query'],[self.segmentationEntry])
 | 
	
		
			
				|  |  | +        #since we loaded a version, origin should be set to dataset
 | 
	
		
			
				|  |  | +        self.segmentationEntry['origin']='dataset'
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def saveNode(self,node,dataset,path):
 | 
	
		
			
				|  |  | +        fName=path[-1]
 | 
	
		
			
				|  |  | +        localPath=os.path.join(self.tempDir,fName)
 | 
	
		
			
				|  |  | +        slicer.util.saveNode(node,localPath)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        dset=self.isetup['datasets'][dataset]
 | 
	
		
			
				|  |  | +        #exclude file name when building directory structure
 | 
	
		
			
				|  |  | +        remotePath=self.fb.buildPathURL(dset['project'],path[:-1])
 | 
	
		
			
				|  |  | +        remotePath+='/'+fName
 | 
	
		
			
				|  |  | +        self.fb.writeFileToFile(localPath,remotePath)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #add entry to segmentation list
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def createSegmentation(self,entry):
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #create segmentation entry for database update
 | 
	
		
			
				|  |  | +        #note that origin is not set to database
 | 
	
		
			
				|  |  | +        copyFields=['ParticipantId','patientCode','visitCode','SequenceNum']
 | 
	
		
			
				|  |  | +        self.segmentationEntry={x:entry[x] for x in copyFields}
 | 
	
		
			
				|  |  | +        self.segmentationEntry['User']=self.remoteId['id']
 | 
	
		
			
				|  |  | +        self.segmentationEntry['origin']='created'
 | 
	
		
			
				|  |  | +        self.segmentationEntry['version']=-1111
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +        #create a segmentation node
 | 
	
		
			
				|  |  | +        uName=re.sub(' ','_',self.remoteId['displayName'])
 | 
	
		
			
				|  |  | +        segNode=slicer.vtkMRMLSegmentationNode()
 | 
	
		
			
				|  |  | +        self.volumeNode['Segmentation']=segNode
 | 
	
		
			
				|  |  | +        segNode.SetName('Segmentation_{}_{}_{}'.
 | 
	
		
			
				|  |  | +                format(entry['patientCode'],entry['visitCode'],uName))
 | 
	
		
			
				|  |  | +        slicer.mrmlScene.AddNode(segNode)
 | 
	
		
			
				|  |  | +        segNode.CreateDefaultDisplayNodes()
 | 
	
		
			
				|  |  | +        segNode.SetReferenceImageGeometryParameterFromVolumeNode(self.volumeNode['PET'])
 | 
	
		
			
				|  |  | +        segNode.GetSegmentation().AddEmptySegment("Lesion","Lesion")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def clearVolumesAndSegmentations(self):
 | 
	
		
			
				|  |  |          nodes=slicer.util.getNodesByClass("vtkMRMLVolumeNode")
 | 
	
		
			
				|  |  | -        #nodes.extend(slicer.util.getNodesByClass("vtkMRMLSegmentationNode"))
 | 
	
		
			
				|  |  | +        nodes.extend(slicer.util.getNodesByClass("vtkMRMLSegmentationNode"))
 | 
	
		
			
				|  |  |          res=[slicer.mrmlScene.RemoveNode(f) for f in nodes] 
 | 
	
		
			
				|  |  |          #self.segmentationNode=None
 | 
	
		
			
				|  |  |          #self.reviewResult={}
 |