Example #1
0
  def TestSection_1_RunPlastimatchProtonDoseEngine(self):
    logging.info('Test section 1: Run Plastimatch proton dose engine')

    engineLogic = slicer.qSlicerDoseEngineLogic()
    engineLogic.setMRMLScene(slicer.mrmlScene)

    # Get input
    ctVolumeNode = slicer.util.getNode('TinyPatient_CT')
    segmentationNode = slicer.util.getNode('TinyPatient_Structures')
    self.assertIsNotNone(ctVolumeNode)
    self.assertIsNotNone(segmentationNode)
    
    # Create node for output dose
    totalDoseVolumeNode = slicer.vtkMRMLScalarVolumeNode()
    totalDoseVolumeNode.SetName('TotalDose')
    slicer.mrmlScene.AddNode(totalDoseVolumeNode)
    
    # Setup plan
    planNode = slicer.vtkMRMLRTPlanNode()
    planNode.SetName('TestProtonPlan')
    slicer.mrmlScene.AddNode(planNode)
    
    planNode.SetAndObserveReferenceVolumeNode(ctVolumeNode);
    planNode.SetAndObserveSegmentationNode(segmentationNode);
    planNode.SetAndObserveOutputTotalDoseVolumeNode(totalDoseVolumeNode);
    planNode.SetTargetSegmentID("Tumor_Contour");
    planNode.SetIsocenterToTargetCenter();
    planNode.SetDoseEngineName(self.plastimatchProtonDoseEngineName)

    # Add first beam
    firstBeamNode = engineLogic.createBeamInPlan(planNode)
    firstBeamNode.SetX1Jaw(-50.0)
    firstBeamNode.SetX2Jaw(50.0)
    firstBeamNode.SetY1Jaw(-50.0)
    firstBeamNode.SetY2Jaw(75.0)

    #TODO: For some reason the instance() function cannot be called as a class function although it's static
    engineHandler = slicer.qSlicerDoseEnginePluginHandler()
    engineHandlerSingleton = engineHandler.instance()
    plastimatchProtonEngine = engineHandlerSingleton.doseEngineByName(self.plastimatchProtonDoseEngineName)
    plastimatchProtonEngine.setParameter(firstBeamNode, 'EnergyResolution', 4.0)
    plastimatchProtonEngine.setParameter(firstBeamNode, 'RangeCompensatorSmearingRadius', 0.0)
    plastimatchProtonEngine.setParameter(firstBeamNode, 'ProximalMargin', 0.0)
    plastimatchProtonEngine.setParameter(firstBeamNode, 'DistalMargin', 0.0)
    
    # Calculate dose
    import time
    startTime = time.time()
    
    errorMessage = engineLogic.calculateDose(planNode)
    self.assertEqual(errorMessage, "")
    
    calculationTime = time.time() - startTime
    logging.info('Dose computation time: ' + str(calculationTime) + ' s')
    
    # Check computed output
    imageAccumulate = vtk.vtkImageAccumulate()
    imageAccumulate.SetInputConnection(totalDoseVolumeNode.GetImageDataConnection())
    imageAccumulate.Update()

    doseMax = imageAccumulate.GetMax()[0]
    doseMean = imageAccumulate.GetMean()[0]
    doseStdDev = imageAccumulate.GetStandardDeviation()[0]
    doseVoxelCount = imageAccumulate.GetVoxelCount()
    logging.info("Dose volume properties:\n  Max=" + str(doseMax) + ", Mean=" + str(doseMean) + ", StdDev=" + str(doseStdDev) + ", NumberOfVoxels=" + str(doseVoxelCount))

    self.assertTrue(self.isEqualWithTolerance(doseMax, 1.09556))
    self.assertTrue(self.isEqualWithTolerance(doseMean, 0.01670))
    self.assertTrue(self.isEqualWithTolerance(doseStdDev, 0.12670))
    self.assertTrue(self.isEqualWithTolerance(doseVoxelCount, 1000))
  def TestSection_1_RunPlastimatchProtonDoseEngine(self):
    logging.info('Test section 1: Run Plastimatch proton dose engine')

    engineLogic = slicer.qSlicerDoseEngineLogic()
    engineLogic.setMRMLScene(slicer.mrmlScene)

    # Get input
    ctVolumeNode = slicer.util.getNode('TinyPatient_CT')
    segmentationNode = slicer.util.getNode('TinyPatient_Structures')
    self.assertIsNotNone(ctVolumeNode)
    self.assertIsNotNone(segmentationNode)
    
    # Create node for output dose
    totalDoseVolumeNode = slicer.vtkMRMLScalarVolumeNode()
    totalDoseVolumeNode.SetName('TotalDose')
    slicer.mrmlScene.AddNode(totalDoseVolumeNode)
    
    # Setup plan
    planNode = slicer.vtkMRMLRTPlanNode()
    planNode.SetName('TestProtonPlan')
    slicer.mrmlScene.AddNode(planNode)
    
    planNode.SetAndObserveReferenceVolumeNode(ctVolumeNode);
    planNode.SetAndObserveSegmentationNode(segmentationNode);
    planNode.SetAndObserveOutputTotalDoseVolumeNode(totalDoseVolumeNode);
    planNode.SetTargetSegmentID("Tumor_Contour");
    planNode.SetIsocenterToTargetCenter();
    planNode.SetDoseEngineName("Plastimatch proton")

    # Add first beam
    firstBeamNode = engineLogic.createBeamInPlan(planNode)
    firstBeamNode.SetX1Jaw(-50.0)
    firstBeamNode.SetX2Jaw(50.0)
    firstBeamNode.SetY1Jaw(-50.0)
    firstBeamNode.SetY2Jaw(75.0)

    #TODO: For some reason the instance() function cannot be called as a class function although it's static
    engineHandler = slicer.qSlicerDoseEnginePluginHandler()
    engineHandlerSingleton = engineHandler.instance()
    plastimatchProtonEngine = engineHandlerSingleton.doseEngineByName('Plastimatch proton')
    plastimatchProtonEngine.setParameter(firstBeamNode, 'EnergyResolution', 4.0)
    plastimatchProtonEngine.setParameter(firstBeamNode, 'RangeCompensatorSmearingRadius', 0.0)
    plastimatchProtonEngine.setParameter(firstBeamNode, 'ProximalMargin', 0.0)
    plastimatchProtonEngine.setParameter(firstBeamNode, 'DistalMargin', 0.0)
    
    # Calculate dose
    import time
    startTime = time.time()
    
    errorMessage = engineLogic.calculateDose(planNode)
    self.assertNotEqual(errorMessage, "")
    
    calculationTime = time.time() - startTime
    logging.info('Dose computation time: ' + str(calculationTime) + ' s')
    
    # Check computed output
    imageAccumulate = vtk.vtkImageAccumulate()
    imageAccumulate.SetInputConnection(totalDoseVolumeNode.GetImageDataConnection())
    imageAccumulate.Update()

    doseMax = imageAccumulate.GetMax()[0]
    doseMean = imageAccumulate.GetMean()[0]
    doseStdDev = imageAccumulate.GetStandardDeviation()[0]
    doseVoxelCount = imageAccumulate.GetVoxelCount()
    logging.info("Dose volume properties:\n  Max=" + str(doseMax) + ", Mean=" + str(doseMean) + ", StdDev=" + str(doseStdDev) + ", NumberOfVoxels=" + str(doseVoxelCount))

    self.assertTrue(self.isEqualWithTolerance(doseMax, 1.05797))
    self.assertTrue(self.isEqualWithTolerance(doseMean, 0.0251127))
    self.assertTrue(self.isEqualWithTolerance(doseStdDev, 0.144932))
    self.assertTrue(self.isEqualWithTolerance(doseVoxelCount, 1000))