68#ifdef TTK_ENABLE_OPENMP
82 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>
bestMatching,
90 template <
class dataType>
96 std::vector<std::vector<double>> &v1,
97 std::vector<std::vector<double>> &v2,
98 std::vector<std::vector<double>> &trees2V1,
99 std::vector<std::vector<double>> &trees2V2) {
100 auto initializedVectorsProjection
102 std::vector<std::vector<double>> &_v,
103 std::vector<std::vector<double>> &_v2,
104 std::vector<std::vector<std::vector<double>>> &_vS,
105 std::vector<std::vector<std::vector<double>>> &_v2s,
107 std::vector<std::vector<double>> &_trees2V,
108 std::vector<std::vector<double>> &_trees2V2,
109 std::vector<std::vector<std::vector<double>>> &_trees2Vs,
110 std::vector<std::vector<std::vector<double>>> &_trees2V2s,
111 bool _useSecondInput,
unsigned int _noProjectionStep) {
112 return this->
projectionStep(_geodesicNumber, _barycenter, _v, _v2,
113 _vS, _v2s, _barycenter2, _trees2V,
114 _trees2V2, _trees2Vs, _trees2V2s,
115 _useSecondInput, _noProjectionStep);
118 MergeTreeAxesAlgorithmBase::initVectors<dataType>(
119 geodesicNumber, barycenter, trees, barycenter2, trees2, v1, v2,
123 initializedVectorsProjection);
130 std::vector<std::vector<std::vector<double>>> &v2s,
131 std::vector<std::vector<double>> &v,
132 std::vector<std::vector<double>> &v2) {
137 std::vector<std::vector<double>> &v2) {
145 std::vector<std::vector<double>> &v2,
146 std::vector<std::vector<std::vector<double>>> &vS,
147 std::vector<std::vector<std::vector<double>>> &v2s,
156 template <
class dataType>
159 std::vector<std::vector<double>> &v,
161 bool useDoubleInput =
false,
162 bool isFirstInput =
true) {
165 double const t = (isV1 ? -1.0 : 1.0);
167 std::vector<std::tuple<ftm::idNode, ftm::idNode, double>> matching;
169 std::vector<ftm::idNode> matchingVector;
173 useDoubleInput, isFirstInput);
177 std::numeric_limits<ftm::idNode>::max());
179 std::vector<std::vector<double>>
const oriV = v;
183 auto matched = matchingVector[i];
185 = getParametrizedBirthDeath<dataType>(barycenterTree, i);
186 dataType birthBary = std::get<0>(birthDeathBary);
187 dataType deathBary = std::get<1>(birthDeathBary);
188 std::vector<double> newV{0.0, 0.0};
189 if(matched != std::numeric_limits<ftm::idNode>::max()) {
190 auto birthDeathMatched
191 = getParametrizedBirthDeath<dataType>(extremityTree, matched);
192 newV[0] = std::get<0>(birthDeathMatched);
193 newV[1] = std::get<1>(birthDeathMatched);
195 dataType projec = (birthBary + deathBary) / 2.0;
199 newV[0] = (newV[0] - birthBary) * t;
200 newV[1] = (newV[1] - deathBary) * t;
209 template <
class dataType>
212 std::vector<std::vector<double>> &v,
213 std::vector<std::vector<double>> &v2,
215 std::vector<std::vector<double>> &trees2V,
216 std::vector<std::vector<double>> &trees2V2,
217 bool useSecondInput =
false) {
218 std::vector<ftm::MergeTree<dataType>> extremities(
219 (useSecondInput ? 4 : 2));
220 getInterpolation<dataType>(barycenter, v, v2, 0.0, extremities[0]);
221 getInterpolation<dataType>(barycenter, v, v2, 1.0, extremities[1]);
223 getInterpolation<dataType>(
224 barycenter2, trees2V, trees2V2, 0.0, extremities[2]);
225 getInterpolation<dataType>(
226 barycenter2, trees2V, trees2V2, 1.0, extremities[3]);
229#ifdef TTK_ENABLE_OPENMP
230#pragma omp parallel for schedule(dynamic) \
231 num_threads(this->threadNumber_) if(parallelize_)
233 for(
unsigned int i = 0; i < extremities.size(); ++i) {
234 bool isFirstInput = (i < 2);
236 = (i < 2 ? barycenter : barycenter2);
237 std::vector<std::vector<double>> &vToUse
238 = (i == 0 ? v : (i == 1 ? v2 : (i == 2 ? trees2V : trees2V2)));
241 (i % 2 == 0), useSecondInput, isFirstInput);
249 std::vector<std::vector<double>> &v2) {
250 std::vector<double> v1_flatten, v2_flatten;
255 double const beta = v2_norm / (v1_norm + v2_norm);
256 std::vector<double> v;
266 std::vector<std::vector<double>> &v2,
267 std::vector<std::vector<std::vector<double>>> &vS,
268 std::vector<std::vector<std::vector<double>>> &v2s) {
270 std::vector<std::vector<double>> sumVs;
274 std::vector<double> v1_flatten, v2_flatten, v1_proj, v2_proj;
288 template <
class dataType>
292 std::vector<std::vector<double>> &v,
293 std::vector<std::vector<double>> &v2,
294 std::vector<std::vector<std::vector<double>>> &vS,
295 std::vector<std::vector<std::vector<double>>> &v2s,
297 std::vector<std::vector<double>> &trees2V,
298 std::vector<std::vector<double>> &trees2V2,
299 std::vector<std::vector<std::vector<double>>> &trees2Vs,
300 std::vector<std::vector<std::vector<double>>> &trees2V2s,
302 unsigned int noProjectionStep) {
303 std::vector<std::vector<std::vector<double>>> vSConcat, v2sConcat;
308 for(
unsigned int j = 0; j < vS.size(); ++j) {
310 vSConcat[j].
end(), trees2Vs[j].
begin(), trees2Vs[j].
end());
312 v2sConcat[j].
end(), trees2V2s[j].
begin(), trees2V2s[j].
end());
317 double optMapCost = 0.0;
318 for(
unsigned i = 0; i < noProjectionStep; ++i) {
319 std::vector<std::vector<double>> vOld = v, v2Old = v2;
326 barycenter, v, v2, barycenter2, trees2V, trees2V2, useSecondInput);
331 std::vector<std::vector<double>> vConcat, v2Concat;
335 vConcat.insert(vConcat.end(), trees2V.begin(), trees2V.end());
337 v2Concat.insert(v2Concat.end(), trees2V2.begin(), trees2V2.end());
353 if(geodesicNumber != 0) {
368 for(
unsigned int j = 0; j < v.size(); ++j) {
372 for(
unsigned int j = 0; j < trees2V.size(); ++j) {
373 trees2V[j] = vConcat[v.size() + j];
374 trees2V2[j] = v2Concat[v.size() + j];
385 template <
class dataType>
389 std::vector<std::vector<double>> &v,
390 std::vector<std::vector<double>> &v2,
393 std::vector<std::vector<double>> &trees2V,
394 std::vector<std::vector<double>> &trees2V2,
395 std::vector<std::vector<double>> &allTreesTs,
396 std::vector<std::vector<std::vector<double>>> &vS,
397 std::vector<std::vector<std::vector<double>>> &v2s,
398 std::vector<std::vector<std::vector<double>>> &trees2Vs,
399 std::vector<std::vector<std::vector<double>>> &trees2V2s,
400 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
402 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
404 std::vector<double> &ts,
405 std::vector<double> &distances) {
406 std::vector<std::vector<Compare>> best(
407 trees.size(), std::vector<Compare>(
k_));
409#ifdef TTK_ENABLE_OPENMP
410#pragma omp parallel num_threads(this->threadNumber_) if(parallelize_) \
413#pragma omp single nowait
416 for(
unsigned int k = 0; k <
k_; ++k) {
417 for(
unsigned int i = 0; i < trees.size(); ++i) {
418#ifdef TTK_ENABLE_OPENMP
419#pragma omp task shared(best) firstprivate(i, k)
422 double const kT = (k % 2 == 0 ? k / 2 :
k_ - 1 - (int)(k / 2));
423 double t = 1.0 / (
k_ - 1) * kT;
425 dataType distance, distance2;
427 auto tsToUse = (allTreesTs.size() == 0 ? std::vector<double>()
430 barycenter, vS, v2s, v, v2, tsToUse, t, interpolated);
432 computeOneDistance<dataType>(interpolated, trees[i],
433 best[i][kT].bestMatching,
435 if(trees2.size() != 0) {
438 trees2V, trees2V2, tsToUse, t,
440 computeOneDistance<dataType>(
441 interpolated2, trees2[i], best[i][kT].bestMatching2,
445 best[i][kT].bestDistance = distance;
446 best[i][kT].bestIndex = kT;
448#ifdef TTK_ENABLE_OPENMP
453#ifdef TTK_ENABLE_OPENMP
458 for(
unsigned int i = 0; i < trees.size(); ++i) {
459#ifdef TTK_ENABLE_OPENMP
460#pragma omp task firstprivate(i)
463 double bestDistance = std::numeric_limits<double>::max();
465 for(
unsigned int k = 0; k <
k_; ++k) {
466 if(best[i][k].bestDistance < bestDistance) {
468 bestDistance = best[i][k].bestDistance;
471 matchings[i] = best[i][bestIndex].bestMatching;
472 if(trees2.size() != 0)
473 matchings2[i] = best[i][bestIndex].bestMatching2;
474 ts[i] = best[i][bestIndex].bestIndex * 1.0 / (
k_ - 1);
475 distances[i] = best[i][bestIndex].bestDistance;
476#ifdef TTK_ENABLE_OPENMP
480#ifdef TTK_ENABLE_OPENMP
486 template <
class dataType>
490 std::vector<std::vector<double>> &v,
491 std::vector<std::vector<double>> &v2,
494 std::vector<std::vector<double>> &trees2V,
495 std::vector<std::vector<double>> &trees2V2,
496 std::vector<std::vector<double>> &allTreesTs,
497 std::vector<std::vector<std::vector<double>>> &vS,
498 std::vector<std::vector<std::vector<double>>> &v2s,
499 std::vector<std::vector<std::vector<double>>> &trees2Vs,
500 std::vector<std::vector<std::vector<double>>> &trees2V2s,
501 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
503 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
505 std::vector<double> &ts,
506 std::vector<double> &distances) {
508 matchings.resize(trees.size());
509 matchings2.resize(trees2.size());
510 ts.resize(trees.size());
511 distances.resize(trees.size());
514 assignmentImpl<dataType>(barycenter, trees, v, v2, barycenter2, trees2,
515 trees2V, trees2V2, allTreesTs, vS, v2s, trees2Vs,
516 trees2V2s, matchings, matchings2, ts, distances);
522 template <
class dataType>
528 std::vector<std::vector<double>> &v,
529 std::vector<std::vector<double>> &v2,
530 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
532 std::vector<std::vector<double>> &tss,
533 std::vector<std::vector<double>> &vR,
534 std::vector<std::vector<double>> &vR2,
535 std::vector<bool> &isUniform) {
539 std::vector<ftm::FTMTree_MT *> ftmTrees, allInterpolatedTrees;
540 ttk::ftm::mergeTreeToFTMTree<dataType>(trees, ftmTrees);
541 if(geodesicNumber != 0) {
542 ttk::ftm::mergeTreeToFTMTree<dataType>(
543 allInterpolated, allInterpolatedTrees);
547 std::vector<std::vector<ftm::idNode>> matchingMatrix;
564 = getParametrizedBirthDeath<dataType>(barycenterTree, i);
565 dataType birthBary = std::get<0>(birthDeathBary);
566 dataType deathBary = std::get<1>(birthDeathBary);
567 dataType projec = (birthBary + deathBary) / 2.0;
568 std::vector<dataType> allBirthBary(trees.size(), birthBary);
569 std::vector<dataType> allDeathBary(trees.size(), deathBary);
570 std::vector<dataType> allProjec(trees.size(), projec);
572 if(geodesicNumber != 0)
573 for(
unsigned int j = 0; j < trees.size(); ++j) {
574 auto birthDeathInterpol
575 = getParametrizedBirthDeath<dataType>(allInterpolatedTrees[j], i);
576 allBirthBary[j] = std::get<0>(birthDeathInterpol);
577 allDeathBary[j] = std::get<1>(birthDeathInterpol);
578 allProjec[j] = (allBirthBary[j] + allDeathBary[j]) / 2.0;
582 std::vector<std::vector<dataType>> allMatched(trees.size());
583 for(
unsigned int j = 0; j < trees.size(); ++j) {
584 dataType birth = allProjec[j];
585 dataType death = allProjec[j];
586 if(matchingMatrix[i][j] != std::numeric_limits<ftm::idNode>::max()) {
587 auto birthDeath = getParametrizedBirthDeath<dataType>(
588 ftmTrees[j], matchingMatrix[i][j]);
589 birth = std::get<0>(birthDeath);
590 death = std::get<1>(birthDeath);
592 allMatched[j].resize(2);
593 allMatched[j][0] = birth;
594 allMatched[j][1] = death;
598 double ti_squared = 0.0, one_min_ti_squared = 0.0, ti_one_min_ti = 0.0;
599 for(
auto t : tss[i]) {
601 one_min_ti_squared += (1 - t) * (1 - t);
602 ti_one_min_ti += t * (1 - t);
606 double multBirthV1 = 0.0, multDeathV1 = 0.0, multBirthV2 = 0.0,
608 for(
unsigned int j = 0; j < trees.size(); ++j) {
610 += tss[i][j] * (allMatched[j][0] - allBirthBary[j]) / ti_squared;
612 += tss[i][j] * (allMatched[j][1] - allDeathBary[j]) / ti_squared;
613 multBirthV2 += (1 - tss[i][j]) * (-allMatched[j][0] + allBirthBary[j])
614 / one_min_ti_squared;
615 multDeathV2 += (1 - tss[i][j]) * (-allMatched[j][1] + allDeathBary[j])
616 / one_min_ti_squared;
620 double newBirthV1 = 0.0, newDeathV1 = 0.0, newBirthV2 = 0.0,
622 for(
unsigned int j = 0; j < trees.size(); ++j) {
623 newBirthV1 += (1 - tss[i][j])
624 * (-allMatched[j][0] + allBirthBary[j]
625 + tss[i][j] * multBirthV1);
626 newDeathV1 += (1 - tss[i][j])
627 * (-allMatched[j][1] + allDeathBary[j]
628 + tss[i][j] * multDeathV1);
629 newBirthV2 += tss[i][j]
630 * (allMatched[j][0] - allBirthBary[j]
631 + (1 - tss[i][j]) * multBirthV2);
632 newDeathV2 += tss[i][j]
633 * (allMatched[j][1] - allDeathBary[j]
634 + (1 - tss[i][j]) * multDeathV2);
636 double const divisorV1
637 = one_min_ti_squared - ti_one_min_ti * ti_one_min_ti / ti_squared;
638 double const divisorV2
639 = ti_squared - ti_one_min_ti * ti_one_min_ti / one_min_ti_squared;
640 newBirthV1 /= divisorV1;
641 newDeathV1 /= divisorV1;
642 newBirthV2 /= divisorV2;
643 newDeathV2 /= divisorV2;
646 v[i][0] = newBirthV1;
647 v[i][1] = newDeathV1;
648 v2[i][0] = newBirthV2;
649 v2[i][1] = newDeathV2;
653 template <
class dataType>
658 std::vector<std::vector<double>> &v,
659 std::vector<std::vector<double>> &v2,
660 std::vector<std::vector<std::vector<double>>> &vS,
661 std::vector<std::vector<std::vector<double>>> &v2s,
662 std::vector<double> &ts,
663 std::vector<std::vector<double>> &allTreesTs,
665 std::vector<bool> &isUniform,
666 std::vector<std::vector<double>> &tss,
667 unsigned int &noUniform,
668 bool &foundAllUniform) {
670 allInterpolated.resize(trees.size());
671 if(geodesicNumber != 0) {
672 for(
unsigned int i = 0; i < trees.size(); ++i)
674 barycenter, vS, v2s, allTreesTs[i], allInterpolated[i]);
679 foundAllUniform =
true;
686 for(
unsigned int j = 0; j < tss[i].size(); ++j) {
688 = (geodesicNumber != 0 ? allInterpolated[j] : barycenter);
689 tss[i][j] = getTNew<dataType>(treeToUse, v, v2, i, ts[j]);
692 noUniform += isUniform[i];
693 foundAllUniform &= isUniform[i];
697 template <
class dataType>
702 std::vector<std::vector<double>> &v,
703 std::vector<std::vector<double>> &v2,
704 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
706 std::vector<std::vector<std::vector<double>>> &vS,
707 std::vector<std::vector<std::vector<double>>> &v2s,
710 std::vector<std::vector<double>> &trees2V,
711 std::vector<std::vector<double>> &trees2V2,
712 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
714 std::vector<std::vector<std::vector<double>>> &trees2Vs,
715 std::vector<std::vector<std::vector<double>>> &trees2V2s,
716 std::vector<double> &ts,
717 std::vector<std::vector<double>> &allTreesTs) {
719 std::vector<ftm::MergeTree<dataType>> allInterpolated, allInterpolated2;
720 std::vector<bool> isUniform, isUniform2;
721 std::vector<std::vector<double>> tss, tss2;
722 unsigned int noUniform;
723 bool foundAllUniform;
725 allTreesTs, allInterpolated, isUniform, tss, noUniform,
727 if(trees2.size() != 0) {
728 unsigned int noUniform2;
729 bool foundAllUniform2;
731 trees2V2, trees2Vs, trees2V2s, ts, allTreesTs,
732 allInterpolated2, isUniform2, tss2, noUniform2,
734 noUniform += noUniform2;
735 foundAllUniform &= foundAllUniform2;
738 if(foundAllUniform) {
739 printMsg(
"All projection coefficients are the same.");
740 printMsg(
"New vectors will be initialized.");
742 initVectors(geodesicNumber, barycenter, trees, barycenter2, trees2, v,
743 v2, trees2V, trees2V2);
746 std::vector<std::vector<double>> vR, vR2, trees2VR, trees2VR2;
748 printMsg(
"Found " + std::to_string(noUniform)
749 +
" uniform coefficients.");
750 initVectors(geodesicNumber, barycenter, trees, barycenter2, trees2, vR,
751 vR2, trees2VR, trees2VR2);
755 v2, matchings, tss, vR, vR2, isUniform);
756 if(trees2.size() != 0) {
758 trees2V, trees2V2, matchings2, tss2, trees2VR,
759 trees2VR2, isUniform2);
765 template <
class dataType>
770 std::vector<std::vector<double>> &v,
771 std::vector<std::vector<double>> &v2,
772 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
774 std::vector<std::vector<std::vector<double>>> &vS,
775 std::vector<std::vector<std::vector<double>>> &v2s,
778 std::vector<std::vector<double>> &trees2V,
779 std::vector<std::vector<double>> &trees2V2,
780 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
782 std::vector<std::vector<std::vector<double>>> &trees2Vs,
783 std::vector<std::vector<std::vector<double>>> &trees2V2s,
784 std::vector<double> &ts,
785 std::vector<std::vector<double>> &allTreesTs) {
786 return updateClosedFormStep<dataType>(
787 geodesicNumber, barycenter, trees, v, v2, matchings, vS, v2s,
788 barycenter2, trees2, trees2V, trees2V2, matchings2, trees2Vs, trees2V2s,
795 template <
class dataType>
797 std::vector<std::vector<double>> &v,
798 std::vector<std::vector<double>> &v2,
799 dataType &oldFrechetEnergy,
800 dataType &minFrechetEnergy,
804 bool isBestEnergy =
false;
807 double frechetEnergy = 0;
808 for(
unsigned int i = 0; i < distances.size(); ++i)
809 frechetEnergy += distances[i] * distances[i] / distances.size();
810 std::stringstream ssEnergy;
811 ssEnergy <<
"Energy = " << frechetEnergy;
815 std::stringstream ssReg;
817 ssReg <<
"Prop. cost = " << reg;
821 std::stringstream ssOrthoCost;
823 ssOrthoCost <<
"Ortho. cost = " << orthoCost;
827 std::stringstream ssOptMapCost;
828 ssOptMapCost <<
"Map. cost = " << optMapCost;
833 tol = oldFrechetEnergy / 125.0;
834 converged = std::abs(frechetEnergy - oldFrechetEnergy) < tol;
835 oldFrechetEnergy = frechetEnergy;
838 minFrechetEnergy = frechetEnergy;
843 cptBlocked += (minFrechetEnergy < frechetEnergy) ? 1 : 0;
844 converged = (cptBlocked >= 10);
850 template <
class dataType>
860 std::vector<std::vector<double>> v, v2, trees2V, trees2V2;
861 initVectors<dataType>(geodesicNumber, barycenter, trees, barycenter2,
862 trees2, v, v2, trees2V, trees2V2);
866 std::vector<std::vector<double>> bestV, bestV2, bestTrees2V, bestTrees2V2;
867 std::vector<double> bestTs, bestDistances;
868 int bestIteration = 0;
871 dataType oldFrechetEnergy, minFrechetEnergy;
872 int cptBlocked, iteration = 0;
873 auto initLoop = [&]() {
874 oldFrechetEnergy = -1;
875 minFrechetEnergy = std::numeric_limits<dataType>::max();
882 double optMapCost = 0.0;
883 bool converged =
false;
884 while(not converged) {
885 std::stringstream ss;
886 ss <<
"Iteration " << iteration;
893 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
894 matchings, matchings2;
895 std::vector<double> ts, distances;
896 assignmentStep(barycenter, trees, v, v2, barycenter2, trees2, trees2V,
898 matchings, matchings2, ts, distances);
900 allTs_[geodesicNumber] = ts;
905 minFrechetEnergy, cptBlocked, converged,
911 bestTrees2V = trees2V;
912 bestTrees2V2 = trees2V2;
914 bestDistances = distances;
915 bestIteration = iteration;
925 =
updateStep(geodesicNumber, barycenter, trees, v, v2, matchings,
vS_,
926 v2s_, barycenter2, trees2, trees2V, trees2V2, matchings2,
939 barycenter2, trees2V, trees2V2,
trees2Vs_,
950 printMsg(
"Best energy is " + std::to_string(minFrechetEnergy)
951 +
" (iteration " + std::to_string(bestIteration) +
" / "
952 + std::to_string(iteration) +
")");
958 trees2V = bestTrees2V;
959 trees2V2 = bestTrees2V2;
961 allTs_[geodesicNumber] = bestTs;
971 template <
class dataType>
984 if(trees2.size() != 0) {
985 std::vector<double> baryDistances2;
999 printMsg(
"KeepState is enabled and barycenter was already computed");
1000 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
1002 if(trees2.size() != 0) {
1003 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
1008 mergeTreeTemplateToDouble(barycenter,
barycenter_);
1009 if(trees2.size() != 0) {
1015 double const globalVariance
1020 if(trees2.size() != 0)
1023 std::stringstream ss;
1024 ss <<
numberOfAxes_ <<
" principal geodesics are asked but only "
1025 << maxNoGeodesics <<
" can be computed.";
1027 printMsg(
"(the maximum is twice the number of persistence pairs in the "
1033 unsigned int const oldNoGeod =
allTs_.size();
1055 "KeepState is enabled, restart the computation at geodesic number "
1056 + std::to_string(oldNoGeod));
1060 for(
unsigned int geodNum = oldNoGeod; geodNum <
numberOfAxes_;
1063 std::stringstream ss;
1064 ss <<
"Compute geodesic " << geodNum;
1068 computePrincipalGeodesic<dataType>(
1069 geodNum, barycenter, trees, barycenter2, trees2);
1073 barycenter, trees, barycenter2, trees2, geodNum, globalVariance);
1077 template <
class dataType>
1083 if(trees2.size() != 0)
1091 computePrincipalGeodesics<dataType>(trees, trees2);
1096 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
barycenter_, barycenter);
1099 computeGeodesicExtremities<dataType>();
1102 computeBranchesCorrelationMatrix<dataType>(barycenter, trees);
1108 std::stringstream ss;
1109 ss <<
"Reconstruction Error = " << reconstructionError;
1116 if(trees2.size() != 0)
1120 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
barycenter_, barycenter);
1121 for(
unsigned int i = 0; i < trees.size(); ++i) {
1122 postprocessingPipeline<dataType>(&(trees[i].tree));
1123 convertBranchDecompositionMatching<dataType>(
1126 for(
unsigned int i = 0; i < trees2.size(); ++i)
1127 postprocessingPipeline<dataType>(&(trees2[i].tree));
1134 std::vector<std::vector<double>> &v2,
1135 std::vector<std::vector<double>> &trees2V,
1136 std::vector<std::vector<double>> &trees2V2) {
1139 trees2V[root2] = v[root];
1140 trees2V2[root2] = v2[root];
1143 template <
class dataType>
1147 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
barycenter_, barycenter);
1149 ttk::ftm::mergeTreeDoubleToTemplate<dataType>(
1151#ifdef TTK_ENABLE_OPENMP
1152#pragma omp parallel for schedule(dynamic) \
1153 num_threads(this->threadNumber_) if(parallelize_)
1157 getInterpolation<dataType>(
1158 barycenter,
vS_[i],
v2s_[i], 0.0, extremityV1);
1159 getInterpolation<dataType>(
1160 barycenter,
vS_[i],
v2s_[i], 1.0, extremityV2);
1167 getInterpolation<dataType>(
1169 getInterpolation<dataType>(
1177 for(
unsigned int j = 0; j <
allTs_[i].size(); ++j)
1182 template <
class dataType>
1194 template <
class dataType>
1200 double globalVariance) {
1201 bool const printOriginalVariances =
false;
1202 bool const printSurfaceVariance =
false;
1203 bool const printTVariances =
true;
1205 if(printOriginalVariances) {
1207 double variance = computeExplainedVariance<dataType>(
1208 barycenter, trees,
vS_[geodesicNumber],
v2s_[geodesicNumber],
1210 double const variancePercent = variance / globalVariance * 100.0;
1211 std::stringstream ssVariance, ssCumul;
1212 ssVariance <<
"Variance explained : "
1213 << round(variancePercent * 100.0) / 100.0 <<
" %";
1218 double const cumulVariancePercent
1220 ssCumul <<
"Cumulative explained variance : "
1221 << round(cumulVariancePercent * 100.0) / 100.0 <<
" %";
1225 if(printSurfaceVariance) {
1227 double surfaceVariance = computeSurfaceExplainedVariance<dataType>(
1229 double const surfaceVariancePercent
1230 = surfaceVariance / globalVariance * 100.0;
1231 std::stringstream ssSurface;
1232 ssSurface <<
"Surface Variance explained : "
1233 << round(surfaceVariancePercent * 100.0) / 100.0 <<
" %";
1237 if(printTVariances) {
1240 if(trees2.size() != 0) {
1242 barycenter,
vS_[geodesicNumber],
v2s_[geodesicNumber], barycenter2,
1247 v2s_[geodesicNumber],
1249 double const tVariancePercent = tVariance / globalVariance * 100.0;
1250 std::stringstream ssTVariance, ssCumulT;
1251 ssTVariance <<
"Explained T-Variance : "
1252 << round(tVariancePercent * 100.0) / 100.0 <<
" %";
1257 double const cumulTVariancePercent
1259 ssCumulT <<
"Cumulative explained T-Variance : "
1260 << round(cumulTVariancePercent * 100.0) / 100.0 <<
" %";
1270 std::vector<std::vector<std::vector<double>>> &v2s,
1271 bool doPrint =
true);
1274 std::vector<std::vector<std::vector<double>>> &v2s,
1275 std::vector<std::vector<double>> &v,
1276 std::vector<std::vector<double>> &v2,
1277 bool doPrint =
true);
1279 template <
class dataType>
1282 template <
class dataType>
1286 std::vector<std::vector<double>> &v,
1287 std::vector<std::vector<double>> &v2,
1288 std::vector<double> &ts,
1291 template <
class dataType>
1295 template <
class dataType>
1299 std::vector<std::vector<std::vector<double>>> &vS,
1300 std::vector<std::vector<std::vector<double>>> &v2s,
1301 std::vector<std::vector<double>> &ts);
1303 template <
class dataType>
1305 std::vector<std::vector<double>> &v,
1306 std::vector<std::vector<double>> &v2,
1307 std::vector<double> &ts,
1308 std::vector<double> &distances,
1309 bool useDoubleInput =
false,
1310 bool isFirstInput =
true);
1312 template <
class dataType>
1314 std::vector<std::vector<double>> &v,
1315 std::vector<std::vector<double>> &v2,
1316 std::vector<double> &ts);
1318 template <
class dataType>
1320 std::vector<std::vector<double>> &v,
1321 std::vector<std::vector<double>> &v2,
1323 std::vector<std::vector<double>> &trees2V,
1324 std::vector<std::vector<double>> &trees2V2,
1325 std::vector<double> &ts);
1330 template <
class dataType>
1336 std::stringstream ss;
1338 auto birthRoot = std::get<0>(birthDeathRoot);
1339 auto deathRoot = std::get<1>(birthDeathRoot);
1345 auto birth = std::get<0>(birthDeath);
1346 auto death = std::get<1>(birthDeath);
1347 if(birth < birthRoot or birth > deathRoot or death < birthRoot
1348 or death > deathRoot) {
1349 ss << tree->
printNode2<dataType>(i).str() << std::endl;
1363 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)
unsigned int numberOfAxes_
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)
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)
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)