CTRegistration.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. from slicer.ScriptedLoadableModule import *
  2. import slicerNetwork
  3. import qt,vtk,ctk,slicer
  4. import os
  5. import resample
  6. import exportDicom
  7. import loadPatient
  8. class CTRegistration(slicer.ScriptedLoadableModule.ScriptedLoadableModule):
  9. def __init__(self,parent):
  10. slicer.ScriptedLoadableModule.ScriptedLoadableModule.__init__(self, parent)
  11. self.className="CTRegistration"
  12. self.parent.title="CTRegistration"
  13. self.parent.categories = ["EMBRACE"]
  14. self.parent.dependencies = []
  15. self.parent.contributors = ["Andrej Studen (University of Ljubljana)"] # replace with "Firstname Lastname (Organization)"
  16. self.parent.helpText = """
  17. This is an example of scripted loadable module bundled in an extension.
  18. It performs registration of CT (EBRT) and MRI (BRT)
  19. """
  20. self.parent.helpText += self.getDefaultModuleDocumentationLink()
  21. self.parent.acknowledgementText = """
  22. This extension developed within Medical Physics research programe of ARRS
  23. """ # replace with organization, grant and thanks.
  24. #
  25. # dataExplorerWidget
  26. class CTRegistrationWidget(ScriptedLoadableModuleWidget):
  27. """Uses ScriptedLoadableModuleWidget base class, available at:
  28. https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
  29. """
  30. def setup(self):
  31. ScriptedLoadableModuleWidget.setup(self)
  32. self.logic=CTRegistrationLogic(self)
  33. try:
  34. fhome=os.environ["HOME"]
  35. except:
  36. #in windows, the variable is called HOMEPATH
  37. fhome=os.environ['HOMEDRIVE']+os.environ['HOMEPATH']
  38. cfgPath=os.path.join(fhome,".labkey")
  39. cfgPath=os.path.join(cfgPath,"onko-nix.json")
  40. self.onkoNet=slicerNetwork.labkeyURIHandler()
  41. self.onkoNet.parseConfig(cfgPath)
  42. self.onkoNet.initRemote()
  43. self.project='EMBRACE/Studija'
  44. datasetCollapsibleButton = ctk.ctkCollapsibleButton()
  45. datasetCollapsibleButton.text = "Node data"
  46. self.layout.addWidget(datasetCollapsibleButton)
  47. # Layout within the dummy collapsible button
  48. datasetFormLayout = qt.QFormLayout(datasetCollapsibleButton)
  49. self.patientId=qt.QLineEdit("LJU004")
  50. datasetFormLayout.addRow("EMBRACE ID:",self.patientId)
  51. loadDataButton=qt.QPushButton("Load")
  52. loadDataButton.clicked.connect(self.onLoadDataButtonClicked)
  53. datasetFormLayout.addRow("Data:",loadDataButton)
  54. self.exportButton=qt.QPushButton("Export")
  55. self.exportButton.clicked.connect(self.onExportButtonClicked)
  56. datasetFormLayout.addRow("Export:",self.exportButton)
  57. self.debugCheckBox=qt.QCheckBox()
  58. self.debugCheckBox.setChecked(True)
  59. datasetFormLayout.addRow("Debug:",self.debugCheckBox)
  60. def onLoadDataButtonClicked(self):
  61. self.logic.loadData(self.onkoNet,self.patientId.text)
  62. def onExportButtonClicked(self):
  63. self.logic.export(self.onkoNet,self.project,self.patientId.text)
  64. class CTRegistrationLogic(slicer.ScriptedLoadableModule.ScriptedLoadableModuleLogic):
  65. def __init__(self,parent):
  66. slicer.ScriptedLoadableModule.ScriptedLoadableModuleLogic.__init__(self, parent)
  67. self.exporter=exportDicom.exportDicomLogic(self)
  68. self.importer=loadPatient.loadPatientLogic(self)
  69. self.resampler=resample.resampleLogic(self)
  70. try:
  71. fhome=os.environ["HOME"]
  72. except:
  73. #in windows, the variable is called HOMEPATH
  74. fhome=os.environ['HOMEDRIVE']+os.environ['HOMEPATH']
  75. def setLocal(self,basePath):
  76. self.importer.setLocal(basePath)
  77. def getLocalRegistrationPath(self,net,project,patientId):
  78. path=os.path.join(net.GetLocalCacheDirectory(),project)
  79. path=os.path.join(path,"%40files")
  80. path=os.path.join(path,patientId)
  81. path=os.path.join(path,"Registration")
  82. if not os.path.isdir(path):
  83. os.mkdir(path)
  84. relDir=net.GetRelativePathFromLocalPath(path)
  85. remoteDir=net.GetLabkeyPathFromRelativePath(relDir)
  86. if not net.isRemoteDir(remoteDir):
  87. net.mkdir(remoteDir)
  88. return path
  89. def loadData(self,net,patientId):
  90. self.importer.setURIHandler(net)
  91. self.ct=self.importer.loadCT(patientId)
  92. if len(self.ct)<1:
  93. print("No CT found for patient {}").format(patientId)
  94. return
  95. if len(self.ct)>1:
  96. print("Too many CT volumes found for patient {}").format(patientId)
  97. return
  98. volumeNode=self.ct[0]['node']
  99. volumeNode.SetName(patientId+"_CT")
  100. self.ctrs=self.importer.loadCTRS(patientId)
  101. if len(self.ctrs)<1:
  102. print("No CT-segmentation found for patient {}").format(patientId)
  103. return
  104. if len(self.ctrs)>1:
  105. print("Multiple CT-segmentations found for patient {}").format(patientId)
  106. return
  107. segNode=self.ctrs[0]['node']
  108. segNode.SetName(patientId+"_CTRS")
  109. self.dmr=self.importer.loadDMR(patientId)
  110. if len(self.dmr)<1:
  111. print("No DMR found for patient {}").format(patientId)
  112. return
  113. if len(self.dmr)>1:
  114. print("Multiple DMR found for patient {}").format(patientId)
  115. return
  116. dmrMetadata=self.dmr[0]['metadata']
  117. if len(dmrMetadata['frameOfReferenceInstanceUid'])<1:
  118. refId=self.exporter.generateFrameOfReferenceUUID('volume')
  119. dmrMetadata['frameOfReferenceInstanceUid']=refId
  120. self.dmr[0]['node'].SetName(patientId+"_DMR")
  121. def exportFile(self,net,path):
  122. print("localPath: {}").format(path)
  123. relativePath=net.GetRelativePathFromLocalPath(path)
  124. print("relativePath: {}").format(relativePath)
  125. remotePath=net.GetLabkeyPathFromRelativePath(relativePath)
  126. print("remotePath: {}").format(relativePath)
  127. net.copyLocalFileToRemote(path,remotePath)
  128. def exportTransformation(self,net,project,patientId):
  129. tNodeName=patientId+"_T2_DF"
  130. tNode=slicer.util.getFirstNodeByName(tNodeName)
  131. path=self.getLocalRegistrationPath(net,project,patientId)
  132. fname=tNodeName+".h5"
  133. path=os.path.join(path,fname)
  134. slicer.util.saveNode(tNode,path)
  135. self.exportFile(net,path)
  136. return tNode
  137. def exportSegmentation(self,net,project,patientId,tNode):
  138. #DMR
  139. dmrNode=self.dmr[0]['node']
  140. dmrMetadata=self.dmr[0]['metadata']
  141. #segmentations
  142. segNode=self.ctrs[0]['node']
  143. segMetadata=self.ctrs[0]['metadata']
  144. segMetadata['frameOfReferenceInstanceUid']=dmrMetadata['frameOfReferenceInstanceUid']
  145. nSeg=segNode.GetSegmentation().GetNumberOfSegments()
  146. for i in range(0,nSeg):
  147. segId=segNode.GetSegmentation().GetNthSegmentID(i)
  148. segment=segNode.GetSegmentation().GetSegment(segId)
  149. nodeName=segNode.GetName()+'_'+segId
  150. node=slicer.util.getFirstNodeByName(nodeName)
  151. if node==None:
  152. segNode.SetAndObserveTransformNodeID(tNode.GetID())
  153. binaryRep={'node':segNode,
  154. 'mask':segNode.GetBinaryLabelmapRepresentation(segId),
  155. 'segId':segId}
  156. if binaryRep['mask']==None:
  157. segNode.CreateBinaryLabelmapRepresentation()
  158. binaryRep['mask']=segNode.GetBinaryLabelmapRepresentation(segId)
  159. self.resampler.rebinSegment(dmrNode,binaryRep)
  160. node=slicer.util.getFirstNodeByName(nodeName)
  161. segMetadata['seriesInstanceUid']=self.exporter.generateSeriesUUID('segmentation')
  162. segMetadata['seriesNumber']=i
  163. segMetadata['patientId']=patientId
  164. self.exporter.exportNode(net,project,node,segMetadata)
  165. def exportCT(self,net,project,patientId,tNode):
  166. #DMR
  167. dmrNode=self.dmr[0]['node']
  168. dmrMetadata=self.dmr[0]['metadata']
  169. #CT (rebinned)
  170. ctNode=self.ct[0]['node']
  171. ctMetadata=self.ct[0]['metadata']
  172. ctMetadata['frameOfReferenceInstanceUid']=dmrMetadata['frameOfReferenceInstanceUid']
  173. ctMetadata['seriesInstanceUid']=self.exporter.generateSeriesUUID('segmentation')
  174. ctMetadata['patientId']=patientId
  175. ctNode=self.ct[0]['node']
  176. ctName=ctNode.GetName()
  177. ctRBName=ctNode.GetName()+"_TF"
  178. ctRBNode=slicer.util.getFirstNodeByName(ctRBName)
  179. if ctRBNode==None:
  180. ctNode.SetAndObserveTransformNodeID(tNode.GetID())
  181. ctRBNode=self.resampler.rebinNode(ctNode,dmrNode)
  182. ctRBNode.SetName(ctRBName)
  183. ctNode.SetName(ctName)
  184. self.exporter.exportNode(net,project,ctRBNode,ctMetadata)
  185. def export(self,net,project,patientId):
  186. #transformation
  187. tNode=self.exportTransformation(net,project,patientId)
  188. self.exportSegmentation(net,project,patientId,tNode)
  189. #tNodeName=patientId+"_T2_DF"
  190. #tNode=slicer.util.getFirstNodeByName(tNodeName)
  191. self.exportCT(net,project,patientId,tNode)