579 std::vector<FTMTree_MT *> &barycenters) {
580 int numInputs = trees.size();
581 int const numInputsOri = numInputs;
582 int NumberOfBarycenters = barycenters.size();
583 bool const clusteringOutput = (NumberOfBarycenters != 0);
585 = std::max(NumberOfBarycenters, 1);
586 bool const embeddedDiagram = not PlanarLayout and isPersistenceDiagram;
589 for(
int i = 0; i < numInputs; ++i) {
590 if(i < (
int)treesNodes.size() and treesNodes[i]) {
592 = treesNodes[i]->GetPointData()->GetArray(
"TreeNodeId");
593 if(treeNodeIdArray) {
594 std::vector<int> treeNodeIdRev;
596 for(
unsigned int j = 0; j < treesNodeCorrMesh[i].size(); ++j)
597 treesNodeCorrMesh[i][j] = treeNodeIdRev[treesNodeCorrMesh[i][j]];
604 std::vector<std::tuple<double, double, double, double, double, double>>
605 allBounds(numInputs);
606 for(
int i = 0; i < numInputs; ++i) {
607 if(OutputSegmentation and treesSegmentation[i]) {
608 double *tBounds = treesSegmentation[i]->GetBounds();
609 allBounds[i] = std::make_tuple(tBounds[0], tBounds[1], tBounds[2],
610 tBounds[3], tBounds[4], tBounds[5]);
611 }
else if(treesNodes.size() != 0 and treesNodes[i] !=
nullptr) {
612 if(not isPersistenceDiagram)
614 =
getRealBounds(treesNodes[i], trees[i], treesNodeCorrMesh[i]);
617 treesNodes[i]->GetBounds(bounds);
618 allBounds[i] = std::make_tuple(
619 bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
622 allBounds[i] = allBounds[0];
626 std::vector<std::tuple<double, double, double, double, double, double>>
627 allBaryBounds(barycenters.size());
628 std::vector<std::vector<idNode>> allBaryBranching(barycenters.size());
629 std::vector<std::vector<int>> allBaryBranchingID(barycenters.size());
630 for(
size_t c = 0; c < barycenters.size(); ++c) {
632 if(not isPersistenceDiagram)
633 barycenters[c]->getTreeBranching(
634 allBaryBranching[c], allBaryBranchingID[c]);
636 if(not clusteringOutput)
637 allBaryBounds.emplace_back(
644 std::vector<FTMTree_MT *>
const treesOri(trees);
647 clusteringAssignment.clear();
648 for(
unsigned int j = 0; j < barycenters.size(); ++j) {
649 trees.emplace_back(barycenters[j]);
650 clusteringAssignment.emplace_back(j);
652 numInputs = trees.size();
655 vtkNew<vtkUnstructuredGrid> vtkArcs{};
656 vtkNew<vtkPoints> points{};
659 vtkNew<vtkIntArray> criticalType{};
661 vtkNew<vtkDoubleArray> persistenceNode{};
663 vtkNew<vtkIntArray> clusterIDNode{};
664 clusterIDNode->SetName(
"ClusterID");
665 vtkNew<vtkIntArray> isDummyNode{};
666 isDummyNode->SetName(
"isDummyNode");
667 vtkNew<vtkIntArray> branchNodeID{};
668 branchNodeID->SetName(
"BranchNodeID");
669 vtkNew<vtkFloatArray> scalar{};
670 scalar->SetName(
"Scalar");
671 vtkNew<vtkIntArray> isImportantPairsNode{};
672 isImportantPairsNode->SetName(
"isImportantPair");
673 vtkNew<vtkIntArray> nodeID{};
674 nodeID->SetName(
"NodeId");
675 vtkNew<vtkIntArray> trueNodeID{};
676 trueNodeID->SetName(
"TrueNodeId");
677 vtkNew<vtkIntArray> vertexID{};
681 vtkNew<vtkIntArray> treeIDNode{};
682 treeIDNode->SetName(
"TreeID");
683 vtkNew<vtkIntArray> branchBaryNodeID{};
684 branchBaryNodeID->SetName(
"BranchBaryNodeID");
685 vtkNew<vtkIntArray> isInterpolatedTreeNode{};
686 isInterpolatedTreeNode->SetName(
"isInterpolatedTree");
688 vtkNew<vtkFloatArray> percentMatch{};
689 percentMatch->SetName(
"PercentMatchNode");
690 vtkNew<vtkFloatArray> persistenceBaryNode{};
691 persistenceBaryNode->SetName(
"PersistenceBarycenter");
692 vtkNew<vtkIntArray> persistenceBaryOrderNode{};
693 persistenceBaryOrderNode->SetName(
"PersistenceBarycenterOrder");
695 vtkNew<vtkDoubleArray> pairBirthNode{};
698 vtkNew<vtkFloatArray> treeNodeId{};
699 treeNodeId->SetName(
"TreeNodeId");
701 vtkNew<vtkFloatArray> treeNodeIdOrigin{};
702 treeNodeIdOrigin->SetName(
"TreeNodeIdOrigin");
703 vtkNew<vtkDoubleArray> coordinates{};
705 coordinates->SetNumberOfComponents(3);
707 vtkNew<vtkIntArray> isMultiPersPairNode{};
708 isMultiPersPairNode->SetName(
"isMultiPersPairNode");
710 std::vector<std::vector<double>> customArraysValues(customArrays.size());
711 std::vector<std::vector<int>> customIntArraysValues(customIntArrays.size());
712 std::vector<std::vector<std::string>> customStringArraysValues(
713 customStringArrays.size());
716 vtkNew<vtkDoubleArray> persistenceArc{};
718 vtkNew<vtkIntArray> clusterIDArc{};
719 clusterIDArc->SetName(
"ClusterID");
720 vtkNew<vtkIntArray> isImportantPairsArc{};
721 isImportantPairsArc->SetName(
"isImportantPair");
722 vtkNew<vtkIntArray> isDummyArc{};
723 isDummyArc->SetName(
"isDummyArc");
724 vtkNew<vtkIntArray> branchID{};
725 branchID->SetName(
"BranchID");
726 vtkNew<vtkIntArray> upNodeId{};
727 upNodeId->SetName(
"upNodeId");
728 vtkNew<vtkIntArray> downNodeId{};
729 downNodeId->SetName(
"downNodeId");
731 vtkNew<vtkIntArray> treeIDArc{};
732 treeIDArc->SetName((isPersistenceDiagram ?
"DiagramID" :
"TreeID"));
733 vtkNew<vtkIntArray> branchBaryID{};
734 branchBaryID->SetName(
"BranchBaryNodeID");
735 vtkNew<vtkIntArray> isInterpolatedTreeArc{};
736 isInterpolatedTreeArc->SetName(
"isInterpolatedTree");
738 vtkNew<vtkFloatArray> percentMatchArc{};
739 percentMatchArc->SetName(
"PercentMatchArc");
740 vtkNew<vtkFloatArray> persistenceBaryArc{};
741 persistenceBaryArc->SetName(
"PersistenceBarycenter");
742 vtkNew<vtkIntArray> persistenceBaryOrderArc{};
743 persistenceBaryOrderArc->SetName(
"PersistenceBarycenterOrder");
745 vtkNew<vtkIntArray> pairIdentifier{};
747 vtkNew<vtkIntArray> pairType{};
749 vtkNew<vtkIntArray> pairIsFinite{};
751 vtkNew<vtkDoubleArray> pairBirth{};
754 vtkNew<vtkIntArray> isMultiPersPairArc{};
755 isMultiPersPairArc->SetName(
"isMultiPersPairArc");
757 std::vector<std::vector<double>> customCellArraysValues(
758 customArrays.size());
759 std::vector<std::vector<int>> customCellIntArraysValues(
760 customIntArrays.size());
761 std::vector<std::vector<std::string>> customCellStringArraysValues(
762 customStringArrays.size());
765 vtkNew<vtkAppendFilter> appendFilter{};
770 bool foundOneInterpolatedTree =
false;
772 nodeCorr.resize(numInputs);
773 clusterShift.clear();
774 clusterShift.resize(NumberOfBarycenters, 0);
775 allBaryPercentMatch.clear();
776 allBaryPercentMatch.resize(NumberOfBarycenters);
783 for(
int c = 0; c < NumberOfBarycenters; ++c) {
786 std::vector<int> baryPersistenceOrder;
787 if(clusteringOutput and ShiftMode != 1) {
788 baryPersistenceOrder.resize(barycenters[c]->getNumberOfNodes(), -1);
789 std::vector<std::tuple<ttk::ftm::idNode, ttk::ftm::idNode, dataType>>
791 barycenters[c]->getPersistencePairsFromTree<dataType>(pairsBary,
false);
792 for(
unsigned int j = 0; j < pairsBary.size(); ++j) {
793 int const index = pairsBary.size() - 1 - j;
794 baryPersistenceOrder[std::get<0>(pairsBary[j])] = index;
795 baryPersistenceOrder[std::get<1>(pairsBary[j])] = index;
801 double delta_max = 1.0;
802 int noSample = 0 + noSampleOffset;
803 for(
int i = 0; i < numInputsOri; ++i) {
804 delta_max = std::max(
805 (std::get<3>(allBounds[i]) - std::get<2>(allBounds[i])), delta_max);
806 delta_max = std::max(
807 (std::get<1>(allBounds[i]) - std::get<0>(allBounds[i])), delta_max);
808 if(clusteringAssignment[i] != c)
812 double const radius = delta_max * 2 * DimensionSpacing;
813 int iSample = 0 + iSampleOffset - 1;
815 if(c < NumberOfBarycenters - 1)
816 clusterShift[c + 1] = radius * 4 + clusterShift[c];
819 prevXMax = 0 + prevXMaxOffset;
820 std::vector<double> allPrevXMax;
821 double prevYMax = std::numeric_limits<double>::lowest();
826 printMsg(
"Iterate through all trees of this cluster",
828 for(
int i = 0; i < numInputs; ++i) {
829 if(clusteringAssignment[i] != c)
834 if((printTreeId == -1 and printClusterId != -1 and c != printClusterId)
835 or (printTreeId != -1 and printClusterId == -1 and i != printTreeId)
836 or (printTreeId != -1 and printClusterId != -1
837 and (c != printClusterId or i != printTreeId)))
842 if(MaximumImportantPairs > 0 or MinimumImportantPairs > 0) {
843 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
844 trees[i]->getPersistencePairsFromTree(pairs,
false);
845 if(MaximumImportantPairs > 0) {
846 int firstIndex = pairs.size() - MaximumImportantPairs;
848 = std::max(std::min(firstIndex,
int(pairs.size()) - 1), 0);
849 double tempThreshold = 0.999 * std::get<2>(pairs[firstIndex])
850 / std::get<2>(pairs[pairs.size() - 1]);
851 tempThreshold *= 100;
854 if(MinimumImportantPairs > 0) {
855 int firstIndex = pairs.size() - MinimumImportantPairs;
857 = std::max(std::min(firstIndex,
int(pairs.size()) - 1), 0);
858 double tempThreshold = 0.999 * std::get<2>(pairs[firstIndex])
859 / std::get<2>(pairs[pairs.size() - 1]);
860 tempThreshold *= 100;
866 bool isInterpolatedTree =
false;
867 if(interpolatedTrees.size() != 0)
868 isInterpolatedTree = interpolatedTrees[i];
869 foundOneInterpolatedTree |= isInterpolatedTree;
873 std::vector<idNode> treeBranching;
874 std::vector<int> treeBranchingID;
875 if(not isPersistenceDiagram)
876 trees[i]->getTreeBranching(treeBranching, treeBranchingID);
880 double const angle = 360.0 / noSample * iSample;
881 double const pi =
M_PI;
882 double diff_x = 0, diff_y = 0;
883 double const alphaShift
884 = BarycenterPositionAlpha ? (-radius + 2 * radius * Alpha) * -1 : 0;
892 = -1 * radius * std::cos(-1 * angle * pi / 180) + clusterShift[c];
893 diff_y = -1 * radius * std::sin(-1 * angle * pi / 180);
896 diff_x = clusterShift[c] + alphaShift;
900 diff_x = prevXMax + radius;
903 diff_x = prevXMax + radius;
904 if(i >= numInputs / 2) {
905 diff_y = -(prevYMax + radius / 2);
906 diff_x = allPrevXMax[i - int(numInputs / 2)] + radius;
908 allPrevXMax.emplace_back(prevXMax);
916 double diff_z = PlanarLayout ? 0 : -std::get<4>(allBounds[i]);
919 if(DimensionToShift != 0) {
920 if(DimensionToShift == 2)
922 else if(DimensionToShift == 1)
924 diff_x = -std::get<0>(allBounds[i]);
929 std::vector<float> layout;
931 double refPersistence;
933 refPersistence = barycenters[0]->getNodePersistence<dataType>(
934 barycenters[0]->getRoot());
937 = trees[0]->getNodePersistence<dataType>(trees[0]->getRoot());
938 if(not isPersistenceDiagram)
939 treePlanarLayout<dataType>(
940 trees[i], allBaryBounds[c], refPersistence, layout);
942 persistenceDiagramPlanarLayout<dataType>(trees[i], layout);
949 nodeCorr[i].resize(trees[i]->getNumberOfNodes());
950 std::vector<SimplexId> treeSimplexId(trees[i]->getNumberOfNodes());
951 std::vector<SimplexId> treeDummySimplexId(trees[i]->getNumberOfNodes());
952 std::vector<SimplexId> layoutCorr(trees[i]->getNumberOfNodes());
953 std::vector<idNode> treeMatching(trees[i]->getNumberOfNodes(), -1);
954 if(clusteringOutput and ShiftMode != 1)
955 for(
auto match : outputMatchingBarycenter[c][i])
956 treeMatching[std::get<1>(match)] = std::get<0>(match);
959 std::vector<std::vector<idNode>> baryMatching(
960 trees[i]->getNumberOfNodes(),
962 numInputsOri, std::numeric_limits<idNode>::max()));
964 for(
size_t j = 0; j < outputMatchingBarycenter[c].size(); ++j)
965 for(
auto match : outputMatchingBarycenter[c][j])
966 baryMatching[std::get<0>(match)][j] = std::get<1>(match);
967 allBaryPercentMatch[c].resize(trees[i]->getNumberOfNodes(), 100.0);
969 double minBirth = std::numeric_limits<double>::max(),
970 maxBirth = std::numeric_limits<double>::lowest();
971 SimplexId minBirthNode = 0, maxBirthNode = 0;
977 std::queue<idNode> queue;
978 queue.emplace(trees[i]->getRoot());
979 while(!queue.empty()) {
980 idNode
const node = queue.front();
982 idNode
const nodeOrigin = trees[i]->getNode(node)->getOrigin();
987 std::vector<idNode> children;
988 trees[i]->getChildren(node, children);
989 for(
auto child : children)
990 queue.emplace(child);
996 = [&](vtkUnstructuredGrid *vtu,
int pointID, double(&point)[3]) {
999 if(not isPersistenceDiagram or convertedToDiagram) {
1000 double *pointTemp = vtu->GetPoints()->GetPoint(pointID);
1001 for(
int k = 0; k < 3; ++k)
1002 point[k] += pointTemp[k];
1004 for(
int k = 0; k < 3; ++k) {
1005 auto array = vtu->GetPointData()->GetArray(
1008 point[k] += array->GetComponent(pointID, k);
1015 int nodeMeshTreeIndex = -1;
1016 double noMatched = 0.0;
1017 double point[3] = {0, 0, 0};
1018 if(ShiftMode == 1) {
1019 for(
int j = 0; j < numInputsOri; ++j) {
1020 if(baryMatching[node][j] != std::numeric_limits<idNode>::max()) {
1021 nodeMesh = treesNodeCorrMesh[j][baryMatching[node][j]];
1022 if(not PlanarLayout)
1023 getPoint(treesNodes[j], nodeMesh, point);
1025 nodeMeshTreeIndex = j;
1028 for(
int k = 0; k < 3; ++k)
1029 point[k] /= noMatched;
1030 }
else if(not isInterpolatedTree and treesNodes.size() != 0
1031 and treesNodes[i] !=
nullptr) {
1032 nodeMesh = treesNodeCorrMesh[i][node];
1033 if(not PlanarLayout)
1034 getPoint(treesNodes[i], nodeMesh, point);
1037 layoutCorr[node] = cptNode;
1038 point[0] = layout[cptNode];
1039 point[1] = layout[cptNode + 1];
1048 if(ShiftMode == 1) {
1049 float const percentMatchT = noMatched * 100 / numInputs;
1050 allBaryPercentMatch[c][node] = percentMatchT;
1054 prevXMax = std::max(prevXMax, point[0]);
1055 if(ShiftMode == 3) {
1056 if(i < numInputs / 2)
1057 prevYMax = std::max(prevYMax, point[1]);
1058 if(i ==
int(numInputs / 2) - 1)
1065 and (!trees[i]->isRoot(node) or isPersistenceDiagram);
1066 dummyNode = dummyNode or embeddedDiagram;
1068 double pointToAdd[3] = {0, 0, 0};
1069 if(embeddedDiagram) {
1070 if(i < (
int)treesNodes.size()
1071 and i < (
int)treesNodeCorrMesh.size()
1072 and nodeOrigin < treesNodeCorrMesh[i].size())
1074 treesNodes[i], treesNodeCorrMesh[i][nodeOrigin], pointToAdd);
1076 if(not isPersistenceDiagram) {
1079 std::begin(point), std::end(point), std::begin(pointToAdd));
1081 double pdPoint[3] = {
1084 - (layout[layoutCorr[node] + 1] - layout[layoutCorr[node]]),
1086 std::copy(std::begin(pdPoint), std::end(pdPoint),
1087 std::begin(pointToAdd));
1090 treeDummySimplexId[node] = points->InsertNextPoint(pointToAdd);
1091 if(not embeddedDiagram) {
1092 if(isPersistenceDiagram) {
1093 if(layout[layoutCorr[node]] < minBirth) {
1094 minBirth = layout[layoutCorr[node]];
1095 minBirthNode = treeDummySimplexId[node];
1097 if(layout[layoutCorr[node]] > maxBirth) {
1098 maxBirth = layout[layoutCorr[node]];
1099 maxBirthNode = treeDummySimplexId[node];
1104 SimplexId
const nextPointId = points->InsertNextPoint(point);
1105 treeSimplexId[node] = nextPointId;
1106 nodeCorr[i][node] = nextPointId;
1108 nodeCorr[i][node] = treeDummySimplexId[node];
1109 if(isPersistenceDiagram)
1110 nodeCorr[i][node] = nextPointId;
1112 idNode
const nodeBranching
1114 or isPersistenceDiagram
1116 : treeBranching[node]);
1123 if(!trees[i]->isRoot(node) or isPersistenceDiagram) {
1124 vtkIdType pointIds[2];
1125 pointIds[0] = treeSimplexId[node];
1127 idNode
const nodeParent = trees[i]->getParentSafe(node);
1129 bool const dummyCell
1131 and (node < treeBranching.size()
1132 and treeBranching[node] == nodeParent)
1133 and !trees[i]->isRoot(nodeParent) and not isPersistenceDiagram;
1134 if(isPersistenceDiagram) {
1135 pointIds[1] = treeDummySimplexId[node];
1137 pointIds[1] = treeSimplexId[treeBranching[node]];
1138 }
else if(dummyCell) {
1139 double dummyPoint[3]
1140 = {point[0], layout[layoutCorr[nodeParent] + 1] + diff_y,
1142 SimplexId
const dummyPointId = treeDummySimplexId[nodeParent];
1143 points->SetPoint(dummyPointId, dummyPoint);
1144 vtkIdType dummyPointIds[2];
1145 dummyPointIds[0] = dummyPointId;
1146 dummyPointIds[1] = treeSimplexId[nodeParent];
1147 vtkArcs->InsertNextCell(VTK_LINE, 2, dummyPointIds);
1148 pointIds[1] = dummyPointId;
1150 pointIds[1] = treeSimplexId[nodeParent];
1152 vtkArcs->InsertNextCell(VTK_LINE, 2, pointIds);
1157 int const toAdd = (dummyCell ? 2 : 1);
1158 for(
int toAddT = 0; toAddT < toAdd; ++toAddT) {
1160 if(ShiftMode == 1) {
1162 = (!isPersistenceDiagram ? allBaryBranching[c][node] : node);
1163 percentMatchArc->InsertNextTuple1(
1164 allBaryPercentMatch[c][nodeToGet]);
1170 if(clusteringOutput and ShiftMode != 1) {
1172 auto nodeToGet = node;
1173 if(treeMatching[nodeToGet] < allBaryBranchingID[c].size())
1174 tBranchID = allBaryBranchingID[c][treeMatching[nodeToGet]];
1175 branchBaryID->InsertNextTuple1(tBranchID);
1179 if(not isPersistenceDiagram) {
1180 int const tBranchID = treeBranchingID[node];
1181 branchID->InsertNextTuple1(tBranchID);
1185 if(not isPersistenceDiagram) {
1186 upNodeId->InsertNextTuple1(treeSimplexId[nodeParent]);
1187 downNodeId->InsertNextTuple1(treeSimplexId[node]);
1193 idNode
const nodeToGetPers
1194 = (isPersistenceDiagram ? node : nodeBranching);
1195 double const persToAdd
1196 = trees[i]->getNodePersistence<dataType>(nodeToGetPers);
1197 persistenceArc->InsertNextTuple1(persToAdd);
1201 = trees[i]->getBirthDeath<dataType>(nodeToGetPers);
1202 pairBirth->InsertNextTuple1(std::get<0>(birthDeath));
1205 if(clusteringOutput and ShiftMode != 1) {
1206 idNode
const nodeToGet = nodeBranching;
1207 if(treeMatching[nodeToGet] < allBaryBranchingID[c].size()) {
1208 persistenceBaryArc->InsertTuple1(
1209 cellCount, barycenters[c]->getNodePersistence<dataType>(
1210 treeMatching[nodeToGet]));
1211 persistenceBaryOrderArc->InsertTuple1(
1212 cellCount, baryPersistenceOrder[treeMatching[nodeToGet]]);
1217 clusterIDArc->InsertNextTuple1(clusteringAssignment[i]);
1220 treeIDArc->InsertNextTuple1(i + iSampleOffset);
1223 bool isImportant =
false;
1224 idNode
const nodeToGetImportance = nodeBranching;
1225 isImportant = trees[i]->isImportantPair<dataType>(
1229 isImportantPairsArc->InsertNextTuple1(isImportant);
1232 bool const isDummy = toAdd == 2 and toAddT == 0;
1233 isDummyArc->InsertNextTuple1(isDummy);
1236 isInterpolatedTreeArc->InsertNextTuple1(isInterpolatedTree);
1239 pairIdentifier->InsertNextTuple1(treeSimplexId[node]);
1242 bool const isMinMaxPair
1243 = (trees[i]->isRoot(node) and not trees[i]->isLeaf(node))
1244 or (trees[i]->isRoot(nodeOrigin)
1245 and not trees[i]->isLeaf(nodeOrigin));
1246 pairIsFinite->InsertNextTuple1(!isMinMaxPair);
1249 pairType->InsertNextTuple1(0);
1252 bool const isMultiPersPair
1253 = (trees[i]->isMultiPersPair(nodeBranching)
1254 or trees[i]->isMultiPersPair(
1255 trees[i]->getNode(nodeBranching)->getOrigin()));
1256 isMultiPersPairArc->InsertNextTuple1(isMultiPersPair);
1259 for(
unsigned int ca = 0; ca < customArrays.size(); ++ca)
1260 customCellArraysValues[ca].push_back(
1261 std::get<1>(customArrays[ca])[nodeBranching]);
1262 for(
unsigned int ca = 0; ca < customIntArrays.size(); ++ca)
1263 customCellIntArraysValues[ca].push_back(
1264 std::get<1>(customIntArrays[ca])[nodeBranching]);
1265 for(
unsigned int ca = 0; ca < customStringArrays.size(); ++ca)
1266 customCellStringArraysValues[ca].push_back(
1267 std::get<1>(customStringArrays[ca])[nodeBranching]);
1276 int const toAdd = (dummyNode ? 2 : 1);
1277 for(
int toAddT = 0; toAddT < toAdd; ++toAddT) {
1279 nodeID->InsertNextTuple1(treeSimplexId[node]);
1282 trueNodeID->InsertNextTuple1(node);
1285 int nodeVertexId = -1;
1286 if(i <
int(treesNodes.size()) and treesNodes[i]) {
1287 auto vertexIdArray = treesNodes[i]->GetPointData()->GetArray(
1290 if(vertexIdArray and nodeMesh != -1)
1291 nodeVertexId = vertexIdArray->GetTuple1(nodeMesh);
1293 vertexID->InsertNextTuple1(nodeVertexId);
1296 scalar->InsertNextTuple1(trees[i]->getValue<dataType>(node));
1300 int criticalTypeT = -1;
1301 if(not isPersistenceDiagram) {
1302 if(not isInterpolatedTree) {
1303 if(ShiftMode == 1) {
1304 if(nodeMeshTreeIndex != -1) {
1306 = treesNodes[nodeMeshTreeIndex]->GetPointData()->GetArray(
1309 criticalTypeT = array->GetTuple1(nodeMesh);
1311 }
else if(treesNodes.size() != 0 and treesNodes[i] !=
nullptr) {
1313 = treesNodes[i]->GetPointData()->GetArray(
"CriticalType");
1315 criticalTypeT = array->GetTuple1(nodeMesh);
1325 auto nodeIsRoot = trees[i]->isRoot(node);
1328 ? (isPDSadMax or nodeIsRoot ? locMax : saddle1)
1329 : (not isPDSadMax or nodeIsRoot ? locMin : saddle2));
1330 if(embeddedDiagram) {
1331 bool const nodeSup = trees[i]->getValue<dataType>(node)
1332 > trees[i]->getValue<dataType>(nodeOrigin);
1334 = ((nodeSup and toAddT == 1) or (not nodeSup and toAddT == 0)
1335 ? (isPDSadMax or nodeIsRoot ? locMax : saddle1)
1336 : (not isPDSadMax or nodeIsRoot ? locMin : saddle2));
1339 criticalType->InsertNextTuple1(criticalTypeT);
1342 if(ShiftMode == 1) {
1343 percentMatch->InsertNextTuple1(allBaryPercentMatch[c][node]);
1349 if(clusteringOutput and ShiftMode != 1) {
1351 if(treeMatching[node] < allBaryBranchingID[c].size()) {
1352 tBranchID = allBaryBranchingID[c][treeMatching[node]];
1353 if(!trees[i]->isLeaf(node)
1354 && treeMatching[nodeOrigin] < allBaryBranchingID[c].size())
1355 tBranchID = allBaryBranchingID[c][treeMatching[nodeOrigin]];
1357 branchBaryNodeID->InsertNextTuple1(tBranchID);
1361 if(not isPersistenceDiagram) {
1362 int tBranchID = treeBranchingID[node];
1363 if(not trees[i]->isLeaf(node))
1364 tBranchID = treeBranchingID[nodeOrigin];
1365 branchNodeID->InsertNextTuple1(tBranchID);
1370 persistenceNode->InsertNextTuple1(
1371 trees[i]->getNodePersistence<dataType>(node));
1374 auto birthDeath = trees[i]->getBirthDeath<dataType>(node);
1375 pairBirthNode->InsertNextTuple1(std::get<0>(birthDeath));
1378 if(clusteringOutput and ShiftMode != 1) {
1379 if(treeMatching[node] < allBaryBranchingID[c].size()) {
1380 persistenceBaryNode->InsertTuple1(
1381 pointCount, barycenters[c]->getNodePersistence<dataType>(
1382 treeMatching[node]));
1383 persistenceBaryOrderNode->InsertTuple1(
1384 pointCount, baryPersistenceOrder[treeMatching[node]]);
1389 clusterIDNode->InsertNextTuple1(clusteringAssignment[i]);
1392 treeIDNode->InsertNextTuple1(i + iSampleOffset);
1396 = toAdd == 2 and toAddT == 1 and !trees[i]->isRoot(node);
1397 isDummyNode->InsertNextTuple1(isDummy);
1400 isInterpolatedTreeNode->InsertNextTuple1(isInterpolatedTree);
1403 bool isImportant =
false;
1404 isImportant = trees[i]->isImportantPair<dataType>(
1407 isImportantPairsNode->InsertNextTuple1(isImportant);
1410 treeNodeId->InsertNextTuple1(node);
1413 treeNodeIdOrigin->InsertNextTuple1(nodeOrigin);
1417 if(isPersistenceDiagram and !treesNodes.empty()
1418 and ShiftMode != 1) {
1419 double coord[3] = {0.0, 0.0, 0.0};
1420 getPoint(treesNodes[i], treesNodeCorrMesh[i][node], coord);
1421 coordinates->InsertNextTuple3(coord[0], coord[1], coord[2]);
1426 bool const isMultiPersPair
1427 = (trees[i]->isMultiPersPair(node)
1428 or trees[i]->isMultiPersPair(
1429 trees[i]->getNode(node)->getOrigin()));
1430 isMultiPersPairNode->InsertNextTuple1(isMultiPersPair);
1433 for(
unsigned int ca = 0; ca < customArrays.size(); ++ca)
1434 customArraysValues[ca].emplace_back(
1435 std::get<1>(customArrays[ca])[node]);
1436 for(
unsigned int ca = 0; ca < customIntArrays.size(); ++ca)
1437 customIntArraysValues[ca].emplace_back(
1438 std::get<1>(customIntArrays[ca])[node]);
1439 for(
unsigned int ca = 0; ca < customStringArrays.size(); ++ca)
1440 customStringArraysValues[ca].emplace_back(
1441 std::get<1>(customStringArrays[ca])[node]);
1450 if(isPersistenceDiagram and not embeddedDiagram) {
1451 vtkIdType pointIds[2];
1452 pointIds[0] = minBirthNode;
1453 pointIds[1] = maxBirthNode;
1454 vtkArcs->InsertNextCell(VTK_LINE, 2, pointIds);
1457 pairIdentifier->InsertNextTuple1(-1);
1458 pairType->InsertNextTuple1(-1);
1459 persistenceArc->InsertNextTuple1(-1);
1460 pairIsFinite->InsertNextTuple1(0);
1461 pairBirth->InsertNextTuple1(0);
1463 for(
unsigned int ca = 0; ca < customArrays.size(); ++ca)
1464 customCellArraysValues[ca].push_back(-1);
1465 for(
unsigned int ca = 0; ca < customIntArrays.size(); ++ca)
1466 customCellIntArraysValues[ca].push_back(-1);
1467 for(
unsigned int ca = 0; ca < customStringArrays.size(); ++ca)
1468 customCellStringArraysValues[ca].emplace_back(
"");
1470 isMultiPersPairArc->InsertNextTuple1(0);
1471 clusterIDArc->InsertNextTuple1(clusteringAssignment[i]);
1472 treeIDArc->InsertNextTuple1(i + iSampleOffset);
1473 isImportantPairsArc->InsertNextTuple1(0);
1474 branchBaryID->InsertNextTuple1(-1);
1475 percentMatchArc->InsertNextTuple1(100);
1485 if(OutputSegmentation and not PlanarLayout and treesSegmentation[i]) {
1486 vtkNew<vtkUnstructuredGrid> iTreesSegmentationCopy{};
1488 iTreesSegmentationCopy->DeepCopy(treesSegmentation[i]);
1490 iTreesSegmentationCopy->ShallowCopy(treesSegmentation[i]);
1491 auto iVkOutputSegmentationTemp
1492 = vtkUnstructuredGrid::SafeDownCast(iTreesSegmentationCopy);
1493 if(!iVkOutputSegmentationTemp
1494 or !iVkOutputSegmentationTemp->GetPoints()) {
1495 printWrn(
"Convert segmentation to vtkUnstructuredGrid.");
1496 vtkNew<vtkAppendFilter> appendFilter2{};
1497 appendFilter2->AddInputData(treesSegmentation[i]);
1498 appendFilter2->Update();
1499 iVkOutputSegmentationTemp->ShallowCopy(appendFilter2->GetOutput());
1501 if(ShiftMode != -1) {
1503 p < iVkOutputSegmentationTemp->GetPoints()->GetNumberOfPoints();
1506 = iVkOutputSegmentationTemp->GetPoints()->GetPoint(p);
1510 iVkOutputSegmentationTemp->GetPoints()->SetPoint(p, point);
1513 appendFilter->AddInputData(iVkOutputSegmentationTemp);
1518 for(
int i = persistenceBaryNode->GetNumberOfTuples(); i < pointCount; ++i)
1519 persistenceBaryNode->InsertNextTuple1(0);
1520 for(
int i = persistenceBaryArc->GetNumberOfTuples(); i < cellCount; ++i)
1521 persistenceBaryArc->InsertNextTuple1(0);
1522 for(
int i = persistenceBaryOrderNode->GetNumberOfTuples(); i < pointCount;
1524 persistenceBaryOrderNode->InsertNextTuple1(0);
1525 for(
int i = persistenceBaryOrderArc->GetNumberOfTuples(); i < cellCount;
1527 persistenceBaryOrderArc->InsertNextTuple1(0);
1535 customIntArrays, customIntArraysValues, vtkOutputNode, 1, 0);
1537 customStringArrays, customStringArraysValues, vtkOutputNode, 2, 0);
1540 vtkOutputNode->SetPoints(points);
1541 vtkOutputNode->GetPointData()->AddArray(criticalType);
1542 vtkOutputNode->GetPointData()->AddArray(persistenceNode);
1543 vtkOutputNode->GetPointData()->AddArray(clusterIDNode);
1544 vtkOutputNode->GetPointData()->AddArray(treeIDNode);
1545 vtkOutputNode->GetPointData()->AddArray(trueNodeID);
1546 vtkOutputNode->GetPointData()->AddArray(vertexID);
1547 vtkOutputNode->GetPointData()->AddArray(isImportantPairsNode);
1548 vtkOutputNode->GetPointData()->AddArray(isMultiPersPairNode);
1549 if(not isPersistenceDiagram) {
1550 vtkOutputNode->GetPointData()->AddArray(nodeID);
1551 vtkOutputNode->GetPointData()->AddArray(branchNodeID);
1552 vtkOutputNode->GetPointData()->AddArray(isDummyNode);
1555 vtkOutputNode->GetPointData()->AddArray(scalar);
1556 if(clusteringOutput and ShiftMode != 1) {
1557 vtkOutputNode->GetPointData()->AddArray(branchBaryNodeID);
1558 vtkOutputNode->GetPointData()->AddArray(persistenceBaryNode);
1559 vtkOutputNode->GetPointData()->AddArray(persistenceBaryOrderNode);
1561 if(foundOneInterpolatedTree)
1562 vtkOutputNode->GetPointData()->AddArray(isInterpolatedTreeNode);
1564 vtkOutputNode->GetPointData()->AddArray(percentMatch);
1565 if(outputTreeNodeIndex)
1566 vtkOutputNode->GetPointData()->AddArray(treeNodeId);
1567 if(isPersistenceDiagram) {
1568 vtkOutputNode->GetPointData()->AddArray(treeNodeIdOrigin);
1569 if(!treesNodes.empty() and ShiftMode != 1)
1570 vtkOutputNode->GetPointData()->AddArray(coordinates);
1572 vtkOutputNode->GetPointData()->AddArray(pairBirthNode);
1578 customIntArrays, customCellIntArraysValues, vtkArcs, 1, 1);
1580 customStringArrays, customCellStringArraysValues, vtkArcs, 2, 1);
1583 vtkArcs->SetPoints(points);
1584 vtkArcs->GetCellData()->AddArray(persistenceArc);
1585 vtkArcs->GetCellData()->AddArray(clusterIDArc);
1586 vtkArcs->GetCellData()->AddArray(treeIDArc);
1587 vtkArcs->GetCellData()->AddArray(isImportantPairsArc);
1588 vtkArcs->GetCellData()->AddArray(isMultiPersPairArc);
1589 if(not isPersistenceDiagram) {
1590 vtkArcs->GetCellData()->AddArray(isDummyArc);
1591 vtkArcs->GetCellData()->AddArray(branchID);
1592 vtkArcs->GetCellData()->AddArray(upNodeId);
1593 vtkArcs->GetCellData()->AddArray(downNodeId);
1595 if(clusteringOutput and ShiftMode != 1) {
1596 vtkArcs->GetCellData()->AddArray(branchBaryID);
1597 vtkArcs->GetCellData()->AddArray(persistenceBaryArc);
1598 vtkArcs->GetCellData()->AddArray(persistenceBaryOrderArc);
1600 if(foundOneInterpolatedTree)
1601 vtkArcs->GetCellData()->AddArray(isInterpolatedTreeArc);
1603 vtkArcs->GetCellData()->AddArray(percentMatchArc);
1604 if(isPersistenceDiagram) {
1605 vtkArcs->GetCellData()->AddArray(pairIdentifier);
1606 vtkArcs->GetCellData()->AddArray(pairType);
1607 vtkArcs->GetCellData()->AddArray(pairIsFinite);
1609 vtkArcs->GetCellData()->AddArray(pairBirth);
1610 if(vtkOutputArc == vtkOutputNode)
1611 vtkArcs->GetPointData()->ShallowCopy(vtkOutputNode->GetPointData());
1613 vtkArcs->GetPointData()->AddArray(scalar);
1614 vtkOutputArc->ShallowCopy(vtkArcs);
1617 if(OutputSegmentation and not PlanarLayout
1618 and appendFilter->GetNumberOfInputConnections(0) != 0) {
1619 appendFilter->SetMergePoints(
false);
1620 appendFilter->Update();
1621 vtkOutputSegmentation->ShallowCopy(appendFilter->GetOutput());