TTK
Loading...
Searching...
No Matches
ttkMergeTreePrincipalGeodesicsDecoding.cpp
Go to the documentation of this file.
3#include <ttkMergeTreeUtils.h>
4
5#include <vtkInformation.h>
6
7#include <vtkDataArray.h>
8#include <vtkDataSet.h>
9#include <vtkObjectFactory.h>
10#include <vtkPointData.h>
11#include <vtkSmartPointer.h>
12#include <vtkVariantArray.h>
13
14#include <ttkUtils.h>
15
16// A VTK macro that enables the instantiation of this class via ::New()
17// You do not have to modify this
19
34 this->SetNumberOfInputPorts(5);
35 this->SetNumberOfOutputPorts(1);
36}
37
46 int port, vtkInformation *info) {
47 if(port == 0)
48 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
49 else if(port == 1 or port == 2 or port == 3) {
50 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
51 if(port == 3) // correlation table
52 info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
53 } else if(port == 4) {
54 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
55 info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
56 } else
57 return 0;
58 return 1;
59}
60
77 int port, vtkInformation *info) {
78 if(port == 0) {
79 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
80 } else
81 return 0;
82 return 1;
83}
84
99 vtkInformation *ttkNotUsed(request),
100 vtkInformationVector **inputVector,
101 vtkInformationVector *outputVector) {
102 // ------------------------------------------------------------------------------------
103 // --- Get input object from input vector
104 // ------------------------------------------------------------------------------------
105 auto blockBary = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
106 auto tableCoefficients = vtkTable::GetData(inputVector[1], 0);
107 auto tableVectors = vtkTable::GetData(inputVector[2], 0);
108 auto tableCorrelation = vtkTable::GetData(inputVector[3], 0);
109 auto blockInputTrees = vtkMultiBlockDataSet::GetData(inputVector[4], 0);
110
111 // ------------------------------------------------------------------------------------
112 // --- Load blocks
113 // ------------------------------------------------------------------------------------
114 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> inputBary, inputTrees;
115 ttk::ftm::loadBlocks(inputBary, blockBary);
116 ttk::ftm::loadBlocks(inputTrees, blockInputTrees);
117
118 // If we have already computed once but the input has changed
119 if((baryTreeNodes.size() != 0
120 and inputBary[0]->GetBlock(0) != baryTreeNodes[0])
121 or (allTs_.size() != 0
122 and int(allTs_[0].size()) != tableCoefficients->GetNumberOfRows())
123 or tableCoefficientsMTime != tableCoefficients->GetMTime()
124 or tableVectorsMTime != tableVectors->GetMTime()
125 or (tableCorrelation
126 and tableCorrelationMTime != tableCorrelation->GetMTime())
127 or (blockInputTrees
128 and blockInputTreesMTime != blockInputTrees->GetMTime())) {
129 resetDataVisualization();
130 }
131 tableCoefficientsMTime = tableCoefficients->GetMTime();
132 tableVectorsMTime = tableVectors->GetMTime();
133 if(tableCorrelation)
134 tableCorrelationMTime = tableCorrelation->GetMTime();
135 if(blockInputTrees)
136 blockInputTreesMTime = blockInputTrees->GetMTime();
137
138 // Parameters
139 printMsg("Load parameters from field data.");
140 std::vector<std::string> paramNames;
141 getParamNames(paramNames);
142 for(auto paramName : paramNames) {
143 auto array = tableCoefficients->GetFieldData()->GetArray(paramName.c_str());
144 if(array) {
145 double const value = array->GetTuple1(0);
146 setParamValueFromName(paramName, value);
147 } else
148 printMsg(" - " + paramName + " was not found in the field data.");
149 printMsg(" - " + paramName + " = "
150 + std::to_string(getParamValueFromName(paramName)));
151 }
153 printMsg("Computation with normalized Wasserstein.");
154 else
155 printMsg("Computation without normalized Wasserstein.");
156
157 // ------------------------------------------------------------------------------------
158 // --- Load tables
159 // ------------------------------------------------------------------------------------
160 auto tableVNoCols = tableVectors->GetNumberOfColumns() / inputBary.size();
161 unsigned int const numberOfGeodesics = tableVNoCols / 4;
162 auto numberOfInputs = tableCoefficients->GetNumberOfRows();
163
164 auto baryNoNodes = tableVectors->GetNumberOfRows();
165 auto baryNoNodes2 = baryNoNodes;
166 if(inputBary.size() > 1) {
167 for(unsigned int i = 0; i < 2; ++i) {
168 auto &baryNoNodesT = (i == 0 ? baryNoNodes : baryNoNodes2);
169 while(
170 std::isnan(tableVectors
171 ->GetColumnByName(ttk::axa::getTableVectorName(
172 numberOfGeodesics, 0, 0, 0, (i == 1))
173 .c_str())
174 ->GetVariantValue(baryNoNodesT - 1)
175 .ToDouble()))
176 --baryNoNodesT;
177 }
178 }
179
180 // -----------------
181 // Coefficients
182 // -----------------
183 // Pointers can't be used because we need to access the rows (VariantArray)
184 std::vector<std::string> nonFieldDataNames{"TreeID"};
185 allTs_.resize(numberOfGeodesics, std::vector<double>(numberOfInputs, 0.0));
186 for(unsigned int i = 0; i < numberOfGeodesics; ++i)
187 for(unsigned int j = 0; j < numberOfInputs; ++j) {
188 std::string const name
189 = ttk::axa::getTableCoefficientName(numberOfGeodesics, i);
190 allTs_[i][j] = tableCoefficients->GetColumnByName(name.c_str())
191 ->GetVariantValue(j)
192 .ToDouble();
193 nonFieldDataNames.push_back(name);
194 std::string const normName
195 = ttk::axa::getTableCoefficientNormName(numberOfGeodesics, i);
196 nonFieldDataNames.push_back(normName);
197 }
199
200 // - aggregate input field data
201 vtkNew<vtkFieldData> fd{};
202 for(int i = 0; i < tableCoefficients->GetNumberOfColumns(); ++i) {
203 std::string const name{tableCoefficients->GetColumnName(i)};
204 if(std::count(nonFieldDataNames.begin(), nonFieldDataNames.end(), name)
205 == 0) {
206 auto array = tableCoefficients->GetColumn(i);
207 array->SetName(name.c_str());
208 fd->AddArray(array);
209 }
210 }
211 inputFieldData = vtkFieldData::New();
212 inputFieldData->ShallowCopy(fd);
213
214 // -----------------
215 // Vectors
216 // -----------------
217 pVS_.resize(numberOfGeodesics, std::vector<double *>(2));
218 pV2s_ = pVS_;
219 if(inputBary.size() > 1) {
220 pTrees2Vs_.resize(numberOfGeodesics, std::vector<double *>(2));
222 }
223 for(unsigned int h = 0; h < inputBary.size(); ++h) {
224 auto &pVS = (h == 0 ? pVS_ : pTrees2Vs_);
225 auto &pV2s = (h == 0 ? pV2s_ : pTrees2V2s_);
226 bool const secondInput = (h == 1);
227 for(unsigned int i = 0; i < numberOfGeodesics; ++i) {
228 for(unsigned int k = 0; k < 2; ++k) {
229 std::string const name1 = ttk::axa::getTableVectorName(
230 numberOfGeodesics, i, 0, k, secondInput);
231 std::string const name2 = ttk::axa::getTableVectorName(
232 numberOfGeodesics, i, 1, k, secondInput);
233 pVS[i][k] = ttkUtils::GetPointer<double>(vtkDataArray::SafeDownCast(
234 tableVectors->GetColumnByName(name1.c_str())));
235 pV2s[i][k] = ttkUtils::GetPointer<double>(vtkDataArray::SafeDownCast(
236 tableVectors->GetColumnByName(name2.c_str())));
237 }
238 }
239 }
240 vSize_ = baryNoNodes;
241 vSize2_ = baryNoNodes2;
242
243 // -----------------
244 // Correlation
245 // -----------------
246 if(tableCorrelation) {
247 pBranchesCorrelationMatrix_.resize(numberOfGeodesics);
249
250 auto tableCorrNoRows = tableCorrelation->GetNumberOfRows();
251 auto baryNodeIdArray = tableCorrelation->GetColumnByName("BaryNodeId");
252
253 for(unsigned int j = 0; j < numberOfGeodesics; ++j) {
254 std::string const name
255 = ttk::axa::getTableCorrelationName(numberOfGeodesics, j);
256 std::string const name2
257 = ttk::axa::getTableCorrelationPersName(numberOfGeodesics, j);
259 = ttkUtils::GetPointer<double>(vtkDataArray::SafeDownCast(
260 tableCorrelation->GetColumnByName(name.c_str())));
262 = ttkUtils::GetPointer<double>(vtkDataArray::SafeDownCast(
263 tableCorrelation->GetColumnByName(name2.c_str())));
264 }
265
266 // Pointers can't be used because processing on these data will be done
267 // later
268 baryMatchings_.resize(numberOfInputs);
269 for(unsigned int i = 0; i < numberOfInputs; ++i) {
270 std::string const name = ttk::axa::getTableTreeName(numberOfInputs, i);
271 auto array = tableCorrelation->GetColumnByName(name.c_str());
272 if(array) {
273 baryMatchings_[i].resize(tableCorrNoRows);
274 for(unsigned int j = 0; j < tableCorrNoRows; ++j) {
275 auto baryNodeId = baryNodeIdArray->GetVariantValue(j).ToInt();
276 baryMatchings_[i][j] = std::make_tuple(
277 baryNodeId, array->GetVariantValue(j).ToDouble(), 0.0);
278 }
279 }
280 }
281 } else {
284 baryMatchings_.clear();
285 }
286
287 // ------------------------------------------------------------------------------------
288
289 return run<float>(outputVector, inputBary, inputTrees);
290}
291
292template <class dataType>
294 vtkInformationVector *outputVector,
295 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputBary,
296 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees) {
297 if(not isDataVisualizationFilled())
298 runCompute<dataType>(outputVector, inputBary, inputTrees);
299 runOutput<dataType>(outputVector, inputBary, inputTrees);
300 return 1;
301}
302
303template <class dataType>
305 vtkInformationVector *ttkNotUsed(outputVector),
306 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputBary,
307 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees) {
308 useDoubleInput_ = (inputBary.size() > 1);
309 processFirstInput = (not useDoubleInput_ or not ProcessSecondInput);
310 // ------------------------------------------------------------------------------------
311 // --- Construct trees
312 // ------------------------------------------------------------------------------------
313 const int numTrees = inputTrees.size();
314
315 setDataVisualization(numTrees);
316
317 std::vector<ttk::ftm::MergeTree<dataType>> baryDTree, inputDTrees;
318
319 std::vector<bool> useSadMaxPairsVec{false, true};
320 if(not useDoubleInput_ and mixtureCoefficient_ == 0)
321 useSadMaxPairsVec.erase(useSadMaxPairsVec.begin()); // {true}
322 ttk::ftm::constructTrees<dataType>(inputBary, baryDTree, baryTreeNodes,
323 baryTreeArcs, baryTreeSegmentation,
324 useSadMaxPairsVec);
325
326 if(OutputInputTrees
327 or (ReconstructInputTrees
329 bool const useSadMaxPairs
330 = (useDoubleInput_ and not processFirstInput) or mixtureCoefficient_ == 0;
331 bool const isInputPD = ttk::ftm::constructTrees<dataType>(
332 inputTrees, inputDTrees, inputTreesNodes, inputTreesArcs,
333 inputTreesSegmentation, useSadMaxPairs);
334 if(not isInputPD and isPersistenceDiagram_)
335 mtsFlattening(inputDTrees);
336 }
337
338 //------------------------------------------------------------------------------------
339 // --- Call base
340 //------------------------------------------------------------------------------------
341 std::string const preFix{(processFirstInput ? "" : "Second Input ")};
342 auto &baryToUse = (processFirstInput ? baryDTree[0] : baryDTree[1]);
343
344 // Geodesics distances
345 if(geodesicsDistances_.size() == 0) {
347 printMsg("Compute Geodesics Distance...");
348 computeGeodesicsDistance<dataType>(baryDTree);
349 }
350
351 // Input Trees
352 if(OutputInputTrees) {
354 printMsg("Process Input Trees...");
355 processInputTrees<dataType>(inputDTrees);
356 }
357
358 // Reconstructed Trees
359 if(ReconstructInputTrees) {
361 printMsg("Reconstruct " + preFix + "Input Trees...");
362 std::vector<ttk::ftm::MergeTree<dataType>> reconstructedTreesT;
363 reconstruction<dataType>(baryToUse, inputDTrees, reconstructedTreesT,
364 reconstructionErrors, recInputMatchings,
365 recBaryMatchings, !processFirstInput);
366 ttk::ftm::mergeTreesTemplateToDouble<dataType>(
367 reconstructedTreesT, reconstructedTrees);
368 } else
369 reconstructedTrees.clear();
370
371 // Geodesics Trees
372 if(ConstructGeodesicsTrees) {
374 printMsg("Construct Geodesics Trees...");
375 std::vector<std::vector<ttk::ftm::MergeTree<dataType>>> geodesicsTreesT;
376 constructGeodesicsTrees<dataType>(
377 baryToUse, geodesicsTreesT, !processFirstInput);
378 ttk::ftm::mergeTreesTemplateToDouble<dataType>(
379 geodesicsTreesT, geodesicsTrees);
380 } else
381 geodesicsTrees.clear();
382
383 // Ellipses Trees
384 if(ConstructEllipses) {
386 printMsg("Construct Ellipses Trees...");
387 std::vector<ttk::ftm::MergeTree<dataType>> geodesicsEllipsesT;
388 constructGeodesicsEllipses<dataType>(
389 baryToUse, geodesicsEllipsesT, !processFirstInput);
390 ttk::ftm::mergeTreesTemplateToDouble<dataType>(
391 geodesicsEllipsesT, geodesicsEllipses);
392 } else
393 geodesicsEllipses.clear();
394
395 // Rectangle Trees
396 if(ConstructRectangle) {
398 printMsg("Construct Rectangle Trees...");
399 std::vector<ttk::ftm::MergeTree<dataType>> geodesicsRectangleT;
400 constructGeodesicsRectangle<dataType>(
401 baryToUse, geodesicsRectangleT, RectangleMultiplier, !processFirstInput);
402 ttk::ftm::mergeTreesTemplateToDouble<dataType>(
403 geodesicsRectangleT, geodesicsRectangle);
404 } else
405 geodesicsRectangle.clear();
406
407 // Surface Trees
408 if(ConstructSurface) {
410 printMsg("Construct " + preFix + "Surface Trees...");
411 std::vector<ttk::ftm::MergeTree<dataType>> geodesicsSurfaceT;
412 constructGeodesicsSurface<dataType>(
413 baryToUse, geodesicsSurfaceT, !processFirstInput);
414 ttk::ftm::mergeTreesTemplateToDouble<dataType>(
415 geodesicsSurfaceT, geodesicsSurface);
416 } else
417 geodesicsSurface.clear();
418
419 ttk::ftm::mergeTreesTemplateToDouble<dataType>(baryDTree, baryMTree);
420 ttk::ftm::mergeTreesTemplateToDouble<dataType>(inputDTrees, inputMTrees);
421
422 return 1;
423}
424
425template <class dataType>
427 vtkInformationVector *outputVector,
428 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &ttkNotUsed(inputBary),
429 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees) {
431 printMsg("Make output...");
432 // ------------------------------------------------------------------------------------
433 // --- Create output
434 // ------------------------------------------------------------------------------------
435 auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
436
437 unsigned int const noInput = (OutputInputTrees ? inputTrees.size() : 0);
438 unsigned int const noReconst = reconstructedTrees.size();
439 unsigned int const noBary = (OutputBarycenter ? 1 : 0);
440 unsigned int const noGeod
441 = geodesicsTrees.size()
442 * (geodesicsTrees.size() == 0 ? 0 : geodesicsTrees[0].size());
443 unsigned int const noEllipses = geodesicsEllipses.size();
444 unsigned int const noRectangle = geodesicsRectangle.size();
445 unsigned int const noSurface = geodesicsSurface.size();
446
447 printMsg("noInput = " + std::to_string(noInput));
448 printMsg("noReconst = " + std::to_string(noReconst));
449 printMsg("noBary = " + std::to_string(noBary));
450 printMsg("noGeod = " + std::to_string(noGeod));
451 printMsg("noEllipses = " + std::to_string(noEllipses));
452 printMsg("noRectangle = " + std::to_string(noRectangle));
453 printMsg("noSurface = " + std::to_string(noSurface));
454
455 std::vector<unsigned int> allNo{
456 noInput, noReconst, noBary, noGeod, noEllipses, noRectangle, noSurface};
457 std::vector<unsigned int> steps(allNo.size());
458 for(unsigned int i = 0; i < allNo.size(); ++i)
459 steps[i] = (i == 0 ? 0 : steps[i - 1]) + allNo[i];
460
461 unsigned int const noTreesTotal = steps[steps.size() - 1];
462
463 unsigned int const noBlocks
464 = 2 - isPersistenceDiagram_ + OutputInputTreesSegmentation;
465 output->SetNumberOfBlocks(noBlocks);
466 vtkSmartPointer<vtkMultiBlockDataSet> const vtkBlockNodes
468 vtkBlockNodes->SetNumberOfBlocks(noTreesTotal);
469 output->SetBlock(0, vtkBlockNodes);
470 if(not isPersistenceDiagram_) {
473 vtkBlockArcs->SetNumberOfBlocks(noTreesTotal);
474 output->SetBlock(1, vtkBlockArcs);
475 }
476 if(OutputInputTreesSegmentation) {
479 vtkBlockSegs->SetNumberOfBlocks(noTreesTotal);
480 output->SetBlock(2 - isPersistenceDiagram_, vtkBlockSegs);
481 }
482
483 int const geodesicsTreesOffset = std::max((int)geodesicsTrees.size() - 1, 0);
484
485 // ------------------------------------------
486 // --- Trees
487 // ------------------------------------------
488 std::vector<std::vector<ttk::ftm::idNode>> matchingMatrix;
489 if(!baryMatchings_.empty())
490 getMatchingMatrix<double>(
491 baryMTree[0], inputMTrees, baryMatchings_, matchingMatrix);
492 // TODO compute matching to barycenter if correlation matrix is not provided
494 and (inputMTrees.empty() or baryMatchings_.empty()))
495 printWrn("Please provide input trees and correlation matrix to transfer "
496 "input trees information.");
497 // TODO fix if an interpolation is empty
498#ifdef TTK_ENABLE_OPENMP
499#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
500#endif
501 for(unsigned int i = 0; i < noTreesTotal; ++i) {
502 int index = 0;
503 int treeType = 0;
505 std::vector<double> ts;
506 if(i < steps[0]) {
507 // Input Trees
508 index = i;
509 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(inputMTrees[index], mt);
510 treeType = -1;
511 ts = allTreesTs_[index];
512 } else if(i < steps[1]) {
513 // Reconstructed trees
514 index = i - steps[0];
515 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
516 reconstructedTrees[index], mt);
517 treeType = 0;
518 ts = allTreesTs_[index];
519 } else if(i < steps[2]) {
520 // Barycenter
521 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(baryMTree[0], mt);
522 treeType = 1;
523 std::array<double, 2> middle;
524 getGeodesicsMiddle<dataType>(mt, pVS_, pV2s_, vSize_, middle);
525 ts.resize(2);
526 ts[0] = middle[0];
527 ts[1] = middle[1];
528 } else if(i < steps[3]) {
529 // Geodesics Trees
530 index = i - steps[2];
531 int const i0 = index / geodesicsTrees[0].size();
532 int const i1 = index % geodesicsTrees[0].size();
533 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(geodesicsTrees[i0][i1], mt);
534 treeType = 2 + i0;
535 ts = tGeodesics_[i0][i1];
536 } else if(i < steps[4]) {
537 // Ellipses Trees
538 index = i - steps[3];
539 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
540 geodesicsEllipses[index], mt);
541 treeType = 3 + geodesicsTreesOffset;
542 ts = tEllipses_[index];
543 } else if(i < steps[5]) {
544 // Rectangle Trees
545 index = i - steps[4];
546 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
547 geodesicsRectangle[index], mt);
548 treeType = 4 + geodesicsTreesOffset;
549 ts = tRectangle_[index];
550 } else if(i < steps[6]) {
551 // Surface Trees
552 index = i - steps[5];
553 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
554 geodesicsSurface[index], mt);
555 treeType = 5 + geodesicsTreesOffset;
556 ts = tSurface_[index];
557 }
558
559 bool const isInputTree = (i < steps[0]);
560 bool const isInputTreeAndGotMesh
561 = (isInputTree and inputTrees[i]->GetNumberOfBlocks() >= 3);
562 bool const isReconstructedTree = (i >= steps[0] and i < steps[1]);
563 bool const isInputOrReconstructedTree
564 = (isInputTree or isReconstructedTree);
565
566 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputNode
568 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputArc
570 vtkSmartPointer<vtkUnstructuredGrid> const vtkOutputSegmentation
572
574
575 if(isInputTree) {
576 for(unsigned int g = 0; g < pBranchesCorrelationMatrix_.size(); ++g) {
577 std::vector<double> corr(mt.tree.getNumberOfNodes(), 0.0),
578 corrPers = corr;
579 for(unsigned int n = 0; n < vSize_; ++n) {
580 if((int)matchingMatrix[n][i] != -1) {
581 corr[matchingMatrix[n][i]] = pBranchesCorrelationMatrix_[g][n];
582 corrPers[matchingMatrix[n][i]] = pPersCorrelationMatrix_[g][n];
583 }
584 }
585 std::string name = ttk::axa::getTableCorrelationName(
587 visuMaker.addCustomArray(name, corr);
588 std::string name2 = ttk::axa::getTableCorrelationPersName(
590 visuMaker.addCustomArray(name2, corrPers);
591 }
592 if(!baryMatchings_.empty()) {
593 std::vector<double> baryNodePers(mt.tree.getNumberOfNodes(), -1);
594 std::vector<int> baryNodeID(mt.tree.getNumberOfNodes(), -1);
595 for(unsigned int n = 0; n < vSize_; ++n) {
596 if((int)matchingMatrix[n][i] != -1) {
597 baryNodeID[matchingMatrix[n][i]] = n;
598 baryNodePers[matchingMatrix[n][i]]
599 = baryMTree[0].tree.template getNodePersistence<double>(n);
600 }
601 }
602 std::string nameBaryNodePers{"BaryNodePers"};
603 visuMaker.addCustomArray(nameBaryNodePers, baryNodePers);
604 std::string nameBaryNodeId{"BaryNodeId"};
605 visuMaker.addCustomIntArray(nameBaryNodeId, baryNodeID);
606 }
607 // visuMaker.setShiftMode(0); // Star
608 visuMaker.setShiftMode(-1); // None
609 visuMaker.setISampleOffset(i);
610 visuMaker.setNoSampleOffset(noInput - 1);
611 visuMaker.setTreesNodes(inputTreesNodes[index]);
612 visuMaker.setTreesNodeCorrMesh(treesNodeCorr_[index]);
613 visuMaker.setDimensionSpacing(2);
615 if(isInputTreeAndGotMesh and OutputInputTreesSegmentation) {
616 visuMaker.setOutputSegmentation(true);
617 visuMaker.setVtkOutputSegmentation(vtkOutputSegmentation);
618 visuMaker.setTreesSegmentation(inputTreesSegmentation[index]);
619 }
620 } else
621 visuMaker.setShiftMode(2); // Line
623 visuMaker.setPlanarLayout(true);
624
625 // TODO transfer other information?
626 if(isReconstructedTree) {
629 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(baryMTree[0], baryMT);
630 std::vector<ttk::ftm::idNode> matchingVector;
632 mt, baryMT, recBaryMatchings[index], matchingVector);
633 std::vector<int> baryNodeID(mt.tree.getNumberOfNodes(), -1);
634 for(unsigned int n = 0; n < vSize_; ++n) {
635 auto match = matchingVector[n];
636 if((int)match != -1)
637 baryNodeID[match] = n;
638 }
639 std::string nameBaryNodeId{"BaryNodeId"};
640 visuMaker.addCustomIntArray(nameBaryNodeId, baryNodeID);
641 }
642 if(transferInputTreesInformation_ and !inputMTrees.empty()
643 and !baryMatchings_.empty()) {
645 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
646 inputMTrees[index], inputMT);
647 std::vector<ttk::ftm::idNode> matchingVector;
649 mt, inputMT, recInputMatchings[index], matchingVector);
650 std::vector<int> baryNodeID(mt.tree.getNumberOfNodes(), -1);
651 for(unsigned int n = 0; n < vSize_; ++n) {
652 auto match = matchingMatrix[n][index];
653 if((int)match != -1) {
654 match = matchingVector[match];
655 if((int)match != -1)
656 baryNodeID[match] = n;
657 }
658 }
659 std::string nameBaryNodeId{"BaryNodeId"};
660 visuMaker.addCustomIntArray(nameBaryNodeId, baryNodeID);
661 }
662 }
663
664 visuMaker.setVtkOutputNode(vtkOutputNode);
666 visuMaker.setVtkOutputArc(vtkOutputArc);
667 else {
668 visuMaker.setVtkOutputArc(vtkOutputNode);
670 visuMaker.setIsPDSadMax(!processFirstInput);
671 else
672 visuMaker.setIsPDSadMax(mixtureCoefficient_ == 0);
673 }
674 visuMaker.setDebugLevel(this->debugLevel_);
676 visuMaker.makeTreesOutput<dataType>(&(mt.tree));
677
678 // Copy Input Field Data
679 if(noReconst != 0 or noInput != 0) {
680 vtkNew<vtkFieldData> fd{};
681 if(isInputOrReconstructedTree)
682 fd->DeepCopy(inputFieldData);
683 else
684 fd->CopyStructure(inputFieldData);
685 for(int a = 0; a < inputFieldData->GetNumberOfArrays(); ++a) {
686 auto array = fd->GetAbstractArray(a);
687 array->SetNumberOfTuples(1);
688 if(isInputOrReconstructedTree) {
689 vtkNew<vtkIdList> id;
690 id->InsertNextId(i % (noInput == 0 ? noReconst : noInput));
691 inputFieldData->GetAbstractArray(a)->GetTuples(id, array);
692 } else {
693 auto downArray = vtkDataArray::SafeDownCast(array);
694 if(downArray)
695 downArray->SetTuple1(0, std::nan(""));
696 }
697 }
698 vtkOutputNode->GetFieldData()->ShallowCopy(fd);
699 }
700
701 // Field Data
702 vtkNew<vtkIntArray> treeTypeArray{};
703 treeTypeArray->SetName("TreeType");
704 treeTypeArray->InsertNextTuple1(treeType);
705 vtkOutputNode->GetFieldData()->AddArray(treeTypeArray);
706
707 vtkNew<vtkIntArray> treeIDArray{};
708 treeIDArray->SetName("TreeID");
709 treeIDArray->InsertNextTuple1(i);
710 vtkOutputNode->GetFieldData()->AddArray(treeIDArray);
711
712 for(unsigned int j = 0; j < ts.size(); ++j) {
713 vtkNew<vtkDoubleArray> tArray{};
714 std::string const name = ttk::axa::getTableCoefficientName(ts.size(), j);
715 tArray->SetName(name.c_str());
716 tArray->InsertNextTuple1(ts[j]);
717 vtkOutputNode->GetFieldData()->AddArray(tArray);
718
719 vtkNew<vtkDoubleArray> scaledTArray{};
720 std::string const name2
722 scaledTArray->SetName(name2.c_str());
723 scaledTArray->InsertNextTuple1(ts[j] * geodesicsDistances_[j]);
724 vtkOutputNode->GetFieldData()->AddArray(scaledTArray);
725 }
726
727 bool const isSurfaceTree = (treeType == 5 + geodesicsTreesOffset);
728 vtkNew<vtkIntArray> isSurfaceArray{};
729 isSurfaceArray->SetName("isSurface");
730 isSurfaceArray->InsertNextTuple1(isSurfaceTree);
731 vtkOutputNode->GetFieldData()->AddArray(isSurfaceArray);
732 bool const isBoundary = (isSurfaceTree ? surfaceIsBoundary_[index] : false);
733 vtkNew<vtkIntArray> isBoundaryArray{};
734 isBoundaryArray->SetName("isBoundary");
735 isBoundaryArray->InsertNextTuple1(isBoundary);
736 vtkOutputNode->GetFieldData()->AddArray(isBoundaryArray);
737 int const boundaryID = (isSurfaceTree ? surfaceBoundaryID_[index] : -1);
738 vtkNew<vtkIntArray> BoundaryIDArray{};
739 BoundaryIDArray->SetName("BoundaryID");
740 BoundaryIDArray->InsertNextTuple1(boundaryID);
741 vtkOutputNode->GetFieldData()->AddArray(BoundaryIDArray);
742
743 vtkNew<vtkDoubleArray> reconstructionErrorArray{};
744 reconstructionErrorArray->SetName("ReconstructionError");
745 auto err = (isReconstructedTree and reconstructionErrors.size() != 0
746 ? reconstructionErrors[index]
747 : std::nan(""));
748 reconstructionErrorArray->InsertNextTuple1(err);
749 vtkOutputNode->GetFieldData()->AddArray(reconstructionErrorArray);
750
751 // Add new block
752 vtkMultiBlockDataSet::SafeDownCast(output->GetBlock(0))
753 ->SetBlock(i, vtkOutputNode);
755 vtkMultiBlockDataSet::SafeDownCast(output->GetBlock(1))
756 ->SetBlock(i, vtkOutputArc);
757 if(OutputInputTreesSegmentation)
758 vtkMultiBlockDataSet::SafeDownCast(
759 output->GetBlock(2 - isPersistenceDiagram_))
760 ->SetBlock(i, vtkOutputSegmentation);
761 }
762
763 // Field Data Input Parameters
764 std::vector<std::string> paramNames;
765 getParamNames(paramNames);
766 for(auto paramName : paramNames) {
767 vtkNew<vtkDoubleArray> array{};
768 array->SetName(paramName.c_str());
769 array->InsertNextTuple1(getParamValueFromName(paramName));
770 output->GetFieldData()->AddArray(array);
771 }
772
773 return 1;
774}
#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::MergeTreePrincipalGeodesicsDecoding module.
int runOutput(vtkInformationVector *outputVector, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputBary, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees)
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int runCompute(vtkInformationVector *outputVector, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputBary, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees)
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int run(vtkInformationVector *outputVector, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputBary, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees)
void setTreesSegmentation(std::vector< vtkDataSet * > &segmentation)
void setVtkOutputSegmentation(vtkDataSet *vtkSegmentation)
void setTreesNodeCorrMesh(std::vector< std::vector< int > > &nodeCorrMesh)
void addCustomIntArray(std::string &name, std::vector< int > &vec)
void makeTreesOutput(FTMTree_MT *tree1)
void setVtkOutputArc(vtkUnstructuredGrid *vtkArc)
void setVtkOutputNode(vtkUnstructuredGrid *vtkNode)
void addCustomArray(std::string &name, std::vector< double > &vec)
void setTreesNodes(std::vector< vtkUnstructuredGrid * > &nodes)
int debugLevel_
Definition Debug.h:379
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
virtual int setDebugLevel(const int &debugLevel)
Definition Debug.cpp:147
void getInverseMatchingVector(ftm::MergeTree< dataType > &barycenter, ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matchings, std::vector< ftm::idNode > &matchingVector)
void setParamValueFromName(std::string &paramName, double value)
void getParamNames(std::vector< std::string > &paramNames)
std::vector< std::vector< int > > treesNodeCorr_
void mtsFlattening(std::vector< ftm::MergeTree< dataType > > &mts)
double getParamValueFromName(std::string &paramName)
std::vector< std::vector< double > > allTreesTs_
std::vector< std::vector< double > > allTs_
std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > baryMatchings_
std::vector< std::vector< std::vector< double > > > tGeodesics_
idNode getNumberOfNodes() const
Definition FTMTree_MT.h:389
void transposeMatrix(const std::vector< std::vector< T > > &a, std::vector< std::vector< T > > &out)
Definition Geometry.cpp:818
std::string getTableCoefficientNormName(int noAxes, int axeNum)
std::string getTableCorrelationPersName(int noAxes, int axeNum)
std::string getTableVectorName(int noAxes, int axeNum, int vId, int vComp, bool isSecondInput)
std::string getTableTreeName(int noTrees, int treeNum)
std::string getTableCoefficientName(int noAxes, int axeNum)
std::string getTableCorrelationName(int noAxes, int axeNum)
void loadBlocks(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, vtkMultiBlockDataSet *blocks)
ftm::FTMTree_MT tree
Definition FTMTree_MT.h:903
vtkStandardNewMacro(ttkMergeTreePrincipalGeodesicsDecoding)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)