TTK
Loading...
Searching...
No Matches
ContourTreeAlignment.h
Go to the documentation of this file.
1
37
38#pragma once
39
40// base code includes
41#include <CTA_contourtree.h>
42#include <Debug.h>
43
44#include <algorithm>
45#include <memory>
46#include <random>
47
48namespace ttk {
49
50 namespace cta {
51
53 // enum Type_Match { matchNodes, matchArcs };
55
75 std::shared_ptr<ttk::cta::AlignmentTree> child1;
76 std::shared_ptr<ttk::cta::AlignmentTree> child2;
77 std::shared_ptr<ttk::cta::BinaryTree> node1;
78 std::shared_ptr<ttk::cta::BinaryTree> node2;
79 int size;
80 int height;
81 // int freq;
82 };
83
84 struct AlignmentEdge;
85
109
111 int freq;
114
115 std::vector<std::shared_ptr<ttk::cta::AlignmentEdge>> edgeList;
116
117 std::vector<std::pair<int, int>> nodeRefs;
118 };
119
144
145 std::weak_ptr<ttk::cta::AlignmentNode> node1;
146 std::weak_ptr<ttk::cta::AlignmentNode> node2;
148 float area;
149 float volume;
150 std::vector<int> region;
151 int freq;
152
153 std::vector<std::pair<int, int>> arcRefs;
154 };
155
156 } // namespace cta
157
158} // namespace ttk
159
160namespace ttk {
161
162 class ContourTreeAlignment : virtual public Debug {
163
164 public:
167 this->setDebugMsgPrefix("ContourTreeAlignment");
168 }
169
172 contourtrees.clear();
173 nodes.clear();
174 arcs.clear();
175 }
176
180 void setArcMatchMode(int mode) {
181 arcMatchMode = static_cast<ttk::cta::Mode_ArcMatch>(mode);
182 }
187 void setWeightCombinatorialMatch(float weight) {
189 }
194 void setWeightArcMatch(float weight) {
195 weightArcMatch = weight;
196 }
201 void setWeightScalarValueMatch(float weight) {
202 weightScalarValueMatch = weight;
203 }
208 void setAlignmenttreeType(int type) {
210 }
211
254 template <class scalarType>
255 int execute(const std::vector<void *> &scalarsVP,
256 const std::vector<int *> &regionSizes,
257 const std::vector<int *> &segmentationIds,
258 const std::vector<long long *> &topologies,
259 const std::vector<size_t> &nVertices,
260 const std::vector<size_t> &nEdges,
261 const std::vector<int *> &segmentations,
262 const std::vector<size_t> &segsizes,
263
264 std::vector<float> &outputVertices,
265 std::vector<long long> &outputFrequencies,
266 std::vector<long long> &outputVertexIds,
267 std::vector<long long> &outputBranchIds,
268 std::vector<long long> &outputSegmentationIds,
269 std::vector<long long> &outputArcIds,
270 std::vector<int> &outputEdges,
271 int seed);
272
274
279 bool alignTree(const std::shared_ptr<ContourTree> &t);
284 bool initialize(const std::shared_ptr<ContourTree> &t);
289 bool alignTree_consistentRoot(const std::shared_ptr<ContourTree> &t);
295 bool initialize_consistentRoot(const std::shared_ptr<ContourTree> &t,
296 int rootIdx);
297
300 std::vector<std::pair<std::vector<std::shared_ptr<ttk::cta::CTNode>>,
301 std::vector<std::shared_ptr<ttk::cta::CTEdge>>>>
302 getGraphs();
306 std::vector<std::shared_ptr<ContourTree>> getContourTrees();
307
310 std::pair<std::vector<std::shared_ptr<ttk::cta::AlignmentNode>>,
311 std::vector<std::shared_ptr<ttk::cta::AlignmentEdge>>>
316 std::shared_ptr<ttk::cta::BinaryTree> getAlignmentGraphRooted();
320
326 std::pair<float, std::shared_ptr<ttk::cta::AlignmentTree>>
327 getAlignmentBinary(const std::shared_ptr<ttk::cta::BinaryTree> &t1,
328 const std::shared_ptr<ttk::cta::BinaryTree> &t2);
329
332 void computeBranches();
333
334 protected:
335 // filter parameters
338 float weightArcMatch = 1;
341
342 // alignment graph data
343 std::vector<std::shared_ptr<ttk::cta::AlignmentNode>> nodes;
344 std::vector<std::shared_ptr<ttk::cta::AlignmentEdge>> arcs;
345
346 // iteration variables
347 std::vector<std::shared_ptr<ContourTree>> contourtrees;
348 std::vector<size_t> permutation;
349 std::shared_ptr<ttk::cta::AlignmentNode> alignmentRoot;
352
353 // functions for aligning two trees (computing the alignment value and
354 // memoization matrix)
355 float alignTreeBinary(const std::shared_ptr<ttk::cta::BinaryTree> &t1,
356 const std::shared_ptr<ttk::cta::BinaryTree> &t2,
357 std::vector<std::vector<float>> &memT,
358 std::vector<std::vector<float>> &memF);
359 float alignForestBinary(const std::shared_ptr<ttk::cta::BinaryTree> &t1,
360 const std::shared_ptr<ttk::cta::BinaryTree> &t2,
361 std::vector<std::vector<float>> &memT,
362 std::vector<std::vector<float>> &memF);
363
364 // functions for the traceback of the alignment computation (computing the
365 // actual alignment tree)
366 std::shared_ptr<ttk::cta::AlignmentTree>
367 traceAlignmentTree(const std::shared_ptr<ttk::cta::BinaryTree> &t1,
368 const std::shared_ptr<ttk::cta::BinaryTree> &t2,
369 std::vector<std::vector<float>> &memT,
370 std::vector<std::vector<float>> &memF);
371 std::vector<std::shared_ptr<ttk::cta::AlignmentTree>>
372 traceAlignmentForest(const std::shared_ptr<ttk::cta::BinaryTree> &t1,
373 const std::shared_ptr<ttk::cta::BinaryTree> &t2,
374 std::vector<std::vector<float>> &memT,
375 std::vector<std::vector<float>> &memF);
376 std::shared_ptr<ttk::cta::AlignmentTree>
377 traceNullAlignment(const std::shared_ptr<ttk::cta::BinaryTree> &t,
378 bool first);
379
380 // function that defines the local editing costs of two nodes
381 float editCost(const std::shared_ptr<ttk::cta::BinaryTree> &t1,
382 const std::shared_ptr<ttk::cta::BinaryTree> &t2);
383
384 // helper functions for tree data structures
385 bool isBinary(const std::shared_ptr<ttk::cta::Tree> &t);
386 std::shared_ptr<ttk::cta::BinaryTree>
387 rootAtNode(const std::shared_ptr<ttk::cta::AlignmentNode> &root);
388 std::shared_ptr<ttk::cta::BinaryTree>
389 computeRootedTree(const std::shared_ptr<ttk::cta::AlignmentNode> &node,
390 const std::shared_ptr<ttk::cta::AlignmentEdge> &parent,
391 int &id);
392 std::shared_ptr<ttk::cta::BinaryTree>
393 computeRootedDualTree(const std::shared_ptr<ttk::cta::AlignmentEdge> &arc,
394 bool parent1,
395 int &id);
397 const std::shared_ptr<ttk::cta::AlignmentTree> &res);
398
399 // helper functions for branch decomposition
400 std::pair<float, std::vector<std::shared_ptr<ttk::cta::AlignmentNode>>>
401 pathToMax(const std::shared_ptr<ttk::cta::AlignmentNode> &root,
402 const std::shared_ptr<ttk::cta::AlignmentNode> &parent);
403 std::pair<float, std::vector<std::shared_ptr<ttk::cta::AlignmentNode>>>
404 pathToMin(const std::shared_ptr<ttk::cta::AlignmentNode> &root,
405 const std::shared_ptr<ttk::cta::AlignmentNode> &parent);
406 };
407} // namespace ttk
408
409template <class scalarType>
411 const std::vector<void *> &scalarsVP,
412 const std::vector<int *> &regionSizes,
413 const std::vector<int *> &segmentationIds,
414 const std::vector<long long *> &topologies,
415 const std::vector<size_t> &nVertices,
416 const std::vector<size_t> &nEdges,
417 const std::vector<int *> &segmentations,
418 const std::vector<size_t> &segsizes,
419 std::vector<float> &outputVertices,
420 std::vector<long long> &outputFrequencies,
421 std::vector<long long> &outputVertexIds,
422 std::vector<long long> &outputBranchIds,
423 std::vector<long long> &outputSegmentationIds,
424 std::vector<long long> &outputArcIds,
425 std::vector<int> &outputEdges,
426 int seed) {
427
428 Timer timer;
429
430 const size_t nTrees = nVertices.size();
431
432 std::vector<float *> scalars(nTrees);
433 for(size_t t = 0; t < nTrees; t++) {
434 scalars[t] = (float *)((scalarType *)scalarsVP[t]);
435 }
436
437 // Print Input
438 {
439 this->printMsg(ttk::debug::Separator::L1); // L1 is the '=' separator
440 this->printMsg("Execute base layer");
441 this->printMsg("Computing Alignment for " + std::to_string(nTrees)
442 + " trees.");
443 }
444
445 for(size_t t = 0; t < nTrees; t++) {
447 this->printMsg("Input Tree " + std::to_string(t) + " topology:",
449
450 std::vector<std::vector<std::string>> tableLines;
451 tableLines.push_back(
452 {"cellId", "vId0", "vId1", "scalar0", "scalar1", "region", "segId"});
453 for(size_t i = 0; i < nEdges[t]; i++) {
454 const long long vertexId0 = topologies[t][i * 2 + 0];
455 const long long vertexId1 = topologies[t][i * 2 + 1];
456 const int regionSize = regionSizes[t][i];
457 const int segmentationId = segmentationIds[t][i];
458 scalarType scalarOfVertexId0 = scalars[t][vertexId0];
459 scalarType scalarOfVertexId1 = scalars[t][vertexId1];
460
461 std::vector<std::string> tableLine;
462 tableLine.push_back(std::to_string(i));
463 tableLine.push_back(std::to_string(vertexId0));
464 tableLine.push_back(std::to_string(vertexId1));
465 tableLine.push_back(std::to_string(scalarOfVertexId0));
466 tableLine.push_back(std::to_string(scalarOfVertexId1));
467 tableLine.push_back(std::to_string(regionSize));
468 tableLine.push_back(std::to_string(segmentationId));
469
470 tableLines.push_back(tableLine);
471 }
472 this->printMsg(tableLines, debug::Priority::VERBOSE);
473 }
474
475 std::vector<std::vector<std::vector<int>>> segRegions;
476 if(!segsizes.empty()) {
477 for(size_t i = 0; i < nTrees; i++) {
478 int maxSegId = -1;
479 std::vector<int> seg(segsizes[i]);
480 for(size_t j = 0; j < segsizes[i]; j++) {
481 maxSegId = std::max(maxSegId, segmentations[i][j]);
482 seg[j] = segmentations[i][j];
483 }
484 std::vector<std::vector<int>> reg(maxSegId + 1);
485 for(size_t j = 0; j < segsizes[i]; j++) {
486 reg[segmentations[i][j]].push_back(j);
487 }
488 segRegions.push_back(reg);
489 }
490 for(size_t i = 0; i < nTrees; i++) {
491 int sum = 0;
492 for(const auto &seg : segRegions[i]) {
493 sum += seg.size();
494 }
495 this->printMsg("Tree " + std::to_string(i)
496 + ", sum of segment sizes: " + std::to_string(sum));
497 sum = 0;
498 for(size_t j = 0; j < nEdges[i]; j++) {
499 sum += regionSizes[i][j];
500 }
501 this->printMsg("Tree " + std::to_string(i)
502 + ", sum of region sizes: " + std::to_string(sum));
503 }
504 }
505
506 // prepare data structures
507 contourtrees = std::vector<std::shared_ptr<ContourTree>>();
508 nodes = std::vector<std::shared_ptr<ttk::cta::AlignmentNode>>();
509 arcs = std::vector<std::shared_ptr<ttk::cta::AlignmentEdge>>();
510 int bestRootIdx{};
511
513 this->printMsg("Shuffling input trees. Used seed: " + std::to_string(seed), 0,
515
516 // permute list input trees randomly with given seed
517 permutation = std::vector<size_t>();
518 for(size_t i = 0; i < nTrees; i++) {
519 permutation.push_back(i);
520 }
521
522 // initialize random engine using user-provided seed
523 std::mt19937 random_engine{};
524 random_engine.seed(seed);
525
527 // shuffle using the random engine
528 std::shuffle(permutation.begin(), permutation.end(), random_engine);
529 }
530
531 this->printMsg(
532 "Shuffling input trees. Used seed: " + std::to_string(seed), 1);
533
534 // print permutation
535 if(this->debugLevel_ >= static_cast<int>(debug::Priority::DETAIL)) {
536 std::string permutationString = "";
537 for(size_t i = 0; i < permutation.size(); i++) {
538 permutationString += std::to_string(permutation[i])
539 + (i == permutation.size() - 1 ? "" : ",");
540 }
541 this->printMsg(
542 "Permutation: " + permutationString, debug::Priority::DETAIL);
543 }
544
545 this->printMsg("Starting alignment heuristic.");
546
547 std::tuple<std::vector<std::shared_ptr<ttk::cta::AlignmentNode>>,
548 std::vector<std::shared_ptr<ttk::cta::AlignmentEdge>>,
549 std::vector<std::shared_ptr<ContourTree>>>
550 bestAlignment;
551 float bestAlignmentValue = FLT_MAX;
552
554 printMsg("Filtering input contour trees", 0, debug::LineMode::REPLACE);
555
556 std::vector<std::shared_ptr<ContourTree>> contourtreesToAlign;
557 for(size_t i = 0; i < nTrees; i++) {
558 auto ct = std::make_shared<ContourTree>(
559 scalars[permutation[i]], regionSizes[permutation[i]],
560 segmentationIds[permutation[i]], topologies[permutation[i]],
561 nVertices[permutation[i]], nEdges[permutation[i]],
562 segRegions.empty() ? std::vector<std::vector<int>>() : segRegions[i]);
563 if(ct->isBinary()) {
564 contourtreesToAlign.push_back(ct);
565 } else {
566 this->printWrn("Input " + std::to_string(permutation[i])
567 + " not binary. Will not be aligned.");
568 }
569 printMsg("Filtering input contour trees (" + std::to_string(i) + "/"
570 + std::to_string(nTrees) + ")",
571 (float)i / (float)nTrees, debug::LineMode::REPLACE);
572 }
573 if(contourtreesToAlign.empty()) {
574
575 this->printErr("No input binary.");
576
577 return 0;
578 }
579
580 printMsg("Filtering input contour trees", 1);
581
582 for(size_t rootIdx = 0;
583 rootIdx < contourtreesToAlign[0]->getGraph().first.size(); rootIdx++) {
584
585 contourtrees.clear();
586 nodes.clear();
587 arcs.clear();
588 alignmentVal = 0;
589
591 this->printMsg("Starting alignment computation with root "
592 + std::to_string(rootIdx));
593
594 // initialize alignment with first tree
595 size_t i = 0;
596
597 this->printMsg(
598 "Initializing alignment with tree " + std::to_string(permutation[i]), 0,
600 initialize_consistentRoot(contourtreesToAlign[i], rootIdx);
601 this->printMsg(
602 "Initializing alignment with tree " + std::to_string(permutation[i]), 1,
604
606
607 this->printMsg("Initialized root is saddle, alignment aborted.");
608
609 continue;
610 }
611
612 // construct other contour tree objects and align them
613
614 i++;
615 while(i < contourtreesToAlign.size()) {
616
617 this->printMsg("Aligning tree " + std::to_string(permutation[i]), 0,
619 alignTree_consistentRoot(contourtreesToAlign[i]);
620 this->printMsg("Aligning tree " + std::to_string(permutation[i]), 1,
622
623 i++;
624 }
625
626 this->printMsg("All trees aligned. Total alignment value: "
628
629 if(alignmentVal < bestAlignmentValue) {
630
631 bestAlignmentValue = alignmentVal;
632 bestAlignment = std::make_tuple(nodes, arcs, contourtrees);
633 bestRootIdx = rootIdx;
634 }
635 }
636
637 nodes = std::get<0>(bestAlignment);
638 arcs = std::get<1>(bestAlignment);
639 contourtrees = std::get<2>(bestAlignment);
640
642 this->printMsg("Alignment iteration complete.");
643 this->printMsg("Root of optimal alignment: " + std::to_string(bestRootIdx)
644 + ".");
645 this->printMsg(
646 "Value of optimal alignment: " + std::to_string(bestAlignmentValue) + ".");
648 this->printMsg(
649 "Computing branches", 0, timer.getElapsedTime(), debug::LineMode::REPLACE);
650
652
653 this->printMsg("Computing branches", 1, timer.getElapsedTime());
655 this->printMsg("Writing output pointers", 0, timer.getElapsedTime(),
657
658 for(const auto &node : nodes) {
659
660 outputVertices.push_back(node->scalarValue);
661 outputFrequencies.push_back(node->freq);
662 outputBranchIds.push_back(node->branchID);
663 std::vector<long long> refs(nTrees, -1);
664 std::vector<long long> segRefs(nTrees, -1);
665 for(auto ref : node->nodeRefs) {
666 refs[permutation[ref.first]] = ref.second;
667 const int eId
668 = contourtrees[ref.first]->getGraph().first[ref.second]->edgeList[0];
669 segRefs[permutation[ref.first]]
670 = contourtrees[ref.first]->getGraph().second[eId]->segId;
671 }
672 for(int ref : refs) {
673 outputVertexIds.push_back(ref);
674 }
675 for(int segRef : segRefs) {
676 outputSegmentationIds.push_back(segRef);
677 }
678 }
679
680 for(const auto &edge : arcs) {
681
682 int i = 0;
683 for(const auto &node : nodes) {
684
685 if(node == edge->node1.lock()) {
686 outputEdges.push_back(i);
687 }
688
689 if(node == edge->node2.lock()) {
690 outputEdges.push_back(i);
691 }
692
693 i++;
694 }
695
696 std::vector<long long> arcRefs(nTrees, -1);
697 for(auto ref : edge->arcRefs) {
698 arcRefs[permutation[ref.first]] = ref.second;
699 }
700 for(int ref : arcRefs) {
701 outputArcIds.push_back(ref);
702 }
703 }
704 this->printMsg("Writing output pointers", 1, timer.getElapsedTime());
705
706 // Print performance
707 {
709 this->printMsg("Alignment computed in "
710 + std::to_string(timer.getElapsedTime()) + " s. ("
711 + std::to_string(threadNumber_) + " thread(s)).");
712 this->printMsg("Number of nodes in alignment: "
713 + std::to_string(nodes.size()));
714 }
715
716 return 1;
717}
TTK contourTreeAlignment processing package.
float alignTreeBinary(const std::shared_ptr< ttk::cta::BinaryTree > &t1, const std::shared_ptr< ttk::cta::BinaryTree > &t2, std::vector< std::vector< float > > &memT, std::vector< std::vector< float > > &memF)
bool alignTree_consistentRoot(const std::shared_ptr< ContourTree > &t)
~ContourTreeAlignment() override
Destructor of the Alignment Object.
std::vector< size_t > permutation
ttk::cta::Type_Alignmenttree alignmenttreeType
std::shared_ptr< ttk::cta::BinaryTree > computeRootedDualTree(const std::shared_ptr< ttk::cta::AlignmentEdge > &arc, bool parent1, int &id)
std::shared_ptr< ttk::cta::AlignmentNode > alignmentRoot
std::vector< std::shared_ptr< ttk::cta::AlignmentTree > > traceAlignmentForest(const std::shared_ptr< ttk::cta::BinaryTree > &t1, const std::shared_ptr< ttk::cta::BinaryTree > &t2, std::vector< std::vector< float > > &memT, std::vector< std::vector< float > > &memF)
std::vector< std::shared_ptr< ttk::cta::AlignmentEdge > > arcs
std::vector< std::pair< std::vector< std::shared_ptr< ttk::cta::CTNode > >, std::vector< std::shared_ptr< ttk::cta::CTEdge > > > > getGraphs()
bool initialize(const std::shared_ptr< ContourTree > &t)
std::shared_ptr< ttk::cta::AlignmentTree > traceAlignmentTree(const std::shared_ptr< ttk::cta::BinaryTree > &t1, const std::shared_ptr< ttk::cta::BinaryTree > &t2, std::vector< std::vector< float > > &memT, std::vector< std::vector< float > > &memF)
std::pair< float, std::shared_ptr< ttk::cta::AlignmentTree > > getAlignmentBinary(const std::shared_ptr< ttk::cta::BinaryTree > &t1, const std::shared_ptr< ttk::cta::BinaryTree > &t2)
void computeNewAlignmenttree(const std::shared_ptr< ttk::cta::AlignmentTree > &res)
std::pair< std::vector< std::shared_ptr< ttk::cta::AlignmentNode > >, std::vector< std::shared_ptr< ttk::cta::AlignmentEdge > > > getAlignmentGraph()
int execute(const std::vector< void * > &scalarsVP, const std::vector< int * > &regionSizes, const std::vector< int * > &segmentationIds, const std::vector< long long * > &topologies, const std::vector< size_t > &nVertices, const std::vector< size_t > &nEdges, const std::vector< int * > &segmentations, const std::vector< size_t > &segsizes, std::vector< float > &outputVertices, std::vector< long long > &outputFrequencies, std::vector< long long > &outputVertexIds, std::vector< long long > &outputBranchIds, std::vector< long long > &outputSegmentationIds, std::vector< long long > &outputArcIds, std::vector< int > &outputEdges, int seed)
float editCost(const std::shared_ptr< ttk::cta::BinaryTree > &t1, const std::shared_ptr< ttk::cta::BinaryTree > &t2)
void setWeightCombinatorialMatch(float weight)
std::vector< std::shared_ptr< ttk::cta::AlignmentNode > > nodes
bool isBinary(const std::shared_ptr< ttk::cta::Tree > &t)
bool alignTree(const std::shared_ptr< ContourTree > &t)
std::shared_ptr< ttk::cta::BinaryTree > getAlignmentGraphRooted()
float alignForestBinary(const std::shared_ptr< ttk::cta::BinaryTree > &t1, const std::shared_ptr< ttk::cta::BinaryTree > &t2, std::vector< std::vector< float > > &memT, std::vector< std::vector< float > > &memF)
void setWeightArcMatch(float weight)
ttk::cta::Mode_ArcMatch arcMatchMode
std::pair< float, std::vector< std::shared_ptr< ttk::cta::AlignmentNode > > > pathToMin(const std::shared_ptr< ttk::cta::AlignmentNode > &root, const std::shared_ptr< ttk::cta::AlignmentNode > &parent)
std::shared_ptr< ttk::cta::BinaryTree > computeRootedTree(const std::shared_ptr< ttk::cta::AlignmentNode > &node, const std::shared_ptr< ttk::cta::AlignmentEdge > &parent, int &id)
std::pair< float, std::vector< std::shared_ptr< ttk::cta::AlignmentNode > > > pathToMax(const std::shared_ptr< ttk::cta::AlignmentNode > &root, const std::shared_ptr< ttk::cta::AlignmentNode > &parent)
std::vector< std::shared_ptr< ContourTree > > getContourTrees()
bool initialize_consistentRoot(const std::shared_ptr< ContourTree > &t, int rootIdx)
std::shared_ptr< ttk::cta::AlignmentTree > traceNullAlignment(const std::shared_ptr< ttk::cta::BinaryTree > &t, bool first)
void setWeightScalarValueMatch(float weight)
std::shared_ptr< ttk::cta::BinaryTree > rootAtNode(const std::shared_ptr< ttk::cta::AlignmentNode > &root)
std::vector< std::shared_ptr< ContourTree > > contourtrees
ContourTreeAlignment()
Constructor of the Alignment Object.
Minimalist debugging class.
Definition Debug.h:88
int debugLevel_
Definition Debug.h:379
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
double getElapsedTime()
Definition Timer.h:15
Contour Tree Data Structure for an unrooted contour tree of unbounded degree for internal use from th...
std::string to_string(__int128)
Definition ripserpy.cpp:99
The Topology ToolKit.
Basic data structure for an edge of an unrooted alignment tree.
std::weak_ptr< ttk::cta::AlignmentNode > node1
std::vector< std::pair< int, int > > arcRefs
std::weak_ptr< ttk::cta::AlignmentNode > node2
Basic data structure for a node of an unrooted alignment tree.
std::vector< std::shared_ptr< ttk::cta::AlignmentEdge > > edgeList
std::vector< std::pair< int, int > > nodeRefs
Basic tree data structure for an alignment of two rooted binary trees.
std::shared_ptr< ttk::cta::BinaryTree > node1
std::shared_ptr< ttk::cta::AlignmentTree > child1
std::shared_ptr< ttk::cta::AlignmentTree > child2
std::shared_ptr< ttk::cta::BinaryTree > node2
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)