TTK
Loading...
Searching...
No Matches
ttkMergeTreeClustering.cpp
Go to the documentation of this file.
2#include <FTMStructures.h>
3#include <FTMTree.h>
4#include <FTMTreeUtils.h>
5#include <MergeTreeUtils.h>
9#include <ttkMergeTreeUtils.h>
11
12#include <vtkDataObject.h> // For port information
13#include <vtkObjectFactory.h> // for new macro
14
15#include <vtkCellData.h>
16#include <vtkDataArray.h>
17#include <vtkDataSet.h>
18#include <vtkFloatArray.h>
19#include <vtkInformation.h>
20#include <vtkInformationVector.h>
21#include <vtkMultiBlockDataSet.h>
22#include <vtkPointData.h>
23#include <vtkTable.h>
24
25#include <string>
26
27using namespace ttk;
28using namespace ftm;
29
30// A VTK macro that enables the instantiation of this class via ::New()
31// You do not have to modify this
33
47 this->setDebugMsgPrefix("MergeTreeClustering");
48 this->SetNumberOfInputPorts(2);
49 this->SetNumberOfOutputPorts(3);
50}
51
53
62 vtkInformation *info) {
63 if(port == 0)
64 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
65 else if(port == 1) {
66 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
67 info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
68 } else
69 return 0;
70
71 return 1;
72}
73
90 vtkInformation *info) {
91 if(port == 0 || port == 1 || port == 2) {
92 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
93 } else {
94 return 0;
95 }
96 return 1;
97}
98
113 vtkInformationVector **inputVector,
114 vtkInformationVector *outputVector) {
115 // ------------------------------------------------------------------------------------
116 // --- Get input object from input vector
117 // ------------------------------------------------------------------------------------
118 auto blocks = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
119 auto blocks2 = vtkMultiBlockDataSet::GetData(inputVector[1], 0);
120
121 if(Backend == 0) {
122 baseModule = 0;
123 } else if(Backend == 1) {
124 baseModule = 0;
125 } else if(Backend == 3) {
126 baseModule = 1;
127 } else if(Backend == 4) {
128 baseModule = 2;
129 } else {
130 baseModule = 0;
131 }
132
133 // filter out backends (not yet supported)
134 if(baseModule == 1 && ComputeBarycenter) {
135 printErr("Invalid Backend chosen. Branch Mapping Distance not yet "
136 "supported for Barycenter computation. Canceling computation.");
137 return -1;
138 }
139 if(Backend == 1 && ComputeBarycenter) {
140 printErr("Invalid Backend chosen. Edit Distance is not yet supported for "
141 "Barycenter computation. Canceling computation.");
142 return -1;
143 }
144 if(Backend == 2) {
145 if(ComputeBarycenter) {
146 if(not BranchDecomposition) {
147 printErr(
148 "Invalid Backend chosen. Custom Backend without Branch "
149 "Decomposition is not yet supported for Barycenter computation. "
150 "Canceling computation.");
151 return -1;
152 }
153 if(KeepSubtree) {
154 printErr(
155 "Invalid Backend chosen. Custom Backend with Keep Subtree is not yet "
156 "supported for Barycenter computation. Canceling computation.");
157 return -1;
158 }
159 }
160 if(not BranchDecomposition and NormalizedWasserstein) {
161 printErr(
162 "Invalid Backend chosen. Custom Backend with Normalized Wasserstein "
163 "and without Branch Decomposition is not yet. Canceling computation.");
164 return -1;
165 }
166 }
167
168 // ------------------------------------------------------------------------------------
169 // --- Load blocks
170 // ------------------------------------------------------------------------------------
171 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> inputTrees, inputTrees2;
172 loadBlocks(inputTrees, blocks);
173 loadBlocks(inputTrees2, blocks2);
174
175 // If we have already computed once but the input has changed
176 if(treesNodes.size() != 0 and inputTrees[0]->GetBlock(0) != treesNodes[0])
177 resetDataVisualization();
178
179 return run<float>(outputVector, inputTrees, inputTrees2);
180}
181
182template <class dataType>
184 vtkInformationVector *outputVector,
185 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees,
186 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees2) {
187 if(not isDataVisualizationFilled())
188 runCompute<dataType>(outputVector, inputTrees, inputTrees2);
189 runOutput<dataType>(outputVector, inputTrees, inputTrees2);
190 return 1;
191}
192
193template <class dataType>
195 vtkInformationVector *ttkNotUsed(outputVector),
196 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees,
197 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees2) {
198 // ------------------------------------------------------------------------------------
199 // --- Construct trees
200 // ------------------------------------------------------------------------------------
201 const int numInputs = inputTrees.size();
202 const int numInputs2
203 = (not inputTrees[0]->GetBlock(0)->IsA("vtkUnstructuredGrid")
204 ? inputTrees2.size()
205 : (JoinSplitMixtureCoefficient != 0
206 and JoinSplitMixtureCoefficient != 1
207 ? numInputs
208 : 0));
209
210 setDataVisualization(numInputs, numInputs2);
211
212 std::vector<MergeTree<dataType>> intermediateMTrees(numInputs),
213 intermediateMTrees2(numInputs2), barycenters(NumberOfBarycenters),
214 barycenters2((numInputs2 != 0) * NumberOfBarycenters);
215 std::vector<FTMTree_MT *> intermediateTrees(numInputs),
216 intermediateTrees2(numInputs2);
217
218 bool const useSecondPairsType = (JoinSplitMixtureCoefficient == 0);
219 IsPersistenceDiagram = constructTrees<dataType>(
220 inputTrees, intermediateMTrees, treesNodes, treesArcs, treesSegmentation,
221 useSecondPairsType, DiagramPairTypes);
222 if(not IsPersistenceDiagram
223 or (JoinSplitMixtureCoefficient != 0
224 and JoinSplitMixtureCoefficient != 1)) {
225 auto &inputTrees2ToUse
226 = (not IsPersistenceDiagram ? inputTrees2 : inputTrees);
227 constructTrees<dataType>(inputTrees2ToUse, intermediateMTrees2, treesNodes2,
228 treesArcs2, treesSegmentation2,
229 !useSecondPairsType, DiagramPairTypes);
230 }
231
232 mergeTreeToFTMTree<dataType>(intermediateMTrees, intermediateTrees);
233 mergeTreeToFTMTree<dataType>(intermediateMTrees2, intermediateTrees2);
234
235 // ------------------------------------------------------------------------------------
236 // --- Call base
237 // ------------------------------------------------------------------------------------
238 bool const AddNodes = true;
239 // Classical distance
240 double distance = 0;
241
242 // Verify parameters
243 if(Backend == 0) {
244 BranchDecomposition = true;
245 NormalizedWasserstein = true;
246 KeepSubtree = false;
247 } else if(Backend == 1) {
248 BranchDecomposition = false;
249 NormalizedWasserstein = false;
250 KeepSubtree = true;
251 } else if(Backend == 3) {
252 BranchDecomposition = false;
253 NormalizedWasserstein = false;
254 KeepSubtree = false;
255 } else if(Backend == 4) {
256 BranchDecomposition = false;
257 NormalizedWasserstein = false;
258 KeepSubtree = false;
259 }
260 if(IsPersistenceDiagram) {
261 BranchDecomposition = true;
262 }
263 EpsilonTree2 = EpsilonTree1;
264 Epsilon2Tree2 = Epsilon2Tree1;
265 Epsilon3Tree2 = Epsilon3Tree1;
266 printMsg("BranchDecomposition: " + std::to_string(BranchDecomposition));
267 printMsg("NormalizedWasserstein: " + std::to_string(NormalizedWasserstein));
268 printMsg("KeepSubtree: " + std::to_string(KeepSubtree));
269
270 // Call base
271 if(not ComputeBarycenter) {
272 if(baseModule == 0) {
273 MergeTreeDistance mergeTreeDistance;
274 mergeTreeDistance.setAssignmentSolver(AssignmentSolver);
275 mergeTreeDistance.setEpsilonTree1(EpsilonTree1);
276 mergeTreeDistance.setEpsilonTree2(EpsilonTree2);
277 mergeTreeDistance.setEpsilon2Tree1(Epsilon2Tree1);
278 mergeTreeDistance.setEpsilon2Tree2(Epsilon2Tree2);
279 mergeTreeDistance.setEpsilon3Tree1(Epsilon3Tree1);
280 mergeTreeDistance.setEpsilon3Tree2(Epsilon3Tree2);
281 mergeTreeDistance.setBranchDecomposition(BranchDecomposition);
282 mergeTreeDistance.setPersistenceThreshold(PersistenceThreshold);
283 mergeTreeDistance.setNormalizedWasserstein(NormalizedWasserstein);
284 mergeTreeDistance.setKeepSubtree(KeepSubtree);
285 mergeTreeDistance.setUseMinMaxPair(UseMinMaxPair);
286 mergeTreeDistance.setCleanTree(true);
287 mergeTreeDistance.setPostprocess(OutputTrees);
288 mergeTreeDistance.setDeleteMultiPersPairs(DeleteMultiPersPairs);
289 mergeTreeDistance.setEpsilon1UseFarthestSaddle(Epsilon1UseFarthestSaddle);
290 mergeTreeDistance.setIsPersistenceDiagram(IsPersistenceDiagram);
291 mergeTreeDistance.setNonMatchingWeight(NonMatchingWeight);
292 mergeTreeDistance.setThreadNumber(this->threadNumber_);
293 mergeTreeDistance.setDebugLevel(this->debugLevel_);
294
295 distance = mergeTreeDistance.execute<dataType>(
296 intermediateMTrees[0], intermediateMTrees[1], outputMatching);
297 trees1NodeCorrMesh = mergeTreeDistance.getTreesNodeCorr();
298 finalDistances = std::vector<double>{distance};
299 } else if(baseModule == 1) {
300 BranchMappingDistance branchDist;
301 branchDist.setBaseMetric(branchMetric);
302 branchDist.setAssignmentSolver(AssignmentSolver);
303 branchDist.setSquared(false);
304 branchDist.setComputeMapping(true);
305 branchDist.setPreprocess(true);
306 branchDist.setBranchDecomposition(false);
307 // branchDist.setWriteBD(false);
308 branchDist.setWriteBD(true);
309
310 branchDist.setEpsilonTree1(EpsilonTree1);
311 branchDist.setEpsilonTree2(EpsilonTree2);
312 branchDist.setPersistenceThreshold(PersistenceThreshold);
313 // branchDist.setUseMinMaxPair(UseMinMaxPair);
314 branchDist.setCleanTree(true);
315 branchDist.setDeleteMultiPersPairs(DeleteMultiPersPairs);
316 // branchDist.setEpsilon1UseFarthestSaddle(Epsilon1UseFarthestSaddle);
317 branchDist.setPersistenceThreshold(PersistenceThreshold);
318 branchDist.setThreadNumber(this->threadNumber_);
319 branchDist.setDebugLevel(this->debugLevel_);
320
321 distance = branchDist.execute<dataType>(
322 intermediateMTrees[0], intermediateMTrees[1], &outputMatching);
323
324 std::vector<ttk::SimplexId> nodeCorr1(
325 intermediateTrees[0]->getNumberOfNodes());
326 std::vector<ttk::SimplexId> nodeCorr2(
327 intermediateTrees[1]->getNumberOfNodes());
328 for(unsigned int i = 0; i < nodeCorr1.size(); i++)
329 nodeCorr1[i] = i;
330 for(unsigned int i = 0; i < nodeCorr2.size(); i++)
331 nodeCorr2[i] = i;
332 trees1NodeCorrMesh = branchDist.getTreesNodeCorr();
333 finalDistances = std::vector<double>{distance};
334 } else {
335 PathMappingDistance pathDist;
336 pathDist.setBaseMetric(pathMetric);
337 pathDist.setAssignmentSolver(AssignmentSolver);
338 pathDist.setSquared(false);
339 pathDist.setComputeMapping(true);
340 pathDist.setPreprocess(true);
341 pathDist.setBranchDecomposition(false);
342
343 pathDist.setEpsilonTree1(EpsilonTree1);
344 pathDist.setEpsilonTree2(EpsilonTree2);
345 pathDist.setPersistenceThreshold(PersistenceThreshold);
346 // pathDist.setUseMinMaxPair(UseMinMaxPair);
347 pathDist.setCleanTree(true);
348 pathDist.setDeleteMultiPersPairs(DeleteMultiPersPairs);
349 // pathDist.setEpsilon1UseFarthestSaddle(Epsilon1UseFarthestSaddle);
350 pathDist.setPersistenceThreshold(PersistenceThreshold);
351 pathDist.setThreadNumber(this->threadNumber_);
352 pathDist.setDebugLevel(this->debugLevel_);
353
354 distance = pathDist.execute<dataType>(
355 intermediateMTrees[0], intermediateMTrees[1], &outputMatching);
356 trees1NodeCorrMesh = pathDist.getTreesNodeCorr();
357
358 // std::vector<ttk::SimplexId>
359 // nodeCorr1(intermediateTrees[0]->getNumberOfNodes());
360 // std::vector<ttk::SimplexId>
361 // nodeCorr2(intermediateTrees[1]->getNumberOfNodes()); for(ttk::SimplexId
362 // i=0; i<nodeCorr1.size(); i++) nodeCorr1[i] = i; for(ttk::SimplexId i=0;
363 // i<nodeCorr2.size(); i++) nodeCorr2[i] = i; trees1NodeCorrMesh =
364 // std::vector<std::vector<ttk::SimplexId>>{nodeCorr1,nodeCorr2};
365 finalDistances = std::vector<double>{distance};
366 }
367 } else {
368 if(NumberOfBarycenters == 1) { // and numInputs2==0){
369 MergeTreeBarycenter mergeTreeBarycenter;
370 mergeTreeBarycenter.setAssignmentSolver(AssignmentSolver);
371 mergeTreeBarycenter.setEpsilonTree1(EpsilonTree1);
372 mergeTreeBarycenter.setEpsilonTree2(EpsilonTree2);
373 mergeTreeBarycenter.setEpsilon2Tree1(Epsilon2Tree1);
374 mergeTreeBarycenter.setEpsilon2Tree2(Epsilon2Tree2);
375 mergeTreeBarycenter.setEpsilon3Tree1(Epsilon3Tree1);
376 mergeTreeBarycenter.setEpsilon3Tree2(Epsilon3Tree2);
377 mergeTreeBarycenter.setThreadNumber(this->threadNumber_);
378 mergeTreeBarycenter.setDebugLevel(this->debugLevel_);
379 mergeTreeBarycenter.setBaseModule(this->baseModule);
380 mergeTreeBarycenter.setIsPersistenceDiagram(IsPersistenceDiagram);
381 mergeTreeBarycenter.setAlpha(Alpha);
382 mergeTreeBarycenter.setDeterministic(Deterministic);
383 mergeTreeBarycenter.setPersistenceThreshold(PersistenceThreshold);
384 mergeTreeBarycenter.setUseFixedInit(useFixedInit);
385 mergeTreeBarycenter.setFixedInitNumber(fixedInitNumber);
386 // mergeTreeBarycenter.setUseEarlyOut(useEarlyOut);
387 mergeTreeBarycenter.setIterationLimit(iterationLimit);
388 if(baseModule == 2) {
389 mergeTreeBarycenter.setPathMetric(this->pathMetric);
390 mergeTreeBarycenter.setBranchDecomposition(false);
391 mergeTreeBarycenter.setNormalizedWasserstein(false);
392 mergeTreeBarycenter.setKeepSubtree(false);
393 // mergeTreeBarycenter.setUseMinMaxPair(false);
394 mergeTreeBarycenter.setAddNodes(false);
395 mergeTreeBarycenter.setPostprocess(false);
396 mergeTreeBarycenter.setUseMedianBarycenter(useMedianBarycenter);
397 } else {
398 mergeTreeBarycenter.setBranchDecomposition(BranchDecomposition);
399 mergeTreeBarycenter.setNormalizedWasserstein(NormalizedWasserstein);
400 mergeTreeBarycenter.setKeepSubtree(KeepSubtree);
401 mergeTreeBarycenter.setUseMinMaxPair(UseMinMaxPair);
402 mergeTreeBarycenter.setAddNodes(AddNodes);
403 mergeTreeBarycenter.setBarycenterSizeLimitPercent(
404 BarycenterSizeLimitPercent);
405 mergeTreeBarycenter.setPostprocess(OutputTrees);
406 mergeTreeBarycenter.setDeleteMultiPersPairs(DeleteMultiPersPairs);
407 mergeTreeBarycenter.setEpsilon1UseFarthestSaddle(
408 Epsilon1UseFarthestSaddle);
409 }
410
411 mergeTreeBarycenter.execute<dataType>(
412 intermediateMTrees, outputMatchingBarycenter[0],
413 outputMatchings_path[0], barycenters[0]);
414 trees1NodeCorrMesh = mergeTreeBarycenter.getTreesNodeCorr();
415 finalDistances = mergeTreeBarycenter.getFinalDistances();
416
417 } else {
418 MergeTreeClustering<dataType> mergeTreeClustering;
419 mergeTreeClustering.setAssignmentSolver(AssignmentSolver);
420 mergeTreeClustering.setBaseModule(this->baseModule);
421 mergeTreeClustering.setPathMetric(this->pathMetric);
422 mergeTreeClustering.setEpsilonTree1(EpsilonTree1);
423 mergeTreeClustering.setEpsilonTree2(EpsilonTree2);
424 mergeTreeClustering.setEpsilon2Tree1(Epsilon2Tree1);
425 mergeTreeClustering.setEpsilon2Tree2(Epsilon2Tree2);
426 mergeTreeClustering.setEpsilon3Tree1(Epsilon3Tree1);
427 mergeTreeClustering.setEpsilon3Tree2(Epsilon3Tree2);
428 mergeTreeClustering.setBranchDecomposition(BranchDecomposition);
429 mergeTreeClustering.setPersistenceThreshold(PersistenceThreshold);
430 mergeTreeClustering.setNormalizedWasserstein(NormalizedWasserstein);
431 mergeTreeClustering.setKeepSubtree(KeepSubtree);
432 mergeTreeClustering.setUseMinMaxPair(UseMinMaxPair);
433 mergeTreeClustering.setAddNodes(AddNodes);
434 mergeTreeClustering.setDeterministic(Deterministic);
435 mergeTreeClustering.setNoCentroids(NumberOfBarycenters);
436 mergeTreeClustering.setBarycenterSizeLimitPercent(
437 BarycenterSizeLimitPercent);
438 mergeTreeClustering.setPostprocess(OutputTrees);
439 mergeTreeClustering.setDeleteMultiPersPairs(DeleteMultiPersPairs);
440 mergeTreeClustering.setEpsilon1UseFarthestSaddle(
441 Epsilon1UseFarthestSaddle);
442 mergeTreeClustering.setIsPersistenceDiagram(IsPersistenceDiagram);
443 mergeTreeClustering.setMixtureCoefficient(JoinSplitMixtureCoefficient);
444 mergeTreeClustering.setThreadNumber(this->threadNumber_);
445 mergeTreeClustering.setDebugLevel(this->debugLevel_);
446
447 mergeTreeClustering.template execute<dataType>(
448 intermediateMTrees, outputMatchingBarycenter, clusteringAssignment,
449 intermediateMTrees2, outputMatchingBarycenter2, barycenters,
450 barycenters2);
451 trees1NodeCorrMesh = mergeTreeClustering.getTreesNodeCorr();
452 trees2NodeCorrMesh = mergeTreeClustering.getTrees2NodeCorr();
453 finalDistances = mergeTreeClustering.getFinalDistances();
454 }
455 }
456
457 mergeTreesTemplateToDouble<dataType>(intermediateMTrees, intermediateSTrees);
458 if(numInputs2 != 0)
460 intermediateMTrees2, intermediateSTrees2);
461 if(ComputeBarycenter) {
462 mergeTreesTemplateToDouble<dataType>(barycenters, barycentersS);
463 if(numInputs2 != 0)
464 mergeTreesTemplateToDouble<dataType>(barycenters2, barycentersS2);
465 }
466
467 return 1;
468}
469
470static void addFieldData(vtkDataSet *in, vtkDataSet *out) {
471 auto inFieldData = in->GetFieldData();
472 auto outFieldData = out->GetFieldData();
473 for(int i = 0; i < inFieldData->GetNumberOfArrays(); ++i) {
474 outFieldData->AddArray(inFieldData->GetAbstractArray(i));
475 }
476}
477
478template <class dataType>
480 ttkMergeTreeVisualization &visuMaker,
482 std::vector<FTMTree_MT *> &intermediateTrees2,
483 std::vector<FTMTree_MT *> &barycentersTree2,
484 std::vector<std::vector<
485 std::vector<std::tuple<ttk::ftm::idNode, ttk::ftm::idNode, double>>>>
486 &outputMatchingBarycenter2,
487 std::vector<std::vector<int>> &trees2NodeCorrMesh,
488 vtkUnstructuredGrid *treeNodes,
489 int i,
490 std::vector<SimplexId> &nodeCorr2) {
491 int const nodeCorrShift = vtkOutputNode->GetNumberOfPoints();
492 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputNode2
494 visuMaker.setVtkOutputNode(vtkOutputNode2);
495 visuMaker.setVtkOutputArc(vtkOutputNode2);
496 visuMaker.setOutputMatchingBarycenter(outputMatchingBarycenter2);
497 visuMaker.clearAllCustomArrays();
498 if(treeNodes)
499 visuMaker.copyPointData(treeNodes, trees2NodeCorrMesh[i]);
500 visuMaker.setTreesNodeCorrMesh(trees2NodeCorrMesh);
501 visuMaker.setIsPDSadMax(true);
502 visuMaker.makeTreesOutput<dataType>(intermediateTrees2, barycentersTree2);
503 auto nodeCorrT = visuMaker.getNodeCorr();
504 nodeCorr2 = nodeCorrT[i];
505 for(unsigned int j = 0; j < nodeCorr2.size(); ++j)
506 nodeCorr2[j] += nodeCorrShift;
507
508 vtkNew<vtkAppendFilter> appendFilter{};
509 appendFilter->AddInputData(vtkOutputNode);
510 appendFilter->AddInputData(vtkOutputNode2);
511 appendFilter->SetMergePoints(false);
512 appendFilter->Update();
513 vtkOutputNode->ShallowCopy(appendFilter->GetOutput());
514}
515
516template <class dataType>
518 ttkMergeTreeVisualization &visuMakerMatching,
519 vtkSmartPointer<vtkUnstructuredGrid> &vtkOutputMatching,
520 std::vector<FTMTree_MT *> &intermediateTrees2,
521 std::vector<FTMTree_MT *> &barycentersTree2,
522 std::vector<std::vector<
523 std::vector<std::tuple<ttk::ftm::idNode, ttk::ftm::idNode, double>>>>
524 &outputMatchingBarycenter2,
525 std::vector<std::vector<SimplexId>> &nodeCorr2,
526 std::vector<std::vector<SimplexId>> &nodeCorrBary2,
527 std::vector<std::vector<float>> &allBaryPercentMatch2) {
528 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputMatching2
530 visuMakerMatching.setVtkOutputMatching(vtkOutputMatching2);
531 visuMakerMatching.setOutputMatchingBarycenter(outputMatchingBarycenter2);
532 visuMakerMatching.setAllBaryPercentMatch(allBaryPercentMatch2);
533 visuMakerMatching.setNodeCorr1(nodeCorr2);
534 visuMakerMatching.setNodeCorr2(nodeCorrBary2);
535 visuMakerMatching.makeMatchingOutput<dataType>(
536 intermediateTrees2, barycentersTree2);
537
538 vtkNew<vtkAppendFilter> appendFilter{};
539 appendFilter->AddInputData(vtkOutputMatching);
540 appendFilter->AddInputData(vtkOutputMatching2);
541 appendFilter->SetMergePoints(false);
542 appendFilter->Update();
543 vtkOutputMatching->ShallowCopy(appendFilter->GetOutput());
544}
545
546template <class dataType>
548 vtkInformationVector *outputVector,
549 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees,
550 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &ttkNotUsed(inputTrees2)) {
551 std::vector<MergeTree<dataType>> intermediateMTrees, intermediateMTrees2;
552 mergeTreesDoubleToTemplate<dataType>(intermediateSTrees, intermediateMTrees);
554 intermediateSTrees2, intermediateMTrees2);
555 std::vector<FTMTree_MT *> intermediateTrees, intermediateTrees2;
556 mergeTreeToFTMTree<dataType>(intermediateMTrees, intermediateTrees);
557 mergeTreeToFTMTree<dataType>(intermediateMTrees2, intermediateTrees2);
558
559 std::vector<MergeTree<dataType>> barycenters, barycenters2;
560 if(ComputeBarycenter) {
561 mergeTreesDoubleToTemplate<dataType>(barycentersS, barycenters);
562 mergeTreesDoubleToTemplate<dataType>(barycentersS2, barycenters2);
563 }
564
565 const int numInputs = inputTrees.size();
566 const int numInputs2 = intermediateMTrees2.size();
567 // ------------------------------------------------------------------------------------
568 // --- Create output
569 // ------------------------------------------------------------------------------------
570 Timer t_makeTreesOutput;
571
572 auto output_clusters = vtkMultiBlockDataSet::GetData(outputVector, 0);
573 auto output_centroids = vtkMultiBlockDataSet::GetData(outputVector, 1);
574 auto output_matchings = vtkMultiBlockDataSet::GetData(outputVector, 2);
575
576 // Declare internal arrays
577 std::vector<std::vector<SimplexId>> nodeCorr(numInputs),
578 nodeCorr2(numInputs2);
579
580 if(not ComputeBarycenter) {
581 // ---------------------------------------------------------------
582 // - Classical output
583 // ---------------------------------------------------------------
584 if(OutputTrees) {
585 FTMTree_MT *tree1 = intermediateTrees[0], *tree2 = intermediateTrees[1];
586 // ------------------------------------------
587 // --- Input trees
588 // ------------------------------------------
589 // Declare vtk objects
590 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputNode1
592 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputArc1
594 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputSegmentation1
596
597 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputNode2
599 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputArc2
601 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputSegmentation2
603
604 vtkSmartPointer<vtkMultiBlockDataSet> const vtkBlockNodes
610
611 // Fill vtk objects
613 visuMaker.setPlanarLayout(PlanarLayout);
615 BranchDecompositionPlanarLayout);
616 visuMaker.setBranchSpacing(BranchSpacing);
617 visuMaker.setRescaleTreesIndividually(RescaleTreesIndividually);
618 visuMaker.setOutputSegmentation(OutputSegmentation);
619 visuMaker.setDimensionSpacing(DimensionSpacing);
620 visuMaker.setDimensionToShift(DimensionToShift);
621 visuMaker.setDimensionsShift(XShift, YShift, ZShift);
622 visuMaker.setImportantPairs(ImportantPairs);
623 visuMaker.setMaximumImportantPairs(MaximumImportantPairs);
624 visuMaker.setMinimumImportantPairs(MinimumImportantPairs);
625 visuMaker.setImportantPairsSpacing(ImportantPairsSpacing);
626 visuMaker.setNonImportantPairsSpacing(NonImportantPairsSpacing);
627 visuMaker.setNonImportantPairsProximity(NonImportantPairsProximity);
628 visuMaker.setExcludeImportantPairsHigher(ExcludeImportantPairsHigher);
629 visuMaker.setExcludeImportantPairsLower(ExcludeImportantPairsLower);
630 visuMaker.setIsPersistenceDiagram(IsPersistenceDiagram);
631 visuMaker.setPathPlanarLayout(PathPlanarLayout);
632 // visuMaker.setPathPlanarLayout(baseModule == 2);
633
634 nodeCorr.clear();
635 // First tree
636 visuMaker.setNoSampleOffset(1);
637 visuMaker.setTreesNodes(treesNodes[0]);
638 visuMaker.copyPointData(treesNodes[0], trees1NodeCorrMesh[0]);
639 visuMaker.setTreesNodeCorrMesh(trees1NodeCorrMesh[0]);
640 visuMaker.setTreesSegmentation(treesSegmentation[0]);
641 visuMaker.setVtkOutputNode(vtkOutputNode1);
642 if(IsPersistenceDiagram)
643 visuMaker.setVtkOutputArc(vtkOutputNode1);
644 else
645 visuMaker.setVtkOutputArc(vtkOutputArc1);
646 visuMaker.setVtkOutputSegmentation(vtkOutputSegmentation1);
647 visuMaker.setDebugLevel(this->debugLevel_);
648 visuMaker.setIsPersistenceDiagram(IsPersistenceDiagram);
649
650 visuMaker.makeTreesOutput<dataType>(tree1);
651 nodeCorr.push_back(visuMaker.getNodeCorr()[0]);
652
653 // Second tree
654 visuMaker.setISampleOffset(1);
655 visuMaker.setTreesNodes(treesNodes[1]);
656 visuMaker.clearAllCustomArrays();
657 visuMaker.copyPointData(treesNodes[1], trees1NodeCorrMesh[1]);
658 visuMaker.setTreesNodeCorrMesh(trees1NodeCorrMesh[1]);
659 visuMaker.setTreesSegmentation(treesSegmentation[1]);
660 visuMaker.setVtkOutputNode(vtkOutputNode2);
661 if(IsPersistenceDiagram)
662 visuMaker.setVtkOutputArc(vtkOutputNode2);
663 else
664 visuMaker.setVtkOutputArc(vtkOutputArc2);
665 visuMaker.setVtkOutputSegmentation(vtkOutputSegmentation2);
666
667 visuMaker.makeTreesOutput<dataType>(tree2);
668 nodeCorr.push_back(visuMaker.getNodeCorr()[0]);
669
670 // Field data
671 vtkOutputNode1->GetFieldData()->ShallowCopy(
672 treesNodes[0]->GetFieldData());
673 vtkOutputNode2->GetFieldData()->ShallowCopy(
674 treesNodes[1]->GetFieldData());
675 if(not IsPersistenceDiagram) {
676 vtkOutputArc1->GetFieldData()->ShallowCopy(
677 treesArcs[0]->GetFieldData());
678 vtkOutputArc2->GetFieldData()->ShallowCopy(
679 treesArcs[1]->GetFieldData());
680 }
681 if(treesSegmentation[0])
682 addFieldData(treesSegmentation[0], vtkOutputNode1);
683 if(treesSegmentation[1])
684 addFieldData(treesSegmentation[1], vtkOutputNode2);
685 if(OutputSegmentation) {
686 vtkOutputSegmentation1->GetFieldData()->ShallowCopy(
687 treesSegmentation[0]->GetFieldData());
688 vtkOutputSegmentation2->GetFieldData()->ShallowCopy(
689 treesSegmentation[1]->GetFieldData());
690 }
691
692 // Construct multiblock
693 if(IsPersistenceDiagram and not OutputSegmentation) {
694 output_clusters->SetNumberOfBlocks(2);
695 output_clusters->SetBlock(0, vtkOutputNode1);
696 output_clusters->SetBlock(1, vtkOutputNode2);
697 } else {
698 vtkBlockNodes->SetNumberOfBlocks(2);
699 vtkBlockNodes->SetBlock(0, vtkOutputNode1);
700 vtkBlockNodes->SetBlock(1, vtkOutputNode2);
701
702 if(not IsPersistenceDiagram) {
703 vtkBlockArcs->SetNumberOfBlocks(2);
704 vtkBlockArcs->SetBlock(0, vtkOutputArc1);
705 vtkBlockArcs->SetBlock(1, vtkOutputArc2);
706 }
707
708 output_clusters->SetNumberOfBlocks(1 + !IsPersistenceDiagram
709 + OutputSegmentation);
710 output_clusters->SetBlock(0, vtkBlockNodes);
711 if(not IsPersistenceDiagram)
712 output_clusters->SetBlock(1, vtkBlockArcs);
713 if(OutputSegmentation) {
714 vtkBlockSegs->SetNumberOfBlocks(2);
715 vtkBlockSegs->SetBlock(0, vtkOutputSegmentation1);
716 vtkBlockSegs->SetBlock(1, vtkOutputSegmentation2);
717 int const segBlockID = 1 + !IsPersistenceDiagram;
718 output_clusters->SetBlock(segBlockID, vtkBlockSegs);
719 }
720 }
721
722 // ------------------------------------------
723 // --- Matching
724 // ------------------------------------------
725 // Declare vtk objects
726 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputMatching
728
729 // Fill vtk objects
730 ttkMergeTreeVisualization visuMakerMatching;
731 visuMakerMatching.setVtkOutputMatching(vtkOutputMatching);
732 visuMakerMatching.setOutputMatching(outputMatching);
733 visuMakerMatching.setVtkOutputNode2(vtkOutputNode1);
734 visuMakerMatching.setVtkOutputNode1(vtkOutputNode2);
735 visuMakerMatching.setNodeCorr1(nodeCorr);
736 visuMakerMatching.setDebugLevel(this->debugLevel_);
737 visuMakerMatching.setPathPlanarLayout(PathPlanarLayout);
738 // visuMakerMatching.setPathPlanarLayout(baseModule == 2);
739
740 visuMakerMatching.makeMatchingOutput<dataType>(tree1, tree2);
741
742 // Field data
743 vtkNew<vtkDoubleArray> vtkDistance{};
744 vtkDistance->SetName("Distance");
745 vtkDistance->SetNumberOfTuples(1);
746 vtkDistance->SetTuple1(0, finalDistances[0]);
747 vtkOutputMatching->GetFieldData()->AddArray(vtkDistance);
748
749 // Construct multiblock
750 output_matchings->SetNumberOfBlocks(1);
751 output_matchings->SetBlock(0, vtkOutputMatching);
752 }
753 } else {
754 // ---------------------------------------------------------------
755 // - Barycenter/Clustering output
756 // ---------------------------------------------------------------
757 if(OutputTrees) {
758 // --- Declare internal arrays
759 std::vector<std::vector<SimplexId>> nodeCorrBary(NumberOfBarycenters),
760 nodeCorrBary2((numInputs2 != 0) * NumberOfBarycenters);
761 std::vector<std::vector<float>> allBaryPercentMatch(NumberOfBarycenters),
762 allBaryPercentMatch2((numInputs2 != 0) * NumberOfBarycenters);
763 std::vector<FTMTree_MT *> barycentersTree, barycentersTree2;
764 mergeTreeToFTMTree<dataType>(barycenters, barycentersTree);
765 mergeTreeToFTMTree<dataType>(barycenters2, barycentersTree2);
766
767 // ------------------------------------------
768 // --- Input trees
769 // ------------------------------------------
770 if(IsPersistenceDiagram and not OutputSegmentation) {
771 output_clusters->SetNumberOfBlocks(numInputs);
772 } else {
773 output_clusters->SetNumberOfBlocks((OutputSegmentation ? 3 : 2));
774 vtkSmartPointer<vtkMultiBlockDataSet> const vtkBlockNodes
776 vtkBlockNodes->SetNumberOfBlocks(numInputs);
777 output_clusters->SetBlock(0, vtkBlockNodes);
780 vtkBlockArcs->SetNumberOfBlocks(numInputs);
781 output_clusters->SetBlock(1, vtkBlockArcs);
782 if(OutputSegmentation) {
785 vtkBlockSegs->SetNumberOfBlocks(numInputs);
786 output_clusters->SetBlock(2, vtkBlockSegs);
787 }
788 }
789 for(unsigned int c = 0; c < NumberOfBarycenters; ++c) {
790 /*#ifdef TTK_ENABLE_OPENMP
791 #pragma omp parallel for schedule(dynamic)
792 num_threads(this->threadNumber_) #endif*/
793 for(int i = 0; i < numInputs; ++i) {
794 if(clusteringAssignment[i] != (int)c)
795 continue;
796
797 // Declare vtk objects
800 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputArc
802 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputSegmentation
804
805 // Fill vtk objects
807 visuMaker.setPlanarLayout(PlanarLayout);
809 BranchDecompositionPlanarLayout);
810 visuMaker.setBranchSpacing(BranchSpacing);
811 visuMaker.setRescaleTreesIndividually(RescaleTreesIndividually);
812 visuMaker.setOutputSegmentation(OutputSegmentation);
813 visuMaker.setDimensionSpacing(DimensionSpacing);
814 visuMaker.setDimensionToShift(DimensionToShift);
815 visuMaker.setDimensionsShift(XShift, YShift, ZShift);
816 visuMaker.setImportantPairs(ImportantPairs);
817 visuMaker.setMaximumImportantPairs(MaximumImportantPairs);
818 visuMaker.setMinimumImportantPairs(MinimumImportantPairs);
819 visuMaker.setImportantPairsSpacing(ImportantPairsSpacing);
820 visuMaker.setNonImportantPairsSpacing(NonImportantPairsSpacing);
821 visuMaker.setNonImportantPairsProximity(NonImportantPairsProximity);
822 visuMaker.setExcludeImportantPairsHigher(ExcludeImportantPairsHigher);
823 visuMaker.setExcludeImportantPairsLower(ExcludeImportantPairsLower);
824 visuMaker.setIsPersistenceDiagram(IsPersistenceDiagram);
825 visuMaker.setTreesNodes(treesNodes);
826 visuMaker.copyPointData(treesNodes[i], trees1NodeCorrMesh[i]);
827 visuMaker.setTreesNodeCorrMesh(trees1NodeCorrMesh);
828 visuMaker.setTreesSegmentation(treesSegmentation);
829 visuMaker.setVtkOutputNode(vtkOutputNode);
830 if(IsPersistenceDiagram)
831 visuMaker.setVtkOutputArc(vtkOutputNode);
832 else
833 visuMaker.setVtkOutputArc(vtkOutputArc);
834 visuMaker.setVtkOutputSegmentation(vtkOutputSegmentation);
835 visuMaker.setClusteringAssignment(clusteringAssignment);
836 visuMaker.setOutputMatchingBarycenter(outputMatchingBarycenter);
837 visuMaker.setPathMatchings(outputMatchings_path);
838 visuMaker.setPrintTreeId(i);
839 visuMaker.setPrintClusterId(c);
840 visuMaker.setDebugLevel(this->debugLevel_);
841 visuMaker.setIsPersistenceDiagram(IsPersistenceDiagram);
842 visuMaker.setIsPDSadMax(JoinSplitMixtureCoefficient == 0);
843 visuMaker.setPathPlanarLayout(PathPlanarLayout);
844 visuMaker.setEnableBarycenterAlignment(baseModule == 2);
845 // visuMaker.setPathPlanarLayout(baseModule == 2);
846
847 visuMaker.makeTreesOutput<dataType>(
848 intermediateTrees, barycentersTree);
849 auto nodeCorrT = visuMaker.getNodeCorr();
850 nodeCorr[i] = nodeCorrT[i];
851 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
852 and JoinSplitMixtureCoefficient != 1)
854 visuMaker, vtkOutputNode, intermediateTrees2, barycentersTree2,
855 outputMatchingBarycenter2, trees2NodeCorrMesh, treesNodes[i], i,
856 nodeCorr2[i]);
857
858 // Field data
859 vtkOutputNode->GetFieldData()->ShallowCopy(
860 treesNodes[i]->GetFieldData());
861 if(not IsPersistenceDiagram)
862 vtkOutputArc->GetFieldData()->ShallowCopy(
863 treesArcs[i]->GetFieldData());
864 if(treesSegmentation[i])
865 addFieldData(treesSegmentation[i], vtkOutputNode);
866 if(OutputSegmentation)
867 vtkOutputSegmentation->GetFieldData()->ShallowCopy(
868 treesSegmentation[i]->GetFieldData());
869
870 vtkNew<vtkDoubleArray> vtkClusterAssignment{};
871 vtkClusterAssignment->SetName("ClusterAssignment");
872 vtkClusterAssignment->SetNumberOfTuples(1);
873 vtkClusterAssignment->SetTuple1(0, clusteringAssignment[i]);
874 vtkOutputNode->GetFieldData()->AddArray(vtkClusterAssignment);
875
876 // Construct multiblock
877 if(IsPersistenceDiagram and not OutputSegmentation) {
878 output_clusters->SetBlock(i, vtkOutputNode);
879 } else {
880 vtkMultiBlockDataSet::SafeDownCast(output_clusters->GetBlock(0))
881 ->SetBlock(i, vtkOutputNode);
882 if(not IsPersistenceDiagram)
883 vtkMultiBlockDataSet::SafeDownCast(output_clusters->GetBlock(1))
884 ->SetBlock(i, vtkOutputArc);
885 if(OutputSegmentation) {
886 int const segBlockID = 1 + !IsPersistenceDiagram;
887 vtkMultiBlockDataSet::SafeDownCast(
888 output_clusters->GetBlock(segBlockID))
889 ->SetBlock(i, vtkOutputSegmentation);
890 }
891 }
892 }
893 }
894
895 // ------------------------------------------
896 // --- Barycenter(s)
897 // ------------------------------------------
898 if(IsPersistenceDiagram) {
899 output_centroids->SetNumberOfBlocks(NumberOfBarycenters);
900 } else {
901 output_centroids->SetNumberOfBlocks(2);
902 vtkSmartPointer<vtkMultiBlockDataSet> const vtkBlockNodes2
904 vtkBlockNodes2->SetNumberOfBlocks(NumberOfBarycenters);
905 output_centroids->SetBlock(0, vtkBlockNodes2);
906 vtkSmartPointer<vtkMultiBlockDataSet> const vtkBlockArcs2
908 vtkBlockArcs2->SetNumberOfBlocks(NumberOfBarycenters);
909 output_centroids->SetBlock(1, vtkBlockArcs2);
910 }
911 for(unsigned int c = 0; c < NumberOfBarycenters; ++c) {
912
913 // Declare vtk objects
916 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputArc
918 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputSegmentation
920
921 // Fill vtk objects
922 ttkMergeTreeVisualization visuMakerBary;
923 visuMakerBary.setPlanarLayout(PlanarLayout);
925 BranchDecompositionPlanarLayout);
926 visuMakerBary.setBranchSpacing(BranchSpacing);
927 visuMakerBary.setRescaleTreesIndividually(RescaleTreesIndividually);
928 visuMakerBary.setOutputSegmentation(false);
929 visuMakerBary.setDimensionSpacing(DimensionSpacing);
930 visuMakerBary.setDimensionToShift(DimensionToShift);
931 visuMakerBary.setDimensionsShift(XShift, YShift, ZShift);
932 visuMakerBary.setImportantPairs(ImportantPairs);
933 visuMakerBary.setMaximumImportantPairs(MaximumImportantPairs);
934 visuMakerBary.setMinimumImportantPairs(MinimumImportantPairs);
935 visuMakerBary.setImportantPairsSpacing(ImportantPairsSpacing);
936 visuMakerBary.setNonImportantPairsSpacing(NonImportantPairsSpacing);
937 visuMakerBary.setNonImportantPairsProximity(NonImportantPairsProximity);
938 visuMakerBary.setExcludeImportantPairsHigher(
939 ExcludeImportantPairsHigher);
940 visuMakerBary.setExcludeImportantPairsLower(ExcludeImportantPairsLower);
941 visuMakerBary.setIsPersistenceDiagram(IsPersistenceDiagram);
942 visuMakerBary.setShiftMode(1); // Star Barycenter
943 visuMakerBary.setTreesNodes(treesNodes);
944 visuMakerBary.setTreesNodeCorrMesh(trees1NodeCorrMesh);
945 visuMakerBary.setTreesSegmentation(treesSegmentation);
946 visuMakerBary.setVtkOutputNode(vtkOutputNode);
947 if(IsPersistenceDiagram)
948 visuMakerBary.setVtkOutputArc(vtkOutputNode);
949 else
950 visuMakerBary.setVtkOutputArc(vtkOutputArc);
951 visuMakerBary.setVtkOutputSegmentation(vtkOutputSegmentation);
952 visuMakerBary.setClusteringAssignment(clusteringAssignment);
953 visuMakerBary.setOutputMatchingBarycenter(outputMatchingBarycenter);
954 visuMakerBary.setPathMatchings(outputMatchings_path);
955 visuMakerBary.setPrintTreeId(c);
956 visuMakerBary.setPrintClusterId(c);
957 if(numInputs == 2 and NumberOfBarycenters == 1) {
958 visuMakerBary.setBarycenterPositionAlpha(BarycenterPositionAlpha);
959 visuMakerBary.setAlpha(Alpha);
960 }
961 visuMakerBary.setDebugLevel(this->debugLevel_);
962 visuMakerBary.setIsPersistenceDiagram(IsPersistenceDiagram);
963 visuMakerBary.setIsPDSadMax(JoinSplitMixtureCoefficient == 0);
964 visuMakerBary.setPathPlanarLayout(PathPlanarLayout);
965 visuMakerBary.setEnableBarycenterAlignment(baseModule == 2);
966 // visuMakerBary.setPathPlanarLayout(baseModule == 2);
967
968 visuMakerBary.makeTreesOutput<dataType>(
969 intermediateTrees, barycentersTree);
970 auto nodeCorrBaryT = visuMakerBary.getNodeCorr();
971 nodeCorrBary[c] = nodeCorrBaryT[c];
972 auto allBaryPercentMatchT = visuMakerBary.getAllBaryPercentMatch();
973 allBaryPercentMatch[c] = allBaryPercentMatchT[c];
974
975 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
976 and JoinSplitMixtureCoefficient != 1) {
978 visuMakerBary, vtkOutputNode, intermediateTrees2, barycentersTree2,
979 outputMatchingBarycenter2, trees2NodeCorrMesh, nullptr, c,
980 nodeCorrBary2[c]);
981 allBaryPercentMatchT = visuMakerBary.getAllBaryPercentMatch();
982 allBaryPercentMatch2[c] = allBaryPercentMatchT[c];
983 }
984
985 // Field data
986 vtkNew<vtkDoubleArray> vtkClusterAssignment{};
987 vtkClusterAssignment->SetName("ClusterAssignment");
988 vtkClusterAssignment->SetNumberOfTuples(1);
989 vtkClusterAssignment->SetTuple1(0, c);
990 vtkOutputNode->GetFieldData()->AddArray(vtkClusterAssignment);
991
992 // Construct multiblock
993 if(IsPersistenceDiagram) {
994 output_centroids->SetBlock(c, vtkOutputNode);
995 } else {
996 vtkMultiBlockDataSet::SafeDownCast(output_centroids->GetBlock(0))
997 ->SetBlock(c, vtkOutputNode);
998 vtkMultiBlockDataSet::SafeDownCast(output_centroids->GetBlock(1))
999 ->SetBlock(c, vtkOutputArc);
1000 }
1001 }
1002
1003 // ------------------------------------------
1004 // --- Matching
1005 // ------------------------------------------
1006 output_matchings->SetNumberOfBlocks(numInputs);
1007 for(unsigned int c = 0; c < NumberOfBarycenters; ++c) {
1008 for(int i = 0; i < numInputs; ++i) {
1009 if(clusteringAssignment[i] != (int)c)
1010 continue;
1011
1012 // Declare vtk objects
1013 vtkSmartPointer<vtkUnstructuredGrid> vtkOutputMatching
1015 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputNode1
1016 = vtkUnstructuredGrid::SafeDownCast(
1017 (IsPersistenceDiagram and not OutputSegmentation
1018 ? output_clusters->GetBlock(i)
1019 : vtkMultiBlockDataSet::SafeDownCast(
1020 output_clusters->GetBlock(0))
1021 ->GetBlock(i)));
1022 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputNode2
1023 = vtkUnstructuredGrid::SafeDownCast(
1024 (IsPersistenceDiagram ? output_centroids->GetBlock(c)
1025 : vtkMultiBlockDataSet::SafeDownCast(
1026 output_centroids->GetBlock(0))
1027 ->GetBlock(c)));
1028
1029 // Fill vtk objects
1030 ttkMergeTreeVisualization visuMakerMatching;
1031 visuMakerMatching.setVtkOutputMatching(vtkOutputMatching);
1032 visuMakerMatching.setOutputMatchingBarycenter(
1033 outputMatchingBarycenter);
1034 visuMakerMatching.setAllBaryPercentMatch(allBaryPercentMatch);
1035 visuMakerMatching.setVtkOutputNode1(vtkOutputNode1);
1036 visuMakerMatching.setVtkOutputNode2(vtkOutputNode2);
1037 visuMakerMatching.setNodeCorr1(nodeCorr);
1038 visuMakerMatching.setNodeCorr2(nodeCorrBary);
1039 visuMakerMatching.setPrintTreeId(i);
1040 visuMakerMatching.setPrintClusterId(c);
1041 visuMakerMatching.setDebugLevel(this->debugLevel_);
1042 visuMakerMatching.setPathPlanarLayout(PathPlanarLayout);
1043 // visuMakerMatching.setPathPlanarLayout(baseModule == 2);
1044
1045 visuMakerMatching.makeMatchingOutput<dataType>(
1046 intermediateTrees, barycentersTree);
1047 if(IsPersistenceDiagram and JoinSplitMixtureCoefficient != 0
1048 and JoinSplitMixtureCoefficient != 1)
1050 visuMakerMatching, vtkOutputMatching, intermediateTrees2,
1051 barycentersTree2, outputMatchingBarycenter2, nodeCorr2,
1052 nodeCorrBary2, allBaryPercentMatch2);
1053
1054 // Field data
1055 vtkNew<vtkDoubleArray> vtkDistance{};
1056 vtkDistance->SetName("Distance");
1057 vtkDistance->SetNumberOfTuples(1);
1058 vtkDistance->SetTuple1(0, finalDistances[i]);
1059 vtkOutputMatching->GetFieldData()->AddArray(vtkDistance);
1060
1061 // Construct multiblock
1062 output_matchings->SetBlock(i, vtkOutputMatching);
1063 }
1064 }
1065 }
1066 }
1067
1068 printMsg(
1069 "Trees output", 1, t_makeTreesOutput.getElapsedTime(), this->threadNumber_);
1070
1071 return 1;
1072}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
TTK VTK-filter that wraps the ttk::MergeTreeClustering module.
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillOutputPortInformation(int port, vtkInformation *info) override
virtual int IsA(const char *type)
int runCompute(vtkInformationVector *outputVector, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees2)
int run(vtkInformationVector *outputVector, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees2)
int runOutput(vtkInformationVector *outputVector, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees2)
int FillInputPortInformation(int port, vtkInformation *info) override
~ttkMergeTreeClustering() override
void setTreesSegmentation(std::vector< vtkDataSet * > &segmentation)
void copyPointData(vtkUnstructuredGrid *treeNodes, std::vector< int > &nodeCorrT)
void setDimensionsShift(double xShift, double yShift, double zShift)
void setVtkOutputNode1(vtkUnstructuredGrid *vtkNode1)
void setNodeCorr1(std::vector< std::vector< SimplexId > > &nodeCorrT)
void setOutputMatchingBarycenter(std::vector< std::vector< std::vector< std::tuple< idNode, idNode, double > > > > &matching)
void setVtkOutputSegmentation(vtkDataSet *vtkSegmentation)
void setTreesNodeCorrMesh(std::vector< std::vector< int > > &nodeCorrMesh)
void setVtkOutputMatching(vtkUnstructuredGrid *vtkMatching)
void setClusteringAssignment(std::vector< int > &asgn)
std::vector< std::vector< float > > getAllBaryPercentMatch()
std::vector< std::vector< SimplexId > > getNodeCorr()
void makeTreesOutput(FTMTree_MT *tree1)
void setPathMatchings(std::vector< std::vector< std::vector< std::pair< std::pair< ttk::ftm::idNode, ttk::ftm::idNode >, std::pair< ttk::ftm::idNode, ttk::ftm::idNode > > > > > &matchings)
void setVtkOutputNode2(vtkUnstructuredGrid *vtkNode2)
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 setTreesNodes(std::vector< vtkUnstructuredGrid * > &nodes)
void setAllBaryPercentMatch(std::vector< std::vector< float > > &baryPercentMatch)
virtual int setThreadNumber(const int threadNumber)
Definition BaseClass.h:80
dataType execute(ftm::MergeTree< dataType > &mTree1, ftm::MergeTree< dataType > &mTree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > *outputMatching=nullptr)
void setAssignmentSolver(int assignmentSolver)
int debugLevel_
Definition Debug.h:379
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
virtual int setDebugLevel(const int &debugLevel)
Definition Debug.cpp:147
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
void setUseMedianBarycenter(bool useMedian)
void setAddNodes(bool addNodesT)
void setPostprocess(bool postproc)
void setDeterministic(bool deterministicT)
void setUseFixedInit(bool useFixedInit)
void execute(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< double > &alphas, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &finalMatchings, std::vector< std::vector< std::pair< std::pair< ftm::idNode, ftm::idNode >, std::pair< ftm::idNode, ftm::idNode > > > > &finalMatchings_path, ftm::MergeTree< dataType > &baryMergeTree, bool finalAsgnDoubleInput=false, bool finalAsgnFirstInput=true)
void setBarycenterSizeLimitPercent(double percent)
std::vector< double > getFinalDistances()
void setFixedInitNumber(int fixedInitNumber)
void setBranchDecomposition(bool useBD)
void setNormalizedWasserstein(bool normalizedWasserstein)
void setEpsilon3Tree1(double epsilon)
void setEpsilonTree1(double epsilon)
void setAssignmentSolver(int assignmentSolver)
std::vector< std::vector< int > > getTreesNodeCorr()
void setEpsilon2Tree1(double epsilon)
void setEpsilonTree2(double epsilon)
void setPersistenceThreshold(double pt)
void setNonMatchingWeight(double weight)
void setCleanTree(bool clean)
void setEpsilon2Tree2(double epsilon)
void setKeepSubtree(bool keepSubtree)
void setEpsilon1UseFarthestSaddle(bool b)
void setDeleteMultiPersPairs(bool deleteMultiPersPairsT)
void setUseMinMaxPair(bool useMinMaxPair)
void setEpsilon3Tree2(double epsilon)
void setIsPersistenceDiagram(bool isPD)
void setMixtureCoefficient(double coef)
void setNoCentroids(unsigned int noCentroidsT)
std::vector< std::vector< int > > getTrees2NodeCorr()
void setPostprocess(bool postproc)
dataType execute(ftm::MergeTree< dataType > &mTree1, ftm::MergeTree< dataType > &mTree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
void setExcludeImportantPairsLower(std::string &d)
void setExcludeImportantPairsHigher(std::string &d)
void setAssignmentSolver(int assignmentSolver)
dataType execute(ftm::MergeTree< dataType > &mTree1, ftm::MergeTree< dataType > &mTree2, std::vector< std::pair< std::pair< ftm::idNode, ftm::idNode >, std::pair< ftm::idNode, ftm::idNode > > > *outputMatching)
double getElapsedTime()
Definition Timer.h:15
void mergeTreeToFTMTree(std::vector< MergeTree< dataType > > &trees, std::vector< ftm::FTMTree_MT * > &treesT)
bool constructTrees(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< MergeTree< dataType > > &intermediateTrees, std::vector< vtkUnstructuredGrid * > &treesNodes, std::vector< vtkUnstructuredGrid * > &treesArcs, std::vector< vtkDataSet * > &treesSegmentation, const std::vector< bool > &useSecondPairsTypeVec, int diagramPairTypes=0)
void loadBlocks(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, vtkMultiBlockDataSet *blocks)
void mergeTreesDoubleToTemplate(std::vector< MergeTree< double > > &mts, std::vector< MergeTree< dataType > > &newMts)
void mergeTreesTemplateToDouble(std::vector< MergeTree< dataType > > &mts, std::vector< MergeTree< double > > &newMts)
TTK base package defining the standard types.
vtkStandardNewMacro(ttkMergeTreeClustering)
void makeDoubleInputPersistenceDiagramOutput(ttkMergeTreeVisualization &visuMaker, vtkSmartPointer< vtkUnstructuredGrid > &vtkOutputNode, std::vector< FTMTree_MT * > &intermediateTrees2, std::vector< FTMTree_MT * > &barycentersTree2, std::vector< std::vector< std::vector< std::tuple< ttk::ftm::idNode, ttk::ftm::idNode, double > > > > &outputMatchingBarycenter2, std::vector< std::vector< int > > &trees2NodeCorrMesh, vtkUnstructuredGrid *treeNodes, int i, std::vector< SimplexId > &nodeCorr2)
void makeDoubleInputPersistenceDiagramMatching(ttkMergeTreeVisualization &visuMakerMatching, vtkSmartPointer< vtkUnstructuredGrid > &vtkOutputMatching, std::vector< FTMTree_MT * > &intermediateTrees2, std::vector< FTMTree_MT * > &barycentersTree2, std::vector< std::vector< std::vector< std::tuple< ttk::ftm::idNode, ttk::ftm::idNode, double > > > > &outputMatchingBarycenter2, std::vector< std::vector< SimplexId > > &nodeCorr2, std::vector< std::vector< SimplexId > > &nodeCorrBary2, std::vector< std::vector< float > > &allBaryPercentMatch2)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)