TTK
Loading...
Searching...
No Matches
ttkTrackingFromOverlap.cpp
Go to the documentation of this file.
2
3#include <vtkPointSet.h>
4#include <vtkStreamingDemandDrivenPipeline.h>
5#include <vtkUnstructuredGrid.h>
6
7#include <vtkCellData.h>
8#include <vtkCharArray.h>
9#include <vtkDoubleArray.h>
10#include <vtkFloatArray.h>
11#include <vtkIdTypeArray.h>
12#include <vtkInformation.h>
13#include <vtkInformationVector.h>
14#include <vtkLongLongArray.h>
15#include <vtkPointData.h>
16#include <vtkVersionMacros.h>
17
18#include <ttkMacros.h>
19#include <ttkUtils.h>
20
21using namespace std;
22using namespace ttk;
23
25
26// Function to fetch data of a specificd block
27static void getData(vtkMultiBlockDataSet *mb,
28 size_t time,
29 size_t level,
30 const string &labelFieldName,
31 vtkPointSet *&pointSet,
32 vtkDataArray *&labels) {
33 auto timesteps = vtkMultiBlockDataSet::SafeDownCast(mb->GetBlock(level));
34 pointSet = vtkPointSet::SafeDownCast(timesteps->GetBlock(time));
35 if(pointSet == nullptr) {
36 return;
37 }
38 const auto pd = pointSet->GetPointData();
39 labels = pd->GetArray(labelFieldName.data());
40};
41
42// Function to compute number of levels and timesteps contained in a
43// vtkMultiBlockDataSet
44static void getNumberOfLevelsAndTimesteps(vtkMultiBlockDataSet *mb,
45 size_t &nL,
46 size_t &nT) {
47 nL = mb->GetNumberOfBlocks();
48 auto timesteps = vtkMultiBlockDataSet::SafeDownCast(mb->GetBlock(0));
49 nT = timesteps->GetNumberOfBlocks();
50};
51
52// =============================================================================
53// Finalize
54// =============================================================================
55template <typename labelType>
56int finalize(vector<vector<TrackingFromOverlap::Nodes>> &levelTimeNodesMap,
57 vector<vector<TrackingFromOverlap::Edges>> &levelTimeEdgesTMap,
58 vector<vector<TrackingFromOverlap::Edges>> &timeLevelEdgesNMap,
59 int labelTypeId,
60 const string &labelFieldName,
61
62 vtkDataObject *trackingGraphObject) {
63 auto trackingGraph = vtkUnstructuredGrid::SafeDownCast(trackingGraphObject);
64
65 size_t const nL = levelTimeNodesMap.size();
66 size_t const nT = levelTimeNodesMap[0].size();
67
68 auto prepArray = [](vtkAbstractArray *array, const string &name,
69 size_t nComponents, size_t nValues) {
70 array->SetName(name.data());
71 array->SetNumberOfComponents(nComponents);
72 array->SetNumberOfTuples(nValues);
73 };
74
75 // Add Points
76 {
77 size_t nNodes = 0;
78 for(size_t t = 0; t < nT; t++)
79 for(size_t l = 0; l < nL; l++)
80 nNodes += levelTimeNodesMap[l][t].size();
81
82 auto points = vtkSmartPointer<vtkPoints>::New();
83 points->SetNumberOfPoints(nNodes);
84 auto pointCoords = (float *)ttkUtils::GetVoidPointer(points);
85
87 prepArray(sequence, "SequenceIndex", 1, nNodes);
88 auto sequenceData = (long long *)ttkUtils::GetVoidPointer(sequence);
89
91 prepArray(level, "LevelIndex", 1, nNodes);
92 auto levelData = (long long *)ttkUtils::GetVoidPointer(level);
93
95 prepArray(size, "Size", 1, nNodes);
96 auto sizeData = (float *)ttkUtils::GetVoidPointer(size);
97
99 prepArray(branch, "BranchId", 1, nNodes);
100 auto branchData = (long long *)ttkUtils::GetVoidPointer(branch);
101
103 vtkDataArray::CreateDataArray(labelTypeId));
104 prepArray(label, labelFieldName, 1, nNodes);
105 auto labelData = (labelType *)ttkUtils::GetVoidPointer(label);
106
107 size_t q1 = 0, q2 = 0;
108 for(size_t t = 0; t < nT; t++) {
109 for(size_t l = 0; l < nL; l++) {
110 for(auto &node : levelTimeNodesMap[l][t]) {
111 pointCoords[q1++] = node.x;
112 pointCoords[q1++] = node.y;
113 pointCoords[q1++] = node.z;
114
115 sequenceData[q2] = t;
116 levelData[q2] = l;
117 sizeData[q2] = node.size;
118 branchData[q2] = node.branchID;
119 labelData[q2] = boost::get<labelType>(node.label);
120
121 q2++;
122 }
123 }
124 }
125
126 trackingGraph->SetPoints(points);
127
128 auto pointData = trackingGraph->GetPointData();
129 pointData->AddArray(sequence);
130 pointData->AddArray(level);
131 pointData->AddArray(size);
132 pointData->AddArray(label);
133 pointData->AddArray(branch);
134 }
135
136 // Add Cells
137 {
138 if(nT * nL + 1 <= 0) {
139 return 0;
140 }
141
142 // Build node index offset vector
143 vector<size_t> timeLevelOffsetMap(nT * nL + 1);
144 {
145 timeLevelOffsetMap[0] = 0;
146 size_t q = 1;
147 for(size_t t = 0; t < nT; t++)
148 for(size_t l = 0; l < nL; l++) {
149 timeLevelOffsetMap[q]
150 = timeLevelOffsetMap[q - 1] + levelTimeNodesMap[l][t].size();
151 q++;
152 }
153 }
154
155 size_t nEdgesT = 0;
156 if(nT > 1)
157 for(size_t t = 0; t < nT - 1; t++)
158 for(size_t l = 0; l < nL; l++)
159 nEdgesT += levelTimeEdgesTMap[l][t].size() / 4;
160
161 size_t nEdgesN = 0;
162 if(nL > 1)
163 for(size_t l = 0; l < nL - 1; l++)
164 for(size_t t = 0; t < nT; t++)
165 nEdgesN += timeLevelEdgesNMap[t][l].size() / 4;
166
168 cells->SetNumberOfValues(3 * nEdgesT + 3 * nEdgesN);
169 auto cellIds = (vtkIdType *)ttkUtils::GetVoidPointer(cells);
170
172 prepArray(overlap, "Overlap", 1, nEdgesT + nEdgesN);
173 auto overlapData = (float *)ttkUtils::GetVoidPointer(overlap);
174
176 prepArray(branch, "BranchId", 1, nEdgesT + nEdgesN);
177 auto branchData = (long long *)ttkUtils::GetVoidPointer(branch);
178
180 prepArray(type, "Type", 1, nEdgesT + nEdgesN);
181 auto typeData = (char *)ttkUtils::GetVoidPointer(type);
182
183 size_t q0 = 0, q1 = 0;
184
185 // Tracking graphs
186 if(nT > 1)
187 for(size_t t = 1; t < nT; t++) {
188 for(size_t l = 0; l < nL; l++) {
189 auto &edges = levelTimeEdgesTMap[l][t - 1];
190 for(size_t i = 0, j = edges.size(); i < j;) {
191 cellIds[q0++] = 2;
192 cellIds[q0++]
193 = (vtkIdType)(timeLevelOffsetMap[(t - 1) * nL + l] + edges[i++]);
194 cellIds[q0++]
195 = (vtkIdType)(timeLevelOffsetMap[(t)*nL + l] + edges[i++]);
196 typeData[q1] = 0;
197 overlapData[q1] = edges[i++];
198 branchData[q1] = edges[i++];
199 q1++;
200 }
201 }
202 }
203
204 // Nesting trees
205 if(nL > 1)
206 for(size_t l = 1; l < nL; l++) {
207 for(size_t t = 0; t < nT; t++) {
208 auto &edges = timeLevelEdgesNMap[t][l - 1];
209 size_t const temp = t * nL;
210 for(size_t i = 0, j = edges.size(); i < j;) {
211 cellIds[q0++] = 2;
212 cellIds[q0++]
213 = (vtkIdType)(timeLevelOffsetMap[temp + (l - 1)] + edges[i++]);
214 cellIds[q0++]
215 = (vtkIdType)(timeLevelOffsetMap[temp + (l)] + edges[i++]);
216 typeData[q1] = 1;
217 overlapData[q1] = edges[i++];
218 branchData[q1] = edges[i++];
219 q1++;
220 }
221 }
222 }
223
224 auto cellArray = vtkSmartPointer<vtkCellArray>::New();
225#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 6, 1)
226 cellArray->ImportLegacyFormat(cells);
227#else
228 cellArray->SetCells(nEdgesT + nEdgesN, cells);
229#endif
230 trackingGraph->SetCells(VTK_LINE, cellArray);
231
232 auto cellData = trackingGraph->GetCellData();
233 cellData->AddArray(type);
234 cellData->AddArray(overlap);
235 cellData->AddArray(branch);
236 }
237
238 return 1;
239}
240
241// =============================================================================
242// Mesh Nested Tracking Graph
243// =============================================================================
245 vtkDataObject *trackingGraph) {
246 Timer t;
247
248 printMsg("=======================================================",
250 printMsg("Meshing nested tracking graph", debug::Priority::INFO);
251
252 switch(this->LabelDataType) {
253 vtkTemplateMacro(
254 finalize<VTK_TT>(this->levelTimeNodesMap, this->levelTimeEdgesTMap,
255 this->timeLevelEdgesNMap, this->LabelDataType,
256 this->GetLabelFieldName(), trackingGraph));
257 }
258
259 printMsg("-------------------------------------------------------");
260 stringstream msg;
261 msg << "Nested tracking graph meshed in " << t.getElapsedTime() << " s. ("
262 << threadNumber_ << " thread(s)).";
264
265 return 1;
266}
267
268// =============================================================================
269// Reset
270// =============================================================================
272 this->LabelDataType = -1;
273
274 this->levelTimeNodesMap.clear();
275 this->levelTimeEdgesTMap.clear();
276 this->timeLevelEdgesNMap.clear();
277
278 this->previousIterationData = nullptr;
279
280 return 1;
281}
282
283// =============================================================================
284// Pack Data
285// =============================================================================
287 vtkDataObject *inputDataObject, vtkMultiBlockDataSet *packedInput) const {
288 /* Enforce following vtkMultiBlockDataSet structure:
289 {
290 level_0: {
291 time_0: vtkPointSet,
292 ...
293 time_nT: vtkPointSet
294 },
295 ...
296 level_nL: {
297 time_0: vtkPointSet,
298 ...
299 time_nT: vtkPointSet
300 }
301 }
302 */
303
304 // Check inputDataObject depth: 2->(level->time), 1->(-,time), 0->(-,-)
305 auto inputAsMB = vtkMultiBlockDataSet::SafeDownCast(inputDataObject);
306 auto inputAsPS = vtkPointSet::SafeDownCast(inputDataObject);
307 bool error = false;
308 if(inputAsMB) {
309 size_t const n = inputAsMB->GetNumberOfBlocks();
310
311 // Check if blocks are vtkPointSets or vtkMultiBlockDataSets ...
312 size_t psCounter = 0;
313 size_t mbCounter = 0;
314 for(size_t i = 0; i < n; i++) {
315 auto block = inputAsMB->GetBlock(i);
316 auto blockAsMB = vtkMultiBlockDataSet::SafeDownCast(block);
317 auto blockAsPS = vtkPointSet::SafeDownCast(block);
318 if(blockAsMB)
319 mbCounter++;
320 if(blockAsPS)
321 psCounter++;
322 }
323
324 if(mbCounter
325 == n) { // input already contains timesteps per level -> nothing to do
326 packedInput->ShallowCopy(inputAsMB);
327 } else if(psCounter
328 == n) { // if input is a single list of vtkPointSets over time
330 for(size_t i = 0; i < n; i++) {
331 level->SetBlock(i, vtkPointSet::SafeDownCast(inputAsMB->GetBlock(i)));
332 }
333 packedInput->SetBlock(0, level);
334 } else { // Unexpected input structure
335 error = true;
336 }
337 } else if(inputAsPS) {
339 level->SetBlock(0, inputAsPS);
340 packedInput->SetBlock(0, level);
341 } else { // Unexpected input structure
342 error = true;
343 }
344
345 if(error) {
346 printErr("Unable to convert input into "
347 "'vtkPointSet' collection.");
348 return 0;
349 }
350
351 return 1;
352}
353
354// =============================================================================
355// Check Data
356// =============================================================================
357int ttkTrackingFromOverlap::checkData(vtkMultiBlockDataSet *data) {
358 size_t const nL = data->GetNumberOfBlocks();
359 size_t nT = 0;
360
361 if(nL < 1) {
362 printErr("Input must have at least one "
363 "vtkPointSet.");
364 return 0;
365 }
366
367 for(size_t l = 0; l < nL; l++) {
368 auto timesteps = vtkMultiBlockDataSet::SafeDownCast(data->GetBlock(l));
369 size_t const n = timesteps->GetNumberOfBlocks();
370 if(n < 1) {
371 printErr("Input must have at least one "
372 "vtkPointSet.");
373 return 0;
374 }
375 if(nT == 0)
376 nT = n;
377 if(nT != n) {
378 printErr("Timeseries have unequal length.");
379 return 0;
380 }
381
382 for(size_t t = 0; t < nT; t++) {
383 auto pointSet = vtkPointSet::SafeDownCast(timesteps->GetBlock(t));
384 if(pointSet == nullptr) {
385 return 0;
386 }
387 size_t const nPoints = pointSet->GetNumberOfPoints();
388 auto labels = pointSet->GetPointData()->GetAbstractArray(
389 this->GetLabelFieldName().data());
390
391 if(nPoints > 0 && labels == nullptr) {
392 printErr("Point labels '" + this->GetLabelFieldName() + "' not found.");
393 return 0;
394 }
395 if(labels == nullptr)
396 continue;
397
398 int const labelDataType = labels->GetDataType();
399 if(this->LabelDataType < 0)
400 this->LabelDataType = labelDataType;
401 if(this->LabelDataType != labelDataType) {
402 printErr("Point labels do not have same "
403 "type across point sets.");
404 return 0;
405 }
406 }
407 }
408
409 return 1;
410}
411
412// =============================================================================
413// Pack Streamed Data
414// =============================================================================
415int ttkTrackingFromOverlap::packStreamedData(vtkMultiBlockDataSet *streamedData,
416 vtkMultiBlockDataSet *data) const {
417 size_t const nL_PI = this->previousIterationData->GetNumberOfBlocks();
418 size_t const nL_CI = streamedData->GetNumberOfBlocks();
419 if(nL_PI != nL_CI) {
420 printErr("Number of levels differ over time.");
421 return 0;
422 }
423 for(size_t l = 0; l < nL_PI; l++) {
424 auto timestepsPI = vtkMultiBlockDataSet::SafeDownCast(
425 this->previousIterationData->GetBlock(l));
426 auto timestepsCI
427 = vtkMultiBlockDataSet::SafeDownCast(streamedData->GetBlock(l));
428 size_t const nT_CI = timestepsCI->GetNumberOfBlocks();
429
431
432 // First timestep is previous iteration
433 timesteps->SetBlock(0, timestepsPI->GetBlock(0));
434
435 // Remaining timesteps are from current iteration
436 for(size_t t = 0; t < nT_CI; t++)
437 timesteps->SetBlock(t + 1, timestepsCI->GetBlock(t));
438
439 data->SetBlock(l, timesteps);
440 }
441
442 return 1;
443}
444
445// =============================================================================
446// Store Streamed Data
447// =============================================================================
449 vtkMultiBlockDataSet *streamedData) {
450
452 size_t const nL = streamedData->GetNumberOfBlocks();
453 for(size_t l = 0; l < nL; l++) {
454 auto timestepsSD
455 = vtkMultiBlockDataSet::SafeDownCast(streamedData->GetBlock(l));
456 size_t const nT = timestepsSD->GetNumberOfBlocks();
457
460 lastTimestep->SetBlock(0, timestepsSD->GetBlock(nT - 1));
461
462 temp->SetBlock(l, lastTimestep);
463 }
464
465 this->previousIterationData = vtkSmartPointer<vtkMultiBlockDataSet>::New();
466 this->previousIterationData->DeepCopy(temp);
467
468 return 1;
469}
470
471// =============================================================================
472// Compute Nodes
473// =============================================================================
474int ttkTrackingFromOverlap::computeNodes(vtkMultiBlockDataSet *data) {
475
476 Timer timer;
477
478 size_t nL, nT;
479 getNumberOfLevelsAndTimesteps(data, nL, nT);
480
481 // Reusable variables
482 vtkPointSet *pointSet = nullptr;
483 vtkDataArray *labels = nullptr;
484
485 // Compute Nodes
486 {
487 printMsg("=======================================================",
489 printMsg("Computing nodes", debug::Priority::INFO);
490
491 if(this->levelTimeNodesMap.size() != nL)
492 this->levelTimeNodesMap.resize(nL);
493
494 for(size_t l = 0; l < nL; l++) {
495 {
496 printMsg("-------------------------------------------------------");
497 stringstream msg;
498 msg << "Level Index: " << l;
500 }
501
502 vector<Nodes> &timeNodesMap = this->levelTimeNodesMap[l];
503 size_t const timeOffset = timeNodesMap.size();
504 timeNodesMap.resize(timeOffset + nT);
505
506 for(size_t t = 0; t < nT; t++) {
507 getData(data, t, l, this->GetLabelFieldName(), pointSet, labels);
508
509 size_t const nPoints = pointSet->GetNumberOfPoints();
510 if(nPoints < 1)
511 continue;
512
513 switch(this->LabelDataType) {
515 (float *)ttkUtils::GetVoidPointer(pointSet->GetPoints()),
516 (VTK_TT *)ttkUtils::GetVoidPointer(labels), nPoints,
517 timeNodesMap[timeOffset + t]));
518 }
519 }
520 }
521
522 {
523 printMsg("-------------------------------------------------------");
524 stringstream msg;
525 msg << "Nodes computed in " << timer.getElapsedTime() << " s. ("
526 << threadNumber_ << " thread(s)).";
528 }
529 }
530
531 return 1;
532}
533
534// =============================================================================
535// Compute Tracking Graphs
536// =============================================================================
537int ttkTrackingFromOverlap::computeTrackingGraphs(vtkMultiBlockDataSet *data) {
538
539 Timer timer;
540
541 size_t nL, nT;
542 getNumberOfLevelsAndTimesteps(data, nL, nT);
543
544 if(nT < 2)
545 return 1;
546
547 // Reusable variables
548 vtkPointSet *pointSet0 = nullptr;
549 vtkPointSet *pointSet1 = nullptr;
550 vtkDataArray *labels0 = nullptr;
551 vtkDataArray *labels1 = nullptr;
552
553 printMsg("=======================================================",
555 printMsg("Computing tracking graphs", debug::Priority::INFO);
556
557 if(this->levelTimeEdgesTMap.size() != nL)
558 this->levelTimeEdgesTMap.resize(nL);
559
560 for(size_t l = 0; l < nL; l++) {
561 {
562 printMsg("-------------------------------------------------------");
563 stringstream msg;
564 msg << "Level Index: " << l;
566 }
567
568 vector<Edges> &timeEdgesTMap = this->levelTimeEdgesTMap[l];
569 size_t const timeOffset = timeEdgesTMap.size();
570 timeEdgesTMap.resize(timeOffset + nT - 1);
571
572 for(size_t t = 1; t < nT; t++) {
573 getData(data, t - 1, l, this->GetLabelFieldName(), pointSet0, labels0);
574 getData(data, t, l, this->GetLabelFieldName(), pointSet1, labels1);
575
576 size_t const nPoints0 = pointSet0->GetNumberOfPoints();
577 size_t const nPoints1 = pointSet1->GetNumberOfPoints();
578 if(nPoints0 < 1 || nPoints1 < 1)
579 continue;
580
581 switch(this->LabelDataType) {
582 vtkTemplateMacro(this->computeOverlap<VTK_TT>(
583 (float *)ttkUtils::GetVoidPointer(pointSet0->GetPoints()),
584 (float *)ttkUtils::GetVoidPointer(pointSet1->GetPoints()),
585 (VTK_TT *)ttkUtils::GetVoidPointer(labels0),
586 (VTK_TT *)ttkUtils::GetVoidPointer(labels1), nPoints0, nPoints1,
587 timeEdgesTMap[timeOffset + t - 1]));
588 }
589 }
590 }
591
592 {
593 printMsg("-------------------------------------------------------");
594 stringstream msg;
595 msg << "Tracking graphs computed in " << timer.getElapsedTime() << " s. ("
596 << threadNumber_ << " thread(s)).";
598 }
599 return 1;
600}
601
602// =============================================================================
603// Compute Nesting Trees
604// =============================================================================
605int ttkTrackingFromOverlap::computeNestingTrees(vtkMultiBlockDataSet *data) {
606
607 Timer timer;
608
609 size_t nL, nT;
610 getNumberOfLevelsAndTimesteps(data, nL, nT);
611
612 if(nL < 2)
613 return 1;
614
615 // Reusable variables
616 vtkPointSet *pointSet0 = nullptr;
617 vtkPointSet *pointSet1 = nullptr;
618 vtkDataArray *labels0 = nullptr;
619 vtkDataArray *labels1 = nullptr;
620
621 printMsg("=======================================================",
623 printMsg("Computing nesting trees", debug::Priority::INFO);
624
625 size_t const timeOffset = this->timeLevelEdgesNMap.size();
626 this->timeLevelEdgesNMap.resize(timeOffset + nT);
627
628 for(size_t t = 0; t < nT; t++) {
629 {
630 printMsg("-------------------------------------------------------");
631 stringstream msg;
632 msg << "Time Index: " << t;
634 }
635
636 vector<Edges> &levelEdgesNMap = this->timeLevelEdgesNMap[timeOffset + t];
637 levelEdgesNMap.resize(nL - 1);
638
639 for(size_t l = 1; l < nL; l++) {
640 getData(data, t, l - 1, this->GetLabelFieldName(), pointSet0, labels0);
641 getData(data, t, l, this->GetLabelFieldName(), pointSet1, labels1);
642
643 size_t const nPoints0 = pointSet0->GetNumberOfPoints();
644 size_t const nPoints1 = pointSet1->GetNumberOfPoints();
645 if(nPoints0 < 1 || nPoints1 < 1)
646 continue;
647
648 switch(this->LabelDataType) {
649 vtkTemplateMacro(this->computeOverlap<VTK_TT>(
650 (float *)ttkUtils::GetVoidPointer(pointSet0->GetPoints()),
651 (float *)ttkUtils::GetVoidPointer(pointSet1->GetPoints()),
652 (VTK_TT *)ttkUtils::GetVoidPointer(labels0),
653 (VTK_TT *)ttkUtils::GetVoidPointer(labels1), nPoints0, nPoints1,
654 levelEdgesNMap[l - 1]));
655 }
656 }
657 }
658
659 {
660 printMsg("-------------------------------------------------------");
661 stringstream msg;
662 msg << "Nesting trees computed in " << timer.getElapsedTime() << " s. ("
663 << threadNumber_ << " thread(s)).";
665 }
666
667 return 1;
668}
669
670// =============================================================================
671// Compute Branches
672// =============================================================================
674
675 size_t const nL = this->levelTimeEdgesTMap.size();
676
677 for(size_t l = 0; l < nL; l++)
679 this->levelTimeEdgesTMap[l], this->levelTimeNodesMap[l]);
680
681 return 1;
682}
683
684// =============================================================================
685// Request Data
686// =============================================================================
688 vtkInformationVector **inputVector,
689 vtkInformationVector *outputVector) {
690 Timer timer;
691
692 // Print Status
693 {
694 printMsg(
695 "===================================================================");
696 printMsg("RequestData", debug::Priority::INFO);
697 }
698
699 // Get Input Object
700 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
701 auto inputObject = inInfo->Get(vtkDataObject::DATA_OBJECT());
702
703 // Get iteration information
704 auto iterationInformation = vtkDoubleArray::SafeDownCast(
705 inputObject->GetFieldData()->GetAbstractArray("_ttk_IterationInfo"));
706
707 bool const useStreamingOverTime = iterationInformation != nullptr;
708
709 double iteration = 0;
710 double nIterations = 0;
711 if(useStreamingOverTime) {
712 iteration = iterationInformation->GetValue(0);
713 nIterations = iterationInformation->GetValue(1);
714 }
715
716 // On first iteration reset
717 if(!useStreamingOverTime || iteration == 0)
718 this->reset();
719
720 // -------------------------------------------------------------------------
721 // Prepare Input
722 // -------------------------------------------------------------------------
724
725 if(!this->packInputData(inputObject, packedInput))
726 return 0;
727
728 // Check input integrity
729 if(!this->checkData(packedInput))
730 return 0;
731
732 // During streaming append data to previous timestep; Otherwise pass through
734 if(useStreamingOverTime && this->previousIterationData != nullptr) {
735 if(!this->packStreamedData(packedInput, data))
736 return 0;
737 } else
738 data->ShallowCopy(packedInput);
739
740 // -------------------------------------------------------------------------
741 // Process Input
742 // -------------------------------------------------------------------------
743 // Compute nodes only for current input (previous iterations have already been
744 // processed)
745 if(!this->computeNodes(packedInput))
746 return 0;
747
748 // Compute tracking graphs
749 if(!this->computeTrackingGraphs(data))
750 return 0;
751
752 // Compute nesting trees
753 if(!this->computeNestingTrees(packedInput))
754 return 0;
755
756 // Store last timestep for next iteration
757 if(useStreamingOverTime && !this->storeStreamedData(packedInput))
758 return 0;
759
760 // -------------------------------------------------------------------------
761 // Generate Output
762 // -------------------------------------------------------------------------
763 if(!useStreamingOverTime || iteration == nIterations - 1) {
764 // Get Output
765 vtkInformation *outInfo = outputVector->GetInformationObject(0);
766 auto trackingGraph = outInfo->Get(vtkDataObject::DATA_OBJECT());
767
768 // Compute Branches
769 if(!this->computeBranches())
770 return 0;
771
772 // Mesh Graph
773 if(!this->meshNestedTrackingGraph(trackingGraph))
774 return 0;
775 }
776
777 // -------------------------------------------------------------------------
778 // Print total performance
779 // -------------------------------------------------------------------------
780 if(!useStreamingOverTime) {
781 printMsg("=======================================================");
782 stringstream msg;
783 msg << "Nested tracking graph generated in " << timer.getElapsedTime()
784 << " s. (" << threadNumber_ << " thread(s)).";
786 }
787
788 return 1;
789}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
TTK VTK-filter that computes the overlap between labeled vtkPointSets.
int checkData(vtkMultiBlockDataSet *data)
int computeTrackingGraphs(vtkMultiBlockDataSet *data)
int storeStreamedData(vtkMultiBlockDataSet *data)
int computeNestingTrees(vtkMultiBlockDataSet *data)
int meshNestedTrackingGraph(vtkDataObject *trackingGraph)
int computeNodes(vtkMultiBlockDataSet *data)
int packInputData(vtkDataObject *inputDataObject, vtkMultiBlockDataSet *packedData) const
int packStreamedData(vtkMultiBlockDataSet *streamedData, vtkMultiBlockDataSet *packedData) const
virtual std::string GetLabelFieldName()
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.cpp:228
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
int computeNodes(const float *pointCoordinates, const labelType *pointLabels, const size_t nPoints, Nodes &nodes) const
int computeBranches(std::vector< Edges > &timeEdgesMap, std::vector< Nodes > &timeNodesMap) const
int computeOverlap(const float *pointCoordinates0, const float *pointCoordinates1, const labelType *pointLabels0, const labelType *pointLabels1, const size_t nPoints0, const size_t nPoints1, Edges &edges) const
TTK base package defining the standard types.
int finalize(vector< vector< TrackingFromOverlap::Nodes > > &levelTimeNodesMap, vector< vector< TrackingFromOverlap::Edges > > &levelTimeEdgesTMap, vector< vector< TrackingFromOverlap::Edges > > &timeLevelEdgesNMap, int labelTypeId, const string &labelFieldName, vtkDataObject *trackingGraphObject)
vtkStandardNewMacro(ttkTrackingFromOverlap)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)