|  | @@ -4,13 +4,9 @@ import unittest
 | 
	
		
			
				|  |  |  import vtk, qt, ctk, slicer
 | 
	
		
			
				|  |  |  from slicer.ScriptedLoadableModule import *
 | 
	
		
			
				|  |  |  import logging
 | 
	
		
			
				|  |  | -import parseDicom
 | 
	
		
			
				|  |  |  import vtkInterface as vi
 | 
	
		
			
				|  |  | -import fileIO
 | 
	
		
			
				|  |  |  import slicer
 | 
	
		
			
				|  |  |  import numpy as np
 | 
	
		
			
				|  |  | -import slicerNetwork
 | 
	
		
			
				|  |  | -import resample
 | 
	
		
			
				|  |  |  import json
 | 
	
		
			
				|  |  |  import re
 | 
	
		
			
				|  |  |  #
 | 
	
	
		
			
				|  | @@ -51,17 +47,12 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |      ScriptedLoadableModuleWidget.setup(self)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    self.selectRemote=fileIO.remoteFileSelector()
 | 
	
		
			
				|  |  | -    try:
 | 
	
		
			
				|  |  | -        self.network=slicer.modules.labkeySlicerPythonExtensionWidget.network
 | 
	
		
			
				|  |  | -    except:
 | 
	
		
			
				|  |  | -        self.network=slicerNetwork.labkeyURIHandler()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    configFile=os.path.join(os.path.expanduser('~'),'.cardiacSPECT','cardiacSPECT.json')
 | 
	
		
			
				|  |  | -    self.logic=cardiacSPECTLogic(configFile)
 | 
	
		
			
				|  |  | -    self.logic.setURIHandler(self.network)
 | 
	
		
			
				|  |  | -    self.selectRemote.setMaster(self)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    #load config
 | 
	
		
			
				|  |  | +    configFile=os.path.join(os.path.expanduser('~'),\
 | 
	
		
			
				|  |  | +              '.cardiacSPECT','cardiacSPECT.json')
 | 
	
		
			
				|  |  | +    with open(configFile) as f:
 | 
	
		
			
				|  |  | +          self.cfg=json.load(f)
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |      # Instantiate and connect widgets ...
 | 
	
		
			
				|  |  |      dataButton = ctk.ctkCollapsibleButton()
 | 
	
		
			
				|  |  |      dataButton.text = "Data"
 | 
	
	
		
			
				|  | @@ -241,6 +232,9 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      self.resetPosition=1
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    #add logic aware of all GUI elements on page
 | 
	
		
			
				|  |  | +    self.logic=cardiacSPECTLogic(self.cfg)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    def cleanup(self):
 | 
	
		
			
				|  |  |      pass
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -404,32 +398,46 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |    """
 | 
	
		
			
				|  |  |    def __init__(self,config):
 | 
	
		
			
				|  |  |        ScriptedLoadableModuleLogic.__init__(self)
 | 
	
		
			
				|  |  | +      sconfig=os.path.join(os.path.expanduser('~'),'.labkey','setup.json')
 | 
	
		
			
				|  |  | +      with open(sconfig) as f:
 | 
	
		
			
				|  |  | +            setup=json.load(f)
 | 
	
		
			
				|  |  | +      sys.path.append(setup['paths']['labkeyInterface'])
 | 
	
		
			
				|  |  | +      import labkeyInterface
 | 
	
		
			
				|  |  | +      import labkeyDatabaseBrowser
 | 
	
		
			
				|  |  | +      import labkeyFileBrowser
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      self.net=labkeyInterface.labkeyInterface()
 | 
	
		
			
				|  |  | +      fconfig=os.path.join(os.path.expanduser('~'),'.labkey','network.json')
 | 
	
		
			
				|  |  | +      self.net.init(fconfig)
 | 
	
		
			
				|  |  | +      self.db=labkeyDatabaseBrowser.labkeyDB(self.net)
 | 
	
		
			
				|  |  | +      self.fb=labkeyFileBrowser.labkeyFileBrowser(self.net)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      sys.path.append(setup['paths']['parseDicom'])
 | 
	
		
			
				|  |  | +      import parseDicom
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |        self.pd=parseDicom.parseDicomLogic(self)
 | 
	
		
			
				|  |  | +      self.pd.setFileBrowser(self.fb)
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      sys.path.append(setup['paths']['resample'])
 | 
	
		
			
				|  |  | +      import resample
 | 
	
		
			
				|  |  |        self.resampler=resample.resampleLogic(None)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      fname=config
 | 
	
		
			
				|  |  | -      try:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -          f=open(fname)
 | 
	
		
			
				|  |  | -      except OSError as e:
 | 
	
		
			
				|  |  | -          print "Confgiuration error: OS error({0}): {1}".format(e.errno, e.strerror)
 | 
	
		
			
				|  |  | -          return
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      self.cfg=json.load(f)
 | 
	
		
			
				|  |  | -      self.coreRelativePath=self.cfg["project"]+'/'+self.cfg['atFiles']
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  def setURIHandler(self,net):
 | 
	
		
			
				|  |  | -      self.net=net
 | 
	
		
			
				|  |  | -      self.pd.setURIHandler(net)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      self.tempPath=os.path.join(os.path.expanduser('~'),\
 | 
	
		
			
				|  |  | +              'temp','cardiacSPECT')
 | 
	
		
			
				|  |  | +      if not os.path.isdir(self.tempPath):
 | 
	
		
			
				|  |  | +          os.makedirs(self.tempPath)
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      self.cfg=config
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  |    def loadData(self,widget):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    #calculate inputDir from data on form
 | 
	
		
			
				|  |  |      inputDir=str(widget.dataPath.text)
 | 
	
		
			
				|  |  |      self.pd.readMasterDirectory(inputDir)
 | 
	
		
			
				|  |  |      self.frame_data, self.frame_time, self.frame_duration, self.frame_origin, \
 | 
	
		
			
				|  |  | -        self.frame_pixel_size, self.frame_orientation=self.pd.readNMDirectory(inputDir)
 | 
	
		
			
				|  |  | +        self.frame_pixel_size, \
 | 
	
		
			
				|  |  | +        self.frame_orientation=self.pd.readNMDirectory(inputDir)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      self.ct_data,self.ct_origin,self.ct_pixel_size, \
 | 
	
		
			
				|  |  |          self.ct_orientation=self.pd.readCTDirectory(inputDir)
 | 
	
	
		
			
				|  | @@ -450,25 +458,26 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def getFilespecPath(self,r):
 | 
	
		
			
				|  |  |        if self.cfg["remote"]==True:
 | 
	
		
			
				|  |  | -          path=r['_labkeyurl_Series']
 | 
	
		
			
				|  |  | -          path=path[:path.rfind('/')]
 | 
	
		
			
				|  |  | -          return "labkey://"+path
 | 
	
		
			
				|  |  | +          return self.fb.formatPathURL(self.cfg['project'],\
 | 
	
		
			
				|  |  | +                  '/'.join(self.cfg['imageDir'],r['Study'],r['Series']))
 | 
	
		
			
				|  |  |        else:
 | 
	
		
			
				|  |  |            path=os.path.join(self.cfg["dicomPath"],r["Study"],r["Series"])
 | 
	
		
			
				|  |  | -          return "file://"+path
 | 
	
		
			
				|  |  | +          return path
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def loadPatient(self,patientId):
 | 
	
		
			
				|  |  |        print("Loading {}").format(patientId)
 | 
	
		
			
				|  |  | -      ds=self.net.loadDataset("dinamic_spect/Patients","Imaging")
 | 
	
		
			
				|  |  | -      for r in ds['rows']:
 | 
	
		
			
				|  |  | -        if r['aliasID']==patientId:
 | 
	
		
			
				|  |  | -            visit=r
 | 
	
		
			
				|  |  | +      ds=self.db.selectRows(self.cfg['project'],self.cfg['schemaName'],
 | 
	
		
			
				|  |  | +              self.cfg['queryName'])
 | 
	
		
			
				|  |  | +      visit=[r for r in ds['rows'] if r['aliasID']==patientId][0]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        print visit
 | 
	
		
			
				|  |  | -      dicoms=self.net.loadDataset("Test/Transfer","Imaging")
 | 
	
		
			
				|  |  | +      idFilter={'variable':'PatientId','value':visit['aliasID'],'oper':'eq'}
 | 
	
		
			
				|  |  | +      dicoms=self.db.selectRows(self.cfg['transfer']['project'],
 | 
	
		
			
				|  |  | +              self.cfg['transfer']['schemaName'],
 | 
	
		
			
				|  |  | +              self.cfg['transfer']['queryName'],
 | 
	
		
			
				|  |  | +              [idFilter])
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  |        for r in dicoms['rows']:
 | 
	
		
			
				|  |  | -          if not r['PatientId']==visit['aliasID']:
 | 
	
		
			
				|  |  | -              continue
 | 
	
		
			
				|  |  |            if abs(r['SequenceNum']-float(visit['nmMaster']))<0.1:
 | 
	
		
			
				|  |  |                masterPath=self.getFilespecPath(r)
 | 
	
		
			
				|  |  |                #masterPath="labkey://"+path
 | 
	
	
		
			
				|  | @@ -533,13 +542,19 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |        self.loadNode(patientId,'Heart','SegmentationFile')
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def loadNode(self,patientId,fName,type,suffix='.nrrd'):
 | 
	
		
			
				|  |  | -      relativePath=self.coreRelativePath+'/'+patientId
 | 
	
		
			
				|  |  | -      labkeyFile=relativePath+'/'+fName+suffix
 | 
	
		
			
				|  |  | +      remotePath=self.fb.formatPathURL(self.cfg['project'],
 | 
	
		
			
				|  |  | +              '/'.join([patientId]))
 | 
	
		
			
				|  |  | +      labkeyFile=remotePath+'/'+fName+suffix
 | 
	
		
			
				|  |  | +      localFile=os.path.join(self.tempPath+fName+suffix)
 | 
	
		
			
				|  |  | +      self.fb.readFileToFile(labkeyFile,localFile)
 | 
	
		
			
				|  |  |        print ("Remote: {}").format(labkeyFile)
 | 
	
		
			
				|  |  | -      return self.net.loadNode(labkeyFile,type,returnNode=True)
 | 
	
		
			
				|  |  | +      node=slicer.util.loadNodeFromFile(localFile,type)
 | 
	
		
			
				|  |  | +      os.remove(localFile)
 | 
	
		
			
				|  |  | +      return node
 | 
	
		
			
				|  |  |        
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  def addNode(self,nodeName,v, lpsOrigin, pixel_size, lpsOrientation, dataType):
 | 
	
		
			
				|  |  | +  def addNode(self,nodeName,v, lpsOrigin, pixel_size, \
 | 
	
		
			
				|  |  | +          lpsOrientation, dataType):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |         # if dataType=0 it is CT data, which gets propagated to background an is
 | 
	
		
			
				|  |  |         #used to fit the view field dimensions
 | 
	
	
		
			
				|  | @@ -729,7 +744,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |            return "NONE"
 | 
	
		
			
				|  |  |        return segNode.GetSegmentation().GetSegment(segNode.GetSegmentation().GetNthSegmentID(i)).GetName()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  def storeNodeRemote(self,relativePath,nodeName):
 | 
	
		
			
				|  |  | +  def storeNodeRemote(self,pathList,nodeName):
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      node=slicer.mrmlScene.GetFirstNodeByName(nodeName)
 | 
	
		
			
				|  |  |      if node==None:
 | 
	
	
		
			
				|  | @@ -745,47 +760,33 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fileName=nodeName+suffix
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    localPath=self.getLocalPath(relativePath)
 | 
	
		
			
				|  |  | -    if not os.path.isdir(localPath):
 | 
	
		
			
				|  |  | -        os.mkdir(localPath)
 | 
	
		
			
				|  |  | +    localPath=os.path.join(self.tempPath,fileName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      file=os.path.join(localPath,fileName)
 | 
	
		
			
				|  |  |      slicer.util.saveNode(node,file)
 | 
	
		
			
				|  |  |      print("Stored to: {}").format(file)
 | 
	
		
			
				|  |  |      if self.cfg["remote"]:
 | 
	
		
			
				|  |  | -        labkeyPath=self.pd.net.GetLabkeyPathFromRelativePath(relativePath)
 | 
	
		
			
				|  |  | +        labkeyPath=self.fb.buildPathURL(self.cfg['project'],pathList)
 | 
	
		
			
				|  |  |          print ("Remote: {}").format(labkeyPath)
 | 
	
		
			
				|  |  |          #checks if exists
 | 
	
		
			
				|  |  | -        self.pd.net.mkdir(labkeyPath)
 | 
	
		
			
				|  |  |          remoteFile=labkeyPath+'/'+fileName
 | 
	
		
			
				|  |  | -        f=open(file,"rb")
 | 
	
		
			
				|  |  | -        self.pd.net.put(remoteFile,f.read())
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  def getLocalPath(self,relativePath):
 | 
	
		
			
				|  |  | -    if self.cfg["remote"]:
 | 
	
		
			
				|  |  | -        localPath=self.pd.net.GetLocalPathFromRelativePath(relativePath)
 | 
	
		
			
				|  |  | -        localPath.replace('/',os.path.sep)
 | 
	
		
			
				|  |  | -        return localPath
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -    localPath=os.path.join(self.cfg["labkeyBase"],relativePath)
 | 
	
		
			
				|  |  | -    return localPath
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        self.fb.writeFileToFile(localPath,remoteFile)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def storeVolumeNodes(self,patientId,n1,n2):
 | 
	
		
			
				|  |  |        #n1=self.time_frame.minimum;
 | 
	
		
			
				|  |  |        #n2=self.time_frame.maximum
 | 
	
		
			
				|  |  | -    relativePath=self.coreRelativePath+'/'+patientId
 | 
	
		
			
				|  |  | +    pathList=[patientId]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      print("Store CT")
 | 
	
		
			
				|  |  |      nodeName=patientId+'CT'
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    self.storeNodeRemote(relativePath,nodeName)
 | 
	
		
			
				|  |  | +    self.storeNodeRemote(pathList,nodeName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #prefer resampled
 | 
	
		
			
				|  |  |      testNode=slicer.util.getFirstNodeByName(nodeName+"_RS")
 | 
	
		
			
				|  |  |      if testNode:
 | 
	
		
			
				|  |  |          nodeName=nodeName+"_RS"
 | 
	
		
			
				|  |  | -        self.storeNodeRemote(relativePath,nodeName)
 | 
	
		
			
				|  |  | +        self.storeNodeRemote(pathList,nodeName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      print("Storing NM from {} to {}").format(n1,n2)
 | 
	
		
			
				|  |  |      n=n2-n1+1
 | 
	
	
		
			
				|  | @@ -793,35 +794,35 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
 | 
	
		
			
				|  |  |          it=i+n1
 | 
	
		
			
				|  |  |          nodeName=patientId+'Volume'+str(it)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        self.storeNodeRemote(relativePath,nodeName)
 | 
	
		
			
				|  |  | +        self.storeNodeRemote(pathList,nodeName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          #add resampled
 | 
	
		
			
				|  |  |          testNode=slicer.util.getFirstNodeByName(nodeName+"_RS")
 | 
	
		
			
				|  |  |          if testNode:
 | 
	
		
			
				|  |  |              nodeName=nodeName+"_RS"
 | 
	
		
			
				|  |  | -            self.storeNodeRemote(relativePath,nodeName)
 | 
	
		
			
				|  |  | +            self.storeNodeRemote(pathList,nodeName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      self.storeDummyInputFunction(patientId)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def storeSegmentation(self,patientId):
 | 
	
		
			
				|  |  | -      relativePath=self.coreRelativePath+'/'+patientId
 | 
	
		
			
				|  |  | +      pathList=[patientId]
 | 
	
		
			
				|  |  |        segNodeName="Heart"
 | 
	
		
			
				|  |  | -      self.storeNodeRemote(relativePath,segNodeName)
 | 
	
		
			
				|  |  | +      self.storeNodeRemote(pathList,segNodeName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def storeInputFunction(self,patientId):
 | 
	
		
			
				|  |  |        self.calculateInputFunction(patientId)
 | 
	
		
			
				|  |  | -      relativePath=self.coreRelativePath+'/'+patientId
 | 
	
		
			
				|  |  | +      relativePath=[patientId]
 | 
	
		
			
				|  |  |        doubleArrayNodeName=patientId+'_Ventricle'
 | 
	
		
			
				|  |  |        self.storeNodeRemote(relativePath,doubleArrayNodeName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def storeDummyInputFunction(self,patientId):
 | 
	
		
			
				|  |  |        self.calculateDummyInputFunction(patientId)
 | 
	
		
			
				|  |  | -      relativePath=self.coreRelativePath+'/'+patientId
 | 
	
		
			
				|  |  | +      relativePath=[patientId]
 | 
	
		
			
				|  |  |        doubleArrayNodeName=patientId+'_Dummy'
 | 
	
		
			
				|  |  |        self.storeNodeRemote(relativePath,doubleArrayNodeName)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    def storeTransformation(self,patientId):
 | 
	
		
			
				|  |  | -      relativePath=self.coreRelativePath+'/'+patientId
 | 
	
		
			
				|  |  | +      relativePath=[patientId]
 | 
	
		
			
				|  |  |        transformNodeName=patientId+"_DF"
 | 
	
		
			
				|  |  |        self.storeNodeRemote(relativePath,transformNodeName)
 | 
	
		
			
				|  |  |  
 |