100 vtkInformationVector **inputVector,
101 vtkInformationVector *outputVector) {
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);
114 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> inputBary, inputTrees;
119 if((baryTreeNodes.size() != 0
120 and inputBary[0]->GetBlock(0) != baryTreeNodes[0])
122 and
int(
allTs_[0].size()) != tableCoefficients->GetNumberOfRows())
123 or tableCoefficientsMTime != tableCoefficients->GetMTime()
124 or tableVectorsMTime != tableVectors->GetMTime()
126 and tableCorrelationMTime != tableCorrelation->GetMTime())
128 and blockInputTreesMTime != blockInputTrees->GetMTime())) {
129 resetDataVisualization();
131 tableCoefficientsMTime = tableCoefficients->GetMTime();
132 tableVectorsMTime = tableVectors->GetMTime();
134 tableCorrelationMTime = tableCorrelation->GetMTime();
136 blockInputTreesMTime = blockInputTrees->GetMTime();
139 printMsg(
"Load parameters from field data.");
140 std::vector<std::string> paramNames;
142 for(
auto paramName : paramNames) {
143 auto array = tableCoefficients->GetFieldData()->GetArray(paramName.c_str());
145 double const value = array->GetTuple1(0);
148 printMsg(
" - " + paramName +
" was not found in the field data.");
153 printMsg(
"Computation with normalized Wasserstein.");
155 printMsg(
"Computation without normalized Wasserstein.");
157 auto diagramPairTypesArray
158 = tableCoefficients->GetFieldData()->GetArray(
"DiagramPairTypes");
159 if(diagramPairTypesArray)
160 DiagramPairTypes = diagramPairTypesArray->GetTuple1(0);
165 auto tableVNoCols = tableVectors->GetNumberOfColumns() / inputBary.size();
166 unsigned int const numberOfGeodesics = tableVNoCols / 4;
167 auto numberOfInputs = tableCoefficients->GetNumberOfRows();
169 auto baryNoNodes = tableVectors->GetNumberOfRows();
170 auto baryNoNodes2 = baryNoNodes;
171 if(inputBary.size() > 1) {
172 for(
unsigned int i = 0; i < 2; ++i) {
173 auto &baryNoNodesT = (i == 0 ? baryNoNodes : baryNoNodes2);
175 std::isnan(tableVectors
177 numberOfGeodesics, 0, 0, 0, (i == 1))
179 ->GetVariantValue(baryNoNodesT - 1)
189 std::vector<std::string> nonFieldDataNames{
"TreeID"};
190 allTs_.resize(numberOfGeodesics, std::vector<double>(numberOfInputs, 0.0));
191 for(
unsigned int i = 0; i < numberOfGeodesics; ++i)
192 for(
unsigned int j = 0; j < numberOfInputs; ++j) {
193 std::string
const name
195 allTs_[i][j] = tableCoefficients->GetColumnByName(name.c_str())
198 nonFieldDataNames.push_back(name);
199 std::string
const normName
201 nonFieldDataNames.push_back(normName);
206 vtkNew<vtkFieldData> fd{};
207 for(
int i = 0; i < tableCoefficients->GetNumberOfColumns(); ++i) {
208 std::string
const name{tableCoefficients->GetColumnName(i)};
209 if(std::count(nonFieldDataNames.begin(), nonFieldDataNames.end(), name)
211 auto array = tableCoefficients->GetColumn(i);
212 array->SetName(name.c_str());
216 inputFieldData = vtkFieldData::New();
217 inputFieldData->ShallowCopy(fd);
222 pVS_.resize(numberOfGeodesics, std::vector<double *>(2));
224 if(inputBary.size() > 1) {
225 pTrees2Vs_.resize(numberOfGeodesics, std::vector<double *>(2));
228 for(
unsigned int h = 0; h < inputBary.size(); ++h) {
231 bool const secondInput = (h == 1);
232 for(
unsigned int i = 0; i < numberOfGeodesics; ++i) {
233 for(
unsigned int k = 0; k < 2; ++k) {
235 numberOfGeodesics, i, 0, k, secondInput);
237 numberOfGeodesics, i, 1, k, secondInput);
239 tableVectors->GetColumnByName(name1.c_str())));
241 tableVectors->GetColumnByName(name2.c_str())));
251 if(tableCorrelation) {
255 auto tableCorrNoRows = tableCorrelation->GetNumberOfRows();
256 auto baryNodeIdArray = tableCorrelation->GetColumnByName(
"BaryNodeId");
258 for(
unsigned int j = 0; j < numberOfGeodesics; ++j) {
259 std::string
const name
261 std::string
const name2
265 tableCorrelation->GetColumnByName(name.c_str())));
268 tableCorrelation->GetColumnByName(name2.c_str())));
274 for(
unsigned int i = 0; i < numberOfInputs; ++i) {
276 auto array = tableCorrelation->GetColumnByName(name.c_str());
279 for(
unsigned int j = 0; j < tableCorrNoRows; ++j) {
280 auto baryNodeId = baryNodeIdArray->GetVariantValue(j).ToInt();
282 baryNodeId, array->GetVariantValue(j).ToDouble(), 0.0);
294 return run<float>(outputVector, inputBary, inputTrees);
310 vtkInformationVector *
ttkNotUsed(outputVector),
318 const int numTrees = inputTrees.size();
320 setDataVisualization(numTrees);
322 std::vector<ttk::ftm::MergeTree<dataType>> baryDTree, inputDTrees;
324 std::vector<bool> useSecondPairsTypeVec{
false,
true};
326 useSecondPairsTypeVec.erase(useSecondPairsTypeVec.begin());
328 baryTreeArcs, baryTreeSegmentation,
329 useSecondPairsTypeVec, DiagramPairTypes);
332 or (ReconstructInputTrees
334 bool const useSecondPairsType
337 inputTrees, inputDTrees, inputTreesNodes, inputTreesArcs,
338 inputTreesSegmentation, useSecondPairsType, DiagramPairTypes);
346 std::string
const preFix{(processFirstInput ?
"" :
"Second Input ")};
347 auto &baryToUse = (processFirstInput ? baryDTree[0] : baryDTree[1]);
352 printMsg(
"Compute Geodesics Distance...");
357 if(OutputInputTrees) {
364 if(ReconstructInputTrees) {
366 printMsg(
"Reconstruct " + preFix +
"Input Trees...");
367 std::vector<ttk::ftm::MergeTree<dataType>> reconstructedTreesT;
369 reconstructionErrors, recInputMatchings,
370 recBaryMatchings, !processFirstInput);
372 reconstructedTreesT, reconstructedTrees);
374 reconstructedTrees.clear();
377 if(ConstructGeodesicsTrees) {
379 printMsg(
"Construct Geodesics Trees...");
380 std::vector<std::vector<ttk::ftm::MergeTree<dataType>>> geodesicsTreesT;
382 baryToUse, geodesicsTreesT, !processFirstInput);
384 geodesicsTreesT, geodesicsTrees);
386 geodesicsTrees.clear();
389 if(ConstructEllipses) {
391 printMsg(
"Construct Ellipses Trees...");
392 std::vector<ttk::ftm::MergeTree<dataType>> geodesicsEllipsesT;
394 baryToUse, geodesicsEllipsesT, !processFirstInput);
396 geodesicsEllipsesT, geodesicsEllipses);
398 geodesicsEllipses.clear();
401 if(ConstructRectangle) {
403 printMsg(
"Construct Rectangle Trees...");
404 std::vector<ttk::ftm::MergeTree<dataType>> geodesicsRectangleT;
406 baryToUse, geodesicsRectangleT, RectangleMultiplier, !processFirstInput);
408 geodesicsRectangleT, geodesicsRectangle);
410 geodesicsRectangle.clear();
413 if(ConstructSurface) {
415 printMsg(
"Construct " + preFix +
"Surface Trees...");
416 std::vector<ttk::ftm::MergeTree<dataType>> geodesicsSurfaceT;
418 baryToUse, geodesicsSurfaceT, !processFirstInput);
420 geodesicsSurfaceT, geodesicsSurface);
422 geodesicsSurface.clear();
432 vtkInformationVector *outputVector,
440 auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
442 unsigned int const noInput = (OutputInputTrees ? inputTrees.size() : 0);
443 unsigned int const noReconst = reconstructedTrees.size();
444 unsigned int const noBary = (OutputBarycenter ? 1 : 0);
445 unsigned int const noGeod
446 = geodesicsTrees.size()
447 * (geodesicsTrees.size() == 0 ? 0 : geodesicsTrees[0].size());
448 unsigned int const noEllipses = geodesicsEllipses.size();
449 unsigned int const noRectangle = geodesicsRectangle.size();
450 unsigned int const noSurface = geodesicsSurface.size();
452 printMsg(
"noInput = " + std::to_string(noInput));
453 printMsg(
"noReconst = " + std::to_string(noReconst));
454 printMsg(
"noBary = " + std::to_string(noBary));
455 printMsg(
"noGeod = " + std::to_string(noGeod));
456 printMsg(
"noEllipses = " + std::to_string(noEllipses));
457 printMsg(
"noRectangle = " + std::to_string(noRectangle));
458 printMsg(
"noSurface = " + std::to_string(noSurface));
460 std::vector<unsigned int> allNo{
461 noInput, noReconst, noBary, noGeod, noEllipses, noRectangle, noSurface};
462 std::vector<unsigned int> steps(allNo.size());
463 for(
unsigned int i = 0; i < allNo.size(); ++i)
464 steps[i] = (i == 0 ? 0 : steps[i - 1]) + allNo[i];
466 unsigned int const noTreesTotal = steps[steps.size() - 1];
468 unsigned int const noBlocks
470 output->SetNumberOfBlocks(noBlocks);
473 vtkBlockNodes->SetNumberOfBlocks(noTreesTotal);
474 output->SetBlock(0, vtkBlockNodes);
478 vtkBlockArcs->SetNumberOfBlocks(noTreesTotal);
479 output->SetBlock(1, vtkBlockArcs);
481 if(OutputInputTreesSegmentation) {
484 vtkBlockSegs->SetNumberOfBlocks(noTreesTotal);
488 int const geodesicsTreesOffset = std::max((
int)geodesicsTrees.size() - 1, 0);
493 std::vector<std::vector<ttk::ftm::idNode>> matchingMatrix;
500 printWrn(
"Please provide input trees and correlation matrix to transfer "
501 "input trees information.");
503#ifdef TTK_ENABLE_OPENMP
504#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
506 for(
unsigned int i = 0; i < noTreesTotal; ++i) {
510 std::vector<double> ts;
517 }
else if(i < steps[1]) {
519 index = i - steps[0];
521 reconstructedTrees[index], mt);
524 }
else if(i < steps[2]) {
528 std::array<double, 2> middle;
533 }
else if(i < steps[3]) {
535 index = i - steps[2];
536 int const i0 = index / geodesicsTrees[0].size();
537 int const i1 = index % geodesicsTrees[0].size();
541 }
else if(i < steps[4]) {
543 index = i - steps[3];
545 geodesicsEllipses[index], mt);
546 treeType = 3 + geodesicsTreesOffset;
548 }
else if(i < steps[5]) {
550 index = i - steps[4];
552 geodesicsRectangle[index], mt);
553 treeType = 4 + geodesicsTreesOffset;
555 }
else if(i < steps[6]) {
557 index = i - steps[5];
559 geodesicsSurface[index], mt);
560 treeType = 5 + geodesicsTreesOffset;
564 bool const isInputTree = (i < steps[0]);
565 bool const isInputTreeAndGotMesh
566 = (isInputTree and inputTrees[i]->GetNumberOfBlocks() >= 3);
567 bool const isReconstructedTree = (i >= steps[0] and i < steps[1]);
568 bool const isInputOrReconstructedTree
569 = (isInputTree or isReconstructedTree);
584 for(
unsigned int n = 0; n <
vSize_; ++n) {
585 if((
int)matchingMatrix[n][i] != -1) {
600 for(
unsigned int n = 0; n <
vSize_; ++n) {
601 if((
int)matchingMatrix[n][i] != -1) {
602 baryNodeID[matchingMatrix[n][i]] = n;
603 baryNodePers[matchingMatrix[n][i]]
604 = baryMTree[0].tree.template getNodePersistence<double>(n);
607 std::string nameBaryNodePers{
"BaryNodePers"};
609 std::string nameBaryNodeId{
"BaryNodeId"};
620 if(isInputTreeAndGotMesh and OutputInputTreesSegmentation) {
631 if(isReconstructedTree) {
635 std::vector<ttk::ftm::idNode> matchingVector;
637 mt, baryMT, recBaryMatchings[index], matchingVector);
639 for(
unsigned int n = 0; n <
vSize_; ++n) {
640 auto match = matchingVector[n];
642 baryNodeID[match] = n;
644 std::string nameBaryNodeId{
"BaryNodeId"};
651 inputMTrees[index], inputMT);
652 std::vector<ttk::ftm::idNode> matchingVector;
654 mt, inputMT, recInputMatchings[index], matchingVector);
656 for(
unsigned int n = 0; n <
vSize_; ++n) {
657 auto match = matchingMatrix[n][index];
658 if((
int)match != -1) {
659 match = matchingVector[match];
661 baryNodeID[match] = n;
664 std::string nameBaryNodeId{
"BaryNodeId"};
684 if(noReconst != 0 or noInput != 0) {
685 vtkNew<vtkFieldData> fd{};
686 if(isInputOrReconstructedTree)
687 fd->DeepCopy(inputFieldData);
689 fd->CopyStructure(inputFieldData);
690 for(
int a = 0; a < inputFieldData->GetNumberOfArrays(); ++a) {
691 auto array = fd->GetAbstractArray(a);
692 array->SetNumberOfTuples(1);
693 if(isInputOrReconstructedTree) {
694 vtkNew<vtkIdList> id;
695 id->InsertNextId(i % (noInput == 0 ? noReconst : noInput));
696 inputFieldData->GetAbstractArray(a)->GetTuples(
id, array);
698 auto downArray = vtkDataArray::SafeDownCast(array);
700 downArray->SetTuple1(0, std::nan(
""));
703 vtkOutputNode->GetFieldData()->ShallowCopy(fd);
707 vtkNew<vtkIntArray> treeTypeArray{};
708 treeTypeArray->SetName(
"TreeType");
709 treeTypeArray->InsertNextTuple1(treeType);
710 vtkOutputNode->GetFieldData()->AddArray(treeTypeArray);
712 vtkNew<vtkIntArray> treeIDArray{};
713 treeIDArray->SetName(
"TreeID");
714 treeIDArray->InsertNextTuple1(i);
715 vtkOutputNode->GetFieldData()->AddArray(treeIDArray);
717 for(
unsigned int j = 0; j < ts.size(); ++j) {
718 vtkNew<vtkDoubleArray> tArray{};
720 tArray->SetName(name.c_str());
721 tArray->InsertNextTuple1(ts[j]);
722 vtkOutputNode->GetFieldData()->AddArray(tArray);
724 vtkNew<vtkDoubleArray> scaledTArray{};
725 std::string
const name2
727 scaledTArray->SetName(name2.c_str());
729 vtkOutputNode->GetFieldData()->AddArray(scaledTArray);
732 bool const isSurfaceTree = (treeType == 5 + geodesicsTreesOffset);
733 vtkNew<vtkIntArray> isSurfaceArray{};
734 isSurfaceArray->SetName(
"isSurface");
735 isSurfaceArray->InsertNextTuple1(isSurfaceTree);
736 vtkOutputNode->GetFieldData()->AddArray(isSurfaceArray);
738 vtkNew<vtkIntArray> isBoundaryArray{};
739 isBoundaryArray->SetName(
"isBoundary");
740 isBoundaryArray->InsertNextTuple1(isBoundary);
741 vtkOutputNode->GetFieldData()->AddArray(isBoundaryArray);
743 vtkNew<vtkIntArray> BoundaryIDArray{};
744 BoundaryIDArray->SetName(
"BoundaryID");
745 BoundaryIDArray->InsertNextTuple1(boundaryID);
746 vtkOutputNode->GetFieldData()->AddArray(BoundaryIDArray);
748 vtkNew<vtkDoubleArray> reconstructionErrorArray{};
749 reconstructionErrorArray->SetName(
"ReconstructionError");
750 auto err = (isReconstructedTree and reconstructionErrors.size() != 0
751 ? reconstructionErrors[index]
753 reconstructionErrorArray->InsertNextTuple1(err);
754 vtkOutputNode->GetFieldData()->AddArray(reconstructionErrorArray);
757 vtkMultiBlockDataSet::SafeDownCast(output->GetBlock(0))
758 ->SetBlock(i, vtkOutputNode);
760 vtkMultiBlockDataSet::SafeDownCast(output->GetBlock(1))
761 ->SetBlock(i, vtkOutputArc);
762 if(OutputInputTreesSegmentation)
763 vtkMultiBlockDataSet::SafeDownCast(
765 ->SetBlock(i, vtkOutputSegmentation);
769 std::vector<std::string> paramNames;
771 for(
auto paramName : paramNames) {
772 vtkNew<vtkDoubleArray> array{};
773 array->SetName(paramName.c_str());
775 output->GetFieldData()->AddArray(array);