68#ifdef TTK_ENABLE_OPENMP
69 omp_set_max_active_levels(100);
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);
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);
175 barycenter, extremity, matching, matchingVector);
178 std::numeric_limits<ftm::idNode>::max());
180 std::vector<std::vector<double>>
const oriV = v;
184 auto matched = matchingVector[i];
187 dataType birthBary = std::get<0>(birthDeathBary);
188 dataType deathBary = std::get<1>(birthDeathBary);
189 std::vector<double> newV{0.0, 0.0};
190 if(matched != std::numeric_limits<ftm::idNode>::max()) {
191 auto birthDeathMatched
193 newV[0] = std::get<0>(birthDeathMatched);
194 newV[1] = std::get<1>(birthDeathMatched);
196 dataType projec = (birthBary + deathBary) / 2.0;
200 newV[0] = (newV[0] - birthBary) * t;
201 newV[1] = (newV[1] - deathBary) * t;
210 template <
class dataType>
213 std::vector<std::vector<double>> &v,
214 std::vector<std::vector<double>> &v2,
216 std::vector<std::vector<double>> &trees2V,
217 std::vector<std::vector<double>> &trees2V2,
218 bool useSecondInput =
false) {
219 std::vector<ftm::MergeTree<dataType>> extremities(
220 (useSecondInput ? 4 : 2));
225 barycenter2, trees2V, trees2V2, 0.0, extremities[2]);
227 barycenter2, trees2V, trees2V2, 1.0, extremities[3]);
230#ifdef TTK_ENABLE_OPENMP
231#pragma omp parallel for schedule(dynamic) \
232 num_threads(this->threadNumber_) if(parallelize_)
234 for(
unsigned int i = 0; i < extremities.size(); ++i) {
235 bool isFirstInput = (i < 2);
237 = (i < 2 ? barycenter : barycenter2);
238 std::vector<std::vector<double>> &vToUse
239 = (i == 0 ? v : (i == 1 ? v2 : (i == 2 ? trees2V : trees2V2)));
242 (i % 2 == 0), useSecondInput, isFirstInput);
250 std::vector<std::vector<double>> &v2) {
251 std::vector<double> v1_flatten, v2_flatten;
256 double const beta = v2_norm / (v1_norm + v2_norm);
257 std::vector<double> v;
267 std::vector<std::vector<double>> &v2,
268 std::vector<std::vector<std::vector<double>>> &vS,
269 std::vector<std::vector<std::vector<double>>> &v2s) {
271 std::vector<std::vector<double>> sumVs;
275 std::vector<double> v1_flatten, v2_flatten, v1_proj, v2_proj;
289 template <
class dataType>
293 std::vector<std::vector<double>> &v,
294 std::vector<std::vector<double>> &v2,
295 std::vector<std::vector<std::vector<double>>> &vS,
296 std::vector<std::vector<std::vector<double>>> &v2s,
298 std::vector<std::vector<double>> &trees2V,
299 std::vector<std::vector<double>> &trees2V2,
300 std::vector<std::vector<std::vector<double>>> &trees2Vs,
301 std::vector<std::vector<std::vector<double>>> &trees2V2s,
303 unsigned int noProjectionStep) {
304 std::vector<std::vector<std::vector<double>>> vSConcat, v2sConcat;
309 for(
unsigned int j = 0; j < vS.size(); ++j) {
311 vSConcat[j].
end(), trees2Vs[j].
begin(), trees2Vs[j].
end());
313 v2sConcat[j].
end(), trees2V2s[j].
begin(), trees2V2s[j].
end());
318 double optMapCost = 0.0;
319 for(
unsigned i = 0; i < noProjectionStep; ++i) {
320 std::vector<std::vector<double>> vOld = v, v2Old = v2;
327 barycenter, v, v2, barycenter2, trees2V, trees2V2, useSecondInput);
332 std::vector<std::vector<double>> vConcat, v2Concat;
336 vConcat.insert(vConcat.end(), trees2V.begin(), trees2V.end());
338 v2Concat.insert(v2Concat.end(), trees2V2.begin(), trees2V2.end());
354 if(geodesicNumber != 0) {
369 for(
unsigned int j = 0; j < v.size(); ++j) {
373 for(
unsigned int j = 0; j < trees2V.size(); ++j) {
374 trees2V[j] = vConcat[v.size() + j];
375 trees2V2[j] = v2Concat[v.size() + j];
386 template <
class dataType>
390 std::vector<std::vector<double>> &v,
391 std::vector<std::vector<double>> &v2,
394 std::vector<std::vector<double>> &trees2V,
395 std::vector<std::vector<double>> &trees2V2,
396 std::vector<std::vector<double>> &allTreesTs,
397 std::vector<std::vector<std::vector<double>>> &vS,
398 std::vector<std::vector<std::vector<double>>> &v2s,
399 std::vector<std::vector<std::vector<double>>> &trees2Vs,
400 std::vector<std::vector<std::vector<double>>> &trees2V2s,
401 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
403 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
405 std::vector<double> &ts,
406 std::vector<double> &distances) {
407 std::vector<std::vector<Compare>> best(
408 trees.size(), std::vector<Compare>(
k_));
410#ifdef TTK_ENABLE_OPENMP
411#pragma omp parallel num_threads(this->threadNumber_) if(parallelize_) \
414#pragma omp single nowait
417 for(
unsigned int k = 0; k <
k_; ++k) {
418 for(
unsigned int i = 0; i < trees.size(); ++i) {
419#ifdef TTK_ENABLE_OPENMP
420#pragma omp task shared(best) firstprivate(i, k)
423 double const kT = (k % 2 == 0 ? k / 2 :
k_ - 1 - (int)(k / 2));
424 double t = 1.0 / (
k_ - 1) * kT;
426 dataType distance, distance2;
428 auto tsToUse = (allTreesTs.size() == 0 ? std::vector<double>()
431 barycenter, vS, v2s, v, v2, tsToUse, t, interpolated);
434 best[i][kT].bestMatching,
436 if(trees2.size() != 0) {
439 trees2V, trees2V2, tsToUse, t,
442 interpolated2, trees2[i], best[i][kT].bestMatching2,
446 best[i][kT].bestDistance = distance;
447 best[i][kT].bestIndex = kT;
449#ifdef TTK_ENABLE_OPENMP
454#ifdef TTK_ENABLE_OPENMP
459 for(
unsigned int i = 0; i < trees.size(); ++i) {
460#ifdef TTK_ENABLE_OPENMP
461#pragma omp task firstprivate(i)
464 double bestDistance = std::numeric_limits<double>::max();
466 for(
unsigned int k = 0; k <
k_; ++k) {
467 if(best[i][k].bestDistance < bestDistance) {
469 bestDistance = best[i][k].bestDistance;
472 matchings[i] = best[i][bestIndex].bestMatching;
473 if(trees2.size() != 0)
474 matchings2[i] = best[i][bestIndex].bestMatching2;
475 ts[i] = best[i][bestIndex].bestIndex * 1.0 / (
k_ - 1);
476 distances[i] = best[i][bestIndex].bestDistance;
477#ifdef TTK_ENABLE_OPENMP
481#ifdef TTK_ENABLE_OPENMP
487 template <
class dataType>
491 std::vector<std::vector<double>> &v,
492 std::vector<std::vector<double>> &v2,
495 std::vector<std::vector<double>> &trees2V,
496 std::vector<std::vector<double>> &trees2V2,
497 std::vector<std::vector<double>> &allTreesTs,
498 std::vector<std::vector<std::vector<double>>> &vS,
499 std::vector<std::vector<std::vector<double>>> &v2s,
500 std::vector<std::vector<std::vector<double>>> &trees2Vs,
501 std::vector<std::vector<std::vector<double>>> &trees2V2s,
502 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
504 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
506 std::vector<double> &ts,
507 std::vector<double> &distances) {
509 matchings.resize(trees.size());
510 matchings2.resize(trees2.size());
511 ts.resize(trees.size());
512 distances.resize(trees.size());
516 trees2V, trees2V2, allTreesTs, vS, v2s, trees2Vs,
517 trees2V2s, matchings, matchings2, ts, distances);
523 template <
class dataType>
529 std::vector<std::vector<double>> &v,
530 std::vector<std::vector<double>> &v2,
531 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
533 std::vector<std::vector<double>> &tss,
534 std::vector<std::vector<double>> &vR,
535 std::vector<std::vector<double>> &vR2,
536 std::vector<bool> &isUniform) {
540 std::vector<ftm::FTMTree_MT *> ftmTrees, allInterpolatedTrees;
542 if(geodesicNumber != 0) {
544 allInterpolated, allInterpolatedTrees);
548 std::vector<std::vector<ftm::idNode>> matchingMatrix;
566 dataType birthBary = std::get<0>(birthDeathBary);
567 dataType deathBary = std::get<1>(birthDeathBary);
568 dataType projec = (birthBary + deathBary) / 2.0;
569 std::vector<dataType> allBirthBary(trees.size(), birthBary);
570 std::vector<dataType> allDeathBary(trees.size(), deathBary);
571 std::vector<dataType> allProjec(trees.size(), projec);
573 if(geodesicNumber != 0)
574 for(
unsigned int j = 0; j < trees.size(); ++j) {
575 auto birthDeathInterpol
577 allBirthBary[j] = std::get<0>(birthDeathInterpol);
578 allDeathBary[j] = std::get<1>(birthDeathInterpol);
579 allProjec[j] = (allBirthBary[j] + allDeathBary[j]) / 2.0;
583 std::vector<std::vector<dataType>> allMatched(trees.size());
584 for(
unsigned int j = 0; j < trees.size(); ++j) {
585 dataType birth = allProjec[j];
586 dataType death = allProjec[j];
587 if(matchingMatrix[i][j] != std::numeric_limits<ftm::idNode>::max()) {
589 ftmTrees[j], matchingMatrix[i][j]);
590 birth = std::get<0>(birthDeath);
591 death = std::get<1>(birthDeath);
593 allMatched[j].resize(2);
594 allMatched[j][0] = birth;
595 allMatched[j][1] = death;
599 double ti_squared = 0.0, one_min_ti_squared = 0.0, ti_one_min_ti = 0.0;
600 for(
auto t : tss[i]) {
602 one_min_ti_squared += (1 - t) * (1 - t);
603 ti_one_min_ti += t * (1 - t);
607 double multBirthV1 = 0.0, multDeathV1 = 0.0, multBirthV2 = 0.0,
609 for(
unsigned int j = 0; j < trees.size(); ++j) {
611 += tss[i][j] * (allMatched[j][0] - allBirthBary[j]) / ti_squared;
613 += tss[i][j] * (allMatched[j][1] - allDeathBary[j]) / ti_squared;
614 multBirthV2 += (1 - tss[i][j]) * (-allMatched[j][0] + allBirthBary[j])
615 / one_min_ti_squared;
616 multDeathV2 += (1 - tss[i][j]) * (-allMatched[j][1] + allDeathBary[j])
617 / one_min_ti_squared;
621 double newBirthV1 = 0.0, newDeathV1 = 0.0, newBirthV2 = 0.0,
623 for(
unsigned int j = 0; j < trees.size(); ++j) {
624 newBirthV1 += (1 - tss[i][j])
625 * (-allMatched[j][0] + allBirthBary[j]
626 + tss[i][j] * multBirthV1);
627 newDeathV1 += (1 - tss[i][j])
628 * (-allMatched[j][1] + allDeathBary[j]
629 + tss[i][j] * multDeathV1);
630 newBirthV2 += tss[i][j]
631 * (allMatched[j][0] - allBirthBary[j]
632 + (1 - tss[i][j]) * multBirthV2);
633 newDeathV2 += tss[i][j]
634 * (allMatched[j][1] - allDeathBary[j]
635 + (1 - tss[i][j]) * multDeathV2);
637 double const divisorV1
638 = one_min_ti_squared - ti_one_min_ti * ti_one_min_ti / ti_squared;
639 double const divisorV2
640 = ti_squared - ti_one_min_ti * ti_one_min_ti / one_min_ti_squared;
641 newBirthV1 /= divisorV1;
642 newDeathV1 /= divisorV1;
643 newBirthV2 /= divisorV2;
644 newDeathV2 /= divisorV2;
647 v[i][0] = newBirthV1;
648 v[i][1] = newDeathV1;
649 v2[i][0] = newBirthV2;
650 v2[i][1] = newDeathV2;
654 template <
class dataType>
659 std::vector<std::vector<double>> &v,
660 std::vector<std::vector<double>> &v2,
661 std::vector<std::vector<std::vector<double>>> &vS,
662 std::vector<std::vector<std::vector<double>>> &v2s,
663 std::vector<double> &ts,
664 std::vector<std::vector<double>> &allTreesTs,
666 std::vector<bool> &isUniform,
667 std::vector<std::vector<double>> &tss,
668 unsigned int &noUniform,
669 bool &foundAllUniform) {
671 allInterpolated.resize(trees.size());
672 if(geodesicNumber != 0) {
673 for(
unsigned int i = 0; i < trees.size(); ++i)
675 barycenter, vS, v2s, allTreesTs[i], allInterpolated[i]);
680 foundAllUniform =
true;
687 for(
unsigned int j = 0; j < tss[i].size(); ++j) {
689 = (geodesicNumber != 0 ? allInterpolated[j] : barycenter);
693 noUniform += isUniform[i];
694 foundAllUniform &= isUniform[i];
698 template <
class dataType>
703 std::vector<std::vector<double>> &v,
704 std::vector<std::vector<double>> &v2,
705 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
707 std::vector<std::vector<std::vector<double>>> &vS,
708 std::vector<std::vector<std::vector<double>>> &v2s,
711 std::vector<std::vector<double>> &trees2V,
712 std::vector<std::vector<double>> &trees2V2,
713 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
715 std::vector<std::vector<std::vector<double>>> &trees2Vs,
716 std::vector<std::vector<std::vector<double>>> &trees2V2s,
717 std::vector<double> &ts,
718 std::vector<std::vector<double>> &allTreesTs) {
720 std::vector<ftm::MergeTree<dataType>> allInterpolated, allInterpolated2;
721 std::vector<bool> isUniform, isUniform2;
722 std::vector<std::vector<double>> tss, tss2;
723 unsigned int noUniform;
724 bool foundAllUniform;
726 allTreesTs, allInterpolated, isUniform, tss, noUniform,
728 if(trees2.size() != 0) {
729 unsigned int noUniform2;
730 bool foundAllUniform2;
732 trees2V2, trees2Vs, trees2V2s, ts, allTreesTs,
733 allInterpolated2, isUniform2, tss2, noUniform2,
735 noUniform += noUniform2;
736 foundAllUniform &= foundAllUniform2;
739 if(foundAllUniform) {
740 printMsg(
"All projection coefficients are the same.");
741 printMsg(
"New vectors will be initialized.");
743 initVectors(geodesicNumber, barycenter, trees, barycenter2, trees2, v,
744 v2, trees2V, trees2V2);
747 std::vector<std::vector<double>> vR, vR2, trees2VR, trees2VR2;
749 printMsg(
"Found " + std::to_string(noUniform)
750 +
" uniform coefficients.");
751 initVectors(geodesicNumber, barycenter, trees, barycenter2, trees2, vR,
752 vR2, trees2VR, trees2VR2);
756 v2, matchings, tss, vR, vR2, isUniform);
757 if(trees2.size() != 0) {
759 trees2V, trees2V2, matchings2, tss2, trees2VR,
760 trees2VR2, isUniform2);
766 template <
class dataType>
771 std::vector<std::vector<double>> &v,
772 std::vector<std::vector<double>> &v2,
773 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
775 std::vector<std::vector<std::vector<double>>> &vS,
776 std::vector<std::vector<std::vector<double>>> &v2s,
779 std::vector<std::vector<double>> &trees2V,
780 std::vector<std::vector<double>> &trees2V2,
781 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
783 std::vector<std::vector<std::vector<double>>> &trees2Vs,
784 std::vector<std::vector<std::vector<double>>> &trees2V2s,
785 std::vector<double> &ts,
786 std::vector<std::vector<double>> &allTreesTs) {
788 geodesicNumber, barycenter, trees, v, v2, matchings, vS, v2s,
789 barycenter2, trees2, trees2V, trees2V2, matchings2, trees2Vs, trees2V2s,
796 template <
class dataType>
798 std::vector<std::vector<double>> &v,
799 std::vector<std::vector<double>> &v2,
800 dataType &oldFrechetEnergy,
801 dataType &minFrechetEnergy,
805 bool isBestEnergy =
false;
808 double frechetEnergy = 0;
809 for(
unsigned int i = 0; i < distances.size(); ++i)
810 frechetEnergy += distances[i] * distances[i] / distances.size();
811 std::stringstream ssEnergy;
812 ssEnergy <<
"Energy = " << frechetEnergy;
816 std::stringstream ssReg;
818 ssReg <<
"Prop. cost = " << reg;
822 std::stringstream ssOrthoCost;
824 ssOrthoCost <<
"Ortho. cost = " << orthoCost;
828 std::stringstream ssOptMapCost;
829 ssOptMapCost <<
"Map. cost = " << optMapCost;
834 tol = oldFrechetEnergy / 125.0;
835 converged = std::abs(frechetEnergy - oldFrechetEnergy) < tol;
836 oldFrechetEnergy = frechetEnergy;
839 minFrechetEnergy = frechetEnergy;
844 cptBlocked += (minFrechetEnergy < frechetEnergy) ? 1 : 0;
845 converged = (cptBlocked >= 10);
851 template <
class dataType>
861 std::vector<std::vector<double>> v, v2, trees2V, trees2V2;
863 trees2, v, v2, trees2V, trees2V2);
867 std::vector<std::vector<double>> bestV, bestV2, bestTrees2V, bestTrees2V2;
868 std::vector<double> bestTs, bestDistances;
869 int bestIteration = 0;
872 dataType oldFrechetEnergy, minFrechetEnergy;
873 int cptBlocked, iteration = 0;
874 auto initLoop = [&]() {
875 oldFrechetEnergy = -1;
876 minFrechetEnergy = std::numeric_limits<dataType>::max();
883 double optMapCost = 0.0;
884 bool converged =
false;
885 while(not converged) {
886 std::stringstream ss;
887 ss <<
"Iteration " << iteration;
894 std::vector<std::vector<std::tuple<ftm::idNode, ftm::idNode, double>>>
895 matchings, matchings2;
896 std::vector<double> ts, distances;
897 assignmentStep(barycenter, trees, v, v2, barycenter2, trees2, trees2V,
899 matchings, matchings2, ts, distances);
901 allTs_[geodesicNumber] = ts;
906 minFrechetEnergy, cptBlocked, converged,
912 bestTrees2V = trees2V;
913 bestTrees2V2 = trees2V2;
915 bestDistances = distances;
916 bestIteration = iteration;
926 =
updateStep(geodesicNumber, barycenter, trees, v, v2, matchings,
vS_,
927 v2s_, barycenter2, trees2, trees2V, trees2V2, matchings2,
940 barycenter2, trees2V, trees2V2,
trees2Vs_,
951 printMsg(
"Best energy is " + std::to_string(minFrechetEnergy)
952 +
" (iteration " + std::to_string(bestIteration) +
" / "
953 + std::to_string(iteration) +
")");
959 trees2V = bestTrees2V;
960 trees2V2 = bestTrees2V2;
962 allTs_[geodesicNumber] = bestTs;
972 template <
class dataType>
985 if(trees2.size() != 0) {
986 std::vector<double> baryDistances2;
1000 printMsg(
"KeepState is enabled and barycenter was already computed");
1003 if(trees2.size() != 0) {
1009 mergeTreeTemplateToDouble(barycenter,
barycenter_);
1010 if(trees2.size() != 0) {
1016 double const globalVariance
1021 if(trees2.size() != 0)
1024 std::stringstream ss;
1025 ss <<
numberOfAxes_ <<
" principal geodesics are asked but only "
1026 << maxNoGeodesics <<
" can be computed.";
1028 printMsg(
"(the maximum is twice the number of persistence pairs in the "
1034 unsigned int const oldNoGeod =
allTs_.size();
1056 "KeepState is enabled, restart the computation at geodesic number "
1057 + std::to_string(oldNoGeod));
1061 for(
unsigned int geodNum = oldNoGeod; geodNum <
numberOfAxes_;
1064 std::stringstream ss;
1065 ss <<
"Compute geodesic " << geodNum;
1070 geodNum, barycenter, trees, barycenter2, trees2);
1074 barycenter, trees, barycenter2, trees2, geodNum, globalVariance);
1078 template <
class dataType>
1084 if(trees2.size() != 0)
1109 std::stringstream ss;
1110 ss <<
"Reconstruction Error = " << reconstructionError;
1117 if(trees2.size() != 0)
1122 for(
unsigned int i = 0; i < trees.size(); ++i) {
1127 for(
unsigned int i = 0; i < trees2.size(); ++i)
1135 std::vector<std::vector<double>> &v2,
1136 std::vector<std::vector<double>> &trees2V,
1137 std::vector<std::vector<double>> &trees2V2) {
1140 trees2V[root2] = v[root];
1141 trees2V2[root2] = v2[root];
1144 template <
class dataType>
1152#ifdef TTK_ENABLE_OPENMP
1153#pragma omp parallel for schedule(dynamic) \
1154 num_threads(this->threadNumber_) if(parallelize_)
1159 barycenter,
vS_[i],
v2s_[i], 0.0, extremityV1);
1161 barycenter,
vS_[i],
v2s_[i], 1.0, extremityV2);
1178 for(
unsigned int j = 0; j <
allTs_[i].size(); ++j)
1183 template <
class dataType>
1195 template <
class dataType>
1201 double globalVariance) {
1202 bool const printOriginalVariances =
false;
1203 bool const printSurfaceVariance =
false;
1204 bool const printTVariances =
true;
1206 if(printOriginalVariances) {
1209 barycenter, trees,
vS_[geodesicNumber],
v2s_[geodesicNumber],
1211 double const variancePercent = variance / globalVariance * 100.0;
1212 std::stringstream ssVariance, ssCumul;
1213 ssVariance <<
"Variance explained : "
1214 << round(variancePercent * 100.0) / 100.0 <<
" %";
1219 double const cumulVariancePercent
1221 ssCumul <<
"Cumulative explained variance : "
1222 << round(cumulVariancePercent * 100.0) / 100.0 <<
" %";
1226 if(printSurfaceVariance) {
1230 double const surfaceVariancePercent
1231 = surfaceVariance / globalVariance * 100.0;
1232 std::stringstream ssSurface;
1233 ssSurface <<
"Surface Variance explained : "
1234 << round(surfaceVariancePercent * 100.0) / 100.0 <<
" %";
1238 if(printTVariances) {
1241 if(trees2.size() != 0) {
1243 barycenter,
vS_[geodesicNumber],
v2s_[geodesicNumber], barycenter2,
1248 v2s_[geodesicNumber],
1250 double const tVariancePercent = tVariance / globalVariance * 100.0;
1251 std::stringstream ssTVariance, ssCumulT;
1252 ssTVariance <<
"Explained T-Variance : "
1253 << round(tVariancePercent * 100.0) / 100.0 <<
" %";
1258 double const cumulTVariancePercent
1260 ssCumulT <<
"Cumulative explained T-Variance : "
1261 << round(cumulTVariancePercent * 100.0) / 100.0 <<
" %";
1271 std::vector<std::vector<std::vector<double>>> &v2s,
1272 bool doPrint =
true);
1275 std::vector<std::vector<std::vector<double>>> &v2s,
1276 std::vector<std::vector<double>> &v,
1277 std::vector<std::vector<double>> &v2,
1278 bool doPrint =
true);
1280 template <
class dataType>
1283 template <
class dataType>
1287 std::vector<std::vector<double>> &v,
1288 std::vector<std::vector<double>> &v2,
1289 std::vector<double> &ts,
1292 template <
class dataType>
1296 template <
class dataType>
1300 std::vector<std::vector<std::vector<double>>> &vS,
1301 std::vector<std::vector<std::vector<double>>> &v2s,
1302 std::vector<std::vector<double>> &ts);
1304 template <
class dataType>
1306 std::vector<std::vector<double>> &v,
1307 std::vector<std::vector<double>> &v2,
1308 std::vector<double> &ts,
1309 std::vector<double> &distances,
1310 bool useDoubleInput =
false,
1311 bool isFirstInput =
true);
1313 template <
class dataType>
1315 std::vector<std::vector<double>> &v,
1316 std::vector<std::vector<double>> &v2,
1317 std::vector<double> &ts);
1319 template <
class dataType>
1321 std::vector<std::vector<double>> &v,
1322 std::vector<std::vector<double>> &v2,
1324 std::vector<std::vector<double>> &trees2V,
1325 std::vector<std::vector<double>> &trees2V2,
1326 std::vector<double> &ts);
1331 template <
class dataType>
1337 std::stringstream ss;
1339 auto birthRoot = std::get<0>(birthDeathRoot);
1340 auto deathRoot = std::get<1>(birthDeathRoot);
1346 auto birth = std::get<0>(birthDeath);
1347 auto death = std::get<1>(birthDeath);
1348 if(birth < birthRoot or birth > deathRoot or death < birthRoot
1349 or death > deathRoot) {
1350 ss << tree->
printNode2<dataType>(i).str() << std::endl;
1364 printErr(
"[computePrincipalGeodesics] tree root is not min max.");
#define ENERGY_COMPARISON_TOLERANCE
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 computeOneBarycenter(std::vector< ftm::MergeTree< dataType > > &trees, ftm::MergeTree< dataType > &baryMergeTree, std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > &matchings, std::vector< double > &finalDistances, double barycenterSizeLimitPercent, unsigned int barycenterMaximumNumberOfPairs, int barycenterInitIndex, bool oneIter, bool useDoubleInput=false, bool isFirstInput=true)
void computeOneDistance(const ftm::MergeTree< dataType > &tree1, const 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 preprocessingTrees(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< std::vector< int > > &nodeCorr, bool useMinMaxPairT=true)
void computeBranchesCorrelationMatrix(const 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)
int initVectors(int axeNumber, 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, int newVectorOffset, std::vector< double > &inputToOriginDistances, 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< double > > &inputToAxesDistances, 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, bool projectInitializedVectors, F initializedVectorsProjection)
void convertBranchDecompositionMatching(ftm::FTMTree_MT *tree1, ftm::FTMTree_MT *tree2, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &outputMatching)
bool normalizedWasserstein_
double mixDistances(dataType distance1, dataType distance2)
void postprocessingPipeline(ftm::FTMTree_MT *tree)
std::vector< std::vector< int > > treesNodeCorr_
MergeTreePrincipalGeodesicsBase()
std::vector< std::vector< double > > allTreesTs_
std::vector< std::vector< std::vector< double > > > v2s_
double getTNew(ftm::MergeTree< dataType > &barycenter, std::vector< std::vector< double > > &v, std::vector< std::vector< double > > &v2, int i, double t)
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_
void getInterpolation(ftm::MergeTree< dataType > &barycenter, std::vector< double * > &v, std::vector< double * > &v2, size_t vSize, double t, ftm::MergeTree< dataType > &interpolated, bool transposeVector=true)
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)
std::tuple< dataType, dataType > getMergedRootBirthDeath() const
std::stringstream printNode2(idNode nodeId, bool doPrint=true) const
idNode getNumberOfNodes() const
std::stringstream printTreeStats(bool doPrint=true) const
int getRealNumberOfNodes() const
std::tuple< dataType, dataType > getBirthDeath(idNode nodeId) const
std::stringstream printMergedRoot(bool doPrint=true) const
bool isNodeAlone(idNode nodeId) const
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)
void getMatchingMatrix(const 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 getMatchingVector(const ftm::MergeTree< dataType > &barycenter, const ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matchings, std::vector< ftm::idNode > &matchingVector)
void mergeTreeToFTMTree(std::vector< MergeTree< dataType > > &trees, std::vector< ftm::FTMTree_MT * > &treesT)
void mergeTreeDoubleToTemplate(MergeTree< double > &mt, MergeTree< dataType > &newMt)
TTK base package defining the standard types.
std::tuple< dataType, dataType > getParametrizedBirthDeath(ftm::FTMTree_MT *tree, ftm::idNode node, bool normalize)
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)