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 useSecondPairsType = (JoinSplitMixtureCoefficient == 0);
190 inputTrees, intermediateMTrees, treesNodes, treesArcs, treesSegmentation,
191 useSecondPairsType, DiagramPairTypes);
192 if(not IsPersistenceDiagram
193 or (JoinSplitMixtureCoefficient != 0
194 and JoinSplitMixtureCoefficient != 1)) {
195 auto &inputTrees2ToUse
196 = (not IsPersistenceDiagram ? inputTrees2 : inputTrees);
198 treesArcs2, treesSegmentation2,
199 !useSecondPairsType, DiagramPairTypes);
208 bool const AddNodes =
true;
214 BranchDecomposition =
true;
215 NormalizedWasserstein =
true;
217 }
else if(Backend == 1) {
218 BranchDecomposition =
false;
219 NormalizedWasserstein =
false;
221 ComputeBarycenter =
false;
223 if(IsPersistenceDiagram) {
224 BranchDecomposition =
true;
226 if(ComputeBarycenter) {
227 if(not BranchDecomposition)
228 printMsg(
"BranchDecomposition is set to true since the barycenter "
229 "computation is asked.");
230 BranchDecomposition =
true;
232 printMsg(
"KeepSubtree is set to false since the barycenter computation "
236 if(not BranchDecomposition) {
237 if(NormalizedWasserstein)
238 printMsg(
"NormalizedWasserstein is set to false since branch "
239 "decomposition is not asked.");
240 NormalizedWasserstein =
false;
242 EpsilonTree2 = EpsilonTree1;
243 Epsilon2Tree2 = Epsilon2Tree1;
244 Epsilon3Tree2 = Epsilon3Tree1;
245 printMsg(
"BranchDecomposition: " + std::to_string(BranchDecomposition));
246 printMsg(
"NormalizedWasserstein: " + std::to_string(NormalizedWasserstein));
247 printMsg(
"KeepSubtree: " + std::to_string(KeepSubtree));
250 if(not ComputeBarycenter) {
273 distance = mergeTreeDistance.
execute<dataType>(
274 intermediateMTrees[0], intermediateMTrees[1], outputMatching);
276 finalDistances = std::vector<double>{distance};
278 if(NumberOfBarycenters == 1) {
295 BarycenterSizeLimitPercent);
296 mergeTreeBarycenter.
setAlpha(Alpha);
300 Epsilon1UseFarthestSaddle);
305 mergeTreeBarycenter.
execute<dataType>(
306 intermediateMTrees, outputMatchingBarycenter[0], barycenters[0]);
327 BarycenterSizeLimitPercent);
331 Epsilon1UseFarthestSaddle);
337 mergeTreeClustering.template execute<dataType>(
338 intermediateMTrees, outputMatchingBarycenter, clusteringAssignment,
339 intermediateMTrees2, outputMatchingBarycenter2, barycenters,
350 intermediateMTrees2, intermediateSTrees2);
351 if(ComputeBarycenter) {
438 vtkInformationVector *outputVector,
441 std::vector<MergeTree<dataType>> intermediateMTrees, intermediateMTrees2;
444 intermediateSTrees2, intermediateMTrees2);
445 std::vector<FTMTree_MT *> intermediateTrees, intermediateTrees2;
449 std::vector<MergeTree<dataType>> barycenters, barycenters2;
450 if(ComputeBarycenter) {
455 const int numInputs = inputTrees.size();
456 const int numInputs2 = intermediateMTrees2.size();
460 Timer t_makeTreesOutput;
462 auto output_clusters = vtkMultiBlockDataSet::GetData(outputVector, 0);
463 auto output_centroids = vtkMultiBlockDataSet::GetData(outputVector, 1);
464 auto output_matchings = vtkMultiBlockDataSet::GetData(outputVector, 2);
467 std::vector<std::vector<SimplexId>> nodeCorr(numInputs),
468 nodeCorr2(numInputs2);
470 if(not ComputeBarycenter) {
475 FTMTree_MT *tree1 = intermediateTrees[0], *tree2 = intermediateTrees[1];
505 BranchDecompositionPlanarLayout);
525 visuMaker.
copyPointData(treesNodes[0], trees1NodeCorrMesh[0]);
529 if(IsPersistenceDiagram)
544 visuMaker.
copyPointData(treesNodes[1], trees1NodeCorrMesh[1]);
548 if(IsPersistenceDiagram)
558 vtkOutputNode1->GetFieldData()->ShallowCopy(
559 treesNodes[0]->GetFieldData());
560 vtkOutputNode2->GetFieldData()->ShallowCopy(
561 treesNodes[1]->GetFieldData());
562 if(not IsPersistenceDiagram) {
563 vtkOutputArc1->GetFieldData()->ShallowCopy(
564 treesArcs[0]->GetFieldData());
565 vtkOutputArc2->GetFieldData()->ShallowCopy(
566 treesArcs[1]->GetFieldData());
568 if(treesSegmentation[0])
569 addFieldData(treesSegmentation[0], vtkOutputNode1);
570 if(treesSegmentation[1])
571 addFieldData(treesSegmentation[1], vtkOutputNode2);
572 if(OutputSegmentation) {
573 vtkOutputSegmentation1->GetFieldData()->ShallowCopy(
574 treesSegmentation[0]->GetFieldData());
575 vtkOutputSegmentation2->GetFieldData()->ShallowCopy(
576 treesSegmentation[1]->GetFieldData());
580 if(IsPersistenceDiagram and not OutputSegmentation) {
581 output_clusters->SetNumberOfBlocks(2);
582 output_clusters->SetBlock(0, vtkOutputNode1);
583 output_clusters->SetBlock(1, vtkOutputNode2);
585 vtkBlockNodes->SetNumberOfBlocks(2);
586 vtkBlockNodes->SetBlock(0, vtkOutputNode1);
587 vtkBlockNodes->SetBlock(1, vtkOutputNode2);
589 if(not IsPersistenceDiagram) {
590 vtkBlockArcs->SetNumberOfBlocks(2);
591 vtkBlockArcs->SetBlock(0, vtkOutputArc1);
592 vtkBlockArcs->SetBlock(1, vtkOutputArc2);
595 output_clusters->SetNumberOfBlocks(1 + !IsPersistenceDiagram
596 + OutputSegmentation);
597 output_clusters->SetBlock(0, vtkBlockNodes);
598 if(not IsPersistenceDiagram)
599 output_clusters->SetBlock(1, vtkBlockArcs);
600 if(OutputSegmentation) {
601 vtkBlockSegs->SetNumberOfBlocks(2);
602 vtkBlockSegs->SetBlock(0, vtkOutputSegmentation1);
603 vtkBlockSegs->SetBlock(1, vtkOutputSegmentation2);
604 int const segBlockID = 1 + !IsPersistenceDiagram;
605 output_clusters->SetBlock(segBlockID, vtkBlockSegs);
628 vtkNew<vtkDoubleArray> vtkDistance{};
629 vtkDistance->SetName(
"Distance");
630 vtkDistance->SetNumberOfTuples(1);
631 vtkDistance->SetTuple1(0, finalDistances[0]);
632 vtkOutputMatching->GetFieldData()->AddArray(vtkDistance);
635 output_matchings->SetNumberOfBlocks(1);
636 output_matchings->SetBlock(0, vtkOutputMatching);
644 std::vector<std::vector<SimplexId>> nodeCorrBary(NumberOfBarycenters),
645 nodeCorrBary2((numInputs2 != 0) * NumberOfBarycenters);
646 std::vector<std::vector<float>> allBaryPercentMatch(NumberOfBarycenters),
647 allBaryPercentMatch2((numInputs2 != 0) * NumberOfBarycenters);
648 std::vector<FTMTree_MT *> barycentersTree, barycentersTree2;
655 if(IsPersistenceDiagram and not OutputSegmentation) {
656 output_clusters->SetNumberOfBlocks(numInputs);
658 output_clusters->SetNumberOfBlocks((OutputSegmentation ? 3 : 2));
661 vtkBlockNodes->SetNumberOfBlocks(numInputs);
662 output_clusters->SetBlock(0, vtkBlockNodes);
665 vtkBlockArcs->SetNumberOfBlocks(numInputs);
666 output_clusters->SetBlock(1, vtkBlockArcs);
667 if(OutputSegmentation) {
670 vtkBlockSegs->SetNumberOfBlocks(numInputs);
671 output_clusters->SetBlock(2, vtkBlockSegs);
674 for(
unsigned int c = 0; c < NumberOfBarycenters; ++c) {
675#ifdef TTK_ENABLE_OPENMP
676#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
678 for(
int i = 0; i < numInputs; ++i) {
679 if(clusteringAssignment[i] != (
int)c)
694 BranchDecompositionPlanarLayout);
710 visuMaker.
copyPointData(treesNodes[i], trees1NodeCorrMesh[i]);
714 if(IsPersistenceDiagram)
728 intermediateTrees, barycentersTree);
730 nodeCorr[i] = nodeCorrT[i];
731 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
732 and JoinSplitMixtureCoefficient != 1)
734 visuMaker, vtkOutputNode, intermediateTrees2, barycentersTree2,
735 outputMatchingBarycenter2, trees2NodeCorrMesh, treesNodes[i], i,
739 vtkOutputNode->GetFieldData()->ShallowCopy(
740 treesNodes[i]->GetFieldData());
741 if(not IsPersistenceDiagram)
742 vtkOutputArc->GetFieldData()->ShallowCopy(
743 treesArcs[i]->GetFieldData());
744 if(treesSegmentation[i])
745 addFieldData(treesSegmentation[i], vtkOutputNode);
746 if(OutputSegmentation)
747 vtkOutputSegmentation->GetFieldData()->ShallowCopy(
748 treesSegmentation[i]->GetFieldData());
750 vtkNew<vtkDoubleArray> vtkClusterAssignment{};
751 vtkClusterAssignment->SetName(
"ClusterAssignment");
752 vtkClusterAssignment->SetNumberOfTuples(1);
753 vtkClusterAssignment->SetTuple1(0, clusteringAssignment[i]);
754 vtkOutputNode->GetFieldData()->AddArray(vtkClusterAssignment);
757 if(IsPersistenceDiagram and not OutputSegmentation) {
758 output_clusters->SetBlock(i, vtkOutputNode);
760 vtkMultiBlockDataSet::SafeDownCast(output_clusters->GetBlock(0))
761 ->SetBlock(i, vtkOutputNode);
762 if(not IsPersistenceDiagram)
763 vtkMultiBlockDataSet::SafeDownCast(output_clusters->GetBlock(1))
764 ->SetBlock(i, vtkOutputArc);
765 if(OutputSegmentation) {
766 int const segBlockID = 1 + !IsPersistenceDiagram;
767 vtkMultiBlockDataSet::SafeDownCast(
768 output_clusters->GetBlock(segBlockID))
769 ->SetBlock(i, vtkOutputSegmentation);
778 if(IsPersistenceDiagram) {
779 output_centroids->SetNumberOfBlocks(NumberOfBarycenters);
781 output_centroids->SetNumberOfBlocks(2);
784 vtkBlockNodes2->SetNumberOfBlocks(NumberOfBarycenters);
785 output_centroids->SetBlock(0, vtkBlockNodes2);
788 vtkBlockArcs2->SetNumberOfBlocks(NumberOfBarycenters);
789 output_centroids->SetBlock(1, vtkBlockArcs2);
791 for(
unsigned int c = 0; c < NumberOfBarycenters; ++c) {
805 BranchDecompositionPlanarLayout);
818 ExcludeImportantPairsHigher);
826 if(IsPersistenceDiagram)
835 if(numInputs == 2 and NumberOfBarycenters == 1) {
841 visuMakerBary.
setIsPDSadMax(JoinSplitMixtureCoefficient == 0);
844 intermediateTrees, barycentersTree);
846 nodeCorrBary[c] = nodeCorrBaryT[c];
848 allBaryPercentMatch[c] = allBaryPercentMatchT[c];
850 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
851 and JoinSplitMixtureCoefficient != 1) {
853 visuMakerBary, vtkOutputNode, intermediateTrees2, barycentersTree2,
854 outputMatchingBarycenter2, trees2NodeCorrMesh,
nullptr, c,
857 allBaryPercentMatch2[c] = allBaryPercentMatchT[c];
861 vtkNew<vtkDoubleArray> vtkClusterAssignment{};
862 vtkClusterAssignment->SetName(
"ClusterAssignment");
863 vtkClusterAssignment->SetNumberOfTuples(1);
864 vtkClusterAssignment->SetTuple1(0, c);
865 vtkOutputNode->GetFieldData()->AddArray(vtkClusterAssignment);
868 if(IsPersistenceDiagram) {
869 output_centroids->SetBlock(c, vtkOutputNode);
871 vtkMultiBlockDataSet::SafeDownCast(output_centroids->GetBlock(0))
872 ->SetBlock(c, vtkOutputNode);
873 vtkMultiBlockDataSet::SafeDownCast(output_centroids->GetBlock(1))
874 ->SetBlock(c, vtkOutputArc);
881 output_matchings->SetNumberOfBlocks(numInputs);
882 for(
unsigned int c = 0; c < NumberOfBarycenters; ++c) {
883 for(
int i = 0; i < numInputs; ++i) {
884 if(clusteringAssignment[i] != (
int)c)
891 = vtkUnstructuredGrid::SafeDownCast(
892 (IsPersistenceDiagram and not OutputSegmentation
893 ? output_clusters->GetBlock(i)
894 : vtkMultiBlockDataSet::SafeDownCast(
895 output_clusters->GetBlock(0))
898 = vtkUnstructuredGrid::SafeDownCast(
899 (IsPersistenceDiagram ? output_centroids->GetBlock(c)
900 : vtkMultiBlockDataSet::SafeDownCast(
901 output_centroids->GetBlock(0))
908 outputMatchingBarycenter);
919 intermediateTrees, barycentersTree);
920 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
921 and JoinSplitMixtureCoefficient != 1)
923 visuMakerMatching, vtkOutputMatching, intermediateTrees2,
924 barycentersTree2, outputMatchingBarycenter2, nodeCorr2,
925 nodeCorrBary2, allBaryPercentMatch2);
928 vtkNew<vtkDoubleArray> vtkDistance{};
929 vtkDistance->SetName(
"Distance");
930 vtkDistance->SetNumberOfTuples(1);
931 vtkDistance->SetTuple1(0, finalDistances[i]);
932 vtkOutputMatching->GetFieldData()->AddArray(vtkDistance);
935 output_matchings->SetBlock(i, vtkOutputMatching);
942 "Trees output", 1, t_makeTreesOutput.
getElapsedTime(), this->threadNumber_);