16#include <vtkAppendFilter.h>
17#include <vtkCellData.h>
18#include <vtkDoubleArray.h>
19#include <vtkFloatArray.h>
20#include <vtkImageData.h>
21#include <vtkIntArray.h>
22#include <vtkPointData.h>
24#include <vtkStringArray.h>
25#include <vtkUnstructuredGrid.h>
35 bool PlanarLayout =
false;
36 double DimensionSpacing = 1.;
37 int DimensionToShift = 0;
38 bool OutputSegmentation =
false;
39 int MaximumImportantPairs = 0;
40 int MinimumImportantPairs = 0;
41 bool outputTreeNodeIndex =
false;
42 bool isPersistenceDiagram =
false;
43 bool convertedToDiagram =
false;
44 bool isPDSadMax =
true;
51 int iSampleOffset = 0;
52 int noSampleOffset = 0;
53 double prevXMaxOffset = 0;
57 int printClusterId = -1;
60 bool BarycenterPositionAlpha =
false;
64 std::vector<vtkUnstructuredGrid *> treesNodes;
65 std::vector<std::vector<int>>
69 std::vector<vtkDataSet *> treesSegmentation;
72 std::vector<int> clusteringAssignment;
73 std::vector<std::vector<std::vector<std::tuple<idNode, idNode, double>>>>
74 outputMatchingBarycenter;
77 std::vector<std::vector<float>> allBaryPercentMatch;
80 std::vector<bool> interpolatedTrees;
83 vtkUnstructuredGrid *vtkOutputNode{};
84 vtkUnstructuredGrid *vtkOutputArc{};
85 vtkDataSet *vtkOutputSegmentation{};
88 vtkUnstructuredGrid *vtkOutputNode1{}, *vtkOutputNode2{};
89 std::vector<std::vector<SimplexId>> nodeCorr1, nodeCorr2;
90 vtkUnstructuredGrid *vtkOutputMatching{};
93 std::vector<std::tuple<std::string, std::vector<double>>> customArrays;
94 std::vector<std::tuple<std::string, std::vector<int>>> customIntArrays;
95 std::vector<std::tuple<std::string, std::vector<std::string>>>
99 std::vector<std::vector<SimplexId>> nodeCorr;
100 std::vector<double> clusterShift;
117 DimensionSpacing = d;
120 DimensionToShift = i;
123 OutputSegmentation = b;
129 MaximumImportantPairs = maxPairs;
132 MinimumImportantPairs = minPairs;
136 outputTreeNodeIndex = doOutput;
140 isPersistenceDiagram = isPD;
143 convertedToDiagram = converted;
146 isPDSadMax = isSadMax;
151 iSampleOffset = offset;
154 noSampleOffset = offset;
157 prevXMaxOffset = offset;
170 BarycenterPositionAlpha = pos;
181 treesNodeCorrMesh = nodeCorrMesh;
185 treesNodes.emplace_back(nodes);
188 treesNodeCorrMesh.clear();
189 treesNodeCorrMesh.emplace_back(nodeCorrMesh);
194 treesSegmentation = segmentation;
197 treesSegmentation.clear();
198 treesSegmentation.emplace_back(segmentation);
203 clusteringAssignment = asgn;
206 std::vector<std::vector<std::vector<std::tuple<idNode, idNode, double>>>>
208 outputMatchingBarycenter = matching;
213 return allBaryPercentMatch;
217 allBaryPercentMatch = baryPercentMatch;
222 interpolatedTrees = isInterpolatedTrees;
227 vtkOutputNode = vtkNode;
230 vtkOutputArc = vtkArc;
233 vtkOutputSegmentation = vtkSegmentation;
238 vtkOutputNode1 = vtkNode1;
241 vtkOutputNode2 = vtkNode2;
244 nodeCorr1 = nodeCorrT;
247 nodeCorr2 = nodeCorrT;
250 vtkOutputMatching = vtkMatching;
253 std::vector<std::tuple<idNode, idNode, double>> &matching) {
254 outputMatchingBarycenter.resize(1);
255 outputMatchingBarycenter[0].resize(1);
256 outputMatchingBarycenter[0][0] = matching;
261 customArrays.emplace_back(name, vec);
264 customIntArrays.emplace_back(name, vec);
267 customStringArrays.emplace_back(name, vec);
270 customArrays.clear();
273 customIntArrays.clear();
276 customStringArrays.clear();
284 template <
class dataType>
286 std::vector<std::tuple<std::string, std::vector<dataType>>> &cArrays,
287 std::vector<std::vector<dataType>> &cArraysValues,
288 vtkUnstructuredGrid *vtkOutput,
291 for(
unsigned int i = 0; i < cArrays.size(); ++i) {
292 vtkNew<vtkDoubleArray> customDoubleArrayVtk;
293 vtkNew<vtkIntArray> customIntArrayVtk;
294 vtkNew<vtkStringArray> customStringArrayVtk;
295 vtkAbstractArray *customArrayVtk;
297 customArrayVtk = customDoubleArrayVtk;
299 customArrayVtk = customIntArrayVtk;
301 customArrayVtk = customStringArrayVtk;
302 customArrayVtk->SetName(std::get<0>(cArrays[i]).c_str());
303 customArrayVtk->SetNumberOfTuples(cArraysValues[i].size());
304 for(
unsigned int j = 0; j < cArraysValues[i].size(); ++j) {
307 double doubleValue = (*(std::vector<double> *)&(cArraysValues[i]))[j];
308 customDoubleArrayVtk->SetValue(j, doubleValue);
309 }
else if(type == 1) {
310 int intValue = (*(std::vector<int> *)&(cArraysValues[i]))[j];
311 customIntArrayVtk->SetValue(j, intValue);
313 std::string stringValue
314 = (*(std::vector<std::string> *)&(cArraysValues[i]))[j];
315 customStringArrayVtk->SetValue(j, stringValue);
319 vtkOutput->GetPointData()->AddArray(customArrayVtk);
321 vtkOutput->GetCellData()->AddArray(customArrayVtk);
326 std::vector<int> &treeNodeIdRev) {
327 double valueRange[2];
328 treeNodeIdArray->GetRange(valueRange);
329 int maxValue = valueRange[1];
330 treeNodeIdRev.clear();
331 treeNodeIdRev.resize(maxValue + 1);
332 for(
int i = 0; i < treeNodeIdArray->GetNumberOfValues(); ++i)
333 treeNodeIdRev[treeNodeIdArray->GetTuple1(i)] = i;
337 std::vector<int> &nodeCorrT) {
341 auto treeNodeIdArray = treeNodes->GetPointData()->GetArray(
"TreeNodeId");
342 std::vector<int> treeNodeIdRev;
346 for(
int i = 0; i < treeNodes->GetPointData()->GetNumberOfArrays(); ++i) {
348 = vtkDataArray::SafeDownCast(treeNodes->GetPointData()->GetArray(i));
350 = vtkStringArray::SafeDownCast(treeNodes->GetPointData()->GetArray(i));
351 vtkAbstractArray *array;
358 auto vecSize = (nodeCorrT.size() == 0 ? array->GetNumberOfValues()
360 std::vector<double> vec(vecSize);
361 std::vector<std::string> vecString(vecSize);
362 for(
unsigned int j = 0; j < vec.size(); ++j) {
363 int toGet = (nodeCorrT.size() == 0 ? j : nodeCorrT[j]);
365 toGet = (nodeCorrT.size() == 0 ? treeNodeIdRev[j]
366 : treeNodeIdRev[nodeCorrT[j]]);
367 auto value = array->GetVariantValue(toGet);
369 vec[j] = value.ToDouble();
371 vecString[j] = value.ToString();
373 std::string name{array->GetName()};
381 std::vector<int> nodeCorrT;
399 template <
class dataType>
401 std::vector<FTMTree_MT *> trees{tree1, tree2};
402 std::vector<FTMTree_MT *> barycenters;
404 makeMatchingOutput<dataType>(trees, barycenters);
407 template <
class dataType>
409 std::vector<FTMTree_MT *> &barycenters) {
410 int numInputs = trees.size();
411 int NumberOfBarycenters = barycenters.size();
412 bool clusteringOutput = (NumberOfBarycenters != 0);
414 = std::max(NumberOfBarycenters, 1);
415 if(not clusteringOutput)
418 vtkNew<vtkUnstructuredGrid> vtkMatching{};
419 vtkNew<vtkPoints> pointsM{};
422 vtkNew<vtkIntArray> matchingID{};
423 matchingID->SetName(
"MatchingID");
424 vtkNew<vtkIntArray> matchingType{};
425 matchingType->SetName(
"MatchingType");
426 vtkNew<vtkDoubleArray> matchPers{};
427 matchPers->SetName(
"MeanMatchedPersistence");
428 vtkNew<vtkDoubleArray> costArray{};
429 costArray->SetName(
"Cost");
430 vtkNew<vtkIntArray> tree1NodeIdField{};
431 tree1NodeIdField->SetName(
"tree1NodeId");
432 vtkNew<vtkIntArray> tree2NodeIdField{};
433 tree2NodeIdField->SetName(
"tree2NodeId");
435 vtkNew<vtkFloatArray> matchingPercentMatch{};
436 matchingPercentMatch->SetName(
"MatchingPercentMatch");
442 for(
int c = 0; c < NumberOfBarycenters; ++c) {
443 for(
int i = 0; i < numInputs; ++i) {
444 if((printTreeId == -1 and printClusterId != -1 and c != printClusterId)
445 or (printTreeId != -1 and printClusterId == -1 and i != printTreeId)
446 or (printTreeId != -1 and printClusterId != -1
447 and (c != printClusterId or i != printTreeId)))
449 for(std::tuple<idNode, idNode, double> match :
450 outputMatchingBarycenter[c][i]) {
451 vtkIdType pointIds[2];
452 idNode tree1NodeId = std::get<0>(match);
453 idNode tree2NodeId = std::get<1>(match);
454 double cost = std::get<2>(match);
457 if(not clusteringOutput) {
461 tree1 = barycenters[c];
465 SimplexId pointToGet1 = clusteringOutput ? nodeCorr2[c][tree1NodeId]
466 : nodeCorr1[0][tree1NodeId];
467 double *point1 = vtkOutputNode2->GetPoints()->GetPoint(pointToGet1);
468 const SimplexId nextPointId1 = pointsM->InsertNextPoint(point1);
469 pointIds[0] = nextPointId1;
473 SimplexId pointToGet2 = clusteringOutput ? nodeCorr1[i][tree2NodeId]
474 : nodeCorr1[1][tree2NodeId];
475 double *point2 = vtkOutputNode1->GetPoints()->GetPoint(pointToGet2);
476 const SimplexId nextPointId2 = pointsM->InsertNextPoint(point2);
477 pointIds[1] = nextPointId2;
481 vtkMatching->InsertNextCell(VTK_LINE, 2, pointIds);
486 if(allBaryPercentMatch.size() != 0)
487 matchingPercentMatch->InsertNextTuple1(
488 allBaryPercentMatch[c][tree1NodeId]);
493 tree1NodeIdField->InsertNextTuple1(pointToGet1);
494 tree2NodeIdField->InsertNextTuple1(pointToGet2);
497 matchingID->InsertNextTuple1(count);
510 if(tree1NodeDown != 0 and tree1NodeUp != 0 and tree2NodeDown != 0
511 and tree2NodeUp != 0)
513 if(tree1NodeDown == 0 and tree1NodeUp != 0 and tree2NodeDown == 0
514 and tree2NodeUp != 0)
516 if(tree1NodeDown != 0 and tree1NodeUp == 0 and tree2NodeDown != 0
517 and tree2NodeUp == 0)
519 matchingType->InsertNextTuple1(thisType);
526 double meanPersistence = (tree1Pers + tree2Pers) / 2;
527 matchPers->InsertNextTuple1(meanPersistence);
530 costArray->InsertNextTuple1(cost);
536 vtkMatching->SetPoints(pointsM);
537 vtkMatching->GetCellData()->AddArray(matchingType);
538 vtkMatching->GetCellData()->AddArray(matchPers);
539 vtkMatching->GetCellData()->AddArray(matchingID);
540 vtkMatching->GetCellData()->AddArray(costArray);
541 vtkMatching->GetCellData()->AddArray(tree1NodeIdField);
542 vtkMatching->GetCellData()->AddArray(tree2NodeIdField);
543 if(allBaryPercentMatch.size() != 0)
544 vtkMatching->GetCellData()->AddArray(matchingPercentMatch);
545 vtkOutputMatching->ShallowCopy(vtkMatching);
551 template <
class dataType>
553 std::vector<FTMTree_MT *> trees{tree1};
555 makeTreesOutput<dataType>(trees);
558 template <
class dataType>
560 std::vector<FTMTree_MT *> trees{tree1, tree2};
562 makeTreesOutput<dataType>(trees);
565 template <
class dataType>
567 std::vector<FTMTree_MT *> barycenters;
568 clusteringAssignment.clear();
569 clusteringAssignment.resize(trees.size(), 0);
571 makeTreesOutput<dataType>(trees, barycenters);
574 template <
class dataType>
576 std::vector<FTMTree_MT *> &barycenters) {
577 int numInputs = trees.size();
578 int numInputsOri = numInputs;
579 int NumberOfBarycenters = barycenters.size();
580 bool clusteringOutput = (NumberOfBarycenters != 0);
582 = std::max(NumberOfBarycenters, 1);
583 bool embeddedDiagram = not PlanarLayout and isPersistenceDiagram;
586 for(
int i = 0; i < numInputs; ++i) {
587 if(i < (
int)treesNodes.size() and treesNodes[i]) {
589 = treesNodes[i]->GetPointData()->GetArray(
"TreeNodeId");
590 if(treeNodeIdArray) {
591 std::vector<int> treeNodeIdRev;
593 for(
unsigned int j = 0; j < treesNodeCorrMesh[i].size(); ++j)
594 treesNodeCorrMesh[i][j] = treeNodeIdRev[treesNodeCorrMesh[i][j]];
601 std::vector<std::tuple<double, double, double, double, double, double>>
602 allBounds(numInputs);
603 for(
int i = 0; i < numInputs; ++i) {
604 if(OutputSegmentation and treesSegmentation[i]) {
605 double *tBounds = treesSegmentation[i]->GetBounds();
606 allBounds[i] = std::make_tuple(tBounds[0], tBounds[1], tBounds[2],
607 tBounds[3], tBounds[4], tBounds[5]);
608 }
else if(treesNodes.size() != 0 and treesNodes[i] !=
nullptr) {
609 if(not isPersistenceDiagram)
611 =
getRealBounds(treesNodes[i], trees[i], treesNodeCorrMesh[i]);
614 treesNodes[i]->GetBounds(bounds);
615 allBounds[i] = std::make_tuple(
616 bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
619 allBounds[i] = allBounds[0];
623 std::vector<std::tuple<double, double, double, double, double, double>>
624 allBaryBounds(barycenters.size());
625 std::vector<std::vector<idNode>> allBaryBranching(barycenters.size());
626 std::vector<std::vector<int>> allBaryBranchingID(barycenters.size());
627 for(
size_t c = 0; c < barycenters.size(); ++c) {
629 if(not isPersistenceDiagram)
630 barycenters[c]->getTreeBranching(
631 allBaryBranching[c], allBaryBranchingID[c]);
633 if(not clusteringOutput)
634 allBaryBounds.emplace_back(
641 std::vector<FTMTree_MT *> treesOri(trees);
644 clusteringAssignment.clear();
645 for(
unsigned int j = 0; j < barycenters.size(); ++j) {
646 trees.emplace_back(barycenters[j]);
647 clusteringAssignment.emplace_back(j);
649 numInputs = trees.size();
652 vtkNew<vtkUnstructuredGrid> vtkArcs{};
653 vtkNew<vtkPoints> points{};
656 vtkNew<vtkIntArray> criticalType{};
658 vtkNew<vtkFloatArray> persistenceNode{};
659 persistenceNode->SetName(
"Persistence");
660 vtkNew<vtkIntArray> clusterIDNode{};
661 clusterIDNode->SetName(
"ClusterID");
662 vtkNew<vtkIntArray> isDummyNode{};
663 isDummyNode->SetName(
"isDummyNode");
664 vtkNew<vtkIntArray> branchNodeID{};
665 branchNodeID->SetName(
"BranchNodeID");
666 vtkNew<vtkFloatArray> scalar{};
667 scalar->SetName(
"Scalar");
668 vtkNew<vtkIntArray> isImportantPairsNode{};
669 isImportantPairsNode->SetName(
"isImportantPair");
670 vtkNew<vtkIntArray> nodeID{};
671 nodeID->SetName(
"NodeId");
672 vtkNew<vtkIntArray> trueNodeID{};
673 trueNodeID->SetName(
"TrueNodeId");
674 vtkNew<vtkIntArray> vertexID{};
678 vtkNew<vtkIntArray> treeIDNode{};
679 treeIDNode->SetName(
"TreeID");
680 vtkNew<vtkIntArray> branchBaryNodeID{};
681 branchBaryNodeID->SetName(
"BranchBaryNodeID");
682 vtkNew<vtkIntArray> isInterpolatedTreeNode{};
683 isInterpolatedTreeNode->SetName(
"isInterpolatedTree");
685 vtkNew<vtkFloatArray> percentMatch{};
686 percentMatch->SetName(
"PercentMatchNode");
687 vtkNew<vtkFloatArray> persistenceBaryNode{};
688 persistenceBaryNode->SetName(
"PersistenceBarycenter");
689 vtkNew<vtkIntArray> persistenceBaryOrderNode{};
690 persistenceBaryOrderNode->SetName(
"PersistenceBarycenterOrder");
692 vtkNew<vtkDoubleArray> pairPersistenceNode{};
694 vtkNew<vtkDoubleArray> pairBirthNode{};
697 vtkNew<vtkFloatArray> treeNodeId{};
698 treeNodeId->SetName(
"TreeNodeId");
700 vtkNew<vtkFloatArray> treeNodeIdOrigin{};
701 treeNodeIdOrigin->SetName(
"TreeNodeIdOrigin");
702 vtkNew<vtkDoubleArray> coordinates{};
704 coordinates->SetNumberOfComponents(3);
706 vtkNew<vtkIntArray> isMultiPersPairNode{};
707 isMultiPersPairNode->SetName(
"isMultiPersPairNode");
709 std::vector<std::vector<double>> customArraysValues(customArrays.size());
710 std::vector<std::vector<int>> customIntArraysValues(customIntArrays.size());
711 std::vector<std::vector<std::string>> customStringArraysValues(
712 customStringArrays.size());
715 vtkNew<vtkFloatArray> persistenceArc{};
716 persistenceArc->SetName(
"Persistence");
717 vtkNew<vtkIntArray> clusterIDArc{};
718 clusterIDArc->SetName(
"ClusterID");
719 vtkNew<vtkIntArray> isImportantPairsArc{};
720 isImportantPairsArc->SetName(
"isImportantPair");
721 vtkNew<vtkIntArray> isDummyArc{};
722 isDummyArc->SetName(
"isDummyArc");
723 vtkNew<vtkIntArray> branchID{};
724 branchID->SetName(
"BranchID");
725 vtkNew<vtkIntArray> upNodeId{};
726 upNodeId->SetName(
"upNodeId");
727 vtkNew<vtkIntArray> downNodeId{};
728 downNodeId->SetName(
"downNodeId");
730 vtkNew<vtkIntArray> treeIDArc{};
731 treeIDArc->SetName((isPersistenceDiagram ?
"DiagramID" :
"TreeID"));
732 vtkNew<vtkIntArray> branchBaryID{};
733 branchBaryID->SetName(
"BranchBaryNodeID");
734 vtkNew<vtkIntArray> isInterpolatedTreeArc{};
735 isInterpolatedTreeArc->SetName(
"isInterpolatedTree");
737 vtkNew<vtkFloatArray> percentMatchArc{};
738 percentMatchArc->SetName(
"PercentMatchArc");
739 vtkNew<vtkFloatArray> persistenceBaryArc{};
740 persistenceBaryArc->SetName(
"PersistenceBarycenter");
741 vtkNew<vtkIntArray> persistenceBaryOrderArc{};
742 persistenceBaryOrderArc->SetName(
"PersistenceBarycenterOrder");
744 vtkNew<vtkIntArray> pairIdentifier{};
746 vtkNew<vtkIntArray> pairType{};
748 vtkNew<vtkIntArray> pairIsFinite{};
750 vtkNew<vtkDoubleArray> pairPersistence{};
752 vtkNew<vtkDoubleArray> pairBirth{};
755 vtkNew<vtkIntArray> isMultiPersPairArc{};
756 isMultiPersPairArc->SetName(
"isMultiPersPairArc");
758 std::vector<std::vector<double>> customCellArraysValues(
759 customArrays.size());
760 std::vector<std::vector<int>> customCellIntArraysValues(
761 customIntArrays.size());
762 std::vector<std::vector<std::string>> customCellStringArraysValues(
763 customStringArrays.size());
766 vtkNew<vtkAppendFilter> appendFilter{};
771 bool foundOneInterpolatedTree =
false;
773 nodeCorr.resize(numInputs);
774 clusterShift.clear();
775 clusterShift.resize(NumberOfBarycenters, 0);
776 allBaryPercentMatch.clear();
777 allBaryPercentMatch.resize(NumberOfBarycenters);
784 for(
int c = 0; c < NumberOfBarycenters; ++c) {
787 std::vector<int> baryPersistenceOrder;
788 if(clusteringOutput and ShiftMode != 1) {
789 baryPersistenceOrder.resize(barycenters[c]->getNumberOfNodes(), -1);
790 std::vector<std::tuple<ttk::ftm::idNode, ttk::ftm::idNode, dataType>>
792 barycenters[c]->getPersistencePairsFromTree<dataType>(pairsBary,
false);
793 for(
unsigned int j = 0; j < pairsBary.size(); ++j) {
794 int index = pairsBary.size() - 1 - j;
795 baryPersistenceOrder[std::get<0>(pairsBary[j])] = index;
796 baryPersistenceOrder[std::get<1>(pairsBary[j])] = index;
802 double delta_max = 1.0;
803 int noSample = 0 + noSampleOffset;
804 for(
int i = 0; i < numInputsOri; ++i) {
805 delta_max = std::max(
806 (std::get<3>(allBounds[i]) - std::get<2>(allBounds[i])), delta_max);
807 delta_max = std::max(
808 (std::get<1>(allBounds[i]) - std::get<0>(allBounds[i])), delta_max);
809 if(clusteringAssignment[i] != c)
813 double radius = delta_max * 2 * DimensionSpacing;
814 int iSample = 0 + iSampleOffset - 1;
816 if(c < NumberOfBarycenters - 1)
817 clusterShift[c + 1] = radius * 4 + clusterShift[c];
820 prevXMax = 0 + prevXMaxOffset;
821 std::vector<double> allPrevXMax;
822 double prevYMax = std::numeric_limits<double>::lowest();
827 printMsg(
"Iterate through all trees of this cluster",
829 for(
int i = 0; i < numInputs; ++i) {
830 if(clusteringAssignment[i] != c)
835 if((printTreeId == -1 and printClusterId != -1 and c != printClusterId)
836 or (printTreeId != -1 and printClusterId == -1 and i != printTreeId)
837 or (printTreeId != -1 and printClusterId != -1
838 and (c != printClusterId or i != printTreeId)))
843 if(MaximumImportantPairs > 0 or MinimumImportantPairs > 0) {
844 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
845 trees[i]->getPersistencePairsFromTree(pairs,
false);
846 if(MaximumImportantPairs > 0) {
847 int firstIndex = pairs.size() - MaximumImportantPairs;
849 = std::max(std::min(firstIndex,
int(pairs.size()) - 1), 0);
850 double tempThreshold = 0.999 * std::get<2>(pairs[firstIndex])
851 / std::get<2>(pairs[pairs.size() - 1]);
852 tempThreshold *= 100;
855 if(MinimumImportantPairs > 0) {
856 int firstIndex = pairs.size() - MinimumImportantPairs;
858 = std::max(std::min(firstIndex,
int(pairs.size()) - 1), 0);
859 double tempThreshold = 0.999 * std::get<2>(pairs[firstIndex])
860 / std::get<2>(pairs[pairs.size() - 1]);
861 tempThreshold *= 100;
867 bool isInterpolatedTree =
false;
868 if(interpolatedTrees.size() != 0)
869 isInterpolatedTree = interpolatedTrees[i];
870 foundOneInterpolatedTree |= isInterpolatedTree;
874 std::vector<idNode> treeBranching;
875 std::vector<int> treeBranchingID;
876 if(not isPersistenceDiagram)
877 trees[i]->getTreeBranching(treeBranching, treeBranchingID);
881 double angle = 360.0 / noSample * iSample;
883 double diff_x = 0, diff_y = 0;
885 = BarycenterPositionAlpha ? (-radius + 2 * radius * Alpha) * -1 : 0;
893 = -1 * radius * std::cos(-1 * angle * pi / 180) + clusterShift[c];
894 diff_y = -1 * radius * std::sin(-1 * angle * pi / 180);
897 diff_x = clusterShift[c] + alphaShift;
901 diff_x = prevXMax + radius;
904 diff_x = prevXMax + radius;
905 if(i >= numInputs / 2) {
906 diff_y = -(prevYMax + radius / 2);
907 diff_x = allPrevXMax[i - int(numInputs / 2)] + radius;
909 allPrevXMax.emplace_back(prevXMax);
917 double diff_z = PlanarLayout ? 0 : -std::get<4>(allBounds[i]);
920 if(DimensionToShift != 0) {
921 if(DimensionToShift == 2)
923 else if(DimensionToShift == 1)
925 diff_x = -std::get<0>(allBounds[i]);
930 std::vector<float> layout;
932 double refPersistence;
934 refPersistence = barycenters[0]->getNodePersistence<dataType>(
935 barycenters[0]->getRoot());
938 = trees[0]->getNodePersistence<dataType>(trees[0]->getRoot());
939 if(not isPersistenceDiagram)
940 treePlanarLayout<dataType>(
941 trees[i], allBaryBounds[c], refPersistence, layout);
943 persistenceDiagramPlanarLayout<dataType>(trees[i], layout);
950 nodeCorr[i].resize(trees[i]->getNumberOfNodes());
951 std::vector<SimplexId> treeSimplexId(trees[i]->getNumberOfNodes());
952 std::vector<SimplexId> treeDummySimplexId(trees[i]->getNumberOfNodes());
953 std::vector<SimplexId> layoutCorr(trees[i]->getNumberOfNodes());
954 std::vector<idNode> treeMatching(trees[i]->getNumberOfNodes(), -1);
955 if(clusteringOutput and ShiftMode != 1)
956 for(
auto match : outputMatchingBarycenter[c][i])
957 treeMatching[std::get<1>(match)] = std::get<0>(match);
960 std::vector<std::vector<idNode>> baryMatching(
961 trees[i]->getNumberOfNodes(),
963 numInputsOri, std::numeric_limits<idNode>::max()));
965 for(
size_t j = 0; j < outputMatchingBarycenter[c].size(); ++j)
966 for(
auto match : outputMatchingBarycenter[c][j])
967 baryMatching[std::get<0>(match)][j] = std::get<1>(match);
968 allBaryPercentMatch[c].resize(trees[i]->getNumberOfNodes(), 100.0);
970 double minBirth = std::numeric_limits<double>::max(),
971 maxBirth = std::numeric_limits<double>::lowest();
972 SimplexId minBirthNode = 0, maxBirthNode = 0;
978 std::queue<idNode> queue;
979 queue.emplace(trees[i]->getRoot());
980 while(!queue.empty()) {
981 idNode node = queue.front();
983 idNode nodeOrigin = trees[i]->getNode(node)->getOrigin();
988 std::vector<idNode> children;
989 trees[i]->getChildren(node, children);
990 for(
auto child : children)
991 queue.emplace(child);
997 = [&](vtkUnstructuredGrid *vtu,
int pointID, double(&point)[3]) {
1000 if(not isPersistenceDiagram or convertedToDiagram) {
1001 double *pointTemp = vtu->GetPoints()->GetPoint(pointID);
1002 for(
int k = 0; k < 3; ++k)
1003 point[k] += pointTemp[k];
1005 for(
int k = 0; k < 3; ++k) {
1006 auto array = vtu->GetPointData()->GetArray(
1009 point[k] += array->GetComponent(pointID, k);
1016 int nodeMeshTreeIndex = -1;
1017 double noMatched = 0.0;
1018 double point[3] = {0, 0, 0};
1019 if(ShiftMode == 1) {
1020 for(
int j = 0; j < numInputsOri; ++j) {
1021 if(baryMatching[node][j] != std::numeric_limits<idNode>::max()) {
1022 nodeMesh = treesNodeCorrMesh[j][baryMatching[node][j]];
1023 if(not PlanarLayout)
1024 getPoint(treesNodes[j], nodeMesh, point);
1026 nodeMeshTreeIndex = j;
1029 for(
int k = 0; k < 3; ++k)
1030 point[k] /= noMatched;
1031 }
else if(not isInterpolatedTree and treesNodes.size() != 0
1032 and treesNodes[i] !=
nullptr) {
1033 nodeMesh = treesNodeCorrMesh[i][node];
1034 if(not PlanarLayout)
1035 getPoint(treesNodes[i], nodeMesh, point);
1038 layoutCorr[node] = cptNode;
1039 point[0] = layout[cptNode];
1040 point[1] = layout[cptNode + 1];
1049 if(ShiftMode == 1) {
1050 float percentMatchT = noMatched * 100 / numInputs;
1051 allBaryPercentMatch[c][node] = percentMatchT;
1055 prevXMax = std::max(prevXMax, point[0]);
1056 if(ShiftMode == 3) {
1057 if(i < numInputs / 2)
1058 prevYMax = std::max(prevYMax, point[1]);
1059 if(i ==
int(numInputs / 2) - 1)
1066 and (!trees[i]->isRoot(node) or isPersistenceDiagram);
1067 dummyNode = dummyNode or embeddedDiagram;
1069 double pointToAdd[3] = {0, 0, 0};
1070 if(embeddedDiagram) {
1071 if(i < (
int)treesNodes.size()
1072 and i < (
int)treesNodeCorrMesh.size()
1073 and nodeOrigin < treesNodeCorrMesh[i].size())
1075 treesNodes[i], treesNodeCorrMesh[i][nodeOrigin], pointToAdd);
1077 if(not isPersistenceDiagram) {
1080 std::begin(point), std::end(point), std::begin(pointToAdd));
1082 double pdPoint[3] = {
1085 - (layout[layoutCorr[node] + 1] - layout[layoutCorr[node]]),
1087 std::copy(std::begin(pdPoint), std::end(pdPoint),
1088 std::begin(pointToAdd));
1091 treeDummySimplexId[node] = points->InsertNextPoint(pointToAdd);
1092 if(not embeddedDiagram) {
1093 if(isPersistenceDiagram) {
1094 if(layout[layoutCorr[node]] < minBirth) {
1095 minBirth = layout[layoutCorr[node]];
1096 minBirthNode = treeDummySimplexId[node];
1098 if(layout[layoutCorr[node]] > maxBirth) {
1099 maxBirth = layout[layoutCorr[node]];
1100 maxBirthNode = treeDummySimplexId[node];
1105 SimplexId nextPointId = points->InsertNextPoint(point);
1106 treeSimplexId[node] = nextPointId;
1107 nodeCorr[i][node] = nextPointId;
1109 nodeCorr[i][node] = treeDummySimplexId[node];
1110 if(isPersistenceDiagram)
1111 nodeCorr[i][node] = nextPointId;
1113 idNode nodeBranching
1115 or isPersistenceDiagram
1117 : treeBranching[node]);
1124 if(!trees[i]->isRoot(node) or isPersistenceDiagram) {
1125 vtkIdType pointIds[2];
1126 pointIds[0] = treeSimplexId[node];
1128 idNode nodeParent = trees[i]->getParentSafe(node);
1132 and (node < treeBranching.size()
1133 and treeBranching[node] == nodeParent)
1134 and !trees[i]->isRoot(nodeParent) and not isPersistenceDiagram;
1135 if(isPersistenceDiagram) {
1136 pointIds[1] = treeDummySimplexId[node];
1138 pointIds[1] = treeSimplexId[treeBranching[node]];
1139 }
else if(dummyCell) {
1140 double dummyPoint[3]
1141 = {point[0], layout[layoutCorr[nodeParent] + 1] + diff_y,
1143 SimplexId dummyPointId = treeDummySimplexId[nodeParent];
1144 points->SetPoint(dummyPointId, dummyPoint);
1145 vtkIdType dummyPointIds[2];
1146 dummyPointIds[0] = dummyPointId;
1147 dummyPointIds[1] = treeSimplexId[nodeParent];
1148 vtkArcs->InsertNextCell(VTK_LINE, 2, dummyPointIds);
1149 pointIds[1] = dummyPointId;
1151 pointIds[1] = treeSimplexId[nodeParent];
1153 vtkArcs->InsertNextCell(VTK_LINE, 2, pointIds);
1158 int toAdd = (dummyCell ? 2 : 1);
1159 for(
int toAddT = 0; toAddT < toAdd; ++toAddT) {
1161 if(ShiftMode == 1) {
1163 = (!isPersistenceDiagram ? allBaryBranching[c][node] : node);
1164 percentMatchArc->InsertNextTuple1(
1165 allBaryPercentMatch[c][nodeToGet]);
1171 if(clusteringOutput and ShiftMode != 1) {
1173 auto nodeToGet = node;
1174 if(treeMatching[nodeToGet] < allBaryBranchingID[c].size())
1175 tBranchID = allBaryBranchingID[c][treeMatching[nodeToGet]];
1176 branchBaryID->InsertNextTuple1(tBranchID);
1180 if(not isPersistenceDiagram) {
1181 int tBranchID = treeBranchingID[node];
1182 branchID->InsertNextTuple1(tBranchID);
1186 if(not isPersistenceDiagram) {
1187 upNodeId->InsertNextTuple1(treeSimplexId[nodeParent]);
1188 downNodeId->InsertNextTuple1(treeSimplexId[node]);
1194 idNode nodeToGetPers = nodeBranching;
1196 = trees[i]->getNodePersistence<dataType>(nodeToGetPers);
1197 persistenceArc->InsertNextTuple1(persToAdd);
1200 if(clusteringOutput and ShiftMode != 1) {
1201 idNode nodeToGet = nodeBranching;
1202 if(treeMatching[nodeToGet] < allBaryBranchingID[c].size()) {
1203 persistenceBaryArc->InsertTuple1(
1204 cellCount, barycenters[c]->getNodePersistence<dataType>(
1205 treeMatching[nodeToGet]));
1206 persistenceBaryOrderArc->InsertTuple1(
1207 cellCount, baryPersistenceOrder[treeMatching[nodeToGet]]);
1212 clusterIDArc->InsertNextTuple1(clusteringAssignment[i]);
1215 treeIDArc->InsertNextTuple1(i + iSampleOffset);
1218 bool isImportant =
false;
1219 idNode nodeToGetImportance = nodeBranching;
1220 isImportant = trees[i]->isImportantPair<dataType>(
1224 isImportantPairsArc->InsertNextTuple1(isImportant);
1227 bool isDummy = toAdd == 2 and toAddT == 0;
1228 isDummyArc->InsertNextTuple1(isDummy);
1231 isInterpolatedTreeArc->InsertNextTuple1(isInterpolatedTree);
1234 pairIdentifier->InsertNextTuple1(treeSimplexId[node]);
1237 auto birthDeath = trees[i]->getBirthDeath<dataType>(node);
1238 pairBirth->InsertNextTuple1(std::get<0>(birthDeath));
1239 pairPersistence->InsertNextTuple1(std::get<1>(birthDeath)
1240 - std::get<0>(birthDeath));
1244 = (trees[i]->isRoot(node) and not trees[i]->isLeaf(node))
1245 or (trees[i]->isRoot(nodeOrigin)
1246 and not trees[i]->isLeaf(nodeOrigin));
1247 pairIsFinite->InsertNextTuple1(!isMinMaxPair);
1250 pairType->InsertNextTuple1(0);
1253 bool isMultiPersPair
1254 = (trees[i]->isMultiPersPair(nodeBranching)
1255 or trees[i]->isMultiPersPair(
1256 trees[i]->getNode(nodeBranching)->getOrigin()));
1257 isMultiPersPairArc->InsertNextTuple1(isMultiPersPair);
1260 for(
unsigned int ca = 0; ca < customArrays.size(); ++ca)
1261 customCellArraysValues[ca].push_back(
1262 std::get<1>(customArrays[ca])[nodeBranching]);
1263 for(
unsigned int ca = 0; ca < customIntArrays.size(); ++ca)
1264 customCellIntArraysValues[ca].push_back(
1265 std::get<1>(customIntArrays[ca])[nodeBranching]);
1266 for(
unsigned int ca = 0; ca < customStringArrays.size(); ++ca)
1267 customCellStringArraysValues[ca].push_back(
1268 std::get<1>(customStringArrays[ca])[nodeBranching]);
1277 int toAdd = (dummyNode ? 2 : 1);
1278 for(
int toAddT = 0; toAddT < toAdd; ++toAddT) {
1280 nodeID->InsertNextTuple1(treeSimplexId[node]);
1283 trueNodeID->InsertNextTuple1(node);
1286 int nodeVertexId = -1;
1287 if(i <
int(treesNodes.size()) and treesNodes[i]) {
1288 auto vertexIdArray = treesNodes[i]->GetPointData()->GetArray(
1291 if(vertexIdArray and nodeMesh != -1)
1292 nodeVertexId = vertexIdArray->GetTuple1(nodeMesh);
1294 vertexID->InsertNextTuple1(nodeVertexId);
1297 scalar->InsertNextTuple1(trees[i]->getValue<dataType>(node));
1301 int criticalTypeT = -1;
1302 if(not isPersistenceDiagram) {
1303 if(not isInterpolatedTree) {
1304 if(ShiftMode == 1) {
1305 if(nodeMeshTreeIndex != -1) {
1307 = treesNodes[nodeMeshTreeIndex]->GetPointData()->GetArray(
1310 criticalTypeT = array->GetTuple1(nodeMesh);
1312 }
else if(treesNodes.size() != 0 and treesNodes[i] !=
nullptr) {
1314 = treesNodes[i]->GetPointData()->GetArray(
"CriticalType");
1316 criticalTypeT = array->GetTuple1(nodeMesh);
1326 auto nodeIsRoot = trees[i]->isRoot(node);
1329 ? (isPDSadMax or nodeIsRoot ? locMax : saddle1)
1330 : (not isPDSadMax or nodeIsRoot ? locMin : saddle2));
1331 if(embeddedDiagram) {
1332 bool nodeSup = trees[i]->getValue<dataType>(node)
1333 > trees[i]->getValue<dataType>(nodeOrigin);
1335 = ((nodeSup and toAddT == 1) or (not nodeSup and toAddT == 0)
1336 ? (isPDSadMax or nodeIsRoot ? locMax : saddle1)
1337 : (not isPDSadMax or nodeIsRoot ? locMin : saddle2));
1340 criticalType->InsertNextTuple1(criticalTypeT);
1343 if(ShiftMode == 1) {
1344 percentMatch->InsertNextTuple1(allBaryPercentMatch[c][node]);
1350 if(clusteringOutput and ShiftMode != 1) {
1352 if(treeMatching[node] < allBaryBranchingID[c].size()) {
1353 tBranchID = allBaryBranchingID[c][treeMatching[node]];
1354 if(!trees[i]->isLeaf(node)
1355 && treeMatching[nodeOrigin] < allBaryBranchingID[c].size())
1356 tBranchID = allBaryBranchingID[c][treeMatching[nodeOrigin]];
1358 branchBaryNodeID->InsertNextTuple1(tBranchID);
1362 if(not isPersistenceDiagram) {
1363 int tBranchID = treeBranchingID[node];
1364 if(not trees[i]->isLeaf(node))
1365 tBranchID = treeBranchingID[nodeOrigin];
1366 branchNodeID->InsertNextTuple1(tBranchID);
1371 persistenceNode->InsertNextTuple1(
1372 trees[i]->getNodePersistence<dataType>(node));
1375 if(clusteringOutput and ShiftMode != 1) {
1376 if(treeMatching[node] < allBaryBranchingID[c].size()) {
1377 persistenceBaryNode->InsertTuple1(
1378 pointCount, barycenters[c]->getNodePersistence<dataType>(
1379 treeMatching[node]));
1380 persistenceBaryOrderNode->InsertTuple1(
1381 pointCount, baryPersistenceOrder[treeMatching[node]]);
1386 clusterIDNode->InsertNextTuple1(clusteringAssignment[i]);
1389 treeIDNode->InsertNextTuple1(i + iSampleOffset);
1393 = toAdd == 2 and toAddT == 1 and !trees[i]->isRoot(node);
1394 isDummyNode->InsertNextTuple1(isDummy);
1397 isInterpolatedTreeNode->InsertNextTuple1(isInterpolatedTree);
1400 auto birthDeath = trees[i]->getBirthDeath<dataType>(node);
1401 pairBirthNode->InsertNextTuple1(std::get<0>(birthDeath));
1402 pairPersistenceNode->InsertNextTuple1(std::get<1>(birthDeath)
1403 - std::get<0>(birthDeath));
1406 bool isImportant =
false;
1407 isImportant = trees[i]->isImportantPair<dataType>(
1410 isImportantPairsNode->InsertNextTuple1(isImportant);
1413 treeNodeId->InsertNextTuple1(node);
1416 treeNodeIdOrigin->InsertNextTuple1(nodeOrigin);
1420 if(isPersistenceDiagram and !treesNodes.empty()
1421 and ShiftMode != 1) {
1422 double coord[3] = {0.0, 0.0, 0.0};
1423 getPoint(treesNodes[i], treesNodeCorrMesh[i][node], coord);
1424 coordinates->InsertNextTuple3(coord[0], coord[1], coord[2]);
1429 bool isMultiPersPair = (trees[i]->isMultiPersPair(node)
1430 or trees[i]->isMultiPersPair(
1431 trees[i]->getNode(node)->getOrigin()));
1432 isMultiPersPairNode->InsertNextTuple1(isMultiPersPair);
1435 for(
unsigned int ca = 0; ca < customArrays.size(); ++ca)
1436 customArraysValues[ca].emplace_back(
1437 std::get<1>(customArrays[ca])[node]);
1438 for(
unsigned int ca = 0; ca < customIntArrays.size(); ++ca)
1439 customIntArraysValues[ca].emplace_back(
1440 std::get<1>(customIntArrays[ca])[node]);
1441 for(
unsigned int ca = 0; ca < customStringArrays.size(); ++ca)
1442 customStringArraysValues[ca].emplace_back(
1443 std::get<1>(customStringArrays[ca])[node]);
1452 if(isPersistenceDiagram and not embeddedDiagram) {
1453 vtkIdType pointIds[2];
1454 pointIds[0] = minBirthNode;
1455 pointIds[1] = maxBirthNode;
1456 vtkArcs->InsertNextCell(VTK_LINE, 2, pointIds);
1459 pairIdentifier->InsertNextTuple1(-1);
1460 pairType->InsertNextTuple1(-1);
1461 pairPersistence->InsertNextTuple1(-1);
1462 pairIsFinite->InsertNextTuple1(0);
1463 pairBirth->InsertNextTuple1(0);
1465 for(
unsigned int ca = 0; ca < customArrays.size(); ++ca)
1466 customCellArraysValues[ca].push_back(-1);
1467 for(
unsigned int ca = 0; ca < customIntArrays.size(); ++ca)
1468 customCellIntArraysValues[ca].push_back(-1);
1469 for(
unsigned int ca = 0; ca < customStringArrays.size(); ++ca)
1470 customCellStringArraysValues[ca].push_back(
"");
1472 isMultiPersPairArc->InsertNextTuple1(0);
1473 clusterIDArc->InsertNextTuple1(clusteringAssignment[i]);
1474 treeIDArc->InsertNextTuple1(i + iSampleOffset);
1475 isImportantPairsArc->InsertNextTuple1(0);
1476 branchBaryID->InsertNextTuple1(-1);
1477 percentMatchArc->InsertNextTuple1(100);
1487 if(OutputSegmentation and not PlanarLayout and treesSegmentation[i]) {
1488 vtkNew<vtkUnstructuredGrid> iTreesSegmentationCopy{};
1490 iTreesSegmentationCopy->DeepCopy(treesSegmentation[i]);
1492 iTreesSegmentationCopy->ShallowCopy(treesSegmentation[i]);
1493 auto iVkOutputSegmentationTemp
1494 = vtkUnstructuredGrid::SafeDownCast(iTreesSegmentationCopy);
1495 if(!iVkOutputSegmentationTemp
1496 or !iVkOutputSegmentationTemp->GetPoints()) {
1497 printWrn(
"Convert segmentation to vtkUnstructuredGrid.");
1498 vtkNew<vtkAppendFilter> appendFilter2{};
1499 appendFilter2->AddInputData(treesSegmentation[i]);
1500 appendFilter2->Update();
1501 iVkOutputSegmentationTemp->ShallowCopy(appendFilter2->GetOutput());
1503 if(ShiftMode != -1) {
1505 p < iVkOutputSegmentationTemp->GetPoints()->GetNumberOfPoints();
1508 = iVkOutputSegmentationTemp->GetPoints()->GetPoint(p);
1512 iVkOutputSegmentationTemp->GetPoints()->SetPoint(p, point);
1515 appendFilter->AddInputData(iVkOutputSegmentationTemp);
1520 for(
int i = persistenceBaryNode->GetNumberOfTuples(); i < pointCount; ++i)
1521 persistenceBaryNode->InsertNextTuple1(0);
1522 for(
int i = persistenceBaryArc->GetNumberOfTuples(); i < cellCount; ++i)
1523 persistenceBaryArc->InsertNextTuple1(0);
1524 for(
int i = persistenceBaryOrderNode->GetNumberOfTuples(); i < pointCount;
1526 persistenceBaryOrderNode->InsertNextTuple1(0);
1527 for(
int i = persistenceBaryOrderArc->GetNumberOfTuples(); i < cellCount;
1529 persistenceBaryOrderArc->InsertNextTuple1(0);
1537 customIntArrays, customIntArraysValues, vtkOutputNode, 1, 0);
1539 customStringArrays, customStringArraysValues, vtkOutputNode, 2, 0);
1542 vtkOutputNode->SetPoints(points);
1543 vtkOutputNode->GetPointData()->AddArray(criticalType);
1544 vtkOutputNode->GetPointData()->AddArray(persistenceNode);
1545 vtkOutputNode->GetPointData()->AddArray(clusterIDNode);
1546 vtkOutputNode->GetPointData()->AddArray(treeIDNode);
1547 vtkOutputNode->GetPointData()->AddArray(trueNodeID);
1548 vtkOutputNode->GetPointData()->AddArray(vertexID);
1549 vtkOutputNode->GetPointData()->AddArray(isImportantPairsNode);
1550 vtkOutputNode->GetPointData()->AddArray(isMultiPersPairNode);
1551 if(not isPersistenceDiagram) {
1552 vtkOutputNode->GetPointData()->AddArray(nodeID);
1553 vtkOutputNode->GetPointData()->AddArray(branchNodeID);
1554 vtkOutputNode->GetPointData()->AddArray(isDummyNode);
1557 vtkOutputNode->GetPointData()->AddArray(scalar);
1558 if(clusteringOutput and ShiftMode != 1) {
1559 vtkOutputNode->GetPointData()->AddArray(branchBaryNodeID);
1560 vtkOutputNode->GetPointData()->AddArray(persistenceBaryNode);
1561 vtkOutputNode->GetPointData()->AddArray(persistenceBaryOrderNode);
1563 if(foundOneInterpolatedTree)
1564 vtkOutputNode->GetPointData()->AddArray(isInterpolatedTreeNode);
1566 vtkOutputNode->GetPointData()->AddArray(percentMatch);
1567 if(outputTreeNodeIndex)
1568 vtkOutputNode->GetPointData()->AddArray(treeNodeId);
1569 if(isPersistenceDiagram) {
1570 vtkOutputNode->GetPointData()->AddArray(treeNodeIdOrigin);
1571 if(!treesNodes.empty() and ShiftMode != 1)
1572 vtkOutputNode->GetPointData()->AddArray(coordinates);
1574 vtkOutputNode->GetPointData()->AddArray(pairPersistenceNode);
1575 vtkOutputNode->GetPointData()->AddArray(pairBirthNode);
1581 customIntArrays, customCellIntArraysValues, vtkArcs, 1, 1);
1583 customStringArrays, customCellStringArraysValues, vtkArcs, 2, 1);
1586 vtkArcs->SetPoints(points);
1587 vtkArcs->GetCellData()->AddArray(persistenceArc);
1588 vtkArcs->GetCellData()->AddArray(clusterIDArc);
1589 vtkArcs->GetCellData()->AddArray(treeIDArc);
1590 vtkArcs->GetCellData()->AddArray(isImportantPairsArc);
1591 vtkArcs->GetCellData()->AddArray(isMultiPersPairArc);
1592 if(not isPersistenceDiagram) {
1593 vtkArcs->GetCellData()->AddArray(isDummyArc);
1594 vtkArcs->GetCellData()->AddArray(branchID);
1595 vtkArcs->GetCellData()->AddArray(upNodeId);
1596 vtkArcs->GetCellData()->AddArray(downNodeId);
1598 if(clusteringOutput and ShiftMode != 1) {
1599 vtkArcs->GetCellData()->AddArray(branchBaryID);
1600 vtkArcs->GetCellData()->AddArray(persistenceBaryArc);
1601 vtkArcs->GetCellData()->AddArray(persistenceBaryOrderArc);
1603 if(foundOneInterpolatedTree)
1604 vtkArcs->GetCellData()->AddArray(isInterpolatedTreeArc);
1606 vtkArcs->GetCellData()->AddArray(percentMatchArc);
1607 if(isPersistenceDiagram) {
1608 vtkArcs->GetCellData()->AddArray(pairIdentifier);
1609 vtkArcs->GetCellData()->AddArray(pairType);
1610 vtkArcs->GetCellData()->AddArray(pairIsFinite);
1612 vtkArcs->GetCellData()->AddArray(pairPersistence);
1613 vtkArcs->GetCellData()->AddArray(pairBirth);
1614 if(vtkOutputArc == vtkOutputNode)
1615 vtkArcs->GetPointData()->ShallowCopy(vtkOutputNode->GetPointData());
1617 vtkArcs->GetPointData()->AddArray(scalar);
1618 vtkOutputArc->ShallowCopy(vtkArcs);
1621 if(OutputSegmentation and not PlanarLayout
1622 and appendFilter->GetNumberOfInputConnections(0) != 0) {
1623 appendFilter->SetMergePoints(
false);
1624 appendFilter->Update();
1625 vtkOutputSegmentation->ShallowCopy(appendFilter->GetOutput());
1636 std::tuple<double, double, double, double, double, double>
1639 std::vector<int> &nodeCorrT) {
1640 double x_min = std::numeric_limits<double>::max();
1641 double y_min = std::numeric_limits<double>::max();
1642 double z_min = std::numeric_limits<double>::max();
1643 double x_max = std::numeric_limits<double>::lowest();
1644 double y_max = std::numeric_limits<double>::lowest();
1645 double z_max = std::numeric_limits<double>::lowest();
1646 std::queue<idNode> queue;
1647 queue.emplace(tree->
getRoot());
1648 while(!queue.empty()) {
1649 idNode node = queue.front();
1651 double *point = treeNodes->GetPoints()->GetPoint(nodeCorrT[node]);
1652 x_min = std::min(x_min, point[0]);
1653 x_max = std::max(x_max, point[0]);
1654 y_min = std::min(y_min, point[1]);
1655 y_max = std::max(y_max, point[1]);
1656 z_min = std::min(z_min, point[2]);
1657 z_max = std::max(z_max, point[2]);
1658 std::vector<idNode> children;
1660 for(
auto child : children)
1661 queue.emplace(child);
1663 return std::make_tuple(x_min, x_max, y_min, y_max, z_min, z_max);
1666 std::tuple<double, double, double, double, double, double>
1669 for(
size_t i = 0; i < nodeCorrT.size(); ++i)
void makeTreesOutput(FTMTree_MT *tree1, FTMTree_MT *tree2)
void setTreesSegmentation(std::vector< vtkDataSet * > &segmentation)
void setInterpolatedTrees(std::vector< bool > &isInterpolatedTrees)
std::vector< double > getClusterShift()
void setMinimumImportantPairs(int minPairs)
void setMaximumImportantPairs(int maxPairs)
void clearCustomStringArrays()
void copyPointData(vtkUnstructuredGrid *treeNodes, std::vector< int > &nodeCorrT)
void setVtkOutputNode1(vtkUnstructuredGrid *vtkNode1)
void setNodeCorr1(std::vector< std::vector< SimplexId > > &nodeCorrT)
void setOutputMatchingBarycenter(std::vector< std::vector< std::vector< std::tuple< idNode, idNode, double > > > > &matching)
void setVtkOutputSegmentation(vtkDataSet *vtkSegmentation)
void setTreesNodeCorrMesh(std::vector< std::vector< int > > &nodeCorrMesh)
void setNoSampleOffset(int offset)
ttkMergeTreeVisualization()=default
void setOutputSegmentation(bool b)
void addCustomIntArray(std::string &name, std::vector< int > &vec)
void setPrintTreeId(int id)
void setVtkOutputMatching(vtkUnstructuredGrid *vtkMatching)
void setAlpha(double alpha)
void setPlanarLayout(bool b)
void setClusteringAssignment(std::vector< int > &asgn)
void setPrintClusterId(int id)
void addCustomStringArray(std::string &name, std::vector< std::string > &vec)
void clearAllCustomArrays()
void makeTreesOutput(std::vector< FTMTree_MT * > &trees, std::vector< FTMTree_MT * > &barycenters)
std::vector< std::vector< float > > getAllBaryPercentMatch()
void setPrevXMaxOffset(double offset)
std::vector< std::vector< SimplexId > > getNodeCorr()
std::tuple< double, double, double, double, double, double > getRealBounds(vtkUnstructuredGrid *treeNodes, FTMTree_MT *tree)
std::tuple< double, double, double, double, double, double > getRealBounds(vtkUnstructuredGrid *treeNodes, FTMTree_MT *tree, std::vector< int > &nodeCorrT)
void setTreesNodes(vtkUnstructuredGrid *nodes)
void setOutputTreeNodeId(int doOutput)
void copyPointData(vtkUnstructuredGrid *treeNodes)
void setTreesSegmentation(vtkDataSet *segmentation)
void makeTreesOutput(FTMTree_MT *tree1)
~ttkMergeTreeVisualization() override=default
void clearCustomIntArrays()
void setShiftMode(int mode)
void setConvertedToDiagram(bool converted)
void setISampleOffset(int offset)
void makeMatchingOutput(std::vector< FTMTree_MT * > &trees, std::vector< FTMTree_MT * > &barycenters)
void addVtkCustomArrays(std::vector< std::tuple< std::string, std::vector< dataType > > > &cArrays, std::vector< std::vector< dataType > > &cArraysValues, vtkUnstructuredGrid *vtkOutput, int type, int output)
void getTreeNodeIdRev(vtkDataArray *treeNodeIdArray, std::vector< int > &treeNodeIdRev)
void setDimensionToShift(int i)
void setDimensionSpacing(double d)
void setIsPDSadMax(bool isSadMax)
void setVtkOutputNode2(vtkUnstructuredGrid *vtkNode2)
void setTreesNodeCorrMesh(std::vector< int > &nodeCorrMesh)
void makeTreesOutput(std::vector< FTMTree_MT * > &trees)
void makeMatchingOutput(FTMTree_MT *tree1, FTMTree_MT *tree2)
void setVtkOutputArc(vtkUnstructuredGrid *vtkArc)
void setIsPersistenceDiagram(bool isPD)
void setNodeCorr2(std::vector< std::vector< SimplexId > > &nodeCorrT)
void setVtkOutputNode(vtkUnstructuredGrid *vtkNode)
void setOutputMatching(std::vector< std::tuple< idNode, idNode, double > > &matching)
void addCustomArray(std::string &name, std::vector< double > &vec)
void setBarycenterPositionAlpha(bool pos)
void setTreesNodes(std::vector< vtkUnstructuredGrid * > &nodes)
void setAllBaryPercentMatch(std::vector< std::vector< float > > &baryPercentMatch)
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
bool branchDecompositionPlanarLayout_
std::vector< double > excludeImportantPairsLowerValues_
std::vector< double > excludeImportantPairsHigherValues_
std::tuple< double, double, double, double, double, double > getMaximalBounds(std::vector< std::tuple< double, double, double, double, double, double > > &allBounds, std::vector< int > &clusteringAssignmentT, int clusterID)
dataType getNodePersistence(idNode nodeId)
idNode getNumberOfNodes() const
void getChildren(idNode nodeId, std::vector< idNode > &res)
Node * getNode(idNode nodeId)
idSuperArc getNumberOfDownSuperArcs() const
idSuperArc getNumberOfUpSuperArcs() const
unsigned int idNode
Node index in vect_nodes_.
const char PersistenceName[]
const char PersistenceCoordinatesName[]
const char PersistencePairTypeName[]
const char PersistenceCriticalTypeName[]
const char PersistenceIsFinite[]
const char VertexScalarFieldName[]
default name for vertex scalar field
const char PersistencePairIdentifierName[]
const char PersistenceBirthName[]
int SimplexId
Identifier type for simplices of any dimension.