forked from SlicerRt/SlicerRT
/
DrrImageComputationTest.py
135 lines (120 loc) · 5.87 KB
/
DrrImageComputationTest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import os
import unittest
import vtk, qt, ctk, slicer
from slicer.ScriptedLoadableModule import *
import logging
#
# DrrImageComputationTest
#
# Compute DRR Image from CT volume
# by creating vtkMRMLRTPlanNode, vtkMRMLRTBeamNode, vtkMRMLDrrImageComputationNode
# 1. Load CT volume
# 2. Create dummy RTPlan node
# 3. Create dummy RTBeam node and add it into the dummy plan
# 4. Setup isocenter position
# 5. Setup RTBeam desired gantry and couch angles (optional)
# 6. Setup required DRR image parameters (optional)
# 7. Compute DRR image and check the results
class DrrImageComputationTest(unittest.TestCase):
def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)
#------------------------------------------------------------------------------
def runTest(self):
"""Run as few or as many tests as needed here.
"""
self.setUp()
self.test_DRRComputationTest_FullTest1()
#------------------------------------------------------------------------------
def test_DRRComputationTest_FullTest1(self):
# Check for modules
self.assertIsNotNone( slicer.modules.subjecthierarchy )
self.assertIsNotNone( slicer.modules.segmentations )
self.assertIsNotNone( slicer.modules.beams )
self.assertIsNotNone( slicer.modules.plastimatch_slicer_drr )
self.assertIsNotNone( slicer.modules.drrimagecomputation )
# Load CT volume
ctVolumeNode = self.TestSection_DownloadCtData()
# Create dummy RTPlan and RTBeam
rtImagePlan,rtImageBeam = self.TestSection_CreateDummyPlanAndBeam()
# Setup isocenter
self.TestSection_SetupIsocenterForPlan(ctVolumeNode, rtImagePlan)
# Create DRR parameters for RTImage using beam node
rtImageParameters = self.TestSection_CreateDrrParametersNode(rtImageBeam)
# Compute DRR image and check results
self.TestSection_ComputePlastimatchDrrAndCheckResults( rtImageParameters, ctVolumeNode)
logging.info("Test finished")
#------------------------------------------------------------------------------
def TestSection_DownloadCtData(self):
try:
import SampleData
sampleDataLogic = SampleData.SampleDataLogic()
ctVolumeNode = sampleDataLogic.downloadCTChest()
self.assertIsNotNone( ctVolumeNode )
return ctVolumeNode
except Exception as e:
import traceback
traceback.print_exc()
logging.info('Test caused exception!\n' + str(e))
raise Exception("Exception occurred, handled, thrown further to workflow level")
#------------------------------------------------------------------------------
def TestSection_CreateDummyPlanAndBeam(self):
# Create dummy RT plan
rtImagePlan = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLRTPlanNode', 'rtImagePlan')
# Check that the plan node is valid
self.assertIsNotNone( rtImagePlan )
# Create dummy RT beam for DRR RT image
rtImageBeam = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLRTBeamNode', 'rtImageBeam')
# Check that the beam node is valid
self.assertIsNotNone( rtImageBeam )
# Add beam to the plan
rtImagePlan.AddBeam(rtImageBeam)
# Set required beam parameters
rtImageBeam.SetGantryAngle(90.)
rtImageBeam.SetCouchAngle(12.)
logging.info('Gantry angle = 90. deg, Patient support rotation angle = 12. deg')
return (rtImagePlan, rtImageBeam)
#------------------------------------------------------------------------------
def TestSection_SetupIsocenterForPlan(self, volumeNode, planNode):
# Set and observe CT volume by the plan
planNode.SetAndObserveReferenceVolumeNode(volumeNode)
# Set isocenter position as a point
planNode.SetIsocenterSpecification(planNode.ArbitraryPoint)
isocenterPosition = [ 0., 0., -230. ]
if (planNode.SetIsocenterPosition(isocenterPosition)):
logging.info('Isocenter is set as (0., 0., -230.)')
else:
logging.warning('Unable to set isocenter')
#------------------------------------------------------------------------------
def TestSection_CreateDrrParametersNode(self, beamNode):
# Create DRR RTImage computation node for user imager parameters
drrParameters = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLDrrImageComputationNode', 'rtImageParams')
# Set and observe RTImage beam by the DRR node
drrParameters.SetAndObserveBeamNode(beamNode)
# Set required DRR parameters
drrParameters.SetHUThresholdBelow(150)
drrImagerResolution = [1024, 768]; # [columns, row]
drrImagerSpacing = [0.3, 0.3]; # in mm [columns, row]
drrParameters.SetImagerResolution(drrImagerResolution)
drrParameters.SetImagerSpacing(drrImagerSpacing)
return drrParameters
#------------------------------------------------------------------------------
def TestSection_ComputePlastimatchDrrAndCheckResults(self, rtImageParameters, volumeNode):
# Get DRR computation logic
drrLogic = slicer.modules.drrimagecomputation.logic()
# Update imager markups for the 3D view and slice views (optional)
drrLogic.UpdateMarkupsNodes(rtImageParameters)
# Update imager normal and view-up vectors (mandatory)
drrLogic.UpdateNormalAndVupVectors(rtImageParameters) # REQUIRED
# Compute DRR image
result = drrLogic.ComputePlastimatchDRR( rtImageParameters, volumeNode)
self.assertTrue(result)
logging.info('DRR image has been computed!')
# Check that image is valid
drrImage = rtImageParameters.GetRtImageVolumeNode()
drrImageDim = drrImage.GetImageData().GetDimensions()
drrParametersDim = rtImageParameters.GetImagerResolution()
self.assertTrue( drrImageDim == (drrParametersDim[0], drrParametersDim[1], 1) )
self.assertEqual( drrImage.GetImageData().GetScalarType(), vtk.VTK_FLOAT )
logging.info('It looks like that DRR image is correct!')