TTK
Loading...
Searching...
No Matches
FTMTreeUtils_Template.h
Go to the documentation of this file.
1
7
8#pragma once
9
10#include <FTMTree_MT.h>
11
12namespace ttk {
13 namespace ftm {
14
15 // --------------------
16 // Is
17 // --------------------
18 template <class dataType>
20 auto root = this->getRoot();
21 std::vector<idNode> rootChildren;
22 this->getChildren(root, rootChildren);
23 idNode child = rootChildren[0];
24 if(this->isFullMerge()) {
25 dataType min = std::numeric_limits<dataType>::max();
26 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i) {
27 dataType value = this->getValue<dataType>(i);
28 if(not this->isNodeAlone(i) and value < min) {
29 min = value;
30 child = i;
31 }
32 }
33 }
34 return this->getValue<dataType>(root) > this->getValue<dataType>(child);
35 }
36
37 template <class dataType>
39 double threshold,
40 std::vector<double> &excludeLower,
41 std::vector<double> &excludeHigher) const {
42 idNode treeRoot = this->getRoot();
43 dataType rootValue = this->getValue<dataType>(treeRoot);
44 dataType lowestNodeValue
45 = this->getValue<dataType>(this->getLowestNode<dataType>(treeRoot));
46 dataType rootPers
47 = (rootValue > lowestNodeValue ? rootValue - lowestNodeValue
48 : lowestNodeValue - rootValue);
49 threshold /= 100.0;
50 threshold = rootPers * threshold;
51
52 auto isImportantPairOneNode = [&](idNode node) {
53 auto pers = this->getNodePersistence<dataType>(node);
54
55 // Excluded pairs
56 bool isExcluded = false;
57 if(excludeLower.size() == excludeHigher.size())
58 for(unsigned i = 0; i < excludeLower.size(); ++i) {
59 isExcluded |= (pers > rootPers * excludeLower[i] / 100.0
60 and pers < rootPers * excludeHigher[i] / 100.0);
61 }
62 return (pers > threshold and not isExcluded);
63 };
64
65 if(isImportantPairOneNode(nodeId))
66 return true;
67
68 // Test if it is a parent of an important pair (for not persistence based
69 // branch decomposition)
70 idNode saddleNode
71 = (this->isLeaf(nodeId) ? this->getNode(nodeId)->getOrigin() : nodeId);
72 idNode leafNode
73 = (this->isLeaf(nodeId) ? nodeId : this->getNode(nodeId)->getOrigin());
74 std::queue<idNode> queue;
75 std::vector<bool> nodeDone(this->getNumberOfNodes(), false);
76 queue.emplace(leafNode);
77 while(!queue.empty()) {
78 idNode node = queue.front();
79 queue.pop();
80
81 if(isImportantPairOneNode(node))
82 return true;
83
84 nodeDone[node] = true;
85
86 idNode parent = this->getParentSafe(node);
87 if(parent != saddleNode)
88 if(not nodeDone[parent])
89 queue.emplace(parent);
90
91 std::vector<idNode> children;
92 this->getChildren(node, children);
93 for(auto child : children)
94 if(not nodeDone[child])
95 queue.emplace(child);
96 }
97
98 return false;
99 }
100
101 template <class dataType>
102 bool FTMTree_MT::isImportantPair(idNode nodeId, double threshold) const {
103 std::vector<double> excludeLower, excludeHigher;
104 return this->isImportantPair<dataType>(
105 nodeId, threshold, excludeLower, excludeHigher);
106 }
107
108 template <class dataType>
110 auto parentBirthDeath
111 = this->getBirthDeath<dataType>(this->getParentSafe(nodeId));
112 dataType parentBirth = std::get<0>(parentBirthDeath);
113 dataType parentDeath = std::get<1>(parentBirthDeath);
114 auto birthDeath = this->getBirthDeath<dataType>(nodeId);
115 dataType birth = std::get<0>(birthDeath);
116 dataType death = std::get<1>(birthDeath);
117 bool const parentInconsistent
118 = parentDeath < death or parentBirth > birth;
119 return parentInconsistent;
120 }
121
122 template <class dataType>
124 bool inconsistency = false;
125 std::queue<idNode> queue;
126 queue.emplace(this->getRoot());
127 while(!queue.empty()) {
128 idNode node = queue.front();
129 queue.pop();
130 if(!this->isRoot(node) and this->isParentInconsistent<dataType>(node)) {
131 printErr("inconsistency");
132 this->printNode2<dataType>(node);
133 this->printNode2<dataType>(this->getParentSafe(node));
134 inconsistency = true;
135 }
136 std::vector<idNode> children;
137 this->getChildren(node, children);
138 for(idNode const child : children)
139 queue.emplace(child);
140 }
141 return inconsistency;
142 }
143
144 // --------------------
145 // Get
146 // --------------------
147 template <class dataType>
149 dataType maxPers = std::numeric_limits<dataType>::lowest();
150 int maxIndex = -1;
151 auto root = this->getRoot();
152 for(unsigned int j = 0; j < this->getNumberOfNodes(); ++j) {
153 if(j != root and this->isNodeOriginDefined(j)
154 and this->getNode(j)->getOrigin() == (int)root) {
155 dataType nodePers = this->getNodePersistence<dataType>(j);
156 if(nodePers > maxPers) {
157 maxPers = nodePers;
158 maxIndex = j;
159 }
160 }
161 }
162 return maxIndex;
163 }
164
165 template <class dataType>
167 idNode lowestNode = nodeStart;
168 bool isJT = this->isJoinTree<dataType>();
169 dataType bestVal = isJT ? std::numeric_limits<dataType>::max()
170 : std::numeric_limits<dataType>::lowest();
171 std::queue<idNode> queue;
172 queue.emplace(nodeStart);
173 while(!queue.empty()) {
174 idNode node = queue.front();
175 queue.pop();
176 dataType val = this->getValue<dataType>(node);
177 if((val < bestVal and isJT) or (val > bestVal and not isJT)) {
178 lowestNode = node;
179 bestVal = val;
180 }
181 std::vector<idNode> children;
182 this->getChildren(node, children);
183 for(idNode const child : children)
184 queue.emplace(child);
185 }
186 return lowestNode;
187 }
188
189 // --------------------
190 // Persistence
191 // --------------------
192 template <class dataType>
193 std::tuple<dataType, dataType>
195 dataType scalar1 = this->getValue<dataType>(nodeId1);
196 dataType scalar2 = this->getValue<dataType>(nodeId2);
197 dataType birth = std::min(scalar1, scalar2);
198 dataType death = std::max(scalar1, scalar2);
199 return std::make_tuple(birth, death);
200 }
201
202 template <class dataType>
203 std::tuple<dataType, dataType>
205 idNode nodeId2) const {
206 auto nodeValue = this->getValue<dataType>(nodeId1);
207 auto node2Value = this->getValue<dataType>(nodeId2);
208 auto nodeBirth = (nodeValue < node2Value ? nodeId1 : nodeId2);
209 auto nodeDeath = (nodeValue < node2Value ? nodeId2 : nodeId1);
210 return std::make_tuple(nodeBirth, nodeDeath);
211 }
212
213 template <class dataType>
214 std::tuple<dataType, dataType>
216 // Avoid error if origin is not defined
217 if(this->isNodeOriginDefined(nodeId)) {
219 nodeId, this->getNode(nodeId)->getOrigin());
220 }
221 return std::make_tuple(0.0, 0.0);
222 }
223
224 template <class dataType>
225 std::tuple<ftm::idNode, ftm::idNode>
227 if(this->isNodeOriginDefined(nodeId)) {
229 nodeId, this->getNode(nodeId)->getOrigin());
230 }
231 return std::make_tuple(0.0, 0.0);
232 }
233
234 template <class dataType>
235 std::tuple<dataType, dataType> FTMTree_MT::getMergedRootBirthDeath() const {
236 if(!this->isFullMerge())
237 return this->getBirthDeath<dataType>(this->getRoot());
239 this->getRoot(), this->getMergedRootOrigin<dataType>());
240 }
241
242 template <class dataType>
243 std::tuple<ftm::idNode, ftm::idNode>
245 if(!this->isFullMerge())
246 return this->getBirthDeathNode<dataType>(this->getRoot());
248 this->getRoot(), this->getMergedRootOrigin<dataType>());
249 }
250
251 template <class dataType>
252 dataType FTMTree_MT::getBirth(idNode nodeId) const {
253 return std::get<0>(this->getBirthDeath<dataType>(nodeId));
254 }
255
256 template <class dataType>
257 dataType FTMTree_MT::getNodePersistence(idNode nodeId) const {
258 std::tuple<dataType, dataType> birthDeath
259 = this->getBirthDeath<dataType>(nodeId);
260 return std::get<1>(birthDeath) - std::get<0>(birthDeath);
261 }
262
263 template <class dataType>
265 idNode const root = this->getRoot();
266 bool const fullMerge = this->isFullMerge();
267
268 // Classic case
269 if(not fullMerge)
270 return this->getNodePersistence<dataType>(this->getRoot());
271
272 // Full merge case
273 dataType maxPers = std::numeric_limits<dataType>::lowest();
274 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i)
275 if(/*not this->isNodeAlone(i) and*/ this->isNodeOriginDefined(i)
276 and this->getNode(i)->getOrigin() == (int)root)
277 maxPers = std::max(maxPers, this->getNodePersistence<dataType>(i));
278
279 return maxPers;
280 }
281
282 template <class dataType>
284 idNode const root = this->getRoot();
285 dataType pers = std::numeric_limits<dataType>::lowest();
286 ftm::idNode nodeSecMax = -1;
287 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i) {
288 if(not this->isRoot(i) and not this->isNodeAlone(i)
289 and this->isNodeOriginDefined(i)) {
290 idNode const nodeOrigin = this->getNode(i)->getOrigin();
291 if(not(nodeOrigin == root
292 and this->getNode(nodeOrigin)->getOrigin() == (int)i)) {
293 auto nodePers = this->getNodePersistence<dataType>(i);
294 if(pers < nodePers) {
295 pers = nodePers;
296 nodeSecMax = i;
297 }
298 }
299 }
300 }
301 return nodeSecMax;
302 }
303
304 template <class dataType>
309
310 template <class dataType>
312 std::vector<std::tuple<idNode, idNode, dataType>> &pairs,
313 bool useBD) const {
314 std::vector<idNode> nodes;
315 if(useBD) {
316 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i)
317 if(!this->isNodeAlone(i) and this->getNode(i)->getOrigin() != (int)i)
318 nodes.push_back(i);
319 } else
320 this->getLeavesFromTree(nodes);
321 for(auto node : nodes) {
322 auto pers = this->getNodePersistence<dataType>(node);
323 pairs.push_back(
324 std::make_tuple(node, this->getNode(node)->getOrigin(), pers));
325 }
326 auto comp = [&](const std::tuple<idNode, idNode, dataType> a,
327 const std::tuple<idNode, idNode, dataType> b) {
328 return std::get<2>(a) < std::get<2>(b);
329 };
330 sort(pairs.begin(), pairs.end(), comp);
331 }
332
333 template <class dataType>
334 std::vector<idNode> FTMTree_MT::getMultiPersOrigins(bool useBD) const {
335 std::vector<idNode> multiPersOrigins;
336
337 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
338 this->getPersistencePairsFromTree(pairs, useBD);
339 // std::vector<idNode> origins(this->getNumberOfNodes(), -1);
340 std::vector<std::vector<idNode>> origins(this->getNumberOfNodes());
341 std::vector<bool> birthFound(this->getNumberOfNodes(), false);
342 for(auto pair : pairs) {
343 idNode const nodeBirth = std::get<0>(pair);
344 idNode const nodeDeath = std::get<1>(pair);
345
346 origins[nodeDeath].push_back(nodeBirth);
347 birthFound[nodeBirth] = true;
348 }
349
350 for(unsigned int i = 0; i < origins.size(); ++i)
351 if(birthFound[i])
352 for(auto node : origins[i])
353 multiPersOrigins.push_back(node);
354
355 return multiPersOrigins;
356 }
357
358 // --------------------
359 // Utils
360 // --------------------
361 template <class dataType>
362 std::stringstream FTMTree_MT::printNode2(idNode nodeId,
363 bool doPrint) const {
364 auto origin = this->getNode(nodeId)->getOrigin();
365 std::stringstream ss;
366 ss << "nodeId = " << nodeId << " (" << this->getValue<dataType>(nodeId)
367 << ") _ originId = " << this->getNode(nodeId)->getOrigin();
368 if(not this->isNodeIdInconsistent(origin))
369 ss << " (" << this->getValue<dataType>(origin) << ")";
370 if(doPrint)
371 printMsg(ss.str());
372 return ss;
373 }
374
375 template <class dataType>
376 std::stringstream FTMTree_MT::printMergedRoot(bool doPrint) const {
377 std::stringstream ss;
378 ss << this->getRoot() << " (" << this->getValue<dataType>(this->getRoot())
379 << ") _ ";
380 auto mergedRootOrigin = this->getMergedRootOrigin<dataType>();
381 ss << mergedRootOrigin;
382 if(not this->isNodeIdInconsistent(mergedRootOrigin))
383 ss << " (" << this->getValue<dataType>(mergedRootOrigin) << ")";
384 ss << " _ " << this->getNodePersistence<dataType>(this->getRoot());
385 if(not this->isNodeIdInconsistent(mergedRootOrigin))
386 ss << " _ " << this->getNodePersistence<dataType>(mergedRootOrigin);
387 ss << std::endl;
388 if(doPrint)
389 printMsg(ss.str());
390 return ss;
391 }
392
393 template <class dataType>
394 std::stringstream FTMTree_MT::printTreeScalars(bool printNodeAlone,
395 bool doPrint) const {
396 std::stringstream wholeSS;
397 std::streamsize const sSize = std::cout.precision();
398 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i) {
399 idNode const iOrigin
400 = this->isNodeOriginDefined(i) ? this->getNode(i)->getOrigin() : i;
401 if(printNodeAlone
402 or (not printNodeAlone
403 and (not this->isNodeAlone(i)
404 or not this->isNodeAlone(iOrigin)))) {
405 std::stringstream ss;
406 ss << i << " _ " << std::setprecision(12)
407 << this->getValue<dataType>(i);
408 if(doPrint)
409 printMsg(ss.str());
410 wholeSS << ss.str() << std::endl;
411 }
412 }
413 if(doPrint)
415 std::cout.precision(sSize);
416 return wholeSS;
417 }
418
419 template <class dataType>
420 std::stringstream FTMTree_MT::printPairsFromTree(bool useBD,
421 bool printPairs,
422 bool doPrint) const {
423 std::stringstream ss;
424 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
425 this->getPersistencePairsFromTree(pairs, useBD);
426 ss << "size=" << pairs.size() << std::endl;
427 if(printPairs)
428 for(auto pair : pairs) {
429 ss << std::get<0>(pair) << " ("
430 << this->getValue<dataType>(std::get<0>(pair)) << ") _ ";
431 ss << std::get<1>(pair) << " ("
432 << this->getValue<dataType>(std::get<1>(pair)) << ") _ ";
433 ss << std::get<2>(pair) << std::endl;
434 }
435
436 if(doPrint) {
437 printMsg(ss.str());
439 }
440 return ss;
441 }
442
443 template <class dataType>
445 bool useBD, bool printPairs, bool doPrint) const {
446 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
447 this->getPersistencePairsFromTree(pairs, useBD);
448 std::vector<int> noOrigin(this->getNumberOfNodes(), 0);
449 int noMultiPers = 0;
450 for(auto pair : pairs) {
451 noOrigin[std::get<0>(pair)]++;
452 noMultiPers += (noOrigin[std::get<0>(pair)] > 1) ? 1 : 0;
453 noOrigin[std::get<1>(pair)]++;
454 noMultiPers += (noOrigin[std::get<1>(pair)] > 1) ? 1 : 0;
455 }
456 std::stringstream ss;
457 ss << "Number of multi pers pairs : " << noMultiPers << std::endl;
458 if(printPairs) {
459 auto multiPers = this->getMultiPersOrigins<dataType>(useBD);
460 for(auto node : multiPers)
461 ss << node << std::endl;
462 }
463 if(doPrint) {
464 printMsg(ss.str());
466 }
467 return ss;
468 }
469
470 } // namespace ftm
471} // namespace ttk
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
std::stringstream printMultiPersPairsFromTree(bool useBD=false, bool printPairs=true, bool doPrint=true) const
std::tuple< dataType, dataType > getMergedRootBirthDeath() const
Node * getNode(idNode nodeId) const
Definition FTMTree_MT.h:393
const scalarType & getValue(SimplexId nodeId) const
Definition FTMTree_MT.h:339
void getChildren(idNode nodeId, std::vector< idNode > &res) const
std::tuple< ftm::idNode, ftm::idNode > getBirthDeathNode(idNode nodeId) const
std::tuple< dataType, dataType > getBirthDeathNodeFromIds(idNode nodeId1, idNode nodeId2) const
std::stringstream printNode2(idNode nodeId, bool doPrint=true) const
idNode getNumberOfNodes() const
Definition FTMTree_MT.h:389
bool isParentInconsistent(ftm::idNode nodeId) const
idNode getRoot() const
bool verifyBranchDecompositionInconsistency() const
std::stringstream printTreeScalars(bool printNodeAlone=true, bool doPrint=true) const
idNode getLowestNode(idNode nodeStart) const
ftm::idNode getSecondMaximumPersistenceNode() const
idNode getParentSafe(idNode nodeId) const
std::vector< ftm::idNode > getMultiPersOrigins(bool useBD) const
dataType getMaximumPersistence() const
dataType getSecondMaximumPersistence() const
std::tuple< ftm::idNode, ftm::idNode > getMergedRootBirthDeathNode() const
void getLeavesFromTree(std::vector< idNode > &res) const
dataType getNodePersistence(idNode nodeId) const
std::stringstream printPairsFromTree(bool useBD=false, bool printPairs=true, bool doPrint=true) const
bool isNodeOriginDefined(idNode nodeId) const
bool isLeaf(idNode nodeId) const
std::tuple< dataType, dataType > getBirthDeathFromIds(idNode nodeId1, idNode nodeId2) const
bool isRoot(idNode nodeId) const
std::tuple< dataType, dataType > getBirthDeath(idNode nodeId) const
std::stringstream printMergedRoot(bool doPrint=true) const
bool isNodeIdInconsistent(idNode nodeId) const
bool isNodeAlone(idNode nodeId) const
void getPersistencePairsFromTree(std::vector< std::tuple< ftm::idNode, ftm::idNode, dataType > > &pairs, bool useBD) const
bool isImportantPair(idNode nodeId, double threshold, std::vector< double > &excludeLower, std::vector< double > &excludeHigher) const
bool isJT() const
Definition FTMTree_MT.h:289
bool isFullMerge() const
dataType getBirth(idNode nodeId) const
SimplexId getOrigin() const
Definition FTMNode.h:64
unsigned int idNode
Node index in vect_nodes_.
TTK base package defining the standard types.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)