TTK
Loading...
Searching...
No Matches
ttkMergeTreeUtils.h
Go to the documentation of this file.
1
7
8#pragma once
9
10#include <FTMTree.h>
11#include <FTMTreeUtils.h>
12
13#include <ttkUtils.h>
14
15#include <vtkCellData.h>
16#include <vtkDoubleArray.h>
17#include <vtkIntArray.h>
18#include <vtkMultiBlockDataSet.h>
19#include <vtkPointData.h>
20#include <vtkUnstructuredGrid.h>
21
22namespace ttk {
23 namespace ftm {
24
25 template <class dataType>
26 MergeTree<dataType> makeTree(vtkUnstructuredGrid *treeNodes,
27 vtkUnstructuredGrid *treeArcs) {
28 auto treeNodeIdArray = treeNodes->GetPointData()->GetArray("TreeNodeId");
29
30 // Init Scalars
31 auto scalars = std::make_shared<Scalars>();
32 vtkSmartPointer<vtkDataArray> const nodesScalar
33 = treeNodes->GetPointData()->GetArray("Scalar"); // 1: Scalar
34 scalars->size = nodesScalar->GetNumberOfTuples();
35 if(treeNodeIdArray)
36 scalars->size = std::max(
37 (ttk::SimplexId)treeNodeIdArray->GetRange()[1] + 1, scalars->size);
38 auto scalarsValues
39 = std::make_shared<std::vector<dataType>>(scalars->size);
40 for(int i = 0; i < nodesScalar->GetNumberOfTuples(); ++i) {
41 int const index = (treeNodeIdArray ? treeNodeIdArray->GetTuple1(i) : i);
42 (*scalarsValues)[index] = nodesScalar->GetTuple1(i);
43 }
44 scalars->values = (void *)(scalarsValues->data());
45
46 // Init Tree
47 auto params = std::make_shared<Params>();
48 params->treeType = Join_Split;
49 MergeTree<dataType> mergeTree(scalars, scalarsValues, params);
50
51 // Add Nodes
52 for(vtkIdType i = 0; i < scalars->size; ++i) {
53 mergeTree.tree.makeNode(i);
54 }
55
56 // Add Arcs
58 = treeArcs->GetCellData()->GetArray("upNodeId"); // 1: upNodeId
60 = treeArcs->GetCellData()->GetArray("downNodeId"); // 2: downNodeId
61 vtkIdType const arcsNumTuples = arcsUp->GetNumberOfTuples();
62 vtkSmartPointer<vtkDataArray> const dummyArcArray
63 = treeArcs->GetCellData()->GetArray("isDummyArc");
64 std::set<std::tuple<double, double>> added_arcs; // Avoid duplicates
65 for(vtkIdType i = 0; i < arcsNumTuples; ++i) {
66 if(dummyArcArray != nullptr and dummyArcArray->GetTuple1(i) == 1)
67 continue;
68 double downId = arcsDown->GetTuple1(i);
69 double upId = arcsUp->GetTuple1(i);
70 if(treeNodeIdArray) {
71 downId = treeNodeIdArray->GetTuple1(downId);
72 upId = treeNodeIdArray->GetTuple1(upId);
73 }
74 auto it = added_arcs.find(std::make_tuple(downId, upId));
75 if(it == added_arcs.end()) { // arc not added yet
76 mergeTree.tree.makeSuperArc(downId, upId); // (down, Up)
77 added_arcs.insert(std::make_tuple(downId, upId));
78 }
79 }
80
81 // Manage inconsistent arcs
83
84 // Remove self link
85 removeSelfLink(&(mergeTree.tree));
86
87 return mergeTree;
88 }
89
108 template <class dataType>
110 makeBDTreeFromPDGrid(vtkUnstructuredGrid *persistenceDiagram,
111 bool useSecondPairsType = true,
112 int diagramPairTypes = 0) {
113 auto birthArray
114 = persistenceDiagram->GetCellData()->GetArray(PersistenceBirthName);
115 auto persArray
116 = persistenceDiagram->GetCellData()->GetArray(PersistenceName);
117 auto pairTypeArray
118 = persistenceDiagram->GetCellData()->GetArray(PersistencePairTypeName);
119 auto criticalTypeArray = persistenceDiagram->GetPointData()->GetArray(
121
122 auto treeNodeIdArray
123 = persistenceDiagram->GetPointData()->GetArray("TreeNodeId");
124 auto treeNodeId2Array
125 = persistenceDiagram->GetPointData()->GetArray("TreeNodeIdOrigin");
126 bool const gotNodeArrays = (treeNodeIdArray and treeNodeId2Array);
127
128 auto noPairs = birthArray->GetNumberOfTuples();
129 int noNodes = noPairs * 2;
130 if(gotNodeArrays) {
131 for(vtkIdType i = 0; i < treeNodeIdArray->GetNumberOfTuples(); ++i) {
132 int const val = std::max(treeNodeIdArray->GetTuple1(i),
133 treeNodeId2Array->GetTuple1(i))
134 + 1;
135 noNodes = std::max(noNodes, val);
136 }
137 }
138 std::vector<dataType> scalarsVector(noNodes);
139
140 // Init Tree
141 MergeTree<dataType> mergeTree
142 = ttk::ftm::createEmptyMergeTree<dataType>(scalarsVector.size());
143
144 // Init critical type enum values
145 auto locMin = static_cast<int>(CriticalType::Local_minimum);
146 auto locMax = static_cast<int>(CriticalType::Local_maximum);
147 auto locSad1 = static_cast<int>(CriticalType::Saddle1);
148 auto locSad2 = static_cast<int>(CriticalType::Saddle2);
149
150 // 0 : min-saddle ; 1 : saddle-saddle : 2 : saddle-max
151 int pairsType
152 = (useSecondPairsType
153 and (diagramPairTypes == 0 or diagramPairTypes == 2)
154 ? 2
155 : (not useSecondPairsType
156 and (diagramPairTypes == 0 or diagramPairTypes == 1)
157 ? 0
158 : 1));
159
160 // Get Min-Max pair index
161 int minMaxPairIndex = -1;
162 for(vtkIdType i = 0; i < noPairs; ++i) {
163 vtkIdType npts;
164 vtkIdType const *pts;
165 persistenceDiagram->GetCellPoints(i, npts, pts);
166 auto ct1 = criticalTypeArray->GetTuple1(pts[0]);
167 auto ct2 = criticalTypeArray->GetTuple1(pts[1]);
168 if((ct1 == locMin and ct2 == locMax)
169 or (ct1 == locMax and ct2 == locMin))
170 minMaxPairIndex = i;
171 }
172
173 // Init Tree Structure
174 for(vtkIdType i = 0; i < noNodes; ++i)
175 mergeTree.tree.makeNode(i);
176 for(vtkIdType i = 0; i < noPairs; ++i) {
177 auto pairType = pairTypeArray->GetTuple1(i);
178 vtkIdType npts;
179 vtkIdType const *pts;
180 persistenceDiagram->GetCellPoints(i, npts, pts);
181 auto ct1 = criticalTypeArray->GetTuple1(pts[0]);
182 auto ct2 = criticalTypeArray->GetTuple1(pts[1]);
183 if((pairType == -1
184 or (pairsType == 2 and ct1 != locMax and ct2 != locMax)
185 or (pairsType == 1
186 and not((ct1 == locSad1 and ct2 == locSad2)
187 or (ct1 == locSad2 and ct2 == locSad1)))
188 or (pairsType == 0 and ct1 != locMin and ct2 != locMin))
189 and i != minMaxPairIndex)
190 continue;
191 int const index1
192 = (gotNodeArrays ? treeNodeId2Array->GetTuple1(pts[0]) : i * 2);
193 int const index2
194 = (gotNodeArrays ? treeNodeIdArray->GetTuple1(pts[0]) : i * 2 + 1);
195 mergeTree.tree.getNode(index1)->setOrigin(index2);
196 mergeTree.tree.getNode(index2)->setOrigin(index1);
197 scalarsVector[index1] = birthArray->GetTuple1(i);
198 scalarsVector[index2]
199 = birthArray->GetTuple1(i) + persArray->GetTuple1(i);
200
201 if(i != minMaxPairIndex) {
202 auto up = (gotNodeArrays ? treeNodeIdArray->GetTuple1(minMaxPairIndex)
203 : minMaxPairIndex * 2 + 1);
204 // mergeTree.tree.makeSuperArc(index1, up);
205 mergeTree.tree.makeSuperArc(index2, up);
206 }
207 }
208
209 // Init scalars
210 ttk::ftm::setTreeScalars<dataType>(mergeTree, scalarsVector);
211
212 return mergeTree;
213 }
214
215 inline void
217 vtkMultiBlockDataSet *blocks) {
218 if(blocks != nullptr) {
219 if(blocks->GetBlock(0)->IsA("vtkMultiBlockDataSet"))
220 inputTrees.resize(
221 vtkMultiBlockDataSet::SafeDownCast(blocks->GetBlock(0))
222 ->GetNumberOfBlocks());
223 else if(blocks->GetBlock(0)->IsA("vtkUnstructuredGrid"))
224 inputTrees.resize(blocks->GetNumberOfBlocks());
225 for(size_t i = 0; i < inputTrees.size(); ++i) {
226 if(blocks->GetBlock(0)->IsA("vtkMultiBlockDataSet")) {
229 vtkBlock->SetNumberOfBlocks(blocks->GetNumberOfBlocks());
230 for(unsigned int j = 0; j < blocks->GetNumberOfBlocks(); ++j)
231 vtkBlock->SetBlock(
232 j, vtkMultiBlockDataSet::SafeDownCast(blocks->GetBlock(j))
233 ->GetBlock(i));
234 inputTrees[i] = vtkBlock;
235 } else if(blocks->GetBlock(0)->IsA("vtkUnstructuredGrid")) {
238 vtkBlock->SetNumberOfBlocks(1);
239 vtkBlock->SetBlock(
240 0, vtkUnstructuredGrid::SafeDownCast(blocks->GetBlock(i)));
241 inputTrees[i] = vtkBlock;
242 }
243 }
244 }
245 }
246
247 template <class dataType>
249 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees,
250 std::vector<MergeTree<dataType>> &intermediateTrees,
251 std::vector<vtkUnstructuredGrid *> &treesNodes,
252 std::vector<vtkUnstructuredGrid *> &treesArcs,
253 std::vector<vtkDataSet *> &treesSegmentation,
254 const std::vector<bool> &useSecondPairsTypeVec,
255 int diagramPairTypes = 0) {
256 bool isPersistenceDiagram = false;
257 const int numInputs = inputTrees.size();
258 intermediateTrees.resize(numInputs);
259 treesNodes.resize(numInputs);
260 treesArcs.resize(numInputs);
261 treesSegmentation.resize(numInputs);
262 for(int i = 0; i < numInputs; i++) {
263 if(inputTrees[i]->GetNumberOfBlocks() >= 2) {
264 treesNodes[i]
265 = vtkUnstructuredGrid::SafeDownCast(inputTrees[i]->GetBlock(0));
266 treesArcs[i]
267 = vtkUnstructuredGrid::SafeDownCast(inputTrees[i]->GetBlock(1));
268 if(inputTrees[i]->GetNumberOfBlocks() > 2)
269 treesSegmentation[i]
270 = vtkDataSet::SafeDownCast(inputTrees[i]->GetBlock(2));
271 intermediateTrees[i]
272 = makeTree<dataType>(treesNodes[i], treesArcs[i]);
273 } else {
274 treesNodes[i]
275 = vtkUnstructuredGrid::SafeDownCast(inputTrees[i]->GetBlock(0));
276 vtkUnstructuredGrid *persistenceDiagram
277 = vtkUnstructuredGrid::SafeDownCast(inputTrees[i]->GetBlock(0));
278 intermediateTrees[i] = makeBDTreeFromPDGrid<dataType>(
279 persistenceDiagram, useSecondPairsTypeVec[i], diagramPairTypes);
280 isPersistenceDiagram = true;
281 }
282 }
283 return isPersistenceDiagram;
284 }
285
286 template <class dataType>
288 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees,
289 std::vector<MergeTree<dataType>> &intermediateTrees,
290 std::vector<vtkUnstructuredGrid *> &treesNodes,
291 std::vector<vtkUnstructuredGrid *> &treesArcs,
292 std::vector<vtkDataSet *> &treesSegmentation,
293 bool useSecondPairsType = true,
294 int diagramPairTypes = 0) {
295 const std::vector<bool> useSecondPairsTypeVec(
296 inputTrees.size(), useSecondPairsType);
297 return constructTrees(inputTrees, intermediateTrees, treesNodes,
298 treesArcs, treesSegmentation, useSecondPairsTypeVec,
299 diagramPairTypes);
300 }
301
302 template <class dataType>
304 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees,
305 std::vector<MergeTree<dataType>> &intermediateTrees,
306 bool useSecondPairsType = true,
307 int diagramPairTypes = 0) {
308 std::vector<vtkUnstructuredGrid *> treesNodes;
309 std::vector<vtkUnstructuredGrid *> treesArcs;
310 std::vector<vtkDataSet *> treesSegmentation;
311 return constructTrees(inputTrees, intermediateTrees, treesNodes,
312 treesArcs, treesSegmentation, useSecondPairsType,
313 diagramPairTypes);
314 }
315 } // namespace ftm
316} // namespace ttk
Node * getNode(idNode nodeId) const
Definition FTMTree_MT.h:393
idNode makeNode(SimplexId vertexId, SimplexId linked=nullVertex)
idSuperArc makeSuperArc(idNode downNodeId, idNode upNodeId)
void setOrigin(SimplexId linked)
Definition FTMNode.h:72
void setTreeScalars(MergeTree< dataType > &mergeTree, std::vector< dataType > &scalarsVector)
void removeSelfLink(FTMTree_MT *tree)
MergeTree< dataType > createEmptyMergeTree(int scalarSize)
bool constructTrees(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< MergeTree< dataType > > &intermediateTrees, std::vector< vtkUnstructuredGrid * > &treesNodes, std::vector< vtkUnstructuredGrid * > &treesArcs, std::vector< vtkDataSet * > &treesSegmentation, const std::vector< bool > &useSecondPairsTypeVec, int diagramPairTypes=0)
void loadBlocks(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, vtkMultiBlockDataSet *blocks)
MergeTree< dataType > makeBDTreeFromPDGrid(vtkUnstructuredGrid *persistenceDiagram, bool useSecondPairsType=true, int diagramPairTypes=0)
Create a MergeTree (as a branch decomposition tree) object given a vtkUnstructuredGrid representing a...
void manageInconsistentArcsMultiParent(FTMTree_MT *tree)
MergeTree< dataType > makeTree(vtkUnstructuredGrid *treeNodes, vtkUnstructuredGrid *treeArcs)
TTK base package defining the standard types.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
const char PersistenceName[]
Definition DataTypes.h:80
const char PersistencePairTypeName[]
Definition DataTypes.h:81
const char PersistenceCriticalTypeName[]
Definition DataTypes.h:75
const char PersistenceBirthName[]
Definition DataTypes.h:76
ftm::FTMTree_MT tree
Definition FTMTree_MT.h:906