5 #include <boost/filesystem.hpp>
6 #include <boost/program_options.hpp>
9 #include "airwaysTree.h"
11 #include <cpPlugins/Interface.h>
12 #include <cpPlugins/Workspace.h>
14 using namespace airways;
15 namespace po = boost::program_options;
19 const size_t ERROR_IN_COMMAND_LINE = 1;
20 const size_t SUCCESS = 0;
21 const size_t ERROR_UNHANDLED_EXCEPTION = 2;
24 typedef std::vector< AirwaysTree > AirwaysVector;
26 #include <itkCastImageFilter.h>
28 // Auxiliar struct to save info for execution.
29 typedef void* TImagePointer;
34 this->myWorkspace = new cpPlugins::Workspace( );
39 if( this->IsMyWorkspace )
40 delete this->myWorkspace;
46 auto image = this->myWorkspace->GetFilter( "reader" )->GetOutputData( "Output" )->GetITK< itk::Image< unsigned char, 3 > >( );
47 typedef itk::CastImageFilter< itk::Image< unsigned char, 3 >, TInputImage > _TCast;
48 _TCast::Pointer cast = _TCast::New( );
49 cast->SetInput( image );
51 this->Image = cast->GetOutput( );
52 this->Image->DisconnectPipeline( );
55 TInputImage::Pointer Image;
56 cpPlugins::Workspace* myWorkspace;
59 std::string folderpath_pigResults;
61 std::string image_name;
65 unsigned char red[3] = { 255, 0, 0 };
66 unsigned char green[3] = { 0, 255, 0 };
67 unsigned char blue[3] = { 0, 0, 255 };
68 unsigned char yellow[3]= { 255, 255, 0 };
69 unsigned char purple[3]= { 255, 0, 255 };
70 unsigned char cyan[3]= { 0, 255, 255 };
72 cpPlugins::Interface myPlugins;
74 // -------------------------------------------------------------------------
75 void Load_cpPlugins( const std::string& plugins );
76 void CreateResultDirectory(AirwaysTree tree);
77 void DrawVTKLinesFromTree(AirwaysTree& tree, const std::string filename, bool common);
78 AirwaysTree& CreateAirwaysTreeFromSegmentation(Vec3 seed, TInputImage* input_image, cpPlugins::Workspace& ws );
79 vector<TreeInfo> ReadInputFile(const char* filename);
80 void printCommonTreeBetweenTwoTrees(AirwaysTree tree_A, AirwaysTree tree_B, std::vector< std::pair< std::pair<Node*, Node*>, std::pair<Node*, Node*> > > vector_pair_edges_A_to_B, unsigned int Q, unsigned int F);
81 void printMatchingResultToFile(AirwaysTree tree_A, AirwaysTree tree_B, std::map< unsigned int, std::vector<Node*> > map_A_to_B, std::map< unsigned int, std::vector<Node*> > map_B_to_A, unsigned int Q, unsigned int F);
82 void createLinesAndPointsForVTK(const Node* node, vtkSmartPointer<vtkPoints>& pts,vtkSmartPointer<vtkCellArray>& lines, vtkSmartPointer<vtkUnsignedCharArray>& colors, bool common, bool isRoot);
84 // -------------------------------------------------------------------------
85 int main( int argc, char* argv[] )
87 Load_cpPlugins( "./plugins.cfg" );
91 // Define and parse the program options
92 po::options_description desc("Options");
93 desc.add_options()("use_file", po::value<std::string>(), "Adds the filepath containing the file to be used in creaAirwaysTree -- Mandatory")
94 ("build_trees","Creates trees from a given filepath (arg) and stores it in a .vtk file")
95 ("subtree_levels", po::value<int>(),"Get a subtree(s) by levels - result: a vtk and reconstructed img .mhd")
96 ("subtree_length", po::value<float>(),"Get a subtree(s) by length - result: a vtk and reconstructed img .mhd")
97 ("subtree_diameter", po::value<float>(),"Get a subtree(s) by diameter - result: a vtk and reconstructed img .mhd")
98 ("compare_trees", "Compare the trees given in the input file or the subtrees using an option - result: a vtk and reconstructed img .mhd");
99 //TODO: Fix image segmentation. ("segment_images", "Creates a binary image corresponding to the segmentation of of a given original image (arg) and seed (arg), saves it to a .mhd file and uses it for subsequent operations")
100 po::variables_map vm;
103 std::string fileName;
104 vector<TreeInfo> treeInfoVector;
105 AirwaysVector aVector;
106 TImagePointer segmentationImage;
108 po::store(po::parse_command_line(argc, argv, desc), vm); // can throw
109 if (vm.count("use_file"))
111 fileName = vm["use_file"].as<std::string>();
112 treeInfoVector = ReadInputFile(fileName.c_str());
115 if(vm.count("segment_images"))
119 // Build trees option
120 if (vm.count("build_trees"))
122 for(unsigned int i = 0; i < treeInfoVector.size(); ++ i){
123 TreeInfo info = treeInfoVector[i];
126 info.myWorkspace->PrintExecutionOn( );
127 info.myWorkspace->Execute( "eb" );
129 catch( itk::ExceptionObject& err )
131 std::cerr << "Error: " << err << std::endl;
136 AirwaysTree tree = CreateAirwaysTreeFromSegmentation( info.seed, info.Image, *(info.myWorkspace ));
137 tree.SetResultPath(info.folderpath_pigResults);
138 tree.SetImageName(info.image_name);
139 aVector.push_back(tree);
141 for (unsigned int i = 0; i < aVector.size(); ++i)
143 CreateResultDirectory(aVector[i]);
144 std::string fullPath = aVector[i].GetResultPath() + "/" + aVector[i].GetImageName() + ".vtk";
145 DrawVTKLinesFromTree(aVector[i], fullPath, false);
150 // Subtree levels option
151 if (vm.count("subtree_levels"))
154 else if (vm.count("subtree_length"))
157 else if (vm.count("subtree_diameter"))
161 if (vm.count("compare_trees"))
163 std::cout << "Option: Compare trees" << std::endl;
165 * this piece of code only test in the case of two trees, so it can be replaced
166 * to a code which does a cascade
169 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 //CODIGO DE COMPARACIÓN DE ARBOLES
173 //std::cout << "Comparing trees ..." << std::endl;
174 //aVector[0].CompareTrees(aVector[1]);
175 //std::cout << "Comparing trees ... OK" << std::endl;
177 std::cout << "Tree A ... " << std::endl;
178 //aVector[0].printNodeAndChildrenIds();
179 std::cout << "Tree A ... OK" << std::endl;
181 std::cout << "Tree B ... " << std::endl;
182 //aVector[1].printNodeAndChildrenIds();
183 std::cout << "Tree B ... OK" << std::endl;
185 std::cout << "Comparing trees Orkisz-Morales..." << std::endl;
186 // Vectors to save the common and uncommon nodes
189 vec_nodes nonCommonA;
190 vec_nodes nonCommonB;
191 std::map< unsigned int, std::vector<Node*> > map_A_to_B;
192 std::map< unsigned int, std::vector<Node*> > map_B_to_A;
193 std::vector< std::pair< std::pair<Node*, Node*>, std::pair<Node*, Node*> > > vector_pair_edges_A_to_B;
195 // Input parameter for comparison
196 unsigned int Q = 1; // Corresponds to the depth to select "fathers" nodes
197 unsigned int F = 1; // Correspond to the depth to select "family" nodes
198 std::cout << "Q = " << Q << std::endl;
199 std::cout << "F = " << F << std::endl;
201 clock_t before_compare = clock();
202 aVector[0].CompareTreesOrkiszMorales(aVector[1], Q, F, commonA, commonB, nonCommonA, nonCommonB, map_A_to_B, map_B_to_A, vector_pair_edges_A_to_B);
203 clock_t after_compare = clock();
204 double compare_time = double(after_compare - before_compare) / CLOCKS_PER_SEC;
205 std::cout << "Matching time: " << compare_time << std::endl;
207 // Print the common tree with common edges
208 printCommonTreeBetweenTwoTrees(aVector[0], aVector[1], vector_pair_edges_A_to_B, Q, F);
209 printMatchingResultToFile(aVector[0], aVector[1], map_A_to_B, map_B_to_A, Q, F);
210 //printSeparatedCommonTrees(aVector[0], aVector[1], vector_pair_edges_A_to_B, Q, F);
211 //reconstructAndSaveCommonTrees(aVector[0], aVector[1], vector_pair_edges_A_to_B, Q, F);
213 // Print all the maps that have more that two connections
214 std::cout << "Printing multiple relation A to B. Total relations: " << map_A_to_B.size() << std::endl;
215 for(std::map< unsigned int, std::vector<Node*> >::iterator it_map_A_to_B = map_A_to_B.begin(); it_map_A_to_B != map_A_to_B.end(); ++it_map_A_to_B)
217 if((*it_map_A_to_B).second.size() > 1)
219 std::cout << "Multiple relation A to B with size:" << (*it_map_A_to_B).second.size() << ", from Id:" << (*it_map_A_to_B).first << std::endl;
220 for(std::vector<Node*>::iterator it_node = (*it_map_A_to_B).second.begin(); it_node != (*it_map_A_to_B).second.end(); ++it_node)
222 std::cout << "Id: " << (*it_node)->GetId() << std::endl;
226 std::cout << "Printing multiple relation A to B ... OK" << std::endl;
228 std::cout << "Printing multiple relation B to A. Total relations: " << map_B_to_A.size() << std::endl;
229 for(std::map< unsigned int, std::vector<Node*> >::iterator it_map_B_to_A = map_B_to_A.begin(); it_map_B_to_A != map_B_to_A.end(); ++it_map_B_to_A)
231 if((*it_map_B_to_A).second.size() > 1)
233 std::cout << "Multiple relation B to A with size:" << (*it_map_B_to_A).second.size() << ", from Id:" << (*it_map_B_to_A).first << std::endl;
234 for(std::vector<Node*>::iterator it_node = (*it_map_B_to_A).second.begin(); it_node != (*it_map_B_to_A).second.end(); ++it_node)
236 std::cout << "Id: " << (*it_node)->GetId() << std::endl;
240 std::cout << "Printing multiple relation B to A ... OK" << std::endl;
242 // Mark only the common nodes
243 aVector[0].UnMarkAll();
244 aVector[1].UnMarkAll();
246 // --------------------------------------
247 // ------ Get common paths marked -------
248 // --------------------------------------
251 std::string path_folder = "/run/media/alfredo/Data/Pulmones/results/airwaysGraphs/comparisonResutls/probes/";
252 std::string suffix_vtk = ".vtk";
253 std::string name_tree = "TreeA_dP2P";
255 for(vec_nodes::iterator it_A = commonA.begin(); it_A != commonA.end(); ++it_A)
257 aVector[0].MarkPathFromNodeToNode(aVector[0].GetRoot(), (*it_A));
259 std::stringstream filepath_actualIteration;
260 filepath_actualIteration << path_folder << name_tree << "__" << iteration << "_idA_" << (*it_A)->GetId() << suffix_vtk;
262 DrawVTKLinesFromTree(aVector[0], filepath_actualIteration.str(), true);
267 name_tree = "TreeB_dP2P";
268 for(vec_nodes::iterator it_B = commonB.begin(); it_B != commonB.end(); ++it_B)
270 aVector[1].MarkPathFromNodeToNode(aVector[1].GetRoot(), (*it_B));
272 std::stringstream filepath_actualIteration;
273 filepath_actualIteration << path_folder << name_tree << "__" << iteration << "_idB_" << (*it_B)->GetId() << suffix_vtk;
275 DrawVTKLinesFromTree(aVector[1], filepath_actualIteration.str(), true);
280 // --------------------------------------
281 // --------------------------------------
284 //XXXXXXXXXXXXXXXXXXXXXXXXXXXX
285 //1. PRINT EACH NODE OF EACH TREE AND SAVE IT USING AS NAME ITS ID
288 for(int i = 2; i < aVector[0].GetWeight(); ++i)
290 //std::cout << "Writing idA: " << i << std::endl;
291 AirwaysTree* tree_id = aVector[0].GetSingleDetachedTreeNodeById(i);
292 //std::cout << "Got id: " << i << ", numberOfNodes: " << tree_id->GetWeight() << std::endl;
295 std::stringstream filepath_actualIteration;
296 filepath_actualIteration << aVector[0].GetResultPath() << "/" << aVector[0].GetImageName() << "_id_" << i << suffix_vtk;
297 DrawVTKLinesFromTree(*tree_id, filepath_actualIteration.str(), false);
301 std::cout << "Tree NULL" << std::endl;
305 for(int i = 2; i < aVector[1].GetWeight(); ++i)
307 //std::cout << "Writing idA: " << i << std::endl;
308 AirwaysTree* tree_id = aVector[1].GetSingleDetachedTreeNodeById(i);
309 //std::cout << "Got id: " << i << ", numberOfNodes: " << tree_id->GetWeight() << std::endl;
312 std::stringstream filepath_actualIteration;
313 filepath_actualIteration << aVector[1].GetResultPath() << "/" << aVector[1].GetImageName() << "_id_" << i << suffix_vtk;
314 DrawVTKLinesFromTree(*tree_id, filepath_actualIteration.str(), false);
318 std::cout << "Tree NULL" << std::endl;
321 std::cout << "Comparing trees Orkisz-Morales... OK" << std::endl;
325 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 aVector[0].SubIsomorphism(aVector[1]);
332 std::cout << "Flag after SubIsomorphism" << std::endl;
333 std::string fullPathA = aVector[0].GetResultPath() + "/" + aVector[0].GetImageName() + "_CMP.vtk";
334 std::string fullPathB = aVector[1].GetResultPath() + "/" + aVector[1].GetImageName() + "_CMP.vtk";
335 DrawVTKLinesFromTree(aVector[0], fullPathA, true);
336 DrawVTKLinesFromTree(aVector[1], fullPathB, true);
338 std::cout << "Flag after write vtk" << std::endl;
339 TInputImage::Pointer imgA, imgB;
340 aVector[0].ImageReconstruction(imgA);
341 std::cout << "Flag after Reconstruction A" << std::endl;
343 aVector[1].ImageReconstruction(imgB);
344 std::cout << "Flag after Reconstruction B" << std::endl;
346 std::string fullPathA_mhd = aVector[0].GetResultPath() + "/" + aVector[0].GetImageName() + "_CMP.vtk";
347 std::string fullPathB_mhd = aVector[1].GetResultPath() + "/" + aVector[1].GetImageName() + "_CMP.vtk";
348 WriteImage(imgA, fullPathA_mhd);
349 WriteImage(imgB, fullPathB_mhd);
353 po::notify(vm); // throws on error, so do after help in case
355 catch (std::exception& e)
357 std::cerr << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
358 return ERROR_UNHANDLED_EXCEPTION;
361 catch (std::exception& e)
363 std::cerr << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl;
364 return ERROR_UNHANDLED_EXCEPTION;
369 // -------------------------------------------------------------------------
370 void Load_cpPlugins( const std::string& plugins )
372 myPlugins.LoadConfiguration( plugins );
375 // -------------------------------------------------------------------------
376 void CreateResultDirectory(AirwaysTree tree)
378 boost::filesystem::path dir(tree.GetResultPath());
379 if (boost::filesystem::create_directories(dir))
381 std::cout << "FolderName = " << tree.GetResultPath() << " has been created" << std::endl;
384 std::cout << "FolderName = " << tree.GetResultPath() << " already exists" << std::endl;
387 // -------------------------------------------------------------------------
388 void DrawVTKLinesFromTree(AirwaysTree& tree, const std::string filepath, bool common)
390 // Create the array of points, lines, and colors
391 vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();
392 vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
393 vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
394 colors->SetNumberOfComponents(3);
395 colors->SetName("Colors");
397 //vtk sphere for sources
398 //vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
399 //Vec3 root = tree.GetRoot()->GetCoords();
400 //sphereSource->SetCenter(root[0], root[1], root[2]);
401 //sphereSource->SetRadius(1);
407 // Create and fill the points, lines, and color vectors
408 //CalculateVTKLinesFromEdges(tree.GetRoot(), 0, id, pts, lines, colors, common);
409 pts->SetNumberOfPoints(tree.GetWeight()+1);
410 createLinesAndPointsForVTK(tree.GetRoot(), pts, lines, colors, common, true);
412 // Create the polydata
413 vtkSmartPointer<vtkPolyData> linesPolyData = vtkSmartPointer<vtkPolyData>::New();
415 // Set the points, lines, and colors
416 linesPolyData->SetPoints(pts);
417 linesPolyData->SetLines(lines);
418 linesPolyData->GetCellData()->SetScalars(colors);
421 vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
422 writer->SetFileName(filepath.c_str());
424 #if VTK_MAJOR_VERSION <= 5
425 writer->SetInput(linesPolyData);
427 writer->SetInputData(linesPolyData);
431 //The following code is to test the vtk polydata and visualize it
433 vtkSmartPointer<vtkPolyDataMapper> mapper =
434 vtkSmartPointer<vtkPolyDataMapper>::New();
435 #if VTK_MAJOR_VERSION <= 5
436 mapper->SetInput(linesPolyData);
438 mapper->SetInputData(linesPolyData);
440 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
441 actor->SetMapper(mapper);
444 vtkSmartPointer<vtkPolyDataMapper> mapperSphere = vtkSmartPointer<
445 vtkPolyDataMapper>::New();
446 mapperSphere->SetInputConnection(sphereSource->GetOutputPort());
448 vtkSmartPointer<vtkActor> actorSphere = vtkSmartPointer<vtkActor>::New();
449 actorSphere->SetMapper(mapperSphere);
452 vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
453 vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<
454 vtkRenderWindow>::New();
455 renderWindow->AddRenderer(renderer);
456 vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
457 vtkSmartPointer<vtkRenderWindowInteractor>::New();
458 renderWindowInteractor->SetRenderWindow(renderWindow);
459 renderer->AddActor(actorSphere);
460 renderer->AddActor(actor);
462 renderWindow->Render();
463 renderWindowInteractor->Start();*/
466 // -------------------------------------------------------------------------
467 #include <fpa/Base/ImageSkeleton.h>
468 #include <fpa/Image/MinimumSpanningTree.h>
469 #include <cpExtensions/DataStructures/ImageIndexesContainer.h>
470 #include <itkImage.h>
473 template< class TImage, class TVertex >
474 Node* FAVertexToNode( TVertex vertex, TImage* image )
476 //The FrontAlgorithms Vertex is an TImageType::IndexType
477 typename TImage::PointType point;
478 image->TransformIndexToPhysicalPoint( vertex, point );
479 Vec3 alfPoint(point[0],point[1],point[2]);
480 return new Node(alfPoint);
483 AirwaysTree& ConvertFilterToAirwaysTree( TInputImage* input_image, cpPlugins::Workspace& ws )
486 fpa::Base::ImageSkeleton< fpa::Image::MinimumSpanningTree< 3 > >
488 typedef TFASkeleton::TVertex TVertexFA;
489 typedef TFASkeleton::TVertexCmp TVertexCompareFA;
490 typedef cpExtensions::DataStructures::ImageIndexesContainer< 3 > TVerticesFA;
492 typedef Node TVertexAirways;
493 typedef Edge TEdgeAirways;
494 typedef pair_posVox_rad TSkelePoint;
495 typedef vec_pair_posVox_rad TSkelePoints;
496 typedef std::map< TVertexFA, TVertexAirways*, TVertexCompareFA > VertexMap;
498 std::time_t start,end;
500 std::cout << "Starting conversion " << std::endl;
502 auto w_filter = ws.GetFilter( "eb" );
504 ws.GetFilter( "dmap" )->GetOutputData( "Output" )->
505 GetITK< itk::Image< float, 3 > >( );
507 w_filter->GetOutputData( "Skeleton" )->GetITK< TFASkeleton >( );
508 const auto& branches = sk->Get( );
510 ws.GetFilter( "seed" )->GetOutputData( "Output" )->
511 GetITK< TVerticesFA >( )->Get( )[ 0 ];
513 std::queue< TVertexFA > q;
514 // TODO: std::set< TVertexFA, TVertexCompareFA > marks;
518 auto sVertex = q.front( );
520 auto sIt = branches.find( sVertex );
522 if( marks.find( sVertex ) != marks.end( ) )
524 std::cout << "MARK!!!!! : " << sVertex << std::endl;
526 marks.insert( sVertex );
529 // End node... do nothing
530 if( sIt == branches.end( ) )
533 // Create source node
534 auto srcIt = vertexMap.find( sVertex );
535 if( srcIt == vertexMap.end( ) )
536 srcIt = vertexMap.insert(
537 VertexMap::value_type(
538 sVertex, FAVertexToNode( sVertex, input_image )
542 // TODO: std::cout << sVertex << " " << " " << sLevel << " " << seed0 << std::endl;
543 // Create destination nodes
544 for( auto eIt = sIt->second.begin( ); eIt != sIt->second.end( ); ++eIt )
546 auto dstIt = vertexMap.find( eIt->first );
547 if( dstIt == vertexMap.end( ) )
548 dstIt = vertexMap.insert(
549 VertexMap::value_type(
550 eIt->first, FAVertexToNode( eIt->first, input_image )
554 // Connect in the acyclic graph
555 dstIt->second->SetFather( srcIt->second );
556 srcIt->second->AddChild( dstIt->second );
558 // Create detailed edge
559 TEdgeAirways* edge = new Edge( );
560 edge->SetSource( srcIt->second );
561 edge->SetTarget( dstIt->second );
562 auto path = eIt->second->GetVertexList( );
563 for( unsigned int pIt = 0; pIt < path->Size( ); ++pIt )
565 itk::ImageBase< 3 >::PointType pnt;
566 auto cidx = path->GetElement( pIt );
567 input_image->TransformContinuousIndexToPhysicalPoint( cidx, pnt );
569 input_image->TransformPhysicalPointToIndex( pnt, idx );
570 Vec3 coords = FAVertexToNode( idx, input_image )->GetCoords( );
571 pair_posVox_rad skPair( coords, distance_map->GetPixel( idx ) );
572 edge->AddSkeletonPairInfo( skPair );
576 // Finish association
577 dstIt->second->SetEdge( edge );
579 // Put it as next candidate
580 q.push( eIt->first );
587 new AirwaysTree( input_image, NULL, vertexMap[ seed0 ], false );
589 std::cout << "Finished conversion. New AlfTree has weight: "<<tree->GetWeight()<<". Takes "<<(end-start)<<" s." << std::endl;
593 // -------------------------------------------------------------------------
594 AirwaysTree& CreateAirwaysTreeFromSegmentation(Vec3 seed, TInputImage* input_image, cpPlugins::Workspace& ws )
596 return( ConvertFilterToAirwaysTree( input_image, ws ) );
599 // -------------------------------------------------------------------------
600 vector<TreeInfo> ReadInputFile(const char* filename)
603 std::ifstream infile(filename);
605 std::string folderpath_allResults;
606 vector<TreeInfo> vectorInfo;
608 bool firstLine = false;
610 while (std::getline(infile, line))
612 // First line contains the output folder
613 std::istringstream iss(line);
616 if (!(iss >> folderpath_allResults))
618 std::cout << "no file" << std::endl;
623 // Other lines, not the first one, contain the information for the airways to be created
627 float point_trachea[3];
628 std::string filepath_airwayImage, name_pig, name_image;
629 if (!(iss >> point_trachea[0] >> point_trachea[1] >> point_trachea[2] >> filepath_airwayImage >> name_pig >> name_image))
631 std::cout << "There is no tree information in the file." << std::endl;
637 std::cout << "Point trachea:[" << point_trachea[0] << "," << point_trachea[1] << "," << point_trachea[2] << "]" << std::endl;
643 Vec3 seed(point_trachea[0], point_trachea[1], point_trachea[2]); //real coords seed
644 treeInfo.seed = seed;
645 // Create the outputs
646 treeInfo.folderpath_pigResults = folderpath_allResults + "/" + name_pig + "/";
647 treeInfo.pig_name = name_pig;
648 treeInfo.image_name = name_image;
651 treeInfo.image = ReadImage<TInputImage>(filepath_airwayImage);
653 // Execute first pipeline's part
654 std::stringstream seed_stream;
656 << point_trachea[0] << " "
657 << point_trachea[1] << " "
660 treeInfo.myWorkspace->SetInterface( &myPlugins );
661 std::string err = treeInfo.myWorkspace->LoadWorkspace( "./workspace_airwaysappli.wxml" );
664 std::cerr << "Error: " << err << std::endl;
668 treeInfo.myWorkspace->SetParameter( "FileNames@reader", filepath_airwayImage );
669 treeInfo.myWorkspace->SetParameter( "Text@seed", seed_stream.str( ) );
670 vectorInfo.push_back(treeInfo);
677 // -------------------------------------------------------------------------
678 void printCommonTreeBetweenTwoTrees(AirwaysTree tree_A, AirwaysTree tree_B, std::vector< std::pair< std::pair<Node*, Node*>, std::pair<Node*, Node*> > > vector_pair_edges_A_to_B, unsigned int Q, unsigned int F)
680 std::cout << "printCommonTreeBetweenTwoTrees, edges:" << vector_pair_edges_A_to_B.size() << std::endl;
682 // Vtk points, cell array, and colors
683 vtkSmartPointer<vtkPoints> points_common = vtkSmartPointer<vtkPoints>::New();
684 vtkSmartPointer<vtkCellArray> lines_common = vtkSmartPointer<vtkCellArray>::New();
685 vtkSmartPointer<vtkUnsignedCharArray> colors_common = vtkSmartPointer<vtkUnsignedCharArray>::New();
686 colors_common->SetNumberOfComponents(3);
687 colors_common->SetName("Colors");
689 // Add all the points
690 // 0 - 1000 points for tree A and from 1001 for tree B
691 points_common->SetNumberOfPoints(1000 + tree_B.GetWeight() + 100);
693 // Add points for tree A
694 vec_nodes vector_nodesA = tree_A.GetNodes();
695 for(vec_nodes::iterator it_nodesA = vector_nodesA.begin(); it_nodesA != vector_nodesA.end(); ++it_nodesA)
697 points_common->SetPoint((*it_nodesA)->GetId(),(*it_nodesA)->GetCoords().GetVec3());
700 // Add points for tree B
701 vec_nodes vector_nodesB = tree_B.GetNodes();
702 for(vec_nodes::iterator it_nodesB = vector_nodesB.begin(); it_nodesB != vector_nodesB.end(); ++it_nodesB)
704 points_common->SetPoint((*it_nodesB)->GetId()+1000,(*it_nodesB)->GetCoords().GetVec3());
707 // Add the edges for both trees
708 std::vector< std::pair< std::pair<Node*, Node*>, std::pair<Node*, Node*> > >::iterator it_edges = vector_pair_edges_A_to_B.begin();
709 int number_pairs = 0;
710 for(; it_edges != vector_pair_edges_A_to_B.end(); ++it_edges)
712 std::cout << "Pair:" << number_pairs << std::endl;
713 std::pair<Node*, Node*> edge_A = (*it_edges).first;
714 std::pair<Node*, Node*> edge_B = (*it_edges).second;
717 edge_A.first->GetPathToNode(edge_A.second, path_A);
720 edge_B.first->GetPathToNode(edge_B.second, path_B);
722 // Set color to be used
723 int numColor = number_pairs % 6;
724 unsigned char color[3];
734 else if(numColor == 2)
740 else if(numColor == 3)
742 color[0] = yellow[0];
743 color[1] = yellow[1];
744 color[2] = yellow[2];
746 else if(numColor == 4)
748 color[0] = purple[0];
749 color[1] = purple[1];
750 color[2] = purple[2];
752 else if(numColor == 5)
762 //if(path_A.size() > 0 && number_pairs < 50)
765 vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
766 lines_common->InsertNextCell(path_A.size());
768 for(vec_nodes::iterator it_pathA = path_A.begin(); it_pathA != path_A.end(); ++it_pathA)
770 lines_common->InsertCellPoint((*it_pathA)->GetId());
771 //line->GetPointIds()->SetId( id_point, (*it_pathA)->GetId() );
774 //lines_common->InsertNextCell(line);
775 colors_common->InsertNextTupleValue(color);
779 std::cout << "No path A" << std::endl;
784 //if(path_B.size() > 0 && number_pairs < 50)
787 vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
788 lines_common->InsertNextCell(path_B.size());
790 for(vec_nodes::iterator it_pathB = path_B.begin(); it_pathB != path_B.end(); ++it_pathB)
792 lines_common->InsertCellPoint((*it_pathB)->GetId()+1000);
793 //line->GetPointIds()->SetId( id_point, (*it_pathB)->GetId()+1000 );
796 //lines_common->InsertNextCell(line);
797 colors_common->InsertNextTupleValue(color);
801 std::cout << "No path B" << std::endl;
806 // Create the polydata
807 vtkSmartPointer<vtkPolyData> linesPolyData = vtkSmartPointer<vtkPolyData>::New();
809 // Set the points, lines, and colors
810 linesPolyData->SetPoints(points_common);
811 linesPolyData->SetLines(lines_common);
812 linesPolyData->GetCellData()->SetScalars(colors_common);
814 // ------------------------------------------------
815 // Write the vtk file
817 // Create the pathfile to save
818 std::stringstream filepath_actualIteration;
819 filepath_actualIteration << tree_A.GetResultPath() << "/" << tree_A.GetImageName() << "_" << tree_B.GetImageName() << "_Q_" << Q << "_F_" << F << ".vtk";
820 std::cout << "File to save:" << filepath_actualIteration.str() << std::endl;
823 vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
824 writer->SetFileName(filepath_actualIteration.str().c_str());
826 // Set input and write
827 #if VTK_MAJOR_VERSION <= 5
828 writer->SetInput(linesPolyData);
830 writer->SetInputData(linesPolyData);
836 // ***************************************
837 // Save the links in a file
840 // Create the outputfile
841 std::stringstream filepath_evaluation;
842 filepath_evaluation << tree_A.GetResultPath() << "/" << tree_A.GetImageName() << "_" << tree_B.GetImageName() << "_Q_" << Q << "_F_" << F << ".csv";
844 std::ofstream file(filepath_evaluation.str().c_str());
848 //file << "Node_" << tree_A.GetImageName() << " " << "Node_" << tree_B.GetImageName()<< "\n";
850 "idLocalN1 idLocalN2 "
851 "Node1x Node1y Node1z "
852 "Node2x Node2y Node2z "
854 "idMatch" << std::endl;
857 std::vector< std::pair< std::pair<Node*, Node*>, std::pair<Node*, Node*> > >::iterator it_edges = vector_pair_edges_A_to_B.begin();
858 for(; it_edges != vector_pair_edges_A_to_B.end(); ++it_edges)
861 std::pair<Node*, Node*> edge_A = (*it_edges).first;
862 std::pair<Node*, Node*> edge_B = (*it_edges).second;
864 //file << edge_A.second->GetId() << " " << edge_B.second->GetId()+1000 << "\n";
865 Vec3 coord_EndNodeA = edge_A.second->GetCoords();
866 Vec3 coord_EndNodeB = edge_B.second->GetCoords();
867 file << tree_A.GetImageName() << " " <<
868 edge_A.second->GetId() << " " << edge_B.second->GetId()+1000 << " " <<
869 coord_EndNodeA[0] << " " << coord_EndNodeA[1] << " " << coord_EndNodeA[2] << " " <<
870 coord_EndNodeB[0] << " " << coord_EndNodeB[1] << " " << coord_EndNodeB[2] << " " <<
871 tree_A.GetImageName() << coord_EndNodeA[0] << coord_EndNodeA[1] << coord_EndNodeA[2] << " " <<
872 tree_B.GetImageName() << coord_EndNodeB[0] << coord_EndNodeB[1] << coord_EndNodeB[2] <<"\n";
874 file << tree_B.GetImageName() << " " <<
875 edge_B.second->GetId()+1000 << " " << edge_A.second->GetId() << " " <<
876 coord_EndNodeB[0] << " " << coord_EndNodeB[1] << " " << coord_EndNodeB[2] << " " <<
877 coord_EndNodeA[0] << " " << coord_EndNodeA[1] << " " << coord_EndNodeA[2] << " " <<
878 tree_B.GetImageName() << coord_EndNodeB[0] << coord_EndNodeB[1] << coord_EndNodeB[2] << " " <<
879 tree_A.GetImageName() << coord_EndNodeA[0] << coord_EndNodeA[1] << coord_EndNodeA[2] << "\n";
885 // ***************************************
890 std::cout << "printCommonTreeBetweenTwoTrees ... OK" << std::endl;
893 // -------------------------------------------------------------------------
894 void printMatchingResultToFile(AirwaysTree tree_A, AirwaysTree tree_B, std::map< unsigned int, std::vector<Node*> > map_A_to_B, std::map< unsigned int, std::vector<Node*> > map_B_to_A, unsigned int Q, unsigned int F)
896 std::cout << "Printing matching result ... " << std::endl;
898 // Variables and types
899 typedef std::map< unsigned int, vec_nodes > map_id_node;
901 // Create the outputfile
902 std::stringstream filepath_evaluation;
903 filepath_evaluation << tree_A.GetResultPath() << "/" << tree_A.GetImageName() << "_" << tree_B.GetImageName() << "_Q_" << Q << "_F_" << F << "_matching.csv";
905 std::ofstream file(filepath_evaluation.str().c_str());
909 file << "TreeName idLocalN1 idLocalN2 "
910 "Node1x Node1y Node1z "
911 "Node2x Node2y Node2z "
914 "typeMatch_match_1_nonmatch_0 "
921 // Save the match or non-match for each node from A to B
922 for(int id_a=1; id_a <= tree_A.GetWeight( ); ++id_a)
924 // Get the actual node in tree A
925 Node* node_a = tree_A.GetNodeById( id_a );
926 Vec3 coords_a = node_a->GetCoords();
927 unsigned int depth_a = tree_A.GetDepthById(id_a);
928 bool leaf_a = node_a->IsLeaf();
930 // Check if the node was matched
931 map_id_node::iterator it_a2b = map_A_to_B.find( id_a );
932 if( it_a2b != map_A_to_B.end( ) )
934 // Get the correspoding matching nodes and print them
935 vec_nodes nodes_B = (*it_a2b).second;
937 vec_nodes::iterator it_nodes_b = nodes_B.begin( );
938 for( ; it_nodes_b != nodes_B.end( ); ++it_nodes_b)
940 Vec3 coords_b = (*it_nodes_b)->GetCoords();
942 file << tree_A.GetImageName() << " " << id_a << " " << (*it_nodes_b)->GetId()+1000 << " "
943 << coords_a[0] << " " << coords_a[1] << " " << coords_a[2] << " "
944 << coords_b[0] << " " << coords_b[1] << " " << coords_b[2] << " "
945 << tree_A.GetImageName() << coords_a[0] << coords_a[1] << coords_a[2] << " "
946 << tree_A.GetImageName() << coords_a[0] << coords_a[1] << coords_a[2] << coords_b[0] << coords_b[1] << coords_b[2] << " "
954 file << tree_A.GetImageName() << " " << id_a << " " << "0" << " "
955 << coords_a[0] << " " << coords_a[1] << " " << coords_a[2] << " "
956 << "0" << " " << "0" << " " << "0" << " "
957 << tree_A.GetImageName() << coords_a[0] << coords_a[1] << coords_a[2] << " "
958 << tree_A.GetImageName() << coords_a[0] << coords_a[1] << coords_a[2] << "0" << "0" << "0" << " "
968 // Save the match or non-match for each node from A to B
969 for(int id_b=1; id_b <= tree_B.GetWeight( ); ++id_b)
971 // Get the actual node in tree B
972 Node* node_b = tree_B.GetNodeById( id_b );
973 Vec3 coords_b = node_b->GetCoords();
974 unsigned int depth_b = tree_B.GetDepthById(id_b);
975 bool leaf_b = node_b->IsLeaf();
977 // Check if the node was matched
978 map_id_node::iterator it_b2a = map_B_to_A.find( id_b );
979 if( it_b2a != map_B_to_A.end( ) )
981 // Get the correspoding matching nodes and print them
982 vec_nodes nodes_A = (*it_b2a).second;
984 vec_nodes::iterator it_nodes_a = nodes_A.begin( );
985 for( ; it_nodes_a != nodes_A.end( ); ++it_nodes_a)
987 Vec3 coords_a = (*it_nodes_a)->GetCoords();
989 file << tree_B.GetImageName() << " " << id_b+1000 << " " << (*it_nodes_a)->GetId() << " "
990 << coords_b[0] << " " << coords_b[1] << " " << coords_b[2] << " "
991 << coords_a[0] << " " << coords_a[1] << " " << coords_a[2] << " "
992 << tree_B.GetImageName() << coords_b[0] << coords_b[1] << coords_b[2] << " "
993 << tree_B.GetImageName() << coords_b[0] << coords_b[1] << coords_b[2] << coords_a[0] << coords_a[1] << coords_a[2] << " "
1001 file << tree_B.GetImageName() << " " << id_b+1000 << " " << "0" << " "
1002 << coords_b[0] << " " << coords_b[1] << " " << coords_b[2] << " "
1003 << "0" << " " << "0" << " " << "0" << " "
1004 << tree_B.GetImageName() << coords_b[0] << coords_b[1] << coords_b[2] << " "
1005 << tree_B.GetImageName() << coords_b[0] << coords_b[1] << coords_b[2] << "0" << "0" << "0" << " "
1013 file.close(); // Close the file
1015 std::cout << "Printing matching result DONE" << std::endl;
1018 // -------------------------------------------------------------------------
1019 void createLinesAndPointsForVTK(const Node* node, vtkSmartPointer<vtkPoints>& pts,vtkSmartPointer<vtkCellArray>& lines, vtkSmartPointer<vtkUnsignedCharArray>& colors, bool common, bool isRoot)
1021 // Insert the actual point/node
1022 //vtkIdType id_father = idNonRoot;
1024 //id_father = pts->InsertNextPoint(node->GetCoords().GetVec3());
1025 vtkIdType id_father = node->GetId();
1027 pts->SetPoint(id_father,node->GetCoords().GetVec3());
1029 // Iterate over the children
1030 const vec_nodes children = node->GetChildren();
1031 for (vec_nodes::const_iterator it_child = children.begin(); it_child != children.end(); ++it_child)
1033 if (!(*it_child)->IsMarked() && common)
1036 //vtkIdType id_son = pts->InsertNextPoint((*it_child)->GetCoords().GetVec3());
1037 vtkIdType id_son = (*it_child)->GetId();
1038 pts->SetPoint(id_son,(*it_child)->GetCoords().GetVec3());
1040 // Set color to be used
1041 int numColor = (*it_child)->GetLevel() % 4;
1043 colors->InsertNextTupleValue(green);
1044 else if(numColor == 1)
1045 colors->InsertNextTupleValue(red);
1046 else if(numColor == 2)
1047 colors->InsertNextTupleValue(red);
1049 colors->InsertNextTupleValue(red);
1052 vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
1053 line->GetPointIds()->SetId(0, id_father);
1054 line->GetPointIds()->SetId(1, id_son);
1055 lines->InsertNextCell(line);
1057 createLinesAndPointsForVTK(*it_child, pts, lines, colors, common, false);