TTK
Loading...
Searching...
No Matches
ttkMergeTreeVisualization.h
Go to the documentation of this file.
1
7
8#pragma once
9
10#include <FTMTree.h>
12
13#include <ttkAlgorithm.h>
14
15// VTK Includes
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>
23#include <vtkPoints.h>
24#include <vtkStringArray.h>
25#include <vtkUnstructuredGrid.h>
26
28private:
29 // redefine types
30 using idNode = ttk::ftm::idNode;
31 using SimplexId = ttk::SimplexId;
33
34 // Visualization parameters
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;
45
46 // Shift mode
47 // -1: None ; 0: Star ; 1: Star Barycenter ; 2: Line ; 3: Double Line
48 int ShiftMode = 0;
49
50 // Offset
51 int iSampleOffset = 0;
52 int noSampleOffset = 0;
53 double prevXMaxOffset = 0;
54
55 // Print only one tree
56 int printTreeId = -1; // -1 for all
57 int printClusterId = -1; // -1 for all
58
59 // Barycenter position according alpha
60 bool BarycenterPositionAlpha = false;
61 double Alpha = 0.5;
62
63 // Used for critical type and for point coordinates
64 std::vector<vtkUnstructuredGrid *> treesNodes;
65 std::vector<std::vector<int>>
66 treesNodeCorrMesh; // used to access treesNodes given input trees
67
68 // Segmentation
69 std::vector<vtkDataSet *> treesSegmentation;
70
71 // Clustering output
72 std::vector<int> clusteringAssignment;
73 std::vector<std::vector<std::vector<std::tuple<idNode, idNode, double>>>>
74 outputMatchingBarycenter;
75
76 // Barycenter output
77 std::vector<std::vector<float>> allBaryPercentMatch;
78
79 // Temporal Subsampling Output
80 std::vector<bool> interpolatedTrees;
81
82 // Output
83 vtkUnstructuredGrid *vtkOutputNode{};
84 vtkUnstructuredGrid *vtkOutputArc{};
85 vtkDataSet *vtkOutputSegmentation{};
86
87 // Matching output
88 vtkUnstructuredGrid *vtkOutputNode1{}, *vtkOutputNode2{}; // input data
89 std::vector<std::vector<SimplexId>> nodeCorr1, nodeCorr2;
90 vtkUnstructuredGrid *vtkOutputMatching{}; // output
91
92 // Custom array
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>>>
96 customStringArrays;
97
98 // Filled by the algorithm
99 std::vector<std::vector<SimplexId>> nodeCorr;
100 std::vector<double> clusterShift;
101 double prevXMax = 0;
102
103public:
105 ;
106 ~ttkMergeTreeVisualization() override = default;
107 ;
108
109 // ==========================================================================
110 // Getter / Setter
111 // ==========================================================================
112 // Visualization parameters
113 void setPlanarLayout(bool b) {
114 PlanarLayout = b;
115 }
116 void setDimensionSpacing(double d) {
117 DimensionSpacing = d;
118 }
120 DimensionToShift = i;
121 }
123 OutputSegmentation = b;
124 }
125 void setShiftMode(int mode) {
126 ShiftMode = mode;
127 }
128 void setMaximumImportantPairs(int maxPairs) {
129 MaximumImportantPairs = maxPairs;
130 }
131 void setMinimumImportantPairs(int minPairs) {
132 MinimumImportantPairs = minPairs;
133 }
134
135 void setOutputTreeNodeId(int doOutput) {
136 outputTreeNodeIndex = doOutput;
137 }
138
139 void setIsPersistenceDiagram(bool isPD) {
140 isPersistenceDiagram = isPD;
141 }
142 void setConvertedToDiagram(bool converted) {
143 convertedToDiagram = converted;
144 }
145 void setIsPDSadMax(bool isSadMax) {
146 isPDSadMax = isSadMax;
147 }
148
149 // Offset
150 void setISampleOffset(int offset) {
151 iSampleOffset = offset;
152 }
153 void setNoSampleOffset(int offset) {
154 noSampleOffset = offset;
155 }
156 void setPrevXMaxOffset(double offset) {
157 prevXMaxOffset = offset;
158 }
159
160 // Print only one tree
161 void setPrintTreeId(int id) {
162 printTreeId = id;
163 }
164 void setPrintClusterId(int id) {
165 printClusterId = id;
166 }
167
168 // Barycenter position according alpha
170 BarycenterPositionAlpha = pos;
171 }
172 void setAlpha(double alpha) {
173 Alpha = alpha;
174 }
175
176 // Used for critical type and if not planar layout for point coordinates
177 void setTreesNodes(std::vector<vtkUnstructuredGrid *> &nodes) {
178 treesNodes = nodes;
179 }
180 void setTreesNodeCorrMesh(std::vector<std::vector<int>> &nodeCorrMesh) {
181 treesNodeCorrMesh = nodeCorrMesh;
182 }
183 void setTreesNodes(vtkUnstructuredGrid *nodes) {
184 treesNodes.clear();
185 treesNodes.emplace_back(nodes);
186 }
187 void setTreesNodeCorrMesh(std::vector<int> &nodeCorrMesh) {
188 treesNodeCorrMesh.clear();
189 treesNodeCorrMesh.emplace_back(nodeCorrMesh);
190 }
191
192 // Segmentation
193 void setTreesSegmentation(std::vector<vtkDataSet *> &segmentation) {
194 treesSegmentation = segmentation;
195 }
196 void setTreesSegmentation(vtkDataSet *segmentation) {
197 treesSegmentation.clear();
198 treesSegmentation.emplace_back(segmentation);
199 }
200
201 // Clustering output
202 void setClusteringAssignment(std::vector<int> &asgn) {
203 clusteringAssignment = asgn;
204 }
206 std::vector<std::vector<std::vector<std::tuple<idNode, idNode, double>>>>
207 &matching) {
208 outputMatchingBarycenter = matching;
209 }
210
211 // Barycenter output
212 std::vector<std::vector<float>> getAllBaryPercentMatch() {
213 return allBaryPercentMatch;
214 }
215 void
216 setAllBaryPercentMatch(std::vector<std::vector<float>> &baryPercentMatch) {
217 allBaryPercentMatch = baryPercentMatch;
218 }
219
220 // Temporal Subsampling Output
221 void setInterpolatedTrees(std::vector<bool> &isInterpolatedTrees) {
222 interpolatedTrees = isInterpolatedTrees;
223 }
224
225 // Output
226 void setVtkOutputNode(vtkUnstructuredGrid *vtkNode) {
227 vtkOutputNode = vtkNode;
228 }
229 void setVtkOutputArc(vtkUnstructuredGrid *vtkArc) {
230 vtkOutputArc = vtkArc;
231 }
232 void setVtkOutputSegmentation(vtkDataSet *vtkSegmentation) {
233 vtkOutputSegmentation = vtkSegmentation;
234 }
235
236 // Matching output
237 void setVtkOutputNode1(vtkUnstructuredGrid *vtkNode1) {
238 vtkOutputNode1 = vtkNode1;
239 }
240 void setVtkOutputNode2(vtkUnstructuredGrid *vtkNode2) {
241 vtkOutputNode2 = vtkNode2;
242 }
243 void setNodeCorr1(std::vector<std::vector<SimplexId>> &nodeCorrT) {
244 nodeCorr1 = nodeCorrT;
245 }
246 void setNodeCorr2(std::vector<std::vector<SimplexId>> &nodeCorrT) {
247 nodeCorr2 = nodeCorrT;
248 }
249 void setVtkOutputMatching(vtkUnstructuredGrid *vtkMatching) {
250 vtkOutputMatching = vtkMatching;
251 }
253 std::vector<std::tuple<idNode, idNode, double>> &matching) {
254 outputMatchingBarycenter.resize(1);
255 outputMatchingBarycenter[0].resize(1);
256 outputMatchingBarycenter[0][0] = matching;
257 }
258
259 // Custom array
260 void addCustomArray(std::string &name, std::vector<double> &vec) {
261 customArrays.emplace_back(name, vec);
262 }
263 void addCustomIntArray(std::string &name, std::vector<int> &vec) {
264 customIntArrays.emplace_back(name, vec);
265 }
266 void addCustomStringArray(std::string &name, std::vector<std::string> &vec) {
267 customStringArrays.emplace_back(name, vec);
268 }
270 customArrays.clear();
271 }
273 customIntArrays.clear();
274 }
276 customStringArrays.clear();
277 }
282 }
283
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,
289 int type,
290 int output) {
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;
296 if(type == 0)
297 customArrayVtk = customDoubleArrayVtk;
298 else if(type == 1)
299 customArrayVtk = customIntArrayVtk;
300 else
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) {
305 // Add value depending on type (vtkAbstractArray can not be used here)
306 if(type == 0) {
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);
312 } else {
313 std::string stringValue
314 = (*(std::vector<std::string> *)&(cArraysValues[i]))[j];
315 customStringArrayVtk->SetValue(j, stringValue);
316 }
317 }
318 if(output == 0)
319 vtkOutput->GetPointData()->AddArray(customArrayVtk);
320 else
321 vtkOutput->GetCellData()->AddArray(customArrayVtk);
322 }
323 }
324
325 void getTreeNodeIdRev(vtkDataArray *treeNodeIdArray,
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;
334 }
335
336 void copyPointData(vtkUnstructuredGrid *treeNodes,
337 std::vector<int> &nodeCorrT) {
338 if(!treeNodes)
339 return;
340
341 auto treeNodeIdArray = treeNodes->GetPointData()->GetArray("TreeNodeId");
342 std::vector<int> treeNodeIdRev;
343 if(treeNodeIdArray)
344 getTreeNodeIdRev(treeNodeIdArray, treeNodeIdRev);
345
346 for(int i = 0; i < treeNodes->GetPointData()->GetNumberOfArrays(); ++i) {
347 auto dataArray
348 = vtkDataArray::SafeDownCast(treeNodes->GetPointData()->GetArray(i));
349 auto stringArray
350 = vtkStringArray::SafeDownCast(treeNodes->GetPointData()->GetArray(i));
351 vtkAbstractArray *array;
352 if(dataArray)
353 array = dataArray;
354 else if(stringArray)
355 array = stringArray;
356 else
357 continue;
358 auto vecSize = (nodeCorrT.size() == 0 ? array->GetNumberOfValues()
359 : nodeCorrT.size());
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]);
364 if(treeNodeIdArray)
365 toGet = (nodeCorrT.size() == 0 ? treeNodeIdRev[j]
366 : treeNodeIdRev[nodeCorrT[j]]);
367 auto value = array->GetVariantValue(toGet);
368 if(dataArray)
369 vec[j] = value.ToDouble();
370 else
371 vecString[j] = value.ToString();
372 }
373 std::string name{array->GetName()};
374 if(dataArray)
375 addCustomArray(name, vec);
376 else
377 addCustomStringArray(name, vecString);
378 }
379 }
380 void copyPointData(vtkUnstructuredGrid *treeNodes) {
381 std::vector<int> nodeCorrT;
382 copyPointData(treeNodes, nodeCorrT);
383 }
384
385 // Filled by the algorithm
386 std::vector<std::vector<SimplexId>> getNodeCorr() {
387 return nodeCorr;
388 }
389 std::vector<double> getClusterShift() {
390 return clusterShift;
391 }
392 double getPrevXMax() {
393 return prevXMax;
394 }
395
396 // ==========================================================================
397 // Matching Visualization
398 // ==========================================================================
399 template <class dataType>
401 std::vector<FTMTree_MT *> trees{tree1, tree2};
402 std::vector<FTMTree_MT *> barycenters;
403
404 makeMatchingOutput<dataType>(trees, barycenters);
405 }
406
407 template <class dataType>
408 void makeMatchingOutput(std::vector<FTMTree_MT *> &trees,
409 std::vector<FTMTree_MT *> &barycenters) {
410 int numInputs = trees.size();
411 int NumberOfBarycenters = barycenters.size();
412 bool clusteringOutput = (NumberOfBarycenters != 0);
413 NumberOfBarycenters
414 = std::max(NumberOfBarycenters, 1); // to always enter the outer loop
415 if(not clusteringOutput)
416 numInputs = 1;
417
418 vtkNew<vtkUnstructuredGrid> vtkMatching{};
419 vtkNew<vtkPoints> pointsM{};
420
421 // Fields
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");
434
435 vtkNew<vtkFloatArray> matchingPercentMatch{};
436 matchingPercentMatch->SetName("MatchingPercentMatch");
437
438 // Iterate through clusters and trees
439 printMsg(
440 "// Iterate through clusters and trees", ttk::debug::Priority::VERBOSE);
441 int count = 0;
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)))
448 continue;
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);
455 FTMTree_MT *tree1;
456 FTMTree_MT *tree2 = trees[i];
457 if(not clusteringOutput) {
458 tree1 = trees[0];
459 tree2 = trees[1];
460 } else
461 tree1 = barycenters[c];
462
463 // Get first point
464 printMsg("// Get first point", ttk::debug::Priority::VERBOSE);
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;
470
471 // Get second point
472 printMsg("// Get second point", ttk::debug::Priority::VERBOSE);
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;
478
479 // Add cell
481 vtkMatching->InsertNextCell(VTK_LINE, 2, pointIds);
482
483 // Add arc matching percentage
484 printMsg(
485 "// Add arc matching percentage", ttk::debug::Priority::VERBOSE);
486 if(allBaryPercentMatch.size() != 0)
487 matchingPercentMatch->InsertNextTuple1(
488 allBaryPercentMatch[c][tree1NodeId]);
489
490 // Add tree1 and tree2 node ids
491 printMsg(
492 "// Add tree1 and tree2 node ids", ttk::debug::Priority::VERBOSE);
493 tree1NodeIdField->InsertNextTuple1(pointToGet1);
494 tree2NodeIdField->InsertNextTuple1(pointToGet2);
495
496 // Add matching ID
497 matchingID->InsertNextTuple1(count);
498
499 // Add matching type
500 printMsg("// Add matching type", ttk::debug::Priority::VERBOSE);
501 int thisType = 0;
502 int tree1NodeDown
503 = tree1->getNode(tree1NodeId)->getNumberOfDownSuperArcs();
504 int tree1NodeUp
505 = tree1->getNode(tree1NodeId)->getNumberOfUpSuperArcs();
506 int tree2NodeDown
507 = tree2->getNode(tree2NodeId)->getNumberOfDownSuperArcs();
508 int tree2NodeUp
509 = tree2->getNode(tree2NodeId)->getNumberOfUpSuperArcs();
510 if(tree1NodeDown != 0 and tree1NodeUp != 0 and tree2NodeDown != 0
511 and tree2NodeUp != 0)
512 thisType = 1; // Saddle to Saddle
513 if(tree1NodeDown == 0 and tree1NodeUp != 0 and tree2NodeDown == 0
514 and tree2NodeUp != 0)
515 thisType = 2; // Leaf to leaf
516 if(tree1NodeDown != 0 and tree1NodeUp == 0 and tree2NodeDown != 0
517 and tree2NodeUp == 0)
518 thisType = 3; // Root to root
519 matchingType->InsertNextTuple1(thisType);
520
521 // Add mean matched persistence
522 printMsg(
523 "// Add mean matched persistence", ttk::debug::Priority::VERBOSE);
524 double tree1Pers = tree1->getNodePersistence<dataType>(tree1NodeId);
525 double tree2Pers = tree2->getNodePersistence<dataType>(tree2NodeId);
526 double meanPersistence = (tree1Pers + tree2Pers) / 2;
527 matchPers->InsertNextTuple1(meanPersistence);
528
529 // Add cost
530 costArray->InsertNextTuple1(cost);
531
532 count++;
533 }
534 }
535 }
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);
546 }
547
548 // ==========================================================================
549 // Trees Visualization
550 // ==========================================================================
551 template <class dataType>
553 std::vector<FTMTree_MT *> trees{tree1};
554
555 makeTreesOutput<dataType>(trees);
556 }
557
558 template <class dataType>
559 void makeTreesOutput(FTMTree_MT *tree1, FTMTree_MT *tree2) {
560 std::vector<FTMTree_MT *> trees{tree1, tree2};
561
562 makeTreesOutput<dataType>(trees);
563 }
564
565 template <class dataType>
566 void makeTreesOutput(std::vector<FTMTree_MT *> &trees) {
567 std::vector<FTMTree_MT *> barycenters;
568 clusteringAssignment.clear();
569 clusteringAssignment.resize(trees.size(), 0);
570
571 makeTreesOutput<dataType>(trees, barycenters);
572 }
573
574 template <class dataType>
575 void makeTreesOutput(std::vector<FTMTree_MT *> &trees,
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);
581 NumberOfBarycenters
582 = std::max(NumberOfBarycenters, 1); // to always enter the outer loop
583 bool embeddedDiagram = not PlanarLayout and isPersistenceDiagram;
584
585 // TreeNodeIdRev
586 for(int i = 0; i < numInputs; ++i) {
587 if(i < (int)treesNodes.size() and treesNodes[i]) {
588 auto treeNodeIdArray
589 = treesNodes[i]->GetPointData()->GetArray("TreeNodeId");
590 if(treeNodeIdArray) {
591 std::vector<int> treeNodeIdRev;
592 getTreeNodeIdRev(treeNodeIdArray, treeNodeIdRev);
593 for(unsigned int j = 0; j < treesNodeCorrMesh[i].size(); ++j)
594 treesNodeCorrMesh[i][j] = treeNodeIdRev[treesNodeCorrMesh[i][j]];
595 }
596 }
597 }
598
599 // Bounds
600 printMsg("Bounds and branching", ttk::debug::Priority::VERBOSE);
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)
610 allBounds[i]
611 = getRealBounds(treesNodes[i], trees[i], treesNodeCorrMesh[i]);
612 else {
613 double bounds[6];
614 treesNodes[i]->GetBounds(bounds);
615 allBounds[i] = std::make_tuple(
616 bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
617 }
618 } else {
619 allBounds[i] = allBounds[0];
620 }
621 }
622
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) {
628 allBaryBounds[c] = getMaximalBounds(allBounds, clusteringAssignment, c);
629 if(not isPersistenceDiagram)
630 barycenters[c]->getTreeBranching(
631 allBaryBranching[c], allBaryBranchingID[c]);
632 }
633 if(not clusteringOutput)
634 allBaryBounds.emplace_back(
635 getMaximalBounds(allBounds, clusteringAssignment, 0));
636
637 // ----------------------------------------------------------------------
638 // Make Trees Output
639 // ----------------------------------------------------------------------
640 printMsg("--- Make Trees Output", ttk::debug::Priority::VERBOSE);
641 std::vector<FTMTree_MT *> treesOri(trees);
642 if(ShiftMode == 1) { // Star Barycenter
643 trees.clear();
644 clusteringAssignment.clear();
645 for(unsigned int j = 0; j < barycenters.size(); ++j) {
646 trees.emplace_back(barycenters[j]);
647 clusteringAssignment.emplace_back(j);
648 }
649 numInputs = trees.size();
650 }
651 // - Declare VTK arrays
652 vtkNew<vtkUnstructuredGrid> vtkArcs{};
653 vtkNew<vtkPoints> points{};
654
655 // Node fields
656 vtkNew<vtkIntArray> criticalType{};
657 criticalType->SetName(ttk::PersistenceCriticalTypeName);
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"); // Simplex Id
672 vtkNew<vtkIntArray> trueNodeID{};
673 trueNodeID->SetName("TrueNodeId");
674 vtkNew<vtkIntArray> vertexID{};
675 vertexID->SetName(
676 (isPersistenceDiagram ? ttk::VertexScalarFieldName : "VertexId"));
677
678 vtkNew<vtkIntArray> treeIDNode{};
679 treeIDNode->SetName("TreeID");
680 vtkNew<vtkIntArray> branchBaryNodeID{};
681 branchBaryNodeID->SetName("BranchBaryNodeID");
682 vtkNew<vtkIntArray> isInterpolatedTreeNode{};
683 isInterpolatedTreeNode->SetName("isInterpolatedTree");
684
685 vtkNew<vtkFloatArray> percentMatch{};
686 percentMatch->SetName("PercentMatchNode");
687 vtkNew<vtkFloatArray> persistenceBaryNode{};
688 persistenceBaryNode->SetName("PersistenceBarycenter");
689 vtkNew<vtkIntArray> persistenceBaryOrderNode{};
690 persistenceBaryOrderNode->SetName("PersistenceBarycenterOrder");
691
692 vtkNew<vtkDoubleArray> pairPersistenceNode{};
693 pairPersistenceNode->SetName(ttk::PersistenceName);
694 vtkNew<vtkDoubleArray> pairBirthNode{};
695 pairBirthNode->SetName(ttk::PersistenceBirthName);
696
697 vtkNew<vtkFloatArray> treeNodeId{};
698 treeNodeId->SetName("TreeNodeId");
699
700 vtkNew<vtkFloatArray> treeNodeIdOrigin{};
701 treeNodeIdOrigin->SetName("TreeNodeIdOrigin");
702 vtkNew<vtkDoubleArray> coordinates{};
703 coordinates->SetName(ttk::PersistenceCoordinatesName);
704 coordinates->SetNumberOfComponents(3);
705
706 vtkNew<vtkIntArray> isMultiPersPairNode{};
707 isMultiPersPairNode->SetName("isMultiPersPairNode");
708
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());
713
714 // Arc fields
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");
729
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");
736
737 vtkNew<vtkFloatArray> percentMatchArc{};
738 percentMatchArc->SetName("PercentMatchArc");
739 vtkNew<vtkFloatArray> persistenceBaryArc{};
740 persistenceBaryArc->SetName("PersistenceBarycenter");
741 vtkNew<vtkIntArray> persistenceBaryOrderArc{};
742 persistenceBaryOrderArc->SetName("PersistenceBarycenterOrder");
743
744 vtkNew<vtkIntArray> pairIdentifier{};
745 pairIdentifier->SetName(ttk::PersistencePairIdentifierName);
746 vtkNew<vtkIntArray> pairType{};
747 pairType->SetName(ttk::PersistencePairTypeName);
748 vtkNew<vtkIntArray> pairIsFinite{};
749 pairIsFinite->SetName(ttk::PersistenceIsFinite);
750 vtkNew<vtkDoubleArray> pairPersistence{};
751 pairPersistence->SetName(ttk::PersistenceName);
752 vtkNew<vtkDoubleArray> pairBirth{};
753 pairBirth->SetName(ttk::PersistenceBirthName);
754
755 vtkNew<vtkIntArray> isMultiPersPairArc{};
756 isMultiPersPairArc->SetName("isMultiPersPairArc");
757
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());
764
765 // Segmentation
766 vtkNew<vtkAppendFilter> appendFilter{};
767
768 // Internal data
769 int cellCount = 0;
770 int pointCount = 0;
771 bool foundOneInterpolatedTree = false;
772 nodeCorr.clear();
773 nodeCorr.resize(numInputs);
774 clusterShift.clear();
775 clusterShift.resize(NumberOfBarycenters, 0);
776 allBaryPercentMatch.clear();
777 allBaryPercentMatch.resize(NumberOfBarycenters);
778
779 // --------------------------------------------------------
780 // Iterate through all clusters
781 // --------------------------------------------------------
782 printMsg("Iterate through all clusters", ttk::debug::Priority::VERBOSE);
783 double importantPairsOriginal = importantPairs_;
784 for(int c = 0; c < NumberOfBarycenters; ++c) {
785
786 // Get persistence order
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>>
791 pairsBary;
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;
797 }
798 }
799
800 // Get radius
801 printMsg("// Get radius", ttk::debug::Priority::VERBOSE);
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)
810 continue;
811 noSample += 1;
812 }
813 double radius = delta_max * 2 * DimensionSpacing;
814 int iSample = 0 + iSampleOffset - 1;
815
816 if(c < NumberOfBarycenters - 1)
817 clusterShift[c + 1] = radius * 4 + clusterShift[c];
818
819 // Line/Double line attributes
820 prevXMax = 0 + prevXMaxOffset;
821 std::vector<double> allPrevXMax;
822 double prevYMax = std::numeric_limits<double>::lowest();
823
824 // ------------------------------------------
825 // Iterate through all trees of this cluster
826 // ------------------------------------------
827 printMsg("Iterate through all trees of this cluster",
829 for(int i = 0; i < numInputs; ++i) {
830 if(clusteringAssignment[i] != c)
831 continue;
832
833 iSample += 1;
834
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)))
839 continue;
840
841 // Manage important pairs threshold
842 importantPairs_ = importantPairsOriginal;
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;
848 firstIndex
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;
853 importantPairs_ = std::max(importantPairs_, tempThreshold);
854 }
855 if(MinimumImportantPairs > 0) {
856 int firstIndex = pairs.size() - MinimumImportantPairs;
857 firstIndex
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;
862 importantPairs_ = std::min(importantPairs_, tempThreshold);
863 }
864 }
865
866 // Get is interpolated tree (temporal subsampling)
867 bool isInterpolatedTree = false;
868 if(interpolatedTrees.size() != 0)
869 isInterpolatedTree = interpolatedTrees[i];
870 foundOneInterpolatedTree |= isInterpolatedTree;
871
872 // Get branching
873 printMsg("// Get branching", ttk::debug::Priority::VERBOSE);
874 std::vector<idNode> treeBranching;
875 std::vector<int> treeBranchingID;
876 if(not isPersistenceDiagram)
877 trees[i]->getTreeBranching(treeBranching, treeBranchingID);
878
879 // Get shift
881 double angle = 360.0 / noSample * iSample;
882 double pi = M_PI;
883 double diff_x = 0, diff_y = 0;
884 double alphaShift
885 = BarycenterPositionAlpha ? (-radius + 2 * radius * Alpha) * -1 : 0;
886 switch(ShiftMode) {
887 case -1:
888 diff_x = 0.0;
889 diff_y = 0.0;
890 break;
891 case 0: // Star
892 diff_x
893 = -1 * radius * std::cos(-1 * angle * pi / 180) + clusterShift[c];
894 diff_y = -1 * radius * std::sin(-1 * angle * pi / 180);
895 break;
896 case 1: // Star Barycenter
897 diff_x = clusterShift[c] + alphaShift;
898 diff_y = 0;
899 break;
900 case 2: // Line
901 diff_x = prevXMax + radius;
902 break;
903 case 3: // Double Line
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;
908 } else
909 allPrevXMax.emplace_back(prevXMax);
910 break;
911 default:
912 break;
913 }
914
915 // Get dimension shift
916 printMsg("// Get dimension shift", ttk::debug::Priority::VERBOSE);
917 double diff_z = PlanarLayout ? 0 : -std::get<4>(allBounds[i]);
918 // TODO DimensionToShift for Planar Layout
919 if(not PlanarLayout)
920 if(DimensionToShift != 0) { // is not X
921 if(DimensionToShift == 2) // is Z
922 diff_z = diff_x;
923 else if(DimensionToShift == 1) // is Y
924 diff_y = diff_x;
925 diff_x = -std::get<0>(allBounds[i]);
926 }
927
928 // Planar layout
929 printMsg("// Planar Layout", ttk::debug::Priority::VERBOSE);
930 std::vector<float> layout;
931 if(PlanarLayout) {
932 double refPersistence;
933 if(clusteringOutput)
934 refPersistence = barycenters[0]->getNodePersistence<dataType>(
935 barycenters[0]->getRoot());
936 else
937 refPersistence
938 = trees[0]->getNodePersistence<dataType>(trees[0]->getRoot());
939 if(not isPersistenceDiagram)
940 treePlanarLayout<dataType>(
941 trees[i], allBaryBounds[c], refPersistence, layout);
942 else {
943 persistenceDiagramPlanarLayout<dataType>(trees[i], layout);
944 }
945 }
946
947 // Internal arrays
948 printMsg("// Internal arrays", ttk::debug::Priority::VERBOSE);
949 int cptNode = 0;
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);
958 // _ m[i][j] contains the node in treesOri[j] matched to the node i in
959 // the barycenter
960 std::vector<std::vector<idNode>> baryMatching(
961 trees[i]->getNumberOfNodes(),
962 std::vector<idNode>(
963 numInputsOri, std::numeric_limits<idNode>::max()));
964 if(ShiftMode == 1) {
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);
969 }
970 double minBirth = std::numeric_limits<double>::max(),
971 maxBirth = std::numeric_limits<double>::lowest();
972 SimplexId minBirthNode = 0, maxBirthNode = 0;
973
974 // ----------------------------
975 // Tree traversal
976 // ----------------------------
977 printMsg("// Tree traversal", ttk::debug::Priority::VERBOSE);
978 std::queue<idNode> queue;
979 queue.emplace(trees[i]->getRoot());
980 while(!queue.empty()) {
981 idNode node = queue.front();
982 queue.pop();
983 idNode nodeOrigin = trees[i]->getNode(node)->getOrigin();
984
985 // Push children to the queue
986 printMsg(
987 "// Push children to the queue", ttk::debug::Priority::VERBOSE);
988 std::vector<idNode> children;
989 trees[i]->getChildren(node, children);
990 for(auto child : children)
991 queue.emplace(child);
992
993 // --------------
994 // Insert point
995 // --------------
996 auto getPoint
997 = [&](vtkUnstructuredGrid *vtu, int pointID, double(&point)[3]) {
998 if(not vtu)
999 return;
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];
1004 } else {
1005 for(int k = 0; k < 3; ++k) {
1006 auto array = vtu->GetPointData()->GetArray(
1008 if(array)
1009 point[k] += array->GetComponent(pointID, k);
1010 }
1011 }
1012 };
1013
1014 printMsg("// Get and insert point", ttk::debug::Priority::VERBOSE);
1015 int nodeMesh = -1;
1016 int nodeMeshTreeIndex = -1;
1017 double noMatched = 0.0;
1018 double point[3] = {0, 0, 0};
1019 if(ShiftMode == 1) { // Star barycenter
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);
1025 noMatched += 1;
1026 nodeMeshTreeIndex = j;
1027 }
1028 }
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);
1036 }
1037 if(PlanarLayout) {
1038 layoutCorr[node] = cptNode;
1039 point[0] = layout[cptNode];
1040 point[1] = layout[cptNode + 1];
1041 point[2] = 0;
1042 cptNode += 2;
1043 }
1044 point[0] += diff_x;
1045 point[1] += diff_y;
1046 point[2] += diff_z;
1047
1048 // Bary percentage matching
1049 if(ShiftMode == 1) { // Star Barycenter
1050 float percentMatchT = noMatched * 100 / numInputs;
1051 allBaryPercentMatch[c][node] = percentMatchT;
1052 }
1053
1054 // Get x Max and y Min for next iteration if needed (double line mode)
1055 prevXMax = std::max(prevXMax, point[0]);
1056 if(ShiftMode == 3) { // Double line
1057 if(i < numInputs / 2)
1058 prevYMax = std::max(prevYMax, point[1]);
1059 if(i == int(numInputs / 2) - 1)
1060 prevXMax = 0;
1061 }
1062
1063 // TODO too many dummy nodes are created
1064 bool dummyNode
1065 = PlanarLayout and not branchDecompositionPlanarLayout_
1066 and (!trees[i]->isRoot(node) or isPersistenceDiagram);
1067 dummyNode = dummyNode or embeddedDiagram;
1068 if(dummyNode) {
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())
1074 getPoint(
1075 treesNodes[i], treesNodeCorrMesh[i][nodeOrigin], pointToAdd);
1076 } else {
1077 if(not isPersistenceDiagram) {
1078 // will be modified when processing son
1079 std::copy(
1080 std::begin(point), std::end(point), std::begin(pointToAdd));
1081 } else {
1082 double pdPoint[3] = {
1083 point[0],
1084 point[1]
1085 - (layout[layoutCorr[node] + 1] - layout[layoutCorr[node]]),
1086 0};
1087 std::copy(std::begin(pdPoint), std::end(pdPoint),
1088 std::begin(pointToAdd));
1089 }
1090 }
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];
1097 }
1098 if(layout[layoutCorr[node]] > maxBirth) {
1099 maxBirth = layout[layoutCorr[node]];
1100 maxBirthNode = treeDummySimplexId[node];
1101 }
1102 }
1103 }
1104 }
1105 SimplexId nextPointId = points->InsertNextPoint(point);
1106 treeSimplexId[node] = nextPointId;
1107 nodeCorr[i][node] = nextPointId;
1108 if(dummyNode)
1109 nodeCorr[i][node] = treeDummySimplexId[node];
1110 if(isPersistenceDiagram)
1111 nodeCorr[i][node] = nextPointId;
1112
1113 idNode nodeBranching
1114 = ((PlanarLayout and branchDecompositionPlanarLayout_)
1115 or isPersistenceDiagram
1116 ? node
1117 : treeBranching[node]);
1118
1119 // --------------
1120 // Insert cell connecting parent
1121 // --------------
1122 printMsg(
1123 "// Add cell connecting parent", ttk::debug::Priority::VERBOSE);
1124 if(!trees[i]->isRoot(node) or isPersistenceDiagram) {
1125 vtkIdType pointIds[2];
1126 pointIds[0] = treeSimplexId[node];
1127
1128 idNode nodeParent = trees[i]->getParentSafe(node);
1129 // TODO too many dummy cells are created
1130 bool dummyCell
1131 = PlanarLayout and not branchDecompositionPlanarLayout_
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];
1137 } else if(PlanarLayout and branchDecompositionPlanarLayout_) {
1138 pointIds[1] = treeSimplexId[treeBranching[node]];
1139 } else if(dummyCell) {
1140 double dummyPoint[3]
1141 = {point[0], layout[layoutCorr[nodeParent] + 1] + diff_y,
1142 0. + diff_z};
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;
1150 } else
1151 pointIds[1] = treeSimplexId[nodeParent];
1152
1153 vtkArcs->InsertNextCell(VTK_LINE, 2, pointIds);
1154
1155 // --------------
1156 // Arc field
1157 // --------------
1158 int toAdd = (dummyCell ? 2 : 1);
1159 for(int toAddT = 0; toAddT < toAdd; ++toAddT) {
1160 // Add arc matching percentage
1161 if(ShiftMode == 1) { // Star Barycenter
1162 auto nodeToGet
1163 = (!isPersistenceDiagram ? allBaryBranching[c][node] : node);
1164 percentMatchArc->InsertNextTuple1(
1165 allBaryPercentMatch[c][nodeToGet]);
1166 }
1167
1168 // Add branch bary ID
1169 printMsg(
1170 "// Push arc bary branch id", ttk::debug::Priority::VERBOSE);
1171 if(clusteringOutput and ShiftMode != 1) {
1172 int tBranchID = -1;
1173 auto nodeToGet = node;
1174 if(treeMatching[nodeToGet] < allBaryBranchingID[c].size())
1175 tBranchID = allBaryBranchingID[c][treeMatching[nodeToGet]];
1176 branchBaryID->InsertNextTuple1(tBranchID);
1177 }
1178
1179 // Add branch ID
1180 if(not isPersistenceDiagram) {
1181 int tBranchID = treeBranchingID[node];
1182 branchID->InsertNextTuple1(tBranchID);
1183 }
1184
1185 // Add up and down nodeId
1186 if(not isPersistenceDiagram) {
1187 upNodeId->InsertNextTuple1(treeSimplexId[nodeParent]);
1188 downNodeId->InsertNextTuple1(treeSimplexId[node]);
1189 }
1190
1191 // Add arc persistence
1192 printMsg(
1193 "// Push arc persistence", ttk::debug::Priority::VERBOSE);
1194 idNode nodeToGetPers = nodeBranching;
1195 double persToAdd
1196 = trees[i]->getNodePersistence<dataType>(nodeToGetPers);
1197 persistenceArc->InsertNextTuple1(persToAdd);
1198
1199 // Add arc persistence barycenter and order
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]]);
1208 }
1209 }
1210
1211 // Add arc cluster ID
1212 clusterIDArc->InsertNextTuple1(clusteringAssignment[i]);
1213
1214 // Add arc tree ID
1215 treeIDArc->InsertNextTuple1(i + iSampleOffset);
1216
1217 // Add isImportantPair
1218 bool isImportant = false;
1219 idNode nodeToGetImportance = nodeBranching;
1220 isImportant = trees[i]->isImportantPair<dataType>(
1221 nodeToGetImportance, importantPairs_,
1224 isImportantPairsArc->InsertNextTuple1(isImportant);
1225
1226 // Add isDummyArc
1227 bool isDummy = toAdd == 2 and toAddT == 0;
1228 isDummyArc->InsertNextTuple1(isDummy);
1229
1230 // Add isInterpolatedTree
1231 isInterpolatedTreeArc->InsertNextTuple1(isInterpolatedTree);
1232
1233 // Add pairIdentifier
1234 pairIdentifier->InsertNextTuple1(treeSimplexId[node]);
1235
1236 // Add birth and death
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));
1241
1242 // Add isMinMaxPair
1243 bool isMinMaxPair
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);
1248
1249 // Add pairType TODO
1250 pairType->InsertNextTuple1(0);
1251
1252 // Add isMultiPersPairArc
1253 bool isMultiPersPair
1254 = (trees[i]->isMultiPersPair(nodeBranching)
1255 or trees[i]->isMultiPersPair(
1256 trees[i]->getNode(nodeBranching)->getOrigin()));
1257 isMultiPersPairArc->InsertNextTuple1(isMultiPersPair);
1258
1259 // Add custom point arrays to cells
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]);
1269
1270 cellCount++;
1271 }
1272 }
1273
1274 // --------------
1275 // Node field
1276 // --------------
1277 int toAdd = (dummyNode ? 2 : 1);
1278 for(int toAddT = 0; toAddT < toAdd; ++toAddT) {
1279 // Add node id
1280 nodeID->InsertNextTuple1(treeSimplexId[node]);
1281
1282 // Add trueNodeId
1283 trueNodeID->InsertNextTuple1(node);
1284
1285 // Add VertexId
1286 int nodeVertexId = -1;
1287 if(i < int(treesNodes.size()) and treesNodes[i]) {
1288 auto vertexIdArray = treesNodes[i]->GetPointData()->GetArray(
1289 (isPersistenceDiagram ? ttk::VertexScalarFieldName
1290 : "VertexId"));
1291 if(vertexIdArray and nodeMesh != -1)
1292 nodeVertexId = vertexIdArray->GetTuple1(nodeMesh);
1293 }
1294 vertexID->InsertNextTuple1(nodeVertexId);
1295
1296 // Add node scalar
1297 scalar->InsertNextTuple1(trees[i]->getValue<dataType>(node));
1298
1299 // Add criticalType
1300 printMsg("// Add criticalType", ttk::debug::Priority::VERBOSE);
1301 int criticalTypeT = -1;
1302 if(not isPersistenceDiagram) {
1303 if(not isInterpolatedTree) {
1304 if(ShiftMode == 1) {
1305 if(nodeMeshTreeIndex != -1) {
1306 auto array
1307 = treesNodes[nodeMeshTreeIndex]->GetPointData()->GetArray(
1308 "CriticalType");
1309 if(array)
1310 criticalTypeT = array->GetTuple1(nodeMesh);
1311 }
1312 } else if(treesNodes.size() != 0 and treesNodes[i] != nullptr) {
1313 auto array
1314 = treesNodes[i]->GetPointData()->GetArray("CriticalType");
1315 if(array)
1316 criticalTypeT = array->GetTuple1(nodeMesh);
1317 }
1318 } else {
1319 // TODO critical type for interpolated trees
1320 }
1321 } else {
1322 auto locMin = static_cast<int>(ttk::CriticalType::Local_minimum);
1323 auto saddle1 = static_cast<int>(ttk::CriticalType::Saddle1);
1324 auto locMax = static_cast<int>(ttk::CriticalType::Local_maximum);
1325 auto saddle2 = static_cast<int>(ttk::CriticalType::Saddle2);
1326 auto nodeIsRoot = trees[i]->isRoot(node);
1327 criticalTypeT
1328 = (toAddT == 1
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);
1334 criticalTypeT
1335 = ((nodeSup and toAddT == 1) or (not nodeSup and toAddT == 0)
1336 ? (isPDSadMax or nodeIsRoot ? locMax : saddle1)
1337 : (not isPDSadMax or nodeIsRoot ? locMin : saddle2));
1338 }
1339 }
1340 criticalType->InsertNextTuple1(criticalTypeT);
1341
1342 // Add node matching percentage
1343 if(ShiftMode == 1) { // Star Barycenter
1344 percentMatch->InsertNextTuple1(allBaryPercentMatch[c][node]);
1345 }
1346
1347 // Add node branch bary id
1348 printMsg(
1349 "// Add node bary branch id", ttk::debug::Priority::VERBOSE);
1350 if(clusteringOutput and ShiftMode != 1) {
1351 int tBranchID = -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]];
1357 }
1358 branchBaryNodeID->InsertNextTuple1(tBranchID);
1359 }
1360
1361 // Add node branch id
1362 if(not isPersistenceDiagram) {
1363 int tBranchID = treeBranchingID[node];
1364 if(not trees[i]->isLeaf(node))
1365 tBranchID = treeBranchingID[nodeOrigin];
1366 branchNodeID->InsertNextTuple1(tBranchID);
1367 }
1368
1369 // Add node persistence
1370 printMsg("// Push node persistence", ttk::debug::Priority::VERBOSE);
1371 persistenceNode->InsertNextTuple1(
1372 trees[i]->getNodePersistence<dataType>(node));
1373
1374 // Add node persistence barycenter
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]]);
1382 }
1383 }
1384
1385 // Add node clusterID
1386 clusterIDNode->InsertNextTuple1(clusteringAssignment[i]);
1387
1388 // Add node tree ID
1389 treeIDNode->InsertNextTuple1(i + iSampleOffset);
1390
1391 // Add isDummyNode
1392 bool isDummy
1393 = toAdd == 2 and toAddT == 1 and !trees[i]->isRoot(node);
1394 isDummyNode->InsertNextTuple1(isDummy);
1395
1396 // Add isInterpolatedTree
1397 isInterpolatedTreeNode->InsertNextTuple1(isInterpolatedTree);
1398
1399 // Add birth and death
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));
1404
1405 // Add isImportantPair
1406 bool isImportant = false;
1407 isImportant = trees[i]->isImportantPair<dataType>(
1410 isImportantPairsNode->InsertNextTuple1(isImportant);
1411
1412 // Add treeNodeId
1413 treeNodeId->InsertNextTuple1(node);
1414
1415 // Add treeNodeIdOrigin
1416 treeNodeIdOrigin->InsertNextTuple1(nodeOrigin);
1417
1418 // Add coordinates
1419 printMsg("// Add coordinates", ttk::debug::Priority::VERBOSE);
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]);
1425 }
1426
1427 // Add isMultiPersPairArc
1428 printMsg("// isMultiPersPairArc", ttk::debug::Priority::VERBOSE);
1429 bool isMultiPersPair = (trees[i]->isMultiPersPair(node)
1430 or trees[i]->isMultiPersPair(
1431 trees[i]->getNode(node)->getOrigin()));
1432 isMultiPersPairNode->InsertNextTuple1(isMultiPersPair);
1433
1434 // Add custom arrays
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]);
1444
1445 pointCount++;
1446 }
1447
1449 } // end tree traversal
1450
1451 // Add diagonal if isPersistenceDiagram
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);
1457 cellCount++;
1458
1459 pairIdentifier->InsertNextTuple1(-1);
1460 pairType->InsertNextTuple1(-1);
1461 pairPersistence->InsertNextTuple1(-1);
1462 pairIsFinite->InsertNextTuple1(0);
1463 pairBirth->InsertNextTuple1(0);
1464
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("");
1471
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);
1478 }
1479
1480 // --------------
1481 // Manage segmentation
1482 // --------------
1483 // Use TransformFilter (see commit
1484 // 85600763a8907674b8e57d6ad77ca97640725b30) when issue #513 is
1485 // solved.
1486 printMsg("// Shift segmentation", ttk::debug::Priority::VERBOSE);
1487 if(OutputSegmentation and not PlanarLayout and treesSegmentation[i]) {
1488 vtkNew<vtkUnstructuredGrid> iTreesSegmentationCopy{};
1489 if(ShiftMode != -1)
1490 iTreesSegmentationCopy->DeepCopy(treesSegmentation[i]);
1491 else
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());
1502 }
1503 if(ShiftMode != -1) {
1504 for(int p = 0;
1505 p < iVkOutputSegmentationTemp->GetPoints()->GetNumberOfPoints();
1506 ++p) {
1507 double *point
1508 = iVkOutputSegmentationTemp->GetPoints()->GetPoint(p);
1509 point[0] += diff_x;
1510 point[1] += diff_y;
1511 point[2] += diff_z;
1512 iVkOutputSegmentationTemp->GetPoints()->SetPoint(p, point);
1513 }
1514 }
1515 appendFilter->AddInputData(iVkOutputSegmentationTemp);
1516 }
1517 printMsg("// Shift segmentation DONE", ttk::debug::Priority::VERBOSE);
1518 }
1519 }
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;
1525 ++i)
1526 persistenceBaryOrderNode->InsertNextTuple1(0);
1527 for(int i = persistenceBaryOrderArc->GetNumberOfTuples(); i < cellCount;
1528 ++i)
1529 persistenceBaryOrderArc->InsertNextTuple1(0);
1530
1531 // --- Add VTK arrays to output
1532 printMsg("// Add VTK arrays to output", ttk::debug::Priority::VERBOSE);
1533 // - Manage node output
1534 // Custom arrays
1535 addVtkCustomArrays(customArrays, customArraysValues, vtkOutputNode, 0, 0);
1537 customIntArrays, customIntArraysValues, vtkOutputNode, 1, 0);
1539 customStringArrays, customStringArraysValues, vtkOutputNode, 2, 0);
1540
1541 // Classical arrays
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);
1555 }
1556 if(not branchDecompositionPlanarLayout_ and not isPersistenceDiagram)
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);
1562 }
1563 if(foundOneInterpolatedTree)
1564 vtkOutputNode->GetPointData()->AddArray(isInterpolatedTreeNode);
1565 if(ShiftMode == 1) // Star Barycenter
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);
1573 }
1574 vtkOutputNode->GetPointData()->AddArray(pairPersistenceNode);
1575 vtkOutputNode->GetPointData()->AddArray(pairBirthNode);
1576
1577 // - Manage arc output
1578 // Custom arrays
1579 addVtkCustomArrays(customArrays, customCellArraysValues, vtkArcs, 0, 1);
1581 customIntArrays, customCellIntArraysValues, vtkArcs, 1, 1);
1583 customStringArrays, customCellStringArraysValues, vtkArcs, 2, 1);
1584
1585 // Classical arrays
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);
1597 }
1598 if(clusteringOutput and ShiftMode != 1) {
1599 vtkArcs->GetCellData()->AddArray(branchBaryID);
1600 vtkArcs->GetCellData()->AddArray(persistenceBaryArc);
1601 vtkArcs->GetCellData()->AddArray(persistenceBaryOrderArc);
1602 }
1603 if(foundOneInterpolatedTree)
1604 vtkArcs->GetCellData()->AddArray(isInterpolatedTreeArc);
1605 if(ShiftMode == 1) // Star Barycenter
1606 vtkArcs->GetCellData()->AddArray(percentMatchArc);
1607 if(isPersistenceDiagram) {
1608 vtkArcs->GetCellData()->AddArray(pairIdentifier);
1609 vtkArcs->GetCellData()->AddArray(pairType);
1610 vtkArcs->GetCellData()->AddArray(pairIsFinite);
1611 }
1612 vtkArcs->GetCellData()->AddArray(pairPersistence);
1613 vtkArcs->GetCellData()->AddArray(pairBirth);
1614 if(vtkOutputArc == vtkOutputNode)
1615 vtkArcs->GetPointData()->ShallowCopy(vtkOutputNode->GetPointData());
1616 if(not branchDecompositionPlanarLayout_ and not isPersistenceDiagram)
1617 vtkArcs->GetPointData()->AddArray(scalar);
1618 vtkOutputArc->ShallowCopy(vtkArcs);
1619
1620 // - Manage segmentation output
1621 if(OutputSegmentation and not PlanarLayout
1622 and appendFilter->GetNumberOfInputConnections(0) != 0) {
1623 appendFilter->SetMergePoints(false);
1624 appendFilter->Update();
1625 vtkOutputSegmentation->ShallowCopy(appendFilter->GetOutput());
1626 }
1627
1628 //
1629 if(ShiftMode == 1) // Star Barycenter
1630 trees = treesOri;
1631 }
1632
1633 // ==========================================================================
1634 // Bounds Utils
1635 // ==========================================================================
1636 std::tuple<double, double, double, double, double, double>
1637 getRealBounds(vtkUnstructuredGrid *treeNodes,
1638 FTMTree_MT *tree,
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();
1650 queue.pop();
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;
1659 tree->getChildren(node, children);
1660 for(auto child : children)
1661 queue.emplace(child);
1662 }
1663 return std::make_tuple(x_min, x_max, y_min, y_max, z_min, z_max);
1664 }
1665
1666 std::tuple<double, double, double, double, double, double>
1667 getRealBounds(vtkUnstructuredGrid *treeNodes, FTMTree_MT *tree) {
1668 std::vector<int> nodeCorrT(tree->getNumberOfNodes());
1669 for(size_t i = 0; i < nodeCorrT.size(); ++i)
1670 nodeCorrT[i] = i;
1671
1672 return getRealBounds(treeNodes, tree, nodeCorrT);
1673 }
1674};
#define M_PI
Definition: Os.h:50
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 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)
ttkMergeTreeVisualization()=default
void addCustomIntArray(std::string &name, std::vector< int > &vec)
void setVtkOutputMatching(vtkUnstructuredGrid *vtkMatching)
void setClusteringAssignment(std::vector< int > &asgn)
void addCustomStringArray(std::string &name, std::vector< std::string > &vec)
void makeTreesOutput(std::vector< FTMTree_MT * > &trees, std::vector< FTMTree_MT * > &barycenters)
std::vector< std::vector< float > > getAllBaryPercentMatch()
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 copyPointData(vtkUnstructuredGrid *treeNodes)
void setTreesSegmentation(vtkDataSet *segmentation)
void makeTreesOutput(FTMTree_MT *tree1)
~ttkMergeTreeVisualization() override=default
void setConvertedToDiagram(bool converted)
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 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 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 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
Definition: Debug.h:159
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
Definition: Debug.h:118
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
Definition: FTMTree_MT.h:389
void getChildren(idNode nodeId, std::vector< idNode > &res)
Node * getNode(idNode nodeId)
Definition: FTMTree_MT.h:393
idSuperArc getNumberOfDownSuperArcs() const
Definition: FTMNode.h:82
idSuperArc getNumberOfUpSuperArcs() const
Definition: FTMNode.h:86
unsigned int idNode
Node index in vect_nodes_.
Definition: FTMDataTypes.h:39
const char PersistenceName[]
Definition: DataTypes.h:72
const char PersistenceCoordinatesName[]
Definition: DataTypes.h:70
const char PersistencePairTypeName[]
Definition: DataTypes.h:73
const char PersistenceCriticalTypeName[]
Definition: DataTypes.h:67
const char PersistenceIsFinite[]
Definition: DataTypes.h:74
const char VertexScalarFieldName[]
default name for vertex scalar field
Definition: DataTypes.h:35
const char PersistencePairIdentifierName[]
Definition: DataTypes.h:71
const char PersistenceBirthName[]
Definition: DataTypes.h:68
int SimplexId
Identifier type for simplices of any dimension.
Definition: DataTypes.h:22