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) {
42 dataType rootPers = this->getNodePersistence<dataType>(this->getRoot());
43 if(threshold > 1)
44 threshold /= 100.0;
45 threshold = rootPers * threshold;
46 auto pers = this->getNodePersistence<dataType>(nodeId);
47
48 // Excluded pairs
49 bool isExcluded = false;
50 if(excludeLower.size() == excludeHigher.size())
51 for(unsigned i = 0; i < excludeLower.size(); ++i) {
52 isExcluded |= (pers > rootPers * excludeLower[i] / 100.0
53 and pers < rootPers * excludeHigher[i] / 100.0);
54 }
55
56 return pers > threshold and not isExcluded;
57 }
58
59 template <class dataType>
60 bool FTMTree_MT::isImportantPair(idNode nodeId, double threshold) {
61 std::vector<double> excludeLower, excludeHigher;
62 return this->isImportantPair<dataType>(
63 nodeId, threshold, excludeLower, excludeHigher);
64 }
65
66 template <class dataType>
68 auto parentBirthDeath
69 = this->getBirthDeath<dataType>(this->getParentSafe(nodeId));
70 dataType parentBirth = std::get<0>(parentBirthDeath);
71 dataType parentDeath = std::get<1>(parentBirthDeath);
72 auto birthDeath = this->getBirthDeath<dataType>(nodeId);
73 dataType birth = std::get<0>(birthDeath);
74 dataType death = std::get<1>(birthDeath);
75 bool const parentInconsistent
76 = parentDeath < death or parentBirth > birth;
77 return parentInconsistent;
78 }
79
80 template <class dataType>
82 bool inconsistency = false;
83 std::queue<idNode> queue;
84 queue.emplace(this->getRoot());
85 while(!queue.empty()) {
86 idNode node = queue.front();
87 queue.pop();
88 if(!this->isRoot(node) and this->isParentInconsistent<dataType>(node)) {
89 printErr("inconsistency");
90 this->printNode2<dataType>(node);
91 this->printNode2<dataType>(this->getParentSafe(node));
92 inconsistency = true;
93 }
94 std::vector<idNode> children;
95 this->getChildren(node, children);
96 for(idNode const child : children)
97 queue.emplace(child);
98 }
99 return inconsistency;
100 }
101
102 // --------------------
103 // Get
104 // --------------------
105 template <class dataType>
107 dataType maxPers = std::numeric_limits<dataType>::lowest();
108 int maxIndex = -1;
109 auto root = this->getRoot();
110 for(unsigned int j = 0; j < this->getNumberOfNodes(); ++j) {
111 if(j != root and this->isNodeOriginDefined(j)
112 and this->getNode(j)->getOrigin() == (int)root) {
113 dataType nodePers = this->getNodePersistence<dataType>(j);
114 if(nodePers > maxPers) {
115 maxPers = nodePers;
116 maxIndex = j;
117 }
118 }
119 }
120 return maxIndex;
121 }
122
123 template <class dataType>
125 idNode lowestNode = nodeStart;
126 bool isJT = this->isJoinTree<dataType>();
127 dataType bestVal = isJT ? std::numeric_limits<dataType>::max()
128 : std::numeric_limits<dataType>::lowest();
129 std::queue<idNode> queue;
130 queue.emplace(nodeStart);
131 while(!queue.empty()) {
132 idNode node = queue.front();
133 queue.pop();
134 dataType val = this->getValue<dataType>(node);
135 if((val < bestVal and isJT) or (val > bestVal and not isJT)) {
136 lowestNode = node;
137 bestVal = val;
138 }
139 std::vector<idNode> children;
140 this->getChildren(node, children);
141 for(idNode const child : children)
142 queue.emplace(child);
143 }
144 return lowestNode;
145 }
146
147 // --------------------
148 // Persistence
149 // --------------------
150 template <class dataType>
151 std::tuple<dataType, dataType>
153 dataType scalar1 = this->getValue<dataType>(nodeId1);
154 dataType scalar2 = this->getValue<dataType>(nodeId2);
155 dataType birth = std::min(scalar1, scalar2);
156 dataType death = std::max(scalar1, scalar2);
157 return std::make_tuple(birth, death);
158 }
159
160 template <class dataType>
161 std::tuple<dataType, dataType>
163 auto nodeValue = this->getValue<dataType>(nodeId1);
164 auto node2Value = this->getValue<dataType>(nodeId2);
165 auto nodeBirth = (nodeValue < node2Value ? nodeId1 : nodeId2);
166 auto nodeDeath = (nodeValue < node2Value ? nodeId2 : nodeId1);
167 return std::make_tuple(nodeBirth, nodeDeath);
168 }
169
170 template <class dataType>
171 std::tuple<dataType, dataType> FTMTree_MT::getBirthDeath(idNode nodeId) {
172 // Avoid error if origin is not defined
173 if(this->isNodeOriginDefined(nodeId)) {
174 return this->getBirthDeathFromIds<dataType>(
175 nodeId, this->getNode(nodeId)->getOrigin());
176 }
177 return std::make_tuple(0.0, 0.0);
178 }
179
180 template <class dataType>
181 std::tuple<ftm::idNode, ftm::idNode>
183 if(this->isNodeOriginDefined(nodeId)) {
184 return this->getBirthDeathNodeFromIds<dataType>(
185 nodeId, this->getNode(nodeId)->getOrigin());
186 }
187 return std::make_tuple(0.0, 0.0);
188 }
189
190 template <class dataType>
191 std::tuple<dataType, dataType> FTMTree_MT::getMergedRootBirthDeath() {
192 if(!this->isFullMerge())
193 return this->getBirthDeath<dataType>(this->getRoot());
194 return this->getBirthDeathFromIds<dataType>(
195 this->getRoot(), this->getMergedRootOrigin<dataType>());
196 }
197
198 template <class dataType>
199 std::tuple<ftm::idNode, ftm::idNode>
201 if(!this->isFullMerge())
202 return this->getBirthDeathNode<dataType>(this->getRoot());
203 return this->getBirthDeathNodeFromIds<dataType>(
204 this->getRoot(), this->getMergedRootOrigin<dataType>());
205 }
206
207 template <class dataType>
208 dataType FTMTree_MT::getBirth(idNode nodeId) {
209 return std::get<0>(this->getBirthDeath<dataType>(nodeId));
210 }
211
212 template <class dataType>
214 std::tuple<dataType, dataType> birthDeath
215 = this->getBirthDeath<dataType>(nodeId);
216 return std::get<1>(birthDeath) - std::get<0>(birthDeath);
217 }
218
219 template <class dataType>
221 idNode const root = this->getRoot();
222 bool const fullMerge = this->isFullMerge();
223
224 // Classic case
225 if(not fullMerge)
226 return this->getNodePersistence<dataType>(this->getRoot());
227
228 // Full merge case
229 dataType maxPers = std::numeric_limits<dataType>::lowest();
230 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i)
231 if(/*not this->isNodeAlone(i) and*/ this->isNodeOriginDefined(i)
232 and this->getNode(i)->getOrigin() == (int)root)
233 maxPers = std::max(maxPers, this->getNodePersistence<dataType>(i));
234
235 return maxPers;
236 }
237
238 template <class dataType>
240 idNode const root = this->getRoot();
241 dataType pers = std::numeric_limits<dataType>::lowest();
242 ftm::idNode nodeSecMax = -1;
243 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i) {
244 if(not this->isRoot(i) and not this->isNodeAlone(i)
245 and this->isNodeOriginDefined(i)) {
246 idNode const nodeOrigin = this->getNode(i)->getOrigin();
247 if(not(nodeOrigin == root
248 and this->getNode(nodeOrigin)->getOrigin() == (int)i)) {
249 auto nodePers = this->getNodePersistence<dataType>(i);
250 if(pers < nodePers) {
251 pers = nodePers;
252 nodeSecMax = i;
253 }
254 }
255 }
256 }
257 return nodeSecMax;
258 }
259
260 template <class dataType>
262 return this->getNodePersistence<dataType>(
263 this->getSecondMaximumPersistenceNode<dataType>());
264 }
265
266 template <class dataType>
268 std::vector<std::tuple<idNode, idNode, dataType>> &pairs, bool useBD) {
269 std::vector<idNode> nodes;
270 if(useBD) {
271 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i)
272 if(!this->isNodeAlone(i) and this->getNode(i)->getOrigin() != (int)i)
273 nodes.push_back(i);
274 } else
275 this->getLeavesFromTree(nodes);
276 for(auto node : nodes) {
277 auto pers = this->getNodePersistence<dataType>(node);
278 pairs.push_back(
279 std::make_tuple(node, this->getNode(node)->getOrigin(), pers));
280 }
281 auto comp = [&](const std::tuple<idNode, idNode, dataType> a,
282 const std::tuple<idNode, idNode, dataType> b) {
283 return std::get<2>(a) < std::get<2>(b);
284 };
285 sort(pairs.begin(), pairs.end(), comp);
286 }
287
288 template <class dataType>
289 std::vector<idNode> FTMTree_MT::getMultiPersOrigins(bool useBD) {
290 std::vector<idNode> multiPersOrigins;
291
292 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
293 this->getPersistencePairsFromTree(pairs, useBD);
294 // std::vector<idNode> origins(this->getNumberOfNodes(), -1);
295 std::vector<std::vector<idNode>> origins(this->getNumberOfNodes());
296 std::vector<bool> birthFound(this->getNumberOfNodes(), false);
297 for(auto pair : pairs) {
298 idNode const nodeBirth = std::get<0>(pair);
299 idNode const nodeDeath = std::get<1>(pair);
300
301 origins[nodeDeath].push_back(nodeBirth);
302 birthFound[nodeBirth] = true;
303 }
304
305 for(unsigned int i = 0; i < origins.size(); ++i)
306 if(birthFound[i])
307 for(auto node : origins[i])
308 multiPersOrigins.push_back(node);
309
310 return multiPersOrigins;
311 }
312
313 // --------------------
314 // Utils
315 // --------------------
316 template <class dataType>
317 std::stringstream FTMTree_MT::printNode2(idNode nodeId, bool doPrint) {
318 auto origin = this->getNode(nodeId)->getOrigin();
319 std::stringstream ss;
320 ss << "nodeId = " << nodeId << " (" << this->getValue<dataType>(nodeId)
321 << ") _ originId = " << this->getNode(nodeId)->getOrigin();
322 if(not this->isNodeIdInconsistent(origin))
323 ss << " (" << this->getValue<dataType>(origin) << ")";
324 if(doPrint)
325 printMsg(ss.str());
326 return ss;
327 }
328
329 template <class dataType>
330 std::stringstream FTMTree_MT::printMergedRoot(bool doPrint) {
331 std::stringstream ss;
332 ss << this->getRoot() << " (" << this->getValue<dataType>(this->getRoot())
333 << ") _ ";
334 auto mergedRootOrigin = this->getMergedRootOrigin<dataType>();
335 ss << mergedRootOrigin;
336 if(not this->isNodeIdInconsistent(mergedRootOrigin))
337 ss << " (" << this->getValue<dataType>(mergedRootOrigin) << ")";
338 ss << " _ " << this->getNodePersistence<dataType>(this->getRoot());
339 if(not this->isNodeIdInconsistent(mergedRootOrigin))
340 ss << " _ " << this->getNodePersistence<dataType>(mergedRootOrigin);
341 ss << std::endl;
342 if(doPrint)
343 printMsg(ss.str());
344 return ss;
345 }
346
347 template <class dataType>
348 std::stringstream FTMTree_MT::printTreeScalars(bool printNodeAlone,
349 bool doPrint) {
350 std::stringstream wholeSS;
351 std::streamsize const sSize = std::cout.precision();
352 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i) {
353 idNode const iOrigin
354 = this->isNodeOriginDefined(i) ? this->getNode(i)->getOrigin() : i;
355 if(printNodeAlone
356 or (not printNodeAlone
357 and (not this->isNodeAlone(i)
358 or not this->isNodeAlone(iOrigin)))) {
359 std::stringstream ss;
360 ss << i << " _ " << std::setprecision(12)
361 << this->getValue<dataType>(i);
362 if(doPrint)
363 printMsg(ss.str());
364 wholeSS << ss.str() << std::endl;
365 }
366 }
367 if(doPrint)
369 std::cout.precision(sSize);
370 return wholeSS;
371 }
372
373 template <class dataType>
374 std::stringstream FTMTree_MT::printPairsFromTree(bool useBD,
375 bool printPairs,
376 bool doPrint) {
377 std::stringstream ss;
378 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
379 this->getPersistencePairsFromTree(pairs, useBD);
380 ss << "size=" << pairs.size() << std::endl;
381 if(printPairs)
382 for(auto pair : pairs) {
383 ss << std::get<0>(pair) << " ("
384 << this->getValue<dataType>(std::get<0>(pair)) << ") _ ";
385 ss << std::get<1>(pair) << " ("
386 << this->getValue<dataType>(std::get<1>(pair)) << ") _ ";
387 ss << std::get<2>(pair) << std::endl;
388 }
389
390 if(doPrint) {
391 printMsg(ss.str());
393 }
394 return ss;
395 }
396
397 template <class dataType>
398 std::stringstream FTMTree_MT::printMultiPersPairsFromTree(bool useBD,
399 bool printPairs,
400 bool doPrint) {
401 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
402 this->getPersistencePairsFromTree(pairs, useBD);
403 std::vector<int> noOrigin(this->getNumberOfNodes(), 0);
404 int noMultiPers = 0;
405 for(auto pair : pairs) {
406 noOrigin[std::get<0>(pair)]++;
407 noMultiPers += (noOrigin[std::get<0>(pair)] > 1) ? 1 : 0;
408 noOrigin[std::get<1>(pair)]++;
409 noMultiPers += (noOrigin[std::get<1>(pair)] > 1) ? 1 : 0;
410 }
411 std::stringstream ss;
412 ss << "Number of multi pers pairs : " << noMultiPers << std::endl;
413 if(printPairs) {
414 auto multiPers = this->getMultiPersOrigins<dataType>(useBD);
415 for(auto node : multiPers)
416 ss << node << std::endl;
417 }
418 if(doPrint) {
419 printMsg(ss.str());
421 }
422 return ss;
423 }
424
425 } // namespace ftm
426} // 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::vector< ftm::idNode > getMultiPersOrigins(bool useBD)
std::stringstream printMultiPersPairsFromTree(bool useBD=false, bool printPairs=true, bool doPrint=true)
bool isNodeIdInconsistent(idNode nodeId)
dataType getNodePersistence(idNode nodeId)
idNode getNumberOfNodes() const
Definition FTMTree_MT.h:389
std::stringstream printTreeScalars(bool printNodeAlone=true, bool doPrint=true)
std::tuple< dataType, dataType > getBirthDeath(idNode nodeId)
bool isRoot(idNode nodeId)
std::tuple< ftm::idNode, ftm::idNode > getBirthDeathNode(idNode nodeId)
bool isParentInconsistent(ftm::idNode nodeId)
idNode getParentSafe(idNode nodeId)
bool isNodeOriginDefined(idNode nodeId)
std::tuple< ftm::idNode, ftm::idNode > getMergedRootBirthDeathNode()
ftm::idNode getSecondMaximumPersistenceNode()
bool isImportantPair(idNode nodeId, double threshold, std::vector< double > &excludeLower, std::vector< double > &excludeHigher)
std::stringstream printNode2(idNode nodeId, bool doPrint=true)
void getPersistencePairsFromTree(std::vector< std::tuple< ftm::idNode, ftm::idNode, dataType > > &pairs, bool useBD)
void getChildren(idNode nodeId, std::vector< idNode > &res)
std::tuple< dataType, dataType > getMergedRootBirthDeath()
std::stringstream printPairsFromTree(bool useBD=false, bool printPairs=true, bool doPrint=true)
std::tuple< dataType, dataType > getBirthDeathFromIds(idNode nodeId1, idNode nodeId2)
bool isNodeAlone(idNode nodeId)
bool isJT() const
Definition FTMTree_MT.h:289
void getLeavesFromTree(std::vector< idNode > &res)
idNode getLowestNode(idNode nodeStart)
Node * getNode(idNode nodeId)
Definition FTMTree_MT.h:393
std::stringstream printMergedRoot(bool doPrint=true)
dataType getBirth(idNode nodeId)
std::tuple< dataType, dataType > getBirthDeathNodeFromIds(idNode nodeId1, idNode nodeId2)
SimplexId getOrigin() const
Definition FTMNode.h:64
unsigned int idNode
Node index in vect_nodes_.
The Topology ToolKit.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)