|
@@ -4,7 +4,6 @@ import unittest
|
|
|
import vtk, qt, ctk, slicer
|
|
|
from slicer.ScriptedLoadableModule import *
|
|
|
import logging
|
|
|
-import vtkInterface as vi
|
|
|
import slicer
|
|
|
import numpy as np
|
|
|
import json
|
|
@@ -52,7 +51,26 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
'.cardiacSPECT','cardiacSPECT.json')
|
|
|
with open(configFile) as f:
|
|
|
self.cfg=json.load(f)
|
|
|
-
|
|
|
+
|
|
|
+ #need labkey browser here
|
|
|
+ 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)
|
|
|
+
|
|
|
+ ds=self.db.selectRows(self.cfg['project'],self.cfg['schemaName'],\
|
|
|
+ self.cfg['queryName'],[])
|
|
|
+
|
|
|
+ patients=list(set([row['aliasID'] for row in ds['rows']]))
|
|
|
+
|
|
|
# Instantiate and connect widgets ...
|
|
|
dataButton = ctk.ctkCollapsibleButton()
|
|
|
dataButton.text = "Data"
|
|
@@ -63,10 +81,12 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
|
|
|
|
|
|
|
|
|
- self.patientId=qt.QLineEdit();
|
|
|
+ self.patientId=qt.QComboBox()
|
|
|
+ self.patientId.insertItems(0,patients)
|
|
|
dataFormLayout.addRow('Patient ID', self.patientId)
|
|
|
|
|
|
- self.refPatientId=qt.QLineEdit();
|
|
|
+ self.refPatientId=qt.QComboBox();
|
|
|
+ self.refPatientId.insertItems(0,patients)
|
|
|
dataFormLayout.addRow('Reference Patient ID', self.refPatientId)
|
|
|
|
|
|
|
|
@@ -263,7 +283,7 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
it=self.time_frame_select.value
|
|
|
selectionNode = slicer.app.applicationLogic().GetSelectionNode()
|
|
|
print("Propagating CT volume")
|
|
|
- nodeName=self.patientId.text+'CT'
|
|
|
+ nodeName=self.patientId.currentText+'CT'
|
|
|
node=slicer.mrmlScene.GetFirstNodeByName(nodeName)
|
|
|
selectionNode.SetReferenceActiveVolumeID(node.GetID())
|
|
|
if self.resetPosition==1:
|
|
@@ -272,7 +292,7 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
else:
|
|
|
slicer.app.applicationLogic().PropagateVolumeSelection(0)
|
|
|
print("Propagating SPECT volume")
|
|
|
- nodeName=self.patientId.text+'Volume'+str(it)
|
|
|
+ nodeName=self.patientId.currentText+'Volume'+str(it)
|
|
|
node=slicer.mrmlScene.GetFirstNodeByName(nodeName)
|
|
|
selectionNode.SetSecondaryVolumeID(node.GetID())
|
|
|
slicer.app.applicationLogic().PropagateForegroundVolumeSelection(0)
|
|
@@ -309,12 +329,12 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
dn = slicer.mrmlScene.AddNode(slicer.vtkMRMLDoubleArrayNode())
|
|
|
|
|
|
dn.SetSize(n)
|
|
|
- dn.SetName(self.patientId.text+'_'+self.logic.getSegmentName(j))
|
|
|
+ dn.SetName(self.patientId.currentText+'_'+self.logic.getSegmentName(j))
|
|
|
|
|
|
dt=0;
|
|
|
t0=0;
|
|
|
for i in range(0,n):
|
|
|
- vol=self.patientId.text+"Volume"+str(i)
|
|
|
+ vol=self.patientId.currentText+"Volume"+str(i)
|
|
|
fx=ft[i]
|
|
|
fy=self.logic.meanROI(vol,j)
|
|
|
dt=2*ft[i]-t0
|
|
@@ -342,37 +362,37 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
cvn.SetChartNodeID(cn.GetID())
|
|
|
|
|
|
def onCountSegmentsClicked(self):
|
|
|
- self.countSegmentsDisplay.setText(self.logic.countSegments())
|
|
|
-
|
|
|
+ self.countSegmentsDisplay.setText(self.logic.countSegments)
|
|
|
+
|
|
|
def onPatientLoadButtonClicked(self):
|
|
|
- self.logic.loadPatient(self.patientId.text)
|
|
|
+ self.logic.loadPatient(self.patientId.currentText)
|
|
|
self.time_frame_select.setMaximum(self.logic.frame_data.shape[3]-1)
|
|
|
|
|
|
def onPatientLoadNRRDButtonClicked(self):
|
|
|
- self.logic.loadPatientNRRD(self.patientId.text)
|
|
|
+ self.logic.loadPatientNRRD(self.patientId.currentText)
|
|
|
self.time_frame_select.setMaximum(len(self.logic.frame_time))
|
|
|
|
|
|
def onLoadSegmentationButtonClicked(self):
|
|
|
- self.logic.loadSegmentation(self.patientId.text)
|
|
|
+ self.logic.loadSegmentation(self.patientId.currentText)
|
|
|
|
|
|
def onLoadModelButtonClicked(self):
|
|
|
- self.logic.loadModelVolume(self.patientId.text,self.modelParameter.text)
|
|
|
+ self.logic.loadModelVolume(self.patientId.currentText,self.modelParameter.text)
|
|
|
|
|
|
def onSaveVolumeButtonClicked(self):
|
|
|
- self.logic.storeVolumeNodes(self.patientId.text,
|
|
|
+ self.logic.storeVolumeNodes(self.patientId.currentText,
|
|
|
self.time_frame_select.minimum,self.time_frame_select.maximum)
|
|
|
|
|
|
def onSaveSegmentationButtonClicked(self):
|
|
|
- self.logic.storeSegmentation(self.patientId.text)
|
|
|
+ self.logic.storeSegmentation(self.patientId.currentText)
|
|
|
|
|
|
def onSaveTransformationButtonClicked(self):
|
|
|
- self.logic.storeTransformation(self.patientId.text)
|
|
|
+ self.logic.storeTransformation(self.patientId.currentText)
|
|
|
|
|
|
def onSaveInputFunctionButtonClicked(self):
|
|
|
- self.logic.storeInputFunction(self.patientId.text)
|
|
|
+ self.logic.storeInputFunction(self.patientId.currentText)
|
|
|
|
|
|
def onTransformNodeButtonClicked(self):
|
|
|
- self.logic.applyTransform(self.patientId.text, self.refPatientId.text,
|
|
|
+ self.logic.applyTransform(self.patientId.currentText, self.refPatientId.currentText,
|
|
|
self.time_frame_select.minimum,self.time_frame_select.maximum)
|
|
|
|
|
|
|
|
@@ -418,20 +438,25 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
self.pd=parseDicom.parseDicomLogic(self)
|
|
|
self.pd.setFileBrowser(self.fb)
|
|
|
|
|
|
+ self.tempPath=os.path.join(os.path.expanduser('~'),\
|
|
|
+ 'temp','cardiacSPECT')
|
|
|
+ if not os.path.isdir(self.tempPath):
|
|
|
+ os.makedirs(self.tempPath)
|
|
|
+
|
|
|
+ self.pd.setTempBase(self.tempPath)
|
|
|
+
|
|
|
sys.path.append(setup['paths']['resample'])
|
|
|
import resample
|
|
|
self.resampler=resample.resampleLogic(None)
|
|
|
|
|
|
+ sys.path.append(setup['paths']['vtkInterface'])
|
|
|
|
|
|
- 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):
|
|
|
-
|
|
|
+ import vtkInterface
|
|
|
#calculate inputDir from data on form
|
|
|
inputDir=str(widget.dataPath.text)
|
|
|
self.pd.readMasterDirectory(inputDir)
|
|
@@ -442,8 +467,8 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
self.ct_data,self.ct_origin,self.ct_pixel_size, \
|
|
|
self.ct_orientation=self.pd.readCTDirectory(inputDir)
|
|
|
|
|
|
- self.ct_orientation=vi.completeOrientation(self.ct_orientation)
|
|
|
- self.frame_orientation=vi.completeOrientation(self.frame_orientation)
|
|
|
+ self.ct_orientation=vtkInterface.completeOrientation(self.ct_orientation)
|
|
|
+ self.frame_orientation=vtkInterface.completeOrientation(self.frame_orientation)
|
|
|
|
|
|
self.addCT('test')
|
|
|
self.addFrames('test')
|
|
@@ -458,19 +483,22 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
|
|
|
def getFilespecPath(self,r):
|
|
|
if self.cfg["remote"]==True:
|
|
|
- return self.fb.formatPathURL(self.cfg['project'],\
|
|
|
- '/'.join(self.cfg['imageDir'],r['Study'],r['Series']))
|
|
|
+ return self.fb.formatPathURL(self.cfg['transfer']['project'],\
|
|
|
+ '/'.join([self.cfg['dicomDir'],r['Study'],r['Series']]))
|
|
|
else:
|
|
|
path=os.path.join(self.cfg["dicomPath"],r["Study"],r["Series"])
|
|
|
return path
|
|
|
|
|
|
def loadPatient(self,patientId):
|
|
|
- print("Loading {}").format(patientId)
|
|
|
+
|
|
|
+ import vtkInterface
|
|
|
+ print("Loading {}".format(patientId))
|
|
|
+ idFilter={'variable':'aliasID','value':patientId,'oper':'eq'}
|
|
|
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]
|
|
|
+ self.cfg['queryName'],[idFilter])
|
|
|
+ visit=ds['rows'][0]
|
|
|
|
|
|
- print visit
|
|
|
+ print(visit)
|
|
|
idFilter={'variable':'PatientId','value':visit['aliasID'],'oper':'eq'}
|
|
|
dicoms=self.db.selectRows(self.cfg['transfer']['project'],
|
|
|
self.cfg['transfer']['schemaName'],
|
|
@@ -491,19 +519,20 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
|
|
|
self.pd.readMasterDirectory(masterPath)
|
|
|
self.frame_data, self.frame_time, self.frame_duration,self.frame_origin, \
|
|
|
- self.frame_pixel_size, self.frame_orientation=self.pd.readNMDirectory(nmPath)
|
|
|
+ self.frame_pixel_size, self.frame_orientation=\
|
|
|
+ self.pd.readNMDirectory(nmPath)
|
|
|
self.ct_data,self.ct_origin,self.ct_pixel_size, \
|
|
|
self.ct_orientation=self.pd.readCTDirectory(ctPath)
|
|
|
|
|
|
- self.ct_orientation=vi.completeOrientation(self.ct_orientation)
|
|
|
- self.frame_orientation=vi.completeOrientation(self.frame_orientation)
|
|
|
+ self.ct_orientation=vtkInterface.completeOrientation(self.ct_orientation)
|
|
|
+ self.frame_orientation=vtkInterface.completeOrientation(self.frame_orientation)
|
|
|
|
|
|
self.addCT(patientId)
|
|
|
self.addFrames(patientId)
|
|
|
|
|
|
|
|
|
def loadPatientNRRD(self,patientId):
|
|
|
- print("Loading NRRD {}").format(patientId)
|
|
|
+ print("Loading NRRD {}".format(patientId))
|
|
|
|
|
|
self.loadDummyInputFunction(patientId)
|
|
|
dnsNode=slicer.util.getFirstNodeByName(patientId+'_Dummy')
|
|
@@ -545,10 +574,13 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
remotePath=self.fb.formatPathURL(self.cfg['project'],
|
|
|
'/'.join([patientId]))
|
|
|
labkeyFile=remotePath+'/'+fName+suffix
|
|
|
- localFile=os.path.join(self.tempPath+fName+suffix)
|
|
|
+ localFile=os.path.join(self.tempPath,fName+suffix)
|
|
|
self.fb.readFileToFile(labkeyFile,localFile)
|
|
|
- print ("Remote: {}").format(labkeyFile)
|
|
|
- node=slicer.util.loadNodeFromFile(localFile,type)
|
|
|
+ print("Remote: {}".format(labkeyFile))
|
|
|
+ try:
|
|
|
+ node=slicer.util.loadNodeFromFile(localFile,type)
|
|
|
+ except RuntimeError:
|
|
|
+ return None
|
|
|
os.remove(localFile)
|
|
|
return node
|
|
|
|
|
@@ -590,24 +622,26 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
slicer.mrmlScene.AddNode(newNode)
|
|
|
|
|
|
def addFrames(self,patientId):
|
|
|
+ import vtkInterface
|
|
|
#convert data from numpy.array to vtkImageData
|
|
|
#use time point it
|
|
|
- print "NFrames: {}".format(self.frame_data.shape[3])
|
|
|
+ print("NFrames: {}".format(self.frame_data.shape[3]))
|
|
|
for it in range(0,self.frame_data.shape[3]):
|
|
|
frame_data=self.frame_data[:,:,:,it];
|
|
|
nodeName=patientId+'Volume'+str(it)
|
|
|
self.addNode(nodeName,
|
|
|
- vi.numpyToVTK(frame_data,frame_data.shape),
|
|
|
+ vtkInterface.numpyToVTK(frame_data,frame_data.shape),
|
|
|
self.frame_origin,
|
|
|
self.frame_pixel_size,
|
|
|
self.frame_orientation,1)
|
|
|
|
|
|
def addCT(self,patientId):
|
|
|
+ import vtkInterface
|
|
|
nodeName=patientId+'CT'
|
|
|
self.addNode(nodeName,
|
|
|
#vi.numpyToVTK3D(self.ct_data,
|
|
|
# self.ct_origin,self.ct_pixel_size),
|
|
|
- vi.numpyToVTK(self.ct_data,self.ct_data.shape),
|
|
|
+ vtkInterface.numpyToVTK(self.ct_data,self.ct_data.shape),
|
|
|
self.ct_origin,self.ct_pixel_size,
|
|
|
self.ct_orientation,0)
|
|
|
|
|
@@ -654,7 +688,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
|
|
|
#get the segmentation mask
|
|
|
fNode=slicer.mrmlScene.GetNodesByClass("vtkMRMLSegmentationNode").GetItemAsObject(0)
|
|
|
- print "Found segmentation node: {}".format(fNode.GetName())
|
|
|
+ print("Found segmentation node: {}".format(fNode.GetName()))
|
|
|
segNode=slicer.vtkMRMLSegmentationNode.SafeDownCast(fNode)
|
|
|
|
|
|
#no python bindings for vtkSegmentation
|
|
@@ -665,12 +699,14 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
|
|
|
#edit here to change for more segments
|
|
|
segment=segNode.GetSegmentation().GetNthSegmentID(int(i))
|
|
|
- mask = segNode.GetBinaryLabelmapRepresentation(segment)
|
|
|
+ print('Computing for segment {}'.format(segment))
|
|
|
+ mask=slicer.vtkOrientedImageData()
|
|
|
+ segNode.GetBinaryLabelmapRepresentation(segment,mask)
|
|
|
if mask==None:
|
|
|
print("Segment {} not found".format(segment))
|
|
|
return s
|
|
|
|
|
|
- print "Got mask for segment {}, npts {}".format(segment,mask.GetNumberOfPoints())
|
|
|
+ print("Got mask for segment {}, npts {}".format(segment,mask.GetNumberOfPoints()))
|
|
|
#get mask at (x,y,z)
|
|
|
#mask.GetPointData().GetScalars().GetTuple1(mask.FindPoint([x,y,z]))
|
|
|
|
|
@@ -748,7 +784,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
|
|
|
node=slicer.mrmlScene.GetFirstNodeByName(nodeName)
|
|
|
if node==None:
|
|
|
- print("Node {} not found").format(nodeName)
|
|
|
+ print("Node {} not found".format(nodeName))
|
|
|
return
|
|
|
|
|
|
suffix=".nrrd"
|
|
@@ -762,12 +798,11 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
|
|
|
localPath=os.path.join(self.tempPath,fileName)
|
|
|
|
|
|
- file=os.path.join(localPath,fileName)
|
|
|
- slicer.util.saveNode(node,file)
|
|
|
- print("Stored to: {}").format(file)
|
|
|
+ slicer.util.saveNode(node,localPath)
|
|
|
+ print("Stored to: {}".format(localPath))
|
|
|
if self.cfg["remote"]:
|
|
|
labkeyPath=self.fb.buildPathURL(self.cfg['project'],pathList)
|
|
|
- print ("Remote: {}").format(labkeyPath)
|
|
|
+ print ("Remote: {}".format(labkeyPath))
|
|
|
#checks if exists
|
|
|
remoteFile=labkeyPath+'/'+fileName
|
|
|
self.fb.writeFileToFile(localPath,remoteFile)
|
|
@@ -788,7 +823,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
nodeName=nodeName+"_RS"
|
|
|
self.storeNodeRemote(pathList,nodeName)
|
|
|
|
|
|
- print("Storing NM from {} to {}").format(n1,n2)
|
|
|
+ print("Storing NM from {} to {}".format(n1,n2))
|
|
|
n=n2-n1+1
|
|
|
for i in range(n):
|
|
|
it=i+n1
|
|
@@ -833,7 +868,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
transformNodeName=patientId+"_DF"
|
|
|
transformNode=slicer.util.getFirstNodeByName(transformNodeName)
|
|
|
if transformNode==None:
|
|
|
- print("Transform node [{}] not found").format(transformNodeName)
|
|
|
+ print("Transform node [{}] not found".format(transformNodeName))
|
|
|
return
|
|
|
|
|
|
|
|
@@ -850,7 +885,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
refNode=slicer.util.getFirstNodeByName(refNodeName)
|
|
|
if refNode!=None:
|
|
|
self.resampler.rebinNode(node,refNode)
|
|
|
- print("Completed transformation {}").format(it)
|
|
|
+ print("Completed transformation {}".format(it))
|
|
|
#unset transformation
|
|
|
node.SetAndObserveTransformNodeID('NONE')
|
|
|
|
|
@@ -905,7 +940,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
break
|
|
|
|
|
|
if juse<0:
|
|
|
- print 'Failed to find Ventricle segment'
|
|
|
+ print('Failed to find Ventricle segment')
|
|
|
return
|
|
|
|
|
|
dt=0;
|