# Plot Tree Timing with MPI

**URL:** https://discourse.vtk.org/t/plot-tree-timing-with-mpi/14096
**Category:** Development
**Created:** [June 20, 2024, 10:08pm UTC](https://discourse.vtk.org/t/plot-tree-timing-with-mpi/14096 "2024-06-20T22:08:05Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Rafael\_Scatena](https://discourse.vtk.org/user_avatar/discourse.vtk.org/rafael_scatena/32/7820_2.png) [@Rafael\_Scatena](https://discourse.vtk.org/u/Rafael_Scatena)
#### Post date: [June 20, 2024, 10:08pm UTC](https://discourse.vtk.org/t/plot-tree-timing-with-mpi/14096/1 "2024-06-20T22:08:05Z")

</div>

Hello,

I developed a code to run the tree timing code with MPI. I am not familiar with MPI so I get segmentation fault when I call the function.

Thanks

Rafael Scatena

```
//#ifdef ENABLE_MPI
struct ParallelIsoArgs_tmp
{
  int* RetVal; // Pointer to store the return value
  int Argc; // Number of command-line arguments
  char** Argv; // Array of command-line arguments
  
  vtkCellLocator* CellLocator_mpi;
  vtkCellTreeLocator* CellTreeLocator_mpi;  
  vtkStaticCellLocator* StaticCellLocator_mpi;
  vtkOBBTree* OBBTree_mpi;
  vtkStaticCellLocator* StaticCellLocator;  
  vtkModifiedBSPTree* ModifiedBPSTree_mpi;  
  
      
  vtkMultiProcessController* Controller;
  
  vtkPolyData* Polydata_mpi;  
  LocatorType ChosenLocator_mpi;
  vtkMinimalStandardRandomSequence* Rng_mpi;

  int TotalTime;
  
  int NumberOfTrials;
};

void PlotTreeTimingMPI(vtkSmartPointer<vtkPolyData> polydata_mpi, LocatorType chosenLocator_mpi)
{
    vtkNew<vtkNamedColors> colors;
    vtkMinimalStandardRandomSequence* rng_mpi; rng_mpi->SetSeed(8000000); // rng->SetSeed(8775070);

     std::cout << "Timing Tree MPI..." << std::endl; 
     std::vector<std::pair<int, double>> results;

      int numberOfTrials = 1000;  
   

        
    for(int i= 0; i<16;i++){			  
			  
			  
          double allTimes=0;	    
          int argc_mpi = 0;
          char** argv_mpi = nullptr;

	      
	      vtkCellLocator* cellLocator_mpi;
          vtkCellTreeLocator* cellTreeLocator_mpi;  
          vtkStaticCellLocator* staticCellLocator_mpi;
          vtkOBBTree* oBBTree_mpi;
          vtkStaticCellLocator* staticCellLocator;  
          vtkModifiedBSPTree* modifiedBPSTree_mpi;  

			  
	switch (chosenLocator_mpi) {
			case CELL_LOCATOR:  
			cellLocator_mpi->SetDataSet(polydata_mpi);
			cellLocator_mpi->AutomaticOff();
			cellLocator_mpi->SetMaxLevel(i);
			cellLocator_mpi->UseExistingSearchStructureOn();
			cellLocator_mpi->BuildLocator();break;

			case CELL_TREE_LOCATOR:
			cellTreeLocator_mpi->SetDataSet(polydata_mpi);
			cellTreeLocator_mpi->SetNumberOfBuckets(i);
			cellTreeLocator_mpi->UseExistingSearchStructureOn();
			cellTreeLocator_mpi->BuildLocator();break;

			case STATIC_CELL_LOCATOR:
			staticCellLocator_mpi->SetDataSet(polydata_mpi);
			staticCellLocator_mpi->UseExistingSearchStructureOn();		
			staticCellLocator_mpi->SetMaxLevel(i);
			staticCellLocator_mpi->BuildLocator();break;

			case OBB_TREE:
			oBBTree_mpi->SetDataSet(polydata_mpi);
			oBBTree_mpi->UseExistingSearchStructureOn();
			oBBTree_mpi->AutomaticOff();
			oBBTree_mpi->SetMaxLevel(i);
			oBBTree_mpi->BuildLocator();break;
					
			case MODIFIED_BSP_TREE:
			modifiedBPSTree_mpi->SetDataSet(polydata_mpi);
			modifiedBPSTree_mpi->UseExistingSearchStructureOn();
			modifiedBPSTree_mpi->AutomaticOff();
			modifiedBPSTree_mpi->SetMaxLevel(i);
			modifiedBPSTree_mpi->BuildLocator();break;default:std::cerr << "Unknown Locator Type!" << std::endl;}

      

              // ----------------------------------------------
              int retVal = 1;
              ParallelIsoArgs_tmp args;
              args.RetVal = &retVal;
              args.Argc = argc_mpi;
              args.Argv = argv_mpi;
              args.CellLocator_mpi = cellLocator_mpi ;
  // args.CellTreeLocator_mpi = cellTreeLocator_mpi ;            
 // args.StaticCellLocator_mpi = staticCellLocator_mpi; 
  // args.OBBTree_mpi = oBBTree_mpi;
 // args.StaticCellLocator = staticCellLocator; 
 // args.ModifiedBPSTree_mpi = modifiedBPSTree_mpi;                      
       

       
              args.Polydata_mpi = polydata_mpi;
              args.Rng_mpi = rng_mpi;
              args.ChosenLocator_mpi = chosenLocator_mpi;
              args.NumberOfTrials = numberOfTrials;
              args.TotalTime = 0;
 
              MPI_Init(&argc_mpi, &argv_mpi);
              vtkMPIController* controller = vtkMPIController::New();
 
// int numProcesses = controller->GetNumberOfProcesses();
 // int myRank = controller->GetLocalProcessId();

 
              args.Controller =controller ;              
             
              controller->Initialize(&argc_mpi, &argv_mpi, 1);
              
              // ----------------------------------------------

              // Pass args to your execution method
              controller->SetSingleMethod(TimeTreeMPI, &args);
              controller->SingleMethodExecute();
           

               double collectedTime;
               collectedTime = args.TotalTime;

                
              controller->Finalize();
              controller->Delete(); 
            

        std::pair<int, double> result(i, collectedTime); results.push_back(result); std::cout << "Tree no: "<<i <<" ok!" << std::endl;

            }

	    // Create a table with some points in it.
	    vtkNew<vtkTable> table;

	    vtkNew<vtkFloatArray> maxPointsPerRegion;
	    maxPointsPerRegion->SetName("Max Tree Level");
	    table->AddColumn(maxPointsPerRegion);

	    vtkNew<vtkFloatArray> runtime;
	    runtime->SetName("Run time");
	    table->AddColumn(runtime);
	    
	    
	    // Fill in the table with some example values.
	    size_t numPoints = results.size();
	    table->SetNumberOfRows(static_cast<vtkIdType>(numPoints));
	    for (size_t i = 0; i < numPoints; ++i)
	    {table->SetValue(static_cast<vtkIdType>(i), 0, results[i].first);table->SetValue(static_cast<vtkIdType>(i), 1, results[i].second);}
	    
	    std::pair<int, double> minPair = Tree_Optimization::findMinimum(results);

		// Access the minimum value and its corresponding index
		int minIndex = minPair.first; double minValue = minPair.second;

	    // Set up the view
	    
		vtkNew<vtkEGLRenderWindow> renderWindow;	renderWindow->OffScreenRenderingOn();
		renderWindow->SetShowWindow(false);	renderWindow->WindowInitialize();
		renderWindow->SetSize(640, 480);
		
		std::string datastructuretype;

	int cells_per_bucket=0;

	switch (chosenLocator_mpi) 
	{case CELL_LOCATOR:renderWindow->SetWindowName("Cell Locator Timing MPI ");datastructuretype = "Cell Locator MPI"; cells_per_bucket = Cell_Locator->GetNumberOfCellsPerBucket(); break;
	case CELL_TREE_LOCATOR: renderWindow->SetWindowName("Cell Tree Locator MPI"); datastructuretype = "Cell Tree Locator MPI ";cells_per_bucket =Cell_Tree_Locator->GetNumberOfCellsPerNode(); break;
	case STATIC_CELL_LOCATOR: renderWindow->SetWindowName("Static Cell Locator MPI"); datastructuretype = "Static Cell Locator MPI"; cells_per_bucket = Static_Cell_Locator->GetNumberOfCellsPerNode(); break;
	case OBB_TREE: renderWindow->SetWindowName("OBBTreeTiming Demo"); datastructuretype = "OBB Tree MPI";cells_per_bucket = OBB_Tree->GetNumberOfCellsPerNode(); break;
	case MODIFIED_BSP_TREE: renderWindow->SetWindowName("Modified BSP Tree TimingDemo"); datastructuretype = "Modified BSP Tree MPI ";cells_per_bucket = Modified_BSP_Tree->GetNumberOfCellsPerNode(); break;default:std::cout << "Unknown Locator Type!" << std::endl;}    
		    
	    
		vtkNew<vtkRenderWindowInteractor> interactor;
		interactor->SetRenderWindow(renderWindow);

		vtkNew<vtkContextView> view;
		view->SetRenderWindow(renderWindow);

		// Add multiple line plots, setting the colors etc.
		vtkNew<vtkChartXY> chart;
		view->GetScene()->AddItem(chart);
		
		vtkPlot* line = chart->AddPlot(vtkChart::LINE);
		line->SetInputData(table, 0, 1);
		auto lineColor = colors->HTMLColorToRGBA("Lime").GetData();
		line->SetColor(lineColor[0], lineColor[1], lineColor[2], lineColor[3]);
		line->SetWidth(3.0);
	 
		
	std::string xtitle = "Optimal MPI Level for " + datastructuretype +": "+ std::to_string(minIndex) + " in "+ std::to_string(minValue) + "s. " +std::to_string(numberOfTrials) + " trial rays " +"Cells per Node: " + std::to_string(cells_per_bucket);
		
		line->GetXAxis()->SetMinimum(1.0);
		line->GetXAxis()->SetTitle(xtitle.c_str());
		line->GetYAxis()->SetTitle("Run time (seconds)");
		line->GetYAxis()->AutoScale();
		// line->GetYAxis()->SetRange(0,0.02);

		view->GetRenderWindow()->SetMultiSamples(0);    
		// Render and start interactor
		view->GetRenderWindow()->Render();
		interactor->Initialize();
		interactor->Start();

				  // PRINT
		vtkNew<vtkWindowToImageFilter> windowToImageFilter;
		windowToImageFilter->SetInput(renderWindow);
		windowToImageFilter->Update();
				  
		vtkNew<vtkPNGWriter> writer;
		writer->SetFileName(datastructuretype.c_str());
		writer->SetInputConnection(windowToImageFilter->GetOutputPort());
		writer->Write();
		
		}// END TIME A TREE	MPI

```

---

<div class="post-metadata">

### Author: ![Rafael\_Scatena](https://discourse.vtk.org/user_avatar/discourse.vtk.org/rafael_scatena/32/7820_2.png) [@Rafael\_Scatena](https://discourse.vtk.org/u/Rafael_Scatena)
#### Post date: [June 20, 2024, 10:09pm UTC](https://discourse.vtk.org/t/plot-tree-timing-with-mpi/14096/2 "2024-06-20T22:09:02Z")

</div>

The other function is like this:

```
void TimeTreeMPI(vtkMultiProcessController* controller, void* arg)
	{  
	

	   ParallelIsoArgs_tmp* args = reinterpret_cast<ParallelIsoArgs_tmp*>(arg);
	   vtkNew<vtkTimerLog> timer; timer->StartTimer();
	   
	
	    // Obtain the id of the running process and the total
	    // number of processes
	

         vtkSmartPointer<vtkPolyData> polydata_mpi= args->Polydata_mpi;

         
	    double p1[3]; double p2[3]; Tree_Optimization::RandomLineThroughVolume(polydata_mpi, p1, p2, args->Rng_mpi);
	    double t; double x[3]; double pcoords[3]; int subId; double tol = 1.0e-8;
			  

	//RAY INTERSECTION
	switch (args->ChosenLocator_mpi) {
	case CELL_LOCATOR: args->CellLocator_mpi->IntersectWithLine(p1, p2, .001, t, x, pcoords, subId); break;
	case CELL_TREE_LOCATOR: args->CellTreeLocator_mpi->IntersectWithLine(p1, p2, .001, t, x, pcoords, subId);break;
	case STATIC_CELL_LOCATOR: args->StaticCellLocator_mpi->IntersectWithLine(p1, p2, .001, t, x, pcoords, subId);break;
	case OBB_TREE: args->OBBTree_mpi->IntersectWithLine(p1, p2, .001, t, x, pcoords, subId);break;
	case MODIFIED_BSP_TREE: args->ModifiedBPSTree_mpi->IntersectWithLine(p1, p2, .001, t, x, pcoords, subId);break;default:std::cout << "Unknown Locator Type!" << std::endl;}
	
			  
	timer->StopTimer();
//	std::cout << "timer: " << timer->GetElapsedTime()<< " seconds" << std::endl;
	double elapsedTime = timer->GetElapsedTime();

       //GATHER AND PROCESS  	
    
    vtkMPICommunicator* communicator = vtkMPICommunicator::SafeDownCast(args->Controller->GetCommunicator());
    int myRank = communicator->GetLocalProcessId();
    if (myRank != 0) {communicator->Send(&elapsedTime, 1, 0, 123); } // Tag 123 is arbitrary
        else{
        std::vector<double> receivedTimes(args->Controller->GetNumberOfProcesses());
        receivedTimes[0] = elapsedTime; // Root's own elapsed time
        for (int i = 1; i < args->Controller->GetNumberOfProcesses(); ++i) {
            communicator->Receive(&receivedTimes[i], 1, i, 123); // Tag 123 is arbitrary
        }}

      // Prepare the receive buffer only on the root process
        
/*
      if (myid == 0) {
      
      std::vector<double> receiveBuffer;

      receiveBuffer.resize(numberOfTrials * numProcesses);

      // Gather doubles to the root process
        controller->Gather(arg->sendBuffer.data(), receiveBuffer.data(), arg->NumberOfTrials, 0);
        allTimes = 0;
        
              vtkMPIController* control = arg.Controller;
              int numProcesses = control->GetNumberOfProcesses();
        
              for (int i = 0; i < numProcesses; ++i) {allTimes =allTimes + receiveBuffer[i];}}

			  */
			  
			  
			  }//

```

---

<div class="post-metadata">

### Author: ![Rafael\_Scatena](https://discourse.vtk.org/user_avatar/discourse.vtk.org/rafael_scatena/32/7820_2.png) [@Rafael\_Scatena](https://discourse.vtk.org/u/Rafael_Scatena)
#### Post date: [June 21, 2024, 3:47am UTC](https://discourse.vtk.org/t/plot-tree-timing-with-mpi/14096/3 "2024-06-21T03:47:43Z")

</div>

This code worked. There were several issues including that the intersectwithline function was protected when threaded.

```
struct ParallelIsoArgs_tmp
{
  int* RetVal; // Pointer to store the return value
  int Argc; // Number of command-line arguments
  char** Argv; // Array of command-line arguments
  
  vtkCellLocator* CellLocator_mpi;
// vtkCellTreeLocator* CellTreeLocator_mpi;  
// vtkStaticCellLocator* StaticCellLocator_mpi;
// vtkOBBTree* OBBTree_mpi;
// vtkModifiedBSPTree* ModifiedBPSTree_mpi;  
  
      
  vtkMultiProcessController* Controller;
  
  vtkPolyData* Polydata_mpi;  
  LocatorType ChosenLocator_mpi;
  vtkMinimalStandardRandomSequence* Rng_mpi;

  int TotalTime;
  int MaxLevel;
  
  int NumberOfTrials;
};

  TimeTreeMPI(vtkMultiProcessController* controller, void* arg)
{  
	
//	std::cout << "begin mpi!" << std::endl;

	   ParallelIsoArgs_tmp* args = reinterpret_cast<ParallelIsoArgs_tmp*>(arg);
	   vtkNew<vtkTimerLog> timer; timer->StartTimer();
	   
// std::cout << "args ok!" << std::endl;
		
	    // Obtain the id of the running process and the total
	    // number of processes
	

         vtkSmartPointer<vtkPolyData> polydata_mpi= args->Polydata_mpi;

         
	    double p1[3]; double p2[3]; Tree_Optimization::RandomLineThroughVolume(polydata_mpi, p1, p2, args->Rng_mpi);
	    double t; double x[3]; double pcoords[3]; int subId; double tol = 1.0e-8; vtkIdType cellId; vtkGenericCell* cell;
	
	vtkPoints* points; vtkIdList* cellIds;
	
// std::cout << "p1:"<<p1[0] << std::endl;		  

          LocatorType choLocator;
        
          choLocator =args->ChosenLocator_mpi;
        
// vtkCellLocator* cellLocator_mpi;
// vtkCellTreeLocator* cellTreeLocator_mpi;  
// vtkStaticCellLocator* staticCellLocator_mpi;
// vtkOBBTree* oBBTree_mpi;
// vtkModifiedBSPTree* modifiedBPSTree_mpi;   
          
            vtkNew<vtkCellLocator> cellLocator_mpi;
            
            
// vtkNew<vtkCellTreeLocator> cellTreeLocator_mpi;  
// vtkNew<vtkStaticCellLocator> staticCellLocator_mpi;
// vtkNew<vtkOBBTree> oBBTree_mpi;
// vtkNew<vtkModifiedBSPTree> modifiedBPSTree_mpi;  
          
        	cellLocator_mpi->SetDataSet(args->Polydata_mpi);
			cellLocator_mpi->AutomaticOff();
			cellLocator_mpi->SetMaxLevel(args->MaxLevel);
			cellLocator_mpi->UseExistingSearchStructureOn();
			cellLocator_mpi->BuildLocator();

	// std::cout << "locator ok" << std::endl;		  

   // cellLocator_mpi->IntersectWithLine(p1,p2,.001,t,x,pcoords,subId,cellId,cell); 
        	cellLocator_mpi->IntersectWithLine(p1,p2,points,cellIds);
	
  
  // std::cout << "intersect ok"<< std::endl;		        
	//RAY INTERSECTION
//	switch (choLocator) {
//	case CELL_LOCATOR: cellLocator_mpi->IntersectWithLine(p1,p2,.001,t,x,pcoords,subId,cellId,cell); 
//	case CELL_TREE_LOCATOR: TreeLocator_mpi = args->CellTreeLocator_mpi;
	// TreeLocator_mpi->IntersectWithLine(p1,p2,.001,t,x,pcoords,subId,cellId,cell);break;
//	case STATIC_CELL_LOCATOR: staticLocator_mpi = args->StaticCellLocator_mpi;
	// staticLocator_mpi->IntersectWithLine(p1,p2,.001,t,x,pcoords,subId,cellId,cell);break;
//	case OBB_TREE: oBTree_mpi = args->OBBTree_mpi;
	// oBTree_mpi->IntersectWithLine(p1,p2,.001,t,x,pcoords,subId,cellId,cell);break;
//	case MODIFIED_BSP_TREE: BPSTree_mpi = args->ModifiedBPSTree_mpi;
// BPSTree_mpi->IntersectWithLine(p1,p2,.001,t,x,pcoords,subId,cellId,cell);break;default:std::cout << "Unknown Locator Type!" << std::endl;
//}
	
	
// std::cout << "Intersect ok!" << std::endl;
			  
	timer->StopTimer();
//	std::cout << "timer: " << timer->GetElapsedTime()<< " seconds" << std::endl;
	double elapsedTime = timer->GetElapsedTime();

       //GATHER AND PROCESS  	
    

			  
			  
			  }//
			  

void PlotTreeTimingMPI(vtkSmartPointer<vtkPolyData> polydata_mpi, LocatorType chosenLocator_mpi,int argc, char* argv[])
{
    vtkNew<vtkNamedColors> colors;
    vtkNew<vtkMinimalStandardRandomSequence> rng_mpi; rng_mpi->SetSeed(8000000); // rng->SetSeed(8775070);

     std::cout << "Timing Tree MPI..." << std::endl; 
     std::vector<std::pair<int, double>> results;

      int numberOfTrials = 1000;  
   

       //BROADCAST TREE TYPE	

	      vtkNew<vtkCellLocator> cellLocator_mpi;
          vtkNew<vtkCellTreeLocator> cellTreeLocator_mpi;  
          vtkNew<vtkStaticCellLocator> staticCellLocator_mpi;
          vtkNew<vtkOBBTree> oBBTree_mpi;
          vtkNew<vtkModifiedBSPTree> modifiedBPSTree_mpi;  
          
          
    MPI_Init(&argc, &argv); // Initialize MPI once at the beginning

    vtkMPIController* controller = vtkMPIController::New();
    controller->Initialize(&argc, &argv, 1); // Initialize controller once at the beginning

        
    for(int i= 1; i<16;i++){	
    
    		  
		switch (chosenLocator_mpi) {
			case CELL_LOCATOR:  
			cellLocator_mpi->SetDataSet(polydata_mpi);
			cellLocator_mpi->AutomaticOff();
			cellLocator_mpi->SetMaxLevel(i);
			cellLocator_mpi->UseExistingSearchStructureOn();
			cellLocator_mpi->BuildLocator();break;

			case CELL_TREE_LOCATOR:
			cellTreeLocator_mpi->SetDataSet(polydata_mpi);
			cellTreeLocator_mpi->SetNumberOfBuckets(i);
			cellTreeLocator_mpi->UseExistingSearchStructureOn();
			cellTreeLocator_mpi->BuildLocator();break;

			case STATIC_CELL_LOCATOR:
			staticCellLocator_mpi->SetDataSet(polydata_mpi);
			staticCellLocator_mpi->UseExistingSearchStructureOn();		
			staticCellLocator_mpi->SetMaxLevel(i);
			staticCellLocator_mpi->BuildLocator();break;

			case OBB_TREE:
			oBBTree_mpi->SetDataSet(polydata_mpi);
			oBBTree_mpi->UseExistingSearchStructureOn();
			oBBTree_mpi->AutomaticOff();
			oBBTree_mpi->SetMaxLevel(i);
			oBBTree_mpi->BuildLocator();break;
					
			case MODIFIED_BSP_TREE:
			modifiedBPSTree_mpi->SetDataSet(polydata_mpi);
			modifiedBPSTree_mpi->UseExistingSearchStructureOn();
			modifiedBPSTree_mpi->AutomaticOff();
			modifiedBPSTree_mpi->SetMaxLevel(i);
			modifiedBPSTree_mpi->BuildLocator();break;
			
			default:std::cerr << "Unknown Locator Type!" << std::endl;}

              double allTimes=0;	    
              int argc_mpi = 0;
              char** argv_mpi = nullptr;

      

              // ----------------------------------------------
              int retVal = 1;
              ParallelIsoArgs_tmp args;
              args.RetVal = &retVal;
              args.Argc = argc;
              args.Argv = argv;
              args.CellLocator_mpi = cellLocator_mpi ;
  /// args.CellTreeLocator_mpi = cellTreeLocator_mpi ;            
 // args.StaticCellLocator_mpi = staticCellLocator_mpi; 
 // args.OBBTree_mpi = oBBTree_mpi;
 // args.ModifiedBPSTree_mpi = modifiedBPSTree_mpi;                      
       

       
              args.Polydata_mpi = polydata_mpi;
              args.Rng_mpi = rng_mpi;
              args.ChosenLocator_mpi = chosenLocator_mpi;
              args.NumberOfTrials = numberOfTrials;
              args.TotalTime = 0;
              args.MaxLevel =i;
  // std::cerr << "args ok!" << std::endl;
 

              vtkMPIController* controller = vtkMPIController::New();
 
 // std::cerr << "Controler ok!" << std::endl;
// int numProcesses = controller->GetNumberOfProcesses();
 // int myRank = controller->GetLocalProcessId();

 
              args.Controller =controller ;              
             
              controller->Initialize(&argc, &argv, 1);
              
              // ----------------------------------------------

	        vtkNew<vtkTimerLog> timer; timer->StartTimer();

 // std::cerr << "controler init!" << std::endl;
              // Pass args to your execution method
              controller->SetSingleMethod(TimeTreeMPI, &args);
              controller->SingleMethodExecute();
    
 // std::cerr << "controler execute!" << std::endl;       

     // double collectedTime;
      // collectedTime = args.TotalTime;

 // std::cerr << "collected time!" << std::endl;
                
	        timer->StopTimer();
        //	std::cout << "timer: " << timer->GetElapsedTime()<< " seconds" << std::endl;
	        double elapsedTime = timer->GetElapsedTime(); 

              std::cerr << "TIME!: "<< elapsedTime<< std::endl;            

        std::pair<int, double> result(i, elapsedTime); results.push_back(result); std::cout << "Tree no: "<<i <<" ok!" << std::endl;

            }
            
              controller->Finalize();
              controller->Delete();

	    // Create a table with some points in it.
	    vtkNew<vtkTable> table;

	    vtkNew<vtkFloatArray> maxPointsPerRegion;
	    maxPointsPerRegion->SetName("Max Tree Level");
	    table->AddColumn(maxPointsPerRegion);

	    vtkNew<vtkFloatArray> runtime;
	    runtime->SetName("Run time");
	    table->AddColumn(runtime);
	    
	    
	    // Fill in the table with some example values.
	    size_t numPoints = results.size();
	    table->SetNumberOfRows(static_cast<vtkIdType>(numPoints));
	    for (size_t i = 0; i < numPoints; ++i)
	    {table->SetValue(static_cast<vtkIdType>(i), 0, results[i].first);table->SetValue(static_cast<vtkIdType>(i), 1, results[i].second);}
	    
	    std::pair<int, double> minPair = Tree_Optimization::findMinimum(results);

		// Access the minimum value and its corresponding index
		int minIndex = minPair.first; double minValue = minPair.second;

	    // Set up the view
	    
		vtkNew<vtkEGLRenderWindow> renderWindow;	renderWindow->OffScreenRenderingOn();
		renderWindow->SetShowWindow(false);	renderWindow->WindowInitialize();
		renderWindow->SetSize(640, 480);
		
		std::string datastructuretype;

	int cells_per_bucket=0;

	switch (chosenLocator_mpi) 
	{case CELL_LOCATOR:renderWindow->SetWindowName("Cell Locator Timing MPI ");datastructuretype = "Cell Locator MPI"; cells_per_bucket = Cell_Locator->GetNumberOfCellsPerBucket(); break;
	case CELL_TREE_LOCATOR: renderWindow->SetWindowName("Cell Tree Locator MPI"); datastructuretype = "Cell Tree Locator MPI ";cells_per_bucket =Cell_Tree_Locator->GetNumberOfCellsPerNode(); break;
	case STATIC_CELL_LOCATOR: renderWindow->SetWindowName("Static Cell Locator MPI"); datastructuretype = "Static Cell Locator MPI"; cells_per_bucket = Static_Cell_Locator->GetNumberOfCellsPerNode(); break;
	case OBB_TREE: renderWindow->SetWindowName("OBBTreeTiming Demo"); datastructuretype = "OBB Tree MPI";cells_per_bucket = OBB_Tree->GetNumberOfCellsPerNode(); break;
	case MODIFIED_BSP_TREE: renderWindow->SetWindowName("Modified BSP Tree TimingDemo"); datastructuretype = "Modified BSP Tree MPI ";cells_per_bucket = Modified_BSP_Tree->GetNumberOfCellsPerNode(); break;default:std::cout << "Unknown Locator Type!" << std::endl;}    
		    
	    
		vtkNew<vtkRenderWindowInteractor> interactor;
		interactor->SetRenderWindow(renderWindow);

		vtkNew<vtkContextView> view;
		view->SetRenderWindow(renderWindow);

		// Add multiple line plots, setting the colors etc.
		vtkNew<vtkChartXY> chart;
		view->GetScene()->AddItem(chart);
		
		vtkPlot* line = chart->AddPlot(vtkChart::LINE);
		line->SetInputData(table, 0, 1);
		auto lineColor = colors->HTMLColorToRGBA("Lime").GetData();
		line->SetColor(lineColor[0], lineColor[1], lineColor[2], lineColor[3]);
		line->SetWidth(3.0);
	 
		
	std::string xtitle = "Optimal MPI Level for " + datastructuretype +": "+ std::to_string(minIndex) + " in "+ std::to_string(minValue) + "s. " +std::to_string(numberOfTrials) + " trial rays " +"Cells per Node: " + std::to_string(cells_per_bucket);
		
		line->GetXAxis()->SetMinimum(1.0);
		line->GetXAxis()->SetTitle(xtitle.c_str());
		line->GetYAxis()->SetTitle("Run time (seconds)");
		line->GetYAxis()->AutoScale();
		// line->GetYAxis()->SetRange(0,0.02);

		view->GetRenderWindow()->SetMultiSamples(0);    
		// Render and start interactor
		view->GetRenderWindow()->Render();
		interactor->Initialize();
		interactor->Start();

				  // PRINT
		vtkNew<vtkWindowToImageFilter> windowToImageFilter;
		windowToImageFilter->SetInput(renderWindow);
		windowToImageFilter->Update();
				  
		vtkNew<vtkPNGWriter> writer;
		writer->SetFileName(datastructuretype.c_str());
		writer->SetInputConnection(windowToImageFilter->GetOutputPort());
		writer->Write();
		
		}// END TIME A TREE	MPI

```

---

<div class="post-metadata">

### Author: ![Rafael\_Scatena](https://discourse.vtk.org/user_avatar/discourse.vtk.org/rafael_scatena/32/7820_2.png) [@Rafael\_Scatena](https://discourse.vtk.org/u/Rafael_Scatena)
#### Post date: [June 21, 2024, 3:19pm UTC](https://discourse.vtk.org/t/plot-tree-timing-with-mpi/14096/4 "2024-06-21T15:19:16Z")

</div>

Result:

 ![image (1)](https://discourse.vtk.org/uploads/default/original/2X/0/047eba2bb4e20ec0ea2073756d0280086dcbb7f8.png)
