CTRegistration.py 8.3 KB

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