65#ifdef TTK_ENABLE_OPENMP
79 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
bestMatching,
87 template <
class dataType>
93 std::vector<std::vector<double>> &v1,
94 std::vector<std::vector<double>> &v2,
95 std::vector<std::vector<double>> &trees2V1,
96 std::vector<std::vector<double>> &trees2V2) {
97 auto initializedVectorsProjection
99 std::vector<std::vector<double>> &_v,
100 std::vector<std::vector<double>> &_v2,
101 std::vector<std::vector<std::vector<double>>> &_vS,
102 std::vector<std::vector<std::vector<double>>> &_v2s,
104 std::vector<std::vector<double>> &_trees2V,
105 std::vector<std::vector<double>> &_trees2V2,
106 std::vector<std::vector<std::vector<double>>> &_trees2Vs,
107 std::vector<std::vector<std::vector<double>>> &_trees2V2s,
108 bool _useSecondInput,
unsigned int _noProjectionStep) {
109 return this->
projectionStep(_geodesicNumber, _barycenter, _v, _v2,
110 _vS, _v2s, _barycenter2, _trees2V,
111 _trees2V2, _trees2Vs, _trees2V2s,
112 _useSecondInput, _noProjectionStep);
115 MergeTreeAxesAlgorithmBase::initVectors<dataType>(
116 geodesicNumber, barycenter, trees, barycenter2, trees2, v1, v2,
120 initializedVectorsProjection);
127 std::vector<std::vector<std::vector<double>>> &v2s,
128 std::vector<std::vector<double>> &v,
129 std::vector<std::vector<double>> &v2) {
134 std::vector<std::vector<double>> &v2) {
142 std::vector<std::vector<double>> &v2,
143 std::vector<std::vector<std::vector<double>>> &vS,
144 std::vector<std::vector<std::vector<double>>> &v2s,
153 template <
class dataType>
156 std::vector<std::vector<double>> &v,
158 bool useDoubleInput =
false,
159 bool isFirstInput =
true) {
162 double const t = (isV1 ? -1.0 : 1.0);
164 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
166 std::vector<ftm::idNode> matchingVector;
170 useDoubleInput, isFirstInput);
174 std::numeric_limits<ftm::idNode>::max());
176 std::vector<std::vector<double>>
const oriV = v;
180 auto matched = matchingVector[i];
182 = getParametrizedBirthDeath<dataType>(barycenterTree, i);
183 dataType birthBary = std::get<0>(birthDeathBary);
184 dataType deathBary = std::get<1>(birthDeathBary);
185 std::vector<double> newV{0.0, 0.0};
186 if(matched != std::numeric_limits<ftm::idNode>::max()) {
187 auto birthDeathMatched
188 = getParametrizedBirthDeath<dataType>(extremityTree, matched);
189 newV[0] = std::get<0>(birthDeathMatched);
190 newV[1] = std::get<1>(birthDeathMatched);
192 dataType projec = (birthBary + deathBary) / 2.0;
196 newV[0] = (newV[0] - birthBary) * t;
197 newV[1] = (newV[1] - deathBary) * t;
206 template <
class dataType>
209 std::vector<std::vector<double>> &v,
210 std::vector<std::vector<double>> &v2,
212 std::vector<std::vector<double>> &trees2V,
213 std::vector<std::vector<double>> &trees2V2,
214 bool useSecondInput =
false) {
215 std::vector<ftm::MergeTree<dataType>> extremities(
216 (useSecondInput ? 4 : 2));
217 getInterpolation<dataType>(barycenter, v, v2, 0.0, extremities[0]);
218 getInterpolation<dataType>(barycenter, v, v2, 1.0, extremities[1]);
220 getInterpolation<dataType>(
221 barycenter2, trees2V, trees2V2, 0.0, extremities[2]);
222 getInterpolation<dataType>(
223 barycenter2, trees2V, trees2V2, 1.0, extremities[3]);
226#ifdef TTK_ENABLE_OPENMP
227#pragma omp parallel for schedule(dynamic) \
228 num_threads(this->threadNumber_) if(parallelize_)
230 for(
unsigned int i = 0; i < extremities.size(); ++i) {
231 bool isFirstInput = (i < 2);
233 = (i < 2 ? barycenter : barycenter2);
234 std::vector<std::vector<double>> &vToUse
235 = (i == 0 ? v : (i == 1 ? v2 : (i == 2 ? trees2V : trees2V2)));
238 (i % 2 == 0), useSecondInput, isFirstInput);
246 std::vector<std::vector<double>> &v2) {
247 std::vector<double> v1_flatten, v2_flatten;
252 double const beta = v2_norm / (v1_norm + v2_norm);
253 std::vector<double> v;
263 std::vector<std::vector<double>> &v2,
264 std::vector<std::vector<std::vector<double>>> &vS,
265 std::vector<std::vector<std::vector<double>>> &v2s) {
267 std::vector<std::vector<double>> sumVs;
271 std::vector<double> v1_flatten, v2_flatten, v1_proj, v2_proj;
285 template <
class dataType>
289 std::vector<std::vector<double>> &v,
290 std::vector<std::vector<double>> &v2,
291 std::vector<std::vector<std::vector<double>>> &vS,
292 std::vector<std::vector<std::vector<double>>> &v2s,
294 std::vector<std::vector<double>> &trees2V,
295 std::vector<std::vector<double>> &trees2V2,
296 std::vector<std::vector<std::vector<double>>> &trees2Vs,
297 std::vector<std::vector<std::vector<double>>> &trees2V2s,
299 unsigned int noProjectionStep) {
300 std::vector<std::vector<std::vector<double>>> vSConcat, v2sConcat;
305 for(
unsigned int j = 0; j < vS.size(); ++j) {
307 vSConcat[j].
end(), trees2Vs[j].
begin(), trees2Vs[j].
end());
309 v2sConcat[j].
end(), trees2V2s[j].
begin(), trees2V2s[j].
end());
314 double optMapCost = 0.0;
315 for(
unsigned i = 0; i < noProjectionStep; ++i) {
316 std::vector<std::vector<double>> vOld = v, v2Old = v2;
323 barycenter, v, v2, barycenter2, trees2V, trees2V2, useSecondInput);
328 std::vector<std::vector<double>> vConcat, v2Concat;
332 vConcat.insert(vConcat.end(), trees2V.begin(), trees2V.end());
334 v2Concat.insert(v2Concat.end(), trees2V2.begin(), trees2V2.end());
350 if(geodesicNumber != 0) {
365 for(
unsigned int j = 0; j < v.size(); ++j) {
369 for(
unsigned int j = 0; j < trees2V.size(); ++j) {
370 trees2V[j] = vConcat[v.size() + j];
371 trees2V2[j] = v2Concat[v.size() + j];
382 template <
class dataType>
386 std::vector<std::vector<double>> &v,
387 std::vector<std::vector<double>> &v2,
390 std::vector<std::vector<double>> &trees2V,
391 std::vector<std::vector<double>> &trees2V2,
392 std::vector<std::vector<double>> &allTreesTs,
393 std::vector<std::vector<std::vector<double>>> &vS,
394 std::vector<std::vector<std::vector<double>>> &v2s,
395 std::vector<std::vector<std::vector<double>>> &trees2Vs,
396 std::vector<std::vector<std::vector<double>>> &trees2V2s,
397 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
399 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
401 std::vector<double> &ts,
402 std::vector<double> &distances) {
403 std::vector<std::vector<Compare>> best(
404 trees.size(), std::vector<Compare>(
k_));
406#ifdef TTK_ENABLE_OPENMP
407#pragma omp parallel num_threads(this->threadNumber_) if(parallelize_) \
410#pragma omp single nowait
413 for(
unsigned int k = 0; k <
k_; ++k) {
414 for(
unsigned int i = 0; i < trees.size(); ++i) {
415#ifdef TTK_ENABLE_OPENMP
416#pragma omp task shared(best) firstprivate(i, k)
419 double const kT = (k % 2 == 0 ? k / 2 :
k_ - 1 - (int)(k / 2));
420 double t = 1.0 / (
k_ - 1) * kT;
422 dataType distance, distance2;
424 auto tsToUse = (allTreesTs.size() == 0 ? std::vector<double>()
427 barycenter, vS, v2s, v, v2, tsToUse, t, interpolated);
429 computeOneDistance<dataType>(interpolated, trees[i],
430 best[i][kT].bestMatching,
432 if(trees2.size() != 0) {
435 trees2V, trees2V2, tsToUse, t,
437 computeOneDistance<dataType>(
438 interpolated2, trees2[i], best[i][kT].bestMatching2,
442 best[i][kT].bestDistance = distance;
443 best[i][kT].bestIndex = kT;
445#ifdef TTK_ENABLE_OPENMP
450#ifdef TTK_ENABLE_OPENMP
455 for(
unsigned int i = 0; i < trees.size(); ++i) {
456#ifdef TTK_ENABLE_OPENMP
457#pragma omp task firstprivate(i)
460 double bestDistance = std::numeric_limits<double>::max();
462 for(
unsigned int k = 0; k <
k_; ++k) {
463 if(best[i][k].bestDistance < bestDistance) {
465 bestDistance = best[i][k].bestDistance;
468 matchings[i] = best[i][bestIndex].bestMatching;
469 if(trees2.size() != 0)
470 matchings2[i] = best[i][bestIndex].bestMatching2;
471 ts[i] = best[i][bestIndex].bestIndex * 1.0 / (
k_ - 1);
472 distances[i] = best[i][bestIndex].bestDistance;
473#ifdef TTK_ENABLE_OPENMP
477#ifdef TTK_ENABLE_OPENMP
483 template <
class dataType>
487 std::vector<std::vector<double>> &v,
488 std::vector<std::vector<double>> &v2,
491 std::vector<std::vector<double>> &trees2V,
492 std::vector<std::vector<double>> &trees2V2,
493 std::vector<std::vector<double>> &allTreesTs,
494 std::vector<std::vector<std::vector<double>>> &vS,
495 std::vector<std::vector<std::vector<double>>> &v2s,
496 std::vector<std::vector<std::vector<double>>> &trees2Vs,
497 std::vector<std::vector<std::vector<double>>> &trees2V2s,
498 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
500 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
502 std::vector<double> &ts,
503 std::vector<double> &distances) {
505 matchings.resize(trees.size());
506 matchings2.resize(trees2.size());
507 ts.resize(trees.size());
508 distances.resize(trees.size());
511 assignmentImpl<dataType>(barycenter, trees, v, v2, barycenter2, trees2,
512 trees2V, trees2V2, allTreesTs, vS, v2s, trees2Vs,
513 trees2V2s, matchings, matchings2, ts, distances);
519 template <
class dataType>
525 std::vector<std::vector<double>> &v,
526 std::vector<std::vector<double>> &v2,
527 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
529 std::vector<std::vector<double>> &tss,
530 std::vector<std::vector<double>> &vR,
531 std::vector<std::vector<double>> &vR2,
532 std::vector<bool> &isUniform) {
536 std::vector<ftm::FTMTree_MT *> ftmTrees, allInterpolatedTrees;
537 ttk::ftm::mergeTreeToFTMTree<dataType>(trees, ftmTrees);
538 if(geodesicNumber != 0) {
539 ttk::ftm::mergeTreeToFTMTree<dataType>(
540 allInterpolated, allInterpolatedTrees);
544 std::vector<std::vector<ftm::idNode>> matchingMatrix;
561 = getParametrizedBirthDeath<dataType>(barycenterTree, i);
562 dataType birthBary = std::get<0>(birthDeathBary);
563 dataType deathBary = std::get<1>(birthDeathBary);
564 dataType projec = (birthBary + deathBary) / 2.0;
565 std::vector<dataType> allBirthBary(trees.size(), birthBary);
566 std::vector<dataType> allDeathBary(trees.size(), deathBary);
567 std::vector<dataType> allProjec(trees.size(), projec);
569 if(geodesicNumber != 0)
570 for(
unsigned int j = 0; j < trees.size(); ++j) {
571 auto birthDeathInterpol
572 = getParametrizedBirthDeath<dataType>(allInterpolatedTrees[j], i);
573 allBirthBary[j] = std::get<0>(birthDeathInterpol);
574 allDeathBary[j] = std::get<1>(birthDeathInterpol);
575 allProjec[j] = (allBirthBary[j] + allDeathBary[j]) / 2.0;
579 std::vector<std::vector<dataType>> allMatched(trees.size());
580 for(
unsigned int j = 0; j < trees.size(); ++j) {
581 dataType birth = allProjec[j];
582 dataType death = allProjec[j];
583 if(matchingMatrix[i][j] != std::numeric_limits<ftm::idNode>::max()) {
584 auto birthDeath = getParametrizedBirthDeath<dataType>(
585 ftmTrees[j], matchingMatrix[i][j]);
586 birth = std::get<0>(birthDeath);
587 death = std::get<1>(birthDeath);
589 allMatched[j].resize(2);
590 allMatched[j][0] = birth;
591 allMatched[j][1] = death;
595 double ti_squared = 0.0, one_min_ti_squared = 0.0, ti_one_min_ti = 0.0;
596 for(
auto t : tss[i]) {
598 one_min_ti_squared += (1 - t) * (1 - t);
599 ti_one_min_ti += t * (1 - t);
603 double multBirthV1 = 0.0, multDeathV1 = 0.0, multBirthV2 = 0.0,
605 for(
unsigned int j = 0; j < trees.size(); ++j) {
607 += tss[i][j] * (allMatched[j][0] - allBirthBary[j]) / ti_squared;
609 += tss[i][j] * (allMatched[j][1] - allDeathBary[j]) / ti_squared;
610 multBirthV2 += (1 - tss[i][j]) * (-allMatched[j][0] + allBirthBary[j])
611 / one_min_ti_squared;
612 multDeathV2 += (1 - tss[i][j]) * (-allMatched[j][1] + allDeathBary[j])
613 / one_min_ti_squared;
617 double newBirthV1 = 0.0, newDeathV1 = 0.0, newBirthV2 = 0.0,
619 for(
unsigned int j = 0; j < trees.size(); ++j) {
620 newBirthV1 += (1 - tss[i][j])
621 * (-allMatched[j][0] + allBirthBary[j]
622 + tss[i][j] * multBirthV1);
623 newDeathV1 += (1 - tss[i][j])
624 * (-allMatched[j][1] + allDeathBary[j]
625 + tss[i][j] * multDeathV1);
626 newBirthV2 += tss[i][j]
627 * (allMatched[j][0] - allBirthBary[j]
628 + (1 - tss[i][j]) * multBirthV2);
629 newDeathV2 += tss[i][j]
630 * (allMatched[j][1] - allDeathBary[j]
631 + (1 - tss[i][j]) * multDeathV2);
633 double const divisorV1
634 = one_min_ti_squared - ti_one_min_ti * ti_one_min_ti / ti_squared;
635 double const divisorV2
636 = ti_squared - ti_one_min_ti * ti_one_min_ti / one_min_ti_squared;
637 newBirthV1 /= divisorV1;
638 newDeathV1 /= divisorV1;
639 newBirthV2 /= divisorV2;
640 newDeathV2 /= divisorV2;
643 v[i][0] = newBirthV1;
644 v[i][1] = newDeathV1;
645 v2[i][0] = newBirthV2;
646 v2[i][1] = newDeathV2;
650 template <
class dataType>
655 std::vector<std::vector<double>> &v,
656 std::vector<std::vector<double>> &v2,
657 std::vector<std::vector<std::vector<double>>> &vS,
658 std::vector<std::vector<std::vector<double>>> &v2s,
659 std::vector<double> &ts,
660 std::vector<std::vector<double>> &allTreesTs,
662 std::vector<bool> &isUniform,
663 std::vector<std::vector<double>> &tss,
664 unsigned int &noUniform,
665 bool &foundAllUniform) {
667 allInterpolated.resize(trees.size());
668 if(geodesicNumber != 0) {
669 for(
unsigned int i = 0; i < trees.size(); ++i)
671 barycenter, vS, v2s, allTreesTs[i], allInterpolated[i]);
676 foundAllUniform =
true;
683 for(
unsigned int j = 0; j < tss[i].size(); ++j) {
685 = (geodesicNumber != 0 ? allInterpolated[j] : barycenter);
686 tss[i][j] = getTNew<dataType>(treeToUse, v, v2, i, ts[j]);
689 noUniform += isUniform[i];
690 foundAllUniform &= isUniform[i];
694 template <
class dataType>
699 std::vector<std::vector<double>> &v,
700 std::vector<std::vector<double>> &v2,
701 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
703 std::vector<std::vector<std::vector<double>>> &vS,
704 std::vector<std::vector<std::vector<double>>> &v2s,
707 std::vector<std::vector<double>> &trees2V,
708 std::vector<std::vector<double>> &trees2V2,
709 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
711 std::vector<std::vector<std::vector<double>>> &trees2Vs,
712 std::vector<std::vector<std::vector<double>>> &trees2V2s,
713 std::vector<double> &ts,
714 std::vector<std::vector<double>> &allTreesTs) {
716 std::vector<ftm::MergeTree<dataType>> allInterpolated, allInterpolated2;
717 std::vector<bool> isUniform, isUniform2;
718 std::vector<std::vector<double>> tss, tss2;
719 unsigned int noUniform;
720 bool foundAllUniform;
722 allTreesTs, allInterpolated, isUniform, tss, noUniform,
724 if(trees2.size() != 0) {
725 unsigned int noUniform2;
726 bool foundAllUniform2;
728 trees2V2, trees2Vs, trees2V2s, ts, allTreesTs,
729 allInterpolated2, isUniform2, tss2, noUniform2,
731 noUniform += noUniform2;
732 foundAllUniform &= foundAllUniform2;
735 if(foundAllUniform) {
736 printMsg(
"All projection coefficients are the same.");
737 printMsg(
"New vectors will be initialized.");
739 initVectors(geodesicNumber, barycenter, trees, barycenter2, trees2, v,
740 v2, trees2V, trees2V2);
743 std::vector<std::vector<double>> vR, vR2, trees2VR, trees2VR2;
746 +
" uniform coefficients.");
747 initVectors(geodesicNumber, barycenter, trees, barycenter2, trees2, vR,
748 vR2, trees2VR, trees2VR2);
752 v2, matchings, tss, vR, vR2, isUniform);
753 if(trees2.size() != 0) {
755 trees2V, trees2V2, matchings2, tss2, trees2VR,
756 trees2VR2, isUniform2);
762 template <
class dataType>
767 std::vector<std::vector<double>> &v,
768 std::vector<std::vector<double>> &v2,
769 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
771 std::vector<std::vector<std::vector<double>>> &vS,
772 std::vector<std::vector<std::vector<double>>> &v2s,
775 std::vector<std::vector<double>> &trees2V,
776 std::vector<std::vector<double>> &trees2V2,
777 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
779 std::vector<std::vector<std::vector<double>>> &trees2Vs,
780 std::vector<std::vector<std::vector<double>>> &trees2V2s,
781 std::vector<double> &ts,
782 std::vector<std::vector<double>> &allTreesTs) {
783 return updateClosedFormStep<dataType>(
784 geodesicNumber, barycenter, trees, v, v2, matchings, vS, v2s,
785 barycenter2, trees2, trees2V, trees2V2, matchings2, trees2Vs, trees2V2s,
792 template <
class dataType>
794 std::vector<std::vector<double>> &v,
795 std::vector<std::vector<double>> &v2,
796 dataType &oldFrechetEnergy,
797 dataType &minFrechetEnergy,
801 bool isBestEnergy =
false;
804 double frechetEnergy = 0;
805 for(
unsigned int i = 0; i < distances.size(); ++i)
806 frechetEnergy += distances[i] * distances[i] / distances.size();
807 std::stringstream ssEnergy;
808 ssEnergy <<
"Energy = " << frechetEnergy;
812 std::stringstream ssReg;
814 ssReg <<
"Prop. cost = " << reg;
818 std::stringstream ssOrthoCost;
820 ssOrthoCost <<
"Ortho. cost = " << orthoCost;
824 std::stringstream ssOptMapCost;
825 ssOptMapCost <<
"Map. cost = " << optMapCost;
830 tol = oldFrechetEnergy / 125.0;
831 converged = std::abs(frechetEnergy - oldFrechetEnergy) < tol;
832 oldFrechetEnergy = frechetEnergy;
835 minFrechetEnergy = frechetEnergy;
840 cptBlocked += (minFrechetEnergy < frechetEnergy) ? 1 : 0;
841 converged = (cptBlocked >= 10);
847 template <
class dataType>
857 std::vector<std::vector<double>> v, v2, trees2V, trees2V2;
858 initVectors<dataType>(geodesicNumber, barycenter, trees, barycenter2,
859 trees2, v, v2, trees2V, trees2V2);
863 std::vector<std::vector<double>> bestV, bestV2, bestTrees2V, bestTrees2V2;
864 std::vector<double> bestTs, bestDistances;
865 int bestIteration = 0;
868 dataType oldFrechetEnergy, minFrechetEnergy;
869 int cptBlocked, iteration = 0;
870 auto initLoop = [&]() {
871 oldFrechetEnergy = -1;
872 minFrechetEnergy = std::numeric_limits<dataType>::max();
879 double optMapCost = 0.0;
880 bool converged =
false;
881 while(not converged) {
882 std::stringstream ss;
883 ss <<
"Iteration " << iteration;
890 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
891 matchings, matchings2;
892 std::vector<double> ts, distances;
893 assignmentStep(barycenter, trees, v, v2, barycenter2, trees2, trees2V,
895 matchings, matchings2, ts, distances);
897 allTs_[geodesicNumber] = ts;
902 minFrechetEnergy, cptBlocked, converged,
908 bestTrees2V = trees2V;
909 bestTrees2V2 = trees2V2;
911 bestDistances = distances;
912 bestIteration = iteration;
922 =
updateStep(geodesicNumber, barycenter, trees, v, v2, matchings,
vS_,
923 v2s_, barycenter2, trees2, trees2V, trees2V2, matchings2,
936 barycenter2, trees2V, trees2V2,
trees2Vs_,
955 trees2V = bestTrees2V;
956 trees2V2 = bestTrees2V2;
958 allTs_[geodesicNumber] = bestTs;
968 template <
class dataType>
981 if(trees2.size() != 0) {
982 std::vector<double> baryDistances2;
996 printMsg(
"KeepState is enabled and barycenter was already computed");
997 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
999 if(trees2.size() != 0) {
1000 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
1005 mergeTreeTemplateToDouble(barycenter,
barycenter_);
1006 if(trees2.size() != 0) {
1012 double const globalVariance
1017 if(trees2.size() != 0)
1020 std::stringstream ss;
1022 << maxNoGeodesics <<
" can be computed.";
1024 printMsg(
"(the maximum is twice the number of persistence pairs in the "
1030 unsigned int const oldNoGeod =
allTs_.size();
1052 "KeepState is enabled, restart the computation at geodesic number "
1060 std::stringstream ss;
1061 ss <<
"Compute geodesic " << geodNum;
1065 computePrincipalGeodesic<dataType>(
1066 geodNum, barycenter, trees, barycenter2, trees2);
1070 barycenter, trees, barycenter2, trees2, geodNum, globalVariance);
1074 template <
class dataType>
1080 if(trees2.size() != 0)
1088 computePrincipalGeodesics<dataType>(trees, trees2);
1093 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
barycenter_, barycenter);
1096 computeGeodesicExtremities<dataType>();
1099 computeBranchesCorrelationMatrix<dataType>(barycenter, trees);
1105 std::stringstream ss;
1106 ss <<
"Reconstruction Error = " << reconstructionError;
1113 if(trees2.size() != 0)
1117 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
barycenter_, barycenter);
1118 for(
unsigned int i = 0; i < trees.size(); ++i) {
1119 postprocessingPipeline<dataType>(&(trees[i].tree));
1120 convertBranchDecompositionMatching<dataType>(
1123 for(
unsigned int i = 0; i < trees2.size(); ++i)
1124 postprocessingPipeline<dataType>(&(trees2[i].tree));
1131 std::vector<std::vector<double>> &v2,
1132 std::vector<std::vector<double>> &trees2V,
1133 std::vector<std::vector<double>> &trees2V2) {
1136 trees2V[root2] = v[root];
1137 trees2V2[root2] = v2[root];
1140 template <
class dataType>
1144 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
barycenter_, barycenter);
1146 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
1148#ifdef TTK_ENABLE_OPENMP
1149#pragma omp parallel for schedule(dynamic) \
1150 num_threads(this->threadNumber_) if(parallelize_)
1154 getInterpolation<dataType>(
1155 barycenter,
vS_[i],
v2s_[i], 0.0, extremityV1);
1156 getInterpolation<dataType>(
1157 barycenter,
vS_[i],
v2s_[i], 1.0, extremityV2);
1164 getInterpolation<dataType>(
1166 getInterpolation<dataType>(
1174 for(
unsigned int j = 0; j <
allTs_[i].size(); ++j)
1179 template <
class dataType>
1191 template <
class dataType>
1197 double globalVariance) {
1198 bool const printOriginalVariances =
false;
1199 bool const printSurfaceVariance =
false;
1200 bool const printTVariances =
true;
1202 if(printOriginalVariances) {
1204 double variance = computeExplainedVariance<dataType>(
1205 barycenter, trees,
vS_[geodesicNumber],
v2s_[geodesicNumber],
1207 double const variancePercent = variance / globalVariance * 100.0;
1208 std::stringstream ssVariance, ssCumul;
1209 ssVariance <<
"Variance explained : "
1210 << round(variancePercent * 100.0) / 100.0 <<
" %";
1215 double const cumulVariancePercent
1217 ssCumul <<
"Cumulative explained variance : "
1218 << round(cumulVariancePercent * 100.0) / 100.0 <<
" %";
1222 if(printSurfaceVariance) {
1224 double surfaceVariance = computeSurfaceExplainedVariance<dataType>(
1226 double const surfaceVariancePercent
1227 = surfaceVariance / globalVariance * 100.0;
1228 std::stringstream ssSurface;
1229 ssSurface <<
"Surface Variance explained : "
1230 << round(surfaceVariancePercent * 100.0) / 100.0 <<
" %";
1234 if(printTVariances) {
1237 if(trees2.size() != 0) {
1239 barycenter,
vS_[geodesicNumber],
v2s_[geodesicNumber], barycenter2,
1244 v2s_[geodesicNumber],
1246 double const tVariancePercent = tVariance / globalVariance * 100.0;
1247 std::stringstream ssTVariance, ssCumulT;
1248 ssTVariance <<
"Explained T-Variance : "
1249 << round(tVariancePercent * 100.0) / 100.0 <<
" %";
1254 double const cumulTVariancePercent
1256 ssCumulT <<
"Cumulative explained T-Variance : "
1257 << round(cumulTVariancePercent * 100.0) / 100.0 <<
" %";
1267 std::vector<std::vector<std::vector<double>>> &v2s,
1268 bool doPrint =
true);
1271 std::vector<std::vector<std::vector<double>>> &v2s,
1272 std::vector<std::vector<double>> &v,
1273 std::vector<std::vector<double>> &v2,
1274 bool doPrint =
true);
1276 template <
class dataType>
1279 template <
class dataType>
1283 std::vector<std::vector<double>> &v,
1284 std::vector<std::vector<double>> &v2,
1285 std::vector<double> &ts,
1288 template <
class dataType>
1292 template <
class dataType>
1296 std::vector<std::vector<std::vector<double>>> &vS,
1297 std::vector<std::vector<std::vector<double>>> &v2s,
1298 std::vector<std::vector<double>> &ts);
1300 template <
class dataType>
1302 std::vector<std::vector<double>> &v,
1303 std::vector<std::vector<double>> &v2,
1304 std::vector<double> &ts,
1305 std::vector<double> &distances,
1306 bool useDoubleInput =
false,
1307 bool isFirstInput =
true);
1309 template <
class dataType>
1311 std::vector<std::vector<double>> &v,
1312 std::vector<std::vector<double>> &v2,
1313 std::vector<double> &ts);
1315 template <
class dataType>
1317 std::vector<std::vector<double>> &v,
1318 std::vector<std::vector<double>> &v2,
1320 std::vector<std::vector<double>> &trees2V,
1321 std::vector<std::vector<double>> &trees2V2,
1322 std::vector<double> &ts);
1327 template <
class dataType>
1333 std::stringstream ss;
1335 auto birthRoot = std::get<0>(birthDeathRoot);
1336 auto deathRoot = std::get<1>(birthDeathRoot);
1342 auto birth = std::get<0>(birthDeath);
1343 auto death = std::get<1>(birthDeath);
1344 if(birth < birthRoot or birth > deathRoot or death < birthRoot
1345 or death > deathRoot) {
1346 ss << tree->
printNode2<dataType>(i).str() << std::endl;
1360 printErr(
"[computePrincipalGeodesics] tree root is not min max.");
#define ENERGY_COMPARISON_TOLERANCE
Minimalist debugging class.
void setDebugMsgPrefix(const std::string &prefix)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
std::vector< std::vector< int > > trees2NodeCorr_
void computeOneDistance(ftm::MergeTree< dataType > &tree1, ftm::MergeTree< dataType > &tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matching, dataType &distance, bool isCalled=false, bool useDoubleInput=false, bool isFirstInput=true)
void getMatchingMatrix(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< ftm::idNode > > &matchingMatrix)
void computeBranchesCorrelationMatrix(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &baryMatchings, std::vector< std::vector< double > > &allTs, std::vector< std::vector< double > > &branchesCorrelationMatrix, std::vector< std::vector< double > > &persCorrelationMatrix)
void getMatchingVector(ftm::MergeTree< dataType > &barycenter, ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matchings, std::vector< ftm::idNode > &matchingVector)
unsigned int numberOfGeodesics_
bool normalizedWasserstein_
double mixDistances(dataType distance1, dataType distance2)
std::vector< std::vector< int > > treesNodeCorr_
std::vector< std::vector< double > > allTreesTs_
std::vector< std::vector< std::vector< double > > > v2s_
std::vector< std::vector< std::vector< double > > > trees2V2s_
void getMultiInterpolation(ftm::MergeTree< dataType > &barycenter, std::vector< std::vector< double * > > &vS, std::vector< std::vector< double * > > &v2s, size_t vSize, std::vector< double > &ts, ftm::MergeTree< dataType > &interpolated, bool transposeVector=true)
std::vector< std::vector< std::vector< double > > > vS_
std::vector< std::vector< double > > allTs_
std::vector< std::vector< double > > branchesCorrelationMatrix_
std::vector< std::vector< double > > persCorrelationMatrix_
std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > baryMatchings_
std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > baryMatchings2_
std::vector< std::vector< std::vector< double > > > trees2Vs_
std::vector< std::vector< double > > allScaledTs_
dataType computeReconstructionError(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &inputTrees, std::vector< std::vector< double * > > &vS, std::vector< std::vector< double * > > &v2s, size_t vSize, std::vector< std::vector< double > > &allTreesTs, std::vector< double > &reconstructionErrors, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, bool transposeVector=true)
void callGramSchmidt(std::vector< std::vector< double > > &vS, std::vector< double > &v, std::vector< double > &newV)
bool projectInitializedVectors_
double verifyOrthogonality(std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, bool doPrint=true)
void computeProjectionDistances(ftm::MergeTree< dataType > &barycenter, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< double > &ts, std::vector< double > &distances, bool useDoubleInput=false, bool isFirstInput=true)
void orthogonalProjection(std::vector< std::vector< double > > &v1, std::vector< std::vector< double > > &v2, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s)
void copyMinMaxPairVector(std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< std::vector< double > > &trees2V, std::vector< std::vector< double > > &trees2V2)
void trueGeneralizedGeodesicProjection(std::vector< std::vector< double > > &v1, std::vector< std::vector< double > > &v2)
double computeExplainedVariance(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< double > &ts, bool computeGlobalVariance=false)
double projectionStep(int geodesicNumber, ftm::MergeTree< dataType > &barycenter, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, ftm::MergeTree< dataType > &barycenter2, std::vector< std::vector< double > > &trees2V, std::vector< std::vector< double > > &trees2V2, std::vector< std::vector< std::vector< double > > > &trees2Vs, std::vector< std::vector< std::vector< double > > > &trees2V2s, bool useSecondInput, unsigned int noProjectionStep)
std::vector< double > inputToBaryDistances_
void computeBranchesCorrelationMatrix(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees)
ftm::MergeTree< double > barycenterBDT_
void computePrincipalGeodesics(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< ftm::MergeTree< dataType > > &trees2)
bool updateStep(int geodesicNumber, ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2, std::vector< std::vector< double > > &trees2V, std::vector< std::vector< double > > &trees2V2, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings2, std::vector< std::vector< std::vector< double > > > &trees2Vs, std::vector< std::vector< std::vector< double > > > &trees2V2s, std::vector< double > &ts, std::vector< std::vector< double > > &allTreesTs)
void assignmentStep(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2, std::vector< std::vector< double > > &trees2V, std::vector< std::vector< double > > &trees2V2, std::vector< std::vector< double > > &allTreesTs, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, std::vector< std::vector< std::vector< double > > > &trees2Vs, std::vector< std::vector< std::vector< double > > > &trees2V2s, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings2, std::vector< double > &ts, std::vector< double > &distances)
ftm::MergeTree< double > barycenter_
ftm::MergeTree< double > barycenterInput2_
void execute(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< ftm::MergeTree< dataType > > &trees2)
dataType computeVarianceFromDistances(std::vector< dataType > &distances)
bool updateClosedFormStep(int geodesicNumber, ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2, std::vector< std::vector< double > > &trees2V, std::vector< std::vector< double > > &trees2V2, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings2, std::vector< std::vector< std::vector< double > > > &trees2Vs, std::vector< std::vector< std::vector< double > > > &trees2V2s, std::vector< double > &ts, std::vector< std::vector< double > > &allTreesTs)
ftm::MergeTree< double > barycenterInput2BDT_
double t_allVectorCopy_time_
double regularizerCost(std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2)
double computeSurfaceExplainedVariance(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, std::vector< std::vector< double > > &ts)
MergeTreePrincipalGeodesics()
void assignmentImpl(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2, std::vector< std::vector< double > > &trees2V, std::vector< std::vector< double > > &trees2V2, std::vector< std::vector< double > > &allTreesTs, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, std::vector< std::vector< std::vector< double > > > &trees2Vs, std::vector< std::vector< std::vector< double > > > &trees2V2s, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings2, std::vector< double > &ts, std::vector< double > &distances)
void printIterationVariances(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2, int geodesicNumber, double globalVariance)
double orthogonalCost(std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2)
std::vector< std::vector< double > > inputToGeodesicsDistances_
void verifyMinMaxPair(ftm::MergeTree< dataType > &mTree1, ftm::MergeTree< dataType > &mTree)
void initVectors(int geodesicNumber, ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2, std::vector< std::vector< double > > &v1, std::vector< std::vector< double > > &v2, std::vector< std::vector< double > > &trees2V1, std::vector< std::vector< double > > &trees2V2)
void manageIndividualTs(int geodesicNumber, ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, std::vector< double > &ts, std::vector< std::vector< double > > &allTreesTs, std::vector< ftm::MergeTree< dataType > > &allInterpolated, std::vector< bool > &isUniform, std::vector< std::vector< double > > &tss, unsigned int &noUniform, bool &foundAllUniform)
double computeExplainedVarianceT(ftm::MergeTree< dataType > &barycenter, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< double > &ts)
void computeGeodesicExtremities()
double t_vectorCopy_time_
bool barycenterWasComputed_
double barycentricProjection(ftm::MergeTree< dataType > &barycenter, ftm::MergeTree< dataType > &extremity, std::vector< std::vector< double > > &v, bool isV1, bool useDoubleInput=false, bool isFirstInput=true)
double projectionCost(std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< std::vector< std::vector< double > > > &vS, std::vector< std::vector< std::vector< double > > > &v2s, double optMapCost)
void computePrincipalGeodesic(unsigned int geodesicNumber, ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &barycenter2, std::vector< ftm::MergeTree< dataType > > &trees2)
unsigned int noProjectionStep_
double computeGlobalVariance(ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees)
double optimalMappingSetProjection(ftm::MergeTree< dataType > &barycenter, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, ftm::MergeTree< dataType > &barycenter2, std::vector< std::vector< double > > &trees2V, std::vector< std::vector< double > > &trees2V2, bool useSecondInput=false)
bool convergenceStep(std::vector< double > &distances, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, dataType &oldFrechetEnergy, dataType &minFrechetEnergy, int &cptBlocked, bool &converged, double optMapCost)
bool doComputeReconstructionError_
unsigned int getGeodesicNumber()
void updateClosedForm(int geodesicNumber, ftm::MergeTree< dataType > &barycenter, std::vector< ftm::MergeTree< dataType > > &trees, std::vector< ftm::MergeTree< dataType > > &allInterpolated, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< std::vector< double > > &tss, std::vector< std::vector< double > > &vR, std::vector< std::vector< double > > &vR2, std::vector< bool > &isUniform)
idNode getNumberOfNodes() const
std::tuple< dataType, dataType > getBirthDeath(idNode nodeId)
std::stringstream printNode2(idNode nodeId, bool doPrint=true)
std::tuple< dataType, dataType > getMergedRootBirthDeath()
int getRealNumberOfNodes()
bool isNodeAlone(idNode nodeId)
std::stringstream printMergedRoot(bool doPrint=true)
std::stringstream printTreeStats(bool doPrint=true)
std::string to_string(__int128)
int scaleVector(const T *a, const T factor, T *out, const int &dimension=3)
int addVectors(const T *a, const T *b, T *out, const int &dimension=3)
T dotProductFlatten(const std::vector< std::vector< T > > &vA, const std::vector< std::vector< T > > &vB)
int flattenMultiDimensionalVector(const std::vector< std::vector< T > > &a, std::vector< T > &out)
bool isVectorUniform(const std::vector< T > &a)
T magnitudeFlatten(const std::vector< std::vector< T > > &v)
void transposeMatrix(const std::vector< std::vector< T > > &a, std::vector< std::vector< T > > &out)
int unflattenMultiDimensionalVector(const std::vector< T > &a, std::vector< std::vector< T > > &out, const int &no_columns=2)
T magnitude(const T *v, const int &dimension=3)
T distanceFlatten(const std::vector< std::vector< T > > &p0, const std::vector< std::vector< T > > &p1)
int multiAddVectorsFlatten(const std::vector< std::vector< std::vector< T > > > &a, const std::vector< std::vector< std::vector< T > > > &b, std::vector< std::vector< T > > &out)
T end(std::pair< T, T > &p)
T begin(std::pair< T, T > &p)
std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > bestMatching2
std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > bestMatching
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)