165 vtkInformationVector *
ttkNotUsed(outputVector),
171 const int numInputs = inputTrees.size();
173 = (not inputTrees[0]->GetBlock(0)->IsA(
"vtkUnstructuredGrid")
175 : (JoinSplitMixtureCoefficient != 0
176 and JoinSplitMixtureCoefficient != 1
180 setDataVisualization(numInputs, numInputs2);
182 std::vector<MergeTree<dataType>> intermediateMTrees(numInputs),
183 intermediateMTrees2(numInputs2), barycenters(NumberOfBarycenters),
184 barycenters2((numInputs2 != 0) * NumberOfBarycenters);
185 std::vector<FTMTree_MT *> intermediateTrees(numInputs),
186 intermediateTrees2(numInputs2);
188 bool const useSadMaxPairs = (JoinSplitMixtureCoefficient == 0);
190 = constructTrees<dataType>(inputTrees, intermediateMTrees, treesNodes,
191 treesArcs, treesSegmentation, useSadMaxPairs);
192 if(not IsPersistenceDiagram
193 or (JoinSplitMixtureCoefficient != 0
194 and JoinSplitMixtureCoefficient != 1)) {
195 auto &inputTrees2ToUse
196 = (not IsPersistenceDiagram ? inputTrees2 : inputTrees);
197 constructTrees<dataType>(inputTrees2ToUse, intermediateMTrees2, treesNodes2,
198 treesArcs2, treesSegmentation2, !useSadMaxPairs);
201 mergeTreeToFTMTree<dataType>(intermediateMTrees, intermediateTrees);
202 mergeTreeToFTMTree<dataType>(intermediateMTrees2, intermediateTrees2);
207 bool const AddNodes =
true;
213 BranchDecomposition =
true;
214 NormalizedWasserstein =
true;
216 }
else if(Backend == 1) {
217 BranchDecomposition =
false;
218 NormalizedWasserstein =
false;
220 ComputeBarycenter =
false;
222 if(IsPersistenceDiagram) {
223 BranchDecomposition =
true;
225 if(ComputeBarycenter) {
226 if(not BranchDecomposition)
227 printMsg(
"BranchDecomposition is set to true since the barycenter "
228 "computation is asked.");
229 BranchDecomposition =
true;
231 printMsg(
"KeepSubtree is set to false since the barycenter computation "
235 if(not BranchDecomposition) {
236 if(NormalizedWasserstein)
237 printMsg(
"NormalizedWasserstein is set to false since branch "
238 "decomposition is not asked.");
239 NormalizedWasserstein =
false;
241 EpsilonTree2 = EpsilonTree1;
242 Epsilon2Tree2 = Epsilon2Tree1;
243 Epsilon3Tree2 = Epsilon3Tree1;
244 printMsg(
"BranchDecomposition: " + std::to_string(BranchDecomposition));
245 printMsg(
"NormalizedWasserstein: " + std::to_string(NormalizedWasserstein));
246 printMsg(
"KeepSubtree: " + std::to_string(KeepSubtree));
249 if(not ComputeBarycenter) {
272 distance = mergeTreeDistance.
execute<dataType>(
273 intermediateMTrees[0], intermediateMTrees[1], outputMatching);
275 finalDistances = std::vector<double>{distance};
277 if(NumberOfBarycenters == 1) {
294 BarycenterSizeLimitPercent);
295 mergeTreeBarycenter.
setAlpha(Alpha);
299 Epsilon1UseFarthestSaddle);
304 mergeTreeBarycenter.
execute<dataType>(
305 intermediateMTrees, outputMatchingBarycenter[0], barycenters[0]);
326 BarycenterSizeLimitPercent);
330 Epsilon1UseFarthestSaddle);
336 mergeTreeClustering.template execute<dataType>(
337 intermediateMTrees, outputMatchingBarycenter, clusteringAssignment,
338 intermediateMTrees2, outputMatchingBarycenter2, barycenters,
346 mergeTreesTemplateToDouble<dataType>(intermediateMTrees, intermediateSTrees);
348 mergeTreesTemplateToDouble<dataType>(
349 intermediateMTrees2, intermediateSTrees2);
350 if(ComputeBarycenter) {
351 mergeTreesTemplateToDouble<dataType>(barycenters, barycentersS);
353 mergeTreesTemplateToDouble<dataType>(barycenters2, barycentersS2);
437 vtkInformationVector *outputVector,
440 std::vector<MergeTree<dataType>> intermediateMTrees, intermediateMTrees2;
441 mergeTreesDoubleToTemplate<dataType>(intermediateSTrees, intermediateMTrees);
442 mergeTreesDoubleToTemplate<dataType>(
443 intermediateSTrees2, intermediateMTrees2);
444 std::vector<FTMTree_MT *> intermediateTrees, intermediateTrees2;
445 mergeTreeToFTMTree<dataType>(intermediateMTrees, intermediateTrees);
446 mergeTreeToFTMTree<dataType>(intermediateMTrees2, intermediateTrees2);
448 std::vector<MergeTree<dataType>> barycenters, barycenters2;
449 if(ComputeBarycenter) {
450 mergeTreesDoubleToTemplate<dataType>(barycentersS, barycenters);
451 mergeTreesDoubleToTemplate<dataType>(barycentersS2, barycenters2);
454 const int numInputs = inputTrees.size();
455 const int numInputs2 = intermediateMTrees2.size();
459 Timer t_makeTreesOutput;
461 auto output_clusters = vtkMultiBlockDataSet::GetData(outputVector, 0);
462 auto output_centroids = vtkMultiBlockDataSet::GetData(outputVector, 1);
463 auto output_matchings = vtkMultiBlockDataSet::GetData(outputVector, 2);
466 std::vector<std::vector<SimplexId>> nodeCorr(numInputs),
467 nodeCorr2(numInputs2);
469 if(not ComputeBarycenter) {
474 FTMTree_MT *tree1 = intermediateTrees[0], *tree2 = intermediateTrees[1];
504 BranchDecompositionPlanarLayout);
524 visuMaker.
copyPointData(treesNodes[0], trees1NodeCorrMesh[0]);
528 if(IsPersistenceDiagram)
543 visuMaker.
copyPointData(treesNodes[1], trees1NodeCorrMesh[1]);
547 if(IsPersistenceDiagram)
557 vtkOutputNode1->GetFieldData()->ShallowCopy(
558 treesNodes[0]->GetFieldData());
559 vtkOutputNode2->GetFieldData()->ShallowCopy(
560 treesNodes[1]->GetFieldData());
561 if(not IsPersistenceDiagram) {
562 vtkOutputArc1->GetFieldData()->ShallowCopy(
563 treesArcs[0]->GetFieldData());
564 vtkOutputArc2->GetFieldData()->ShallowCopy(
565 treesArcs[1]->GetFieldData());
567 if(treesSegmentation[0])
568 addFieldData(treesSegmentation[0], vtkOutputNode1);
569 if(treesSegmentation[1])
570 addFieldData(treesSegmentation[1], vtkOutputNode2);
571 if(OutputSegmentation) {
572 vtkOutputSegmentation1->GetFieldData()->ShallowCopy(
573 treesSegmentation[0]->GetFieldData());
574 vtkOutputSegmentation2->GetFieldData()->ShallowCopy(
575 treesSegmentation[1]->GetFieldData());
579 if(IsPersistenceDiagram and not OutputSegmentation) {
580 output_clusters->SetNumberOfBlocks(2);
581 output_clusters->SetBlock(0, vtkOutputNode1);
582 output_clusters->SetBlock(1, vtkOutputNode2);
584 vtkBlockNodes->SetNumberOfBlocks(2);
585 vtkBlockNodes->SetBlock(0, vtkOutputNode1);
586 vtkBlockNodes->SetBlock(1, vtkOutputNode2);
588 if(not IsPersistenceDiagram) {
589 vtkBlockArcs->SetNumberOfBlocks(2);
590 vtkBlockArcs->SetBlock(0, vtkOutputArc1);
591 vtkBlockArcs->SetBlock(1, vtkOutputArc2);
594 output_clusters->SetNumberOfBlocks(1 + !IsPersistenceDiagram
595 + OutputSegmentation);
596 output_clusters->SetBlock(0, vtkBlockNodes);
597 if(not IsPersistenceDiagram)
598 output_clusters->SetBlock(1, vtkBlockArcs);
599 if(OutputSegmentation) {
600 vtkBlockSegs->SetNumberOfBlocks(2);
601 vtkBlockSegs->SetBlock(0, vtkOutputSegmentation1);
602 vtkBlockSegs->SetBlock(1, vtkOutputSegmentation2);
603 int const segBlockID = 1 + !IsPersistenceDiagram;
604 output_clusters->SetBlock(segBlockID, vtkBlockSegs);
627 vtkNew<vtkDoubleArray> vtkDistance{};
628 vtkDistance->SetName(
"Distance");
629 vtkDistance->SetNumberOfTuples(1);
630 vtkDistance->SetTuple1(0, finalDistances[0]);
631 vtkOutputMatching->GetFieldData()->AddArray(vtkDistance);
634 output_matchings->SetNumberOfBlocks(1);
635 output_matchings->SetBlock(0, vtkOutputMatching);
643 std::vector<std::vector<SimplexId>> nodeCorrBary(NumberOfBarycenters),
644 nodeCorrBary2((numInputs2 != 0) * NumberOfBarycenters);
645 std::vector<std::vector<float>> allBaryPercentMatch(NumberOfBarycenters),
646 allBaryPercentMatch2((numInputs2 != 0) * NumberOfBarycenters);
647 std::vector<FTMTree_MT *> barycentersTree, barycentersTree2;
648 mergeTreeToFTMTree<dataType>(barycenters, barycentersTree);
649 mergeTreeToFTMTree<dataType>(barycenters2, barycentersTree2);
654 if(IsPersistenceDiagram and not OutputSegmentation) {
655 output_clusters->SetNumberOfBlocks(numInputs);
657 output_clusters->SetNumberOfBlocks((OutputSegmentation ? 3 : 2));
660 vtkBlockNodes->SetNumberOfBlocks(numInputs);
661 output_clusters->SetBlock(0, vtkBlockNodes);
664 vtkBlockArcs->SetNumberOfBlocks(numInputs);
665 output_clusters->SetBlock(1, vtkBlockArcs);
666 if(OutputSegmentation) {
669 vtkBlockSegs->SetNumberOfBlocks(numInputs);
670 output_clusters->SetBlock(2, vtkBlockSegs);
673 for(
unsigned int c = 0; c < NumberOfBarycenters; ++c) {
674#ifdef TTK_ENABLE_OPENMP
675#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
677 for(
int i = 0; i < numInputs; ++i) {
678 if(clusteringAssignment[i] != (
int)c)
693 BranchDecompositionPlanarLayout);
709 visuMaker.
copyPointData(treesNodes[i], trees1NodeCorrMesh[i]);
713 if(IsPersistenceDiagram)
727 intermediateTrees, barycentersTree);
729 nodeCorr[i] = nodeCorrT[i];
730 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
731 and JoinSplitMixtureCoefficient != 1)
732 makeDoubleInputPersistenceDiagramOutput<dataType>(
733 visuMaker, vtkOutputNode, intermediateTrees2, barycentersTree2,
734 outputMatchingBarycenter2, trees2NodeCorrMesh, treesNodes[i], i,
738 vtkOutputNode->GetFieldData()->ShallowCopy(
739 treesNodes[i]->GetFieldData());
740 if(not IsPersistenceDiagram)
741 vtkOutputArc->GetFieldData()->ShallowCopy(
742 treesArcs[i]->GetFieldData());
743 if(treesSegmentation[i])
744 addFieldData(treesSegmentation[i], vtkOutputNode);
745 if(OutputSegmentation)
746 vtkOutputSegmentation->GetFieldData()->ShallowCopy(
747 treesSegmentation[i]->GetFieldData());
749 vtkNew<vtkDoubleArray> vtkClusterAssignment{};
750 vtkClusterAssignment->SetName(
"ClusterAssignment");
751 vtkClusterAssignment->SetNumberOfTuples(1);
752 vtkClusterAssignment->SetTuple1(0, clusteringAssignment[i]);
753 vtkOutputNode->GetFieldData()->AddArray(vtkClusterAssignment);
756 if(IsPersistenceDiagram and not OutputSegmentation) {
757 output_clusters->SetBlock(i, vtkOutputNode);
759 vtkMultiBlockDataSet::SafeDownCast(output_clusters->GetBlock(0))
760 ->SetBlock(i, vtkOutputNode);
761 if(not IsPersistenceDiagram)
762 vtkMultiBlockDataSet::SafeDownCast(output_clusters->GetBlock(1))
763 ->SetBlock(i, vtkOutputArc);
764 if(OutputSegmentation) {
765 int const segBlockID = 1 + !IsPersistenceDiagram;
766 vtkMultiBlockDataSet::SafeDownCast(
767 output_clusters->GetBlock(segBlockID))
768 ->SetBlock(i, vtkOutputSegmentation);
777 if(IsPersistenceDiagram) {
778 output_centroids->SetNumberOfBlocks(NumberOfBarycenters);
780 output_centroids->SetNumberOfBlocks(2);
783 vtkBlockNodes2->SetNumberOfBlocks(NumberOfBarycenters);
784 output_centroids->SetBlock(0, vtkBlockNodes2);
787 vtkBlockArcs2->SetNumberOfBlocks(NumberOfBarycenters);
788 output_centroids->SetBlock(1, vtkBlockArcs2);
790 for(
unsigned int c = 0; c < NumberOfBarycenters; ++c) {
804 BranchDecompositionPlanarLayout);
817 ExcludeImportantPairsHigher);
825 if(IsPersistenceDiagram)
834 if(numInputs == 2 and NumberOfBarycenters == 1) {
840 visuMakerBary.
setIsPDSadMax(JoinSplitMixtureCoefficient == 0);
843 intermediateTrees, barycentersTree);
845 nodeCorrBary[c] = nodeCorrBaryT[c];
847 allBaryPercentMatch[c] = allBaryPercentMatchT[c];
849 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
850 and JoinSplitMixtureCoefficient != 1) {
851 makeDoubleInputPersistenceDiagramOutput<dataType>(
852 visuMakerBary, vtkOutputNode, intermediateTrees2, barycentersTree2,
853 outputMatchingBarycenter2, trees2NodeCorrMesh,
nullptr, c,
856 allBaryPercentMatch2[c] = allBaryPercentMatchT[c];
860 vtkNew<vtkDoubleArray> vtkClusterAssignment{};
861 vtkClusterAssignment->SetName(
"ClusterAssignment");
862 vtkClusterAssignment->SetNumberOfTuples(1);
863 vtkClusterAssignment->SetTuple1(0, c);
864 vtkOutputNode->GetFieldData()->AddArray(vtkClusterAssignment);
867 if(IsPersistenceDiagram) {
868 output_centroids->SetBlock(c, vtkOutputNode);
870 vtkMultiBlockDataSet::SafeDownCast(output_centroids->GetBlock(0))
871 ->SetBlock(c, vtkOutputNode);
872 vtkMultiBlockDataSet::SafeDownCast(output_centroids->GetBlock(1))
873 ->SetBlock(c, vtkOutputArc);
880 output_matchings->SetNumberOfBlocks(numInputs);
881 for(
unsigned int c = 0; c < NumberOfBarycenters; ++c) {
882 for(
int i = 0; i < numInputs; ++i) {
883 if(clusteringAssignment[i] != (
int)c)
890 = vtkUnstructuredGrid::SafeDownCast(
891 (IsPersistenceDiagram and not OutputSegmentation
892 ? output_clusters->GetBlock(i)
893 : vtkMultiBlockDataSet::SafeDownCast(
894 output_clusters->GetBlock(0))
897 = vtkUnstructuredGrid::SafeDownCast(
898 (IsPersistenceDiagram ? output_centroids->GetBlock(c)
899 : vtkMultiBlockDataSet::SafeDownCast(
900 output_centroids->GetBlock(0))
907 outputMatchingBarycenter);
918 intermediateTrees, barycentersTree);
919 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
920 and JoinSplitMixtureCoefficient != 1)
921 makeDoubleInputPersistenceDiagramMatching<dataType>(
922 visuMakerMatching, vtkOutputMatching, intermediateTrees2,
923 barycentersTree2, outputMatchingBarycenter2, nodeCorr2,
924 nodeCorrBary2, allBaryPercentMatch2);
927 vtkNew<vtkDoubleArray> vtkDistance{};
928 vtkDistance->SetName(
"Distance");
929 vtkDistance->SetNumberOfTuples(1);
930 vtkDistance->SetTuple1(0, finalDistances[i]);
931 vtkOutputMatching->GetFieldData()->AddArray(vtkDistance);
934 output_matchings->SetBlock(i, vtkOutputMatching);
941 "Trees output", 1, t_makeTreesOutput.
getElapsedTime(), this->threadNumber_);