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 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) const {
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 idNode nodeId2) const {
164 auto nodeValue = this->getValue<dataType>(nodeId1);
165 auto node2Value = this->getValue<dataType>(nodeId2);
166 auto nodeBirth = (nodeValue < node2Value ? nodeId1 : nodeId2);
167 auto nodeDeath = (nodeValue < node2Value ? nodeId2 : nodeId1);
168 return std::make_tuple(nodeBirth, nodeDeath);
169 }
170
171 template <class dataType>
172 std::tuple<dataType, dataType>
174 // Avoid error if origin is not defined
175 if(this->isNodeOriginDefined(nodeId)) {
177 nodeId, this->getNode(nodeId)->getOrigin());
178 }
179 return std::make_tuple(0.0, 0.0);
180 }
181
182 template <class dataType>
183 std::tuple<ftm::idNode, ftm::idNode>
185 if(this->isNodeOriginDefined(nodeId)) {
187 nodeId, this->getNode(nodeId)->getOrigin());
188 }
189 return std::make_tuple(0.0, 0.0);
190 }
191
192 template <class dataType>
193 std::tuple<dataType, dataType> FTMTree_MT::getMergedRootBirthDeath() const {
194 if(!this->isFullMerge())
195 return this->getBirthDeath<dataType>(this->getRoot());
197 this->getRoot(), this->getMergedRootOrigin<dataType>());
198 }
199
200 template <class dataType>
201 std::tuple<ftm::idNode, ftm::idNode>
203 if(!this->isFullMerge())
204 return this->getBirthDeathNode<dataType>(this->getRoot());
206 this->getRoot(), this->getMergedRootOrigin<dataType>());
207 }
208
209 template <class dataType>
210 dataType FTMTree_MT::getBirth(idNode nodeId) const {
211 return std::get<0>(this->getBirthDeath<dataType>(nodeId));
212 }
213
214 template <class dataType>
215 dataType FTMTree_MT::getNodePersistence(idNode nodeId) const {
216 std::tuple<dataType, dataType> birthDeath
217 = this->getBirthDeath<dataType>(nodeId);
218 return std::get<1>(birthDeath) - std::get<0>(birthDeath);
219 }
220
221 template <class dataType>
223 idNode const root = this->getRoot();
224 bool const fullMerge = this->isFullMerge();
225
226 // Classic case
227 if(not fullMerge)
228 return this->getNodePersistence<dataType>(this->getRoot());
229
230 // Full merge case
231 dataType maxPers = std::numeric_limits<dataType>::lowest();
232 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i)
233 if(/*not this->isNodeAlone(i) and*/ this->isNodeOriginDefined(i)
234 and this->getNode(i)->getOrigin() == (int)root)
235 maxPers = std::max(maxPers, this->getNodePersistence<dataType>(i));
236
237 return maxPers;
238 }
239
240 template <class dataType>
242 idNode const root = this->getRoot();
243 dataType pers = std::numeric_limits<dataType>::lowest();
244 ftm::idNode nodeSecMax = -1;
245 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i) {
246 if(not this->isRoot(i) and not this->isNodeAlone(i)
247 and this->isNodeOriginDefined(i)) {
248 idNode const nodeOrigin = this->getNode(i)->getOrigin();
249 if(not(nodeOrigin == root
250 and this->getNode(nodeOrigin)->getOrigin() == (int)i)) {
251 auto nodePers = this->getNodePersistence<dataType>(i);
252 if(pers < nodePers) {
253 pers = nodePers;
254 nodeSecMax = i;
255 }
256 }
257 }
258 }
259 return nodeSecMax;
260 }
261
262 template <class dataType>
267
268 template <class dataType>
270 std::vector<std::tuple<idNode, idNode, dataType>> &pairs,
271 bool useBD) const {
272 std::vector<idNode> nodes;
273 if(useBD) {
274 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i)
275 if(!this->isNodeAlone(i) and this->getNode(i)->getOrigin() != (int)i)
276 nodes.push_back(i);
277 } else
278 this->getLeavesFromTree(nodes);
279 for(auto node : nodes) {
280 auto pers = this->getNodePersistence<dataType>(node);
281 pairs.push_back(
282 std::make_tuple(node, this->getNode(node)->getOrigin(), pers));
283 }
284 auto comp = [&](const std::tuple<idNode, idNode, dataType> a,
285 const std::tuple<idNode, idNode, dataType> b) {
286 return std::get<2>(a) < std::get<2>(b);
287 };
288 sort(pairs.begin(), pairs.end(), comp);
289 }
290
291 template <class dataType>
292 std::vector<idNode> FTMTree_MT::getMultiPersOrigins(bool useBD) const {
293 std::vector<idNode> multiPersOrigins;
294
295 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
296 this->getPersistencePairsFromTree(pairs, useBD);
297 // std::vector<idNode> origins(this->getNumberOfNodes(), -1);
298 std::vector<std::vector<idNode>> origins(this->getNumberOfNodes());
299 std::vector<bool> birthFound(this->getNumberOfNodes(), false);
300 for(auto pair : pairs) {
301 idNode const nodeBirth = std::get<0>(pair);
302 idNode const nodeDeath = std::get<1>(pair);
303
304 origins[nodeDeath].push_back(nodeBirth);
305 birthFound[nodeBirth] = true;
306 }
307
308 for(unsigned int i = 0; i < origins.size(); ++i)
309 if(birthFound[i])
310 for(auto node : origins[i])
311 multiPersOrigins.push_back(node);
312
313 return multiPersOrigins;
314 }
315
316 // --------------------
317 // Utils
318 // --------------------
319 template <class dataType>
320 std::stringstream FTMTree_MT::printNode2(idNode nodeId,
321 bool doPrint) const {
322 auto origin = this->getNode(nodeId)->getOrigin();
323 std::stringstream ss;
324 ss << "nodeId = " << nodeId << " (" << this->getValue<dataType>(nodeId)
325 << ") _ originId = " << this->getNode(nodeId)->getOrigin();
326 if(not this->isNodeIdInconsistent(origin))
327 ss << " (" << this->getValue<dataType>(origin) << ")";
328 if(doPrint)
329 printMsg(ss.str());
330 return ss;
331 }
332
333 template <class dataType>
334 std::stringstream FTMTree_MT::printMergedRoot(bool doPrint) const {
335 std::stringstream ss;
336 ss << this->getRoot() << " (" << this->getValue<dataType>(this->getRoot())
337 << ") _ ";
338 auto mergedRootOrigin = this->getMergedRootOrigin<dataType>();
339 ss << mergedRootOrigin;
340 if(not this->isNodeIdInconsistent(mergedRootOrigin))
341 ss << " (" << this->getValue<dataType>(mergedRootOrigin) << ")";
342 ss << " _ " << this->getNodePersistence<dataType>(this->getRoot());
343 if(not this->isNodeIdInconsistent(mergedRootOrigin))
344 ss << " _ " << this->getNodePersistence<dataType>(mergedRootOrigin);
345 ss << std::endl;
346 if(doPrint)
347 printMsg(ss.str());
348 return ss;
349 }
350
351 template <class dataType>
352 std::stringstream FTMTree_MT::printTreeScalars(bool printNodeAlone,
353 bool doPrint) const {
354 std::stringstream wholeSS;
355 std::streamsize const sSize = std::cout.precision();
356 for(unsigned int i = 0; i < this->getNumberOfNodes(); ++i) {
357 idNode const iOrigin
358 = this->isNodeOriginDefined(i) ? this->getNode(i)->getOrigin() : i;
359 if(printNodeAlone
360 or (not printNodeAlone
361 and (not this->isNodeAlone(i)
362 or not this->isNodeAlone(iOrigin)))) {
363 std::stringstream ss;
364 ss << i << " _ " << std::setprecision(12)
365 << this->getValue<dataType>(i);
366 if(doPrint)
367 printMsg(ss.str());
368 wholeSS << ss.str() << std::endl;
369 }
370 }
371 if(doPrint)
373 std::cout.precision(sSize);
374 return wholeSS;
375 }
376
377 template <class dataType>
378 std::stringstream FTMTree_MT::printPairsFromTree(bool useBD,
379 bool printPairs,
380 bool doPrint) const {
381 std::stringstream ss;
382 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
383 this->getPersistencePairsFromTree(pairs, useBD);
384 ss << "size=" << pairs.size() << std::endl;
385 if(printPairs)
386 for(auto pair : pairs) {
387 ss << std::get<0>(pair) << " ("
388 << this->getValue<dataType>(std::get<0>(pair)) << ") _ ";
389 ss << std::get<1>(pair) << " ("
390 << this->getValue<dataType>(std::get<1>(pair)) << ") _ ";
391 ss << std::get<2>(pair) << std::endl;
392 }
393
394 if(doPrint) {
395 printMsg(ss.str());
397 }
398 return ss;
399 }
400
401 template <class dataType>
403 bool useBD, bool printPairs, bool doPrint) const {
404 std::vector<std::tuple<idNode, idNode, dataType>> pairs;
405 this->getPersistencePairsFromTree(pairs, useBD);
406 std::vector<int> noOrigin(this->getNumberOfNodes(), 0);
407 int noMultiPers = 0;
408 for(auto pair : pairs) {
409 noOrigin[std::get<0>(pair)]++;
410 noMultiPers += (noOrigin[std::get<0>(pair)] > 1) ? 1 : 0;
411 noOrigin[std::get<1>(pair)]++;
412 noMultiPers += (noOrigin[std::get<1>(pair)] > 1) ? 1 : 0;
413 }
414 std::stringstream ss;
415 ss << "Number of multi pers pairs : " << noMultiPers << std::endl;
416 if(printPairs) {
417 auto multiPers = this->getMultiPersOrigins<dataType>(useBD);
418 for(auto node : multiPers)
419 ss << node << std::endl;
420 }
421 if(doPrint) {
422 printMsg(ss.str());
424 }
425 return ss;
426 }
427
428 } // namespace ftm
429} // 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
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)