|
@@ -10,6 +10,7 @@ import fileIO
|
|
|
import slicer
|
|
|
import numpy as np
|
|
|
import slicerNetwork
|
|
|
+import resample
|
|
|
|
|
|
|
|
|
|
|
@@ -97,16 +98,35 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
self.patientId=qt.QLineEdit();
|
|
|
dataFormLayout.addRow('Patient ID', self.patientId)
|
|
|
|
|
|
+ self.refPatientId=qt.QLineEdit();
|
|
|
+ dataFormLayout.addRow('Reference Patient ID', self.refPatientId)
|
|
|
+
|
|
|
+
|
|
|
patientLoadButton = qt.QPushButton("Load")
|
|
|
patientLoadButton.toolTip="Load data from DICOM"
|
|
|
dataFormLayout.addRow("Load Patient",patientLoadButton)
|
|
|
patientLoadButton.clicked.connect(self.onPatientLoadButtonClicked)
|
|
|
|
|
|
- saveVolumeButton = qt.QPushButton("Save Volume to NRRD")
|
|
|
- saveVolumeButton.toolTip="Save to NRRD"
|
|
|
- dataFormLayout.addRow("Save to NRRD",saveVolumeButton)
|
|
|
+ loadSegmentationButton = qt.QPushButton("Load")
|
|
|
+ loadSegmentationButton.toolTip="Load segmentation from server"
|
|
|
+ dataFormLayout.addRow("Load Segmentation",loadSegmentationButton)
|
|
|
+ loadSegmentationButton.clicked.connect(self.onLoadSegmentationButtonClicked)
|
|
|
+
|
|
|
+ saveVolumeButton = qt.QPushButton("Save")
|
|
|
+ saveVolumeButton.toolTip="Save volume to NRRD"
|
|
|
+ dataFormLayout.addRow("Volume",saveVolumeButton)
|
|
|
saveVolumeButton.clicked.connect(self.onSaveVolumeButtonClicked)
|
|
|
|
|
|
+ saveSegmentationButton = qt.QPushButton("Save")
|
|
|
+ saveSegmentationButton.toolTip="Save segmentation to NRRD"
|
|
|
+ dataFormLayout.addRow("Segmentation",saveSegmentationButton)
|
|
|
+ saveSegmentationButton.clicked.connect(self.onSaveSegmentationButtonClicked)
|
|
|
+
|
|
|
+ saveTransformationButton = qt.QPushButton("Save")
|
|
|
+ saveTransformationButton.toolTip="Save transformation to NRRD"
|
|
|
+ dataFormLayout.addRow("Transformation",saveTransformationButton)
|
|
|
+ saveTransformationButton.clicked.connect(self.onSaveTransformationButtonClicked)
|
|
|
+
|
|
|
transformNodeButton = qt.QPushButton("Transform Node")
|
|
|
transformNodeButton.toolTip="Transform node with patient based transform"
|
|
|
dataFormLayout.addRow("Transform Nodes",transformNodeButton)
|
|
@@ -338,12 +358,21 @@ class cardiacSPECTWidget(ScriptedLoadableModuleWidget):
|
|
|
def onPatientLoadButtonClicked(self):
|
|
|
self.logic.loadPatient(self,self.patientId.text)
|
|
|
|
|
|
+ def onLoadSegmentationButtonClicked(self):
|
|
|
+ self.logic.loadSegmentation(self.patientId.text)
|
|
|
+
|
|
|
def onSaveVolumeButtonClicked(self):
|
|
|
self.logic.storeVolumeNodes(self.patientId.text,
|
|
|
self.time_frame_select.minimum,self.time_frame_select.maximum)
|
|
|
|
|
|
+ def onSaveSegmentationButtonClicked(self):
|
|
|
+ self.logic.storeSegmentation(self.patientId.text)
|
|
|
+
|
|
|
+ def onSaveTransformationButtonClicked(self):
|
|
|
+ self.logic.storeTransformation(self.patientId.text)
|
|
|
+
|
|
|
def onTransformNodeButtonClicked(self):
|
|
|
- self.logic.applyTransform(self.patientId.text,
|
|
|
+ self.logic.applyTransform(self.patientId.text, self.refPatientId.text,
|
|
|
self.time_frame_select.minimum,self.time_frame_select.maximum)
|
|
|
|
|
|
|
|
@@ -399,11 +428,15 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
'Slicer Python','Data loaded')
|
|
|
|
|
|
|
|
|
+ def formatToGetfileSpec(self,path):
|
|
|
+
|
|
|
+ path="labkey://"+path
|
|
|
+ return path
|
|
|
+
|
|
|
def loadPatient(self,widget,patientId):
|
|
|
print("Loading {}").format(patientId)
|
|
|
ds=self.net.loadDataset("dinamic_spect/Patients","Imaging")
|
|
|
for r in ds['rows']:
|
|
|
- print r
|
|
|
if r['aliasID']==patientId:
|
|
|
visit=r
|
|
|
|
|
@@ -414,23 +447,23 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
continue
|
|
|
if abs(r['SequenceNum']-float(visit['nmMaster']))<0.1:
|
|
|
path=r['_labkeyurl_Series']
|
|
|
- path=path[:path.rfind('/')]
|
|
|
- masterPath="labkey://"+path
|
|
|
+ masterPath=path[:path.rfind('/')]
|
|
|
+
|
|
|
if abs(r['SequenceNum']-float(visit['nmCorrData']))<0.1:
|
|
|
path=r['_labkeyurl_Series']
|
|
|
- path=path[:path.rfind('/')]
|
|
|
- nmPath="labkey://"+path
|
|
|
+ nmPath=path[:path.rfind('/')]
|
|
|
+
|
|
|
if abs(r['SequenceNum']-float(visit['ctData']))<0.1:
|
|
|
path=r['_labkeyurl_Series']
|
|
|
- path=path[:path.rfind('/')]
|
|
|
- ctPath="labkey://"+path
|
|
|
+ ctPath=path[:path.rfind('/')]
|
|
|
+
|
|
|
|
|
|
|
|
|
- self.pd.readMasterDirectory(masterPath)
|
|
|
+ self.pd.readMasterDirectory(self.formatToGetfileSpec(masterPath))
|
|
|
self.frame_data, self.frame_time, self.frame_origin, \
|
|
|
- self.frame_pixel_size, self.frame_orientation=self.pd.readNMDirectory(nmPath)
|
|
|
+ self.frame_pixel_size, self.frame_orientation=self.pd.readNMDirectory(self.formatToGetfileSpec(nmPath))
|
|
|
self.ct_data,self.ct_origin,self.ct_pixel_size, \
|
|
|
- self.ct_orientation=self.pd.readCTDirectory(ctPath)
|
|
|
+ self.ct_orientation=self.pd.readCTDirectory(self.formatToGetfileSpec(ctPath))
|
|
|
|
|
|
self.ct_orientation=vi.completeOrientation(self.ct_orientation)
|
|
|
self.frame_orientation=vi.completeOrientation(self.frame_orientation)
|
|
@@ -440,6 +473,16 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
|
|
|
widget.time_frame_select.setMaximum(self.frame_data.shape[3]-1)
|
|
|
|
|
|
+ def loadSegmentation(self,patientId):
|
|
|
+ project="dinamic_spect/Patients"
|
|
|
+ relativePath=project+'/@files/'+patientId
|
|
|
+ segName="Heart"
|
|
|
+ labkeyFile=relativePath+'/'+segName+'.nrrd'
|
|
|
+ print ("Remote: {}").format(labkeyFile)
|
|
|
+ self.net.loadNode(labkeyFile,'SegmentationFile')
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
def addNode(self,nodeName,v, lpsOrigin, pixel_size, lpsOrientation, dataType):
|
|
|
|
|
|
|
|
@@ -607,12 +650,13 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
return segNode.GetSegmentation().GetSegment(segNode.GetSegmentation().GetNthSegmentID(i)).GetName()
|
|
|
|
|
|
def storeNodeRemote(self,relativePath,nodeName):
|
|
|
- labkeyPath=self.pd.net.GetLabkeyWebdavUrl()+'/'+relativePath
|
|
|
+ labkeyPath=self.pd.net.GetLabkeyPathFromRelativePath(relativePath)
|
|
|
print ("Remote: {}").format(labkeyPath)
|
|
|
|
|
|
self.pd.net.mkdir(labkeyPath)
|
|
|
|
|
|
- localPath=self.pd.net.GetLocalCacheDirectory()+'/'+relativePath
|
|
|
+ localPath=self.pd.net.GetLocalPathFromRelativePath(relativePath)
|
|
|
+ localPath.replace('/',os.path.sep)
|
|
|
|
|
|
node=slicer.mrmlScene.GetFirstNodeByName(nodeName)
|
|
|
if node==None:
|
|
@@ -625,7 +669,7 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
if node.__class__.__name__=="vtkMRMLTransformNode":
|
|
|
suffix=".h5"
|
|
|
fileName=nodeName+suffix
|
|
|
- file=localPath+'/'+fileName
|
|
|
+ file=os.path.join(localPath,fileName)
|
|
|
slicer.util.saveNode(node,file)
|
|
|
print("Stored to: {}").format(file)
|
|
|
f=open(file)
|
|
@@ -650,29 +694,34 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
nodeName=patientId+'Volume'+str(it)
|
|
|
self.storeNodeRemote(relativePath,nodeName)
|
|
|
|
|
|
+ def storeSegmentation(self,patientId):
|
|
|
+ project="dinamic_spect/Patients"
|
|
|
+ relativePath=project+'/@files/'+patientId
|
|
|
segNodeName="Heart"
|
|
|
self.storeNodeRemote(relativePath,segNodeName)
|
|
|
|
|
|
+ def storeInputFunction(self,patientId):
|
|
|
doubleArrayNodeName=patientId+'_Ventricle'
|
|
|
self.storeNodeRemote(relativePath,doubleArrayNodeName)
|
|
|
|
|
|
+ def storeTransformation(self,patientId):
|
|
|
transformNodeName=patientId+"_DF"
|
|
|
self.storeNodeRemote(relativePath,transformNodeName)
|
|
|
|
|
|
- def applyTransform(self, patientId,n1,n2):
|
|
|
+ def applyTransform(self, patientId,refPatientId,n1,n2):
|
|
|
transformNodeName=patientId+"_DF"
|
|
|
transformNode=slicer.util.getFirstNodeByName(transformNodeName)
|
|
|
if transformNode==None:
|
|
|
print("Node {} not found").format(transformNodeName)
|
|
|
return
|
|
|
+
|
|
|
try:
|
|
|
- if self.transformApplied:
|
|
|
- print("Transform already applied")
|
|
|
- return
|
|
|
+ self.resampler.printMe()
|
|
|
+ return
|
|
|
except AttributeError:
|
|
|
- print("Not defined yet")
|
|
|
+ print("Initializing resampler")
|
|
|
+ self.resampler=resample.resampleLogic(None)
|
|
|
|
|
|
- self.transformApplied=True
|
|
|
|
|
|
n=n2-n1+1
|
|
|
for i in range(n):
|
|
@@ -681,18 +730,27 @@ class cardiacSPECTLogic(ScriptedLoadableModuleLogic):
|
|
|
node=slicer.util.getFirstNodeByName(nodeName)
|
|
|
if node==None:
|
|
|
continue
|
|
|
- node.ApplyTransform(transformNode.GetTransformToParent())
|
|
|
+ node.SetAndObserveTransformNodeID(transformNode.GetID())
|
|
|
+
|
|
|
+ refNodeName=refPatientId+'Volume'+str(it)
|
|
|
+ refNode=slicer.util.getFirstNodeByName(refNodeName)
|
|
|
+ if refNode!=None:
|
|
|
+ self.resampler.rebinNode(node,refNode)
|
|
|
|
|
|
nodeName=patientId+'CT'
|
|
|
node=slicer.util.getFirstNodeByName(nodeName)
|
|
|
if not node==None:
|
|
|
- node.ApplyTransform(transformNode.GetTransformToParent())
|
|
|
+ node.SetAndObserveTransformNodeID(transformNode.GetID())
|
|
|
+ refNodeName=refPatientId+'CT'
|
|
|
+ refNode=slicer.util.getFirstNodeByName(refNodeName)
|
|
|
+ if refNode!=None:
|
|
|
+ self.resampler.rebinNode(node,refNode)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- def calculateInputFunction(self):
|
|
|
+ def calculateInputFunction(self):
|
|
|
n=self.frame_data.shape[3]
|
|
|
|
|
|
dns = slicer.mrmlScene.GetNodesByClassByName('vtkMRMLDoubleArrayNode','Ventricle')
|