CTRegistration.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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 getLocalRegistrationPath(self,net,project,patientId):
  76. path=os.path.join(net.GetLocalCacheDirectory(),project)
  77. path=os.path.join(path,"%40files")
  78. path=os.path.join(path,patientId)
  79. path=os.path.join(path,"Registration")
  80. if not os.path.isdir(path):
  81. os.mkdir(path)
  82. relDir=net.GetRelativePathFromLocalPath(path)
  83. remoteDir=net.GetLabkeyPathFromRelativePath(relDir)
  84. if not net.isRemoteDir(remoteDir):
  85. net.mkdir(remoteDir)
  86. return path
  87. def loadData(self,net,patientId):
  88. self.importer.setURIHandler(net)
  89. self.ct=self.importer.loadCT(patientId)
  90. if len(self.ct)<1:
  91. print("No CT found for patient {}").format(patientId)
  92. return
  93. if len(self.ct)>1:
  94. print("Too many CT volumes found for patient {}").format(patientId)
  95. return
  96. volumeNode=self.ct[0]['node']
  97. volumeNode.SetName(patientId+"_CT")
  98. self.ctrs=self.importer.loadCTRS(patientId)
  99. if len(self.ctrs)<1:
  100. print("No CT-segmentation found for patient {}").format(patientId)
  101. return
  102. if len(self.ctrs)>1:
  103. print("Multiple CT-segmentations found for patient {}").format(patientId)
  104. return
  105. segNode=self.ctrs[0]['node']
  106. segNode.SetName(patientId+"_CTRS")
  107. self.dmr=self.importer.loadDMR(patientId)
  108. if len(self.dmr)<1:
  109. print("No DMR found for patient {}").format(patientId)
  110. return
  111. if len(self.dmr)>1:
  112. print("Multiple DMR found for patient {}").format(patientId)
  113. return
  114. dmrMetadata=self.dmr[0]['metadata']
  115. if len(dmrMetadata['frameOfReferenceInstanceUid'])<1:
  116. refId=self.exporter.generateFrameOfReferenceUUID('volume')
  117. dmrMetadata['frameOfReferenceInstanceUid']=refId
  118. self.dmr[0]['node'].SetName(patientId+"_DMR")
  119. def exportFile(self,net,path):
  120. print("localPath: {}").format(path)
  121. relativePath=net.GetRelativePathFromLocalPath(path)
  122. print("relativePath: {}").format(relativePath)
  123. remotePath=net.GetLabkeyPathFromRelativePath(relativePath)
  124. print("remotePath: {}").format(relativePath)
  125. net.copyLocalFileToRemote(path,remotePath)
  126. def exportTransformation(self,net,project,patientId):
  127. tNodeName=patientId+"_T2_DF"
  128. tNode=slicer.util.getFirstNodeByName(tNodeName)
  129. path=self.getLocalRegistrationPath(net,project,patientId)
  130. fname=tNodeName+".h5"
  131. path=os.path.join(path,fname)
  132. slicer.util.saveNode(tNode,path)
  133. self.exportFile(net,path)
  134. return tNode
  135. def exportSegmentation(self,net,project,patientId,tNode):
  136. #DMR
  137. dmrNode=self.dmr[0]['node']
  138. dmrMetadata=self.dmr[0]['metadata']
  139. #segmentations
  140. segNode=self.ctrs[0]['node']
  141. segMetadata=self.ctrs[0]['metadata']
  142. segMetadata['frameOfReferenceInstanceUid']=dmrMetadata['frameOfReferenceInstanceUid']
  143. nSeg=segNode.GetSegmentation().GetNumberOfSegments()
  144. for i in range(0,nSeg):
  145. segId=segNode.GetSegmentation().GetNthSegmentID(i)
  146. segment=segNode.GetSegmentation().GetSegment(segId)
  147. nodeName=segNode.GetName()+'_'+segId
  148. node=slicer.util.getFirstNodeByName(nodeName)
  149. if node==None:
  150. segNode.SetAndObserveTransformNodeID(tNode.GetID())
  151. binaryRep={'node':segNode,
  152. 'mask':segNode.GetBinaryLabelmapRepresentation(segId),
  153. 'segId':segId}
  154. if binaryRep['mask']==None:
  155. segNode.CreateBinaryLabelmapRepresentation()
  156. binaryRep['mask']=segNode.GetBinaryLabelmapRepresentation(segId)
  157. self.resampler.rebinSegment(dmrNode,binaryRep)
  158. node=slicer.util.getFirstNodeByName(nodeName)
  159. segMetadata['seriesInstanceUid']=self.exporter.generateSeriesUUID('segmentation')
  160. segMetadata['seriesNumber']=i
  161. segMetadata['patientId']=patientId
  162. self.exporter.exportNode(net,project,node,segMetadata)
  163. def exportCT(self,net,project,patientId,tNode):
  164. #DMR
  165. dmrNode=self.dmr[0]['node']
  166. dmrMetadata=self.dmr[0]['metadata']
  167. #CT (rebinned)
  168. ctNode=self.ct[0]['node']
  169. ctMetadata=self.ct[0]['metadata']
  170. ctMetadata['frameOfReferenceInstanceUid']=dmrMetadata['frameOfReferenceInstanceUid']
  171. ctMetadata['seriesInstanceUid']=self.exporter.generateSeriesUUID('segmentation')
  172. ctMetadata['patientId']=patientId
  173. ctNode=self.ct[0]['node']
  174. ctName=ctNode.GetName()
  175. ctRBName=ctNode.GetName()+"_TF"
  176. ctRBNode=slicer.util.getFirstNodeByName(ctRBName)
  177. if ctRBNode==None:
  178. ctNode.SetAndObserveTransformNodeID(tNode.GetID())
  179. ctRBNode=self.resampler.rebinNode(ctNode,dmrNode)
  180. ctRBNode.SetName(ctRBName)
  181. ctNode.SetName(ctName)
  182. self.exporter.exportNode(net,project,ctRBNode,ctMetadata)
  183. def export(self,net,project,patientId):
  184. #transformation
  185. tNode=self.exportTransformation(net,project,patientId)
  186. self.exportSegmentation(net,project,patientId,tNode)
  187. #tNodeName=patientId+"_T2_DF"
  188. #tNode=slicer.util.getFirstNodeByName(tNodeName)
  189. self.exportCT(net,project,patientId,tNode)